aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/syslib/ppc_sys.c177
1 files changed, 174 insertions, 3 deletions
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index c0b93c4191ee..879783a41cfd 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -15,11 +15,22 @@
15 */ 15 */
16 16
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/bootmem.h>
18#include <asm/ppc_sys.h> 19#include <asm/ppc_sys.h>
19 20
20int (*ppc_sys_device_fixup) (struct platform_device * pdev); 21int (*ppc_sys_device_fixup) (struct platform_device * pdev);
21 22
22static int ppc_sys_inited; 23static int ppc_sys_inited;
24static int ppc_sys_func_inited;
25
26static const char *ppc_sys_func_names[] = {
27 [PPC_SYS_FUNC_DUMMY] = "dummy",
28 [PPC_SYS_FUNC_ETH] = "eth",
29 [PPC_SYS_FUNC_UART] = "uart",
30 [PPC_SYS_FUNC_HLDC] = "hldc",
31 [PPC_SYS_FUNC_USB] = "usb",
32 [PPC_SYS_FUNC_IRDA] = "irda",
33};
23 34
24void __init identify_ppc_sys_by_id(u32 id) 35void __init identify_ppc_sys_by_id(u32 id)
25{ 36{
@@ -38,13 +49,13 @@ void __init identify_ppc_sys_by_id(u32 id)
38void __init identify_ppc_sys_by_name(char *name) 49void __init identify_ppc_sys_by_name(char *name)
39{ 50{
40 unsigned int i = 0; 51 unsigned int i = 0;
41 while (ppc_sys_specs[i].ppc_sys_name[0]) 52 while (ppc_sys_specs[i].ppc_sys_name[0]) {
42 {
43 if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name)) 53 if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
44 break; 54 break;
45 i++; 55 i++;
46 } 56 }
47 cur_ppc_sys_spec = &ppc_sys_specs[i]; 57 cur_ppc_sys_spec = &ppc_sys_specs[i];
58
48 return; 59 return;
49} 60}
50 61
@@ -128,6 +139,165 @@ void ppc_sys_device_remove(enum ppc_sys_devices dev)
128 } 139 }
129} 140}
130 141
142/* Platform-notify mapping
143 * Helper function for BSP code to assign board-specific platfom-divice bits
144 */
145
146void platform_notify_map(const struct platform_notify_dev_map *map,
147 struct device *dev)
148{
149 struct platform_device *pdev;
150 int len, idx;
151 const char *s;
152
153 /* do nothing if no device or no bus_id */
154 if (!dev || !dev->bus_id)
155 return;
156
157 /* call per device map */
158 while (map->bus_id != NULL) {
159 idx = -1;
160 s = strrchr(dev->bus_id, '.');
161 if (s != NULL)
162 idx = (int)simple_strtol(s + 1, NULL, 10);
163 else
164 s = dev->bus_id;
165
166 len = s - dev->bus_id;
167
168 if (!strncmp(dev->bus_id, map->bus_id, len)) {
169 pdev = container_of(dev, struct platform_device, dev);
170 map->rtn(pdev, idx);
171 }
172 map++;
173 }
174}
175
176/*
177 Function assignment stuff.
178 Intended to work as follows:
179 the device name defined in foo_devices.c will be concatenated with :"func",
180 where func is string map of respective function from platfom_device_func enum
181
182 The PPC_SYS_FUNC_DUMMY function is intended to remove all assignments, making the device to appear
183 in platform bus with unmodified name.
184 */
185
186/*
187 Here we'll replace .name pointers with fixed-lenght strings
188 Hereby, this should be called *before* any func stuff triggeded.
189 */
190void ppc_sys_device_initfunc(void)
191{
192 int i;
193 const char *name;
194 static char new_names[NUM_PPC_SYS_DEVS][BUS_ID_SIZE];
195 enum ppc_sys_devices cur_dev;
196
197 /* If inited yet, do nothing */
198 if (ppc_sys_func_inited)
199 return;
200
201 for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
202 if ((cur_dev = cur_ppc_sys_spec->device_list[i]) < 0)
203 continue;
204
205 if (ppc_sys_platform_devices[cur_dev].name) {
206 /*backup name */
207 name = ppc_sys_platform_devices[cur_dev].name;
208 strlcpy(new_names[i], name, BUS_ID_SIZE);
209 ppc_sys_platform_devices[cur_dev].name = new_names[i];
210 }
211 }
212
213 ppc_sys_func_inited = 1;
214}
215
216/*The "engine" of the func stuff. Here we either concat specified function string description
217 to the name, or remove it if PPC_SYS_FUNC_DUMMY parameter is passed here*/
218void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
219 enum platform_device_func func)
220{
221 char *s;
222 char *name = (char *)ppc_sys_platform_devices[dev].name;
223 char tmp[BUS_ID_SIZE];
224
225 if (!ppc_sys_func_inited) {
226 printk(KERN_ERR "Unable to alter function - not inited!\n");
227 return;
228 }
229
230 if (ppc_sys_inited) {
231 platform_device_unregister(&ppc_sys_platform_devices[dev]);
232 }
233
234 if ((s = (char *)strchr(name, ':')) != NULL) { /* reassign */
235 /* Either change the name after ':' or remove func modifications */
236 if (func != PPC_SYS_FUNC_DUMMY)
237 strlcpy(s + 1, ppc_sys_func_names[func], BUS_ID_SIZE);
238 else
239 *s = 0;
240 } else if (func != PPC_SYS_FUNC_DUMMY) {
241 /* do assignment if it is not just "clear" request */
242 sprintf(tmp, "%s:%s", name, ppc_sys_func_names[func]);
243 strlcpy(name, tmp, BUS_ID_SIZE);
244 }
245
246 if (ppc_sys_inited) {
247 platform_device_register(&ppc_sys_platform_devices[dev]);
248 }
249}
250
251void ppc_sys_device_disable(enum ppc_sys_devices dev)
252{
253 BUG_ON(cur_ppc_sys_spec == NULL);
254
255 /*Check if it is enabled*/
256 if(!(cur_ppc_sys_spec->config[dev] & PPC_SYS_CONFIG_DISABLED)) {
257 if (ppc_sys_inited) {
258 platform_device_unregister(&ppc_sys_platform_devices[dev]);
259 }
260 cur_ppc_sys_spec->config[dev] |= PPC_SYS_CONFIG_DISABLED;
261 }
262}
263
264void ppc_sys_device_enable(enum ppc_sys_devices dev)
265{
266 BUG_ON(cur_ppc_sys_spec == NULL);
267
268 /*Check if it is disabled*/
269 if(cur_ppc_sys_spec->config[dev] & PPC_SYS_CONFIG_DISABLED) {
270 if (ppc_sys_inited) {
271 platform_device_register(&ppc_sys_platform_devices[dev]);
272 }
273 cur_ppc_sys_spec->config[dev] &= ~PPC_SYS_CONFIG_DISABLED;
274 }
275
276}
277
278void ppc_sys_device_enable_all(void)
279{
280 enum ppc_sys_devices cur_dev;
281 int i;
282
283 for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
284 cur_dev = cur_ppc_sys_spec->device_list[i];
285 ppc_sys_device_enable(cur_dev);
286 }
287}
288
289void ppc_sys_device_disable_all(void)
290{
291 enum ppc_sys_devices cur_dev;
292 int i;
293
294 for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
295 cur_dev = cur_ppc_sys_spec->device_list[i];
296 ppc_sys_device_disable(cur_dev);
297 }
298}
299
300
131static int __init ppc_sys_init(void) 301static int __init ppc_sys_init(void)
132{ 302{
133 unsigned int i, dev_id, ret = 0; 303 unsigned int i, dev_id, ret = 0;
@@ -136,7 +306,8 @@ static int __init ppc_sys_init(void)
136 306
137 for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { 307 for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
138 dev_id = cur_ppc_sys_spec->device_list[i]; 308 dev_id = cur_ppc_sys_spec->device_list[i];
139 if (dev_id != -1) { 309 if ((dev_id != -1) &&
310 !(cur_ppc_sys_spec->config[dev_id] & PPC_SYS_CONFIG_DISABLED)) {
140 if (ppc_sys_device_fixup != NULL) 311 if (ppc_sys_device_fixup != NULL)
141 ppc_sys_device_fixup(&ppc_sys_platform_devices 312 ppc_sys_device_fixup(&ppc_sys_platform_devices
142 [dev_id]); 313 [dev_id]);