diff options
Diffstat (limited to 'arch/powerpc/platforms/fsl_uli1575.c')
| -rw-r--r-- | arch/powerpc/platforms/fsl_uli1575.c | 142 |
1 files changed, 124 insertions, 18 deletions
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index afc9141be63..b97f6f3d3c5 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c @@ -15,7 +15,6 @@ #include <linux/interrupt.h> #include <linux/mc146818rtc.h> -#include <asm/system.h> #include <asm/pci-bridge.h> #define ULI_PIRQA 0x08 @@ -51,15 +50,20 @@ u8 uli_pirq_to_irq[8] = { ULI_8259_NONE, /* PIRQH */ }; -/* set in board code if you want this quirks to do something */ -int uses_fsl_uli_m1575; +static inline bool is_quirk_valid(void) +{ + return (machine_is(mpc86xx_hpcn) || + machine_is(mpc8544_ds) || + machine_is(p2020_ds) || + machine_is(mpc8572_ds)); +} /* Bridge */ -static void __devinit early_uli5249(struct pci_dev *dev) +static void early_uli5249(struct pci_dev *dev) { unsigned char temp; - if (!uses_fsl_uli_m1575) + if (!is_quirk_valid()) return; pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO | @@ -78,11 +82,11 @@ static void __devinit early_uli5249(struct pci_dev *dev) } -static void __devinit quirk_uli1575(struct pci_dev *dev) +static void quirk_uli1575(struct pci_dev *dev) { int i; - if (!uses_fsl_uli_m1575) + if (!is_quirk_valid()) return; /* @@ -135,7 +139,7 @@ static void __devinit quirk_uli1575(struct pci_dev *dev) pci_write_config_byte(dev, 0x75, ULI_8259_IRQ15); } -static void __devinit quirk_final_uli1575(struct pci_dev *dev) +static void quirk_final_uli1575(struct pci_dev *dev) { /* Set i8259 interrupt trigger * IRQ 3: Level @@ -150,7 +154,7 @@ static void __devinit quirk_final_uli1575(struct pci_dev *dev) * IRQ 14: Edge * IRQ 15: Edge */ - if (!uses_fsl_uli_m1575) + if (!is_quirk_valid()) return; outb(0xfa, 0x4d0); @@ -171,12 +175,12 @@ static void __devinit quirk_final_uli1575(struct pci_dev *dev) } /* SATA */ -static void __devinit quirk_uli5288(struct pci_dev *dev) +static void quirk_uli5288(struct pci_dev *dev) { unsigned char c; unsigned int d; - if (!uses_fsl_uli_m1575) + if (!is_quirk_valid()) return; /* read/write lock */ @@ -196,11 +200,11 @@ static void __devinit quirk_uli5288(struct pci_dev *dev) } /* PATA */ -static void __devinit quirk_uli5229(struct pci_dev *dev) +static void quirk_uli5229(struct pci_dev *dev) { unsigned short temp; - if (!uses_fsl_uli_m1575) + if (!is_quirk_valid()) return; pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE | @@ -212,16 +216,26 @@ static void __devinit quirk_uli5229(struct pci_dev *dev) } /* We have to do a dummy read on the P2P for the RTC to work, WTF */ -static void __devinit quirk_final_uli5249(struct pci_dev *dev) +static void quirk_final_uli5249(struct pci_dev *dev) { int i; u8 *dummy; struct pci_bus *bus = dev->bus; + struct resource *res; + resource_size_t end = 0; + + for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCES+3; i++) { + unsigned long flags = pci_resource_flags(dev, i); + if ((flags & (IORESOURCE_MEM|IORESOURCE_PREFETCH)) == IORESOURCE_MEM) + end = pci_resource_end(dev, i); + } - for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { - if ((bus->resource[i]) && - (bus->resource[i]->flags & IORESOURCE_MEM)) { - dummy = ioremap(bus->resource[i]->start, 0x4); + pci_bus_for_each_resource(bus, res, i) { + if (res && res->flags & IORESOURCE_MEM) { + if (res->end == end) + dummy = ioremap(res->start, 0x4); + else + dummy = ioremap(res->end - 3, 0x4); if (dummy) { in_8(dummy); iounmap(dummy); @@ -237,6 +251,98 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5249, quirk_final_uli5249); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x1575, quirk_final_uli1575); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); + +static void hpcd_quirk_uli1575(struct pci_dev *dev) +{ + u32 temp32; + + if (!machine_is(mpc86xx_hpcd)) + return; + + /* Disable INTx */ + pci_read_config_dword(dev, 0x48, &temp32); + pci_write_config_dword(dev, 0x48, (temp32 | 1<<26)); + + /* Enable sideband interrupt */ + pci_read_config_dword(dev, 0x90, &temp32); + pci_write_config_dword(dev, 0x90, (temp32 | 1<<22)); +} + +static void hpcd_quirk_uli5288(struct pci_dev *dev) +{ + unsigned char c; + + if (!machine_is(mpc86xx_hpcd)) + return; + + pci_read_config_byte(dev, 0x83, &c); + c |= 0x80; + pci_write_config_byte(dev, 0x83, c); + + pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01); + pci_write_config_byte(dev, PCI_CLASS_DEVICE, 0x06); + + pci_read_config_byte(dev, 0x83, &c); + c &= 0x7f; + pci_write_config_byte(dev, 0x83, c); +} + +/* + * Since 8259PIC was disabled on the board, the IDE device can not + * use the legacy IRQ, we need to let the IDE device work under + * native mode and use the interrupt line like other PCI devices. + * IRQ14 is a sideband interrupt from IDE device to CPU and we use this + * as the interrupt for IDE device. + */ +static void hpcd_quirk_uli5229(struct pci_dev *dev) +{ + unsigned char c; + + if (!machine_is(mpc86xx_hpcd)) + return; + + pci_read_config_byte(dev, 0x4b, &c); + c |= 0x10; + pci_write_config_byte(dev, 0x4b, c); +} + +/* + * SATA interrupt pin bug fix + * There's a chip bug for 5288, The interrupt pin should be 2, + * not the read only value 1, So it use INTB#, not INTA# which + * actually used by the IDE device 5229. + * As of this bug, during the PCI initialization, 5288 read the + * irq of IDE device from the device tree, this function fix this + * bug by re-assigning a correct irq to 5288. + * + */ +static void hpcd_final_uli5288(struct pci_dev *dev) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct device_node *hosenode = hose ? hose->dn : NULL; + struct of_phandle_args oirq; + u32 laddr[3]; + + if (!machine_is(mpc86xx_hpcd)) + return; + + if (!hosenode) + return; + + oirq.np = hosenode; + oirq.args[0] = 2; + oirq.args_count = 1; + laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8); + laddr[1] = laddr[2] = 0; + of_irq_parse_raw(laddr, &oirq); + dev->irq = irq_create_of_mapping(&oirq); +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, hpcd_quirk_uli5288); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, hpcd_quirk_uli5229); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5288, hpcd_final_uli5288); int uli_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) |
