Commit d13ae862 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Paul Mackerras

[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: default avatarG. Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 56d6d1a7
...@@ -305,6 +305,64 @@ err: ...@@ -305,6 +305,64 @@ err:
arch_initcall(gfar_of_init); arch_initcall(gfar_of_init);
#ifdef CONFIG_I2C_BOARDINFO
#include <linux/i2c.h>
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) static int __init fsl_i2c_of_init(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -349,6 +407,8 @@ static int __init fsl_i2c_of_init(void) ...@@ -349,6 +407,8 @@ static int __init fsl_i2c_of_init(void)
fsl_i2c_platform_data)); fsl_i2c_platform_data));
if (ret) if (ret)
goto unreg; goto unreg;
of_register_i2c_devices(np, i);
} }
return 0; return 0;
...@@ -360,6 +420,7 @@ err: ...@@ -360,6 +420,7 @@ err:
} }
arch_initcall(fsl_i2c_of_init); arch_initcall(fsl_i2c_of_init);
#endif
#ifdef CONFIG_PPC_83xx #ifdef CONFIG_PPC_83xx
static int __init mpc83xx_wdt_init(void) static int __init mpc83xx_wdt_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment