diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-10 11:57:03 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-10 11:57:03 -0500 |
| commit | 0bd2cbcdfaff9cb22267d66fc843fa4f73f0c281 (patch) | |
| tree | 7d9732bcf5f2f646cb0c2c529c48b454b15d4ae2 /drivers/of | |
| parent | 57cc7215b70856dc6bae8e55b00ecd7b1d7429b1 (diff) | |
| parent | a081748735c5feb96b1365e78a5ff0fb6ca7e3a4 (diff) | |
Merge branch 'next-devicetree' of git://git.secretlab.ca/git/linux-2.6
* 'next-devicetree' of git://git.secretlab.ca/git/linux-2.6: (29 commits)
of/flattree: forward declare struct device_node in of_fdt.h
ipmi: explicitly include of_address.h and of_irq.h
sparc: explicitly cast negative phandle checks to s32
powerpc/405: Fix missing #{address,size}-cells in i2c node
powerpc/5200: dts: refactor dts files
powerpc/5200: dts: Change combatible strings on localbus
powerpc/5200: dts: remove unused properties
powerpc/5200: dts: rename nodes to prepare for refactoring dts files
of/flattree: Update dtc to current mainline.
of/device: Don't register disabled devices
powerpc/dts: fix syntax bugs in bluestone.dts
of: Fixes for OF probing on little endian systems
of: make drivers depend on CONFIG_OF instead of CONFIG_PPC_OF
of/flattree: Add of_flat_dt_match() helper function
of_serial: explicitly include of_irq.h
of/flattree: Refactor unflatten_device_tree and add fdt_unflatten_tree
of/flattree: Reorder unflatten_dt_node
of/flattree: Refactor unflatten_dt_node
of/flattree: Add non-boottime device tree functions
of/flattree: Add Kconfig for EARLY_FLATTREE
...
Fix up trivial conflict in arch/sparc/prom/tree_32.c as per Grant.
Diffstat (limited to 'drivers/of')
| -rw-r--r-- | drivers/of/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/of/Makefile | 1 | ||||
| -rw-r--r-- | drivers/of/address.c | 54 | ||||
| -rw-r--r-- | drivers/of/fdt.c | 430 | ||||
| -rw-r--r-- | drivers/of/of_mdio.c | 26 | ||||
| -rw-r--r-- | drivers/of/of_net.c | 48 | ||||
| -rw-r--r-- | drivers/of/platform.c | 22 |
7 files changed, 388 insertions, 201 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index aa675ebd8eb..3c6e100a3ad 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
| @@ -19,6 +19,10 @@ config OF_FLATTREE | |||
| 19 | bool | 19 | bool |
| 20 | select DTC | 20 | select DTC |
| 21 | 21 | ||
| 22 | config OF_EARLY_FLATTREE | ||
| 23 | bool | ||
| 24 | select OF_FLATTREE | ||
| 25 | |||
| 22 | config OF_PROMTREE | 26 | config OF_PROMTREE |
| 23 | bool | 27 | bool |
| 24 | 28 | ||
| @@ -49,6 +53,10 @@ config OF_I2C | |||
| 49 | help | 53 | help |
| 50 | OpenFirmware I2C accessors | 54 | OpenFirmware I2C accessors |
| 51 | 55 | ||
| 56 | config OF_NET | ||
| 57 | depends on NETDEVICES | ||
| 58 | def_bool y | ||
| 59 | |||
| 52 | config OF_SPI | 60 | config OF_SPI |
| 53 | def_tristate SPI | 61 | def_tristate SPI |
| 54 | depends on SPI && !SPARC | 62 | depends on SPI && !SPARC |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 7888155bea0..3ab21a0a490 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
| @@ -6,5 +6,6 @@ obj-$(CONFIG_OF_IRQ) += irq.o | |||
| 6 | obj-$(CONFIG_OF_DEVICE) += device.o platform.o | 6 | obj-$(CONFIG_OF_DEVICE) += device.o platform.o |
| 7 | obj-$(CONFIG_OF_GPIO) += gpio.o | 7 | obj-$(CONFIG_OF_GPIO) += gpio.o |
| 8 | obj-$(CONFIG_OF_I2C) += of_i2c.o | 8 | obj-$(CONFIG_OF_I2C) += of_i2c.o |
| 9 | obj-$(CONFIG_OF_NET) += of_net.o | ||
| 9 | obj-$(CONFIG_OF_SPI) += of_spi.o | 10 | obj-$(CONFIG_OF_SPI) += of_spi.o |
| 10 | obj-$(CONFIG_OF_MDIO) += of_mdio.o | 11 | obj-$(CONFIG_OF_MDIO) += of_mdio.o |
diff --git a/drivers/of/address.c b/drivers/of/address.c index 3a1c7e70b19..b4559c58c09 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
| @@ -12,13 +12,13 @@ | |||
| 12 | (ns) > 0) | 12 | (ns) > 0) |
| 13 | 13 | ||
| 14 | static struct of_bus *of_match_bus(struct device_node *np); | 14 | static struct of_bus *of_match_bus(struct device_node *np); |
| 15 | static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, | 15 | static int __of_address_to_resource(struct device_node *dev, |
| 16 | u64 size, unsigned int flags, | 16 | const __be32 *addrp, u64 size, unsigned int flags, |
| 17 | struct resource *r); | 17 | struct resource *r); |
| 18 | 18 | ||
| 19 | /* Debug utility */ | 19 | /* Debug utility */ |
| 20 | #ifdef DEBUG | 20 | #ifdef DEBUG |
| 21 | static void of_dump_addr(const char *s, const u32 *addr, int na) | 21 | static void of_dump_addr(const char *s, const __be32 *addr, int na) |
| 22 | { | 22 | { |
| 23 | printk(KERN_DEBUG "%s", s); | 23 | printk(KERN_DEBUG "%s", s); |
| 24 | while (na--) | 24 | while (na--) |
| @@ -26,7 +26,7 @@ static void of_dump_addr(const char *s, const u32 *addr, int na) | |||
| 26 | printk("\n"); | 26 | printk("\n"); |
| 27 | } | 27 | } |
| 28 | #else | 28 | #else |
| 29 | static void of_dump_addr(const char *s, const u32 *addr, int na) { } | 29 | static void of_dump_addr(const char *s, const __be32 *addr, int na) { } |
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| 32 | /* Callbacks for bus specific translators */ | 32 | /* Callbacks for bus specific translators */ |
| @@ -36,10 +36,10 @@ struct of_bus { | |||
| 36 | int (*match)(struct device_node *parent); | 36 | int (*match)(struct device_node *parent); |
| 37 | void (*count_cells)(struct device_node *child, | 37 | void (*count_cells)(struct device_node *child, |
| 38 | int *addrc, int *sizec); | 38 | int *addrc, int *sizec); |
| 39 | u64 (*map)(u32 *addr, const u32 *range, | 39 | u64 (*map)(u32 *addr, const __be32 *range, |
| 40 | int na, int ns, int pna); | 40 | int na, int ns, int pna); |
| 41 | int (*translate)(u32 *addr, u64 offset, int na); | 41 | int (*translate)(u32 *addr, u64 offset, int na); |
| 42 | unsigned int (*get_flags)(const u32 *addr); | 42 | unsigned int (*get_flags)(const __be32 *addr); |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | /* | 45 | /* |
| @@ -55,7 +55,7 @@ static void of_bus_default_count_cells(struct device_node *dev, | |||
| 55 | *sizec = of_n_size_cells(dev); | 55 | *sizec = of_n_size_cells(dev); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static u64 of_bus_default_map(u32 *addr, const u32 *range, | 58 | static u64 of_bus_default_map(u32 *addr, const __be32 *range, |
| 59 | int na, int ns, int pna) | 59 | int na, int ns, int pna) |
| 60 | { | 60 | { |
| 61 | u64 cp, s, da; | 61 | u64 cp, s, da; |
| @@ -85,7 +85,7 @@ static int of_bus_default_translate(u32 *addr, u64 offset, int na) | |||
| 85 | return 0; | 85 | return 0; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static unsigned int of_bus_default_get_flags(const u32 *addr) | 88 | static unsigned int of_bus_default_get_flags(const __be32 *addr) |
| 89 | { | 89 | { |
| 90 | return IORESOURCE_MEM; | 90 | return IORESOURCE_MEM; |
| 91 | } | 91 | } |
| @@ -110,10 +110,10 @@ static void of_bus_pci_count_cells(struct device_node *np, | |||
| 110 | *sizec = 2; | 110 | *sizec = 2; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | static unsigned int of_bus_pci_get_flags(const u32 *addr) | 113 | static unsigned int of_bus_pci_get_flags(const __be32 *addr) |
| 114 | { | 114 | { |
| 115 | unsigned int flags = 0; | 115 | unsigned int flags = 0; |
| 116 | u32 w = addr[0]; | 116 | u32 w = be32_to_cpup(addr); |
| 117 | 117 | ||
| 118 | switch((w >> 24) & 0x03) { | 118 | switch((w >> 24) & 0x03) { |
| 119 | case 0x01: | 119 | case 0x01: |
| @@ -129,7 +129,8 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr) | |||
| 129 | return flags; | 129 | return flags; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna) | 132 | static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns, |
| 133 | int pna) | ||
| 133 | { | 134 | { |
| 134 | u64 cp, s, da; | 135 | u64 cp, s, da; |
| 135 | unsigned int af, rf; | 136 | unsigned int af, rf; |
| @@ -160,7 +161,7 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na) | |||
| 160 | return of_bus_default_translate(addr + 1, offset, na - 1); | 161 | return of_bus_default_translate(addr + 1, offset, na - 1); |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, | 164 | const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, |
| 164 | unsigned int *flags) | 165 | unsigned int *flags) |
| 165 | { | 166 | { |
| 166 | const __be32 *prop; | 167 | const __be32 *prop; |
| @@ -207,7 +208,7 @@ EXPORT_SYMBOL(of_get_pci_address); | |||
| 207 | int of_pci_address_to_resource(struct device_node *dev, int bar, | 208 | int of_pci_address_to_resource(struct device_node *dev, int bar, |
| 208 | struct resource *r) | 209 | struct resource *r) |
| 209 | { | 210 | { |
| 210 | const u32 *addrp; | 211 | const __be32 *addrp; |
| 211 | u64 size; | 212 | u64 size; |
| 212 | unsigned int flags; | 213 | unsigned int flags; |
| 213 | 214 | ||
| @@ -237,12 +238,13 @@ static void of_bus_isa_count_cells(struct device_node *child, | |||
| 237 | *sizec = 1; | 238 | *sizec = 1; |
| 238 | } | 239 | } |
| 239 | 240 | ||
| 240 | static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna) | 241 | static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, |
| 242 | int pna) | ||
| 241 | { | 243 | { |
| 242 | u64 cp, s, da; | 244 | u64 cp, s, da; |
| 243 | 245 | ||
| 244 | /* Check address type match */ | 246 | /* Check address type match */ |
| 245 | if ((addr[0] ^ range[0]) & 0x00000001) | 247 | if ((addr[0] ^ range[0]) & cpu_to_be32(1)) |
| 246 | return OF_BAD_ADDR; | 248 | return OF_BAD_ADDR; |
| 247 | 249 | ||
| 248 | /* Read address values, skipping high cell */ | 250 | /* Read address values, skipping high cell */ |
| @@ -264,10 +266,10 @@ static int of_bus_isa_translate(u32 *addr, u64 offset, int na) | |||
| 264 | return of_bus_default_translate(addr + 1, offset, na - 1); | 266 | return of_bus_default_translate(addr + 1, offset, na - 1); |
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | static unsigned int of_bus_isa_get_flags(const u32 *addr) | 269 | static unsigned int of_bus_isa_get_flags(const __be32 *addr) |
| 268 | { | 270 | { |
| 269 | unsigned int flags = 0; | 271 | unsigned int flags = 0; |
| 270 | u32 w = addr[0]; | 272 | u32 w = be32_to_cpup(addr); |
| 271 | 273 | ||
| 272 | if (w & 1) | 274 | if (w & 1) |
| 273 | flags |= IORESOURCE_IO; | 275 | flags |= IORESOURCE_IO; |
| @@ -330,7 +332,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, | |||
| 330 | struct of_bus *pbus, u32 *addr, | 332 | struct of_bus *pbus, u32 *addr, |
| 331 | int na, int ns, int pna, const char *rprop) | 333 | int na, int ns, int pna, const char *rprop) |
| 332 | { | 334 | { |
| 333 | const u32 *ranges; | 335 | const __be32 *ranges; |
| 334 | unsigned int rlen; | 336 | unsigned int rlen; |
| 335 | int rone; | 337 | int rone; |
| 336 | u64 offset = OF_BAD_ADDR; | 338 | u64 offset = OF_BAD_ADDR; |
| @@ -398,7 +400,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, | |||
| 398 | * that can be mapped to a cpu physical address). This is not really specified | 400 | * that can be mapped to a cpu physical address). This is not really specified |
| 399 | * that way, but this is traditionally the way IBM at least do things | 401 | * that way, but this is traditionally the way IBM at least do things |
| 400 | */ | 402 | */ |
| 401 | u64 __of_translate_address(struct device_node *dev, const u32 *in_addr, | 403 | u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, |
| 402 | const char *rprop) | 404 | const char *rprop) |
| 403 | { | 405 | { |
| 404 | struct device_node *parent = NULL; | 406 | struct device_node *parent = NULL; |
| @@ -475,22 +477,22 @@ u64 __of_translate_address(struct device_node *dev, const u32 *in_addr, | |||
| 475 | return result; | 477 | return result; |
| 476 | } | 478 | } |
| 477 | 479 | ||
| 478 | u64 of_translate_address(struct device_node *dev, const u32 *in_addr) | 480 | u64 of_translate_address(struct device_node *dev, const __be32 *in_addr) |
| 479 | { | 481 | { |
| 480 | return __of_translate_address(dev, in_addr, "ranges"); | 482 | return __of_translate_address(dev, in_addr, "ranges"); |
| 481 | } | 483 | } |
| 482 | EXPORT_SYMBOL(of_translate_address); | 484 | EXPORT_SYMBOL(of_translate_address); |
| 483 | 485 | ||
| 484 | u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr) | 486 | u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) |
| 485 | { | 487 | { |
| 486 | return __of_translate_address(dev, in_addr, "dma-ranges"); | 488 | return __of_translate_address(dev, in_addr, "dma-ranges"); |
| 487 | } | 489 | } |
| 488 | EXPORT_SYMBOL(of_translate_dma_address); | 490 | EXPORT_SYMBOL(of_translate_dma_address); |
| 489 | 491 | ||
| 490 | const u32 *of_get_address(struct device_node *dev, int index, u64 *size, | 492 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, |
| 491 | unsigned int *flags) | 493 | unsigned int *flags) |
| 492 | { | 494 | { |
| 493 | const u32 *prop; | 495 | const __be32 *prop; |
| 494 | unsigned int psize; | 496 | unsigned int psize; |
| 495 | struct device_node *parent; | 497 | struct device_node *parent; |
| 496 | struct of_bus *bus; | 498 | struct of_bus *bus; |
| @@ -525,8 +527,8 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size, | |||
| 525 | } | 527 | } |
| 526 | EXPORT_SYMBOL(of_get_address); | 528 | EXPORT_SYMBOL(of_get_address); |
| 527 | 529 | ||
| 528 | static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, | 530 | static int __of_address_to_resource(struct device_node *dev, |
| 529 | u64 size, unsigned int flags, | 531 | const __be32 *addrp, u64 size, unsigned int flags, |
| 530 | struct resource *r) | 532 | struct resource *r) |
| 531 | { | 533 | { |
| 532 | u64 taddr; | 534 | u64 taddr; |
| @@ -564,7 +566,7 @@ static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, | |||
| 564 | int of_address_to_resource(struct device_node *dev, int index, | 566 | int of_address_to_resource(struct device_node *dev, int index, |
| 565 | struct resource *r) | 567 | struct resource *r) |
| 566 | { | 568 | { |
| 567 | const u32 *addrp; | 569 | const __be32 *addrp; |
| 568 | u64 size; | 570 | u64 size; |
| 569 | unsigned int flags; | 571 | unsigned int flags; |
| 570 | 572 | ||
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index c1360e02f92..c787c3d95c6 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
| @@ -11,10 +11,12 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/initrd.h> | 13 | #include <linux/initrd.h> |
| 14 | #include <linux/module.h> | ||
| 14 | #include <linux/of.h> | 15 | #include <linux/of.h> |
| 15 | #include <linux/of_fdt.h> | 16 | #include <linux/of_fdt.h> |
| 16 | #include <linux/string.h> | 17 | #include <linux/string.h> |
| 17 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
| 19 | #include <linux/slab.h> | ||
| 18 | 20 | ||
| 19 | #ifdef CONFIG_PPC | 21 | #ifdef CONFIG_PPC |
| 20 | #include <asm/machdep.h> | 22 | #include <asm/machdep.h> |
| @@ -22,104 +24,19 @@ | |||
| 22 | 24 | ||
| 23 | #include <asm/page.h> | 25 | #include <asm/page.h> |
| 24 | 26 | ||
| 25 | int __initdata dt_root_addr_cells; | 27 | char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) |
| 26 | int __initdata dt_root_size_cells; | ||
| 27 | |||
| 28 | struct boot_param_header *initial_boot_params; | ||
| 29 | |||
| 30 | char *find_flat_dt_string(u32 offset) | ||
| 31 | { | 28 | { |
| 32 | return ((char *)initial_boot_params) + | 29 | return ((char *)blob) + |
| 33 | be32_to_cpu(initial_boot_params->off_dt_strings) + offset; | 30 | be32_to_cpu(blob->off_dt_strings) + offset; |
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | ||
| 38 | * @it: callback function | ||
| 39 | * @data: context data pointer | ||
| 40 | * | ||
| 41 | * This function is used to scan the flattened device-tree, it is | ||
| 42 | * used to extract the memory information at boot before we can | ||
| 43 | * unflatten the tree | ||
| 44 | */ | ||
| 45 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
| 46 | const char *uname, int depth, | ||
| 47 | void *data), | ||
| 48 | void *data) | ||
| 49 | { | ||
| 50 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
| 51 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
| 52 | int rc = 0; | ||
| 53 | int depth = -1; | ||
| 54 | |||
| 55 | do { | ||
| 56 | u32 tag = be32_to_cpup((__be32 *)p); | ||
| 57 | char *pathp; | ||
| 58 | |||
| 59 | p += 4; | ||
| 60 | if (tag == OF_DT_END_NODE) { | ||
| 61 | depth--; | ||
| 62 | continue; | ||
| 63 | } | ||
| 64 | if (tag == OF_DT_NOP) | ||
| 65 | continue; | ||
| 66 | if (tag == OF_DT_END) | ||
| 67 | break; | ||
| 68 | if (tag == OF_DT_PROP) { | ||
| 69 | u32 sz = be32_to_cpup((__be32 *)p); | ||
| 70 | p += 8; | ||
| 71 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
| 72 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
| 73 | p += sz; | ||
| 74 | p = ALIGN(p, 4); | ||
| 75 | continue; | ||
| 76 | } | ||
| 77 | if (tag != OF_DT_BEGIN_NODE) { | ||
| 78 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
| 79 | return -EINVAL; | ||
| 80 | } | ||
| 81 | depth++; | ||
| 82 | pathp = (char *)p; | ||
| 83 | p = ALIGN(p + strlen(pathp) + 1, 4); | ||
| 84 | if ((*pathp) == '/') { | ||
| 85 | char *lp, *np; | ||
| 86 | for (lp = NULL, np = pathp; *np; np++) | ||
| 87 | if ((*np) == '/') | ||
| 88 | lp = np+1; | ||
| 89 | if (lp != NULL) | ||
| 90 | pathp = lp; | ||
| 91 | } | ||
| 92 | rc = it(p, pathp, depth, data); | ||
| 93 | if (rc != 0) | ||
| 94 | break; | ||
| 95 | } while (1); | ||
| 96 | |||
| 97 | return rc; | ||
| 98 | } | 31 | } |
| 99 | 32 | ||
| 100 | /** | 33 | /** |
| 101 | * of_get_flat_dt_root - find the root node in the flat blob | 34 | * of_fdt_get_property - Given a node in the given flat blob, return |
| 35 | * the property ptr | ||
| 102 | */ | 36 | */ |
| 103 | unsigned long __init of_get_flat_dt_root(void) | 37 | void *of_fdt_get_property(struct boot_param_header *blob, |
| 104 | { | 38 | unsigned long node, const char *name, |
| 105 | unsigned long p = ((unsigned long)initial_boot_params) + | 39 | unsigned long *size) |
| 106 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
| 107 | |||
| 108 | while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) | ||
| 109 | p += 4; | ||
| 110 | BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); | ||
| 111 | p += 4; | ||
| 112 | return ALIGN(p + strlen((char *)p) + 1, 4); | ||
| 113 | } | ||
| 114 | |||
| 115 | /** | ||
| 116 | * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr | ||
| 117 | * | ||
| 118 | * This function can be used within scan_flattened_dt callback to get | ||
| 119 | * access to properties | ||
| 120 | */ | ||
| 121 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
| 122 | unsigned long *size) | ||
| 123 | { | 40 | { |
| 124 | unsigned long p = node; | 41 | unsigned long p = node; |
| 125 | 42 | ||
| @@ -137,10 +54,10 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | |||
| 137 | sz = be32_to_cpup((__be32 *)p); | 54 | sz = be32_to_cpup((__be32 *)p); |
| 138 | noff = be32_to_cpup((__be32 *)(p + 4)); | 55 | noff = be32_to_cpup((__be32 *)(p + 4)); |
| 139 | p += 8; | 56 | p += 8; |
| 140 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | 57 | if (be32_to_cpu(blob->version) < 0x10) |
| 141 | p = ALIGN(p, sz >= 8 ? 8 : 4); | 58 | p = ALIGN(p, sz >= 8 ? 8 : 4); |
| 142 | 59 | ||
| 143 | nstr = find_flat_dt_string(noff); | 60 | nstr = of_fdt_get_string(blob, noff); |
| 144 | if (nstr == NULL) { | 61 | if (nstr == NULL) { |
| 145 | pr_warning("Can't find property index name !\n"); | 62 | pr_warning("Can't find property index name !\n"); |
| 146 | return NULL; | 63 | return NULL; |
| @@ -156,21 +73,28 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | |||
| 156 | } | 73 | } |
| 157 | 74 | ||
| 158 | /** | 75 | /** |
| 159 | * of_flat_dt_is_compatible - Return true if given node has compat in compatible list | 76 | * of_fdt_is_compatible - Return true if given node from the given blob has |
| 77 | * compat in its compatible list | ||
| 78 | * @blob: A device tree blob | ||
| 160 | * @node: node to test | 79 | * @node: node to test |
| 161 | * @compat: compatible string to compare with compatible list. | 80 | * @compat: compatible string to compare with compatible list. |
| 81 | * | ||
| 82 | * On match, returns a non-zero value with smaller values returned for more | ||
| 83 | * specific compatible values. | ||
| 162 | */ | 84 | */ |
| 163 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | 85 | int of_fdt_is_compatible(struct boot_param_header *blob, |
| 86 | unsigned long node, const char *compat) | ||
| 164 | { | 87 | { |
| 165 | const char *cp; | 88 | const char *cp; |
| 166 | unsigned long cplen, l; | 89 | unsigned long cplen, l, score = 0; |
| 167 | 90 | ||
| 168 | cp = of_get_flat_dt_prop(node, "compatible", &cplen); | 91 | cp = of_fdt_get_property(blob, node, "compatible", &cplen); |
| 169 | if (cp == NULL) | 92 | if (cp == NULL) |
| 170 | return 0; | 93 | return 0; |
| 171 | while (cplen > 0) { | 94 | while (cplen > 0) { |
| 95 | score++; | ||
| 172 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) | 96 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) |
| 173 | return 1; | 97 | return score; |
| 174 | l = strlen(cp) + 1; | 98 | l = strlen(cp) + 1; |
| 175 | cp += l; | 99 | cp += l; |
| 176 | cplen -= l; | 100 | cplen -= l; |
| @@ -179,7 +103,28 @@ int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | |||
| 179 | return 0; | 103 | return 0; |
| 180 | } | 104 | } |
| 181 | 105 | ||
| 182 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | 106 | /** |
| 107 | * of_fdt_match - Return true if node matches a list of compatible values | ||
| 108 | */ | ||
| 109 | int of_fdt_match(struct boot_param_header *blob, unsigned long node, | ||
| 110 | const char **compat) | ||
| 111 | { | ||
| 112 | unsigned int tmp, score = 0; | ||
| 113 | |||
| 114 | if (!compat) | ||
| 115 | return 0; | ||
| 116 | |||
| 117 | while (*compat) { | ||
| 118 | tmp = of_fdt_is_compatible(blob, node, *compat); | ||
| 119 | if (tmp && (score == 0 || (tmp < score))) | ||
| 120 | score = tmp; | ||
| 121 | compat++; | ||
| 122 | } | ||
| 123 | |||
| 124 | return score; | ||
| 125 | } | ||
| 126 | |||
| 127 | static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size, | ||
| 183 | unsigned long align) | 128 | unsigned long align) |
| 184 | { | 129 | { |
| 185 | void *res; | 130 | void *res; |
| @@ -193,16 +138,18 @@ static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | |||
| 193 | 138 | ||
| 194 | /** | 139 | /** |
| 195 | * unflatten_dt_node - Alloc and populate a device_node from the flat tree | 140 | * unflatten_dt_node - Alloc and populate a device_node from the flat tree |
| 141 | * @blob: The parent device tree blob | ||
| 196 | * @p: pointer to node in flat tree | 142 | * @p: pointer to node in flat tree |
| 197 | * @dad: Parent struct device_node | 143 | * @dad: Parent struct device_node |
| 198 | * @allnextpp: pointer to ->allnext from last allocated device_node | 144 | * @allnextpp: pointer to ->allnext from last allocated device_node |
| 199 | * @fpsize: Size of the node path up at the current depth. | 145 | * @fpsize: Size of the node path up at the current depth. |
| 200 | */ | 146 | */ |
| 201 | unsigned long __init unflatten_dt_node(unsigned long mem, | 147 | unsigned long unflatten_dt_node(struct boot_param_header *blob, |
| 202 | unsigned long *p, | 148 | unsigned long mem, |
| 203 | struct device_node *dad, | 149 | unsigned long *p, |
| 204 | struct device_node ***allnextpp, | 150 | struct device_node *dad, |
| 205 | unsigned long fpsize) | 151 | struct device_node ***allnextpp, |
| 152 | unsigned long fpsize) | ||
| 206 | { | 153 | { |
| 207 | struct device_node *np; | 154 | struct device_node *np; |
| 208 | struct property *pp, **prev_pp = NULL; | 155 | struct property *pp, **prev_pp = NULL; |
| @@ -298,10 +245,10 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
| 298 | sz = be32_to_cpup((__be32 *)(*p)); | 245 | sz = be32_to_cpup((__be32 *)(*p)); |
| 299 | noff = be32_to_cpup((__be32 *)((*p) + 4)); | 246 | noff = be32_to_cpup((__be32 *)((*p) + 4)); |
| 300 | *p += 8; | 247 | *p += 8; |
| 301 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | 248 | if (be32_to_cpu(blob->version) < 0x10) |
| 302 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); | 249 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); |
| 303 | 250 | ||
| 304 | pname = find_flat_dt_string(noff); | 251 | pname = of_fdt_get_string(blob, noff); |
| 305 | if (pname == NULL) { | 252 | if (pname == NULL) { |
| 306 | pr_info("Can't find property name in list !\n"); | 253 | pr_info("Can't find property name in list !\n"); |
| 307 | break; | 254 | break; |
| @@ -380,7 +327,8 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
| 380 | if (tag == OF_DT_NOP) | 327 | if (tag == OF_DT_NOP) |
| 381 | *p += 4; | 328 | *p += 4; |
| 382 | else | 329 | else |
| 383 | mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); | 330 | mem = unflatten_dt_node(blob, mem, p, np, allnextpp, |
| 331 | fpsize); | ||
| 384 | tag = be32_to_cpup((__be32 *)(*p)); | 332 | tag = be32_to_cpup((__be32 *)(*p)); |
| 385 | } | 333 | } |
| 386 | if (tag != OF_DT_END_NODE) { | 334 | if (tag != OF_DT_END_NODE) { |
| @@ -391,6 +339,211 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
| 391 | return mem; | 339 | return mem; |
| 392 | } | 340 | } |
| 393 | 341 | ||
| 342 | /** | ||
| 343 | * __unflatten_device_tree - create tree of device_nodes from flat blob | ||
| 344 | * | ||
| 345 | * unflattens a device-tree, creating the | ||
| 346 | * tree of struct device_node. It also fills the "name" and "type" | ||
| 347 | * pointers of the nodes so the normal device-tree walking functions | ||
| 348 | * can be used. | ||
| 349 | * @blob: The blob to expand | ||
| 350 | * @mynodes: The device_node tree created by the call | ||
| 351 | * @dt_alloc: An allocator that provides a virtual address to memory | ||
| 352 | * for the resulting tree | ||
| 353 | */ | ||
| 354 | void __unflatten_device_tree(struct boot_param_header *blob, | ||
| 355 | struct device_node **mynodes, | ||
| 356 | void * (*dt_alloc)(u64 size, u64 align)) | ||
| 357 | { | ||
| 358 | unsigned long start, mem, size; | ||
| 359 | struct device_node **allnextp = mynodes; | ||
| 360 | |||
| 361 | pr_debug(" -> unflatten_device_tree()\n"); | ||
| 362 | |||
| 363 | if (!blob) { | ||
| 364 | pr_debug("No device tree pointer\n"); | ||
| 365 | return; | ||
| 366 | } | ||
| 367 | |||
| 368 | pr_debug("Unflattening device tree:\n"); | ||
| 369 | pr_debug("magic: %08x\n", be32_to_cpu(blob->magic)); | ||
| 370 | pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize)); | ||
| 371 | pr_debug("version: %08x\n", be32_to_cpu(blob->version)); | ||
| 372 | |||
| 373 | if (be32_to_cpu(blob->magic) != OF_DT_HEADER) { | ||
| 374 | pr_err("Invalid device tree blob header\n"); | ||
| 375 | return; | ||
| 376 | } | ||
| 377 | |||
| 378 | /* First pass, scan for size */ | ||
| 379 | start = ((unsigned long)blob) + | ||
| 380 | be32_to_cpu(blob->off_dt_struct); | ||
| 381 | size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); | ||
| 382 | size = (size | 3) + 1; | ||
| 383 | |||
| 384 | pr_debug(" size is %lx, allocating...\n", size); | ||
| 385 | |||
| 386 | /* Allocate memory for the expanded device tree */ | ||
| 387 | mem = (unsigned long) | ||
| 388 | dt_alloc(size + 4, __alignof__(struct device_node)); | ||
| 389 | |||
| 390 | ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); | ||
| 391 | |||
| 392 | pr_debug(" unflattening %lx...\n", mem); | ||
| 393 | |||
| 394 | /* Second pass, do actual unflattening */ | ||
| 395 | start = ((unsigned long)blob) + | ||
| 396 | be32_to_cpu(blob->off_dt_struct); | ||
| 397 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); | ||
| 398 | if (be32_to_cpup((__be32 *)start) != OF_DT_END) | ||
| 399 | pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
| 400 | if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) | ||
| 401 | pr_warning("End of tree marker overwritten: %08x\n", | ||
| 402 | be32_to_cpu(((__be32 *)mem)[size / 4])); | ||
| 403 | *allnextp = NULL; | ||
| 404 | |||
| 405 | pr_debug(" <- unflatten_device_tree()\n"); | ||
| 406 | } | ||
| 407 | |||
| 408 | static void *kernel_tree_alloc(u64 size, u64 align) | ||
| 409 | { | ||
| 410 | return kzalloc(size, GFP_KERNEL); | ||
| 411 | } | ||
| 412 | |||
| 413 | /** | ||
| 414 | * of_fdt_unflatten_tree - create tree of device_nodes from flat blob | ||
| 415 | * | ||
| 416 | * unflattens the device-tree passed by the firmware, creating the | ||
| 417 | * tree of struct device_node. It also fills the "name" and "type" | ||
| 418 | * pointers of the nodes so the normal device-tree walking functions | ||
| 419 | * can be used. | ||
| 420 | */ | ||
| 421 | void of_fdt_unflatten_tree(unsigned long *blob, | ||
| 422 | struct device_node **mynodes) | ||
| 423 | { | ||
| 424 | struct boot_param_header *device_tree = | ||
| 425 | (struct boot_param_header *)blob; | ||
| 426 | __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc); | ||
| 427 | } | ||
| 428 | EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); | ||
| 429 | |||
| 430 | /* Everything below here references initial_boot_params directly. */ | ||
| 431 | int __initdata dt_root_addr_cells; | ||
| 432 | int __initdata dt_root_size_cells; | ||
| 433 | |||
| 434 | struct boot_param_header *initial_boot_params; | ||
| 435 | |||
| 436 | #ifdef CONFIG_OF_EARLY_FLATTREE | ||
| 437 | |||
| 438 | /** | ||
| 439 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | ||
| 440 | * @it: callback function | ||
| 441 | * @data: context data pointer | ||
| 442 | * | ||
| 443 | * This function is used to scan the flattened device-tree, it is | ||
| 444 | * used to extract the memory information at boot before we can | ||
| 445 | * unflatten the tree | ||
| 446 | */ | ||
| 447 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
| 448 | const char *uname, int depth, | ||
| 449 | void *data), | ||
| 450 | void *data) | ||
| 451 | { | ||
| 452 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
| 453 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
| 454 | int rc = 0; | ||
| 455 | int depth = -1; | ||
| 456 | |||
| 457 | do { | ||
| 458 | u32 tag = be32_to_cpup((__be32 *)p); | ||
| 459 | char *pathp; | ||
| 460 | |||
| 461 | p += 4; | ||
| 462 | if (tag == OF_DT_END_NODE) { | ||
| 463 | depth--; | ||
| 464 | continue; | ||
| 465 | } | ||
| 466 | if (tag == OF_DT_NOP) | ||
| 467 | continue; | ||
| 468 | if (tag == OF_DT_END) | ||
| 469 | break; | ||
| 470 | if (tag == OF_DT_PROP) { | ||
| 471 | u32 sz = be32_to_cpup((__be32 *)p); | ||
| 472 | p += 8; | ||
| 473 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
| 474 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
| 475 | p += sz; | ||
| 476 | p = ALIGN(p, 4); | ||
| 477 | continue; | ||
| 478 | } | ||
| 479 | if (tag != OF_DT_BEGIN_NODE) { | ||
| 480 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
| 481 | return -EINVAL; | ||
| 482 | } | ||
| 483 | depth++; | ||
| 484 | pathp = (char *)p; | ||
| 485 | p = ALIGN(p + strlen(pathp) + 1, 4); | ||
| 486 | if ((*pathp) == '/') { | ||
| 487 | char *lp, *np; | ||
| 488 | for (lp = NULL, np = pathp; *np; np++) | ||
| 489 | if ((*np) == '/') | ||
| 490 | lp = np+1; | ||
| 491 | if (lp != NULL) | ||
| 492 | pathp = lp; | ||
| 493 | } | ||
| 494 | rc = it(p, pathp, depth, data); | ||
| 495 | if (rc != 0) | ||
| 496 | break; | ||
| 497 | } while (1); | ||
| 498 | |||
| 499 | return rc; | ||
| 500 | } | ||
| 501 | |||
| 502 | /** | ||
| 503 | * of_get_flat_dt_root - find the root node in the flat blob | ||
| 504 | */ | ||
| 505 | unsigned long __init of_get_flat_dt_root(void) | ||
| 506 | { | ||
| 507 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
| 508 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
| 509 | |||
| 510 | while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) | ||
| 511 | p += 4; | ||
| 512 | BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); | ||
| 513 | p += 4; | ||
| 514 | return ALIGN(p + strlen((char *)p) + 1, 4); | ||
| 515 | } | ||
| 516 | |||
| 517 | /** | ||
| 518 | * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr | ||
| 519 | * | ||
| 520 | * This function can be used within scan_flattened_dt callback to get | ||
| 521 | * access to properties | ||
| 522 | */ | ||
| 523 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
| 524 | unsigned long *size) | ||
| 525 | { | ||
| 526 | return of_fdt_get_property(initial_boot_params, node, name, size); | ||
| 527 | } | ||
| 528 | |||
| 529 | /** | ||
| 530 | * of_flat_dt_is_compatible - Return true if given node has compat in compatible list | ||
| 531 | * @node: node to test | ||
| 532 | * @compat: compatible string to compare with compatible list. | ||
| 533 | */ | ||
| 534 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | ||
| 535 | { | ||
| 536 | return of_fdt_is_compatible(initial_boot_params, node, compat); | ||
| 537 | } | ||
| 538 | |||
| 539 | /** | ||
| 540 | * of_flat_dt_match - Return true if node matches a list of compatible values | ||
| 541 | */ | ||
| 542 | int __init of_flat_dt_match(unsigned long node, const char **compat) | ||
| 543 | { | ||
| 544 | return of_fdt_match(initial_boot_params, node, compat); | ||
| 545 | } | ||
| 546 | |||
| 394 | #ifdef CONFIG_BLK_DEV_INITRD | 547 | #ifdef CONFIG_BLK_DEV_INITRD |
| 395 | /** | 548 | /** |
| 396 | * early_init_dt_check_for_initrd - Decode initrd location from flat tree | 549 | * early_init_dt_check_for_initrd - Decode initrd location from flat tree |
| @@ -539,6 +692,12 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
| 539 | return 1; | 692 | return 1; |
| 540 | } | 693 | } |
| 541 | 694 | ||
| 695 | static void *__init early_device_tree_alloc(u64 size, u64 align) | ||
| 696 | { | ||
| 697 | unsigned long mem = early_init_dt_alloc_memory_arch(size, align); | ||
| 698 | return __va(mem); | ||
| 699 | } | ||
| 700 | |||
| 542 | /** | 701 | /** |
| 543 | * unflatten_device_tree - create tree of device_nodes from flat blob | 702 | * unflatten_device_tree - create tree of device_nodes from flat blob |
| 544 | * | 703 | * |
| @@ -549,58 +708,13 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
| 549 | */ | 708 | */ |
| 550 | void __init unflatten_device_tree(void) | 709 | void __init unflatten_device_tree(void) |
| 551 | { | 710 | { |
| 552 | unsigned long start, mem, size; | 711 | __unflatten_device_tree(initial_boot_params, &allnodes, |
| 553 | struct device_node **allnextp = &allnodes; | 712 | early_device_tree_alloc); |
| 554 | |||
| 555 | pr_debug(" -> unflatten_device_tree()\n"); | ||
| 556 | |||
| 557 | if (!initial_boot_params) { | ||
| 558 | pr_debug("No device tree pointer\n"); | ||
| 559 | return; | ||
| 560 | } | ||
| 561 | |||
| 562 | pr_debug("Unflattening device tree:\n"); | ||
| 563 | pr_debug("magic: %08x\n", be32_to_cpu(initial_boot_params->magic)); | ||
| 564 | pr_debug("size: %08x\n", be32_to_cpu(initial_boot_params->totalsize)); | ||
| 565 | pr_debug("version: %08x\n", be32_to_cpu(initial_boot_params->version)); | ||
| 566 | |||
| 567 | if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { | ||
| 568 | pr_err("Invalid device tree blob header\n"); | ||
| 569 | return; | ||
| 570 | } | ||
| 571 | |||
| 572 | /* First pass, scan for size */ | ||
| 573 | start = ((unsigned long)initial_boot_params) + | ||
| 574 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
| 575 | size = unflatten_dt_node(0, &start, NULL, NULL, 0); | ||
| 576 | size = (size | 3) + 1; | ||
| 577 | |||
| 578 | pr_debug(" size is %lx, allocating...\n", size); | ||
| 579 | |||
| 580 | /* Allocate memory for the expanded device tree */ | ||
| 581 | mem = early_init_dt_alloc_memory_arch(size + 4, | ||
| 582 | __alignof__(struct device_node)); | ||
| 583 | mem = (unsigned long) __va(mem); | ||
| 584 | |||
| 585 | ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); | ||
| 586 | |||
| 587 | pr_debug(" unflattening %lx...\n", mem); | ||
| 588 | |||
| 589 | /* Second pass, do actual unflattening */ | ||
| 590 | start = ((unsigned long)initial_boot_params) + | ||
| 591 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
| 592 | unflatten_dt_node(mem, &start, NULL, &allnextp, 0); | ||
| 593 | if (be32_to_cpup((__be32 *)start) != OF_DT_END) | ||
| 594 | pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
| 595 | if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) | ||
| 596 | pr_warning("End of tree marker overwritten: %08x\n", | ||
| 597 | be32_to_cpu(((__be32 *)mem)[size / 4])); | ||
| 598 | *allnextp = NULL; | ||
| 599 | 713 | ||
| 600 | /* Get pointer to OF "/chosen" node for use everywhere */ | 714 | /* Get pointer to OF "/chosen" node for use everywhere */ |
| 601 | of_chosen = of_find_node_by_path("/chosen"); | 715 | of_chosen = of_find_node_by_path("/chosen"); |
| 602 | if (of_chosen == NULL) | 716 | if (of_chosen == NULL) |
| 603 | of_chosen = of_find_node_by_path("/chosen@0"); | 717 | of_chosen = of_find_node_by_path("/chosen@0"); |
| 604 | |||
| 605 | pr_debug(" <- unflatten_device_tree()\n"); | ||
| 606 | } | 718 | } |
| 719 | |||
| 720 | #endif /* CONFIG_OF_EARLY_FLATTREE */ | ||
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 1fce00eb421..dcd7857784f 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c | |||
| @@ -52,27 +52,35 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) | |||
| 52 | 52 | ||
| 53 | /* Loop over the child nodes and register a phy_device for each one */ | 53 | /* Loop over the child nodes and register a phy_device for each one */ |
| 54 | for_each_child_of_node(np, child) { | 54 | for_each_child_of_node(np, child) { |
| 55 | const __be32 *addr; | 55 | const __be32 *paddr; |
| 56 | u32 addr; | ||
| 56 | int len; | 57 | int len; |
| 57 | 58 | ||
| 58 | /* A PHY must have a reg property in the range [0-31] */ | 59 | /* A PHY must have a reg property in the range [0-31] */ |
| 59 | addr = of_get_property(child, "reg", &len); | 60 | paddr = of_get_property(child, "reg", &len); |
| 60 | if (!addr || len < sizeof(*addr) || *addr >= 32 || *addr < 0) { | 61 | if (!paddr || len < sizeof(*paddr)) { |
| 61 | dev_err(&mdio->dev, "%s has invalid PHY address\n", | 62 | dev_err(&mdio->dev, "%s has invalid PHY address\n", |
| 62 | child->full_name); | 63 | child->full_name); |
| 63 | continue; | 64 | continue; |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 67 | addr = be32_to_cpup(paddr); | ||
| 68 | if (addr >= 32) { | ||
| 69 | dev_err(&mdio->dev, "%s PHY address %i is too large\n", | ||
| 70 | child->full_name, addr); | ||
| 71 | continue; | ||
| 72 | } | ||
| 73 | |||
| 66 | if (mdio->irq) { | 74 | if (mdio->irq) { |
| 67 | mdio->irq[*addr] = irq_of_parse_and_map(child, 0); | 75 | mdio->irq[addr] = irq_of_parse_and_map(child, 0); |
| 68 | if (!mdio->irq[*addr]) | 76 | if (!mdio->irq[addr]) |
| 69 | mdio->irq[*addr] = PHY_POLL; | 77 | mdio->irq[addr] = PHY_POLL; |
| 70 | } | 78 | } |
| 71 | 79 | ||
| 72 | phy = get_phy_device(mdio, be32_to_cpup(addr)); | 80 | phy = get_phy_device(mdio, addr); |
| 73 | if (!phy || IS_ERR(phy)) { | 81 | if (!phy || IS_ERR(phy)) { |
| 74 | dev_err(&mdio->dev, "error probing PHY at address %i\n", | 82 | dev_err(&mdio->dev, "error probing PHY at address %i\n", |
| 75 | *addr); | 83 | addr); |
| 76 | continue; | 84 | continue; |
| 77 | } | 85 | } |
| 78 | phy_scan_fixups(phy); | 86 | phy_scan_fixups(phy); |
| @@ -91,7 +99,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) | |||
| 91 | } | 99 | } |
| 92 | 100 | ||
| 93 | dev_dbg(&mdio->dev, "registered phy %s at address %i\n", | 101 | dev_dbg(&mdio->dev, "registered phy %s at address %i\n", |
| 94 | child->name, *addr); | 102 | child->name, addr); |
| 95 | } | 103 | } |
| 96 | 104 | ||
| 97 | return 0; | 105 | return 0; |
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c new file mode 100644 index 00000000000..86f334a2769 --- /dev/null +++ b/drivers/of/of_net.c | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * OF helpers for network devices. | ||
| 3 | * | ||
| 4 | * This file is released under the GPLv2 | ||
| 5 | * | ||
| 6 | * Initially copied out of arch/powerpc/kernel/prom_parse.c | ||
| 7 | */ | ||
| 8 | #include <linux/etherdevice.h> | ||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/of_net.h> | ||
| 11 | |||
| 12 | /** | ||
| 13 | * Search the device tree for the best MAC address to use. 'mac-address' is | ||
| 14 | * checked first, because that is supposed to contain to "most recent" MAC | ||
| 15 | * address. If that isn't set, then 'local-mac-address' is checked next, | ||
| 16 | * because that is the default address. If that isn't set, then the obsolete | ||
| 17 | * 'address' is checked, just in case we're using an old device tree. | ||
| 18 | * | ||
| 19 | * Note that the 'address' property is supposed to contain a virtual address of | ||
| 20 | * the register set, but some DTS files have redefined that property to be the | ||
| 21 | * MAC address. | ||
| 22 | * | ||
| 23 | * All-zero MAC addresses are rejected, because those could be properties that | ||
| 24 | * exist in the device tree, but were not set by U-Boot. For example, the | ||
| 25 | * DTS could define 'mac-address' and 'local-mac-address', with zero MAC | ||
| 26 | * addresses. Some older U-Boots only initialized 'local-mac-address'. In | ||
| 27 | * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists | ||
| 28 | * but is all zeros. | ||
| 29 | */ | ||
| 30 | const void *of_get_mac_address(struct device_node *np) | ||
| 31 | { | ||
| 32 | struct property *pp; | ||
| 33 | |||
| 34 | pp = of_find_property(np, "mac-address", NULL); | ||
| 35 | if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) | ||
| 36 | return pp->value; | ||
| 37 | |||
| 38 | pp = of_find_property(np, "local-mac-address", NULL); | ||
| 39 | if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) | ||
| 40 | return pp->value; | ||
| 41 | |||
| 42 | pp = of_find_property(np, "address", NULL); | ||
| 43 | if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) | ||
| 44 | return pp->value; | ||
| 45 | |||
| 46 | return NULL; | ||
| 47 | } | ||
| 48 | EXPORT_SYMBOL(of_get_mac_address); | ||
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 5b4a07f1220..c01cd1ac761 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
| @@ -633,6 +633,9 @@ EXPORT_SYMBOL(of_device_alloc); | |||
| 633 | * @np: pointer to node to create device for | 633 | * @np: pointer to node to create device for |
| 634 | * @bus_id: name to assign device | 634 | * @bus_id: name to assign device |
| 635 | * @parent: Linux device model parent device. | 635 | * @parent: Linux device model parent device. |
| 636 | * | ||
| 637 | * Returns pointer to created platform device, or NULL if a device was not | ||
| 638 | * registered. Unavailable devices will not get registered. | ||
| 636 | */ | 639 | */ |
| 637 | struct platform_device *of_platform_device_create(struct device_node *np, | 640 | struct platform_device *of_platform_device_create(struct device_node *np, |
| 638 | const char *bus_id, | 641 | const char *bus_id, |
| @@ -640,6 +643,9 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
| 640 | { | 643 | { |
| 641 | struct platform_device *dev; | 644 | struct platform_device *dev; |
| 642 | 645 | ||
| 646 | if (!of_device_is_available(np)) | ||
| 647 | return NULL; | ||
| 648 | |||
| 643 | dev = of_device_alloc(np, bus_id, parent); | 649 | dev = of_device_alloc(np, bus_id, parent); |
| 644 | if (!dev) | 650 | if (!dev) |
| 645 | return NULL; | 651 | return NULL; |
| @@ -683,8 +689,9 @@ static int of_platform_bus_create(const struct device_node *bus, | |||
| 683 | pr_debug(" create child: %s\n", child->full_name); | 689 | pr_debug(" create child: %s\n", child->full_name); |
| 684 | dev = of_platform_device_create(child, NULL, parent); | 690 | dev = of_platform_device_create(child, NULL, parent); |
| 685 | if (dev == NULL) | 691 | if (dev == NULL) |
| 686 | rc = -ENOMEM; | 692 | continue; |
| 687 | else if (!of_match_node(matches, child)) | 693 | |
| 694 | if (!of_match_node(matches, child)) | ||
| 688 | continue; | 695 | continue; |
| 689 | if (rc == 0) { | 696 | if (rc == 0) { |
| 690 | pr_debug(" and sub busses\n"); | 697 | pr_debug(" and sub busses\n"); |
| @@ -733,10 +740,9 @@ int of_platform_bus_probe(struct device_node *root, | |||
| 733 | if (of_match_node(matches, root)) { | 740 | if (of_match_node(matches, root)) { |
| 734 | pr_debug(" root match, create all sub devices\n"); | 741 | pr_debug(" root match, create all sub devices\n"); |
| 735 | dev = of_platform_device_create(root, NULL, parent); | 742 | dev = of_platform_device_create(root, NULL, parent); |
| 736 | if (dev == NULL) { | 743 | if (dev == NULL) |
| 737 | rc = -ENOMEM; | ||
| 738 | goto bail; | 744 | goto bail; |
| 739 | } | 745 | |
| 740 | pr_debug(" create all sub busses\n"); | 746 | pr_debug(" create all sub busses\n"); |
| 741 | rc = of_platform_bus_create(root, matches, &dev->dev); | 747 | rc = of_platform_bus_create(root, matches, &dev->dev); |
| 742 | goto bail; | 748 | goto bail; |
| @@ -748,9 +754,9 @@ int of_platform_bus_probe(struct device_node *root, | |||
| 748 | pr_debug(" match: %s\n", child->full_name); | 754 | pr_debug(" match: %s\n", child->full_name); |
| 749 | dev = of_platform_device_create(child, NULL, parent); | 755 | dev = of_platform_device_create(child, NULL, parent); |
| 750 | if (dev == NULL) | 756 | if (dev == NULL) |
| 751 | rc = -ENOMEM; | 757 | continue; |
| 752 | else | 758 | |
| 753 | rc = of_platform_bus_create(child, matches, &dev->dev); | 759 | rc = of_platform_bus_create(child, matches, &dev->dev); |
| 754 | if (rc) { | 760 | if (rc) { |
| 755 | of_node_put(child); | 761 | of_node_put(child); |
| 756 | break; | 762 | break; |
