diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/of | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/Kconfig | 19 | ||||
-rw-r--r-- | drivers/of/Makefile | 3 | ||||
-rw-r--r-- | drivers/of/address.c | 56 | ||||
-rw-r--r-- | drivers/of/base.c | 7 | ||||
-rw-r--r-- | drivers/of/device.c | 61 | ||||
-rw-r--r-- | drivers/of/fdt.c | 438 | ||||
-rw-r--r-- | drivers/of/irq.c | 41 | ||||
-rw-r--r-- | drivers/of/of_i2c.c | 3 | ||||
-rw-r--r-- | drivers/of/of_mdio.c | 28 | ||||
-rw-r--r-- | drivers/of/of_net.c | 48 | ||||
-rw-r--r-- | drivers/of/of_pci.c | 92 | ||||
-rw-r--r-- | drivers/of/pdt.c | 248 | ||||
-rw-r--r-- | drivers/of/platform.c | 573 |
13 files changed, 828 insertions, 789 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 6acbff389ab6..d06a6374ed6c 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -4,7 +4,7 @@ config DTC | |||
4 | config OF | 4 | config OF |
5 | bool | 5 | bool |
6 | 6 | ||
7 | menu "Flattened Device Tree and Open Firmware support" | 7 | menu "Device Tree and Open Firmware support" |
8 | depends on OF | 8 | depends on OF |
9 | 9 | ||
10 | config PROC_DEVICETREE | 10 | config PROC_DEVICETREE |
@@ -19,6 +19,13 @@ 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 | |||
26 | config OF_PROMTREE | ||
27 | bool | ||
28 | |||
22 | config OF_DYNAMIC | 29 | config OF_DYNAMIC |
23 | def_bool y | 30 | def_bool y |
24 | depends on PPC_OF | 31 | depends on PPC_OF |
@@ -46,6 +53,10 @@ config OF_I2C | |||
46 | help | 53 | help |
47 | OpenFirmware I2C accessors | 54 | OpenFirmware I2C accessors |
48 | 55 | ||
56 | config OF_NET | ||
57 | depends on NETDEVICES | ||
58 | def_bool y | ||
59 | |||
49 | config OF_SPI | 60 | config OF_SPI |
50 | def_tristate SPI | 61 | def_tristate SPI |
51 | depends on SPI && !SPARC | 62 | depends on SPI && !SPARC |
@@ -58,4 +69,10 @@ config OF_MDIO | |||
58 | help | 69 | help |
59 | OpenFirmware MDIO bus (Ethernet PHY) accessors | 70 | OpenFirmware MDIO bus (Ethernet PHY) accessors |
60 | 71 | ||
72 | config OF_PCI | ||
73 | def_tristate PCI | ||
74 | depends on PCI && (PPC || MICROBLAZE || X86) | ||
75 | help | ||
76 | OpenFirmware PCI bus accessors | ||
77 | |||
61 | endmenu # OF | 78 | endmenu # OF |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 0052c405463a..f7861ed2f287 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -1,9 +1,12 @@ | |||
1 | obj-y = base.o | 1 | obj-y = base.o |
2 | obj-$(CONFIG_OF_FLATTREE) += fdt.o | 2 | obj-$(CONFIG_OF_FLATTREE) += fdt.o |
3 | obj-$(CONFIG_OF_PROMTREE) += pdt.o | ||
3 | obj-$(CONFIG_OF_ADDRESS) += address.o | 4 | obj-$(CONFIG_OF_ADDRESS) += address.o |
4 | obj-$(CONFIG_OF_IRQ) += irq.o | 5 | obj-$(CONFIG_OF_IRQ) += irq.o |
5 | obj-$(CONFIG_OF_DEVICE) += device.o platform.o | 6 | obj-$(CONFIG_OF_DEVICE) += device.o platform.o |
6 | obj-$(CONFIG_OF_GPIO) += gpio.o | 7 | obj-$(CONFIG_OF_GPIO) += gpio.o |
7 | obj-$(CONFIG_OF_I2C) += of_i2c.o | 8 | obj-$(CONFIG_OF_I2C) += of_i2c.o |
9 | obj-$(CONFIG_OF_NET) += of_net.o | ||
8 | obj-$(CONFIG_OF_SPI) += of_spi.o | 10 | obj-$(CONFIG_OF_SPI) += of_spi.o |
9 | obj-$(CONFIG_OF_MDIO) += of_mdio.o | 11 | obj-$(CONFIG_OF_MDIO) += of_mdio.o |
12 | obj-$(CONFIG_OF_PCI) += of_pci.o | ||
diff --git a/drivers/of/address.c b/drivers/of/address.c index fcadb726d4f9..b4559c58c095 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,10 +161,10 @@ 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 u32 *prop; | 167 | const __be32 *prop; |
167 | unsigned int psize; | 168 | unsigned int psize; |
168 | struct device_node *parent; | 169 | struct device_node *parent; |
169 | struct of_bus *bus; | 170 | struct of_bus *bus; |
@@ -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/base.c b/drivers/of/base.c index aa805250de76..632ebae7f17a 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -33,7 +33,7 @@ DEFINE_RWLOCK(devtree_lock); | |||
33 | 33 | ||
34 | int of_n_addr_cells(struct device_node *np) | 34 | int of_n_addr_cells(struct device_node *np) |
35 | { | 35 | { |
36 | const int *ip; | 36 | const __be32 *ip; |
37 | 37 | ||
38 | do { | 38 | do { |
39 | if (np->parent) | 39 | if (np->parent) |
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(of_n_addr_cells); | |||
49 | 49 | ||
50 | int of_n_size_cells(struct device_node *np) | 50 | int of_n_size_cells(struct device_node *np) |
51 | { | 51 | { |
52 | const int *ip; | 52 | const __be32 *ip; |
53 | 53 | ||
54 | do { | 54 | do { |
55 | if (np->parent) | 55 | if (np->parent) |
@@ -496,6 +496,9 @@ EXPORT_SYMBOL(of_find_node_with_property); | |||
496 | const struct of_device_id *of_match_node(const struct of_device_id *matches, | 496 | const struct of_device_id *of_match_node(const struct of_device_id *matches, |
497 | const struct device_node *node) | 497 | const struct device_node *node) |
498 | { | 498 | { |
499 | if (!matches) | ||
500 | return NULL; | ||
501 | |||
499 | while (matches->name[0] || matches->type[0] || matches->compatible[0]) { | 502 | while (matches->name[0] || matches->type[0] || matches->compatible[0]) { |
500 | int match = 1; | 503 | int match = 1; |
501 | if (matches->name[0]) | 504 | if (matches->name[0]) |
diff --git a/drivers/of/device.c b/drivers/of/device.c index 92de0eb74aea..62b4b32ac887 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -47,63 +47,10 @@ void of_dev_put(struct platform_device *dev) | |||
47 | } | 47 | } |
48 | EXPORT_SYMBOL(of_dev_put); | 48 | EXPORT_SYMBOL(of_dev_put); |
49 | 49 | ||
50 | static ssize_t devspec_show(struct device *dev, | 50 | int of_device_add(struct platform_device *ofdev) |
51 | struct device_attribute *attr, char *buf) | ||
52 | { | ||
53 | struct platform_device *ofdev; | ||
54 | |||
55 | ofdev = to_platform_device(dev); | ||
56 | return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); | ||
57 | } | ||
58 | |||
59 | static ssize_t name_show(struct device *dev, | ||
60 | struct device_attribute *attr, char *buf) | ||
61 | { | ||
62 | struct platform_device *ofdev; | ||
63 | |||
64 | ofdev = to_platform_device(dev); | ||
65 | return sprintf(buf, "%s\n", ofdev->dev.of_node->name); | ||
66 | } | ||
67 | |||
68 | static ssize_t modalias_show(struct device *dev, | ||
69 | struct device_attribute *attr, char *buf) | ||
70 | { | ||
71 | ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); | ||
72 | buf[len] = '\n'; | ||
73 | buf[len+1] = 0; | ||
74 | return len+1; | ||
75 | } | ||
76 | |||
77 | struct device_attribute of_platform_device_attrs[] = { | ||
78 | __ATTR_RO(devspec), | ||
79 | __ATTR_RO(name), | ||
80 | __ATTR_RO(modalias), | ||
81 | __ATTR_NULL | ||
82 | }; | ||
83 | |||
84 | /** | ||
85 | * of_release_dev - free an of device structure when all users of it are finished. | ||
86 | * @dev: device that's been disconnected | ||
87 | * | ||
88 | * Will be called only by the device core when all users of this of device are | ||
89 | * done. | ||
90 | */ | ||
91 | void of_release_dev(struct device *dev) | ||
92 | { | ||
93 | struct platform_device *ofdev; | ||
94 | |||
95 | ofdev = to_platform_device(dev); | ||
96 | of_node_put(ofdev->dev.of_node); | ||
97 | kfree(ofdev); | ||
98 | } | ||
99 | EXPORT_SYMBOL(of_release_dev); | ||
100 | |||
101 | int of_device_register(struct platform_device *ofdev) | ||
102 | { | 51 | { |
103 | BUG_ON(ofdev->dev.of_node == NULL); | 52 | BUG_ON(ofdev->dev.of_node == NULL); |
104 | 53 | ||
105 | device_initialize(&ofdev->dev); | ||
106 | |||
107 | /* name and id have to be set so that the platform bus doesn't get | 54 | /* name and id have to be set so that the platform bus doesn't get |
108 | * confused on matching */ | 55 | * confused on matching */ |
109 | ofdev->name = dev_name(&ofdev->dev); | 56 | ofdev->name = dev_name(&ofdev->dev); |
@@ -117,6 +64,12 @@ int of_device_register(struct platform_device *ofdev) | |||
117 | 64 | ||
118 | return device_add(&ofdev->dev); | 65 | return device_add(&ofdev->dev); |
119 | } | 66 | } |
67 | |||
68 | int of_device_register(struct platform_device *pdev) | ||
69 | { | ||
70 | device_initialize(&pdev->dev); | ||
71 | return of_device_add(pdev); | ||
72 | } | ||
120 | EXPORT_SYMBOL(of_device_register); | 73 | EXPORT_SYMBOL(of_device_register); |
121 | 74 | ||
122 | void of_device_unregister(struct platform_device *ofdev) | 75 | void of_device_unregister(struct platform_device *ofdev) |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 65da5aec7552..65200af29c52 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 | } | ||
99 | |||
100 | /** | ||
101 | * of_get_flat_dt_root - find the root node in the flat blob | ||
102 | */ | ||
103 | unsigned long __init of_get_flat_dt_root(void) | ||
104 | { | ||
105 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
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 | } | 31 | } |
114 | 32 | ||
115 | /** | 33 | /** |
116 | * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr | 34 | * of_fdt_get_property - Given a node in the given flat blob, return |
117 | * | 35 | * the property ptr |
118 | * This function can be used within scan_flattened_dt callback to get | ||
119 | * access to properties | ||
120 | */ | 36 | */ |
121 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | 37 | void *of_fdt_get_property(struct boot_param_header *blob, |
122 | unsigned long *size) | 38 | unsigned long node, const char *name, |
39 | 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,19 @@ 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 | ||
142 | * @mem: Memory chunk to use for allocating device nodes and properties | ||
196 | * @p: pointer to node in flat tree | 143 | * @p: pointer to node in flat tree |
197 | * @dad: Parent struct device_node | 144 | * @dad: Parent struct device_node |
198 | * @allnextpp: pointer to ->allnext from last allocated device_node | 145 | * @allnextpp: pointer to ->allnext from last allocated device_node |
199 | * @fpsize: Size of the node path up at the current depth. | 146 | * @fpsize: Size of the node path up at the current depth. |
200 | */ | 147 | */ |
201 | unsigned long __init unflatten_dt_node(unsigned long mem, | 148 | static unsigned long unflatten_dt_node(struct boot_param_header *blob, |
202 | unsigned long *p, | 149 | unsigned long mem, |
203 | struct device_node *dad, | 150 | unsigned long *p, |
204 | struct device_node ***allnextpp, | 151 | struct device_node *dad, |
205 | unsigned long fpsize) | 152 | struct device_node ***allnextpp, |
153 | unsigned long fpsize) | ||
206 | { | 154 | { |
207 | struct device_node *np; | 155 | struct device_node *np; |
208 | struct property *pp, **prev_pp = NULL; | 156 | struct property *pp, **prev_pp = NULL; |
@@ -283,6 +231,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
283 | } | 231 | } |
284 | kref_init(&np->kref); | 232 | kref_init(&np->kref); |
285 | } | 233 | } |
234 | /* process properties */ | ||
286 | while (1) { | 235 | while (1) { |
287 | u32 sz, noff; | 236 | u32 sz, noff; |
288 | char *pname; | 237 | char *pname; |
@@ -298,10 +247,10 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
298 | sz = be32_to_cpup((__be32 *)(*p)); | 247 | sz = be32_to_cpup((__be32 *)(*p)); |
299 | noff = be32_to_cpup((__be32 *)((*p) + 4)); | 248 | noff = be32_to_cpup((__be32 *)((*p) + 4)); |
300 | *p += 8; | 249 | *p += 8; |
301 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | 250 | if (be32_to_cpu(blob->version) < 0x10) |
302 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); | 251 | *p = ALIGN(*p, sz >= 8 ? 8 : 4); |
303 | 252 | ||
304 | pname = find_flat_dt_string(noff); | 253 | pname = of_fdt_get_string(blob, noff); |
305 | if (pname == NULL) { | 254 | if (pname == NULL) { |
306 | pr_info("Can't find property name in list !\n"); | 255 | pr_info("Can't find property name in list !\n"); |
307 | break; | 256 | break; |
@@ -380,7 +329,8 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
380 | if (tag == OF_DT_NOP) | 329 | if (tag == OF_DT_NOP) |
381 | *p += 4; | 330 | *p += 4; |
382 | else | 331 | else |
383 | mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); | 332 | mem = unflatten_dt_node(blob, mem, p, np, allnextpp, |
333 | fpsize); | ||
384 | tag = be32_to_cpup((__be32 *)(*p)); | 334 | tag = be32_to_cpup((__be32 *)(*p)); |
385 | } | 335 | } |
386 | if (tag != OF_DT_END_NODE) { | 336 | if (tag != OF_DT_END_NODE) { |
@@ -391,6 +341,211 @@ unsigned long __init unflatten_dt_node(unsigned long mem, | |||
391 | return mem; | 341 | return mem; |
392 | } | 342 | } |
393 | 343 | ||
344 | /** | ||
345 | * __unflatten_device_tree - create tree of device_nodes from flat blob | ||
346 | * | ||
347 | * unflattens a device-tree, creating the | ||
348 | * tree of struct device_node. It also fills the "name" and "type" | ||
349 | * pointers of the nodes so the normal device-tree walking functions | ||
350 | * can be used. | ||
351 | * @blob: The blob to expand | ||
352 | * @mynodes: The device_node tree created by the call | ||
353 | * @dt_alloc: An allocator that provides a virtual address to memory | ||
354 | * for the resulting tree | ||
355 | */ | ||
356 | static void __unflatten_device_tree(struct boot_param_header *blob, | ||
357 | struct device_node **mynodes, | ||
358 | void * (*dt_alloc)(u64 size, u64 align)) | ||
359 | { | ||
360 | unsigned long start, mem, size; | ||
361 | struct device_node **allnextp = mynodes; | ||
362 | |||
363 | pr_debug(" -> unflatten_device_tree()\n"); | ||
364 | |||
365 | if (!blob) { | ||
366 | pr_debug("No device tree pointer\n"); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | pr_debug("Unflattening device tree:\n"); | ||
371 | pr_debug("magic: %08x\n", be32_to_cpu(blob->magic)); | ||
372 | pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize)); | ||
373 | pr_debug("version: %08x\n", be32_to_cpu(blob->version)); | ||
374 | |||
375 | if (be32_to_cpu(blob->magic) != OF_DT_HEADER) { | ||
376 | pr_err("Invalid device tree blob header\n"); | ||
377 | return; | ||
378 | } | ||
379 | |||
380 | /* First pass, scan for size */ | ||
381 | start = ((unsigned long)blob) + | ||
382 | be32_to_cpu(blob->off_dt_struct); | ||
383 | size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); | ||
384 | size = (size | 3) + 1; | ||
385 | |||
386 | pr_debug(" size is %lx, allocating...\n", size); | ||
387 | |||
388 | /* Allocate memory for the expanded device tree */ | ||
389 | mem = (unsigned long) | ||
390 | dt_alloc(size + 4, __alignof__(struct device_node)); | ||
391 | |||
392 | ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); | ||
393 | |||
394 | pr_debug(" unflattening %lx...\n", mem); | ||
395 | |||
396 | /* Second pass, do actual unflattening */ | ||
397 | start = ((unsigned long)blob) + | ||
398 | be32_to_cpu(blob->off_dt_struct); | ||
399 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); | ||
400 | if (be32_to_cpup((__be32 *)start) != OF_DT_END) | ||
401 | pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
402 | if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) | ||
403 | pr_warning("End of tree marker overwritten: %08x\n", | ||
404 | be32_to_cpu(((__be32 *)mem)[size / 4])); | ||
405 | *allnextp = NULL; | ||
406 | |||
407 | pr_debug(" <- unflatten_device_tree()\n"); | ||
408 | } | ||
409 | |||
410 | static void *kernel_tree_alloc(u64 size, u64 align) | ||
411 | { | ||
412 | return kzalloc(size, GFP_KERNEL); | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * of_fdt_unflatten_tree - create tree of device_nodes from flat blob | ||
417 | * | ||
418 | * unflattens the device-tree passed by the firmware, creating the | ||
419 | * tree of struct device_node. It also fills the "name" and "type" | ||
420 | * pointers of the nodes so the normal device-tree walking functions | ||
421 | * can be used. | ||
422 | */ | ||
423 | void of_fdt_unflatten_tree(unsigned long *blob, | ||
424 | struct device_node **mynodes) | ||
425 | { | ||
426 | struct boot_param_header *device_tree = | ||
427 | (struct boot_param_header *)blob; | ||
428 | __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc); | ||
429 | } | ||
430 | EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); | ||
431 | |||
432 | /* Everything below here references initial_boot_params directly. */ | ||
433 | int __initdata dt_root_addr_cells; | ||
434 | int __initdata dt_root_size_cells; | ||
435 | |||
436 | struct boot_param_header *initial_boot_params; | ||
437 | |||
438 | #ifdef CONFIG_OF_EARLY_FLATTREE | ||
439 | |||
440 | /** | ||
441 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | ||
442 | * @it: callback function | ||
443 | * @data: context data pointer | ||
444 | * | ||
445 | * This function is used to scan the flattened device-tree, it is | ||
446 | * used to extract the memory information at boot before we can | ||
447 | * unflatten the tree | ||
448 | */ | ||
449 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
450 | const char *uname, int depth, | ||
451 | void *data), | ||
452 | void *data) | ||
453 | { | ||
454 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
455 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
456 | int rc = 0; | ||
457 | int depth = -1; | ||
458 | |||
459 | do { | ||
460 | u32 tag = be32_to_cpup((__be32 *)p); | ||
461 | char *pathp; | ||
462 | |||
463 | p += 4; | ||
464 | if (tag == OF_DT_END_NODE) { | ||
465 | depth--; | ||
466 | continue; | ||
467 | } | ||
468 | if (tag == OF_DT_NOP) | ||
469 | continue; | ||
470 | if (tag == OF_DT_END) | ||
471 | break; | ||
472 | if (tag == OF_DT_PROP) { | ||
473 | u32 sz = be32_to_cpup((__be32 *)p); | ||
474 | p += 8; | ||
475 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
476 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
477 | p += sz; | ||
478 | p = ALIGN(p, 4); | ||
479 | continue; | ||
480 | } | ||
481 | if (tag != OF_DT_BEGIN_NODE) { | ||
482 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
483 | return -EINVAL; | ||
484 | } | ||
485 | depth++; | ||
486 | pathp = (char *)p; | ||
487 | p = ALIGN(p + strlen(pathp) + 1, 4); | ||
488 | if ((*pathp) == '/') { | ||
489 | char *lp, *np; | ||
490 | for (lp = NULL, np = pathp; *np; np++) | ||
491 | if ((*np) == '/') | ||
492 | lp = np+1; | ||
493 | if (lp != NULL) | ||
494 | pathp = lp; | ||
495 | } | ||
496 | rc = it(p, pathp, depth, data); | ||
497 | if (rc != 0) | ||
498 | break; | ||
499 | } while (1); | ||
500 | |||
501 | return rc; | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * of_get_flat_dt_root - find the root node in the flat blob | ||
506 | */ | ||
507 | unsigned long __init of_get_flat_dt_root(void) | ||
508 | { | ||
509 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
510 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
511 | |||
512 | while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) | ||
513 | p += 4; | ||
514 | BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); | ||
515 | p += 4; | ||
516 | return ALIGN(p + strlen((char *)p) + 1, 4); | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr | ||
521 | * | ||
522 | * This function can be used within scan_flattened_dt callback to get | ||
523 | * access to properties | ||
524 | */ | ||
525 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
526 | unsigned long *size) | ||
527 | { | ||
528 | return of_fdt_get_property(initial_boot_params, node, name, size); | ||
529 | } | ||
530 | |||
531 | /** | ||
532 | * of_flat_dt_is_compatible - Return true if given node has compat in compatible list | ||
533 | * @node: node to test | ||
534 | * @compat: compatible string to compare with compatible list. | ||
535 | */ | ||
536 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | ||
537 | { | ||
538 | return of_fdt_is_compatible(initial_boot_params, node, compat); | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * of_flat_dt_match - Return true if node matches a list of compatible values | ||
543 | */ | ||
544 | int __init of_flat_dt_match(unsigned long node, const char **compat) | ||
545 | { | ||
546 | return of_fdt_match(initial_boot_params, node, compat); | ||
547 | } | ||
548 | |||
394 | #ifdef CONFIG_BLK_DEV_INITRD | 549 | #ifdef CONFIG_BLK_DEV_INITRD |
395 | /** | 550 | /** |
396 | * early_init_dt_check_for_initrd - Decode initrd location from flat tree | 551 | * early_init_dt_check_for_initrd - Decode initrd location from flat tree |
@@ -515,27 +670,25 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
515 | 670 | ||
516 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | 671 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
517 | 672 | ||
518 | if (depth != 1 || | 673 | if (depth != 1 || !data || |
519 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) | 674 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) |
520 | return 0; | 675 | return 0; |
521 | 676 | ||
522 | early_init_dt_check_for_initrd(node); | 677 | early_init_dt_check_for_initrd(node); |
523 | 678 | ||
524 | /* Retreive command line */ | 679 | /* Retrieve command line */ |
525 | p = of_get_flat_dt_prop(node, "bootargs", &l); | 680 | p = of_get_flat_dt_prop(node, "bootargs", &l); |
526 | if (p != NULL && l > 0) | 681 | if (p != NULL && l > 0) |
527 | strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); | 682 | strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); |
528 | 683 | ||
529 | #ifdef CONFIG_CMDLINE | 684 | #ifdef CONFIG_CMDLINE |
530 | #ifndef CONFIG_CMDLINE_FORCE | 685 | #ifndef CONFIG_CMDLINE_FORCE |
531 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) | 686 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) |
532 | #endif | 687 | #endif |
533 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | 688 | strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
534 | #endif /* CONFIG_CMDLINE */ | 689 | #endif /* CONFIG_CMDLINE */ |
535 | 690 | ||
536 | early_init_dt_scan_chosen_arch(node); | 691 | pr_debug("Command line is: %s\n", (char*)data); |
537 | |||
538 | pr_debug("Command line is: %s\n", cmd_line); | ||
539 | 692 | ||
540 | /* break now */ | 693 | /* break now */ |
541 | return 1; | 694 | return 1; |
@@ -551,58 +704,13 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
551 | */ | 704 | */ |
552 | void __init unflatten_device_tree(void) | 705 | void __init unflatten_device_tree(void) |
553 | { | 706 | { |
554 | unsigned long start, mem, size; | 707 | __unflatten_device_tree(initial_boot_params, &allnodes, |
555 | struct device_node **allnextp = &allnodes; | 708 | early_init_dt_alloc_memory_arch); |
556 | |||
557 | pr_debug(" -> unflatten_device_tree()\n"); | ||
558 | |||
559 | if (!initial_boot_params) { | ||
560 | pr_debug("No device tree pointer\n"); | ||
561 | return; | ||
562 | } | ||
563 | |||
564 | pr_debug("Unflattening device tree:\n"); | ||
565 | pr_debug("magic: %08x\n", be32_to_cpu(initial_boot_params->magic)); | ||
566 | pr_debug("size: %08x\n", be32_to_cpu(initial_boot_params->totalsize)); | ||
567 | pr_debug("version: %08x\n", be32_to_cpu(initial_boot_params->version)); | ||
568 | |||
569 | if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) { | ||
570 | pr_err("Invalid device tree blob header\n"); | ||
571 | return; | ||
572 | } | ||
573 | |||
574 | /* First pass, scan for size */ | ||
575 | start = ((unsigned long)initial_boot_params) + | ||
576 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
577 | size = unflatten_dt_node(0, &start, NULL, NULL, 0); | ||
578 | size = (size | 3) + 1; | ||
579 | |||
580 | pr_debug(" size is %lx, allocating...\n", size); | ||
581 | |||
582 | /* Allocate memory for the expanded device tree */ | ||
583 | mem = early_init_dt_alloc_memory_arch(size + 4, | ||
584 | __alignof__(struct device_node)); | ||
585 | mem = (unsigned long) __va(mem); | ||
586 | |||
587 | ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); | ||
588 | |||
589 | pr_debug(" unflattening %lx...\n", mem); | ||
590 | |||
591 | /* Second pass, do actual unflattening */ | ||
592 | start = ((unsigned long)initial_boot_params) + | ||
593 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
594 | unflatten_dt_node(mem, &start, NULL, &allnextp, 0); | ||
595 | if (be32_to_cpup((__be32 *)start) != OF_DT_END) | ||
596 | pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
597 | if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) | ||
598 | pr_warning("End of tree marker overwritten: %08x\n", | ||
599 | be32_to_cpu(((__be32 *)mem)[size / 4])); | ||
600 | *allnextp = NULL; | ||
601 | 709 | ||
602 | /* Get pointer to OF "/chosen" node for use everywhere */ | 710 | /* Get pointer to OF "/chosen" node for use everywhere */ |
603 | of_chosen = of_find_node_by_path("/chosen"); | 711 | of_chosen = of_find_node_by_path("/chosen"); |
604 | if (of_chosen == NULL) | 712 | if (of_chosen == NULL) |
605 | of_chosen = of_find_node_by_path("/chosen@0"); | 713 | of_chosen = of_find_node_by_path("/chosen@0"); |
606 | |||
607 | pr_debug(" <- unflatten_device_tree()\n"); | ||
608 | } | 714 | } |
715 | |||
716 | #endif /* CONFIG_OF_EARLY_FLATTREE */ | ||
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 6e595e5a3977..9f689f1da0fc 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c | |||
@@ -24,6 +24,11 @@ | |||
24 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | 26 | ||
27 | /* For archs that don't support NO_IRQ (such as x86), provide a dummy value */ | ||
28 | #ifndef NO_IRQ | ||
29 | #define NO_IRQ 0 | ||
30 | #endif | ||
31 | |||
27 | /** | 32 | /** |
28 | * irq_of_parse_and_map - Parse and map an interrupt into linux virq space | 33 | * irq_of_parse_and_map - Parse and map an interrupt into linux virq space |
29 | * @device: Device node of the device whose interrupt is to be mapped | 34 | * @device: Device node of the device whose interrupt is to be mapped |
@@ -51,7 +56,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); | |||
51 | * Returns a pointer to the interrupt parent node, or NULL if the interrupt | 56 | * Returns a pointer to the interrupt parent node, or NULL if the interrupt |
52 | * parent could not be determined. | 57 | * parent could not be determined. |
53 | */ | 58 | */ |
54 | static struct device_node *of_irq_find_parent(struct device_node *child) | 59 | struct device_node *of_irq_find_parent(struct device_node *child) |
55 | { | 60 | { |
56 | struct device_node *p; | 61 | struct device_node *p; |
57 | const __be32 *parp; | 62 | const __be32 *parp; |
@@ -347,3 +352,37 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) | |||
347 | return irq; | 352 | return irq; |
348 | } | 353 | } |
349 | EXPORT_SYMBOL_GPL(of_irq_to_resource); | 354 | EXPORT_SYMBOL_GPL(of_irq_to_resource); |
355 | |||
356 | /** | ||
357 | * of_irq_count - Count the number of IRQs a node uses | ||
358 | * @dev: pointer to device tree node | ||
359 | */ | ||
360 | int of_irq_count(struct device_node *dev) | ||
361 | { | ||
362 | int nr = 0; | ||
363 | |||
364 | while (of_irq_to_resource(dev, nr, NULL) != NO_IRQ) | ||
365 | nr++; | ||
366 | |||
367 | return nr; | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * of_irq_to_resource_table - Fill in resource table with node's IRQ info | ||
372 | * @dev: pointer to device tree node | ||
373 | * @res: array of resources to fill in | ||
374 | * @nr_irqs: the number of IRQs (and upper bound for num of @res elements) | ||
375 | * | ||
376 | * Returns the size of the filled in table (up to @nr_irqs). | ||
377 | */ | ||
378 | int of_irq_to_resource_table(struct device_node *dev, struct resource *res, | ||
379 | int nr_irqs) | ||
380 | { | ||
381 | int i; | ||
382 | |||
383 | for (i = 0; i < nr_irqs; i++, res++) | ||
384 | if (of_irq_to_resource(dev, i, res) == NO_IRQ) | ||
385 | break; | ||
386 | |||
387 | return i; | ||
388 | } | ||
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index 0a694debd226..f37fbeb66a44 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/irq.h> | ||
15 | #include <linux/of.h> | 16 | #include <linux/of.h> |
16 | #include <linux/of_i2c.h> | 17 | #include <linux/of_i2c.h> |
17 | #include <linux/of_irq.h> | 18 | #include <linux/of_irq.h> |
@@ -60,7 +61,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap) | |||
60 | info.of_node = of_node_get(node); | 61 | info.of_node = of_node_get(node); |
61 | info.archdata = &dev_ad; | 62 | info.archdata = &dev_ad; |
62 | 63 | ||
63 | request_module("%s", info.type); | 64 | request_module("%s%s", I2C_MODULE_PREFIX, info.type); |
64 | 65 | ||
65 | result = i2c_new_device(adap, &info); | 66 | result = i2c_new_device(adap, &info); |
66 | if (result == NULL) { | 67 | if (result == NULL) { |
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 1fce00eb421b..d35e300b0ad1 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; |
@@ -128,7 +136,7 @@ EXPORT_SYMBOL(of_phy_find_device); | |||
128 | * @hndlr: Link state callback for the network device | 136 | * @hndlr: Link state callback for the network device |
129 | * @iface: PHY data interface type | 137 | * @iface: PHY data interface type |
130 | * | 138 | * |
131 | * Returns a pointer to the phy_device if successfull. NULL otherwise | 139 | * Returns a pointer to the phy_device if successful. NULL otherwise |
132 | */ | 140 | */ |
133 | struct phy_device *of_phy_connect(struct net_device *dev, | 141 | struct phy_device *of_phy_connect(struct net_device *dev, |
134 | struct device_node *phy_np, | 142 | struct device_node *phy_np, |
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c new file mode 100644 index 000000000000..86f334a2769c --- /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/of_pci.c b/drivers/of/of_pci.c new file mode 100644 index 000000000000..ac1ec54e4fd5 --- /dev/null +++ b/drivers/of/of_pci.c | |||
@@ -0,0 +1,92 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/of_pci.h> | ||
3 | #include <linux/of_irq.h> | ||
4 | #include <asm/prom.h> | ||
5 | |||
6 | /** | ||
7 | * of_irq_map_pci - Resolve the interrupt for a PCI device | ||
8 | * @pdev: the device whose interrupt is to be resolved | ||
9 | * @out_irq: structure of_irq filled by this function | ||
10 | * | ||
11 | * This function resolves the PCI interrupt for a given PCI device. If a | ||
12 | * device-node exists for a given pci_dev, it will use normal OF tree | ||
13 | * walking. If not, it will implement standard swizzling and walk up the | ||
14 | * PCI tree until an device-node is found, at which point it will finish | ||
15 | * resolving using the OF tree walking. | ||
16 | */ | ||
17 | int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) | ||
18 | { | ||
19 | struct device_node *dn, *ppnode; | ||
20 | struct pci_dev *ppdev; | ||
21 | u32 lspec; | ||
22 | __be32 lspec_be; | ||
23 | __be32 laddr[3]; | ||
24 | u8 pin; | ||
25 | int rc; | ||
26 | |||
27 | /* Check if we have a device node, if yes, fallback to standard | ||
28 | * device tree parsing | ||
29 | */ | ||
30 | dn = pci_device_to_OF_node(pdev); | ||
31 | if (dn) { | ||
32 | rc = of_irq_map_one(dn, 0, out_irq); | ||
33 | if (!rc) | ||
34 | return rc; | ||
35 | } | ||
36 | |||
37 | /* Ok, we don't, time to have fun. Let's start by building up an | ||
38 | * interrupt spec. we assume #interrupt-cells is 1, which is standard | ||
39 | * for PCI. If you do different, then don't use that routine. | ||
40 | */ | ||
41 | rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); | ||
42 | if (rc != 0) | ||
43 | return rc; | ||
44 | /* No pin, exit */ | ||
45 | if (pin == 0) | ||
46 | return -ENODEV; | ||
47 | |||
48 | /* Now we walk up the PCI tree */ | ||
49 | lspec = pin; | ||
50 | for (;;) { | ||
51 | /* Get the pci_dev of our parent */ | ||
52 | ppdev = pdev->bus->self; | ||
53 | |||
54 | /* Ouch, it's a host bridge... */ | ||
55 | if (ppdev == NULL) { | ||
56 | ppnode = pci_bus_to_OF_node(pdev->bus); | ||
57 | |||
58 | /* No node for host bridge ? give up */ | ||
59 | if (ppnode == NULL) | ||
60 | return -EINVAL; | ||
61 | } else { | ||
62 | /* We found a P2P bridge, check if it has a node */ | ||
63 | ppnode = pci_device_to_OF_node(ppdev); | ||
64 | } | ||
65 | |||
66 | /* Ok, we have found a parent with a device-node, hand over to | ||
67 | * the OF parsing code. | ||
68 | * We build a unit address from the linux device to be used for | ||
69 | * resolution. Note that we use the linux bus number which may | ||
70 | * not match your firmware bus numbering. | ||
71 | * Fortunately, in most cases, interrupt-map-mask doesn't | ||
72 | * include the bus number as part of the matching. | ||
73 | * You should still be careful about that though if you intend | ||
74 | * to rely on this function (you ship a firmware that doesn't | ||
75 | * create device nodes for all PCI devices). | ||
76 | */ | ||
77 | if (ppnode) | ||
78 | break; | ||
79 | |||
80 | /* We can only get here if we hit a P2P bridge with no node, | ||
81 | * let's do standard swizzling and try again | ||
82 | */ | ||
83 | lspec = pci_swizzle_interrupt_pin(pdev, lspec); | ||
84 | pdev = ppdev; | ||
85 | } | ||
86 | |||
87 | lspec_be = cpu_to_be32(lspec); | ||
88 | laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); | ||
89 | laddr[1] = laddr[2] = cpu_to_be32(0); | ||
90 | return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq); | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(of_irq_map_pci); | ||
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c new file mode 100644 index 000000000000..4d87b5dc9284 --- /dev/null +++ b/drivers/of/pdt.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* pdt.c: OF PROM device tree support code. | ||
2 | * | ||
3 | * Paul Mackerras August 1996. | ||
4 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
5 | * | ||
6 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
7 | * {engebret|bergner}@us.ibm.com | ||
8 | * | ||
9 | * Adapted for sparc by David S. Miller davem@davemloft.net | ||
10 | * Adapted for multiple architectures by Andres Salomon <dilinger@queued.net> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/of_pdt.h> | ||
25 | #include <asm/prom.h> | ||
26 | |||
27 | static struct of_pdt_ops *of_pdt_prom_ops __initdata; | ||
28 | |||
29 | void __initdata (*of_pdt_build_more)(struct device_node *dp, | ||
30 | struct device_node ***nextp); | ||
31 | |||
32 | #if defined(CONFIG_SPARC) | ||
33 | unsigned int of_pdt_unique_id __initdata; | ||
34 | |||
35 | #define of_pdt_incr_unique_id(p) do { \ | ||
36 | (p)->unique_id = of_pdt_unique_id++; \ | ||
37 | } while (0) | ||
38 | |||
39 | static char * __init of_pdt_build_full_name(struct device_node *dp) | ||
40 | { | ||
41 | int len, ourlen, plen; | ||
42 | char *n; | ||
43 | |||
44 | dp->path_component_name = build_path_component(dp); | ||
45 | |||
46 | plen = strlen(dp->parent->full_name); | ||
47 | ourlen = strlen(dp->path_component_name); | ||
48 | len = ourlen + plen + 2; | ||
49 | |||
50 | n = prom_early_alloc(len); | ||
51 | strcpy(n, dp->parent->full_name); | ||
52 | if (!of_node_is_root(dp->parent)) { | ||
53 | strcpy(n + plen, "/"); | ||
54 | plen++; | ||
55 | } | ||
56 | strcpy(n + plen, dp->path_component_name); | ||
57 | |||
58 | return n; | ||
59 | } | ||
60 | |||
61 | #else /* CONFIG_SPARC */ | ||
62 | |||
63 | static inline void of_pdt_incr_unique_id(void *p) { } | ||
64 | static inline void irq_trans_init(struct device_node *dp) { } | ||
65 | |||
66 | static char * __init of_pdt_build_full_name(struct device_node *dp) | ||
67 | { | ||
68 | static int failsafe_id = 0; /* for generating unique names on failure */ | ||
69 | char *buf; | ||
70 | int len; | ||
71 | |||
72 | if (of_pdt_prom_ops->pkg2path(dp->phandle, NULL, 0, &len)) | ||
73 | goto failsafe; | ||
74 | |||
75 | buf = prom_early_alloc(len + 1); | ||
76 | if (of_pdt_prom_ops->pkg2path(dp->phandle, buf, len, &len)) | ||
77 | goto failsafe; | ||
78 | return buf; | ||
79 | |||
80 | failsafe: | ||
81 | buf = prom_early_alloc(strlen(dp->parent->full_name) + | ||
82 | strlen(dp->name) + 16); | ||
83 | sprintf(buf, "%s/%s@unknown%i", | ||
84 | of_node_is_root(dp->parent) ? "" : dp->parent->full_name, | ||
85 | dp->name, failsafe_id++); | ||
86 | pr_err("%s: pkg2path failed; assigning %s\n", __func__, buf); | ||
87 | return buf; | ||
88 | } | ||
89 | |||
90 | #endif /* !CONFIG_SPARC */ | ||
91 | |||
92 | static struct property * __init of_pdt_build_one_prop(phandle node, char *prev, | ||
93 | char *special_name, | ||
94 | void *special_val, | ||
95 | int special_len) | ||
96 | { | ||
97 | static struct property *tmp = NULL; | ||
98 | struct property *p; | ||
99 | int err; | ||
100 | |||
101 | if (tmp) { | ||
102 | p = tmp; | ||
103 | memset(p, 0, sizeof(*p) + 32); | ||
104 | tmp = NULL; | ||
105 | } else { | ||
106 | p = prom_early_alloc(sizeof(struct property) + 32); | ||
107 | of_pdt_incr_unique_id(p); | ||
108 | } | ||
109 | |||
110 | p->name = (char *) (p + 1); | ||
111 | if (special_name) { | ||
112 | strcpy(p->name, special_name); | ||
113 | p->length = special_len; | ||
114 | p->value = prom_early_alloc(special_len); | ||
115 | memcpy(p->value, special_val, special_len); | ||
116 | } else { | ||
117 | err = of_pdt_prom_ops->nextprop(node, prev, p->name); | ||
118 | if (err) { | ||
119 | tmp = p; | ||
120 | return NULL; | ||
121 | } | ||
122 | p->length = of_pdt_prom_ops->getproplen(node, p->name); | ||
123 | if (p->length <= 0) { | ||
124 | p->length = 0; | ||
125 | } else { | ||
126 | int len; | ||
127 | |||
128 | p->value = prom_early_alloc(p->length + 1); | ||
129 | len = of_pdt_prom_ops->getproperty(node, p->name, | ||
130 | p->value, p->length); | ||
131 | if (len <= 0) | ||
132 | p->length = 0; | ||
133 | ((unsigned char *)p->value)[p->length] = '\0'; | ||
134 | } | ||
135 | } | ||
136 | return p; | ||
137 | } | ||
138 | |||
139 | static struct property * __init of_pdt_build_prop_list(phandle node) | ||
140 | { | ||
141 | struct property *head, *tail; | ||
142 | |||
143 | head = tail = of_pdt_build_one_prop(node, NULL, | ||
144 | ".node", &node, sizeof(node)); | ||
145 | |||
146 | tail->next = of_pdt_build_one_prop(node, NULL, NULL, NULL, 0); | ||
147 | tail = tail->next; | ||
148 | while(tail) { | ||
149 | tail->next = of_pdt_build_one_prop(node, tail->name, | ||
150 | NULL, NULL, 0); | ||
151 | tail = tail->next; | ||
152 | } | ||
153 | |||
154 | return head; | ||
155 | } | ||
156 | |||
157 | static char * __init of_pdt_get_one_property(phandle node, const char *name) | ||
158 | { | ||
159 | char *buf = "<NULL>"; | ||
160 | int len; | ||
161 | |||
162 | len = of_pdt_prom_ops->getproplen(node, name); | ||
163 | if (len > 0) { | ||
164 | buf = prom_early_alloc(len); | ||
165 | len = of_pdt_prom_ops->getproperty(node, name, buf, len); | ||
166 | } | ||
167 | |||
168 | return buf; | ||
169 | } | ||
170 | |||
171 | static struct device_node * __init of_pdt_create_node(phandle node, | ||
172 | struct device_node *parent) | ||
173 | { | ||
174 | struct device_node *dp; | ||
175 | |||
176 | if (!node) | ||
177 | return NULL; | ||
178 | |||
179 | dp = prom_early_alloc(sizeof(*dp)); | ||
180 | of_pdt_incr_unique_id(dp); | ||
181 | dp->parent = parent; | ||
182 | |||
183 | kref_init(&dp->kref); | ||
184 | |||
185 | dp->name = of_pdt_get_one_property(node, "name"); | ||
186 | dp->type = of_pdt_get_one_property(node, "device_type"); | ||
187 | dp->phandle = node; | ||
188 | |||
189 | dp->properties = of_pdt_build_prop_list(node); | ||
190 | |||
191 | irq_trans_init(dp); | ||
192 | |||
193 | return dp; | ||
194 | } | ||
195 | |||
196 | static struct device_node * __init of_pdt_build_tree(struct device_node *parent, | ||
197 | phandle node, | ||
198 | struct device_node ***nextp) | ||
199 | { | ||
200 | struct device_node *ret = NULL, *prev_sibling = NULL; | ||
201 | struct device_node *dp; | ||
202 | |||
203 | while (1) { | ||
204 | dp = of_pdt_create_node(node, parent); | ||
205 | if (!dp) | ||
206 | break; | ||
207 | |||
208 | if (prev_sibling) | ||
209 | prev_sibling->sibling = dp; | ||
210 | |||
211 | if (!ret) | ||
212 | ret = dp; | ||
213 | prev_sibling = dp; | ||
214 | |||
215 | *(*nextp) = dp; | ||
216 | *nextp = &dp->allnext; | ||
217 | |||
218 | dp->full_name = of_pdt_build_full_name(dp); | ||
219 | |||
220 | dp->child = of_pdt_build_tree(dp, | ||
221 | of_pdt_prom_ops->getchild(node), nextp); | ||
222 | |||
223 | if (of_pdt_build_more) | ||
224 | of_pdt_build_more(dp, nextp); | ||
225 | |||
226 | node = of_pdt_prom_ops->getsibling(node); | ||
227 | } | ||
228 | |||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) | ||
233 | { | ||
234 | struct device_node **nextp; | ||
235 | |||
236 | BUG_ON(!ops); | ||
237 | of_pdt_prom_ops = ops; | ||
238 | |||
239 | allnodes = of_pdt_create_node(root_node, NULL); | ||
240 | #if defined(CONFIG_SPARC) | ||
241 | allnodes->path_component_name = ""; | ||
242 | #endif | ||
243 | allnodes->full_name = "/"; | ||
244 | |||
245 | nextp = &allnodes->allnext; | ||
246 | allnodes->child = of_pdt_build_tree(allnodes, | ||
247 | of_pdt_prom_ops->getchild(allnodes->phandle), &nextp); | ||
248 | } | ||
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index bb72223c22ae..63d3cb73bdb9 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -42,471 +42,10 @@ struct platform_device *of_find_device_by_node(struct device_node *np) | |||
42 | } | 42 | } |
43 | EXPORT_SYMBOL(of_find_device_by_node); | 43 | EXPORT_SYMBOL(of_find_device_by_node); |
44 | 44 | ||
45 | static int platform_driver_probe_shim(struct platform_device *pdev) | ||
46 | { | ||
47 | struct platform_driver *pdrv; | ||
48 | struct of_platform_driver *ofpdrv; | ||
49 | const struct of_device_id *match; | ||
50 | |||
51 | pdrv = container_of(pdev->dev.driver, struct platform_driver, driver); | ||
52 | ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver); | ||
53 | |||
54 | /* There is an unlikely chance that an of_platform driver might match | ||
55 | * on a non-OF platform device. If so, then of_match_device() will | ||
56 | * come up empty. Return -EINVAL in this case so other drivers get | ||
57 | * the chance to bind. */ | ||
58 | match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); | ||
59 | return match ? ofpdrv->probe(pdev, match) : -EINVAL; | ||
60 | } | ||
61 | |||
62 | static void platform_driver_shutdown_shim(struct platform_device *pdev) | ||
63 | { | ||
64 | struct platform_driver *pdrv; | ||
65 | struct of_platform_driver *ofpdrv; | ||
66 | |||
67 | pdrv = container_of(pdev->dev.driver, struct platform_driver, driver); | ||
68 | ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver); | ||
69 | ofpdrv->shutdown(pdev); | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * of_register_platform_driver | ||
74 | */ | ||
75 | int of_register_platform_driver(struct of_platform_driver *drv) | ||
76 | { | ||
77 | char *of_name; | ||
78 | |||
79 | /* setup of_platform_driver to platform_driver adaptors */ | ||
80 | drv->platform_driver.driver = drv->driver; | ||
81 | |||
82 | /* Prefix the driver name with 'of:' to avoid namespace collisions | ||
83 | * and bogus matches. There are some drivers in the tree that | ||
84 | * register both an of_platform_driver and a platform_driver with | ||
85 | * the same name. This is a temporary measure until they are all | ||
86 | * cleaned up --gcl July 29, 2010 */ | ||
87 | of_name = kmalloc(strlen(drv->driver.name) + 5, GFP_KERNEL); | ||
88 | if (!of_name) | ||
89 | return -ENOMEM; | ||
90 | sprintf(of_name, "of:%s", drv->driver.name); | ||
91 | drv->platform_driver.driver.name = of_name; | ||
92 | |||
93 | if (drv->probe) | ||
94 | drv->platform_driver.probe = platform_driver_probe_shim; | ||
95 | drv->platform_driver.remove = drv->remove; | ||
96 | if (drv->shutdown) | ||
97 | drv->platform_driver.shutdown = platform_driver_shutdown_shim; | ||
98 | drv->platform_driver.suspend = drv->suspend; | ||
99 | drv->platform_driver.resume = drv->resume; | ||
100 | |||
101 | return platform_driver_register(&drv->platform_driver); | ||
102 | } | ||
103 | EXPORT_SYMBOL(of_register_platform_driver); | ||
104 | |||
105 | void of_unregister_platform_driver(struct of_platform_driver *drv) | ||
106 | { | ||
107 | platform_driver_unregister(&drv->platform_driver); | ||
108 | kfree(drv->platform_driver.driver.name); | ||
109 | drv->platform_driver.driver.name = NULL; | ||
110 | } | ||
111 | EXPORT_SYMBOL(of_unregister_platform_driver); | ||
112 | |||
113 | #if defined(CONFIG_PPC_DCR) | 45 | #if defined(CONFIG_PPC_DCR) |
114 | #include <asm/dcr.h> | 46 | #include <asm/dcr.h> |
115 | #endif | 47 | #endif |
116 | 48 | ||
117 | extern struct device_attribute of_platform_device_attrs[]; | ||
118 | |||
119 | static int of_platform_bus_match(struct device *dev, struct device_driver *drv) | ||
120 | { | ||
121 | const struct of_device_id *matches = drv->of_match_table; | ||
122 | |||
123 | if (!matches) | ||
124 | return 0; | ||
125 | |||
126 | return of_match_device(matches, dev) != NULL; | ||
127 | } | ||
128 | |||
129 | static int of_platform_device_probe(struct device *dev) | ||
130 | { | ||
131 | int error = -ENODEV; | ||
132 | struct of_platform_driver *drv; | ||
133 | struct platform_device *of_dev; | ||
134 | const struct of_device_id *match; | ||
135 | |||
136 | drv = to_of_platform_driver(dev->driver); | ||
137 | of_dev = to_platform_device(dev); | ||
138 | |||
139 | if (!drv->probe) | ||
140 | return error; | ||
141 | |||
142 | of_dev_get(of_dev); | ||
143 | |||
144 | match = of_match_device(drv->driver.of_match_table, dev); | ||
145 | if (match) | ||
146 | error = drv->probe(of_dev, match); | ||
147 | if (error) | ||
148 | of_dev_put(of_dev); | ||
149 | |||
150 | return error; | ||
151 | } | ||
152 | |||
153 | static int of_platform_device_remove(struct device *dev) | ||
154 | { | ||
155 | struct platform_device *of_dev = to_platform_device(dev); | ||
156 | struct of_platform_driver *drv = to_of_platform_driver(dev->driver); | ||
157 | |||
158 | if (dev->driver && drv->remove) | ||
159 | drv->remove(of_dev); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void of_platform_device_shutdown(struct device *dev) | ||
164 | { | ||
165 | struct platform_device *of_dev = to_platform_device(dev); | ||
166 | struct of_platform_driver *drv = to_of_platform_driver(dev->driver); | ||
167 | |||
168 | if (dev->driver && drv->shutdown) | ||
169 | drv->shutdown(of_dev); | ||
170 | } | ||
171 | |||
172 | #ifdef CONFIG_PM_SLEEP | ||
173 | |||
174 | static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg) | ||
175 | { | ||
176 | struct platform_device *of_dev = to_platform_device(dev); | ||
177 | struct of_platform_driver *drv = to_of_platform_driver(dev->driver); | ||
178 | int ret = 0; | ||
179 | |||
180 | if (dev->driver && drv->suspend) | ||
181 | ret = drv->suspend(of_dev, mesg); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | static int of_platform_legacy_resume(struct device *dev) | ||
186 | { | ||
187 | struct platform_device *of_dev = to_platform_device(dev); | ||
188 | struct of_platform_driver *drv = to_of_platform_driver(dev->driver); | ||
189 | int ret = 0; | ||
190 | |||
191 | if (dev->driver && drv->resume) | ||
192 | ret = drv->resume(of_dev); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static int of_platform_pm_prepare(struct device *dev) | ||
197 | { | ||
198 | struct device_driver *drv = dev->driver; | ||
199 | int ret = 0; | ||
200 | |||
201 | if (drv && drv->pm && drv->pm->prepare) | ||
202 | ret = drv->pm->prepare(dev); | ||
203 | |||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | static void of_platform_pm_complete(struct device *dev) | ||
208 | { | ||
209 | struct device_driver *drv = dev->driver; | ||
210 | |||
211 | if (drv && drv->pm && drv->pm->complete) | ||
212 | drv->pm->complete(dev); | ||
213 | } | ||
214 | |||
215 | #ifdef CONFIG_SUSPEND | ||
216 | |||
217 | static int of_platform_pm_suspend(struct device *dev) | ||
218 | { | ||
219 | struct device_driver *drv = dev->driver; | ||
220 | int ret = 0; | ||
221 | |||
222 | if (!drv) | ||
223 | return 0; | ||
224 | |||
225 | if (drv->pm) { | ||
226 | if (drv->pm->suspend) | ||
227 | ret = drv->pm->suspend(dev); | ||
228 | } else { | ||
229 | ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND); | ||
230 | } | ||
231 | |||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | static int of_platform_pm_suspend_noirq(struct device *dev) | ||
236 | { | ||
237 | struct device_driver *drv = dev->driver; | ||
238 | int ret = 0; | ||
239 | |||
240 | if (!drv) | ||
241 | return 0; | ||
242 | |||
243 | if (drv->pm) { | ||
244 | if (drv->pm->suspend_noirq) | ||
245 | ret = drv->pm->suspend_noirq(dev); | ||
246 | } | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static int of_platform_pm_resume(struct device *dev) | ||
252 | { | ||
253 | struct device_driver *drv = dev->driver; | ||
254 | int ret = 0; | ||
255 | |||
256 | if (!drv) | ||
257 | return 0; | ||
258 | |||
259 | if (drv->pm) { | ||
260 | if (drv->pm->resume) | ||
261 | ret = drv->pm->resume(dev); | ||
262 | } else { | ||
263 | ret = of_platform_legacy_resume(dev); | ||
264 | } | ||
265 | |||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | static int of_platform_pm_resume_noirq(struct device *dev) | ||
270 | { | ||
271 | struct device_driver *drv = dev->driver; | ||
272 | int ret = 0; | ||
273 | |||
274 | if (!drv) | ||
275 | return 0; | ||
276 | |||
277 | if (drv->pm) { | ||
278 | if (drv->pm->resume_noirq) | ||
279 | ret = drv->pm->resume_noirq(dev); | ||
280 | } | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | #else /* !CONFIG_SUSPEND */ | ||
286 | |||
287 | #define of_platform_pm_suspend NULL | ||
288 | #define of_platform_pm_resume NULL | ||
289 | #define of_platform_pm_suspend_noirq NULL | ||
290 | #define of_platform_pm_resume_noirq NULL | ||
291 | |||
292 | #endif /* !CONFIG_SUSPEND */ | ||
293 | |||
294 | #ifdef CONFIG_HIBERNATION | ||
295 | |||
296 | static int of_platform_pm_freeze(struct device *dev) | ||
297 | { | ||
298 | struct device_driver *drv = dev->driver; | ||
299 | int ret = 0; | ||
300 | |||
301 | if (!drv) | ||
302 | return 0; | ||
303 | |||
304 | if (drv->pm) { | ||
305 | if (drv->pm->freeze) | ||
306 | ret = drv->pm->freeze(dev); | ||
307 | } else { | ||
308 | ret = of_platform_legacy_suspend(dev, PMSG_FREEZE); | ||
309 | } | ||
310 | |||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static int of_platform_pm_freeze_noirq(struct device *dev) | ||
315 | { | ||
316 | struct device_driver *drv = dev->driver; | ||
317 | int ret = 0; | ||
318 | |||
319 | if (!drv) | ||
320 | return 0; | ||
321 | |||
322 | if (drv->pm) { | ||
323 | if (drv->pm->freeze_noirq) | ||
324 | ret = drv->pm->freeze_noirq(dev); | ||
325 | } | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | static int of_platform_pm_thaw(struct device *dev) | ||
331 | { | ||
332 | struct device_driver *drv = dev->driver; | ||
333 | int ret = 0; | ||
334 | |||
335 | if (!drv) | ||
336 | return 0; | ||
337 | |||
338 | if (drv->pm) { | ||
339 | if (drv->pm->thaw) | ||
340 | ret = drv->pm->thaw(dev); | ||
341 | } else { | ||
342 | ret = of_platform_legacy_resume(dev); | ||
343 | } | ||
344 | |||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | static int of_platform_pm_thaw_noirq(struct device *dev) | ||
349 | { | ||
350 | struct device_driver *drv = dev->driver; | ||
351 | int ret = 0; | ||
352 | |||
353 | if (!drv) | ||
354 | return 0; | ||
355 | |||
356 | if (drv->pm) { | ||
357 | if (drv->pm->thaw_noirq) | ||
358 | ret = drv->pm->thaw_noirq(dev); | ||
359 | } | ||
360 | |||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | static int of_platform_pm_poweroff(struct device *dev) | ||
365 | { | ||
366 | struct device_driver *drv = dev->driver; | ||
367 | int ret = 0; | ||
368 | |||
369 | if (!drv) | ||
370 | return 0; | ||
371 | |||
372 | if (drv->pm) { | ||
373 | if (drv->pm->poweroff) | ||
374 | ret = drv->pm->poweroff(dev); | ||
375 | } else { | ||
376 | ret = of_platform_legacy_suspend(dev, PMSG_HIBERNATE); | ||
377 | } | ||
378 | |||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static int of_platform_pm_poweroff_noirq(struct device *dev) | ||
383 | { | ||
384 | struct device_driver *drv = dev->driver; | ||
385 | int ret = 0; | ||
386 | |||
387 | if (!drv) | ||
388 | return 0; | ||
389 | |||
390 | if (drv->pm) { | ||
391 | if (drv->pm->poweroff_noirq) | ||
392 | ret = drv->pm->poweroff_noirq(dev); | ||
393 | } | ||
394 | |||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | static int of_platform_pm_restore(struct device *dev) | ||
399 | { | ||
400 | struct device_driver *drv = dev->driver; | ||
401 | int ret = 0; | ||
402 | |||
403 | if (!drv) | ||
404 | return 0; | ||
405 | |||
406 | if (drv->pm) { | ||
407 | if (drv->pm->restore) | ||
408 | ret = drv->pm->restore(dev); | ||
409 | } else { | ||
410 | ret = of_platform_legacy_resume(dev); | ||
411 | } | ||
412 | |||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | static int of_platform_pm_restore_noirq(struct device *dev) | ||
417 | { | ||
418 | struct device_driver *drv = dev->driver; | ||
419 | int ret = 0; | ||
420 | |||
421 | if (!drv) | ||
422 | return 0; | ||
423 | |||
424 | if (drv->pm) { | ||
425 | if (drv->pm->restore_noirq) | ||
426 | ret = drv->pm->restore_noirq(dev); | ||
427 | } | ||
428 | |||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | #else /* !CONFIG_HIBERNATION */ | ||
433 | |||
434 | #define of_platform_pm_freeze NULL | ||
435 | #define of_platform_pm_thaw NULL | ||
436 | #define of_platform_pm_poweroff NULL | ||
437 | #define of_platform_pm_restore NULL | ||
438 | #define of_platform_pm_freeze_noirq NULL | ||
439 | #define of_platform_pm_thaw_noirq NULL | ||
440 | #define of_platform_pm_poweroff_noirq NULL | ||
441 | #define of_platform_pm_restore_noirq NULL | ||
442 | |||
443 | #endif /* !CONFIG_HIBERNATION */ | ||
444 | |||
445 | static struct dev_pm_ops of_platform_dev_pm_ops = { | ||
446 | .prepare = of_platform_pm_prepare, | ||
447 | .complete = of_platform_pm_complete, | ||
448 | .suspend = of_platform_pm_suspend, | ||
449 | .resume = of_platform_pm_resume, | ||
450 | .freeze = of_platform_pm_freeze, | ||
451 | .thaw = of_platform_pm_thaw, | ||
452 | .poweroff = of_platform_pm_poweroff, | ||
453 | .restore = of_platform_pm_restore, | ||
454 | .suspend_noirq = of_platform_pm_suspend_noirq, | ||
455 | .resume_noirq = of_platform_pm_resume_noirq, | ||
456 | .freeze_noirq = of_platform_pm_freeze_noirq, | ||
457 | .thaw_noirq = of_platform_pm_thaw_noirq, | ||
458 | .poweroff_noirq = of_platform_pm_poweroff_noirq, | ||
459 | .restore_noirq = of_platform_pm_restore_noirq, | ||
460 | }; | ||
461 | |||
462 | #define OF_PLATFORM_PM_OPS_PTR (&of_platform_dev_pm_ops) | ||
463 | |||
464 | #else /* !CONFIG_PM_SLEEP */ | ||
465 | |||
466 | #define OF_PLATFORM_PM_OPS_PTR NULL | ||
467 | |||
468 | #endif /* !CONFIG_PM_SLEEP */ | ||
469 | |||
470 | int of_bus_type_init(struct bus_type *bus, const char *name) | ||
471 | { | ||
472 | bus->name = name; | ||
473 | bus->match = of_platform_bus_match; | ||
474 | bus->probe = of_platform_device_probe; | ||
475 | bus->remove = of_platform_device_remove; | ||
476 | bus->shutdown = of_platform_device_shutdown; | ||
477 | bus->dev_attrs = of_platform_device_attrs; | ||
478 | bus->pm = OF_PLATFORM_PM_OPS_PTR; | ||
479 | return bus_register(bus); | ||
480 | } | ||
481 | |||
482 | int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) | ||
483 | { | ||
484 | /* | ||
485 | * Temporary: of_platform_bus used to be distinct from the platform | ||
486 | * bus. It isn't anymore, and so drivers on the platform bus need | ||
487 | * to be registered in a special way. | ||
488 | * | ||
489 | * After all of_platform_bus_type drivers are converted to | ||
490 | * platform_drivers, this exception can be removed. | ||
491 | */ | ||
492 | if (bus == &platform_bus_type) | ||
493 | return of_register_platform_driver(drv); | ||
494 | |||
495 | /* register with core */ | ||
496 | drv->driver.bus = bus; | ||
497 | return driver_register(&drv->driver); | ||
498 | } | ||
499 | EXPORT_SYMBOL(of_register_driver); | ||
500 | |||
501 | void of_unregister_driver(struct of_platform_driver *drv) | ||
502 | { | ||
503 | if (drv->driver.bus == &platform_bus_type) | ||
504 | of_unregister_platform_driver(drv); | ||
505 | else | ||
506 | driver_unregister(&drv->driver); | ||
507 | } | ||
508 | EXPORT_SYMBOL(of_unregister_driver); | ||
509 | |||
510 | #if !defined(CONFIG_SPARC) | 49 | #if !defined(CONFIG_SPARC) |
511 | /* | 50 | /* |
512 | * The following routines scan a subtree and registers a device for | 51 | * The following routines scan a subtree and registers a device for |
@@ -584,34 +123,33 @@ struct platform_device *of_device_alloc(struct device_node *np, | |||
584 | struct device *parent) | 123 | struct device *parent) |
585 | { | 124 | { |
586 | struct platform_device *dev; | 125 | struct platform_device *dev; |
587 | int rc, i, num_reg = 0, num_irq = 0; | 126 | int rc, i, num_reg = 0, num_irq; |
588 | struct resource *res, temp_res; | 127 | struct resource *res, temp_res; |
589 | 128 | ||
590 | /* First count how many resources are needed */ | 129 | dev = platform_device_alloc("", -1); |
591 | while (of_address_to_resource(np, num_reg, &temp_res) == 0) | ||
592 | num_reg++; | ||
593 | while (of_irq_to_resource(np, num_irq, &temp_res) != NO_IRQ) | ||
594 | num_irq++; | ||
595 | |||
596 | /* Allocate memory for both the struct device and the resource table */ | ||
597 | dev = kzalloc(sizeof(*dev) + (sizeof(*res) * (num_reg + num_irq)), | ||
598 | GFP_KERNEL); | ||
599 | if (!dev) | 130 | if (!dev) |
600 | return NULL; | 131 | return NULL; |
601 | res = (struct resource *) &dev[1]; | 132 | |
133 | /* count the io and irq resources */ | ||
134 | while (of_address_to_resource(np, num_reg, &temp_res) == 0) | ||
135 | num_reg++; | ||
136 | num_irq = of_irq_count(np); | ||
602 | 137 | ||
603 | /* Populate the resource table */ | 138 | /* Populate the resource table */ |
604 | if (num_irq || num_reg) { | 139 | if (num_irq || num_reg) { |
140 | res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); | ||
141 | if (!res) { | ||
142 | platform_device_put(dev); | ||
143 | return NULL; | ||
144 | } | ||
145 | |||
605 | dev->num_resources = num_reg + num_irq; | 146 | dev->num_resources = num_reg + num_irq; |
606 | dev->resource = res; | 147 | dev->resource = res; |
607 | for (i = 0; i < num_reg; i++, res++) { | 148 | for (i = 0; i < num_reg; i++, res++) { |
608 | rc = of_address_to_resource(np, i, res); | 149 | rc = of_address_to_resource(np, i, res); |
609 | WARN_ON(rc); | 150 | WARN_ON(rc); |
610 | } | 151 | } |
611 | for (i = 0; i < num_irq; i++, res++) { | 152 | WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); |
612 | rc = of_irq_to_resource(np, i, res); | ||
613 | WARN_ON(rc == NO_IRQ); | ||
614 | } | ||
615 | } | 153 | } |
616 | 154 | ||
617 | dev->dev.of_node = of_node_get(np); | 155 | dev->dev.of_node = of_node_get(np); |
@@ -619,7 +157,6 @@ struct platform_device *of_device_alloc(struct device_node *np, | |||
619 | dev->dev.dma_mask = &dev->archdata.dma_mask; | 157 | dev->dev.dma_mask = &dev->archdata.dma_mask; |
620 | #endif | 158 | #endif |
621 | dev->dev.parent = parent; | 159 | dev->dev.parent = parent; |
622 | dev->dev.release = of_release_dev; | ||
623 | 160 | ||
624 | if (bus_id) | 161 | if (bus_id) |
625 | dev_set_name(&dev->dev, "%s", bus_id); | 162 | dev_set_name(&dev->dev, "%s", bus_id); |
@@ -635,6 +172,9 @@ EXPORT_SYMBOL(of_device_alloc); | |||
635 | * @np: pointer to node to create device for | 172 | * @np: pointer to node to create device for |
636 | * @bus_id: name to assign device | 173 | * @bus_id: name to assign device |
637 | * @parent: Linux device model parent device. | 174 | * @parent: Linux device model parent device. |
175 | * | ||
176 | * Returns pointer to created platform device, or NULL if a device was not | ||
177 | * registered. Unavailable devices will not get registered. | ||
638 | */ | 178 | */ |
639 | struct platform_device *of_platform_device_create(struct device_node *np, | 179 | struct platform_device *of_platform_device_create(struct device_node *np, |
640 | const char *bus_id, | 180 | const char *bus_id, |
@@ -642,6 +182,9 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
642 | { | 182 | { |
643 | struct platform_device *dev; | 183 | struct platform_device *dev; |
644 | 184 | ||
185 | if (!of_device_is_available(np)) | ||
186 | return NULL; | ||
187 | |||
645 | dev = of_device_alloc(np, bus_id, parent); | 188 | dev = of_device_alloc(np, bus_id, parent); |
646 | if (!dev) | 189 | if (!dev) |
647 | return NULL; | 190 | return NULL; |
@@ -657,8 +200,8 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
657 | * to do such, possibly using a device notifier | 200 | * to do such, possibly using a device notifier |
658 | */ | 201 | */ |
659 | 202 | ||
660 | if (of_device_register(dev) != 0) { | 203 | if (of_device_add(dev) != 0) { |
661 | of_device_free(dev); | 204 | platform_device_put(dev); |
662 | return NULL; | 205 | return NULL; |
663 | } | 206 | } |
664 | 207 | ||
@@ -667,13 +210,16 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
667 | EXPORT_SYMBOL(of_platform_device_create); | 210 | EXPORT_SYMBOL(of_platform_device_create); |
668 | 211 | ||
669 | /** | 212 | /** |
670 | * of_platform_bus_create - Create an OF device for a bus node and all its | 213 | * of_platform_bus_create() - Create a device for a node and its children. |
671 | * children. Optionally recursively instantiate matching busses. | ||
672 | * @bus: device node of the bus to instantiate | 214 | * @bus: device node of the bus to instantiate |
673 | * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to | 215 | * @matches: match table for bus nodes |
674 | * disallow recursive creation of child busses | 216 | * disallow recursive creation of child buses |
217 | * @parent: parent for new device, or NULL for top level. | ||
218 | * | ||
219 | * Creates a platform_device for the provided device_node, and optionally | ||
220 | * recursively create devices for all the child nodes. | ||
675 | */ | 221 | */ |
676 | static int of_platform_bus_create(const struct device_node *bus, | 222 | static int of_platform_bus_create(struct device_node *bus, |
677 | const struct of_device_id *matches, | 223 | const struct of_device_id *matches, |
678 | struct device *parent) | 224 | struct device *parent) |
679 | { | 225 | { |
@@ -681,17 +227,13 @@ static int of_platform_bus_create(const struct device_node *bus, | |||
681 | struct platform_device *dev; | 227 | struct platform_device *dev; |
682 | int rc = 0; | 228 | int rc = 0; |
683 | 229 | ||
230 | dev = of_platform_device_create(bus, NULL, parent); | ||
231 | if (!dev || !of_match_node(matches, bus)) | ||
232 | return 0; | ||
233 | |||
684 | for_each_child_of_node(bus, child) { | 234 | for_each_child_of_node(bus, child) { |
685 | pr_debug(" create child: %s\n", child->full_name); | 235 | pr_debug(" create child: %s\n", child->full_name); |
686 | dev = of_platform_device_create(child, NULL, parent); | 236 | rc = of_platform_bus_create(child, matches, &dev->dev); |
687 | if (dev == NULL) | ||
688 | rc = -ENOMEM; | ||
689 | else if (!of_match_node(matches, child)) | ||
690 | continue; | ||
691 | if (rc == 0) { | ||
692 | pr_debug(" and sub busses\n"); | ||
693 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
694 | } | ||
695 | if (rc) { | 237 | if (rc) { |
696 | of_node_put(child); | 238 | of_node_put(child); |
697 | break; | 239 | break; |
@@ -701,9 +243,9 @@ static int of_platform_bus_create(const struct device_node *bus, | |||
701 | } | 243 | } |
702 | 244 | ||
703 | /** | 245 | /** |
704 | * of_platform_bus_probe - Probe the device-tree for platform busses | 246 | * of_platform_bus_probe() - Probe the device-tree for platform buses |
705 | * @root: parent of the first level to probe or NULL for the root of the tree | 247 | * @root: parent of the first level to probe or NULL for the root of the tree |
706 | * @matches: match table, NULL to use the default | 248 | * @matches: match table for bus nodes |
707 | * @parent: parent to hook devices from, NULL for toplevel | 249 | * @parent: parent to hook devices from, NULL for toplevel |
708 | * | 250 | * |
709 | * Note that children of the provided root are not instantiated as devices | 251 | * Note that children of the provided root are not instantiated as devices |
@@ -714,51 +256,26 @@ int of_platform_bus_probe(struct device_node *root, | |||
714 | struct device *parent) | 256 | struct device *parent) |
715 | { | 257 | { |
716 | struct device_node *child; | 258 | struct device_node *child; |
717 | struct platform_device *dev; | ||
718 | int rc = 0; | 259 | int rc = 0; |
719 | 260 | ||
720 | if (WARN_ON(!matches || matches == OF_NO_DEEP_PROBE)) | 261 | root = root ? of_node_get(root) : of_find_node_by_path("/"); |
721 | return -EINVAL; | 262 | if (!root) |
722 | if (root == NULL) | ||
723 | root = of_find_node_by_path("/"); | ||
724 | else | ||
725 | of_node_get(root); | ||
726 | if (root == NULL) | ||
727 | return -EINVAL; | 263 | return -EINVAL; |
728 | 264 | ||
729 | pr_debug("of_platform_bus_probe()\n"); | 265 | pr_debug("of_platform_bus_probe()\n"); |
730 | pr_debug(" starting at: %s\n", root->full_name); | 266 | pr_debug(" starting at: %s\n", root->full_name); |
731 | 267 | ||
732 | /* Do a self check of bus type, if there's a match, create | 268 | /* Do a self check of bus type, if there's a match, create children */ |
733 | * children | ||
734 | */ | ||
735 | if (of_match_node(matches, root)) { | 269 | if (of_match_node(matches, root)) { |
736 | pr_debug(" root match, create all sub devices\n"); | 270 | rc = of_platform_bus_create(root, matches, parent); |
737 | dev = of_platform_device_create(root, NULL, parent); | 271 | } else for_each_child_of_node(root, child) { |
738 | if (dev == NULL) { | ||
739 | rc = -ENOMEM; | ||
740 | goto bail; | ||
741 | } | ||
742 | pr_debug(" create all sub busses\n"); | ||
743 | rc = of_platform_bus_create(root, matches, &dev->dev); | ||
744 | goto bail; | ||
745 | } | ||
746 | for_each_child_of_node(root, child) { | ||
747 | if (!of_match_node(matches, child)) | 272 | if (!of_match_node(matches, child)) |
748 | continue; | 273 | continue; |
749 | 274 | rc = of_platform_bus_create(child, matches, parent); | |
750 | pr_debug(" match: %s\n", child->full_name); | 275 | if (rc) |
751 | dev = of_platform_device_create(child, NULL, parent); | ||
752 | if (dev == NULL) | ||
753 | rc = -ENOMEM; | ||
754 | else | ||
755 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
756 | if (rc) { | ||
757 | of_node_put(child); | ||
758 | break; | 276 | break; |
759 | } | ||
760 | } | 277 | } |
761 | bail: | 278 | |
762 | of_node_put(root); | 279 | of_node_put(root); |
763 | return rc; | 280 | return rc; |
764 | } | 281 | } |