aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/Kconfig5
-rw-r--r--drivers/of/Makefile1
-rw-r--r--drivers/of/address.c2
-rw-r--r--drivers/of/base.c4
-rw-r--r--drivers/of/device.c27
-rw-r--r--drivers/of/fdt.c2
-rw-r--r--drivers/of/irq.c39
-rw-r--r--drivers/of/of_i2c.c1
-rw-r--r--drivers/of/pdt.c276
-rw-r--r--drivers/of/platform.c34
10 files changed, 347 insertions, 44 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 6acbff389ab6..aa675ebd8eb3 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -4,7 +4,7 @@ config DTC
4config OF 4config OF
5 bool 5 bool
6 6
7menu "Flattened Device Tree and Open Firmware support" 7menu "Device Tree and Open Firmware support"
8 depends on OF 8 depends on OF
9 9
10config PROC_DEVICETREE 10config PROC_DEVICETREE
@@ -19,6 +19,9 @@ config OF_FLATTREE
19 bool 19 bool
20 select DTC 20 select DTC
21 21
22config OF_PROMTREE
23 bool
24
22config OF_DYNAMIC 25config OF_DYNAMIC
23 def_bool y 26 def_bool y
24 depends on PPC_OF 27 depends on PPC_OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 0052c405463a..7888155bea08 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,5 +1,6 @@
1obj-y = base.o 1obj-y = base.o
2obj-$(CONFIG_OF_FLATTREE) += fdt.o 2obj-$(CONFIG_OF_FLATTREE) += fdt.o
3obj-$(CONFIG_OF_PROMTREE) += pdt.o
3obj-$(CONFIG_OF_ADDRESS) += address.o 4obj-$(CONFIG_OF_ADDRESS) += address.o
4obj-$(CONFIG_OF_IRQ) += irq.o 5obj-$(CONFIG_OF_IRQ) += irq.o
5obj-$(CONFIG_OF_DEVICE) += device.o platform.o 6obj-$(CONFIG_OF_DEVICE) += device.o platform.o
diff --git a/drivers/of/address.c b/drivers/of/address.c
index fcadb726d4f9..3a1c7e70b192 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -163,7 +163,7 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
163const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, 163const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
164 unsigned int *flags) 164 unsigned int *flags)
165{ 165{
166 const u32 *prop; 166 const __be32 *prop;
167 unsigned int psize; 167 unsigned int psize;
168 struct device_node *parent; 168 struct device_node *parent;
169 struct of_bus *bus; 169 struct of_bus *bus;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index aa805250de76..710b53bfac6d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -33,7 +33,7 @@ DEFINE_RWLOCK(devtree_lock);
33 33
34int of_n_addr_cells(struct device_node *np) 34int 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
50int of_n_size_cells(struct device_node *np) 50int 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)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 92de0eb74aea..45d86530799f 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -81,29 +81,10 @@ struct device_attribute of_platform_device_attrs[] = {
81 __ATTR_NULL 81 __ATTR_NULL
82}; 82};
83 83
84/** 84int of_device_add(struct platform_device *ofdev)
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 */
91void 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}
99EXPORT_SYMBOL(of_release_dev);
100
101int of_device_register(struct platform_device *ofdev)
102{ 85{
103 BUG_ON(ofdev->dev.of_node == NULL); 86 BUG_ON(ofdev->dev.of_node == NULL);
104 87
105 device_initialize(&ofdev->dev);
106
107 /* name and id have to be set so that the platform bus doesn't get 88 /* name and id have to be set so that the platform bus doesn't get
108 * confused on matching */ 89 * confused on matching */
109 ofdev->name = dev_name(&ofdev->dev); 90 ofdev->name = dev_name(&ofdev->dev);
@@ -117,6 +98,12 @@ int of_device_register(struct platform_device *ofdev)
117 98
118 return device_add(&ofdev->dev); 99 return device_add(&ofdev->dev);
119} 100}
101
102int of_device_register(struct platform_device *pdev)
103{
104 device_initialize(&pdev->dev);
105 return of_device_add(pdev);
106}
120EXPORT_SYMBOL(of_device_register); 107EXPORT_SYMBOL(of_device_register);
121 108
122void of_device_unregister(struct platform_device *ofdev) 109void of_device_unregister(struct platform_device *ofdev)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65da5aec7552..c1360e02f921 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -533,8 +533,6 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
533 strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 533 strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
534#endif /* CONFIG_CMDLINE */ 534#endif /* CONFIG_CMDLINE */
535 535
536 early_init_dt_scan_chosen_arch(node);
537
538 pr_debug("Command line is: %s\n", cmd_line); 536 pr_debug("Command line is: %s\n", cmd_line);
539 537
540 /* break now */ 538 /* break now */
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 6e595e5a3977..75b0d3cb7676 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
@@ -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}
349EXPORT_SYMBOL_GPL(of_irq_to_resource); 354EXPORT_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 */
360int 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 */
378int 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..c85d3c7421fc 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>
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
new file mode 100644
index 000000000000..28295d0a50f6
--- /dev/null
+++ b/drivers/of/pdt.c
@@ -0,0 +1,276 @@
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
27static struct of_pdt_ops *of_pdt_prom_ops __initdata;
28
29void __initdata (*of_pdt_build_more)(struct device_node *dp,
30 struct device_node ***nextp);
31
32#if defined(CONFIG_SPARC)
33unsigned 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
39static inline const char *of_pdt_node_name(struct device_node *dp)
40{
41 return dp->path_component_name;
42}
43
44#else
45
46static inline void of_pdt_incr_unique_id(void *p) { }
47static inline void irq_trans_init(struct device_node *dp) { }
48
49static inline const char *of_pdt_node_name(struct device_node *dp)
50{
51 return dp->name;
52}
53
54#endif /* !CONFIG_SPARC */
55
56static struct property * __init of_pdt_build_one_prop(phandle node, char *prev,
57 char *special_name,
58 void *special_val,
59 int special_len)
60{
61 static struct property *tmp = NULL;
62 struct property *p;
63 int err;
64
65 if (tmp) {
66 p = tmp;
67 memset(p, 0, sizeof(*p) + 32);
68 tmp = NULL;
69 } else {
70 p = prom_early_alloc(sizeof(struct property) + 32);
71 of_pdt_incr_unique_id(p);
72 }
73
74 p->name = (char *) (p + 1);
75 if (special_name) {
76 strcpy(p->name, special_name);
77 p->length = special_len;
78 p->value = prom_early_alloc(special_len);
79 memcpy(p->value, special_val, special_len);
80 } else {
81 err = of_pdt_prom_ops->nextprop(node, prev, p->name);
82 if (err) {
83 tmp = p;
84 return NULL;
85 }
86 p->length = of_pdt_prom_ops->getproplen(node, p->name);
87 if (p->length <= 0) {
88 p->length = 0;
89 } else {
90 int len;
91
92 p->value = prom_early_alloc(p->length + 1);
93 len = of_pdt_prom_ops->getproperty(node, p->name,
94 p->value, p->length);
95 if (len <= 0)
96 p->length = 0;
97 ((unsigned char *)p->value)[p->length] = '\0';
98 }
99 }
100 return p;
101}
102
103static struct property * __init of_pdt_build_prop_list(phandle node)
104{
105 struct property *head, *tail;
106
107 head = tail = of_pdt_build_one_prop(node, NULL,
108 ".node", &node, sizeof(node));
109
110 tail->next = of_pdt_build_one_prop(node, NULL, NULL, NULL, 0);
111 tail = tail->next;
112 while(tail) {
113 tail->next = of_pdt_build_one_prop(node, tail->name,
114 NULL, NULL, 0);
115 tail = tail->next;
116 }
117
118 return head;
119}
120
121static char * __init of_pdt_get_one_property(phandle node, const char *name)
122{
123 char *buf = "<NULL>";
124 int len;
125
126 len = of_pdt_prom_ops->getproplen(node, name);
127 if (len > 0) {
128 buf = prom_early_alloc(len);
129 len = of_pdt_prom_ops->getproperty(node, name, buf, len);
130 }
131
132 return buf;
133}
134
135static char * __init of_pdt_try_pkg2path(phandle node)
136{
137 char *res, *buf = NULL;
138 int len;
139
140 if (!of_pdt_prom_ops->pkg2path)
141 return NULL;
142
143 if (of_pdt_prom_ops->pkg2path(node, buf, 0, &len))
144 return NULL;
145 buf = prom_early_alloc(len + 1);
146 if (of_pdt_prom_ops->pkg2path(node, buf, len, &len)) {
147 pr_err("%s: package-to-path failed\n", __func__);
148 return NULL;
149 }
150
151 res = strrchr(buf, '/');
152 if (!res) {
153 pr_err("%s: couldn't find / in %s\n", __func__, buf);
154 return NULL;
155 }
156 return res+1;
157}
158
159/*
160 * When fetching the node's name, first try using package-to-path; if
161 * that fails (either because the arch hasn't supplied a PROM callback,
162 * or some other random failure), fall back to just looking at the node's
163 * 'name' property.
164 */
165static char * __init of_pdt_build_name(phandle node)
166{
167 char *buf;
168
169 buf = of_pdt_try_pkg2path(node);
170 if (!buf)
171 buf = of_pdt_get_one_property(node, "name");
172
173 return buf;
174}
175
176static struct device_node * __init of_pdt_create_node(phandle node,
177 struct device_node *parent)
178{
179 struct device_node *dp;
180
181 if (!node)
182 return NULL;
183
184 dp = prom_early_alloc(sizeof(*dp));
185 of_pdt_incr_unique_id(dp);
186 dp->parent = parent;
187
188 kref_init(&dp->kref);
189
190 dp->name = of_pdt_build_name(node);
191 dp->type = of_pdt_get_one_property(node, "device_type");
192 dp->phandle = node;
193
194 dp->properties = of_pdt_build_prop_list(node);
195
196 irq_trans_init(dp);
197
198 return dp;
199}
200
201static char * __init of_pdt_build_full_name(struct device_node *dp)
202{
203 int len, ourlen, plen;
204 char *n;
205
206 plen = strlen(dp->parent->full_name);
207 ourlen = strlen(of_pdt_node_name(dp));
208 len = ourlen + plen + 2;
209
210 n = prom_early_alloc(len);
211 strcpy(n, dp->parent->full_name);
212 if (!of_node_is_root(dp->parent)) {
213 strcpy(n + plen, "/");
214 plen++;
215 }
216 strcpy(n + plen, of_pdt_node_name(dp));
217
218 return n;
219}
220
221static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
222 phandle node,
223 struct device_node ***nextp)
224{
225 struct device_node *ret = NULL, *prev_sibling = NULL;
226 struct device_node *dp;
227
228 while (1) {
229 dp = of_pdt_create_node(node, parent);
230 if (!dp)
231 break;
232
233 if (prev_sibling)
234 prev_sibling->sibling = dp;
235
236 if (!ret)
237 ret = dp;
238 prev_sibling = dp;
239
240 *(*nextp) = dp;
241 *nextp = &dp->allnext;
242
243#if defined(CONFIG_SPARC)
244 dp->path_component_name = build_path_component(dp);
245#endif
246 dp->full_name = of_pdt_build_full_name(dp);
247
248 dp->child = of_pdt_build_tree(dp,
249 of_pdt_prom_ops->getchild(node), nextp);
250
251 if (of_pdt_build_more)
252 of_pdt_build_more(dp, nextp);
253
254 node = of_pdt_prom_ops->getsibling(node);
255 }
256
257 return ret;
258}
259
260void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
261{
262 struct device_node **nextp;
263
264 BUG_ON(!ops);
265 of_pdt_prom_ops = ops;
266
267 allnodes = of_pdt_create_node(root_node, NULL);
268#if defined(CONFIG_SPARC)
269 allnodes->path_component_name = "";
270#endif
271 allnodes->full_name = "/";
272
273 nextp = &allnodes->allnext;
274 allnodes->child = of_pdt_build_tree(allnodes,
275 of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
276}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index bb72223c22ae..5b4a07f1220e 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -584,34 +584,33 @@ struct platform_device *of_device_alloc(struct device_node *np,
584 struct device *parent) 584 struct device *parent)
585{ 585{
586 struct platform_device *dev; 586 struct platform_device *dev;
587 int rc, i, num_reg = 0, num_irq = 0; 587 int rc, i, num_reg = 0, num_irq;
588 struct resource *res, temp_res; 588 struct resource *res, temp_res;
589 589
590 /* First count how many resources are needed */ 590 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) 591 if (!dev)
600 return NULL; 592 return NULL;
601 res = (struct resource *) &dev[1]; 593
594 /* count the io and irq resources */
595 while (of_address_to_resource(np, num_reg, &temp_res) == 0)
596 num_reg++;
597 num_irq = of_irq_count(np);
602 598
603 /* Populate the resource table */ 599 /* Populate the resource table */
604 if (num_irq || num_reg) { 600 if (num_irq || num_reg) {
601 res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
602 if (!res) {
603 platform_device_put(dev);
604 return NULL;
605 }
606
605 dev->num_resources = num_reg + num_irq; 607 dev->num_resources = num_reg + num_irq;
606 dev->resource = res; 608 dev->resource = res;
607 for (i = 0; i < num_reg; i++, res++) { 609 for (i = 0; i < num_reg; i++, res++) {
608 rc = of_address_to_resource(np, i, res); 610 rc = of_address_to_resource(np, i, res);
609 WARN_ON(rc); 611 WARN_ON(rc);
610 } 612 }
611 for (i = 0; i < num_irq; i++, res++) { 613 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 } 614 }
616 615
617 dev->dev.of_node = of_node_get(np); 616 dev->dev.of_node = of_node_get(np);
@@ -619,7 +618,6 @@ struct platform_device *of_device_alloc(struct device_node *np,
619 dev->dev.dma_mask = &dev->archdata.dma_mask; 618 dev->dev.dma_mask = &dev->archdata.dma_mask;
620#endif 619#endif
621 dev->dev.parent = parent; 620 dev->dev.parent = parent;
622 dev->dev.release = of_release_dev;
623 621
624 if (bus_id) 622 if (bus_id)
625 dev_set_name(&dev->dev, "%s", bus_id); 623 dev_set_name(&dev->dev, "%s", bus_id);
@@ -657,8 +655,8 @@ struct platform_device *of_platform_device_create(struct device_node *np,
657 * to do such, possibly using a device notifier 655 * to do such, possibly using a device notifier
658 */ 656 */
659 657
660 if (of_device_register(dev) != 0) { 658 if (of_device_add(dev) != 0) {
661 of_device_free(dev); 659 platform_device_put(dev);
662 return NULL; 660 return NULL;
663 } 661 }
664 662