|
@@ -194,11 +194,41 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
|
|
* 4xx PCI 2.x part
|
|
* 4xx PCI 2.x part
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
+static int __init ppc4xx_setup_one_pci_PMM(struct pci_controller *hose,
|
|
|
|
+ void __iomem *reg,
|
|
|
|
+ u64 plb_addr,
|
|
|
|
+ u64 pci_addr,
|
|
|
|
+ u64 size,
|
|
|
|
+ unsigned int flags,
|
|
|
|
+ int index)
|
|
|
|
+{
|
|
|
|
+ u32 ma, pcila, pciha;
|
|
|
|
+
|
|
|
|
+ if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) ||
|
|
|
|
+ size < 0x1000 || (plb_addr & (size - 1)) != 0) {
|
|
|
|
+ printk(KERN_WARNING "%s: Resource out of range\n",
|
|
|
|
+ hose->dn->full_name);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ ma = (0xffffffffu << ilog2(size)) | 1;
|
|
|
|
+ if (flags & IORESOURCE_PREFETCH)
|
|
|
|
+ ma |= 2;
|
|
|
|
+
|
|
|
|
+ pciha = RES_TO_U32_HIGH(pci_addr);
|
|
|
|
+ pcila = RES_TO_U32_LOW(pci_addr);
|
|
|
|
+
|
|
|
|
+ writel(plb_addr, reg + PCIL0_PMM0LA + (0x10 * index));
|
|
|
|
+ writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * index));
|
|
|
|
+ writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * index));
|
|
|
|
+ writel(ma, reg + PCIL0_PMM0MA + (0x10 * index));
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
|
|
static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
|
|
void __iomem *reg)
|
|
void __iomem *reg)
|
|
{
|
|
{
|
|
- u32 la, ma, pcila, pciha;
|
|
|
|
- int i, j;
|
|
|
|
|
|
+ int i, j, found_isa_hole = 0;
|
|
|
|
|
|
/* Setup outbound memory windows */
|
|
/* Setup outbound memory windows */
|
|
for (i = j = 0; i < 3; i++) {
|
|
for (i = j = 0; i < 3; i++) {
|
|
@@ -213,28 +243,29 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Calculate register values */
|
|
|
|
- la = res->start;
|
|
|
|
- pciha = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
|
|
|
|
- pcila = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
|
|
|
|
-
|
|
|
|
- ma = res->end + 1 - res->start;
|
|
|
|
- if (!is_power_of_2(ma) || ma < 0x1000 || ma > 0xffffffffu) {
|
|
|
|
- printk(KERN_WARNING "%s: Resource out of range\n",
|
|
|
|
- hose->dn->full_name);
|
|
|
|
- continue;
|
|
|
|
|
|
+ /* Configure the resource */
|
|
|
|
+ if (ppc4xx_setup_one_pci_PMM(hose, reg,
|
|
|
|
+ res->start,
|
|
|
|
+ res->start - hose->pci_mem_offset,
|
|
|
|
+ res->end + 1 - res->start,
|
|
|
|
+ res->flags,
|
|
|
|
+ j) == 0) {
|
|
|
|
+ j++;
|
|
|
|
+
|
|
|
|
+ /* If the resource PCI address is 0 then we have our
|
|
|
|
+ * ISA memory hole
|
|
|
|
+ */
|
|
|
|
+ if (res->start == hose->pci_mem_offset)
|
|
|
|
+ found_isa_hole = 1;
|
|
}
|
|
}
|
|
- ma = (0xffffffffu << ilog2(ma)) | 0x1;
|
|
|
|
- if (res->flags & IORESOURCE_PREFETCH)
|
|
|
|
- ma |= 0x2;
|
|
|
|
-
|
|
|
|
- /* Program register values */
|
|
|
|
- writel(la, reg + PCIL0_PMM0LA + (0x10 * j));
|
|
|
|
- writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * j));
|
|
|
|
- writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * j));
|
|
|
|
- writel(ma, reg + PCIL0_PMM0MA + (0x10 * j));
|
|
|
|
- j++;
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* Handle ISA memory hole if not already covered */
|
|
|
|
+ if (j <= 2 && !found_isa_hole && hose->isa_mem_size)
|
|
|
|
+ if (ppc4xx_setup_one_pci_PMM(hose, reg, hose->isa_mem_phys, 0,
|
|
|
|
+ hose->isa_mem_size, 0, j) == 0)
|
|
|
|
+ printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
|
|
|
|
+ hose->dn->full_name);
|
|
}
|
|
}
|
|
|
|
|
|
static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,
|
|
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)
|
|
* 4xx PCI-X part
|
|
* 4xx PCI-X part
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
+static int __init ppc4xx_setup_one_pcix_POM(struct pci_controller *hose,
|
|
|
|
+ void __iomem *reg,
|
|
|
|
+ u64 plb_addr,
|
|
|
|
+ u64 pci_addr,
|
|
|
|
+ u64 size,
|
|
|
|
+ unsigned int flags,
|
|
|
|
+ int index)
|
|
|
|
+{
|
|
|
|
+ u32 lah, lal, pciah, pcial, sa;
|
|
|
|
+
|
|
|
|
+ if (!is_power_of_2(size) || size < 0x1000 ||
|
|
|
|
+ (plb_addr & (size - 1)) != 0) {
|
|
|
|
+ printk(KERN_WARNING "%s: Resource out of range\n",
|
|
|
|
+ hose->dn->full_name);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Calculate register values */
|
|
|
|
+ lah = RES_TO_U32_HIGH(plb_addr);
|
|
|
|
+ lal = RES_TO_U32_LOW(plb_addr);
|
|
|
|
+ pciah = RES_TO_U32_HIGH(pci_addr);
|
|
|
|
+ pcial = RES_TO_U32_LOW(pci_addr);
|
|
|
|
+ sa = (0xffffffffu << ilog2(size)) | 0x1;
|
|
|
|
+
|
|
|
|
+ /* Program register values */
|
|
|
|
+ if (index == 0) {
|
|
|
|
+ writel(lah, reg + PCIX0_POM0LAH);
|
|
|
|
+ writel(lal, reg + PCIX0_POM0LAL);
|
|
|
|
+ writel(pciah, reg + PCIX0_POM0PCIAH);
|
|
|
|
+ writel(pcial, reg + PCIX0_POM0PCIAL);
|
|
|
|
+ writel(sa, reg + PCIX0_POM0SA);
|
|
|
|
+ } else {
|
|
|
|
+ writel(lah, reg + PCIX0_POM1LAH);
|
|
|
|
+ writel(lal, reg + PCIX0_POM1LAL);
|
|
|
|
+ writel(pciah, reg + PCIX0_POM1PCIAH);
|
|
|
|
+ writel(pcial, reg + PCIX0_POM1PCIAL);
|
|
|
|
+ writel(sa, reg + PCIX0_POM1SA);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
|
|
static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
|
|
void __iomem *reg)
|
|
void __iomem *reg)
|
|
{
|
|
{
|
|
- u32 lah, lal, pciah, pcial, sa;
|
|
|
|
- int i, j;
|
|
|
|
|
|
+ int i, j, found_isa_hole = 0;
|
|
|
|
|
|
/* Setup outbound memory windows */
|
|
/* Setup outbound memory windows */
|
|
for (i = j = 0; i < 3; i++) {
|
|
for (i = j = 0; i < 3; i++) {
|
|
@@ -371,36 +443,29 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Calculate register values */
|
|
|
|
- lah = RES_TO_U32_HIGH(res->start);
|
|
|
|
- lal = RES_TO_U32_LOW(res->start);
|
|
|
|
- pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
|
|
|
|
- pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
|
|
|
|
- sa = res->end + 1 - res->start;
|
|
|
|
- if (!is_power_of_2(sa) || sa < 0x100000 ||
|
|
|
|
- sa > 0xffffffffu) {
|
|
|
|
- printk(KERN_WARNING "%s: Resource out of range\n",
|
|
|
|
- hose->dn->full_name);
|
|
|
|
- continue;
|
|
|
|
|
|
+ /* Configure the resource */
|
|
|
|
+ if (ppc4xx_setup_one_pcix_POM(hose, reg,
|
|
|
|
+ res->start,
|
|
|
|
+ res->start - hose->pci_mem_offset,
|
|
|
|
+ res->end + 1 - res->start,
|
|
|
|
+ res->flags,
|
|
|
|
+ j) == 0) {
|
|
|
|
+ j++;
|
|
|
|
+
|
|
|
|
+ /* If the resource PCI address is 0 then we have our
|
|
|
|
+ * ISA memory hole
|
|
|
|
+ */
|
|
|
|
+ if (res->start == hose->pci_mem_offset)
|
|
|
|
+ found_isa_hole = 1;
|
|
}
|
|
}
|
|
- sa = (0xffffffffu << ilog2(sa)) | 0x1;
|
|
|
|
-
|
|
|
|
- /* Program register values */
|
|
|
|
- if (j == 0) {
|
|
|
|
- writel(lah, reg + PCIX0_POM0LAH);
|
|
|
|
- writel(lal, reg + PCIX0_POM0LAL);
|
|
|
|
- writel(pciah, reg + PCIX0_POM0PCIAH);
|
|
|
|
- writel(pcial, reg + PCIX0_POM0PCIAL);
|
|
|
|
- writel(sa, reg + PCIX0_POM0SA);
|
|
|
|
- } else {
|
|
|
|
- writel(lah, reg + PCIX0_POM1LAH);
|
|
|
|
- writel(lal, reg + PCIX0_POM1LAL);
|
|
|
|
- writel(pciah, reg + PCIX0_POM1PCIAH);
|
|
|
|
- writel(pcial, reg + PCIX0_POM1PCIAL);
|
|
|
|
- writel(sa, reg + PCIX0_POM1SA);
|
|
|
|
- }
|
|
|
|
- j++;
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* Handle ISA memory hole if not already covered */
|
|
|
|
+ if (j <= 1 && !found_isa_hole && hose->isa_mem_size)
|
|
|
|
+ if (ppc4xx_setup_one_pcix_POM(hose, reg, hose->isa_mem_phys, 0,
|
|
|
|
+ hose->isa_mem_size, 0, j) == 0)
|
|
|
|
+ printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
|
|
|
|
+ hose->dn->full_name);
|
|
}
|
|
}
|
|
|
|
|
|
static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
|
|
static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
|
|
@@ -1317,12 +1382,72 @@ static struct pci_ops ppc4xx_pciex_pci_ops =
|
|
.write = ppc4xx_pciex_write_config,
|
|
.write = ppc4xx_pciex_write_config,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
|
|
|
|
+ struct pci_controller *hose,
|
|
|
|
+ void __iomem *mbase,
|
|
|
|
+ u64 plb_addr,
|
|
|
|
+ u64 pci_addr,
|
|
|
|
+ u64 size,
|
|
|
|
+ unsigned int flags,
|
|
|
|
+ int index)
|
|
|
|
+{
|
|
|
|
+ u32 lah, lal, pciah, pcial, sa;
|
|
|
|
+
|
|
|
|
+ if (!is_power_of_2(size) ||
|
|
|
|
+ (index < 2 && size < 0x100000) ||
|
|
|
|
+ (index == 2 && size < 0x100) ||
|
|
|
|
+ (plb_addr & (size - 1)) != 0) {
|
|
|
|
+ printk(KERN_WARNING "%s: Resource out of range\n",
|
|
|
|
+ hose->dn->full_name);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Calculate register values */
|
|
|
|
+ lah = RES_TO_U32_HIGH(plb_addr);
|
|
|
|
+ lal = RES_TO_U32_LOW(plb_addr);
|
|
|
|
+ pciah = RES_TO_U32_HIGH(pci_addr);
|
|
|
|
+ pcial = RES_TO_U32_LOW(pci_addr);
|
|
|
|
+ sa = (0xffffffffu << ilog2(size)) | 0x1;
|
|
|
|
+
|
|
|
|
+ /* Program register values */
|
|
|
|
+ switch (index) {
|
|
|
|
+ case 0:
|
|
|
|
+ out_le32(mbase + PECFG_POM0LAH, pciah);
|
|
|
|
+ out_le32(mbase + PECFG_POM0LAL, pcial);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
|
|
|
|
+ /* Note that 3 here means enabled | single region */
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
|
|
|
|
+ break;
|
|
|
|
+ case 1:
|
|
|
|
+ out_le32(mbase + PECFG_POM1LAH, pciah);
|
|
|
|
+ out_le32(mbase + PECFG_POM1LAL, pcial);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
|
|
|
|
+ /* Note that 3 here means enabled | single region */
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
|
|
|
|
+ break;
|
|
|
|
+ case 2:
|
|
|
|
+ out_le32(mbase + PECFG_POM2LAH, pciah);
|
|
|
|
+ out_le32(mbase + PECFG_POM2LAL, pcial);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
|
|
|
|
+ /* Note that 3 here means enabled | IO space !!! */
|
|
|
|
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
|
|
static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
|
|
struct pci_controller *hose,
|
|
struct pci_controller *hose,
|
|
void __iomem *mbase)
|
|
void __iomem *mbase)
|
|
{
|
|
{
|
|
- u32 lah, lal, pciah, pcial, sa;
|
|
|
|
- int i, j;
|
|
|
|
|
|
+ int i, j, found_isa_hole = 0;
|
|
|
|
|
|
/* Setup outbound memory windows */
|
|
/* Setup outbound memory windows */
|
|
for (i = j = 0; i < 3; i++) {
|
|
for (i = j = 0; i < 3; i++) {
|
|
@@ -1337,53 +1462,38 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Calculate register values */
|
|
|
|
- lah = RES_TO_U32_HIGH(res->start);
|
|
|
|
- lal = RES_TO_U32_LOW(res->start);
|
|
|
|
- pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
|
|
|
|
- pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
|
|
|
|
- sa = res->end + 1 - res->start;
|
|
|
|
- if (!is_power_of_2(sa) || sa < 0x100000 ||
|
|
|
|
- sa > 0xffffffffu) {
|
|
|
|
- printk(KERN_WARNING "%s: Resource out of range\n",
|
|
|
|
- port->node->full_name);
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- sa = (0xffffffffu << ilog2(sa)) | 0x1;
|
|
|
|
-
|
|
|
|
- /* Program register values */
|
|
|
|
- switch (j) {
|
|
|
|
- case 0:
|
|
|
|
- out_le32(mbase + PECFG_POM0LAH, pciah);
|
|
|
|
- out_le32(mbase + PECFG_POM0LAL, pcial);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
|
|
|
|
- break;
|
|
|
|
- case 1:
|
|
|
|
- out_le32(mbase + PECFG_POM1LAH, pciah);
|
|
|
|
- out_le32(mbase + PECFG_POM1LAL, pcial);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
|
|
|
|
- break;
|
|
|
|
|
|
+ /* Configure the resource */
|
|
|
|
+ if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
|
|
|
|
+ res->start,
|
|
|
|
+ res->start - hose->pci_mem_offset,
|
|
|
|
+ res->end + 1 - res->start,
|
|
|
|
+ res->flags,
|
|
|
|
+ j) == 0) {
|
|
|
|
+ j++;
|
|
|
|
+
|
|
|
|
+ /* If the resource PCI address is 0 then we have our
|
|
|
|
+ * ISA memory hole
|
|
|
|
+ */
|
|
|
|
+ if (res->start == hose->pci_mem_offset)
|
|
|
|
+ found_isa_hole = 1;
|
|
}
|
|
}
|
|
- j++;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- /* Configure IO, always 64K starting at 0 */
|
|
|
|
- if (hose->io_resource.flags & IORESOURCE_IO) {
|
|
|
|
- lah = RES_TO_U32_HIGH(hose->io_base_phys);
|
|
|
|
- lal = RES_TO_U32_LOW(hose->io_base_phys);
|
|
|
|
- out_le32(mbase + PECFG_POM2LAH, 0);
|
|
|
|
- out_le32(mbase + PECFG_POM2LAL, 0);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
|
|
|
|
- dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0xffff0000 | 3);
|
|
|
|
- }
|
|
|
|
|
|
+ /* Handle ISA memory hole if not already covered */
|
|
|
|
+ if (j <= 1 && !found_isa_hole && hose->isa_mem_size)
|
|
|
|
+ if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
|
|
|
|
+ hose->isa_mem_phys, 0,
|
|
|
|
+ hose->isa_mem_size, 0, j) == 0)
|
|
|
|
+ printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
|
|
|
|
+ hose->dn->full_name);
|
|
|
|
+
|
|
|
|
+ /* Configure IO, always 64K starting at 0. We hard wire it to 64K !
|
|
|
|
+ * Note also that it -has- to be region index 2 on this HW
|
|
|
|
+ */
|
|
|
|
+ if (hose->io_resource.flags & IORESOURCE_IO)
|
|
|
|
+ ppc4xx_setup_one_pciex_POM(port, hose, mbase,
|
|
|
|
+ hose->io_base_phys, 0,
|
|
|
|
+ 0x10000, IORESOURCE_IO, 2);
|
|
}
|
|
}
|
|
|
|
|
|
static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
|
|
static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
|