aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/of_device.c80
-rw-r--r--arch/powerpc/kernel/of_platform.c70
-rw-r--r--include/asm-powerpc/of_device.h4
-rw-r--r--include/linux/of_device.h5
4 files changed, 91 insertions, 68 deletions
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 8f3db32fac8b..3388ad619996 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -7,8 +7,88 @@
7#include <linux/slab.h> 7#include <linux/slab.h>
8 8
9#include <asm/errno.h> 9#include <asm/errno.h>
10#include <asm/dcr.h>
10#include <asm/of_device.h> 11#include <asm/of_device.h>
11 12
13static void of_device_make_bus_id(struct of_device *dev)
14{
15 static atomic_t bus_no_reg_magic;
16 struct device_node *node = dev->node;
17 char *name = dev->dev.bus_id;
18 const u32 *reg;
19 u64 addr;
20 int magic;
21
22 /*
23 * If it's a DCR based device, use 'd' for native DCRs
24 * and 'D' for MMIO DCRs.
25 */
26#ifdef CONFIG_PPC_DCR
27 reg = of_get_property(node, "dcr-reg", NULL);
28 if (reg) {
29#ifdef CONFIG_PPC_DCR_NATIVE
30 snprintf(name, BUS_ID_SIZE, "d%x.%s",
31 *reg, node->name);
32#else /* CONFIG_PPC_DCR_NATIVE */
33 addr = of_translate_dcr_address(node, *reg, NULL);
34 if (addr != OF_BAD_ADDR) {
35 snprintf(name, BUS_ID_SIZE,
36 "D%llx.%s", (unsigned long long)addr,
37 node->name);
38 return;
39 }
40#endif /* !CONFIG_PPC_DCR_NATIVE */
41 }
42#endif /* CONFIG_PPC_DCR */
43
44 /*
45 * For MMIO, get the physical address
46 */
47 reg = of_get_property(node, "reg", NULL);
48 if (reg) {
49 addr = of_translate_address(node, reg);
50 if (addr != OF_BAD_ADDR) {
51 snprintf(name, BUS_ID_SIZE,
52 "%llx.%s", (unsigned long long)addr,
53 node->name);
54 return;
55 }
56 }
57
58 /*
59 * No BusID, use the node name and add a globally incremented
60 * counter (and pray...)
61 */
62 magic = atomic_add_return(1, &bus_no_reg_magic);
63 snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
64}
65
66struct of_device *of_device_alloc(struct device_node *np,
67 const char *bus_id,
68 struct device *parent)
69{
70 struct of_device *dev;
71
72 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
73 if (!dev)
74 return NULL;
75
76 dev->node = of_node_get(np);
77 dev->dev.dma_mask = &dev->dma_mask;
78 dev->dev.parent = parent;
79 dev->dev.release = of_release_dev;
80 dev->dev.archdata.of_node = np;
81 dev->dev.archdata.numa_node = of_node_to_nid(np);
82
83 if (bus_id)
84 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
85 else
86 of_device_make_bus_id(dev);
87
88 return dev;
89}
90EXPORT_SYMBOL(of_device_alloc);
91
12ssize_t of_device_get_modalias(struct of_device *ofdev, 92ssize_t of_device_get_modalias(struct of_device *ofdev,
13 char *str, ssize_t len) 93 char *str, ssize_t len)
14{ 94{
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index eca8ccc3fa12..aeaa20268ce2 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -23,7 +23,6 @@
23#include <linux/of_platform.h> 23#include <linux/of_platform.h>
24 24
25#include <asm/errno.h> 25#include <asm/errno.h>
26#include <asm/dcr.h>
27#include <asm/topology.h> 26#include <asm/topology.h>
28#include <asm/pci-bridge.h> 27#include <asm/pci-bridge.h>
29#include <asm/ppc-pci.h> 28#include <asm/ppc-pci.h>
@@ -53,8 +52,6 @@ static struct of_device_id of_default_bus_ids[] = {
53 {}, 52 {},
54}; 53};
55 54
56static atomic_t bus_no_reg_magic;
57
58struct bus_type of_platform_bus_type = { 55struct bus_type of_platform_bus_type = {
59 .uevent = of_device_uevent, 56 .uevent = of_device_uevent,
60}; 57};
@@ -87,89 +84,26 @@ void of_unregister_platform_driver(struct of_platform_driver *drv)
87} 84}
88EXPORT_SYMBOL(of_unregister_platform_driver); 85EXPORT_SYMBOL(of_unregister_platform_driver);
89 86
90static void of_platform_make_bus_id(struct of_device *dev)
91{
92 struct device_node *node = dev->node;
93 char *name = dev->dev.bus_id;
94 const u32 *reg;
95 u64 addr;
96 int magic;
97
98 /*
99 * If it's a DCR based device, use 'd' for native DCRs
100 * and 'D' for MMIO DCRs.
101 */
102#ifdef CONFIG_PPC_DCR
103 reg = of_get_property(node, "dcr-reg", NULL);
104 if (reg) {
105#ifdef CONFIG_PPC_DCR_NATIVE
106 snprintf(name, BUS_ID_SIZE, "d%x.%s",
107 *reg, node->name);
108#else /* CONFIG_PPC_DCR_NATIVE */
109 addr = of_translate_dcr_address(node, *reg, NULL);
110 if (addr != OF_BAD_ADDR) {
111 snprintf(name, BUS_ID_SIZE,
112 "D%llx.%s", (unsigned long long)addr,
113 node->name);
114 return;
115 }
116#endif /* !CONFIG_PPC_DCR_NATIVE */
117 }
118#endif /* CONFIG_PPC_DCR */
119
120 /*
121 * For MMIO, get the physical address
122 */
123 reg = of_get_property(node, "reg", NULL);
124 if (reg) {
125 addr = of_translate_address(node, reg);
126 if (addr != OF_BAD_ADDR) {
127 snprintf(name, BUS_ID_SIZE,
128 "%llx.%s", (unsigned long long)addr,
129 node->name);
130 return;
131 }
132 }
133
134 /*
135 * No BusID, use the node name and add a globally incremented
136 * counter (and pray...)
137 */
138 magic = atomic_add_return(1, &bus_no_reg_magic);
139 snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
140}
141
142struct of_device* of_platform_device_create(struct device_node *np, 87struct of_device* of_platform_device_create(struct device_node *np,
143 const char *bus_id, 88 const char *bus_id,
144 struct device *parent) 89 struct device *parent)
145{ 90{
146 struct of_device *dev; 91 struct of_device *dev;
147 92
148 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 93 dev = of_device_alloc(np, bus_id, parent);
149 if (!dev) 94 if (!dev)
150 return NULL; 95 return NULL;
151 96
152 dev->node = of_node_get(np);
153 dev->dma_mask = 0xffffffffUL; 97 dev->dma_mask = 0xffffffffUL;
154 dev->dev.dma_mask = &dev->dma_mask;
155 dev->dev.parent = parent;
156 dev->dev.bus = &of_platform_bus_type; 98 dev->dev.bus = &of_platform_bus_type;
157 dev->dev.release = of_release_dev;
158 dev->dev.archdata.of_node = np;
159 dev->dev.archdata.numa_node = of_node_to_nid(np);
160 99
161 /* We do not fill the DMA ops for platform devices by default. 100 /* We do not fill the DMA ops for platform devices by default.
162 * This is currently the responsibility of the platform code 101 * This is currently the responsibility of the platform code
163 * to do such, possibly using a device notifier 102 * to do such, possibly using a device notifier
164 */ 103 */
165 104
166 if (bus_id)
167 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
168 else
169 of_platform_make_bus_id(dev);
170
171 if (of_device_register(dev) != 0) { 105 if (of_device_register(dev) != 0) {
172 kfree(dev); 106 of_device_free(dev);
173 return NULL; 107 return NULL;
174 } 108 }
175 109
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index 93262f2546ad..6526e139a463 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -17,6 +17,10 @@ struct of_device
17 struct device dev; /* Generic device interface */ 17 struct device dev; /* Generic device interface */
18}; 18};
19 19
20extern struct of_device *of_device_alloc(struct device_node *np,
21 const char *bus_id,
22 struct device *parent);
23
20extern ssize_t of_device_get_modalias(struct of_device *ofdev, 24extern ssize_t of_device_get_modalias(struct of_device *ofdev,
21 char *str, ssize_t len); 25 char *str, ssize_t len);
22extern int of_device_uevent(struct device *dev, 26extern int of_device_uevent(struct device *dev,
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 91bf84b9d144..212bffb2b174 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev);
22extern void of_device_unregister(struct of_device *ofdev); 22extern void of_device_unregister(struct of_device *ofdev);
23extern void of_release_dev(struct device *dev); 23extern void of_release_dev(struct device *dev);
24 24
25static inline void of_device_free(struct of_device *dev)
26{
27 of_release_dev(&dev->dev);
28}
29
25#endif /* __KERNEL__ */ 30#endif /* __KERNEL__ */
26#endif /* _LINUX_OF_DEVICE_H */ 31#endif /* _LINUX_OF_DEVICE_H */