From d13ae8620dfdedfa7e9ab6d1eec294adc0516065 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 21 Jul 2007 06:26:15 +1000 Subject: [PATCH] [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 Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/fsl_soc.c | 61 +++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 3289fab01e..727453d3e8 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -305,6 +305,64 @@ err: arch_initcall(gfar_of_init); +#ifdef CONFIG_I2C_BOARDINFO +#include +struct i2c_driver_device { + char *of_device; + char *i2c_driver; + char *i2c_type; +}; + +static struct i2c_driver_device i2c_devices[] __initdata = { + {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",}, + {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",}, + {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",}, + {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",}, +}; + +static int __init of_find_i2c_driver(struct device_node *node, struct i2c_board_info *info) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { + if (!of_device_is_compatible(node, i2c_devices[i].of_device)) + continue; + strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN); + strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE); + return 0; + } + return -ENODEV; +} + +static void __init of_register_i2c_devices(struct device_node *adap_node, int bus_num) +{ + struct device_node *node = NULL; + + while ((node = of_get_next_child(adap_node, node))) { + struct i2c_board_info info; + const u32 *addr; + int len; + + addr = of_get_property(node, "reg", &len); + if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) { + printk(KERN_WARNING "fsl_ioc.c: invalid i2c device entry\n"); + continue; + } + + info.irq = irq_of_parse_and_map(node, 0); + if (info.irq == NO_IRQ) + info.irq = -1; + + if (of_find_i2c_driver(node, &info) < 0) + continue; + + info.platform_data = NULL; + info.addr = *addr; + + i2c_register_board_info(bus_num, &info, 1); + } +} + static int __init fsl_i2c_of_init(void) { struct device_node *np; @@ -349,6 +407,8 @@ static int __init fsl_i2c_of_init(void) fsl_i2c_platform_data)); if (ret) goto unreg; + + of_register_i2c_devices(np, i); } return 0; @@ -360,6 +420,7 @@ err: } arch_initcall(fsl_i2c_of_init); +#endif #ifdef CONFIG_PPC_83xx static int __init mpc83xx_wdt_init(void) -- 2.39.5