diff options
Diffstat (limited to 'arch/powerpc/sysdev/ppc4xx_pci.c')
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 306 |
1 files changed, 208 insertions, 98 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index d3e4d61030b5..77fae5f64f2e 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c | |||
@@ -194,11 +194,41 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose, | |||
194 | * 4xx PCI 2.x part | 194 | * 4xx PCI 2.x part |
195 | */ | 195 | */ |
196 | 196 | ||
197 | static int __init ppc4xx_setup_one_pci_PMM(struct pci_controller *hose, | ||
198 | void __iomem *reg, | ||
199 | u64 plb_addr, | ||
200 | u64 pci_addr, | ||
201 | u64 size, | ||
202 | unsigned int flags, | ||
203 | int index) | ||
204 | { | ||
205 | u32 ma, pcila, pciha; | ||
206 | |||
207 | if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) || | ||
208 | size < 0x1000 || (plb_addr & (size - 1)) != 0) { | ||
209 | printk(KERN_WARNING "%s: Resource out of range\n", | ||
210 | hose->dn->full_name); | ||
211 | return -1; | ||
212 | } | ||
213 | ma = (0xffffffffu << ilog2(size)) | 1; | ||
214 | if (flags & IORESOURCE_PREFETCH) | ||
215 | ma |= 2; | ||
216 | |||
217 | pciha = RES_TO_U32_HIGH(pci_addr); | ||
218 | pcila = RES_TO_U32_LOW(pci_addr); | ||
219 | |||
220 | writel(plb_addr, reg + PCIL0_PMM0LA + (0x10 * index)); | ||
221 | writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * index)); | ||
222 | writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * index)); | ||
223 | writel(ma, reg + PCIL0_PMM0MA + (0x10 * index)); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
197 | static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, | 228 | static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, |
198 | void __iomem *reg) | 229 | void __iomem *reg) |
199 | { | 230 | { |
200 | u32 la, ma, pcila, pciha; | 231 | int i, j, found_isa_hole = 0; |
201 | int i, j; | ||
202 | 232 | ||
203 | /* Setup outbound memory windows */ | 233 | /* Setup outbound memory windows */ |
204 | for (i = j = 0; i < 3; i++) { | 234 | for (i = j = 0; i < 3; i++) { |
@@ -213,28 +243,29 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, | |||
213 | break; | 243 | break; |
214 | } | 244 | } |
215 | 245 | ||
216 | /* Calculate register values */ | 246 | /* Configure the resource */ |
217 | la = res->start; | 247 | if (ppc4xx_setup_one_pci_PMM(hose, reg, |
218 | pciha = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset); | 248 | res->start, |
219 | pcila = RES_TO_U32_LOW(res->start - hose->pci_mem_offset); | 249 | res->start - hose->pci_mem_offset, |
220 | 250 | res->end + 1 - res->start, | |
221 | ma = res->end + 1 - res->start; | 251 | res->flags, |
222 | if (!is_power_of_2(ma) || ma < 0x1000 || ma > 0xffffffffu) { | 252 | j) == 0) { |
223 | printk(KERN_WARNING "%s: Resource out of range\n", | 253 | j++; |
224 | hose->dn->full_name); | 254 | |
225 | continue; | 255 | /* If the resource PCI address is 0 then we have our |
256 | * ISA memory hole | ||
257 | */ | ||
258 | if (res->start == hose->pci_mem_offset) | ||
259 | found_isa_hole = 1; | ||
226 | } | 260 | } |
227 | ma = (0xffffffffu << ilog2(ma)) | 0x1; | ||
228 | if (res->flags & IORESOURCE_PREFETCH) | ||
229 | ma |= 0x2; | ||
230 | |||
231 | /* Program register values */ | ||
232 | writel(la, reg + PCIL0_PMM0LA + (0x10 * j)); | ||
233 | writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * j)); | ||
234 | writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * j)); | ||
235 | writel(ma, reg + PCIL0_PMM0MA + (0x10 * j)); | ||
236 | j++; | ||
237 | } | 261 | } |
262 | |||
263 | /* Handle ISA memory hole if not already covered */ | ||
264 | if (j <= 2 && !found_isa_hole && hose->isa_mem_size) | ||
265 | if (ppc4xx_setup_one_pci_PMM(hose, reg, hose->isa_mem_phys, 0, | ||
266 | hose->isa_mem_size, 0, j) == 0) | ||
267 | printk(KERN_INFO "%s: Legacy ISA memory support enabled\n", | ||
268 | hose->dn->full_name); | ||
238 | } | 269 | } |
239 | 270 | ||
240 | static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose, | 271 | static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose, |
@@ -352,11 +383,52 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np) | |||
352 | * 4xx PCI-X part | 383 | * 4xx PCI-X part |
353 | */ | 384 | */ |
354 | 385 | ||
386 | static int __init ppc4xx_setup_one_pcix_POM(struct pci_controller *hose, | ||
387 | void __iomem *reg, | ||
388 | u64 plb_addr, | ||
389 | u64 pci_addr, | ||
390 | u64 size, | ||
391 | unsigned int flags, | ||
392 | int index) | ||
393 | { | ||
394 | u32 lah, lal, pciah, pcial, sa; | ||
395 | |||
396 | if (!is_power_of_2(size) || size < 0x1000 || | ||
397 | (plb_addr & (size - 1)) != 0) { | ||
398 | printk(KERN_WARNING "%s: Resource out of range\n", | ||
399 | hose->dn->full_name); | ||
400 | return -1; | ||
401 | } | ||
402 | |||
403 | /* Calculate register values */ | ||
404 | lah = RES_TO_U32_HIGH(plb_addr); | ||
405 | lal = RES_TO_U32_LOW(plb_addr); | ||
406 | pciah = RES_TO_U32_HIGH(pci_addr); | ||
407 | pcial = RES_TO_U32_LOW(pci_addr); | ||
408 | sa = (0xffffffffu << ilog2(size)) | 0x1; | ||
409 | |||
410 | /* Program register values */ | ||
411 | if (index == 0) { | ||
412 | writel(lah, reg + PCIX0_POM0LAH); | ||
413 | writel(lal, reg + PCIX0_POM0LAL); | ||
414 | writel(pciah, reg + PCIX0_POM0PCIAH); | ||
415 | writel(pcial, reg + PCIX0_POM0PCIAL); | ||
416 | writel(sa, reg + PCIX0_POM0SA); | ||
417 | } else { | ||
418 | writel(lah, reg + PCIX0_POM1LAH); | ||
419 | writel(lal, reg + PCIX0_POM1LAL); | ||
420 | writel(pciah, reg + PCIX0_POM1PCIAH); | ||
421 | writel(pcial, reg + PCIX0_POM1PCIAL); | ||
422 | writel(sa, reg + PCIX0_POM1SA); | ||
423 | } | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
355 | static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, | 428 | static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, |
356 | void __iomem *reg) | 429 | void __iomem *reg) |
357 | { | 430 | { |
358 | u32 lah, lal, pciah, pcial, sa; | 431 | int i, j, found_isa_hole = 0; |
359 | int i, j; | ||
360 | 432 | ||
361 | /* Setup outbound memory windows */ | 433 | /* Setup outbound memory windows */ |
362 | for (i = j = 0; i < 3; i++) { | 434 | for (i = j = 0; i < 3; i++) { |
@@ -371,36 +443,29 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, | |||
371 | break; | 443 | break; |
372 | } | 444 | } |
373 | 445 | ||
374 | /* Calculate register values */ | 446 | /* Configure the resource */ |
375 | lah = RES_TO_U32_HIGH(res->start); | 447 | if (ppc4xx_setup_one_pcix_POM(hose, reg, |
376 | lal = RES_TO_U32_LOW(res->start); | 448 | res->start, |
377 | pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset); | 449 | res->start - hose->pci_mem_offset, |
378 | pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset); | 450 | res->end + 1 - res->start, |
379 | sa = res->end + 1 - res->start; | 451 | res->flags, |
380 | if (!is_power_of_2(sa) || sa < 0x100000 || | 452 | j) == 0) { |
381 | sa > 0xffffffffu) { | 453 | j++; |
382 | printk(KERN_WARNING "%s: Resource out of range\n", | 454 | |
383 | hose->dn->full_name); | 455 | /* If the resource PCI address is 0 then we have our |
384 | continue; | 456 | * ISA memory hole |
457 | */ | ||
458 | if (res->start == hose->pci_mem_offset) | ||
459 | found_isa_hole = 1; | ||
385 | } | 460 | } |
386 | sa = (0xffffffffu << ilog2(sa)) | 0x1; | ||
387 | |||
388 | /* Program register values */ | ||
389 | if (j == 0) { | ||
390 | writel(lah, reg + PCIX0_POM0LAH); | ||
391 | writel(lal, reg + PCIX0_POM0LAL); | ||
392 | writel(pciah, reg + PCIX0_POM0PCIAH); | ||
393 | writel(pcial, reg + PCIX0_POM0PCIAL); | ||
394 | writel(sa, reg + PCIX0_POM0SA); | ||
395 | } else { | ||
396 | writel(lah, reg + PCIX0_POM1LAH); | ||
397 | writel(lal, reg + PCIX0_POM1LAL); | ||
398 | writel(pciah, reg + PCIX0_POM1PCIAH); | ||
399 | writel(pcial, reg + PCIX0_POM1PCIAL); | ||
400 | writel(sa, reg + PCIX0_POM1SA); | ||
401 | } | ||
402 | j++; | ||
403 | } | 461 | } |
462 | |||
463 | /* Handle ISA memory hole if not already covered */ | ||
464 | if (j <= 1 && !found_isa_hole && hose->isa_mem_size) | ||
465 | if (ppc4xx_setup_one_pcix_POM(hose, reg, hose->isa_mem_phys, 0, | ||
466 | hose->isa_mem_size, 0, j) == 0) | ||
467 | printk(KERN_INFO "%s: Legacy ISA memory support enabled\n", | ||
468 | hose->dn->full_name); | ||
404 | } | 469 | } |
405 | 470 | ||
406 | static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose, | 471 | static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose, |
@@ -1317,12 +1382,72 @@ static struct pci_ops ppc4xx_pciex_pci_ops = | |||
1317 | .write = ppc4xx_pciex_write_config, | 1382 | .write = ppc4xx_pciex_write_config, |
1318 | }; | 1383 | }; |
1319 | 1384 | ||
1385 | static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, | ||
1386 | struct pci_controller *hose, | ||
1387 | void __iomem *mbase, | ||
1388 | u64 plb_addr, | ||
1389 | u64 pci_addr, | ||
1390 | u64 size, | ||
1391 | unsigned int flags, | ||
1392 | int index) | ||
1393 | { | ||
1394 | u32 lah, lal, pciah, pcial, sa; | ||
1395 | |||
1396 | if (!is_power_of_2(size) || | ||
1397 | (index < 2 && size < 0x100000) || | ||
1398 | (index == 2 && size < 0x100) || | ||
1399 | (plb_addr & (size - 1)) != 0) { | ||
1400 | printk(KERN_WARNING "%s: Resource out of range\n", | ||
1401 | hose->dn->full_name); | ||
1402 | return -1; | ||
1403 | } | ||
1404 | |||
1405 | /* Calculate register values */ | ||
1406 | lah = RES_TO_U32_HIGH(plb_addr); | ||
1407 | lal = RES_TO_U32_LOW(plb_addr); | ||
1408 | pciah = RES_TO_U32_HIGH(pci_addr); | ||
1409 | pcial = RES_TO_U32_LOW(pci_addr); | ||
1410 | sa = (0xffffffffu << ilog2(size)) | 0x1; | ||
1411 | |||
1412 | /* Program register values */ | ||
1413 | switch (index) { | ||
1414 | case 0: | ||
1415 | out_le32(mbase + PECFG_POM0LAH, pciah); | ||
1416 | out_le32(mbase + PECFG_POM0LAL, pcial); | ||
1417 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); | ||
1418 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); | ||
1419 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); | ||
1420 | /* Note that 3 here means enabled | single region */ | ||
1421 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); | ||
1422 | break; | ||
1423 | case 1: | ||
1424 | out_le32(mbase + PECFG_POM1LAH, pciah); | ||
1425 | out_le32(mbase + PECFG_POM1LAL, pcial); | ||
1426 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); | ||
1427 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); | ||
1428 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); | ||
1429 | /* Note that 3 here means enabled | single region */ | ||
1430 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); | ||
1431 | break; | ||
1432 | case 2: | ||
1433 | out_le32(mbase + PECFG_POM2LAH, pciah); | ||
1434 | out_le32(mbase + PECFG_POM2LAL, pcial); | ||
1435 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah); | ||
1436 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); | ||
1437 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); | ||
1438 | /* Note that 3 here means enabled | IO space !!! */ | ||
1439 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3); | ||
1440 | break; | ||
1441 | } | ||
1442 | |||
1443 | return 0; | ||
1444 | } | ||
1445 | |||
1320 | static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, | 1446 | static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, |
1321 | struct pci_controller *hose, | 1447 | struct pci_controller *hose, |
1322 | void __iomem *mbase) | 1448 | void __iomem *mbase) |
1323 | { | 1449 | { |
1324 | u32 lah, lal, pciah, pcial, sa; | 1450 | int i, j, found_isa_hole = 0; |
1325 | int i, j; | ||
1326 | 1451 | ||
1327 | /* Setup outbound memory windows */ | 1452 | /* Setup outbound memory windows */ |
1328 | for (i = j = 0; i < 3; i++) { | 1453 | for (i = j = 0; i < 3; i++) { |
@@ -1337,53 +1462,38 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, | |||
1337 | break; | 1462 | break; |
1338 | } | 1463 | } |
1339 | 1464 | ||
1340 | /* Calculate register values */ | 1465 | /* Configure the resource */ |
1341 | lah = RES_TO_U32_HIGH(res->start); | 1466 | if (ppc4xx_setup_one_pciex_POM(port, hose, mbase, |
1342 | lal = RES_TO_U32_LOW(res->start); | 1467 | res->start, |
1343 | pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset); | 1468 | res->start - hose->pci_mem_offset, |
1344 | pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset); | 1469 | res->end + 1 - res->start, |
1345 | sa = res->end + 1 - res->start; | 1470 | res->flags, |
1346 | if (!is_power_of_2(sa) || sa < 0x100000 || | 1471 | j) == 0) { |
1347 | sa > 0xffffffffu) { | 1472 | j++; |
1348 | printk(KERN_WARNING "%s: Resource out of range\n", | 1473 | |
1349 | port->node->full_name); | 1474 | /* If the resource PCI address is 0 then we have our |
1350 | continue; | 1475 | * ISA memory hole |
1351 | } | 1476 | */ |
1352 | sa = (0xffffffffu << ilog2(sa)) | 0x1; | 1477 | if (res->start == hose->pci_mem_offset) |
1353 | 1478 | found_isa_hole = 1; | |
1354 | /* Program register values */ | ||
1355 | switch (j) { | ||
1356 | case 0: | ||
1357 | out_le32(mbase + PECFG_POM0LAH, pciah); | ||
1358 | out_le32(mbase + PECFG_POM0LAL, pcial); | ||
1359 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); | ||
1360 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); | ||
1361 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); | ||
1362 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); | ||
1363 | break; | ||
1364 | case 1: | ||
1365 | out_le32(mbase + PECFG_POM1LAH, pciah); | ||
1366 | out_le32(mbase + PECFG_POM1LAL, pcial); | ||
1367 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); | ||
1368 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); | ||
1369 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); | ||
1370 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); | ||
1371 | break; | ||
1372 | } | 1479 | } |
1373 | j++; | ||
1374 | } | 1480 | } |
1375 | 1481 | ||
1376 | /* Configure IO, always 64K starting at 0 */ | 1482 | /* Handle ISA memory hole if not already covered */ |
1377 | if (hose->io_resource.flags & IORESOURCE_IO) { | 1483 | if (j <= 1 && !found_isa_hole && hose->isa_mem_size) |
1378 | lah = RES_TO_U32_HIGH(hose->io_base_phys); | 1484 | if (ppc4xx_setup_one_pciex_POM(port, hose, mbase, |
1379 | lal = RES_TO_U32_LOW(hose->io_base_phys); | 1485 | hose->isa_mem_phys, 0, |
1380 | out_le32(mbase + PECFG_POM2LAH, 0); | 1486 | hose->isa_mem_size, 0, j) == 0) |
1381 | out_le32(mbase + PECFG_POM2LAL, 0); | 1487 | printk(KERN_INFO "%s: Legacy ISA memory support enabled\n", |
1382 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah); | 1488 | hose->dn->full_name); |
1383 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); | 1489 | |
1384 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); | 1490 | /* Configure IO, always 64K starting at 0. We hard wire it to 64K ! |
1385 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0xffff0000 | 3); | 1491 | * Note also that it -has- to be region index 2 on this HW |
1386 | } | 1492 | */ |
1493 | if (hose->io_resource.flags & IORESOURCE_IO) | ||
1494 | ppc4xx_setup_one_pciex_POM(port, hose, mbase, | ||
1495 | hose->io_base_phys, 0, | ||
1496 | 0x10000, IORESOURCE_IO, 2); | ||
1387 | } | 1497 | } |
1388 | 1498 | ||
1389 | static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, | 1499 | static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, |