[i2c] [patch 2.6.21-rc5-git +i2c 2/2] convert tps65010 to new-style driver

David Brownell david-b at pacbell.net
Mon Apr 2 22:02:31 CEST 2007


Switch the tps65010 driver into a "new-style" I2C driver, and convert all
of its in-tree users (board support for OSK, H2, H3) accordingly.

That accounts for much of the board-specific code in this driver; move the
other such code to board-specific fs_initcall() routines.

Signed-off-by: David Brownell <dbrownell at users.sourceforge.net>
---
Tested on OSK ... which should now behave, mostly, with the upstream kernel.
Note that the previous patch (1/2) doesn't depend on the I2C stack updates,
but this one does.  And I've arranged the patch so it won't conflict with
what's pending in the linux-omap tree ... so if this gets added to the merge
queue for 2.6.22-early, I anticipate few consequential problems.

 arch/arm/mach-omap1/board-h2.c  |   41 ++++++++++
 arch/arm/mach-omap1/board-h3.c  |   41 ++++++++++
 arch/arm/mach-omap1/board-osk.c |   61 +++++++++++++++
 drivers/i2c/chips/tps65010.c    |  162 +++++++---------------------------------
 4 files changed, 175 insertions(+), 130 deletions(-)

--- osk2.orig/arch/arm/mach-omap1/board-h2.c	2007-04-01 22:40:01.000000000 -0700
+++ osk2/arch/arm/mach-omap1/board-h2.c	2007-04-01 23:38:13.000000000 -0700
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/i2c.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
@@ -39,6 +40,7 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/irda.h>
@@ -414,6 +416,21 @@ static struct platform_device *h2_device
 	&h2_mcbsp1_device,
 };
 
+static struct i2c_board_info __initdata h2_i2c_board_info[] = {
+{
+	I2C_BOARD_INFO("tps65010", 0x48),
+	.type		= "tps65010",
+	.irq		= OMAP_GPIO_IRQ(58),
+},
+	/* TODO when driver support is ready:
+	 *  - isp1301 OTG transceiver
+	 *  - tsc2003 (?)
+	 *  - optional ov9640 camera sensor at 0x30
+	 *  - pcf9754 for aGPS control
+	 *  - optional aGPS
+	 */
+};
+
 static void __init h2_init_smc91x(void)
 {
 	if ((omap_request_gpio(0)) < 0) {
@@ -518,6 +535,14 @@ static void __init h2_init(void)
 	omap_board_config = h2_config;
 	omap_board_config_size = ARRAY_SIZE(h2_config);
 	omap_serial_init();
+
+	/* irq for tps65010 chip */
+	omap_cfg_reg(W4_GPIO58);
+	omap_request_gpio(58);
+	omap_set_gpio_direction(58, 1);
+
+	i2c_register_board_info(1, h2_i2c_board_info,
+			ARRAY_SIZE(h2_i2c_board_info));
 }
 
 static void __init h2_map_io(void)
@@ -525,6 +550,22 @@ static void __init h2_map_io(void)
 	omap1_map_common_io();
 }
 
+#ifdef CONFIG_TPS65010
+static int __init h2_tps_init(void)
+{
+	if (!machine_is_omap_h2())
+		return 0;
+
+	/* gpio3 for SD, gpio4 for VDD_DSP */
+	// FIXME power DSP iff it's configured
+
+	/* Enable LOW_PWR */
+	tps65010_set_low_pwr(ON);
+	return 0;
+}
+fs_initcall(h2_tps_init);
+#endif
+
 MACHINE_START(OMAP_H2, "TI-H2")
 	/* Maintainer: Imre Deak <imre.deak at nokia.com> */
 	.phys_io	= 0xfff00000,
--- osk2.orig/arch/arm/mach-omap1/board-h3.c	2007-04-01 22:40:01.000000000 -0700
+++ osk2/arch/arm/mach-omap1/board-h3.c	2007-04-01 23:20:56.000000000 -0700
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/workqueue.h>
+#include <linux/i2c.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
@@ -38,6 +39,7 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
 #include <asm/arch/gpioexpander.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/mux.h>
@@ -540,6 +542,19 @@ static struct omap_board_config_kernel h
 	{ OMAP_TAG_LCD,		&h3_lcd_config },
 };
 
+static struct i2c_board_info __initdata h3_i2c_board_info[] = {
+{
+	I2C_BOARD_INFO("tps65010", 0x48),
+	.type		= "tps65013",
+	// .irq		= OMAP_GPIO_IRQ(??),
+},
+	/* TODO when driver support is ready:
+	 *  - isp1301 OTG transceiver
+	 *  - optional ov9640 camera sensor at 0x30
+	 *  - ...
+	 */
+};
+
 #define H3_NAND_RB_GPIO_PIN	10
 
 static int nand_dev_ready(struct nand_platform_data *data)
@@ -575,6 +590,14 @@ static void __init h3_init(void)
 	omap_board_config = h3_config;
 	omap_board_config_size = ARRAY_SIZE(h3_config);
 	omap_serial_init();
+
+	/* FIXME setup irq for tps65013 chip */
+	// omap_cfg_reg(???);
+	// omap_request_gpio(???);
+	// omap_set_gpio_direction(???, 1);
+
+	i2c_register_board_info(1, h3_i2c_board_info,
+			ARRAY_SIZE(h3_i2c_board_info));
 }
 
 static void __init h3_init_smc91x(void)
@@ -599,6 +622,24 @@ static void __init h3_map_io(void)
 	omap1_map_common_io();
 }
 
+#ifdef CONFIG_TPS65010
+static int __init h3_tps_init(void)
+{
+	if (!machine_is_omap_h3())
+		return 0;
+
+	/* gpio4 for SD, gpio3 for VDD_DSP */
+	// FIXME power DSP iff it's configured
+
+#ifdef CONFIG_PM
+	/* Enable LOW_PWR */
+	tps65013_set_low_pwr(ON);
+#endif
+	return 0;
+}
+fs_initcall(h3_tps_init);
+#endif
+
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
 	/* Maintainer: Texas Instruments, Inc. */
 	.phys_io	= 0xfff00000,
--- osk2.orig/arch/arm/mach-omap1/board-osk.c	2007-04-01 22:40:01.000000000 -0700
+++ osk2/arch/arm/mach-omap1/board-osk.c	2007-04-01 23:41:04.000000000 -0700
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/i2c.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -44,6 +45,7 @@
 
 #include <asm/arch/gpio.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/tps65010.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/common.h>
@@ -180,6 +182,19 @@ static struct platform_device *osk5912_d
 	&osk5912_mcbsp1_device,
 };
 
+static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+{
+	I2C_BOARD_INFO("tps65010", 0x48),
+	.type		= "tps65010",
+	.irq		= OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
+},
+	/* TODO when driver support is ready:
+	 *  - aic23 audio chip at 0x1a
+	 *  - on Mistral, 24c04 eeprom at 0x50
+	 *  - optionally on Mistral, ov9640 camera sensor at 0x30
+	 */
+};
+
 static void __init osk_init_smc91x(void)
 {
 	if ((omap_request_gpio(0)) < 0) {
@@ -452,6 +467,14 @@ static void __init osk_init(void)
 	omap_board_config_size = ARRAY_SIZE(osk_config);
 	USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
 
+	/* irq for tps65010 chip */
+	// omap_cfg_reg(U19_1610_MPUIO1);
+	omap_request_gpio(OMAP_MPUIO(1));
+	omap_set_gpio_direction(OMAP_MPUIO(1), 1);
+
+	i2c_register_board_info(1, osk_i2c_board_info,
+			ARRAY_SIZE(osk_i2c_board_info));
+
 	omap_serial_init();
 	osk_mistral_init();
 }
@@ -461,6 +484,44 @@ static void __init osk_map_io(void)
 	omap1_map_common_io();
 }
 
+#ifdef CONFIG_TPS65010
+static int __init osk_tps_init(void)
+{
+	if (!machine_is_omap_osk())
+		return 0;
+
+	/* Let LED1 (D9) blink */
+	tps65010_set_led(LED1, BLINK);
+
+	/* Disable LED 2 (D2) */
+	tps65010_set_led(LED2, OFF);
+
+	/* Set GPIO 1 HIGH to disable VBUS power supply;
+	 * OHCI driver powers it up/down as needed.
+	 */
+	tps65010_set_gpio_out_value(GPIO1, HIGH);
+
+	/* Set GPIO 2 low to turn on LED D3 */
+	tps65010_set_gpio_out_value(GPIO2, HIGH);
+
+	/* Set GPIO 3 low to take ethernet out of reset */
+	tps65010_set_gpio_out_value(GPIO3, LOW);
+
+	/* gpio4 for VDD_DSP */
+	// FIXME power DSP iff it's configured
+
+	/* Enable LOW_PWR */
+	tps65010_set_low_pwr(ON);
+
+	/* Switch VLDO2 to 3.0V for AIC23 */
+	tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
+			| TPS_LDO1_ENABLE);
+
+	return 0;
+}
+fs_initcall(osk_tps_init);
+#endif
+
 MACHINE_START(OMAP_OSK, "TI-OSK")
 	/* Maintainer: Dirk Behme <dirk.behme at de.bosch.com> */
 	.phys_io	= 0xfff00000,
--- osk2.orig/drivers/i2c/chips/tps65010.c	2007-04-01 23:13:06.000000000 -0700
+++ osk2/drivers/i2c/chips/tps65010.c	2007-04-01 23:13:06.000000000 -0700
@@ -48,10 +48,6 @@
 MODULE_DESCRIPTION("TPS6501x Power Management Driver");
 MODULE_LICENSE("GPL");
 
-static unsigned short normal_i2c[] = { 0x48, /* 0x49, */ I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
 static struct i2c_driver tps65010_driver;
 
 /*-------------------------------------------------------------------------*/
@@ -79,10 +75,8 @@ enum tps_model {
 };
 
 struct tps65010 {
-	struct i2c_client	c;
 	struct i2c_client	*client;
 	struct mutex		lock;
-	int			irq;
 	struct delayed_work	work;
 	struct dentry		*file;
 	unsigned		charging:1;
@@ -443,7 +437,7 @@ static void tps65010_work(struct work_st
 	}
 
 	if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
-		enable_irq(tps->irq);
+		enable_irq(tps->client->irq);
 
 	mutex_unlock(&tps->lock);
 }
@@ -462,66 +456,51 @@ static irqreturn_t tps65010_irq(int irq,
 
 static struct tps65010 *the_tps;
 
-static int __exit tps65010_detach_client(struct i2c_client *client)
+static int __exit tps65010_remove(struct i2c_client *client)
 {
-	struct tps65010		*tps;
+	struct tps65010		*tps = i2c_get_clientdata(client);
 
-	tps = container_of(client, struct tps65010, c);
-	free_irq(tps->irq, tps);
-#ifdef	CONFIG_ARM
-	if (machine_is_omap_h2())
-		omap_free_gpio(58);
-	if (machine_is_omap_osk())
-		omap_free_gpio(OMAP_MPUIO(1));
-#endif
+	if (client->irq > 0)
+		free_irq(client->irq, tps);
 	cancel_delayed_work(&tps->work);
 	flush_scheduled_work();
 	debugfs_remove(tps->file);
-	if (i2c_detach_client(client) == 0)
-		kfree(tps);
+	kfree(tps);
 	the_tps = NULL;
 	return 0;
 }
 
-static int tps65010_noscan(struct i2c_adapter *bus)
-{
-	/* pure paranoia, in case someone adds another i2c bus
-	 * after our init section's gone...
-	 */
-	return -ENODEV;
-}
-
-/* no error returns, they'd just make bus scanning stop */
-static int __init
-tps65010_probe(struct i2c_adapter *bus, int address, int kind)
+static int tps65010_probe(struct i2c_client *client)
 {
 	struct tps65010		*tps;
 	int			status;
 	unsigned long		irqflags;
-	struct i2c_client	*client;
 
 	if (the_tps) {
-		dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME);
-		return 0;
+		dev_dbg(&client->dev, "only one %s for now\n", DRIVER_NAME);
+		return -ENODEV;
 	}
 
 	tps = kzalloc(sizeof *tps, GFP_KERNEL);
 	if (!tps)
-		return 0;
+		return -ENOMEM;
 
 	mutex_init(&tps->lock);
 	INIT_DELAYED_WORK(&tps->work, tps65010_work);
-	tps->irq = -1;
-	tps->c.addr = address;
-	tps->c.adapter = bus;
-	tps->c.driver = &tps65010_driver;
-	strlcpy(tps->c.name, DRIVER_NAME, I2C_NAME_SIZE);
-	tps->client = client = &tps->c;
+	tps->client = client;
 
-	status = i2c_attach_client(client);
-	if (status < 0) {
-		dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
-				DRIVER_NAME, address, status);
+	if (strcmp(client->name, "tps65010") == 0)
+		tps->model = TPS65010;
+	else if (strcmp(client->name, "tps65011") == 0)
+		tps->model = TPS65011;
+	else if (strcmp(client->name, "tps65012") == 0)
+		tps->model = TPS65012;
+	else if (strcmp(client->name, "tps65013") == 0)
+		tps->model = TPS65013;
+	else {
+		printk(KERN_WARNING "%s: unknown chip '%s'\n",
+				DRIVER_NAME, client->name);
+		status = -ENODEV;
 		goto fail1;
 	}
 
@@ -529,46 +508,23 @@ tps65010_probe(struct i2c_adapter *bus, 
 	 * so this driver can use falling-edge triggers instead.
 	 */
 	irqflags = IRQF_SAMPLE_RANDOM;
-#ifdef	CONFIG_ARM
-	if (machine_is_omap_h2()) {
-		tps->model = TPS65010;
-		omap_cfg_reg(W4_GPIO58);
-		tps->irq = OMAP_GPIO_IRQ(58);
-		omap_request_gpio(58);
-		omap_set_gpio_direction(58, 1);
-		irqflags |= IRQF_TRIGGER_FALLING;
-	}
-	if (machine_is_omap_osk()) {
-		tps->model = TPS65010;
-		// omap_cfg_reg(U19_1610_MPUIO1);
-		tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1));
-		omap_request_gpio(OMAP_MPUIO(1));
-		omap_set_gpio_direction(OMAP_MPUIO(1), 1);
-		irqflags |= IRQF_TRIGGER_FALLING;
-	}
-	if (machine_is_omap_h3()) {
-		tps->model = TPS65013;
-
-		// FIXME set up this board's IRQ ...
-	}
+#ifdef	CONFIG_ARCH_OMAP
+	irqflags |= IRQF_TRIGGER_FALLING;
 #endif
 
-	if (tps->irq > 0) {
-		status = request_irq(tps->irq, tps65010_irq,
+	if (client->irq > 0) {
+		status = request_irq(client->irq, tps65010_irq,
 			irqflags, DRIVER_NAME, tps);
 		if (status < 0) {
 			dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
-					tps->irq, status);
-			i2c_detach_client(client);
+					client->irq, status);
 			goto fail1;
 		}
-#ifdef	CONFIG_ARM
 		/* annoying race here, ideally we'd have an option
 		 * to claim the irq now and enable it later.
 		 */
-		disable_irq(tps->irq);
+		disable_irq(client->irq);
 		set_bit(FLAG_IRQ_ENABLE, &tps->flags);
-#endif
 	} else
 		printk(KERN_WARNING "%s: IRQ not configured!\n",
 				DRIVER_NAME);
@@ -600,7 +556,6 @@ tps65010_probe(struct i2c_adapter *bus, 
 		i2c_smbus_read_byte_data(client, TPS_DEFGPIO),
 		i2c_smbus_read_byte_data(client, TPS_MASK3));
 
-	tps65010_driver.attach_adapter = tps65010_noscan;
 	the_tps = tps;
 
 #if	defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
@@ -633,22 +588,15 @@ tps65010_probe(struct i2c_adapter *bus, 
 	return 0;
 fail1:
 	kfree(tps);
-	return 0;
-}
-
-static int __init tps65010_scan_bus(struct i2c_adapter *bus)
-{
-	if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -EINVAL;
-	return i2c_probe(bus, &addr_data, tps65010_probe);
+	return status;
 }
 
 static struct i2c_driver tps65010_driver = {
 	.driver = {
 		.name	= "tps65010",
 	},
-	.attach_adapter	= tps65010_scan_bus,
-	.detach_client	= __exit_p(tps65010_detach_client),
+	.probe	= tps65010_probe,
+	.remove	= __exit_p(tps65010_remove),
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1012,52 +960,6 @@ static int __init tps_init(void)
 		msleep(10);
 	}
 
-#ifdef	CONFIG_ARM
-	if (machine_is_omap_osk()) {
-
-		// FIXME: More should be placed in the initialization code
-		//	  of the submodules (DSP, ethernet, power management,
-		//	  board-osk.c). Careful: I2C is initialized "late".
-
-		/* Let LED1 (D9) blink */
-		tps65010_set_led(LED1, BLINK);
-
-		/* Disable LED 2 (D2) */
-		tps65010_set_led(LED2, OFF);
-
-		/* Set GPIO 1 HIGH to disable VBUS power supply;
-		 * OHCI driver powers it up/down as needed.
-		 */
-		tps65010_set_gpio_out_value(GPIO1, HIGH);
-
-		/* Set GPIO 2 low to turn on LED D3 */
-		tps65010_set_gpio_out_value(GPIO2, HIGH);
-
-		/* Set GPIO 3 low to take ethernet out of reset */
-		tps65010_set_gpio_out_value(GPIO3, LOW);
-
-		/* gpio4 for VDD_DSP */
-
-		/* Enable LOW_PWR */
-		tps65010_set_low_pwr(ON);
-
-		/* Switch VLDO2 to 3.0V for AIC23 */
-		tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V | TPS_LDO1_ENABLE);
-
-	} else if (machine_is_omap_h2()) {
-		/* gpio3 for SD, gpio4 for VDD_DSP */
-
-		/* Enable LOW_PWR */
-		tps65010_set_low_pwr(ON);
-	} else if (machine_is_omap_h3()) {
-		/* gpio4 for SD, gpio3 for VDD_DSP */
-#ifdef CONFIG_PM
-		/* Enable LOW_PWR */
-		tps65013_set_low_pwr(ON);
-#endif
-	}
-#endif
-
 	return status;
 }
 /* NOTE:  this MUST be initialized before the other parts of the system



More information about the i2c mailing list