1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2008-2011 Freescale Semiconductor, Inc. 4 * Copyright 2017 NXP 5 */ 6 7 #include <common.h> 8 #include <linux/libfdt.h> 9 #include <fdt_support.h> 10 11 #include <asm/processor.h> 12 #include <asm/io.h> 13 #ifdef CONFIG_PPC 14 #include <asm/fsl_portals.h> 15 #include <asm/fsl_liodn.h> 16 #else 17 #include <asm/arch-fsl-layerscape/fsl_portals.h> 18 #include <asm/arch-fsl-layerscape/fsl_icid.h> 19 #endif 20 #include <fsl_qbman.h> 21 22 #define MAX_BPORTALS (CONFIG_SYS_BMAN_CINH_SIZE / CONFIG_SYS_BMAN_SP_CINH_SIZE) 23 #define MAX_QPORTALS (CONFIG_SYS_QMAN_CINH_SIZE / CONFIG_SYS_QMAN_SP_CINH_SIZE) 24 void setup_qbman_portals(void) 25 { 26 void __iomem *bpaddr = (void *)CONFIG_SYS_BMAN_CINH_BASE + 27 CONFIG_SYS_BMAN_SWP_ISDR_REG; 28 void __iomem *qpaddr = (void *)CONFIG_SYS_QMAN_CINH_BASE + 29 CONFIG_SYS_QMAN_SWP_ISDR_REG; 30 struct ccsr_qman *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR; 31 32 /* Set the Qman initiator BAR to match the LAW (for DQRR stashing) */ 33 #ifdef CONFIG_PHYS_64BIT 34 out_be32(&qman->qcsp_bare, (u32)(CONFIG_SYS_QMAN_MEM_PHYS >> 32)); 35 #endif 36 out_be32(&qman->qcsp_bar, (u32)CONFIG_SYS_QMAN_MEM_PHYS); 37 #ifdef CONFIG_FSL_CORENET 38 int i; 39 40 for (i = 0; i < CONFIG_SYS_QMAN_NUM_PORTALS; i++) { 41 u8 sdest = qp_info[i].sdest; 42 u16 fliodn = qp_info[i].fliodn; 43 u16 dliodn = qp_info[i].dliodn; 44 u16 liodn_off = qp_info[i].liodn_offset; 45 46 out_be32(&qman->qcsp[i].qcsp_lio_cfg, (liodn_off << 16) | 47 dliodn); 48 /* set frame liodn */ 49 out_be32(&qman->qcsp[i].qcsp_io_cfg, (sdest << 16) | fliodn); 50 } 51 #else 52 #if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) 53 int i; 54 55 for (i = 0; i < CONFIG_SYS_QMAN_NUM_PORTALS; i++) { 56 u8 sdest = qp_info[i].sdest; 57 u16 ficid = qp_info[i].ficid; 58 u16 dicid = qp_info[i].dicid; 59 u16 icid = qp_info[i].icid; 60 61 out_be32(&qman->qcsp[i].qcsp_lio_cfg, (icid << 16) | 62 dicid); 63 /* set frame icid */ 64 out_be32(&qman->qcsp[i].qcsp_io_cfg, (sdest << 16) | ficid); 65 } 66 #endif 67 #endif 68 69 /* Change default state of BMan ISDR portals to all 1s */ 70 inhibit_portals(bpaddr, CONFIG_SYS_BMAN_NUM_PORTALS, MAX_BPORTALS, 71 CONFIG_SYS_BMAN_SP_CINH_SIZE); 72 inhibit_portals(qpaddr, CONFIG_SYS_QMAN_NUM_PORTALS, MAX_QPORTALS, 73 CONFIG_SYS_QMAN_SP_CINH_SIZE); 74 } 75 76 void inhibit_portals(void __iomem *addr, int max_portals, 77 int arch_max_portals, int portal_cinh_size) 78 { 79 u32 val; 80 int i; 81 82 /* arch_max_portals is the maximum based on memory size. This includes 83 * the reserved memory in the SoC. max_portals the number of physical 84 * portals in the SoC 85 */ 86 if (max_portals > arch_max_portals) { 87 printf("ERROR: portal config error\n"); 88 max_portals = arch_max_portals; 89 } 90 91 for (i = 0; i < max_portals; i++) { 92 out_be32(addr, -1); 93 val = in_be32(addr); 94 if (!val) { 95 printf("ERROR: Stopped after %d portals\n", i); 96 return; 97 } 98 addr += portal_cinh_size; 99 } 100 debug("Cleared %d portals\n", i); 101 } 102 103 #ifdef CONFIG_PPC 104 static int fdt_qportal(void *blob, int off, int id, char *name, 105 enum fsl_dpaa_dev dev, int create) 106 { 107 int childoff, dev_off, ret = 0; 108 u32 dev_handle; 109 #ifdef CONFIG_FSL_CORENET 110 int num; 111 u32 liodns[2]; 112 #endif 113 114 childoff = fdt_subnode_offset(blob, off, name); 115 if (create) { 116 char handle[64], *p; 117 118 strncpy(handle, name, sizeof(handle)); 119 p = strchr(handle, '@'); 120 if (!strncmp(name, "fman", 4)) { 121 *p = *(p + 1); 122 p++; 123 } 124 *p = '\0'; 125 126 dev_off = fdt_path_offset(blob, handle); 127 /* skip this node if alias is not found */ 128 if (dev_off == -FDT_ERR_BADPATH) 129 return 0; 130 if (dev_off < 0) 131 return dev_off; 132 133 if (childoff <= 0) 134 childoff = fdt_add_subnode(blob, off, name); 135 136 /* need to update the dev_off after adding a subnode */ 137 dev_off = fdt_path_offset(blob, handle); 138 if (dev_off < 0) 139 return dev_off; 140 141 if (childoff > 0) { 142 dev_handle = fdt_get_phandle(blob, dev_off); 143 if (dev_handle <= 0) { 144 dev_handle = fdt_alloc_phandle(blob); 145 ret = fdt_set_phandle(blob, dev_off, 146 dev_handle); 147 if (ret < 0) 148 return ret; 149 } 150 151 ret = fdt_setprop(blob, childoff, "dev-handle", 152 &dev_handle, sizeof(dev_handle)); 153 if (ret < 0) 154 return ret; 155 156 #ifdef CONFIG_FSL_CORENET 157 num = get_dpaa_liodn(dev, &liodns[0], id); 158 ret = fdt_setprop(blob, childoff, "fsl,liodn", 159 &liodns[0], sizeof(u32) * num); 160 if (!strncmp(name, "pme", 3)) { 161 u32 pme_rev1, pme_rev2; 162 ccsr_pme_t *pme_regs = 163 (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR; 164 165 pme_rev1 = in_be32(&pme_regs->pm_ip_rev_1); 166 pme_rev2 = in_be32(&pme_regs->pm_ip_rev_2); 167 ret = fdt_setprop(blob, childoff, 168 "fsl,pme-rev1", &pme_rev1, 169 sizeof(u32)); 170 if (ret < 0) 171 return ret; 172 ret = fdt_setprop(blob, childoff, 173 "fsl,pme-rev2", &pme_rev2, 174 sizeof(u32)); 175 } 176 #endif 177 } else { 178 return childoff; 179 } 180 } else { 181 if (childoff > 0) 182 ret = fdt_del_node(blob, childoff); 183 } 184 185 return ret; 186 } 187 #endif /* CONFIG_PPC */ 188 189 void fdt_fixup_qportals(void *blob) 190 { 191 int off, err; 192 unsigned int maj, min; 193 unsigned int ip_cfg; 194 struct ccsr_qman *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR; 195 u32 rev_1 = in_be32(&qman->ip_rev_1); 196 u32 rev_2 = in_be32(&qman->ip_rev_2); 197 char compat[64]; 198 int compat_len; 199 200 #if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) 201 int smmu_ph = fdt_get_smmu_phandle(blob); 202 #endif 203 204 maj = (rev_1 >> 8) & 0xff; 205 min = rev_1 & 0xff; 206 ip_cfg = rev_2 & 0xff; 207 208 compat_len = sprintf(compat, "fsl,qman-portal-%u.%u.%u", 209 maj, min, ip_cfg) + 1; 210 compat_len += sprintf(compat + compat_len, "fsl,qman-portal") + 1; 211 212 off = fdt_node_offset_by_compatible(blob, -1, "fsl,qman-portal"); 213 while (off != -FDT_ERR_NOTFOUND) { 214 #if defined(CONFIG_PPC) || defined(CONFIG_ARCH_LS1043A) || \ 215 defined(CONFIG_ARCH_LS1046A) 216 #ifdef CONFIG_FSL_CORENET 217 u32 liodns[2]; 218 #endif 219 const int *ci = fdt_getprop(blob, off, "cell-index", &err); 220 int i; 221 222 if (!ci) 223 goto err; 224 225 i = fdt32_to_cpu(*ci); 226 #if defined(CONFIG_SYS_DPAA_FMAN) && defined(CONFIG_PPC) 227 int j; 228 #endif 229 230 #endif /* CONFIG_PPC || CONFIG_ARCH_LS1043A || CONFIG_ARCH_LS1046A */ 231 err = fdt_setprop(blob, off, "compatible", compat, compat_len); 232 if (err < 0) 233 goto err; 234 #ifdef CONFIG_PPC 235 #ifdef CONFIG_FSL_CORENET 236 liodns[0] = qp_info[i].dliodn; 237 liodns[1] = qp_info[i].fliodn; 238 err = fdt_setprop(blob, off, "fsl,liodn", 239 &liodns, sizeof(u32) * 2); 240 if (err < 0) 241 goto err; 242 #endif 243 244 i++; 245 246 err = fdt_qportal(blob, off, i, "crypto@0", FSL_HW_PORTAL_SEC, 247 IS_E_PROCESSOR(get_svr())); 248 if (err < 0) 249 goto err; 250 251 #ifdef CONFIG_FSL_CORENET 252 #ifdef CONFIG_SYS_DPAA_PME 253 err = fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 1); 254 if (err < 0) 255 goto err; 256 #else 257 fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 0); 258 #endif 259 #endif 260 261 #ifdef CONFIG_SYS_DPAA_FMAN 262 for (j = 0; j < CONFIG_SYS_NUM_FMAN; j++) { 263 char name[] = "fman@0"; 264 265 name[sizeof(name) - 2] = '0' + j; 266 err = fdt_qportal(blob, off, i, name, 267 FSL_HW_PORTAL_FMAN1 + j, 1); 268 if (err < 0) 269 goto err; 270 } 271 #endif 272 #ifdef CONFIG_SYS_DPAA_RMAN 273 err = fdt_qportal(blob, off, i, "rman@0", 274 FSL_HW_PORTAL_RMAN, 1); 275 if (err < 0) 276 goto err; 277 #endif 278 #else 279 #if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) 280 if (smmu_ph >= 0) { 281 u32 icids[3]; 282 283 icids[0] = qp_info[i].icid; 284 icids[1] = qp_info[i].dicid; 285 icids[2] = qp_info[i].ficid; 286 287 fdt_set_iommu_prop(blob, off, smmu_ph, icids, 3); 288 } 289 #endif 290 #endif /* CONFIG_PPC */ 291 292 err: 293 if (err < 0) { 294 printf("ERROR: unable to create props for %s: %s\n", 295 fdt_get_name(blob, off, NULL), 296 fdt_strerror(err)); 297 return; 298 } 299 300 off = fdt_node_offset_by_compatible(blob, off, 301 "fsl,qman-portal"); 302 } 303 } 304 305 void fdt_fixup_bportals(void *blob) 306 { 307 int off, err; 308 unsigned int maj, min; 309 unsigned int ip_cfg; 310 struct ccsr_bman *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR; 311 u32 rev_1 = in_be32(&bman->ip_rev_1); 312 u32 rev_2 = in_be32(&bman->ip_rev_2); 313 char compat[64]; 314 int compat_len; 315 316 maj = (rev_1 >> 8) & 0xff; 317 min = rev_1 & 0xff; 318 319 ip_cfg = rev_2 & 0xff; 320 321 compat_len = sprintf(compat, "fsl,bman-portal-%u.%u.%u", 322 maj, min, ip_cfg) + 1; 323 compat_len += sprintf(compat + compat_len, "fsl,bman-portal") + 1; 324 325 off = fdt_node_offset_by_compatible(blob, -1, "fsl,bman-portal"); 326 while (off != -FDT_ERR_NOTFOUND) { 327 err = fdt_setprop(blob, off, "compatible", compat, compat_len); 328 if (err < 0) { 329 printf("ERROR: unable to create props for %s: %s\n", 330 fdt_get_name(blob, off, NULL), 331 fdt_strerror(err)); 332 return; 333 } 334 335 off = fdt_node_offset_by_compatible(blob, off, 336 "fsl,bman-portal"); 337 } 338 } 339