1db977abfSKumar Gala /* 26b3a8d00SKumar Gala * Copyright 2008-2011 Freescale Semiconductor, Inc. 3db977abfSKumar Gala * 4db977abfSKumar Gala * See file CREDITS for list of people who contributed to this 5db977abfSKumar Gala * project. 6db977abfSKumar Gala * 7db977abfSKumar Gala * This program is free software; you can redistribute it and/or 8db977abfSKumar Gala * modify it under the terms of the GNU General Public License as 9db977abfSKumar Gala * published by the Free Software Foundation; either version 2 of 10db977abfSKumar Gala * the License, or (at your option) any later version. 11db977abfSKumar Gala * 12db977abfSKumar Gala * This program is distributed in the hope that it will be useful, 13db977abfSKumar Gala * but WITHOUT ANY WARRANTY; without even the implied warranty of 14db977abfSKumar Gala * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15db977abfSKumar Gala * GNU General Public License for more details. 16db977abfSKumar Gala * 17db977abfSKumar Gala * You should have received a copy of the GNU General Public License 18db977abfSKumar Gala * along with this program; if not, write to the Free Software 19db977abfSKumar Gala * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20db977abfSKumar Gala * MA 02111-1307 USA 21db977abfSKumar Gala */ 22db977abfSKumar Gala 23db977abfSKumar Gala #include <common.h> 24db977abfSKumar Gala #include <libfdt.h> 25db977abfSKumar Gala #include <fdt_support.h> 26db977abfSKumar Gala 27db977abfSKumar Gala #include <asm/immap_85xx.h> 28db977abfSKumar Gala #include <asm/io.h> 29db977abfSKumar Gala #include <asm/processor.h> 30db977abfSKumar Gala #include <asm/fsl_portals.h> 31db977abfSKumar Gala #include <asm/fsl_liodn.h> 32db977abfSKumar Gala 33db977abfSKumar Gala int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset) 34db977abfSKumar Gala { 35db977abfSKumar Gala liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset; 36db977abfSKumar Gala 37db977abfSKumar Gala if (liodn_bases[dpaa_dev].num_ids == 2) 38db977abfSKumar Gala liodns[1] = liodn_bases[dpaa_dev].id[1] + liodn_offset; 39db977abfSKumar Gala 40db977abfSKumar Gala return liodn_bases[dpaa_dev].num_ids; 41db977abfSKumar Gala } 42db977abfSKumar Gala 43fd946040STimur Tabi #ifdef CONFIG_SYS_SRIO 441a0c6421SKumar Gala static void set_srio_liodn(struct srio_liodn_id_table *tbl, int size) 451a0c6421SKumar Gala { 461a0c6421SKumar Gala int i; 471a0c6421SKumar Gala 481a0c6421SKumar Gala for (i = 0; i < size; i++) { 491a0c6421SKumar Gala unsigned long reg_off = tbl[i].reg_offset[0]; 501a0c6421SKumar Gala out_be32((u32 *)reg_off, tbl[i].id[0]); 511a0c6421SKumar Gala 521a0c6421SKumar Gala if (tbl[i].num_ids == 2) { 531a0c6421SKumar Gala reg_off = tbl[i].reg_offset[1]; 541a0c6421SKumar Gala out_be32((u32 *)reg_off, tbl[i].id[1]); 551a0c6421SKumar Gala } 561a0c6421SKumar Gala } 571a0c6421SKumar Gala } 58fd946040STimur Tabi #endif 591a0c6421SKumar Gala 60db977abfSKumar Gala static void set_liodn(struct liodn_id_table *tbl, int size) 61db977abfSKumar Gala { 62db977abfSKumar Gala int i; 63db977abfSKumar Gala 64db977abfSKumar Gala for (i = 0; i < size; i++) { 65db977abfSKumar Gala u32 liodn; 66db977abfSKumar Gala if (tbl[i].num_ids == 2) { 67db977abfSKumar Gala liodn = (tbl[i].id[0] << 16) | tbl[i].id[1]; 68db977abfSKumar Gala } else { 69db977abfSKumar Gala liodn = tbl[i].id[0]; 70db977abfSKumar Gala } 71db977abfSKumar Gala 72db977abfSKumar Gala out_be32((volatile u32 *)(tbl[i].reg_offset), liodn); 73db977abfSKumar Gala } 74db977abfSKumar Gala } 75db977abfSKumar Gala 76db977abfSKumar Gala static void setup_sec_liodn_base(void) 77db977abfSKumar Gala { 78db977abfSKumar Gala ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR; 79db977abfSKumar Gala u32 base; 80db977abfSKumar Gala 81db977abfSKumar Gala if (!IS_E_PROCESSOR(get_svr())) 82db977abfSKumar Gala return; 83db977abfSKumar Gala 84db977abfSKumar Gala /* QILCR[QSLOM] */ 85db977abfSKumar Gala out_be32(&sec->qilcr_ms, 0x3ff<<16); 86db977abfSKumar Gala 87db977abfSKumar Gala base = (liodn_bases[FSL_HW_PORTAL_SEC].id[0] << 16) | 88db977abfSKumar Gala liodn_bases[FSL_HW_PORTAL_SEC].id[1]; 89db977abfSKumar Gala 90db977abfSKumar Gala out_be32(&sec->qilcr_ls, base); 91db977abfSKumar Gala } 92db977abfSKumar Gala 93db977abfSKumar Gala #ifdef CONFIG_SYS_DPAA_FMAN 94db977abfSKumar Gala static void setup_fman_liodn_base(enum fsl_dpaa_dev dev, 95db977abfSKumar Gala struct liodn_id_table *tbl, int size) 96db977abfSKumar Gala { 97db977abfSKumar Gala int i; 98db977abfSKumar Gala ccsr_fman_t *fm; 99db977abfSKumar Gala u32 base; 100db977abfSKumar Gala 101db977abfSKumar Gala switch(dev) { 102db977abfSKumar Gala case FSL_HW_PORTAL_FMAN1: 103db977abfSKumar Gala fm = (void *)CONFIG_SYS_FSL_FM1_ADDR; 104db977abfSKumar Gala break; 105db977abfSKumar Gala 106db977abfSKumar Gala #if (CONFIG_SYS_NUM_FMAN == 2) 107db977abfSKumar Gala case FSL_HW_PORTAL_FMAN2: 108db977abfSKumar Gala fm = (void *)CONFIG_SYS_FSL_FM2_ADDR; 109db977abfSKumar Gala break; 110db977abfSKumar Gala #endif 111db977abfSKumar Gala default: 112db977abfSKumar Gala printf("Error: Invalid device type to %s\n", __FUNCTION__); 113db977abfSKumar Gala return ; 114db977abfSKumar Gala } 115db977abfSKumar Gala 116db977abfSKumar Gala base = (liodn_bases[dev].id[0] << 16) | liodn_bases[dev].id[0]; 117db977abfSKumar Gala 118db977abfSKumar Gala /* setup all bases the same */ 119db977abfSKumar Gala for (i = 0; i < 32; i++) { 120db977abfSKumar Gala out_be32(&fm->fm_dma.fmdmplr[i], base); 121db977abfSKumar Gala } 122db977abfSKumar Gala 123db977abfSKumar Gala /* update tbl to ... */ 124db977abfSKumar Gala for (i = 0; i < size; i++) 125db977abfSKumar Gala tbl[i].id[0] += liodn_bases[dev].id[0]; 126db977abfSKumar Gala } 127db977abfSKumar Gala #endif 128db977abfSKumar Gala 129db977abfSKumar Gala static void setup_pme_liodn_base(void) 130db977abfSKumar Gala { 131db977abfSKumar Gala #ifdef CONFIG_SYS_DPAA_PME 132db977abfSKumar Gala ccsr_pme_t *pme = (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR; 133db977abfSKumar Gala u32 base = (liodn_bases[FSL_HW_PORTAL_PME].id[0] << 16) | 134db977abfSKumar Gala liodn_bases[FSL_HW_PORTAL_PME].id[1]; 135db977abfSKumar Gala 136db977abfSKumar Gala out_be32(&pme->liodnbr, base); 137db977abfSKumar Gala #endif 138db977abfSKumar Gala } 139db977abfSKumar Gala 1406b3a8d00SKumar Gala #ifdef CONFIG_SYS_FSL_RAID_ENGINE 1416b3a8d00SKumar Gala static void setup_raide_liodn_base(void) 1426b3a8d00SKumar Gala { 1436b3a8d00SKumar Gala struct ccsr_raide *raide = (void *)CONFIG_SYS_FSL_RAID_ENGINE_ADDR; 1446b3a8d00SKumar Gala 1456b3a8d00SKumar Gala /* setup raid engine liodn base for data/desc ; both set to 47 */ 1466b3a8d00SKumar Gala u32 base = (liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0] << 16) | 1476b3a8d00SKumar Gala liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0]; 1486b3a8d00SKumar Gala 1496b3a8d00SKumar Gala out_be32(&raide->liodnbr, base); 1506b3a8d00SKumar Gala } 1516b3a8d00SKumar Gala #endif 1526b3a8d00SKumar Gala 1534d28db8aSKumar Gala #ifdef CONFIG_SYS_DPAA_RMAN 1544d28db8aSKumar Gala static void set_rman_liodn(struct liodn_id_table *tbl, int size) 1554d28db8aSKumar Gala { 1564d28db8aSKumar Gala int i; 1574d28db8aSKumar Gala struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR; 1584d28db8aSKumar Gala 1594d28db8aSKumar Gala for (i = 0; i < size; i++) { 1604d28db8aSKumar Gala /* write the RMan block number */ 1614d28db8aSKumar Gala out_be32(&rman->mmitar, i); 1624d28db8aSKumar Gala /* write the liodn offset corresponding to the block */ 1634d28db8aSKumar Gala out_be32((u32 *)(tbl[i].reg_offset), tbl[i].id[0]); 1644d28db8aSKumar Gala } 1654d28db8aSKumar Gala } 1664d28db8aSKumar Gala 1674d28db8aSKumar Gala static void setup_rman_liodn_base(struct liodn_id_table *tbl, int size) 1684d28db8aSKumar Gala { 1694d28db8aSKumar Gala int i; 1704d28db8aSKumar Gala struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR; 1714d28db8aSKumar Gala u32 base = liodn_bases[FSL_HW_PORTAL_RMAN].id[0]; 1724d28db8aSKumar Gala 1734d28db8aSKumar Gala out_be32(&rman->mmliodnbr, base); 1744d28db8aSKumar Gala 1754d28db8aSKumar Gala /* update liodn offset */ 1764d28db8aSKumar Gala for (i = 0; i < size; i++) 1774d28db8aSKumar Gala tbl[i].id[0] += base; 1784d28db8aSKumar Gala } 1794d28db8aSKumar Gala #endif 1804d28db8aSKumar Gala 181db977abfSKumar Gala void set_liodns(void) 182db977abfSKumar Gala { 183db977abfSKumar Gala /* setup general liodn offsets */ 184db977abfSKumar Gala set_liodn(liodn_tbl, liodn_tbl_sz); 185db977abfSKumar Gala 186fd946040STimur Tabi #ifdef CONFIG_SYS_SRIO 1871a0c6421SKumar Gala /* setup SRIO port liodns */ 1881a0c6421SKumar Gala set_srio_liodn(srio_liodn_tbl, srio_liodn_tbl_sz); 189fd946040STimur Tabi #endif 1901a0c6421SKumar Gala 191db977abfSKumar Gala /* setup SEC block liodn bases & offsets if we have one */ 192db977abfSKumar Gala if (IS_E_PROCESSOR(get_svr())) { 193db977abfSKumar Gala set_liodn(sec_liodn_tbl, sec_liodn_tbl_sz); 194db977abfSKumar Gala setup_sec_liodn_base(); 195db977abfSKumar Gala } 196db977abfSKumar Gala 197db977abfSKumar Gala /* setup FMAN block(s) liodn bases & offsets if we have one */ 198db977abfSKumar Gala #ifdef CONFIG_SYS_DPAA_FMAN 199db977abfSKumar Gala set_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz); 200db977abfSKumar Gala setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl, 201db977abfSKumar Gala fman1_liodn_tbl_sz); 202db977abfSKumar Gala 203db977abfSKumar Gala #if (CONFIG_SYS_NUM_FMAN == 2) 204db977abfSKumar Gala set_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz); 205db977abfSKumar Gala setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl, 206db977abfSKumar Gala fman2_liodn_tbl_sz); 207db977abfSKumar Gala #endif 208db977abfSKumar Gala #endif 209db977abfSKumar Gala /* setup PME liodn base */ 210db977abfSKumar Gala setup_pme_liodn_base(); 2116b3a8d00SKumar Gala 2126b3a8d00SKumar Gala #ifdef CONFIG_SYS_FSL_RAID_ENGINE 2136b3a8d00SKumar Gala /* raid engine ccr addr code for liodn */ 2146b3a8d00SKumar Gala set_liodn(raide_liodn_tbl, raide_liodn_tbl_sz); 2156b3a8d00SKumar Gala setup_raide_liodn_base(); 2166b3a8d00SKumar Gala #endif 2174d28db8aSKumar Gala 2184d28db8aSKumar Gala #ifdef CONFIG_SYS_DPAA_RMAN 2194d28db8aSKumar Gala /* setup RMan liodn offsets */ 2204d28db8aSKumar Gala set_rman_liodn(rman_liodn_tbl, rman_liodn_tbl_sz); 2214d28db8aSKumar Gala /* setup RMan liodn base */ 2224d28db8aSKumar Gala setup_rman_liodn_base(rman_liodn_tbl, rman_liodn_tbl_sz); 2234d28db8aSKumar Gala #endif 224db977abfSKumar Gala } 225db977abfSKumar Gala 226fd946040STimur Tabi #ifdef CONFIG_SYS_SRIO 2279c42ef61SKumar Gala static void fdt_fixup_srio_liodn(void *blob, struct srio_liodn_id_table *tbl) 2289c42ef61SKumar Gala { 2299c42ef61SKumar Gala int i, srio_off; 2309c42ef61SKumar Gala 2319c42ef61SKumar Gala /* search for srio node, if doesn't exist just return - nothing todo */ 2329c42ef61SKumar Gala srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio"); 2339c42ef61SKumar Gala if (srio_off < 0) 2349c42ef61SKumar Gala return ; 2359c42ef61SKumar Gala 2369c42ef61SKumar Gala for (i = 0; i < srio_liodn_tbl_sz; i++) { 2379c42ef61SKumar Gala int off, portid = tbl[i].portid; 2389c42ef61SKumar Gala 2399c42ef61SKumar Gala off = fdt_node_offset_by_prop_value(blob, srio_off, 2409c42ef61SKumar Gala "cell-index", &portid, 4); 2419c42ef61SKumar Gala if (off >= 0) { 2429c42ef61SKumar Gala off = fdt_setprop(blob, off, "fsl,liodn", 2439c42ef61SKumar Gala &tbl[i].id[0], 2449c42ef61SKumar Gala sizeof(u32) * tbl[i].num_ids); 2459c42ef61SKumar Gala if (off > 0) 2469c42ef61SKumar Gala printf("WARNING unable to set fsl,liodn for " 2479c42ef61SKumar Gala "fsl,srio port %d: %s\n", 2489c42ef61SKumar Gala portid, fdt_strerror(off)); 2499c42ef61SKumar Gala } else { 2509c42ef61SKumar Gala debug("WARNING: couldn't set fsl,liodn for srio: %s.\n", 2519c42ef61SKumar Gala fdt_strerror(off)); 2529c42ef61SKumar Gala } 2539c42ef61SKumar Gala } 2549c42ef61SKumar Gala } 255fd946040STimur Tabi #endif 2569c42ef61SKumar Gala 257*71cfcef6SLaurentiu Tudor #define CONFIG_SYS_MAX_PCI_EPS 8 258*71cfcef6SLaurentiu Tudor #define CONFIG_SYS_PCI_EP_LIODN_START 256 259*71cfcef6SLaurentiu Tudor 260*71cfcef6SLaurentiu Tudor static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat) 261*71cfcef6SLaurentiu Tudor { 262*71cfcef6SLaurentiu Tudor int off, pci_idx = 0, pci_cnt = 0, i, rc; 263*71cfcef6SLaurentiu Tudor const uint32_t *base_liodn; 264*71cfcef6SLaurentiu Tudor uint32_t liodn_offs[CONFIG_SYS_MAX_PCI_EPS + 1] = { 0 }; 265*71cfcef6SLaurentiu Tudor 266*71cfcef6SLaurentiu Tudor /* 267*71cfcef6SLaurentiu Tudor * Count the number of pci nodes. 268*71cfcef6SLaurentiu Tudor * It's needed later when the interleaved liodn offsets are generated. 269*71cfcef6SLaurentiu Tudor */ 270*71cfcef6SLaurentiu Tudor off = fdt_node_offset_by_compatible(fdt, -1, compat); 271*71cfcef6SLaurentiu Tudor while (off != -FDT_ERR_NOTFOUND) { 272*71cfcef6SLaurentiu Tudor pci_cnt++; 273*71cfcef6SLaurentiu Tudor off = fdt_node_offset_by_compatible(fdt, off, compat); 274*71cfcef6SLaurentiu Tudor } 275*71cfcef6SLaurentiu Tudor 276*71cfcef6SLaurentiu Tudor for (off = fdt_node_offset_by_compatible(fdt, -1, compat); 277*71cfcef6SLaurentiu Tudor off != -FDT_ERR_NOTFOUND; 278*71cfcef6SLaurentiu Tudor off = fdt_node_offset_by_compatible(fdt, off, compat)) { 279*71cfcef6SLaurentiu Tudor base_liodn = fdt_getprop(fdt, off, "fsl,liodn", &rc); 280*71cfcef6SLaurentiu Tudor if (!base_liodn) { 281*71cfcef6SLaurentiu Tudor char path[64]; 282*71cfcef6SLaurentiu Tudor 283*71cfcef6SLaurentiu Tudor if (fdt_get_path(fdt, off, path, sizeof(path)) < 0) 284*71cfcef6SLaurentiu Tudor strcpy(path, "(unknown)"); 285*71cfcef6SLaurentiu Tudor printf("WARNING Could not get liodn of node %s: %s\n", 286*71cfcef6SLaurentiu Tudor path, fdt_strerror(rc)); 287*71cfcef6SLaurentiu Tudor continue; 288*71cfcef6SLaurentiu Tudor } 289*71cfcef6SLaurentiu Tudor for (i = 0; i < CONFIG_SYS_MAX_PCI_EPS; i++) 290*71cfcef6SLaurentiu Tudor liodn_offs[i + 1] = CONFIG_SYS_PCI_EP_LIODN_START + 291*71cfcef6SLaurentiu Tudor i * pci_cnt + pci_idx - *base_liodn; 292*71cfcef6SLaurentiu Tudor rc = fdt_setprop(fdt, off, "fsl,liodn-offset-list", 293*71cfcef6SLaurentiu Tudor liodn_offs, sizeof(liodn_offs)); 294*71cfcef6SLaurentiu Tudor if (rc) { 295*71cfcef6SLaurentiu Tudor char path[64]; 296*71cfcef6SLaurentiu Tudor 297*71cfcef6SLaurentiu Tudor if (fdt_get_path(fdt, off, path, sizeof(path)) < 0) 298*71cfcef6SLaurentiu Tudor strcpy(path, "(unknown)"); 299*71cfcef6SLaurentiu Tudor printf("WARNING Unable to set fsl,liodn-offset-list for " 300*71cfcef6SLaurentiu Tudor "node %s: %s\n", path, fdt_strerror(rc)); 301*71cfcef6SLaurentiu Tudor continue; 302*71cfcef6SLaurentiu Tudor } 303*71cfcef6SLaurentiu Tudor pci_idx++; 304*71cfcef6SLaurentiu Tudor } 305*71cfcef6SLaurentiu Tudor } 306*71cfcef6SLaurentiu Tudor 307db977abfSKumar Gala static void fdt_fixup_liodn_tbl(void *blob, struct liodn_id_table *tbl, int sz) 308db977abfSKumar Gala { 309db977abfSKumar Gala int i; 310db977abfSKumar Gala 311db977abfSKumar Gala for (i = 0; i < sz; i++) { 312db977abfSKumar Gala int off; 313db977abfSKumar Gala 314db977abfSKumar Gala if (tbl[i].compat == NULL) 315db977abfSKumar Gala continue; 316db977abfSKumar Gala 317db977abfSKumar Gala off = fdt_node_offset_by_compat_reg(blob, 318db977abfSKumar Gala tbl[i].compat, tbl[i].compat_offset); 319db977abfSKumar Gala if (off >= 0) { 320db977abfSKumar Gala off = fdt_setprop(blob, off, "fsl,liodn", 321db977abfSKumar Gala &tbl[i].id[0], 322db977abfSKumar Gala sizeof(u32) * tbl[i].num_ids); 323db977abfSKumar Gala if (off > 0) 324db977abfSKumar Gala printf("WARNING unable to set fsl,liodn for " 325db977abfSKumar Gala "%s: %s\n", 326db977abfSKumar Gala tbl[i].compat, fdt_strerror(off)); 327db977abfSKumar Gala } else { 328db977abfSKumar Gala debug("WARNING: could not set fsl,liodn for %s: %s.\n", 329db977abfSKumar Gala tbl[i].compat, fdt_strerror(off)); 330db977abfSKumar Gala } 331db977abfSKumar Gala } 332db977abfSKumar Gala } 333db977abfSKumar Gala 334db977abfSKumar Gala void fdt_fixup_liodn(void *blob) 335db977abfSKumar Gala { 336fd946040STimur Tabi #ifdef CONFIG_SYS_SRIO 3379c42ef61SKumar Gala fdt_fixup_srio_liodn(blob, srio_liodn_tbl); 338fd946040STimur Tabi #endif 3399c42ef61SKumar Gala 340db977abfSKumar Gala fdt_fixup_liodn_tbl(blob, liodn_tbl, liodn_tbl_sz); 341db977abfSKumar Gala #ifdef CONFIG_SYS_DPAA_FMAN 342db977abfSKumar Gala fdt_fixup_liodn_tbl(blob, fman1_liodn_tbl, fman1_liodn_tbl_sz); 343db977abfSKumar Gala #if (CONFIG_SYS_NUM_FMAN == 2) 344db977abfSKumar Gala fdt_fixup_liodn_tbl(blob, fman2_liodn_tbl, fman2_liodn_tbl_sz); 345db977abfSKumar Gala #endif 346db977abfSKumar Gala #endif 347db977abfSKumar Gala fdt_fixup_liodn_tbl(blob, sec_liodn_tbl, sec_liodn_tbl_sz); 3486b3a8d00SKumar Gala 3496b3a8d00SKumar Gala #ifdef CONFIG_SYS_FSL_RAID_ENGINE 3506b3a8d00SKumar Gala fdt_fixup_liodn_tbl(blob, raide_liodn_tbl, raide_liodn_tbl_sz); 3516b3a8d00SKumar Gala #endif 3524d28db8aSKumar Gala 3534d28db8aSKumar Gala #ifdef CONFIG_SYS_DPAA_RMAN 3544d28db8aSKumar Gala fdt_fixup_liodn_tbl(blob, rman_liodn_tbl, rman_liodn_tbl_sz); 3554d28db8aSKumar Gala #endif 356*71cfcef6SLaurentiu Tudor 357*71cfcef6SLaurentiu Tudor fdt_fixup_pci_liodn_offsets(blob, "fsl,qoriq-pcie-v2.4"); 358db977abfSKumar Gala } 359