aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_soc.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2007-07-20 16:26:15 -0400
committerPaul Mackerras <paulus@samba.org>2007-07-26 02:12:17 -0400
commitd13ae8620dfdedfa7e9ab6d1eec294adc0516065 (patch)
tree7cdf15b89eaee9cb7f40b47985f309755a202974 /arch/powerpc/sysdev/fsl_soc.c
parent56d6d1a73d9e5ddd9eb1a7baeeda30803ba44879 (diff)
[POWERPC] Add of_register_i2c_devices()
Scan the device tree for i2c devices, check their "compatible" property against a hard-coded table, and, if found, register with i2c boardinfo. This provides the infrastructure needed to find i2c devices in the device tree and register them with the i2c subsystem. This and the following commit let the linkstation work with the new i2c API and thus fix a regression. Signed-off-by: G. Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev/fsl_soc.c')
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 3289fab01e92..727453d3e8b9 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -305,6 +305,64 @@ err:
305 305
306arch_initcall(gfar_of_init); 306arch_initcall(gfar_of_init);
307 307
308#ifdef CONFIG_I2C_BOARDINFO
309#include <linux/i2c.h>
310struct i2c_driver_device {
311 char *of_device;
312 char *i2c_driver;
313 char *i2c_type;
314};
315
316static struct i2c_driver_device i2c_devices[] __initdata = {
317 {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},
318 {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
319 {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",},
320 {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
321};
322
323static int __init of_find_i2c_driver(struct device_node *node, struct i2c_board_info *info)
324{
325 int i;
326
327 for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
328 if (!of_device_is_compatible(node, i2c_devices[i].of_device))
329 continue;
330 strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN);
331 strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE);
332 return 0;
333 }
334 return -ENODEV;
335}
336
337static void __init of_register_i2c_devices(struct device_node *adap_node, int bus_num)
338{
339 struct device_node *node = NULL;
340
341 while ((node = of_get_next_child(adap_node, node))) {
342 struct i2c_board_info info;
343 const u32 *addr;
344 int len;
345
346 addr = of_get_property(node, "reg", &len);
347 if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
348 printk(KERN_WARNING "fsl_ioc.c: invalid i2c device entry\n");
349 continue;
350 }
351
352 info.irq = irq_of_parse_and_map(node, 0);
353 if (info.irq == NO_IRQ)
354 info.irq = -1;
355
356 if (of_find_i2c_driver(node, &info) < 0)
357 continue;
358
359 info.platform_data = NULL;
360 info.addr = *addr;
361
362 i2c_register_board_info(bus_num, &info, 1);
363 }
364}
365
308static int __init fsl_i2c_of_init(void) 366static int __init fsl_i2c_of_init(void)
309{ 367{
310 struct device_node *np; 368 struct device_node *np;
@@ -349,6 +407,8 @@ static int __init fsl_i2c_of_init(void)
349 fsl_i2c_platform_data)); 407 fsl_i2c_platform_data));
350 if (ret) 408 if (ret)
351 goto unreg; 409 goto unreg;
410
411 of_register_i2c_devices(np, i);
352 } 412 }
353 413
354 return 0; 414 return 0;
@@ -360,6 +420,7 @@ err:
360} 420}
361 421
362arch_initcall(fsl_i2c_of_init); 422arch_initcall(fsl_i2c_of_init);
423#endif
363 424
364#ifdef CONFIG_PPC_83xx 425#ifdef CONFIG_PPC_83xx
365static int __init mpc83xx_wdt_init(void) 426static int __init mpc83xx_wdt_init(void)