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