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