Skip to contentSkip to conversation

Series to add device tree naming to i2c

PATCH NAK Jon Smirl 2 participants 10 messages Dec 18, 2007

Subsystems (6)
lore
Share & tools
lore

Jon Smirl

author
#0 lore raw

cover Series to add device tree naming to i2c

Another rework of the i2c for powerpc device tree patch. This version implements standard alias naming only on the powerpc platform and only for the device tree names. The old naming mechanism of i2c_client.name,driver_name is left in place and not changed for non-powerpc platforms. This patch is fully capable of dynamically loading the i2c modules. You can modprobe in the i2c-mpc driver and the i2c modules described in the device tree will be automatically loaded. Modules also work if compiled in.

The follow on patch to module-init-tools is also needed since the i2c subsystem has never implemented dynamic loading.

Since the i2c-mpc driver also supports the ppc architecture the i2c-mpc driver was copied to i2c-mpc-ppc before changes were made. The i2c-mpc-ppc driver should be deleted in six months when the rest of the ppc architecture is removed.

The following series implements standard linux module aliasing for i2c modules on arch=powerpc. It then converts the mpc i2c driver from being a platform driver to an open firmware one. I2C device names are picked up from the device tree. Module aliasing is used to translate from device tree names into to linux kernel names. Several i2c drivers are updated to use the new aliasing.

--
Jon Smirl
[email protected]

author
#1 lore raw

PATCH 1/7 Copy mpc-i2c to preserve support for ARCH=ppc and allow changes on ARCH=powerpc

Temporarily copy the mpc-i2c driver to continue support for the ppc architecture until it is removed in mid-2008. This file should be deleted as part of ppc's final removal.

---

 arch/ppc/configs/TQM8540_defconfig     |    2 
 arch/ppc/configs/TQM8541_defconfig     |    2 
 arch/ppc/configs/TQM8555_defconfig     |    2 
 arch/ppc/configs/TQM8560_defconfig     |    2 
 arch/ppc/configs/mpc834x_sys_defconfig |    2 
 arch/ppc/configs/mpc8540_ads_defconfig |    2 
 arch/ppc/configs/mpc8548_cds_defconfig |    2 
 arch/ppc/configs/mpc8555_cds_defconfig |    2 
 arch/ppc/configs/mpc8560_ads_defconfig |    2 
 drivers/i2c/busses/Kconfig             |   16 +
 drivers/i2c/busses/Makefile            |    1 
 drivers/i2c/busses/i2c-mpc-ppc.c       |  418 ++++++++++++++++++++++++++++++++
 12 files changed, 443 insertions(+), 10 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-mpc-ppc.c
arch/ppc/configs/TQM8540_defconfig +1 -1
index f33f0e7..7098ed0 100644
@@ -684,7 +684,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
arch/ppc/configs/TQM8541_defconfig +1 -1
index e00cd62..2137d01 100644
@@ -687,7 +687,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_MPC8260 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
arch/ppc/configs/TQM8555_defconfig +1 -1
index 43a0d9d..f2317b6 100644
@@ -687,7 +687,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
arch/ppc/configs/TQM8560_defconfig +1 -1
index a814d17..6c19121 100644
@@ -694,7 +694,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_MPC8260 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
arch/ppc/configs/mpc834x_sys_defconfig +1 -1
index d90c8a7..cd568d2 100644
@@ -562,7 +562,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
arch/ppc/configs/mpc8540_ads_defconfig +1 -1
index bf676eb..5819835 100644
@@ -452,7 +452,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PIIX4 is not set
arch/ppc/configs/mpc8548_cds_defconfig +1 -1
index f36fc5d..e5b5071 100644
@@ -413,7 +413,7 @@ CONFIG_I2C_CHARDEV=y
 #
 # I2C Hardware Bus support
 #
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PCA_ISA is not set
 
arch/ppc/configs/mpc8555_cds_defconfig +1 -1
index 4f1e320..08dbab0 100644
@@ -518,7 +518,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
arch/ppc/configs/mpc8560_ads_defconfig +1 -1
index f12d48f..0e0080b 100644
@@ -489,7 +489,7 @@ CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_MPC=y
+CONFIG_I2C_MPC_PPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
drivers/i2c/busses/Kconfig +15 -1
index c466c6c..c5ad557 100644
@@ -301,7 +301,7 @@ config I2C_POWERMAC
 
 config I2C_MPC
 	tristate "MPC107/824x/85xx/52xx/86xx"
-	depends on PPC32
+	depends on PPC32 && PPC_MERGE
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
@@ -311,6 +311,20 @@ config I2C_MPC
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
 
+config I2C_MPC_PPC
+	tristate "MPC107/824x/85xx/52xx/86xx"
+	depends on PPC32 && !PPC_MERGE
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
+	  MPC85xx/MPC8641 family processors. The driver may also work on 52xx
+	  family processors, though interrupts are known not to work.
+ 
+	  This version of the driver is scheduled for deletion with the PPC architecture.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mpc.
+
 config I2C_NFORCE2
 	tristate "Nvidia nForce2, nForce3 and nForce4"
 	depends on PCI
drivers/i2c/busses/Makefile +1 -0
index 81d43c2..b7fe095 100644
@@ -23,6 +23,7 @@ obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
 obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
 obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
+obj-$(CONFIG_I2C_MPC_PPC)	+= i2c-mpc-ppc.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
drivers/i2c/busses/i2c-mpc-ppc.c new file +418 -0

418 lines not on this page · raw message

#2 lore raw

Re: [PATCH 1/7] Copy mpc-i2c to preserve support for ARCH=ppc and allow changes on ARCH=powerpc

Quoted 23 lines · Jon Smirl

Temporarily copy the mpc-i2c driver to continue support for the ppc architecture until it is removed in mid-2008. This file should be deleted as part of ppc's final removal.

---

arch/ppc/configs/TQM8540_defconfig     |    2
arch/ppc/configs/TQM8541_defconfig     |    2
arch/ppc/configs/TQM8555_defconfig     |    2
arch/ppc/configs/TQM8560_defconfig     |    2
arch/ppc/configs/mpc834x_sys_defconfig |    2
arch/ppc/configs/mpc8540_ads_defconfig |    2
arch/ppc/configs/mpc8548_cds_defconfig |    2
arch/ppc/configs/mpc8555_cds_defconfig |    2
arch/ppc/configs/mpc8560_ads_defconfig |    2
drivers/i2c/busses/Kconfig             |   16 +
drivers/i2c/busses/Makefile            |    1
drivers/i2c/busses/i2c-mpc-ppc.c       |  418 +++++++++++++++++++++++ 
+++++++++
12 files changed, 443 insertions(+), 10 deletions(-)
Quoted 1 line

create mode 100644 drivers/i2c/busses/i2c-mpc-ppc.c

Nak.

Just ifdef the probe functionality in i2c-mpc.c based on CONFIG_PPC_MERGE. Your patch set shows the reason you should do this. You provide fixes to the error path handling, but only for i2c-mpc.c and not i2c-mpc-ppc.c.

- k

author
#3 lore raw

PATCH 2/7 Implement module aliasing for i2c to translate from device tree names

In reply to Jon Smirl

This patch allows new style i2c chip drivers to have alias names using the official kernel aliasing system and MODULE_DEVICE_TABLE(). I've tested it on PowerPC and x86. This change is required for PowerPC device tree support.

---

 drivers/i2c/i2c-core.c          |   32 ++++++++++++++++++++++++++------
 include/linux/i2c.h             |    9 ++++-----
 include/linux/mod_devicetable.h |   20 ++++++++++++++++++++
 scripts/mod/file2alias.c        |   19 +++++++++++++++++++
 4 files changed, 69 insertions(+), 11 deletions(-)
drivers/i2c/i2c-core.c +26 -6
index b5e13e4..fce06fd 100644
@@ -47,10 +47,25 @@ static DEFINE_IDR(i2c_adapter_idr);
 
 /* ------------------------------------------------------------------------- */
 
-static int i2c_device_match(struct device *dev, struct device_driver *drv)
+static const struct i2c_device_id *i2c_device_match(const struct i2c_device_id *id, struct i2c_client *client)
+{
+	/* only powerpc drivers implement the id_table,
+	 * it is empty on other platforms */
+	if (id) {
+		while (id->name[0]) {
+			if (strcmp(client->driver_name, id->name) == 0)
+				return id;
+			id++;
+		}
+	}
+	return NULL;
+}
+
+static int i2c_bus_match(struct device *dev, struct device_driver *drv)
 {
 	struct i2c_client	*client = to_i2c_client(dev);
 	struct i2c_driver	*driver = to_i2c_driver(drv);
+	const struct i2c_device_id *found_id;
 
 	/* make legacy i2c drivers bypass driver model probing entirely;
 	 * such drivers scan each i2c adapter/bus themselves.
@@ -58,9 +73,11 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
 	if (!is_newstyle_driver(driver))
 		return 0;
 
-	/* new style drivers use the same kind of driver matching policy
-	 * as platform devices or SPI:  compare device and driver IDs.
-	 */
+	/* match on an id table if there is one */
+	found_id = i2c_device_match(driver->id_table, client);
+	if (found_id)
+		return 1;
+
 	return strcmp(client->driver_name, drv->name) == 0;
 }
 
@@ -89,12 +106,15 @@ static int i2c_device_probe(struct device *dev)
 {
 	struct i2c_client	*client = to_i2c_client(dev);
 	struct i2c_driver	*driver = to_i2c_driver(dev->driver);
+	const struct i2c_device_id *id;
 
 	if (!driver->probe)
 		return -ENODEV;
 	client->driver = driver;
 	dev_dbg(dev, "probe\n");
-	return driver->probe(client);
+
+	id = i2c_device_match(driver->id_table, client);
+	return driver->probe(client, id);
 }
 
 static int i2c_device_remove(struct device *dev)
@@ -189,7 +209,7 @@ static struct device_attribute i2c_dev_attrs[] = {
 static struct bus_type i2c_bus_type = {
 	.name		= "i2c",
 	.dev_attrs	= i2c_dev_attrs,
-	.match		= i2c_device_match,
+	.match		= i2c_bus_match,
 	.uevent		= i2c_device_uevent,
 	.probe		= i2c_device_probe,
 	.remove		= i2c_device_remove,
include/linux/i2c.h +4 -5
index a100c9f..49fc682 100644
@@ -126,7 +126,7 @@ struct i2c_driver {
 	 * With the driver model, device enumeration is NEVER done by drivers;
 	 * it's done by infrastructure.  (NEW STYLE DRIVERS ONLY)
 	 */
-	int (*probe)(struct i2c_client *);
+	int (*probe)(struct i2c_client *, const struct i2c_device_id *id);
 	int (*remove)(struct i2c_client *);
 
 	/* driver model interfaces that don't relate to enumeration  */
@@ -141,11 +141,10 @@ struct i2c_driver {
 
 	struct device_driver driver;
 	struct list_head list;
+	struct i2c_device_id *id_table;
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
-#define I2C_NAME_SIZE	20
-
 /**
  * struct i2c_client - represent an I2C slave device
  * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
@@ -179,7 +178,7 @@ struct i2c_client {
 					/* to the client		*/
 	struct device dev;		/* the device structure		*/
 	int irq;			/* irq issued by device (or -1) */
-	char driver_name[KOBJ_NAME_LEN];
+	char driver_name[I2C_NAME_SIZE];
 	struct list_head list;
 	struct completion released;
 };
@@ -223,7 +222,7 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
  * with the adapter already known.
  */
 struct i2c_board_info {
-	char		driver_name[KOBJ_NAME_LEN];
+	char		driver_name[I2C_NAME_SIZE];
 	char		type[I2C_NAME_SIZE];
 	unsigned short	flags;
 	unsigned short	addr;
include/linux/mod_devicetable.h +20 -0
index e9fddb4..d66038a 100644
@@ -367,4 +367,24 @@ struct virtio_device_id {
 };
 #define VIRTIO_DEV_ANY_ID	0xffffffff
 
+/* i2c */
+
+/* These defines are used to separate PowerPC open firmware
+ * drivers into their own namespace */
+#define I2C_NAME_SIZE	(16*3)
+#define I2C_MODULE_PREFIX "i2c:N"
+#ifdef CONFIG_OF
+#define OF_I2C_PREFIX "OF,"
+#define I2C_OF_MODULE_PREFIX I2C_MODULE_PREFIX OF_I2C_PREFIX
+#define OF_I2C_ID(s,d) {OF_I2C_PREFIX s, (d) },
+#else
+#define OF_I2C_ID(s,d)
+#endif
+
+struct i2c_device_id {
+	char name[I2C_NAME_SIZE];
+	kernel_ulong_t driver_data;	/* Data private to the driver */
+};
+
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
scripts/mod/file2alias.c +19 -0
index d802b5a..da43742 100644
@@ -539,6 +539,21 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
 	return 1;
 }
 
+/* Looks like: i2c:Ns */
+static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
+			   char *alias)
+{
+    char *tmp;
+    sprintf (alias, I2C_MODULE_PREFIX "%s", id->name);
+
+    /* Replace all whitespace with underscores */
+    for (tmp = alias; tmp && *tmp; tmp++)
+        if (isspace (*tmp))
+            *tmp = '_';
+
+    return 1;
+}
+
 /* Ignore any prefix, eg. v850 prepends _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -669,6 +684,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
 		do_table(symval, sym->st_size,
 			 sizeof(struct virtio_device_id), "virtio",
 			 do_virtio_entry, mod);
+	else if (sym_is(symname, "__mod_i2c_device_table"))
+		do_table(symval, sym->st_size,
+			 sizeof(struct i2c_device_id), "i2c",
+			 do_i2c_entry, mod);
 	free(zeros);
 }
 
author
#4 lore raw

PATCH 3/7 Modify several rtc drivers to use the alias names list property of i2c

In reply to Jon Smirl

This patch modifies the ds1307, ds1374, and rs5c372 i2c drivers to support device tree names using the new i2c mod alias support

---

 arch/powerpc/sysdev/fsl_soc.c |   44 ++++----------------------------
 drivers/rtc/rtc-ds1307.c      |   20 +++++++++++++-
 drivers/rtc/rtc-ds1374.c      |    9 ++++++
 drivers/rtc/rtc-m41t80.c      |   57 ++++++++++++++++++++++++++++-------------
 drivers/rtc/rtc-rs5c372.c     |   16 ++++++++++--
 5 files changed, 85 insertions(+), 61 deletions(-)
arch/powerpc/sysdev/fsl_soc.c +6 -38
index 3ace747..268638a 100644
@@ -320,48 +320,12 @@ 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",},
-	{"dallas,ds1307",  "rtc-ds1307",  "ds1307",},
-	{"dallas,ds1337",  "rtc-ds1307",  "ds1337",},
-	{"dallas,ds1338",  "rtc-ds1307",  "ds1338",},
-	{"dallas,ds1339",  "rtc-ds1307",  "ds1339",},
-	{"dallas,ds1340",  "rtc-ds1307",  "ds1340",},
-	{"stm,m41t00",     "rtc-ds1307",  "m41t00"},
-	{"dallas,ds1374",  "rtc-ds1374",  "rtc-ds1374",},
-};
-
-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;
-		if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
-			    KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
-		    strlcpy(info->type, i2c_devices[i].i2c_type,
-			    I2C_NAME_SIZE) >= I2C_NAME_SIZE)
-			return -ENOMEM;
-		return 0;
-	}
-	return -ENODEV;
-}
 
 static void __init of_register_i2c_devices(struct device_node *adap_node,
 					   int bus_num)
 {
 	struct device_node *node = NULL;
+	const char *compatible;
 
 	while ((node = of_get_next_child(adap_node, node))) {
 		struct i2c_board_info info = {};
@@ -378,8 +342,12 @@ static void __init of_register_i2c_devices(struct device_node *adap_node,
 		if (info.irq == NO_IRQ)
 			info.irq = -1;
 
-		if (of_find_i2c_driver(node, &info) < 0)
+		compatible = of_get_property(node, "compatible", &len);
+		if (!compatible) {
+			printk(KERN_WARNING "i2c-mpc.c: invalid entry, missing compatible attribute\n");
 			continue;
+		}
+		strncpy(info.driver_name, compatible, sizeof(info.driver_name));
 
 		info.addr = *addr;
 
drivers/rtc/rtc-ds1307.c +18 -2
index bc1c7fe..d4874ff 100644
@@ -139,6 +139,17 @@ static inline const struct chip_desc *find_chip(const char *s)
 	return NULL;
 }
 
+static struct i2c_device_id ds1307_id[] = {
+	OF_I2C_ID("dallas,ds1307", ds_1307)
+	OF_I2C_ID("dallas,ds1337", ds_1337)
+	OF_I2C_ID("dallas,ds1338", ds_1338)
+	OF_I2C_ID("dallas,ds1339", ds_1339)
+	OF_I2C_ID("dallas,ds1340", ds_1340)
+	OF_I2C_ID("stm,m41t00", m41t00)
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, ds1307_id);
+
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
 	struct ds1307	*ds1307 = dev_get_drvdata(dev);
@@ -326,7 +337,7 @@ static struct bin_attribute nvram = {
 
 static struct i2c_driver ds1307_driver;
 
-static int __devinit ds1307_probe(struct i2c_client *client)
+static int __devinit ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct ds1307		*ds1307;
 	int			err = -ENODEV;
@@ -334,7 +345,11 @@ static int __devinit ds1307_probe(struct i2c_client *client)
 	const struct chip_desc	*chip;
 	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
 
-	chip = find_chip(client->name);
+	if (id)
+		chip = &chips[id->driver_data];
+	else
+		chip = find_chip(client->name);
+
 	if (!chip) {
 		dev_err(&client->dev, "unknown chip type '%s'\n",
 				client->name);
@@ -537,6 +552,7 @@ static struct i2c_driver ds1307_driver = {
 	},
 	.probe		= ds1307_probe,
 	.remove		= __devexit_p(ds1307_remove),
+	.id_table	= ds1307_id,
 };
 
 static int __init ds1307_init(void)
drivers/rtc/rtc-ds1374.c +8 -1
index 45bda18..6dc05c4 100644
@@ -41,6 +41,12 @@
 #define DS1374_REG_SR_AF	0x01 /* Alarm Flag */
 #define DS1374_REG_TCR		0x09 /* Trickle Charge */
 
+static struct i2c_device_id ds1374_id[] = {
+	OF_I2C_ID("dallas,ds1374", 0)
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, ds1374_id);
+
 struct ds1374 {
 	struct i2c_client *client;
 	struct rtc_device *rtc;
@@ -355,7 +361,7 @@ static const struct rtc_class_ops ds1374_rtc_ops = {
 	.ioctl = ds1374_ioctl,
 };
 
-static int ds1374_probe(struct i2c_client *client)
+static int ds1374_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct ds1374 *ds1374;
 	int ret;
@@ -429,6 +435,7 @@ static struct i2c_driver ds1374_driver = {
 	},
 	.probe = ds1374_probe,
 	.remove = __devexit_p(ds1374_remove),
+	.id_table = ds1374_id,
 };
 
 static int __init ds1374_init(void)
drivers/rtc/rtc-m41t80.c +39 -18

117 lines not on this page · raw message

drivers/rtc/rtc-rs5c372.c +14 -2
index 6b67b50..e2022c0 100644
@@ -69,6 +69,15 @@ enum rtc_type {
 	rtc_rv5c387a,
 };
 
+static struct i2c_device_id rs5c372_id[] = {
+	OF_I2C_ID("ricoh,rs5c372a", rtc_rs5c372a)
+	OF_I2C_ID("ricoh,rs5c372b", rtc_rs5c372b)
+	OF_I2C_ID("ricoh,rv5c386", rtc_rv5c386)
+	OF_I2C_ID("ricoh,rv5c387a", rtc_rv5c387a)
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, rs5c372_id);
+
 /* REVISIT:  this assumes that:
  *  - we're in the 21st century, so it's safe to ignore the century
  *    bit for rv5c38[67] (REG_MONTH bit 7);
@@ -494,7 +503,7 @@ static void rs5c_sysfs_unregister(struct device *dev)
 
 static struct i2c_driver rs5c372_driver;
 
-static int rs5c372_probe(struct i2c_client *client)
+static int rs5c372_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	int err = 0;
 	struct rs5c372 *rs5c372;
@@ -522,7 +531,9 @@ static int rs5c372_probe(struct i2c_client *client)
 	if (err < 0)
 		goto exit_kfree;
 
-	if (strcmp(client->name, "rs5c372a") == 0)
+	if (id)
+		rs5c372->type = id->driver_data;
+	else if (strcmp(client->name, "rs5c372a") == 0)
 		rs5c372->type = rtc_rs5c372a;
 	else if (strcmp(client->name, "rs5c372b") == 0)
 		rs5c372->type = rtc_rs5c372b;
@@ -651,6 +662,7 @@ static struct i2c_driver rs5c372_driver = {
 	},
 	.probe		= rs5c372_probe,
 	.remove		= rs5c372_remove,
+	.id_table	= rs5c372_id,
 };
 
 static __init int rs5c372_init(void)
author
#5 lore raw

PATCH 4/7 Clean up error returns

In reply to Jon Smirl

Return errors that were being ignored in the mpc-i2c driver

---

 drivers/i2c/busses/i2c-mpc.c |   30 +++++++++++++++++-------------
 1 files changed, 17 insertions(+), 13 deletions(-)
drivers/i2c/busses/i2c-mpc.c +17 -13
index d8de4ac..7c35a8f 100644
@@ -180,7 +180,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c)
 static int mpc_write(struct mpc_i2c *i2c, int target,
 		     const u8 * data, int length, int restart)
 {
-	int i;
+	int i, result;
 	unsigned timeout = i2c->adap.timeout;
 	u32 flags = restart ? CCR_RSTA : 0;
 
@@ -192,15 +192,17 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
 	/* Write target byte */
 	writeb((target << 1), i2c->base + MPC_I2C_DR);
 
-	if (i2c_wait(i2c, timeout, 1) < 0)
-		return -1;
+	result = i2c_wait(i2c, timeout, 1);
+	if (result < 0)
+		return result;
 
 	for (i = 0; i < length; i++) {
 		/* Write data byte */
 		writeb(data[i], i2c->base + MPC_I2C_DR);
 
-		if (i2c_wait(i2c, timeout, 1) < 0)
-			return -1;
+		result = i2c_wait(i2c, timeout, 1);
+		if (result < 0)
+			return result;
 	}
 
 	return 0;
@@ -210,7 +212,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
 		    u8 * data, int length, int restart)
 {
 	unsigned timeout = i2c->adap.timeout;
-	int i;
+	int i, result;
 	u32 flags = restart ? CCR_RSTA : 0;
 
 	/* Start with MEN */
@@ -221,8 +223,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
 	/* Write target address byte - this time with the read flag set */
 	writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
 
-	if (i2c_wait(i2c, timeout, 1) < 0)
-		return -1;
+	result = i2c_wait(i2c, timeout, 1);
+	if (result < 0)
+		return result;
 
 	if (length) {
 		if (length == 1)
@@ -234,8 +237,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
 	}
 
 	for (i = 0; i < length; i++) {
-		if (i2c_wait(i2c, timeout, 0) < 0)
-			return -1;
+		result = i2c_wait(i2c, timeout, 0);
+		if (result < 0)
+			return result;
 
 		/* Generate txack on next to last byte */
 		if (i == length - 2)
@@ -321,9 +325,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
 
 	pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
 
-	if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
+	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+	if (!i2c)
 		return -ENOMEM;
-	}
 
 	i2c->irq = platform_get_irq(pdev, 0);
 	if (i2c->irq < 0) {
@@ -381,7 +385,7 @@ static int fsl_i2c_remove(struct platform_device *pdev)
 	i2c_del_adapter(&i2c->adap);
 	platform_set_drvdata(pdev, NULL);
 
-	if (i2c->irq != 0)
+	if (i2c->irq != NO_IRQ)
 		free_irq(i2c->irq, i2c);
 
 	iounmap(i2c->base);
author
#6 lore raw

PATCH 5/7 Convert PowerPC MPC i2c to of_platform_driver from platform_driver

In reply to Jon Smirl

Convert MPC i2c driver from being a platform_driver to an open firmware version. Error returns were improved. Routine names were changed from fsl_ to mpc_ to make them match the file name.

---

 arch/powerpc/sysdev/fsl_soc.c |   96 ------------------------
 drivers/i2c/busses/i2c-mpc.c  |  167 +++++++++++++++++++++++++++++------------
 2 files changed, 119 insertions(+), 144 deletions(-)
arch/powerpc/sysdev/fsl_soc.c +0 -96
index 268638a..d6ef264 100644
@@ -318,102 +318,6 @@ err:
 
 arch_initcall(gfar_of_init);
 
-#ifdef CONFIG_I2C_BOARDINFO
-#include <linux/i2c.h>
-
-static void __init of_register_i2c_devices(struct device_node *adap_node,
-					   int bus_num)
-{
-	struct device_node *node = NULL;
-	const char *compatible;
-
-	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_soc.c: invalid i2c device entry\n");
-			continue;
-		}
-
-		info.irq = irq_of_parse_and_map(node, 0);
-		if (info.irq == NO_IRQ)
-			info.irq = -1;
-
-		compatible = of_get_property(node, "compatible", &len);
-		if (!compatible) {
-			printk(KERN_WARNING "i2c-mpc.c: invalid entry, missing compatible attribute\n");
-			continue;
-		}
-		strncpy(info.driver_name, compatible, sizeof(info.driver_name));
-
-		info.addr = *addr;
-
-		i2c_register_board_info(bus_num, &info, 1);
-	}
-}
-
-static int __init fsl_i2c_of_init(void)
-{
-	struct device_node *np;
-	unsigned int i;
-	struct platform_device *i2c_dev;
-	int ret;
-
-	for (np = NULL, i = 0;
-	     (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
-	     i++) {
-		struct resource r[2];
-		struct fsl_i2c_platform_data i2c_data;
-		const unsigned char *flags = NULL;
-
-		memset(&r, 0, sizeof(r));
-		memset(&i2c_data, 0, sizeof(i2c_data));
-
-		ret = of_address_to_resource(np, 0, &r[0]);
-		if (ret)
-			goto err;
-
-		of_irq_to_resource(np, 0, &r[1]);
-
-		i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
-		if (IS_ERR(i2c_dev)) {
-			ret = PTR_ERR(i2c_dev);
-			goto err;
-		}
-
-		i2c_data.device_flags = 0;
-		flags = of_get_property(np, "dfsrr", NULL);
-		if (flags)
-			i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
-
-		flags = of_get_property(np, "fsl5200-clocking", NULL);
-		if (flags)
-			i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
-
-		ret =
-		    platform_device_add_data(i2c_dev, &i2c_data,
-					     sizeof(struct
-						    fsl_i2c_platform_data));
-		if (ret)
-			goto unreg;
-
-		of_register_i2c_devices(np, i);
-	}
-
-	return 0;
-
-unreg:
-	platform_device_unregister(i2c_dev);
-err:
-	return ret;
-}
-
-arch_initcall(fsl_i2c_of_init);
-#endif
-
 #ifdef CONFIG_PPC_83xx
 static int __init mpc83xx_wdt_init(void)
 {
drivers/i2c/busses/i2c-mpc.c +119 -48

244 lines not on this page · raw message

author
#7 lore raw

PATCH 6/7 Convert pfc8563 i2c driver from old style to new style

In reply to Jon Smirl

Convert pfc8563 i2c driver from old style to new style. The driver is also modified to support device tree names via the i2c mod alias mechanism.

---

 drivers/rtc/rtc-pcf8563.c |  107 +++++++++++----------------------------------
 1 files changed, 27 insertions(+), 80 deletions(-)
drivers/rtc/rtc-pcf8563.c +27 -80
index 0242d80..e1ea2a0 100644
@@ -25,10 +25,6 @@
  * located at 0x51 will pass the validation routine due to
  * the way the registers are implemented.
  */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Module parameters */
-I2C_CLIENT_INSMOD;
 
 #define PCF8563_REG_ST1		0x00 /* status */
 #define PCF8563_REG_ST2		0x01
@@ -72,9 +68,6 @@ struct pcf8563 {
 	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
 };
 
-static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind);
-static int pcf8563_detach(struct i2c_client *client);
-
 /*
  * In the routines that deal directly with the pcf8563 hardware, we use
  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
@@ -257,98 +250,52 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
 	.set_time	= pcf8563_rtc_set_time,
 };
 
-static int pcf8563_attach(struct i2c_adapter *adapter)
+static int pcf8563_remove(struct i2c_client *client)
 {
-	return i2c_probe(adapter, &addr_data, pcf8563_probe);
+	struct rtc_device *rtc = i2c_get_clientdata(client);
+
+	if (rtc)
+		rtc_device_unregister(rtc);
+
+	return 0;
 }
 
+static struct i2c_device_id pcf8563_id[] = {
+	OF_I2C_ID("philips,pcf8563", 0)
+	OF_I2C_ID("epson,rtc8564", 0)
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, pcf8563_id);
+
+static int pcf8563_probe(struct i2c_client *client, const struct i2c_device_id *id);
+
 static struct i2c_driver pcf8563_driver = {
 	.driver		= {
-		.name	= "pcf8563",
+		.name	= "rtc-pcf8563",
 	},
 	.id		= I2C_DRIVERID_PCF8563,
-	.attach_adapter = &pcf8563_attach,
-	.detach_client	= &pcf8563_detach,
+	.probe = &pcf8563_probe,
+	.remove = &pcf8563_remove,
+	.id_table	= pcf8563_id,
 };
 
-static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
+static int pcf8563_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct pcf8563 *pcf8563;
-	struct i2c_client *client;
+	int result;
 	struct rtc_device *rtc;
 
-	int err = 0;
-
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
-		err = -ENODEV;
-		goto exit;
-	}
-
-	if (!(pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	client = &pcf8563->client;
-	client->addr = address;
-	client->driver = &pcf8563_driver;
-	client->adapter	= adapter;
-
-	strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE);
-
-	/* Verify the chip is really an PCF8563 */
-	if (kind < 0) {
-		if (pcf8563_validate_client(client) < 0) {
-			err = -ENODEV;
-			goto exit_kfree;
-		}
-	}
-
-	/* Inform the i2c layer */
-	if ((err = i2c_attach_client(client)))
-		goto exit_kfree;
-
-	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+	result = pcf8563_validate_client(client);
+	if (result)
+		return result;
 
 	rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev,
 				&pcf8563_rtc_ops, THIS_MODULE);
-
-	if (IS_ERR(rtc)) {
-		err = PTR_ERR(rtc);
-		goto exit_detach;
-	}
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 
 	i2c_set_clientdata(client, rtc);
 
 	return 0;
-
-exit_detach:
-	i2c_detach_client(client);
-
-exit_kfree:
-	kfree(pcf8563);
-
-exit:
-	return err;
-}
-
-static int pcf8563_detach(struct i2c_client *client)
-{
-	struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
-	int err;
-	struct rtc_device *rtc = i2c_get_clientdata(client);
-
-	if (rtc)
-		rtc_device_unregister(rtc);
-
-	if ((err = i2c_detach_client(client)))
-		return err;
-
-	kfree(pcf8563);
-
-	return 0;
 }
 
 static int __init pcf8563_init(void)
author
#8 lore raw

PATCH 7/7 Makefile

In reply to Jon Smirl

---

 Makefile |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
Makefile +3 -0
index c1825aa..15ada3f 100644
@@ -35,6 +35,9 @@ MAKEFLAGS += -rR --no-print-directory
 # To put more focus on warnings, be less verbose as default
 # Use 'make V=1' to see the full commands
 
+ARCH=powerpc
+CROSS_COMPILE=powerpc-603e-linux-gnu-
+
 ifdef V
   ifeq ("$(origin V)", "command line")
     KBUILD_VERBOSE = $(V)
author
#9 lore raw

Re: [PATCH 7/7] Makefile

Ignore this patch, I forgot to remove it before mailing the series.

Quoted 30 lines · Jon Smirl

---

 Makefile |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
Makefile +3 -1
index c1825aa..15ada3f 100644
@@ -35,6 +35,9 @@ MAKEFLAGS += -rR --no-print-directory
 # To put more focus on warnings, be less verbose as default
 # Use 'make V=1' to see the full commands
 
+ARCH=powerpc
+CROSS_COMPILE=powerpc-603e-linux-gnu-
+
 ifdef V
   ifeq ("$(origin V)", "command line")
     KBUILD_VERBOSE = $(V)
 
--

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 2 lines
Jon Smirl
[email protected]