1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2008-2011 Freescale Semiconductor, Inc. 4 */ 5 6 #include <common.h> 7 #include <linux/libfdt.h> 8 #include <fdt_support.h> 9 10 #include <asm/immap_85xx.h> 11 #include <asm/io.h> 12 #include <asm/processor.h> 13 #include <asm/fsl_portals.h> 14 #include <asm/fsl_liodn.h> 15 16 int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset) 17 { 18 liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset; 19 20 if (liodn_bases[dpaa_dev].num_ids == 2) 21 liodns[1] = liodn_bases[dpaa_dev].id[1] + liodn_offset; 22 23 return liodn_bases[dpaa_dev].num_ids; 24 } 25 26 #ifdef CONFIG_SYS_SRIO 27 static void set_srio_liodn(struct srio_liodn_id_table *tbl, int size) 28 { 29 int i; 30 31 for (i = 0; i < size; i++) { 32 unsigned long reg_off = tbl[i].reg_offset[0]; 33 out_be32((u32 *)reg_off, tbl[i].id[0]); 34 35 if (tbl[i].num_ids == 2) { 36 reg_off = tbl[i].reg_offset[1]; 37 out_be32((u32 *)reg_off, tbl[i].id[1]); 38 } 39 } 40 } 41 #endif 42 43 static void set_liodn(struct liodn_id_table *tbl, int size) 44 { 45 int i; 46 47 for (i = 0; i < size; i++) { 48 u32 liodn; 49 if (tbl[i].num_ids == 2) { 50 liodn = (tbl[i].id[0] << 16) | tbl[i].id[1]; 51 } else { 52 liodn = tbl[i].id[0]; 53 } 54 55 out_be32((volatile u32 *)(tbl[i].reg_offset), liodn); 56 } 57 } 58 59 #ifdef CONFIG_SYS_DPAA_FMAN 60 static void set_fman_liodn(struct fman_liodn_id_table *tbl, int size) 61 { 62 int i; 63 64 for (i = 0; i < size; i++) { 65 u32 liodn; 66 if (tbl[i].num_ids == 2) 67 liodn = (tbl[i].id[0] << 16) | tbl[i].id[1]; 68 else 69 liodn = tbl[i].id[0]; 70 71 out_be32((volatile u32 *)(tbl[i].reg_offset), liodn); 72 } 73 } 74 #endif 75 76 static void setup_sec_liodn_base(void) 77 { 78 ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR; 79 u32 base; 80 81 if (!IS_E_PROCESSOR(get_svr())) 82 return; 83 84 /* QILCR[QSLOM] */ 85 sec_out32(&sec->qilcr_ms, 0x3ff<<16); 86 87 base = (liodn_bases[FSL_HW_PORTAL_SEC].id[0] << 16) | 88 liodn_bases[FSL_HW_PORTAL_SEC].id[1]; 89 90 sec_out32(&sec->qilcr_ls, base); 91 } 92 93 #ifdef CONFIG_SYS_DPAA_FMAN 94 static void setup_fman_liodn_base(enum fsl_dpaa_dev dev, 95 struct fman_liodn_id_table *tbl, int size) 96 { 97 int i; 98 ccsr_fman_t *fm; 99 u32 base; 100 101 switch(dev) { 102 case FSL_HW_PORTAL_FMAN1: 103 fm = (void *)CONFIG_SYS_FSL_FM1_ADDR; 104 break; 105 106 #if (CONFIG_SYS_NUM_FMAN == 2) 107 case FSL_HW_PORTAL_FMAN2: 108 fm = (void *)CONFIG_SYS_FSL_FM2_ADDR; 109 break; 110 #endif 111 default: 112 printf("Error: Invalid device type to %s\n", __FUNCTION__); 113 return ; 114 } 115 116 base = (liodn_bases[dev].id[0] << 16) | liodn_bases[dev].id[0]; 117 118 /* setup all bases the same */ 119 for (i = 0; i < 32; i++) { 120 out_be32(&fm->fm_dma.fmdmplr[i], base); 121 } 122 123 /* update tbl to ... */ 124 for (i = 0; i < size; i++) 125 tbl[i].id[0] += liodn_bases[dev].id[0]; 126 } 127 #endif 128 129 static void setup_pme_liodn_base(void) 130 { 131 #ifdef CONFIG_SYS_DPAA_PME 132 ccsr_pme_t *pme = (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR; 133 u32 base = (liodn_bases[FSL_HW_PORTAL_PME].id[0] << 16) | 134 liodn_bases[FSL_HW_PORTAL_PME].id[1]; 135 136 out_be32(&pme->liodnbr, base); 137 #endif 138 } 139 140 #ifdef CONFIG_SYS_FSL_RAID_ENGINE 141 static void setup_raide_liodn_base(void) 142 { 143 struct ccsr_raide *raide = (void *)CONFIG_SYS_FSL_RAID_ENGINE_ADDR; 144 145 /* setup raid engine liodn base for data/desc ; both set to 47 */ 146 u32 base = (liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0] << 16) | 147 liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0]; 148 149 out_be32(&raide->liodnbr, base); 150 } 151 #endif 152 153 #ifdef CONFIG_SYS_DPAA_RMAN 154 static void set_rman_liodn(struct liodn_id_table *tbl, int size) 155 { 156 int i; 157 struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR; 158 159 for (i = 0; i < size; i++) { 160 /* write the RMan block number */ 161 out_be32(&rman->mmitar, i); 162 /* write the liodn offset corresponding to the block */ 163 out_be32((u32 *)(tbl[i].reg_offset), tbl[i].id[0]); 164 } 165 } 166 167 static void setup_rman_liodn_base(struct liodn_id_table *tbl, int size) 168 { 169 int i; 170 struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR; 171 u32 base = liodn_bases[FSL_HW_PORTAL_RMAN].id[0]; 172 173 out_be32(&rman->mmliodnbr, base); 174 175 /* update liodn offset */ 176 for (i = 0; i < size; i++) 177 tbl[i].id[0] += base; 178 } 179 #endif 180 181 void set_liodns(void) 182 { 183 /* setup general liodn offsets */ 184 set_liodn(liodn_tbl, liodn_tbl_sz); 185 186 #ifdef CONFIG_SYS_SRIO 187 /* setup SRIO port liodns */ 188 set_srio_liodn(srio_liodn_tbl, srio_liodn_tbl_sz); 189 #endif 190 191 /* setup SEC block liodn bases & offsets if we have one */ 192 if (IS_E_PROCESSOR(get_svr())) { 193 set_liodn(sec_liodn_tbl, sec_liodn_tbl_sz); 194 setup_sec_liodn_base(); 195 } 196 197 /* setup FMAN block(s) liodn bases & offsets if we have one */ 198 #ifdef CONFIG_SYS_DPAA_FMAN 199 set_fman_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz); 200 setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl, 201 fman1_liodn_tbl_sz); 202 203 #if (CONFIG_SYS_NUM_FMAN == 2) 204 set_fman_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz); 205 setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl, 206 fman2_liodn_tbl_sz); 207 #endif 208 #endif 209 /* setup PME liodn base */ 210 setup_pme_liodn_base(); 211 212 #ifdef CONFIG_SYS_FSL_RAID_ENGINE 213 /* raid engine ccr addr code for liodn */ 214 set_liodn(raide_liodn_tbl, raide_liodn_tbl_sz); 215 setup_raide_liodn_base(); 216 #endif 217 218 #ifdef CONFIG_SYS_DPAA_RMAN 219 /* setup RMan liodn offsets */ 220 set_rman_liodn(rman_liodn_tbl, rman_liodn_tbl_sz); 221 /* setup RMan liodn base */ 222 setup_rman_liodn_base(rman_liodn_tbl, rman_liodn_tbl_sz); 223 #endif 224 } 225 226 #ifdef CONFIG_SYS_SRIO 227 static void fdt_fixup_srio_liodn(void *blob, struct srio_liodn_id_table *tbl) 228 { 229 int i, srio_off; 230 231 /* search for srio node, if doesn't exist just return - nothing todo */ 232 srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio"); 233 if (srio_off < 0) 234 return ; 235 236 for (i = 0; i < srio_liodn_tbl_sz; i++) { 237 int off, portid = tbl[i].portid; 238 239 off = fdt_node_offset_by_prop_value(blob, srio_off, 240 "cell-index", &portid, 4); 241 if (off >= 0) { 242 off = fdt_setprop(blob, off, "fsl,liodn", 243 &tbl[i].id[0], 244 sizeof(u32) * tbl[i].num_ids); 245 if (off > 0) 246 printf("WARNING unable to set fsl,liodn for " 247 "fsl,srio port %d: %s\n", 248 portid, fdt_strerror(off)); 249 } else { 250 debug("WARNING: couldn't set fsl,liodn for srio: %s.\n", 251 fdt_strerror(off)); 252 } 253 } 254 } 255 #endif 256 257 #define CONFIG_SYS_MAX_PCI_EPS 8 258 259 static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat, 260 int ep_liodn_start) 261 { 262 int off, pci_idx = 0, pci_cnt = 0, i, rc; 263 const uint32_t *base_liodn; 264 uint32_t liodn_offs[CONFIG_SYS_MAX_PCI_EPS + 1] = { 0 }; 265 266 /* 267 * Count the number of pci nodes. 268 * It's needed later when the interleaved liodn offsets are generated. 269 */ 270 off = fdt_node_offset_by_compatible(fdt, -1, compat); 271 while (off != -FDT_ERR_NOTFOUND) { 272 pci_cnt++; 273 off = fdt_node_offset_by_compatible(fdt, off, compat); 274 } 275 276 for (off = fdt_node_offset_by_compatible(fdt, -1, compat); 277 off != -FDT_ERR_NOTFOUND; 278 off = fdt_node_offset_by_compatible(fdt, off, compat)) { 279 base_liodn = fdt_getprop(fdt, off, "fsl,liodn", &rc); 280 if (!base_liodn) { 281 char path[64]; 282 283 if (fdt_get_path(fdt, off, path, sizeof(path)) < 0) 284 strcpy(path, "(unknown)"); 285 printf("WARNING Could not get liodn of node %s: %s\n", 286 path, fdt_strerror(rc)); 287 continue; 288 } 289 for (i = 0; i < CONFIG_SYS_MAX_PCI_EPS; i++) 290 liodn_offs[i + 1] = ep_liodn_start + 291 i * pci_cnt + pci_idx - *base_liodn; 292 rc = fdt_setprop(fdt, off, "fsl,liodn-offset-list", 293 liodn_offs, sizeof(liodn_offs)); 294 if (rc) { 295 char path[64]; 296 297 if (fdt_get_path(fdt, off, path, sizeof(path)) < 0) 298 strcpy(path, "(unknown)"); 299 printf("WARNING Unable to set fsl,liodn-offset-list for " 300 "node %s: %s\n", path, fdt_strerror(rc)); 301 continue; 302 } 303 pci_idx++; 304 } 305 } 306 307 static void fdt_fixup_liodn_tbl(void *blob, struct liodn_id_table *tbl, int sz) 308 { 309 int i; 310 311 for (i = 0; i < sz; i++) { 312 int off; 313 314 if (tbl[i].compat == NULL) 315 continue; 316 317 off = fdt_node_offset_by_compat_reg(blob, 318 tbl[i].compat, tbl[i].compat_offset); 319 if (off >= 0) { 320 off = fdt_setprop(blob, off, "fsl,liodn", 321 &tbl[i].id[0], 322 sizeof(u32) * tbl[i].num_ids); 323 if (off > 0) 324 printf("WARNING unable to set fsl,liodn for " 325 "%s: %s\n", 326 tbl[i].compat, fdt_strerror(off)); 327 } else { 328 debug("WARNING: could not set fsl,liodn for %s: %s.\n", 329 tbl[i].compat, fdt_strerror(off)); 330 } 331 } 332 } 333 334 #ifdef CONFIG_SYS_DPAA_FMAN 335 static void fdt_fixup_liodn_tbl_fman(void *blob, 336 struct fman_liodn_id_table *tbl, 337 int sz) 338 { 339 int i; 340 341 for (i = 0; i < sz; i++) { 342 int off; 343 344 if (tbl[i].compat == NULL) 345 continue; 346 347 /* Try the new compatible first. 348 * If the node is missing, try the old. 349 */ 350 off = fdt_node_offset_by_compat_reg(blob, 351 tbl[i].compat[0], tbl[i].compat_offset); 352 if (off < 0) 353 off = fdt_node_offset_by_compat_reg(blob, 354 tbl[i].compat[1], tbl[i].compat_offset); 355 356 if (off >= 0) { 357 off = fdt_setprop(blob, off, "fsl,liodn", 358 &tbl[i].id[0], 359 sizeof(u32) * tbl[i].num_ids); 360 if (off > 0) 361 printf("WARNING unable to set fsl,liodn for FMan Port: %s\n", 362 fdt_strerror(off)); 363 } else { 364 debug("WARNING: could not set fsl,liodn for FMan Portport: %s.\n", 365 fdt_strerror(off)); 366 } 367 } 368 } 369 #endif 370 371 void fdt_fixup_liodn(void *blob) 372 { 373 #ifdef CONFIG_SYS_SRIO 374 fdt_fixup_srio_liodn(blob, srio_liodn_tbl); 375 #endif 376 377 fdt_fixup_liodn_tbl(blob, liodn_tbl, liodn_tbl_sz); 378 #ifdef CONFIG_SYS_DPAA_FMAN 379 fdt_fixup_liodn_tbl_fman(blob, fman1_liodn_tbl, fman1_liodn_tbl_sz); 380 #if (CONFIG_SYS_NUM_FMAN == 2) 381 fdt_fixup_liodn_tbl_fman(blob, fman2_liodn_tbl, fman2_liodn_tbl_sz); 382 #endif 383 #endif 384 fdt_fixup_liodn_tbl(blob, sec_liodn_tbl, sec_liodn_tbl_sz); 385 386 #ifdef CONFIG_SYS_FSL_RAID_ENGINE 387 fdt_fixup_liodn_tbl(blob, raide_liodn_tbl, raide_liodn_tbl_sz); 388 #endif 389 390 #ifdef CONFIG_SYS_DPAA_RMAN 391 fdt_fixup_liodn_tbl(blob, rman_liodn_tbl, rman_liodn_tbl_sz); 392 #endif 393 394 ccsr_pcix_t *pcix = (ccsr_pcix_t *)CONFIG_SYS_PCIE1_ADDR; 395 int pci_ver = pcix->ipver1 & 0xffff, liodn_base = 0; 396 397 if (pci_ver >= 0x0204) { 398 if (pci_ver >= 0x0300) 399 liodn_base = 1024; 400 else 401 liodn_base = 256; 402 } 403 404 if (liodn_base) { 405 char compat[32]; 406 407 sprintf(compat, "fsl,qoriq-pcie-v%d.%d", 408 (pci_ver & 0xff00) >> 8, pci_ver & 0xff); 409 fdt_fixup_pci_liodn_offsets(blob, compat, liodn_base); 410 fdt_fixup_pci_liodn_offsets(blob, "fsl,qoriq-pcie", liodn_base); 411 } 412 } 413