Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[safe/jmp/linux-2.6] / arch / powerpc / kernel / prom_parse.c
index 91b443c..8362620 100644 (file)
@@ -68,9 +68,9 @@ static void of_bus_default_count_cells(struct device_node *dev,
                                       int *addrc, int *sizec)
 {
        if (addrc)
-               *addrc = prom_n_addr_cells(dev);
+               *addrc = of_n_addr_cells(dev);
        if (sizec)
-               *sizec = prom_n_size_cells(dev);
+               *sizec = of_n_size_cells(dev);
 }
 
 static u64 of_bus_default_map(u32 *addr, const u32 *range,
@@ -128,12 +128,35 @@ static void of_bus_pci_count_cells(struct device_node *np,
                *sizec = 2;
 }
 
+static unsigned int of_bus_pci_get_flags(const u32 *addr)
+{
+       unsigned int flags = 0;
+       u32 w = addr[0];
+
+       switch((w >> 24) & 0x03) {
+       case 0x01:
+               flags |= IORESOURCE_IO;
+               break;
+       case 0x02: /* 32 bits */
+       case 0x03: /* 64 bits */
+               flags |= IORESOURCE_MEM;
+               break;
+       }
+       if (w & 0x40000000)
+               flags |= IORESOURCE_PREFETCH;
+       return flags;
+}
+
 static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
 {
        u64 cp, s, da;
+       unsigned int af, rf;
+
+       af = of_bus_pci_get_flags(addr);
+       rf = of_bus_pci_get_flags(range);
 
        /* Check address type match */
-       if ((addr[0] ^ range[0]) & 0x03000000)
+       if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
                return OF_BAD_ADDR;
 
        /* Read address values, skipping high cell */
@@ -153,25 +176,6 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
        return of_bus_default_translate(addr + 1, offset, na - 1);
 }
 
-static unsigned int of_bus_pci_get_flags(const u32 *addr)
-{
-       unsigned int flags = 0;
-       u32 w = addr[0];
-
-       switch((w >> 24) & 0x03) {
-       case 0x01:
-               flags |= IORESOURCE_IO;
-               break;
-       case 0x02: /* 32 bits */
-       case 0x03: /* 64 bits */
-               flags |= IORESOURCE_MEM;
-               break;
-       }
-       if (w & 0x40000000)
-               flags |= IORESOURCE_PREFETCH;
-       return flags;
-}
-
 const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
                        unsigned int *flags)
 {
@@ -196,7 +200,7 @@ const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
                return NULL;
 
        /* Get "reg" or "assigned-addresses" property */
-       prop = get_property(dev, bus->addresses, &psize);
+       prop = of_get_property(dev, bus->addresses, &psize);
        if (prop == NULL)
                return NULL;
        psize /= 4;
@@ -228,11 +232,6 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
 }
 EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
 
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
-       return (((pin - 1) + slot) % 4) + 1;
-}
-
 int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 {
        struct device_node *dn, *ppnode;
@@ -246,8 +245,11 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
         * parsing
         */
        dn = pci_device_to_OF_node(pdev);
-       if (dn)
-               return of_irq_map_one(dn, 0, out_irq);
+       if (dn) {
+               rc = of_irq_map_one(dn, 0, out_irq);
+               if (!rc)
+                       return rc;
+       }
 
        /* Ok, we don't, time to have fun. Let's start by building up an
         * interrupt spec.  we assume #interrupt-cells is 1, which is standard
@@ -273,7 +275,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 #else
                        struct pci_controller *host;
                        host = pci_bus_to_host(pdev->bus);
-                       ppnode = host ? host->arch_data : NULL;
+                       ppnode = host ? host->dn : NULL;
 #endif
                        /* No node for host bridge ? give up */
                        if (ppnode == NULL)
@@ -299,7 +301,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
                /* We can only get here if we hit a P2P bridge with no node,
                 * let's do standard swizzling and try again
                 */
-               lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+               lspec = pci_swizzle_interrupt_pin(pdev, lspec);
                pdev = ppdev;
        }
 
@@ -419,7 +421,7 @@ static struct of_bus *of_match_bus(struct device_node *np)
 
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
                            struct of_bus *pbus, u32 *addr,
-                           int na, int ns, int pna)
+                           int na, int ns, int pna, const char *rprop)
 {
        const u32 *ranges;
        unsigned int rlen;
@@ -438,7 +440,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * to translate addresses that aren't supposed to be translated in
         * the first place. --BenH.
         */
-       ranges = get_property(parent, "ranges", &rlen);
+       ranges = of_get_property(parent, rprop, &rlen);
        if (ranges == NULL || rlen == 0) {
                offset = of_read_number(addr, na);
                memset(addr, 0, pna * 4);
@@ -481,7 +483,8 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
+                          const char *rprop)
 {
        struct device_node *parent = NULL;
        struct of_bus *bus, *pbus;
@@ -540,7 +543,7 @@ u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
                    pbus->name, pna, pns, parent->full_name);
 
                /* Apply bus translation */
-               if (of_translate_one(dev, bus, pbus, addr, na, ns, pna))
+               if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
                        break;
 
                /* Complete the move up one level */
@@ -556,8 +559,19 @@ u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
 
        return result;
 }
+
+u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+{
+       return __of_translate_address(dev, in_addr, "ranges");
+}
 EXPORT_SYMBOL(of_translate_address);
 
+u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr)
+{
+       return __of_translate_address(dev, in_addr, "dma-ranges");
+}
+EXPORT_SYMBOL(of_translate_dma_address);
+
 const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
                    unsigned int *flags)
 {
@@ -578,7 +592,7 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
                return NULL;
 
        /* Get "reg" or "assigned-addresses" property */
-       prop = get_property(dev, bus->addresses, &psize);
+       prop = of_get_property(dev, bus->addresses, &psize);
        if (prop == NULL)
                return NULL;
        psize /= 4;
@@ -650,17 +664,17 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
        /* busno is always one cell */
        *busno = *(dma_window++);
 
-       prop = get_property(dn, "ibm,#dma-address-cells", NULL);
+       prop = of_get_property(dn, "ibm,#dma-address-cells", NULL);
        if (!prop)
-               prop = get_property(dn, "#address-cells", NULL);
+               prop = of_get_property(dn, "#address-cells", NULL);
 
-       cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn);
+       cells = prop ? *(u32 *)prop : of_n_addr_cells(dn);
        *phys = of_read_number(dma_window, cells);
 
        dma_window += cells;
 
-       prop = get_property(dn, "ibm,#dma-size-cells", NULL);
-       cells = prop ? *(u32 *)prop : prom_n_size_cells(dn);
+       prop = of_get_property(dn, "ibm,#dma-size-cells", NULL);
+       cells = prop ? *(u32 *)prop : of_n_size_cells(dn);
        *size = of_read_number(dma_window, cells);
 }
 
@@ -680,7 +694,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child)
                return NULL;
 
        do {
-               parp = get_property(child, "interrupt-parent", NULL);
+               parp = of_get_property(child, "interrupt-parent", NULL);
                if (parp == NULL)
                        p = of_get_parent(child);
                else {
@@ -691,7 +705,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child)
                }
                of_node_put(child);
                child = p;
-       } while (p && get_property(p, "#interrupt-cells", NULL) == NULL);
+       } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
 
        return p;
 }
@@ -715,10 +729,7 @@ void of_irq_map_init(unsigned int flags)
        if (flags & OF_IMAP_NO_PHANDLE) {
                struct device_node *np;
 
-               for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) {
-                       if (get_property(np, "interrupt-controller", NULL)
-                           == NULL)
-                               continue;
+               for_each_node_with_property(np, "interrupt-controller") {
                        /* Skip /chosen/interrupt-controller */
                        if (strcmp(np->name, "chosen") == 0)
                                continue;
@@ -755,7 +766,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
         * is none, we are nice and just walk up the tree
         */
        do {
-               tmp = get_property(ipar, "#interrupt-cells", NULL);
+               tmp = of_get_property(ipar, "#interrupt-cells", NULL);
                if (tmp != NULL) {
                        intsize = *tmp;
                        break;
@@ -779,7 +790,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
         */
        old = of_node_get(ipar);
        do {
-               tmp = get_property(old, "#address-cells", NULL);
+               tmp = of_get_property(old, "#address-cells", NULL);
                tnode = of_get_parent(old);
                of_node_put(old);
                old = tnode;
@@ -795,7 +806,8 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
                /* Now check if cursor is an interrupt-controller and if it is
                 * then we are done
                 */
-               if (get_property(ipar, "interrupt-controller", NULL) != NULL) {
+               if (of_get_property(ipar, "interrupt-controller", NULL) !=
+                               NULL) {
                        DBG(" -> got it !\n");
                        memcpy(out_irq->specifier, intspec,
                               intsize * sizeof(u32));
@@ -806,7 +818,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
                }
 
                /* Now look for an interrupt-map */
-               imap = get_property(ipar, "interrupt-map", &imaplen);
+               imap = of_get_property(ipar, "interrupt-map", &imaplen);
                /* No interrupt map, check for an interrupt parent */
                if (imap == NULL) {
                        DBG(" -> no map, getting parent\n");
@@ -816,7 +828,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
                imaplen /= sizeof(u32);
 
                /* Look for a mask */
-               imask = get_property(ipar, "interrupt-map-mask", NULL);
+               imask = of_get_property(ipar, "interrupt-map-mask", NULL);
 
                /* If we were passed no "reg" property and we attempt to parse
                 * an interrupt-map, then #address-cells must be 0.
@@ -863,15 +875,13 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
                        /* Get #interrupt-cells and #address-cells of new
                         * parent
                         */
-                       tmp = get_property(newpar, "#interrupt-cells",
-                                                 NULL);
+                       tmp = of_get_property(newpar, "#interrupt-cells", NULL);
                        if (tmp == NULL) {
                                DBG(" -> parent lacks #interrupt-cells !\n");
                                goto fail;
                        }
                        newintsize = *tmp;
-                       tmp = get_property(newpar, "#address-cells",
-                                                 NULL);
+                       tmp = of_get_property(newpar, "#address-cells", NULL);
                        newaddrsize = (tmp == NULL) ? 0 : *tmp;
 
                        DBG(" -> newintsize=%d, newaddrsize=%d\n",
@@ -928,7 +938,7 @@ static int of_irq_map_oldworld(struct device_node *device, int index,
         * everything together on these)
         */
        while (device) {
-               ints = get_property(device, "AAPL,interrupts", &intlen);
+               ints = of_get_property(device, "AAPL,interrupts", &intlen);
                if (ints != NULL)
                        break;
                device = device->parent;
@@ -961,7 +971,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
        struct device_node *p;
        const u32 *intspec, *tmp, *addr;
        u32 intsize, intlen;
-       int res;
+       int res = -EINVAL;
 
        DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
 
@@ -970,13 +980,13 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
                return of_irq_map_oldworld(device, index, out_irq);
 
        /* Get the interrupts property */
-       intspec = get_property(device, "interrupts", &intlen);
+       intspec = of_get_property(device, "interrupts", &intlen);
        if (intspec == NULL)
                return -EINVAL;
        intlen /= sizeof(u32);
 
        /* Get the reg property (if any) */
-       addr = get_property(device, "reg", NULL);
+       addr = of_get_property(device, "reg", NULL);
 
        /* Look for the interrupt parent. */
        p = of_irq_find_parent(device);
@@ -984,22 +994,21 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
                return -EINVAL;
 
        /* Get size of interrupt specifier */
-       tmp = get_property(p, "#interrupt-cells", NULL);
-       if (tmp == NULL) {
-               of_node_put(p);
-               return -EINVAL;
-       }
+       tmp = of_get_property(p, "#interrupt-cells", NULL);
+       if (tmp == NULL)
+               goto out;
        intsize = *tmp;
 
        DBG(" intsize=%d intlen=%d\n", intsize, intlen);
 
        /* Check index */
        if ((index + 1) * intsize > intlen)
-               return -EINVAL;
+               goto out;
 
        /* Get new specifier and map it */
        res = of_irq_map_raw(p, intspec + index * intsize, intsize,
                             addr, out_irq);
+out:
        of_node_put(p);
        return res;
 }
@@ -1043,3 +1052,28 @@ const void *of_get_mac_address(struct device_node *np)
 }
 EXPORT_SYMBOL(of_get_mac_address);
 
+int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
+{
+       int irq = irq_of_parse_and_map(dev, index);
+
+       /* Only dereference the resource if both the
+        * resource and the irq are valid. */
+       if (r && irq != NO_IRQ) {
+               r->start = r->end = irq;
+               r->flags = IORESOURCE_IRQ;
+       }
+
+       return irq;
+}
+EXPORT_SYMBOL_GPL(of_irq_to_resource);
+
+void __iomem *of_iomap(struct device_node *np, int index)
+{
+       struct resource res;
+
+       if (of_address_to_resource(np, index, &res))
+               return NULL;
+
+       return ioremap(res.start, 1 + res.end - res.start);
+}
+EXPORT_SYMBOL(of_iomap);