Re: [PATCH 02/12] hwmon: lis3: regulator control
Op 22-10-10 13:57, Samu Onkalo schreef: Based on pm_runtime control, turn lis3 regulators on and off. Perform context save and restore on transitions. Feature is optional and must be enabled in platform data. Signed-off-by: Samu Onkalo I have very little knowledge about regulators, but for what I could understand it looks fine... Acked-by: Eric Piel --- drivers/hwmon/lis3lv02d.c | 52 ++ drivers/hwmon/lis3lv02d.h | 12 + drivers/hwmon/lis3lv02d_i2c.c | 55 - include/linux/lis3lv02d.h |2 + 4 files changed, 120 insertions(+), 1 deletions(-) diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 412ddc3..ade6f3a 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -223,10 +224,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 +286,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); @@ -640,6 +679,7 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3) pm_runtime_disable(lis3->pm_dev); pm_runtime_set_suspended(lis3->pm_dev); } + kfree(lis3->reg_cache); return 0; } EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); @@ -719,6 +759,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"); @@ -728,6 +770,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 @@ -735,6 +779,14 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) return -EINVAL; } + dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs), +sizeof(lis3_wai12_regs)), GFP_KERNEL); + + if (dev->reg_cache == NULL) { + printk(KERN_ERR DRIVER_NAME "out of memory\n"); + return -ENOMEM; + } + mutex_init(&dev->mutex); lis3lv02d_add_fs(dev); diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h index 3e8a208..7661e59 100644 --- a/drivers/hwmon/lis3lv02d.h +++ b/drivers/hwmon/lis3lv02d.h @@ -20,6 +20,7 @@ */ #include #include +#include /* * This driver tries to support the "digital" accelerometer chips from @@ -206,6 +207,11 @@ enum lis3lv02d_click_src_8b { CLICK_IA= 0x40, }; +enum lis3lv02d_reg_state { + LIS3_REG_OFF= 0x00, + LIS3_REG_ON = 0x01, +}; + struct axis_conver
Re: [PATCH 02/12] hwmon: lis3: regulator control
On 10/22/10 12:57, Samu Onkalo wrote: > Based on pm_runtime control, turn lis3 regulators on and off. > Perform context save and restore on transitions. > > Feature is optional and must be enabled in platform data. Answers all my queries on the previous version > > Signed-off-by: Samu Onkalo Acked-by: Jonathan Cameron > --- > drivers/hwmon/lis3lv02d.c | 52 ++ > drivers/hwmon/lis3lv02d.h | 12 + > drivers/hwmon/lis3lv02d_i2c.c | 55 > - > include/linux/lis3lv02d.h |2 + > 4 files changed, 120 insertions(+), 1 deletions(-) > > diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c > index 412ddc3..ade6f3a 100644 > --- a/drivers/hwmon/lis3lv02d.c > +++ b/drivers/hwmon/lis3lv02d.c > @@ -31,6 +31,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -223,10 +224,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 +286,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); > > @@ -640,6 +679,7 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3) > pm_runtime_disable(lis3->pm_dev); > pm_runtime_set_suspended(lis3->pm_dev); > } > + kfree(lis3->reg_cache); > return 0; > } > EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); > @@ -719,6 +759,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"); > @@ -728,6 +770,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 > @@ -735,6 +779,14 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) > return -EINVAL; > } > > + dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs), > + sizeof(lis3_wai12_regs)), GFP_KERNEL); > + > + if (dev->reg_cache == NULL) { > + printk(KERN_ERR DRIVER_NAME "out of memory\n"); > + return -ENOMEM; > + } > + > mutex_init(&dev->mutex); > > lis3lv02d_add_fs(dev); > diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h > index 3e8a208..7661e59 100644 > --- a/drivers/hwmon/lis3lv02d.h > +++ b/drivers/hwmon/lis3lv02d.h > @@ -20,6 +20,7 @@ > */ > #include > #include > +#include > > /* > * This driver tries to support the "digital" accelerometer chips from > @@ -206,6 +207,11 @@ enum lis3lv02d_click_src_8b { > CLICK_IA= 0x40, > }; > > +enum lis3lv0