1 /* 2 * Copyright 2008-2011 Freescale Semiconductor, Inc. 3 * 4 * See file CREDITS for list of people who contributed to this 5 * project. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * MA 02111-1307 USA 21 */ 22 23 #include <common.h> 24 #include <libfdt.h> 25 #include <fdt_support.h> 26 27 #include <asm/immap_85xx.h> 28 #include <asm/io.h> 29 #include <asm/processor.h> 30 #include <asm/fsl_portals.h> 31 #include <asm/fsl_liodn.h> 32 33 int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset) 34 { 35 liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset; 36 37 if (liodn_bases[dpaa_dev].num_ids == 2) 38 liodns[1] = liodn_bases[dpaa_dev].id[1] + liodn_offset; 39 40 return liodn_bases[dpaa_dev].num_ids; 41 } 42 43 #ifdef CONFIG_SYS_SRIO 44 static void set_srio_liodn(struct srio_liodn_id_table *tbl, int size) 45 { 46 int i; 47 48 for (i = 0; i < size; i++) { 49 unsigned long reg_off = tbl[i].reg_offset[0]; 50 out_be32((u32 *)reg_off, tbl[i].id[0]); 51 52 if (tbl[i].num_ids == 2) { 53 reg_off = tbl[i].reg_offset[1]; 54 out_be32((u32 *)reg_off, tbl[i].id[1]); 55 } 56 } 57 } 58 #endif 59 60 static void set_liodn(struct 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 72 out_be32((volatile u32 *)(tbl[i].reg_offset), liodn); 73 } 74 } 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 out_be32(&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 out_be32(&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 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_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_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 #define CONFIG_SYS_PCI_EP_LIODN_START 256 259 260 static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat) 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] = CONFIG_SYS_PCI_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 void fdt_fixup_liodn(void *blob) 335 { 336 #ifdef CONFIG_SYS_SRIO 337 fdt_fixup_srio_liodn(blob, srio_liodn_tbl); 338 #endif 339 340 fdt_fixup_liodn_tbl(blob, liodn_tbl, liodn_tbl_sz); 341 #ifdef CONFIG_SYS_DPAA_FMAN 342 fdt_fixup_liodn_tbl(blob, fman1_liodn_tbl, fman1_liodn_tbl_sz); 343 #if (CONFIG_SYS_NUM_FMAN == 2) 344 fdt_fixup_liodn_tbl(blob, fman2_liodn_tbl, fman2_liodn_tbl_sz); 345 #endif 346 #endif 347 fdt_fixup_liodn_tbl(blob, sec_liodn_tbl, sec_liodn_tbl_sz); 348 349 #ifdef CONFIG_SYS_FSL_RAID_ENGINE 350 fdt_fixup_liodn_tbl(blob, raide_liodn_tbl, raide_liodn_tbl_sz); 351 #endif 352 353 #ifdef CONFIG_SYS_DPAA_RMAN 354 fdt_fixup_liodn_tbl(blob, rman_liodn_tbl, rman_liodn_tbl_sz); 355 #endif 356 357 fdt_fixup_pci_liodn_offsets(blob, "fsl,qoriq-pcie-v2.4"); 358 } 359