diff options
Diffstat (limited to 'arch/ppc')
-rw-r--r-- | arch/ppc/syslib/ppc_sys.c | 177 |
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 | ||
20 | int (*ppc_sys_device_fixup) (struct platform_device * pdev); | 21 | int (*ppc_sys_device_fixup) (struct platform_device * pdev); |
21 | 22 | ||
22 | static int ppc_sys_inited; | 23 | static int ppc_sys_inited; |
24 | static int ppc_sys_func_inited; | ||
25 | |||
26 | static 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 | ||
24 | void __init identify_ppc_sys_by_id(u32 id) | 35 | void __init identify_ppc_sys_by_id(u32 id) |
25 | { | 36 | { |
@@ -38,13 +49,13 @@ void __init identify_ppc_sys_by_id(u32 id) | |||
38 | void __init identify_ppc_sys_by_name(char *name) | 49 | void __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 | |||
146 | void 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 | */ | ||
190 | void 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*/ | ||
218 | void 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 | |||
251 | void 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 | |||
264 | void 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 | |||
278 | void 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 | |||
289 | void 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 | |||
131 | static int __init ppc_sys_init(void) | 301 | static 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]); |