diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/device.c | 84 | ||||
-rw-r--r-- | drivers/of/gpio.c | 38 | ||||
-rw-r--r-- | drivers/of/platform.c | 3 |
3 files changed, 72 insertions, 53 deletions
diff --git a/drivers/of/device.c b/drivers/of/device.c index 29681c4b700b..8a1d93a2bb81 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -48,16 +48,32 @@ void of_dev_put(struct of_device *dev) | |||
48 | } | 48 | } |
49 | EXPORT_SYMBOL(of_dev_put); | 49 | EXPORT_SYMBOL(of_dev_put); |
50 | 50 | ||
51 | static ssize_t dev_show_devspec(struct device *dev, | 51 | static ssize_t devspec_show(struct device *dev, |
52 | struct device_attribute *attr, char *buf) | 52 | struct device_attribute *attr, char *buf) |
53 | { | 53 | { |
54 | struct of_device *ofdev; | 54 | struct of_device *ofdev; |
55 | 55 | ||
56 | ofdev = to_of_device(dev); | 56 | ofdev = to_of_device(dev); |
57 | return sprintf(buf, "%s", ofdev->node->full_name); | 57 | return sprintf(buf, "%s\n", ofdev->node->full_name); |
58 | } | 58 | } |
59 | 59 | ||
60 | static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); | 60 | static ssize_t modalias_show(struct device *dev, |
61 | struct device_attribute *attr, char *buf) | ||
62 | { | ||
63 | struct of_device *ofdev = to_of_device(dev); | ||
64 | ssize_t len = 0; | ||
65 | |||
66 | len = of_device_get_modalias(ofdev, buf, PAGE_SIZE - 2); | ||
67 | buf[len] = '\n'; | ||
68 | buf[len+1] = 0; | ||
69 | return len+1; | ||
70 | } | ||
71 | |||
72 | struct device_attribute of_platform_device_attrs[] = { | ||
73 | __ATTR_RO(devspec), | ||
74 | __ATTR_RO(modalias), | ||
75 | __ATTR_NULL | ||
76 | }; | ||
61 | 77 | ||
62 | /** | 78 | /** |
63 | * of_release_dev - free an of device structure when all users of it are finished. | 79 | * of_release_dev - free an of device structure when all users of it are finished. |
@@ -78,25 +94,61 @@ EXPORT_SYMBOL(of_release_dev); | |||
78 | 94 | ||
79 | int of_device_register(struct of_device *ofdev) | 95 | int of_device_register(struct of_device *ofdev) |
80 | { | 96 | { |
81 | int rc; | ||
82 | |||
83 | BUG_ON(ofdev->node == NULL); | 97 | BUG_ON(ofdev->node == NULL); |
84 | 98 | return device_register(&ofdev->dev); | |
85 | rc = device_register(&ofdev->dev); | ||
86 | if (rc) | ||
87 | return rc; | ||
88 | |||
89 | rc = device_create_file(&ofdev->dev, &dev_attr_devspec); | ||
90 | if (rc) | ||
91 | device_unregister(&ofdev->dev); | ||
92 | |||
93 | return rc; | ||
94 | } | 99 | } |
95 | EXPORT_SYMBOL(of_device_register); | 100 | EXPORT_SYMBOL(of_device_register); |
96 | 101 | ||
97 | void of_device_unregister(struct of_device *ofdev) | 102 | void of_device_unregister(struct of_device *ofdev) |
98 | { | 103 | { |
99 | device_remove_file(&ofdev->dev, &dev_attr_devspec); | ||
100 | device_unregister(&ofdev->dev); | 104 | device_unregister(&ofdev->dev); |
101 | } | 105 | } |
102 | EXPORT_SYMBOL(of_device_unregister); | 106 | EXPORT_SYMBOL(of_device_unregister); |
107 | |||
108 | ssize_t of_device_get_modalias(struct of_device *ofdev, | ||
109 | char *str, ssize_t len) | ||
110 | { | ||
111 | const char *compat; | ||
112 | int cplen, i; | ||
113 | ssize_t tsize, csize, repend; | ||
114 | |||
115 | /* Name & Type */ | ||
116 | csize = snprintf(str, len, "of:N%sT%s", | ||
117 | ofdev->node->name, ofdev->node->type); | ||
118 | |||
119 | /* Get compatible property if any */ | ||
120 | compat = of_get_property(ofdev->node, "compatible", &cplen); | ||
121 | if (!compat) | ||
122 | return csize; | ||
123 | |||
124 | /* Find true end (we tolerate multiple \0 at the end */ | ||
125 | for (i = (cplen - 1); i >= 0 && !compat[i]; i--) | ||
126 | cplen--; | ||
127 | if (!cplen) | ||
128 | return csize; | ||
129 | cplen++; | ||
130 | |||
131 | /* Check space (need cplen+1 chars including final \0) */ | ||
132 | tsize = csize + cplen; | ||
133 | repend = tsize; | ||
134 | |||
135 | if (csize >= len) /* @ the limit, all is already filled */ | ||
136 | return tsize; | ||
137 | |||
138 | if (tsize >= len) { /* limit compat list */ | ||
139 | cplen = len - csize - 1; | ||
140 | repend = len; | ||
141 | } | ||
142 | |||
143 | /* Copy and do char replacement */ | ||
144 | memcpy(&str[csize + 1], compat, cplen); | ||
145 | for (i = csize; i < repend; i++) { | ||
146 | char c = str[i]; | ||
147 | if (c == '\0') | ||
148 | str[i] = 'C'; | ||
149 | else if (c == ' ') | ||
150 | str[i] = '_'; | ||
151 | } | ||
152 | |||
153 | return tsize; | ||
154 | } | ||
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 000681e98f2c..1c9cab844f10 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c | |||
@@ -137,38 +137,6 @@ int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, | |||
137 | } | 137 | } |
138 | EXPORT_SYMBOL(of_gpio_simple_xlate); | 138 | EXPORT_SYMBOL(of_gpio_simple_xlate); |
139 | 139 | ||
140 | /* Should be sufficient for now, later we'll use dynamic bases. */ | ||
141 | #if defined(CONFIG_PPC32) || defined(CONFIG_SPARC32) | ||
142 | #define GPIOS_PER_CHIP 32 | ||
143 | #else | ||
144 | #define GPIOS_PER_CHIP 64 | ||
145 | #endif | ||
146 | |||
147 | static int of_get_gpiochip_base(struct device_node *np) | ||
148 | { | ||
149 | struct device_node *gc = NULL; | ||
150 | int gpiochip_base = 0; | ||
151 | |||
152 | while ((gc = of_find_all_nodes(gc))) { | ||
153 | if (!of_get_property(gc, "gpio-controller", NULL)) | ||
154 | continue; | ||
155 | |||
156 | if (gc != np) { | ||
157 | gpiochip_base += GPIOS_PER_CHIP; | ||
158 | continue; | ||
159 | } | ||
160 | |||
161 | of_node_put(gc); | ||
162 | |||
163 | if (gpiochip_base >= ARCH_NR_GPIOS) | ||
164 | return -ENOSPC; | ||
165 | |||
166 | return gpiochip_base; | ||
167 | } | ||
168 | |||
169 | return -ENOENT; | ||
170 | } | ||
171 | |||
172 | /** | 140 | /** |
173 | * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank) | 141 | * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank) |
174 | * @np: device node of the GPIO chip | 142 | * @np: device node of the GPIO chip |
@@ -205,11 +173,7 @@ int of_mm_gpiochip_add(struct device_node *np, | |||
205 | if (!mm_gc->regs) | 173 | if (!mm_gc->regs) |
206 | goto err1; | 174 | goto err1; |
207 | 175 | ||
208 | gc->base = of_get_gpiochip_base(np); | 176 | gc->base = -1; |
209 | if (gc->base < 0) { | ||
210 | ret = gc->base; | ||
211 | goto err1; | ||
212 | } | ||
213 | 177 | ||
214 | if (!of_gc->xlate) | 178 | if (!of_gc->xlate) |
215 | of_gc->xlate = of_gpio_simple_xlate; | 179 | of_gc->xlate = of_gpio_simple_xlate; |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index ca09a63a64db..298de0f95d70 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/of_device.h> | 17 | #include <linux/of_device.h> |
18 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
19 | 19 | ||
20 | extern struct device_attribute of_platform_device_attrs[]; | ||
21 | |||
20 | static int of_platform_bus_match(struct device *dev, struct device_driver *drv) | 22 | static int of_platform_bus_match(struct device *dev, struct device_driver *drv) |
21 | { | 23 | { |
22 | struct of_device *of_dev = to_of_device(dev); | 24 | struct of_device *of_dev = to_of_device(dev); |
@@ -103,6 +105,7 @@ int of_bus_type_init(struct bus_type *bus, const char *name) | |||
103 | bus->suspend = of_platform_device_suspend; | 105 | bus->suspend = of_platform_device_suspend; |
104 | bus->resume = of_platform_device_resume; | 106 | bus->resume = of_platform_device_resume; |
105 | bus->shutdown = of_platform_device_shutdown; | 107 | bus->shutdown = of_platform_device_shutdown; |
108 | bus->dev_attrs = of_platform_device_attrs; | ||
106 | return bus_register(bus); | 109 | return bus_register(bus); |
107 | } | 110 | } |
108 | 111 | ||