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 #ifdef 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 #ifdef 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_LS1046A) 215 #ifdef CONFIG_FSL_CORENET 216 u32 liodns[2]; 217 #endif 218 const int *ci = fdt_getprop(blob, off, "cell-index", &err); 219 int i; 220 221 if (!ci) 222 goto err; 223 224 i = fdt32_to_cpu(*ci); 225 #if defined(CONFIG_SYS_DPAA_FMAN) && defined(CONFIG_PPC) 226 int j; 227 #endif 228 229 #endif /* CONFIG_PPC || CONFIG_ARCH_LS1046A */ 230 err = fdt_setprop(blob, off, "compatible", compat, compat_len); 231 if (err < 0) 232 goto err; 233 #ifdef CONFIG_PPC 234 #ifdef CONFIG_FSL_CORENET 235 liodns[0] = qp_info[i].dliodn; 236 liodns[1] = qp_info[i].fliodn; 237 err = fdt_setprop(blob, off, "fsl,liodn", 238 &liodns, sizeof(u32) * 2); 239 if (err < 0) 240 goto err; 241 #endif 242 243 i++; 244 245 err = fdt_qportal(blob, off, i, "crypto@0", FSL_HW_PORTAL_SEC, 246 IS_E_PROCESSOR(get_svr())); 247 if (err < 0) 248 goto err; 249 250 #ifdef CONFIG_FSL_CORENET 251 #ifdef CONFIG_SYS_DPAA_PME 252 err = fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 1); 253 if (err < 0) 254 goto err; 255 #else 256 fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 0); 257 #endif 258 #endif 259 260 #ifdef CONFIG_SYS_DPAA_FMAN 261 for (j = 0; j < CONFIG_SYS_NUM_FMAN; j++) { 262 char name[] = "fman@0"; 263 264 name[sizeof(name) - 2] = '0' + j; 265 err = fdt_qportal(blob, off, i, name, 266 FSL_HW_PORTAL_FMAN1 + j, 1); 267 if (err < 0) 268 goto err; 269 } 270 #endif 271 #ifdef CONFIG_SYS_DPAA_RMAN 272 err = fdt_qportal(blob, off, i, "rman@0", 273 FSL_HW_PORTAL_RMAN, 1); 274 if (err < 0) 275 goto err; 276 #endif 277 #else 278 #ifdef CONFIG_ARCH_LS1046A 279 if (smmu_ph >= 0) { 280 u32 icids[3]; 281 282 icids[0] = qp_info[i].icid; 283 icids[1] = qp_info[i].dicid; 284 icids[2] = qp_info[i].ficid; 285 286 fdt_set_iommu_prop(blob, off, smmu_ph, icids, 3); 287 } 288 #endif 289 #endif /* CONFIG_PPC */ 290 291 err: 292 if (err < 0) { 293 printf("ERROR: unable to create props for %s: %s\n", 294 fdt_get_name(blob, off, NULL), 295 fdt_strerror(err)); 296 return; 297 } 298 299 off = fdt_node_offset_by_compatible(blob, off, 300 "fsl,qman-portal"); 301 } 302 } 303 304 void fdt_fixup_bportals(void *blob) 305 { 306 int off, err; 307 unsigned int maj, min; 308 unsigned int ip_cfg; 309 struct ccsr_bman *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR; 310 u32 rev_1 = in_be32(&bman->ip_rev_1); 311 u32 rev_2 = in_be32(&bman->ip_rev_2); 312 char compat[64]; 313 int compat_len; 314 315 maj = (rev_1 >> 8) & 0xff; 316 min = rev_1 & 0xff; 317 318 ip_cfg = rev_2 & 0xff; 319 320 compat_len = sprintf(compat, "fsl,bman-portal-%u.%u.%u", 321 maj, min, ip_cfg) + 1; 322 compat_len += sprintf(compat + compat_len, "fsl,bman-portal") + 1; 323 324 off = fdt_node_offset_by_compatible(blob, -1, "fsl,bman-portal"); 325 while (off != -FDT_ERR_NOTFOUND) { 326 err = fdt_setprop(blob, off, "compatible", compat, compat_len); 327 if (err < 0) { 328 printf("ERROR: unable to create props for %s: %s\n", 329 fdt_get_name(blob, off, NULL), 330 fdt_strerror(err)); 331 return; 332 } 333 334 off = fdt_node_offset_by_compatible(blob, off, 335 "fsl,bman-portal"); 336 } 337 } 338