All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
To: Samu Onkalo <samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
Cc: eric.piel-VkQ1JFuSMpfAbQlEx87xDw@public.gmane.org,
	khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org,
	guenter.roeck-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org,
	kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
Subject: Re: [lm-sensors] [RFC PATCH 2/9] hwmon: lis3: regulator control
Date: Sat, 02 Oct 2010 18:33:14 +0100	[thread overview]
Message-ID: <4CA76CDA.4040803@cam.ac.uk> (raw)
In-Reply-To: <1285933616-16044-3-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>

On 10/01/10 12:46, Samu Onkalo wrote:
> Based on pm_runtime control, turn lis3 regulators on and off.
> Perform context save and restore on transitions.

As this is a simple save and restore state patch I'm happy to comment on it.

Mostly fine, though I have a couple of minor questions.
> 
> Signed-off-by: Samu Onkalo <samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/hwmon/lis3lv02d.c     |   48 +++++++++++++++++++++++++++++++++++++++++
>  drivers/hwmon/lis3lv02d.h     |   19 ++++++++++++++++
>  drivers/hwmon/lis3lv02d_i2c.c |   43 +++++++++++++++++++++++++++++++++++-
>  3 files changed, 109 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
> index eaa5bf0..23d47ad 100644
> --- a/drivers/hwmon/lis3lv02d.c
> +++ b/drivers/hwmon/lis3lv02d.c
> @@ -223,10 +223,46 @@ fail:
>  	return ret;
>  }
>  
> +/*
> + * Order of registers in the list affects to order of the restore process.
> + * Perhaps it is a good idea to set interrupt enable register as a last one
> + * after all other configurations
> + */
> +static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
> +			       FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
> +			       CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
> +			       CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
> +			       CTRL_REG1, CTRL_REG2, CTRL_REG3};
> +
> +static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
> +			       FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
> +			       DD_THSE_L, DD_THSE_H,
> +			       CTRL_REG1, CTRL_REG3, CTRL_REG2};
> +
> +static inline void lis3_context_save(struct lis3lv02d *lis3)
> +{
> +	int i;
> +	for (i = 0; i < lis3->regs_size; i++)
> +		lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
> +	lis3->regs_stored = true;
> +}
> +
> +static inline void lis3_context_restore(struct lis3lv02d *lis3)
> +{
> +	int i;
> +	if (lis3->regs_stored)
> +		for (i = 0; i < lis3->regs_size; i++)
> +			lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
> +}
> +
>  void lis3lv02d_poweroff(struct lis3lv02d *lis3)
>  {
> +	if (lis3->reg_ctrl)
> +		lis3_context_save(lis3);
>  	/* disable X,Y,Z axis and power down */
>  	lis3->write(lis3, CTRL_REG1, 0x00);
> +	if (lis3->reg_ctrl)
> +		lis3->reg_ctrl(lis3, LIS3_REG_OFF);
>  }
>  EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
>  
> @@ -249,6 +285,8 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
>  		reg |= CTRL2_BDU;
>  		lis3->write(lis3, CTRL_REG2, reg);
>  	}
> +	if (lis3->reg_ctrl)
> +		lis3_context_restore(lis3);
>  }
>  EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
>  
> @@ -718,6 +756,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
>  		dev->odrs = lis3_12_rates;
>  		dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
>  		dev->scale = LIS3_SENSITIVITY_12B;
> +		dev->regs = lis3_wai12_regs;
> +		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
>  		break;
>  	case WAI_8B:
>  		printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
> @@ -727,6 +767,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
>  		dev->odrs = lis3_8_rates;
>  		dev->odr_mask = CTRL1_DR;
>  		dev->scale = LIS3_SENSITIVITY_8B;
> +		dev->regs = lis3_wai8_regs;
> +		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
>  		break;
>  	default:
>  		printk(KERN_ERR DRIVER_NAME
> @@ -734,6 +776,12 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
>  		return -EINVAL;
>  	}
>  
This is a little odd as runtime checks go.  Surely it can only occur in event
of a clear driver bug?  Personally I'd just go with dynamically allocating
the reg_cache to be the right size...
> +	if (dev->regs_size > LIS3_NUM_MAX_REG) {
> +		printk(KERN_ERR DRIVER_NAME
> +			": register cache area is too small");
> +		return -EINVAL;
> +	}
> +
>  	mutex_init(&dev->mutex);
>  
>  	lis3lv02d_add_fs(dev);
> diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
> index 3e8a208..caf3ed1 100644
> --- a/drivers/hwmon/lis3lv02d.h
> +++ b/drivers/hwmon/lis3lv02d.h
> @@ -20,6 +20,7 @@
>   */
>  #include <linux/platform_device.h>
>  #include <linux/input-polldev.h>
> +#include <linux/regulator/consumer.h>
>  
>  /*
>   * This driver tries to support the "digital" accelerometer chips from
> @@ -97,6 +98,15 @@ enum lis3_who_am_i {
>  	WAI_8B		= 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
>  	WAI_6B		= 0x52, /* 6 bits: LIS331DLF - not supported */
>  };
> +/* Number of RW registers in each device for register caching purposes */
You could just enforce this through review, but I guess it doesn't hurt
to have sanity checks... 

> +#define NUM_RW_REGS_12B 21
> +#define NUM_RW_REGS_8B  15
> +
> +#if NUM_RW_REGS_8B > NUM_RW_REGS_12B
> +#define LIS3_NUM_MAX_REG NUM_RW_REGS_8B
> +#else
> +#define LIS3_NUM_MAX_REG NUM_RW_REGS_12B
> +#endif
>  
>  enum lis3lv02d_ctrl1_12b {
>  	CTRL1_Xen	= 0x01,
> @@ -206,6 +216,9 @@ enum lis3lv02d_click_src_8b {
>  	CLICK_IA	= 0x40,
>  };
>  
> +#define LIS3_REG_OFF	0x00
> +#define LIS3_REG_ON	0x01
I think the rest of these are done as enums.  Worth doing that here for
consistency?
> +
>  struct axis_conversion {
>  	s8	x;
>  	s8	y;
> @@ -218,8 +231,13 @@ struct lis3lv02d {
>  	int (*init) (struct lis3lv02d *lis3);
>  	int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
>  	int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
> +	int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
>  
>  	int                     *odrs;     /* Supported output data rates */
> +	u8			*regs;	   /* Regs to store / restore */
> +	int			regs_size;
> +	bool			regs_stored;
> +	u8                      reg_cache[LIS3_NUM_MAX_REG];
>  	u8                      odr_mask;  /* ODR bit mask */
>  	u8			whoami;    /* indicates measurement precision */
>  	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
> @@ -232,6 +250,7 @@ struct lis3lv02d {
>  
>  	struct input_polled_dev	*idev;     /* input device */
>  	struct platform_device	*pdev;     /* platform device */
> +	struct regulator_bulk_data regulators[2];
>  	atomic_t		count;     /* interrupt count after last read */
>  	struct axis_conversion	ac;        /* hw -> logical axis */
>  	int			mapped_btns[3];
> diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
> index b9ed1fb..0852bed 100644
> --- a/drivers/hwmon/lis3lv02d_i2c.c
> +++ b/drivers/hwmon/lis3lv02d_i2c.c
> @@ -30,10 +30,29 @@
>  #include <linux/err.h>
>  #include <linux/i2c.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/delay.h>
>  #include "lis3lv02d.h"
>  
>  #define DRV_NAME 	"lis3lv02d_i2c"
>  
> +static const char reg_vdd[]    = "Vdd";
> +static const char reg_vdd_io[] = "Vdd_IO";
> +
> +static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
> +{
> +	int ret;
> +	if (state == LIS3_REG_OFF) {
> +		ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
> +					lis3->regulators);
> +	} else {
> +		ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
> +					lis3->regulators);
> +		/* Chip needs time to wakeup. Not mentioned in datasheet */
> +		usleep_range(5000, 10000);
> +	}
> +	return ret;
> +}
> +
>  static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
>  {
>  	struct i2c_client *c = lis3->bus_priv;
> @@ -52,6 +71,12 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
>  	u8 reg;
>  	int ret;
>  
> +	lis3_reg_ctrl(lis3, LIS3_REG_ON);
> +
> +	lis3->read(lis3, WHO_AM_I, &reg);
> +	if (lis3->whoami != 0 && reg != lis3->whoami)
What is the purpose of the first test? How can we get here without that being set?
> +		printk(KERN_ERR "lis3: power on failure\n");
> +
>  	/* power up the device */
>  	ret = lis3->read(lis3, CTRL_REG1, &reg);
>  	if (ret < 0)
> @@ -89,16 +114,29 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
>  			goto fail;
>  	}
>  
> +	lis3_dev.regulators[0].supply = reg_vdd;
> +	lis3_dev.regulators[1].supply = reg_vdd_io;
> +	ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(lis3_dev.regulators),
> +				lis3_dev.regulators);
> +	if (ret < 0)
> +		goto fail;
> +
>  	lis3_dev.pdata	  = pdata;
>  	lis3_dev.bus_priv = client;
>  	lis3_dev.init	  = lis3_i2c_init;
>  	lis3_dev.read	  = lis3_i2c_read;
>  	lis3_dev.write	  = lis3_i2c_write;
> +	lis3_dev.reg_ctrl = lis3_reg_ctrl;
>  	lis3_dev.irq	  = client->irq;
>  	lis3_dev.ac	  = lis3lv02d_axis_map;
>  	lis3_dev.pm_dev	  = &client->dev;
>  
>  	i2c_set_clientdata(client, &lis3_dev);
> +
> +	/* Provide power over the init call */
> +	lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
> +	lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
> +
>  	ret = lis3lv02d_init_device(&lis3_dev);
>  fail:
>  	return ret;
> @@ -113,8 +151,11 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
>  		pdata->release_resources();
>  
>  	lis3lv02d_joystick_disable();
> +	lis3lv02d_remove_fs(lis3);
subtle change here... Out of intererst, why did the top level lis3_dev
structure ever exist?  (you can tell I haven't looked closely at this driver
before!) Can remove_fs return an error? 
>  
> -	return lis3lv02d_remove_fs(&lis3_dev);
> +	regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
> +			lis3_dev.regulators);
> +	return 0;
>  }
>  
>  #ifdef CONFIG_PM

WARNING: multiple messages have this Message-ID (diff)
From: Jonathan Cameron <jic23@cam.ac.uk>
To: Samu Onkalo <samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
Cc: eric.piel-VkQ1JFuSMpfAbQlEx87xDw@public.gmane.org,
	khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org,
	guenter.roeck-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org,
	kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
Subject: Re: [lm-sensors] [RFC PATCH 2/9] hwmon: lis3: regulator control
Date: Sat, 02 Oct 2010 17:33:14 +0000	[thread overview]
Message-ID: <4CA76CDA.4040803@cam.ac.uk> (raw)
In-Reply-To: <1285933616-16044-3-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>

On 10/01/10 12:46, Samu Onkalo wrote:
> Based on pm_runtime control, turn lis3 regulators on and off.
> Perform context save and restore on transitions.

As this is a simple save and restore state patch I'm happy to comment on it.

Mostly fine, though I have a couple of minor questions.
> 
> Signed-off-by: Samu Onkalo <samu.p.onkalo@nokia.com>
> ---
>  drivers/hwmon/lis3lv02d.c     |   48 +++++++++++++++++++++++++++++++++++++++++
>  drivers/hwmon/lis3lv02d.h     |   19 ++++++++++++++++
>  drivers/hwmon/lis3lv02d_i2c.c |   43 +++++++++++++++++++++++++++++++++++-
>  3 files changed, 109 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
> index eaa5bf0..23d47ad 100644
> --- a/drivers/hwmon/lis3lv02d.c
> +++ b/drivers/hwmon/lis3lv02d.c
> @@ -223,10 +223,46 @@ fail:
>  	return ret;
>  }
>  
> +/*
> + * Order of registers in the list affects to order of the restore process.
> + * Perhaps it is a good idea to set interrupt enable register as a last one
> + * after all other configurations
> + */
> +static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
> +			       FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
> +			       CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
> +			       CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
> +			       CTRL_REG1, CTRL_REG2, CTRL_REG3};
> +
> +static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
> +			       FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
> +			       DD_THSE_L, DD_THSE_H,
> +			       CTRL_REG1, CTRL_REG3, CTRL_REG2};
> +
> +static inline void lis3_context_save(struct lis3lv02d *lis3)
> +{
> +	int i;
> +	for (i = 0; i < lis3->regs_size; i++)
> +		lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
> +	lis3->regs_stored = true;
> +}
> +
> +static inline void lis3_context_restore(struct lis3lv02d *lis3)
> +{
> +	int i;
> +	if (lis3->regs_stored)
> +		for (i = 0; i < lis3->regs_size; i++)
> +			lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
> +}
> +
>  void lis3lv02d_poweroff(struct lis3lv02d *lis3)
>  {
> +	if (lis3->reg_ctrl)
> +		lis3_context_save(lis3);
>  	/* disable X,Y,Z axis and power down */
>  	lis3->write(lis3, CTRL_REG1, 0x00);
> +	if (lis3->reg_ctrl)
> +		lis3->reg_ctrl(lis3, LIS3_REG_OFF);
>  }
>  EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
>  
> @@ -249,6 +285,8 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
>  		reg |= CTRL2_BDU;
>  		lis3->write(lis3, CTRL_REG2, reg);
>  	}
> +	if (lis3->reg_ctrl)
> +		lis3_context_restore(lis3);
>  }
>  EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
>  
> @@ -718,6 +756,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
>  		dev->odrs = lis3_12_rates;
>  		dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
>  		dev->scale = LIS3_SENSITIVITY_12B;
> +		dev->regs = lis3_wai12_regs;
> +		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
>  		break;
>  	case WAI_8B:
>  		printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
> @@ -727,6 +767,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
>  		dev->odrs = lis3_8_rates;
>  		dev->odr_mask = CTRL1_DR;
>  		dev->scale = LIS3_SENSITIVITY_8B;
> +		dev->regs = lis3_wai8_regs;
> +		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
>  		break;
>  	default:
>  		printk(KERN_ERR DRIVER_NAME
> @@ -734,6 +776,12 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
>  		return -EINVAL;
>  	}
>  
This is a little odd as runtime checks go.  Surely it can only occur in event
of a clear driver bug?  Personally I'd just go with dynamically allocating
the reg_cache to be the right size...
> +	if (dev->regs_size > LIS3_NUM_MAX_REG) {
> +		printk(KERN_ERR DRIVER_NAME
> +			": register cache area is too small");
> +		return -EINVAL;
> +	}
> +
>  	mutex_init(&dev->mutex);
>  
>  	lis3lv02d_add_fs(dev);
> diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
> index 3e8a208..caf3ed1 100644
> --- a/drivers/hwmon/lis3lv02d.h
> +++ b/drivers/hwmon/lis3lv02d.h
> @@ -20,6 +20,7 @@
>   */
>  #include <linux/platform_device.h>
>  #include <linux/input-polldev.h>
> +#include <linux/regulator/consumer.h>
>  
>  /*
>   * This driver tries to support the "digital" accelerometer chips from
> @@ -97,6 +98,15 @@ enum lis3_who_am_i {
>  	WAI_8B		= 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
>  	WAI_6B		= 0x52, /* 6 bits: LIS331DLF - not supported */
>  };
> +/* Number of RW registers in each device for register caching purposes */
You could just enforce this through review, but I guess it doesn't hurt
to have sanity checks... 

> +#define NUM_RW_REGS_12B 21
> +#define NUM_RW_REGS_8B  15
> +
> +#if NUM_RW_REGS_8B > NUM_RW_REGS_12B
> +#define LIS3_NUM_MAX_REG NUM_RW_REGS_8B
> +#else
> +#define LIS3_NUM_MAX_REG NUM_RW_REGS_12B
> +#endif
>  
>  enum lis3lv02d_ctrl1_12b {
>  	CTRL1_Xen	= 0x01,
> @@ -206,6 +216,9 @@ enum lis3lv02d_click_src_8b {
>  	CLICK_IA	= 0x40,
>  };
>  
> +#define LIS3_REG_OFF	0x00
> +#define LIS3_REG_ON	0x01
I think the rest of these are done as enums.  Worth doing that here for
consistency?
> +
>  struct axis_conversion {
>  	s8	x;
>  	s8	y;
> @@ -218,8 +231,13 @@ struct lis3lv02d {
>  	int (*init) (struct lis3lv02d *lis3);
>  	int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
>  	int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
> +	int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
>  
>  	int                     *odrs;     /* Supported output data rates */
> +	u8			*regs;	   /* Regs to store / restore */
> +	int			regs_size;
> +	bool			regs_stored;
> +	u8                      reg_cache[LIS3_NUM_MAX_REG];
>  	u8                      odr_mask;  /* ODR bit mask */
>  	u8			whoami;    /* indicates measurement precision */
>  	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
> @@ -232,6 +250,7 @@ struct lis3lv02d {
>  
>  	struct input_polled_dev	*idev;     /* input device */
>  	struct platform_device	*pdev;     /* platform device */
> +	struct regulator_bulk_data regulators[2];
>  	atomic_t		count;     /* interrupt count after last read */
>  	struct axis_conversion	ac;        /* hw -> logical axis */
>  	int			mapped_btns[3];
> diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
> index b9ed1fb..0852bed 100644
> --- a/drivers/hwmon/lis3lv02d_i2c.c
> +++ b/drivers/hwmon/lis3lv02d_i2c.c
> @@ -30,10 +30,29 @@
>  #include <linux/err.h>
>  #include <linux/i2c.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/delay.h>
>  #include "lis3lv02d.h"
>  
>  #define DRV_NAME 	"lis3lv02d_i2c"
>  
> +static const char reg_vdd[]    = "Vdd";
> +static const char reg_vdd_io[] = "Vdd_IO";
> +
> +static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
> +{
> +	int ret;
> +	if (state = LIS3_REG_OFF) {
> +		ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
> +					lis3->regulators);
> +	} else {
> +		ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
> +					lis3->regulators);
> +		/* Chip needs time to wakeup. Not mentioned in datasheet */
> +		usleep_range(5000, 10000);
> +	}
> +	return ret;
> +}
> +
>  static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
>  {
>  	struct i2c_client *c = lis3->bus_priv;
> @@ -52,6 +71,12 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
>  	u8 reg;
>  	int ret;
>  
> +	lis3_reg_ctrl(lis3, LIS3_REG_ON);
> +
> +	lis3->read(lis3, WHO_AM_I, &reg);
> +	if (lis3->whoami != 0 && reg != lis3->whoami)
What is the purpose of the first test? How can we get here without that being set?
> +		printk(KERN_ERR "lis3: power on failure\n");
> +
>  	/* power up the device */
>  	ret = lis3->read(lis3, CTRL_REG1, &reg);
>  	if (ret < 0)
> @@ -89,16 +114,29 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
>  			goto fail;
>  	}
>  
> +	lis3_dev.regulators[0].supply = reg_vdd;
> +	lis3_dev.regulators[1].supply = reg_vdd_io;
> +	ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(lis3_dev.regulators),
> +				lis3_dev.regulators);
> +	if (ret < 0)
> +		goto fail;
> +
>  	lis3_dev.pdata	  = pdata;
>  	lis3_dev.bus_priv = client;
>  	lis3_dev.init	  = lis3_i2c_init;
>  	lis3_dev.read	  = lis3_i2c_read;
>  	lis3_dev.write	  = lis3_i2c_write;
> +	lis3_dev.reg_ctrl = lis3_reg_ctrl;
>  	lis3_dev.irq	  = client->irq;
>  	lis3_dev.ac	  = lis3lv02d_axis_map;
>  	lis3_dev.pm_dev	  = &client->dev;
>  
>  	i2c_set_clientdata(client, &lis3_dev);
> +
> +	/* Provide power over the init call */
> +	lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
> +	lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
> +
>  	ret = lis3lv02d_init_device(&lis3_dev);
>  fail:
>  	return ret;
> @@ -113,8 +151,11 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
>  		pdata->release_resources();
>  
>  	lis3lv02d_joystick_disable();
> +	lis3lv02d_remove_fs(lis3);
subtle change here... Out of intererst, why did the top level lis3_dev
structure ever exist?  (you can tell I haven't looked closely at this driver
before!) Can remove_fs return an error? 
>  
> -	return lis3lv02d_remove_fs(&lis3_dev);
> +	regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
> +			lis3_dev.regulators);
> +	return 0;
>  }
>  
>  #ifdef CONFIG_PM


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

  parent reply	other threads:[~2010-10-02 17:33 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-01 11:46 [RFC PATCH 0/9] lis3 accelerator feature update Samu Onkalo
2010-10-01 11:46 ` [lm-sensors] " Samu Onkalo
2010-10-01 11:46 ` [RFC PATCH 6/9] hwmon: lis3: New parameters to platform data Samu Onkalo
2010-10-01 11:46   ` [lm-sensors] [RFC PATCH 6/9] hwmon: lis3: New parameters to Samu Onkalo
     [not found]   ` <1285933616-16044-7-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
2010-10-04 11:37     ` [lm-sensors] [RFC PATCH 6/9] hwmon: lis3: New parameters to platform data Jonathan Cameron
2010-10-04 11:37       ` [lm-sensors] [RFC PATCH 6/9] hwmon: lis3: New parameters Jonathan Cameron
     [not found] ` <1285933616-16044-1-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
2010-10-01 11:46   ` [RFC PATCH 1/9] hwmon: lis3: pm_runtime support Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] " Samu Onkalo
     [not found]     ` <1285933616-16044-2-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
2010-10-02 17:14       ` Jonathan Cameron
2010-10-02 17:14         ` Jonathan Cameron
     [not found]         ` <4CA76875.1040508-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-10-03  5:03           ` Onkalo Samu
2010-10-03  5:03             ` Onkalo Samu
     [not found]             ` <1286082228.2064.14.camel-Vo7XL3ix0D0UEupzmRo7jhl4MBrZKKet0E9HWUfgJXw@public.gmane.org>
2010-10-03 11:18               ` Jonathan Cameron
2010-10-03 11:18                 ` Jonathan Cameron
2010-10-01 11:46   ` [RFC PATCH 2/9] hwmon: lis3: regulator control Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] " Samu Onkalo
     [not found]     ` <1285933616-16044-3-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
2010-10-02 17:33       ` Jonathan Cameron [this message]
2010-10-02 17:33         ` Jonathan Cameron
     [not found]         ` <4CA76CDA.4040803-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-10-03  5:25           ` Onkalo Samu
2010-10-03  5:25             ` Onkalo Samu
     [not found]             ` <1286083558.2064.35.camel-Vo7XL3ix0D0UEupzmRo7jhl4MBrZKKet0E9HWUfgJXw@public.gmane.org>
2010-10-03 11:21               ` Jonathan Cameron
2010-10-03 11:21                 ` Jonathan Cameron
2010-10-03 11:53                 ` David Lutolf
2010-10-03 11:53                   ` [lm-sensors] " David Lutolf
2010-10-01 11:46   ` [RFC PATCH 3/9] hwmon: lis3: Cleanup interrupt handling Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] " Samu Onkalo
2010-10-01 11:46   ` [RFC PATCH 4/9] hwmon: lis3: Update coordinates at polled device open Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] [RFC PATCH 4/9] hwmon: lis3: Update coordinates at Samu Onkalo
2010-10-01 11:46   ` [RFC PATCH 5/9] hwmon: lis3: Power on corrections Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] " Samu Onkalo
     [not found]     ` <1285933616-16044-6-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
2010-10-02 17:43       ` Jonathan Cameron
2010-10-02 17:43         ` Jonathan Cameron
2010-10-01 11:46   ` [RFC PATCH 7/9] hwmon: lis3: Adjust fuzziness for 8 bit device Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] [RFC PATCH 7/9] hwmon: lis3: Adjust fuzziness for 8 Samu Onkalo
2010-10-01 11:46   ` [RFC PATCH 8/9] hwmon: lis3: use block read to access data registers Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] [RFC PATCH 8/9] hwmon: lis3: use block read to access Samu Onkalo
     [not found]     ` <1285933616-16044-9-git-send-email-samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org>
2010-10-04 11:41       ` [lm-sensors] [RFC PATCH 8/9] hwmon: lis3: use block read to access data registers Jonathan Cameron
2010-10-04 11:41         ` [lm-sensors] [RFC PATCH 8/9] hwmon: lis3: use block read to Jonathan Cameron
     [not found]         ` <4CA9BD6E.6040002-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-10-04 13:29           ` [lm-sensors] [RFC PATCH 8/9] hwmon: lis3: use block read to access data registers Guenter Roeck
2010-10-04 13:29             ` [lm-sensors] [RFC PATCH 8/9] hwmon: lis3: use block read to Guenter Roeck
2010-10-01 11:46   ` [RFC PATCH 9/9] hwmon: lis3: Enhance lis3 selftest with IRQ line test Samu Onkalo
2010-10-01 11:46     ` [lm-sensors] [RFC PATCH 9/9] hwmon: lis3: Enhance lis3 selftest Samu Onkalo
2010-10-02  2:53   ` [RFC PATCH 0/9] lis3 accelerator feature update Guenter Roeck
2010-10-02  2:53     ` [lm-sensors] " Guenter Roeck
     [not found]     ` <20101002025311.GA25875-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org>
2010-10-02  8:25       ` Jean Delvare
2010-10-02  8:25         ` [lm-sensors] " Jean Delvare
     [not found]         ` <20101002102528.2955d95a-R0o5gVi9kd7kN2dkZ6Wm7A@public.gmane.org>
2010-10-02 12:27           ` Jonathan Cameron
2010-10-02 12:27             ` Jonathan Cameron
     [not found]             ` <4CA72519.1070600-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-10-02 13:16               ` Guenter Roeck
2010-10-02 13:16                 ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4CA76CDA.4040803@cam.ac.uk \
    --to=jic23-kwpb1pkirijaa/9udqfwiw@public.gmane.org \
    --cc=eric.piel-VkQ1JFuSMpfAbQlEx87xDw@public.gmane.org \
    --cc=guenter.roeck-IzeFyvvaP7pWk0Htik3J/w@public.gmane.org \
    --cc=khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org \
    --cc=kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org \
    --cc=samu.p.onkalo-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.