[i2c] [patch 2.6.22] tps65010 new-style driver updates, part 2

Jean Delvare khali at linux-fr.org
Sat Aug 11 18:45:46 CEST 2007


Hi David,

On Sun, 15 Jul 2007 13:21:24 -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; the
> rest of that code is now moved into board-specific initcalls.
>
> Also remove some now-superfluous #includes.

You've been overeager, see below.

> 
> Signed-off-by: David Brownell <dbrownell at users.sourceforge.net>
> ---
> Note that the upstream version of board-h3 still has build errors
> because of missing workqueue conversions.
> 
>  arch/arm/mach-omap1/board-h2.c  |   45 ++++++++-
>  arch/arm/mach-omap1/board-h3.c  |   39 ++++++++
>  arch/arm/mach-omap1/board-osk.c |   64 +++++++++++++
>  drivers/i2c/chips/tps65010.c    |  187 +++++++---------------------------------
>  4 files changed, 180 insertions(+), 155 deletions(-)
> 
> --- osk.orig/drivers/i2c/chips/tps65010.c	2007-07-15 09:57:44.000000000 -0700
> +++ osk/drivers/i2c/chips/tps65010.c	2007-07-15 11:55:49.000000000 -0700
> @@ -20,24 +20,12 @@
>   */
>  
>  #include <linux/kernel.h>
> -#include <linux/module.h>

This one defines MODULE_DESCRIPTION, MODULE_LICENSE and EXPORT_SYMBOL,
which your driver uses, so you can't remove it.

> -#include <linux/init.h>

This one defines __init, __exit and __exit_p, which your driver uses,
so you can't remove it.

> -#include <linux/slab.h>

This one defines kfree(), which your driver uses, so you can't remove
it.

>  #include <linux/interrupt.h>
> -#include <linux/device.h>
>  #include <linux/i2c.h>
>  #include <linux/delay.h>
> -#include <linux/workqueue.h>

This one defines INIT_DELAYED_WORK, which your driver uses, so you
can't remove it.

> -#include <linux/suspend.h>
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
> -#include <linux/mutex.h>
> -
> -#include <asm/irq.h>
> -#include <asm/mach-types.h>
>  
> -#include <asm/arch/gpio.h>
> -#include <asm/arch/mux.h>
>  #include <asm/arch/tps65010.h>
>  
>  /*-------------------------------------------------------------------------*/
> @@ -48,10 +36,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 +63,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;
> @@ -445,7 +427,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);
>  }
> @@ -464,116 +446,75 @@ 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 tps6501x chip allowed\n");
> +		return -ENODEV;
>  	}
>  
> +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
> +		return -EINVAL;
> +
>  	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 {
> +		dev_warn(&client->dev, "unknown chip '%s'\n", client->name);
> +		status = -ENODEV;
>  		goto fail1;
>  	}
>  
>  	/* the IRQ is active low, but many gpio lines can't support that
> -	 * so this driver can use falling-edge triggers instead.
> +	 * so this driver uses 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 ...
> -	}
> -#endif
> -
> -	if (tps->irq > 0) {
> -		status = request_irq(tps->irq, tps65010_irq,
> -			irqflags, DRIVER_NAME, tps);
> +	if (client->irq > 0) {
> +		status = request_irq(client->irq, tps65010_irq,
> +			IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING,
> +			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.
> +		 * FIXME genirq IRQF_NOAUTOEN now solves that ...
>  		 */
> -		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);
> +		dev_warn(&client->dev, "IRQ not configured!\n");
>  
>  
>  	switch (tps->model) {
> @@ -602,7 +543,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)
> @@ -635,22 +575,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),
>  };
>  
>  /*-------------------------------------------------------------------------*/
> @@ -1014,52 +947,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
> --- osk.orig/arch/arm/mach-omap1/board-h2.c	2007-07-15 09:57:44.000000000 -0700
> +++ osk/arch/arm/mach-omap1/board-h2.c	2007-07-15 12:07:11.000000000 -0700
> @@ -20,22 +20,23 @@
>   */
>  
>  #include <linux/kernel.h>
> -#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>
>  #include <linux/input.h>
> -#include <linux/workqueue.h>
>  
>  #include <asm/hardware.h>
> +#include <asm/gpio.h>
> +
>  #include <asm/mach-types.h>
>  #include <asm/mach/arch.h>
>  #include <asm/mach/flash.h>
>  #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>
> @@ -277,6 +278,20 @@ 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
> +	 *  - optional ov9640 camera sensor at 0x30
> +	 *  - pcf9754 for aGPS control
> +	 *  - ... etc
> +	 */
> +};
> +
>  static void __init h2_init_smc91x(void)
>  {
>  	if ((omap_request_gpio(0)) < 0) {
> @@ -367,6 +382,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);
> +	if (gpio_request(58, "tps65010") == 0)
> +		gpio_direction_input(58);
> +
> +	i2c_register_board_info(1, h2_i2c_board_info,
> +			ARRAY_SIZE(h2_i2c_board_info));
>  }
>  
>  static void __init h2_map_io(void)
> @@ -374,6 +397,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 send power to 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,
> --- osk.orig/arch/arm/mach-omap1/board-h3.c	2007-07-15 09:57:44.000000000 -0700
> +++ osk/arch/arm/mach-omap1/board-h3.c	2007-07-15 11:09:04.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>
> @@ -29,12 +30,14 @@
>  #include <asm/setup.h>
>  #include <asm/page.h>
>  #include <asm/hardware.h>
> +#include <asm/gpio.h>
> +
>  #include <asm/mach-types.h>
>  #include <asm/mach/arch.h>
>  #include <asm/mach/flash.h>
>  #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>
> @@ -411,6 +414,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)
> @@ -444,6 +460,10 @@ 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 */
> +	i2c_register_board_info(1, h3_i2c_board_info,
> +			ARRAY_SIZE(h3_i2c_board_info));
>  }
>  
>  static void __init h3_init_smc91x(void)
> @@ -468,6 +488,23 @@ 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 send power to DSP iff it's configured */
> +
> +	/* Enable LOW_PWR */
> +	tps65013_set_low_pwr(ON);
> +
> +	return 0;
> +}
> +fs_initcall(h3_tps_init);
> +#endif
> +
>  MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
>  	/* Maintainer: Texas Instruments, Inc. */
>  	.phys_io	= 0xfff00000,
> --- osk.orig/arch/arm/mach-omap1/board-osk.c	2007-07-15 09:57:44.000000000 -0700
> +++ osk/arch/arm/mach-omap1/board-osk.c	2007-07-15 12:04:42.000000000 -0700
> @@ -31,18 +31,21 @@
>  #include <linux/platform_device.h>
>  #include <linux/irq.h>
>  #include <linux/interrupt.h>
> +#include <linux/i2c.h>
>  
>  #include <linux/mtd/mtd.h>
>  #include <linux/mtd/partitions.h>
>  
>  #include <asm/hardware.h>
> +#include <asm/gpio.h>
> +
>  #include <asm/mach-types.h>
>  #include <asm/mach/arch.h>
>  #include <asm/mach/map.h>
>  #include <asm/mach/flash.h>
>  
> -#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>
> @@ -179,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) {
> @@ -397,6 +413,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); */

Why is this line commented out? Either it's needed, or it's not.

> +	if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0)
> +		gpio_direction_input(OMAP_MPUIO(1));
> +
> +	i2c_register_board_info(1, osk_i2c_board_info,
> +			ARRAY_SIZE(osk_i2c_board_info));
> +
>  	omap_serial_init();
>  	osk_mistral_init();
>  }
> @@ -406,6 +430,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 send power to 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,

Rest looks good, please send an updated patch and I'll push it to -mm
together with the 1st part.

-- 
Jean Delvare



More information about the i2c mailing list