Merge mulgrave-w:git/scsi-misc-2.6
[pandora-kernel.git] / drivers / macintosh / macio_asic.c
index 431bd37..d562160 100644 (file)
@@ -17,7 +17,6 @@
  *    sub-devices.
  */
  
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -140,7 +139,9 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp,
 {
        struct macio_dev * macio_dev;
        struct of_device * of;
-       char *scratch, *compat, *compat2;
+       char *scratch;
+       const char *compat, *compat2;
+
        int i = 0;
        int length, cplen, cplen2, seen = 0;
 
@@ -174,7 +175,7 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp,
          * it's not really legal to split it out with commas. We split it
          * up using a number of environment variables instead. */
 
-       compat = (char *) get_property(of->node, "compatible", &cplen);
+       compat = get_property(of->node, "compatible", &cplen);
        compat2 = compat;
        cplen2= cplen;
        while (compat && cplen > 0) {
@@ -281,75 +282,128 @@ static void macio_release_dev(struct device *dev)
 static int macio_resource_quirks(struct device_node *np, struct resource *res,
                                 int index)
 {
-       if (res->flags & IORESOURCE_MEM) {
-               /* Grand Central has too large resource 0 on some machines */
-               if (index == 0 && !strcmp(np->name, "gc"))
-                       res->end = res->start + 0x1ffff;
+       /* Only quirks for memory resources for now */
+       if ((res->flags & IORESOURCE_MEM) == 0)
+               return 0;
 
-               /* Airport has bogus resource 2 */
-               if (index >= 2 && !strcmp(np->name, "radio"))
-                       return 1;
+       /* Grand Central has too large resource 0 on some machines */
+       if (index == 0 && !strcmp(np->name, "gc"))
+               res->end = res->start + 0x1ffff;
+
+       /* Airport has bogus resource 2 */
+       if (index >= 2 && !strcmp(np->name, "radio"))
+               return 1;
 
 #ifndef CONFIG_PPC64
-               /* DBDMAs may have bogus sizes */
-               if ((res->start & 0x0001f000) == 0x00008000)
-                       res->end = res->start + 0xff;
+       /* DBDMAs may have bogus sizes */
+       if ((res->start & 0x0001f000) == 0x00008000)
+               res->end = res->start + 0xff;
 #endif /* CONFIG_PPC64 */
 
-               /* ESCC parent eats child resources. We could have added a
-                * level of hierarchy, but I don't really feel the need
-                * for it
-                */
-               if (!strcmp(np->name, "escc"))
-                       return 1;
-
-               /* ESCC has bogus resources >= 3 */
-               if (index >= 3 && !(strcmp(np->name, "ch-a") &&
-                                   strcmp(np->name, "ch-b")))
-                       return 1;
-
-               /* Media bay has too many resources, keep only first one */
-               if (index > 0 && !strcmp(np->name, "media-bay"))
-                       return 1;
-
-               /* Some older IDE resources have bogus sizes */
-               if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") &&
-                     strcmp(np->type, "ide") && strcmp(np->type, "ata"))) {
-                       if (index == 0 && (res->end - res->start) > 0xfff)
-                               res->end = res->start + 0xfff;
-                       if (index == 1 && (res->end - res->start) > 0xff)
-                               res->end = res->start + 0xff;
-               }
+       /* ESCC parent eats child resources. We could have added a
+        * level of hierarchy, but I don't really feel the need
+        * for it
+        */
+       if (!strcmp(np->name, "escc"))
+               return 1;
+
+       /* ESCC has bogus resources >= 3 */
+       if (index >= 3 && !(strcmp(np->name, "ch-a") &&
+                           strcmp(np->name, "ch-b")))
+               return 1;
+
+       /* Media bay has too many resources, keep only first one */
+       if (index > 0 && !strcmp(np->name, "media-bay"))
+               return 1;
+
+       /* Some older IDE resources have bogus sizes */
+       if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") &&
+             strcmp(np->type, "ide") && strcmp(np->type, "ata"))) {
+               if (index == 0 && (res->end - res->start) > 0xfff)
+                       res->end = res->start + 0xfff;
+               if (index == 1 && (res->end - res->start) > 0xff)
+                       res->end = res->start + 0xff;
        }
        return 0;
 }
 
+static void macio_create_fixup_irq(struct macio_dev *dev, int index,
+                                  unsigned int line)
+{
+       unsigned int irq;
 
-static void macio_setup_interrupts(struct macio_dev *dev)
+       irq = irq_create_mapping(NULL, line);
+       if (irq != NO_IRQ) {
+               dev->interrupt[index].start = irq;
+               dev->interrupt[index].flags = IORESOURCE_IRQ;
+               dev->interrupt[index].name = dev->ofdev.dev.bus_id;
+       }
+       if (dev->n_interrupts <= index)
+               dev->n_interrupts = index + 1;
+}
+
+static void macio_add_missing_resources(struct macio_dev *dev)
 {
        struct device_node *np = dev->ofdev.node;
-       int i,j;
+       unsigned int irq_base;
+
+       /* Gatwick has some missing interrupts on child nodes */
+       if (dev->bus->chip->type != macio_gatwick)
+               return;
 
-       /* For now, we use pre-parsed entries in the device-tree for
-        * interrupt routing and addresses, but we should change that
-        * to dynamically parsed entries and so get rid of most of the
-        * clutter in struct device_node
+       /* irq_base is always 64 on gatwick. I have no cleaner way to get
+        * that value from here at this point
         */
-       for (i = j = 0; i < np->n_intrs; i++) {
+       irq_base = 64;
+
+       /* Fix SCC */
+       if (strcmp(np->name, "ch-a") == 0) {
+               macio_create_fixup_irq(dev, 0, 15 + irq_base);
+               macio_create_fixup_irq(dev, 1,  4 + irq_base);
+               macio_create_fixup_irq(dev, 2,  5 + irq_base);
+               printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n");
+       }
+
+       /* Fix media-bay */
+       if (strcmp(np->name, "media-bay") == 0) {
+               macio_create_fixup_irq(dev, 0, 29 + irq_base);
+               printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n");
+       }
+
+       /* Fix left media bay childs */
+       if (dev->media_bay != NULL && strcmp(np->name, "floppy") == 0) {
+               macio_create_fixup_irq(dev, 0, 19 + irq_base);
+               macio_create_fixup_irq(dev, 1,  1 + irq_base);
+               printk(KERN_INFO "macio: fixed left floppy irqs\n");
+       }
+       if (dev->media_bay != NULL && strcasecmp(np->name, "ata4") == 0) {
+               macio_create_fixup_irq(dev, 0, 14 + irq_base);
+               macio_create_fixup_irq(dev, 0,  3 + irq_base);
+               printk(KERN_INFO "macio: fixed left ide irqs\n");
+       }
+}
+
+static void macio_setup_interrupts(struct macio_dev *dev)
+{
+       struct device_node *np = dev->ofdev.node;
+       unsigned int irq;
+       int i = 0, j = 0;
+
+       for (;;) {
                struct resource *res = &dev->interrupt[j];
 
                if (j >= MACIO_DEV_COUNT_IRQS)
                        break;
-               res->start = np->intrs[i].line;
-               res->flags = IORESOURCE_IO;
-               if (np->intrs[j].sense)
-                       res->flags |= IORESOURCE_IRQ_LOWLEVEL;
-               else
-                       res->flags |= IORESOURCE_IRQ_HIGHEDGE;
+               irq = irq_of_parse_and_map(np, i++);
+               if (irq == NO_IRQ)
+                       break;
+               res->start = irq;
+               res->flags = IORESOURCE_IRQ;
                res->name = dev->ofdev.dev.bus_id;
-               if (macio_resource_quirks(np, res, i))
+               if (macio_resource_quirks(np, res, i - 1)) {
                        memset(res, 0, sizeof(struct resource));
-               else
+                       continue;
+               } else
                        j++;
        }
        dev->n_interrupts = j;
@@ -402,7 +456,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
                                               struct resource *parent_res)
 {
        struct macio_dev *dev;
-       u32 *reg;
+       const u32 *reg;
        
        if (np == NULL)
                return NULL;
@@ -428,16 +482,16 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
 
        /* MacIO itself has a different reg, we use it's PCI base */
        if (np == chip->of_node) {
-               sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s",
+               sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s",
                        chip->lbus.index,
 #ifdef CONFIG_PCI
-                       pci_resource_start(chip->lbus.pdev, 0),
+                       (unsigned int)pci_resource_start(chip->lbus.pdev, 0),
 #else
                        0, /* NuBus may want to do something better here */
 #endif
                        MAX_NODE_NAME_SIZE, np->name);
        } else {
-               reg = (u32 *)get_property(np, "reg", NULL);
+               reg = get_property(np, "reg", NULL);
                sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s",
                        chip->lbus.index,
                        reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name);
@@ -446,6 +500,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
        /* Setup interrupts & resources */
        macio_setup_interrupts(dev);
        macio_setup_resources(dev, parent_res);
+       macio_add_missing_resources(dev);
 
        /* Register with core */
        if (of_device_register(&dev->ofdev) != 0) {