]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/mips/pci/fixup-cobalt.c
Merge branches 'core/futexes' and 'core/iommu' into core/urgent
[karo-tx-linux.git] / arch / mips / pci / fixup-cobalt.c
index 76b4f0ffb1e5f7a276829c19e5903536856e1523..acacd1407c63e1eb5aa800bffc8a0941b3bc849b 100644 (file)
 #include <asm/gt64120.h>
 
 #include <cobalt.h>
+#include <irq.h>
+
+/*
+ * PCI slot numbers
+ */
+#define COBALT_PCICONF_CPU     0x06
+#define COBALT_PCICONF_ETH0    0x07
+#define COBALT_PCICONF_RAQSCSI 0x08
+#define COBALT_PCICONF_VIA     0x09
+#define COBALT_PCICONF_PCISLOT 0x0A
+#define COBALT_PCICONF_ETH1    0x0C
+
+/*
+ * The Cobalt board ID information.  The boards have an ID number wired
+ * into the VIA that is available in the high nibble of register 94.
+ */
+#define VIA_COBALT_BRD_ID_REG  0x94
+#define VIA_COBALT_BRD_REG_to_ID(reg)  ((unsigned char)(reg) >> 4)
 
 static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
 {
@@ -33,6 +51,67 @@ static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
         qube_raq_galileo_early_fixup);
 
+static void __devinit cobalt_legacy_ide_resource_fixup(struct pci_dev *dev,
+                                                      struct resource *res)
+{
+       struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+       unsigned long offset = hose->io_offset;
+       struct resource orig = *res;
+
+       if (!(res->flags & IORESOURCE_IO) ||
+           !(res->flags & IORESOURCE_PCI_FIXED))
+               return;
+
+       res->start -= offset;
+       res->end -= offset;
+       dev_printk(KERN_DEBUG, &dev->dev, "converted legacy %pR to bus %pR\n",
+                  &orig, res);
+}
+
+static void __devinit cobalt_legacy_ide_fixup(struct pci_dev *dev)
+{
+       u32 class;
+       u8 progif;
+
+       /*
+        * If the IDE controller is in legacy mode, pci_setup_device() fills in
+        * the resources with the legacy addresses that normally appear on the
+        * PCI bus, just as if we had read them from a BAR.
+        *
+        * However, with the GT-64111, those legacy addresses, e.g., 0x1f0,
+        * will never appear on the PCI bus because it converts memory accesses
+        * in the PCI I/O region (which is never at address zero) into I/O port
+        * accesses with no address translation.
+        *
+        * For example, if GT_DEF_PCI0_IO_BASE is 0x10000000, a load or store
+        * to physical address 0x100001f0 will become a PCI access to I/O port
+        * 0x100001f0.  There's no way to generate an access to I/O port 0x1f0,
+        * but the VT82C586 IDE controller does respond at 0x100001f0 because
+        * it only decodes the low 24 bits of the address.
+        *
+        * When this quirk runs, the pci_dev resources should contain bus
+        * addresses, not Linux I/O port numbers, so convert legacy addresses
+        * like 0x1f0 to bus addresses like 0x100001f0.  Later, we'll convert
+        * them back with pcibios_fixup_bus() or pcibios_bus_to_resource().
+        */
+       class = dev->class >> 8;
+       if (class != PCI_CLASS_STORAGE_IDE)
+               return;
+
+       pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+       if ((progif & 1) == 0) {
+               cobalt_legacy_ide_resource_fixup(dev, &dev->resource[0]);
+               cobalt_legacy_ide_resource_fixup(dev, &dev->resource[1]);
+       }
+       if ((progif & 4) == 0) {
+               cobalt_legacy_ide_resource_fixup(dev, &dev->resource[2]);
+               cobalt_legacy_ide_resource_fixup(dev, &dev->resource[3]);
+       }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+         cobalt_legacy_ide_fixup);
+
 static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
 {
        unsigned short cfgword;
@@ -132,34 +211,34 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0,
 
 static char irq_tab_qube1[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
-  [COBALT_PCICONF_ETH0]    = COBALT_QUBE1_ETH0_IRQ,
-  [COBALT_PCICONF_RAQSCSI] = COBALT_SCSI_IRQ,
+  [COBALT_PCICONF_ETH0]    = QUBE1_ETH0_IRQ,
+  [COBALT_PCICONF_RAQSCSI] = SCSI_IRQ,
   [COBALT_PCICONF_VIA]     = 0,
-  [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
+  [COBALT_PCICONF_PCISLOT] = PCISLOT_IRQ,
   [COBALT_PCICONF_ETH1]    = 0
 };
 
 static char irq_tab_cobalt[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
-  [COBALT_PCICONF_ETH0]    = COBALT_ETH0_IRQ,
-  [COBALT_PCICONF_RAQSCSI] = COBALT_SCSI_IRQ,
+  [COBALT_PCICONF_ETH0]    = ETH0_IRQ,
+  [COBALT_PCICONF_RAQSCSI] = SCSI_IRQ,
   [COBALT_PCICONF_VIA]     = 0,
-  [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
-  [COBALT_PCICONF_ETH1]    = COBALT_ETH1_IRQ
+  [COBALT_PCICONF_PCISLOT] = PCISLOT_IRQ,
+  [COBALT_PCICONF_ETH1]    = ETH1_IRQ
 };
 
 static char irq_tab_raq2[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
-  [COBALT_PCICONF_ETH0]    = COBALT_ETH0_IRQ,
-  [COBALT_PCICONF_RAQSCSI] = COBALT_RAQ_SCSI_IRQ,
+  [COBALT_PCICONF_ETH0]    = ETH0_IRQ,
+  [COBALT_PCICONF_RAQSCSI] = RAQ2_SCSI_IRQ,
   [COBALT_PCICONF_VIA]     = 0,
-  [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
-  [COBALT_PCICONF_ETH1]    = COBALT_ETH1_IRQ
+  [COBALT_PCICONF_PCISLOT] = PCISLOT_IRQ,
+  [COBALT_PCICONF_ETH1]    = ETH1_IRQ
 };
 
 int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       if (cobalt_board_id < COBALT_BRD_ID_QUBE2)
+       if (cobalt_board_id <= COBALT_BRD_ID_QUBE1)
                return irq_tab_qube1[slot];
 
        if (cobalt_board_id == COBALT_BRD_ID_RAQ2)