Thread (34 messages) 34 messages, 7 authors, 2007-08-16

Re: [PATCH] powerpc: Add of_register_i2c_devices()

From: Guennadi Liakhovetski <hidden>
Date: 2007-07-19 22:08:06
Subsystem: linux for powerpc (32-bit and 64-bit), the rest · Maintainers: Madhavan Srinivasan, Michael Ellerman, Linus Torvalds

On Thu, 19 Jul 2007, Segher Boessenkool wrote:
quoted
quoted
Your device is an rs5c372b.  So, that's what you put in
your device tree.  Simple so far, right?

Now some OF I2C code goes looking for IIC devices in the
device tree.  It finds this thing, and from a table or
something it derives that it has to tell the kernel I2C
layer this is an "rtc-rs5c372".  [It would be nicer if it
could just instantiate the correct driver directly, but
if that's how the Linux I2C layer works, so be it].

No change in the I2C "core" needed, just an OF "compatible"
matching thing like is needed *everywhere else* too.
How about the patch below?
Looks good.  It should later be moved to a more generic
I2C OF matching layer, but fine for now.  Thanks!

You might want to put vendor names in the "compatible"
entries, dunno though, maybe these are "cross-vendor"
ICs?
You mean like

	compatible = "ricoh,rs5c372a"

etc? With this change, plus __init(data) attributes for functions and the 
array, attached below is version 2 of the patch. Corresponding 
modifications to the kurobox*.dts will follow separately.

Thanks
Guennadi
---
Guennadi Liakhovetski

Scan the device tree for i2c devices, check their "compatible" property 
against a hard-coded table, and, if found, register with i2c boardinfo.

Signed-off-by: G. Liakhovetski <redacted>
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 3289fab..e07d031 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -305,6 +305,62 @@ err:
 
 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 > 0xffff)
+			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 +405,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 +418,7 @@ err:
 }
 
 arch_initcall(fsl_i2c_of_init);
+#endif
 
 #ifdef CONFIG_PPC_83xx
 static int __init mpc83xx_wdt_init(void)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help