diff options
Diffstat (limited to 'arch/ppc/syslib/ppc_sys.c')
-rw-r--r-- | arch/ppc/syslib/ppc_sys.c | 179 |
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 | ||
20 | int (*ppc_sys_device_fixup) (struct platform_device * pdev); | 19 | int (*ppc_sys_device_fixup) (struct platform_device * pdev); |
21 | 20 | ||
22 | static int ppc_sys_inited; | 21 | static int ppc_sys_inited; |
22 | static int ppc_sys_func_inited; | ||
23 | |||
24 | static 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 | ||
24 | void __init identify_ppc_sys_by_id(u32 id) | 33 | void __init identify_ppc_sys_by_id(u32 id) |
25 | { | 34 | { |
@@ -38,13 +47,13 @@ void __init identify_ppc_sys_by_id(u32 id) | |||
38 | void __init identify_ppc_sys_by_name(char *name) | 47 | void __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 | |||
144 | void 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 | */ | ||
188 | void 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*/ | ||
216 | void 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 | |||
249 | void 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 | |||
262 | void 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 | |||
276 | void 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 | |||
287 | void 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 | |||
131 | static int __init ppc_sys_init(void) | 299 | static 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]); |