[i2c] [patch 2.6.21-rc5-git +i2c 2/2] convert tps65010 to new-style driver
Jean Delvare
khali at linux-fr.org
Thu Apr 5 21:05:40 CEST 2007
Hi David,
On Mon, 2 Apr 2007 13:02:31 -0700, David Brownell wrote:
> 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.
Then I suggest that you keep the patches in your local stack for now,
and resend them when then can be merged.
> 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(-)
Random comments:
> --- 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),
> +},
You're missing one level of indentation here, and same for the other
declarations later on.
> + /* 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
No C++-style comments please.
> +
> + /* 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
The H2 and OSK cases don't have this #ifdef, should it be added?
> + 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)
Shouldn't this be __devexit?
> {
> - 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)
Shouldn't this be __devinit?
> {
> 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
>
> _______________________________________________
> i2c mailing list
> i2c at lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/i2c
--
Jean Delvare
More information about the i2c
mailing list