From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Return-path: Received: from mail-pg1-f195.google.com ([209.85.215.195]:43898 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728197AbeI2WCk (ORCPT ); Sat, 29 Sep 2018 18:02:40 -0400 Date: Sat, 29 Sep 2018 08:33:46 -0700 From: Guenter Roeck To: Nicolin Chen Cc: jdelvare@suse.com, afd@ti.com, linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH 2/2] hwmon: ina3221: Add suspend and resume functions Message-ID: <20180929153346.GA26651@roeck-us.net> References: <20180928214921.11528-1-nicoleotsuka@gmail.com> <20180928214921.11528-3-nicoleotsuka@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180928214921.11528-3-nicoleotsuka@gmail.com> Sender: linux-hwmon-owner@vger.kernel.org List-Id: linux-hwmon@vger.kernel.org On Fri, Sep 28, 2018 at 02:49:21PM -0700, Nicolin Chen wrote: > Depending on the hardware design, an INA3221 chip might lose > its power during system suspend/resume. So this patch adds > a pair of suspend and resume functions to cache the register > values including config register value and limit settings. > > Signed-off-by: Nicolin Chen > --- > drivers/hwmon/ina3221.c | 54 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 54 insertions(+) > > diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c > index cfe65ff01051..26f66f728b27 100644 > --- a/drivers/hwmon/ina3221.c > +++ b/drivers/hwmon/ina3221.c > @@ -91,11 +91,13 @@ static const unsigned int register_channel[] = { > * @regmap: Register map of the device > * @fields: Register fields of the device > * @shunt_resistors: Array of resistor values per channel > + * @reg_config: Register value of INA3221_CONFIG > */ > struct ina3221_data { > struct regmap *regmap; > struct regmap_field *fields[F_MAX_FIELDS]; > int shunt_resistors[INA3221_NUM_CHANNELS]; > + u32 reg_config; > }; > > static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, > @@ -415,8 +417,59 @@ static int ina3221_probe(struct i2c_client *client, > return PTR_ERR(hwmon_dev); > } > > + dev_set_drvdata(dev, ina); > + > + return 0; > +} > + > +#ifdef CONFIG_PM > +static int ina3221_suspend(struct device *dev) > +{ > + struct ina3221_data *ina = dev_get_drvdata(dev); > + int ret; > + > + /* Save config register value and enable cache-only */ > + ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config); > + if (ret) > + return ret; > + Would it make sense to explicitly disable all channels here ? Thanks, Guenter > + regcache_cache_only(ina->regmap, true); > + regcache_mark_dirty(ina->regmap); > + > + return 0; > +} > + > +static int ina3221_resume(struct device *dev) > +{ > + struct ina3221_data *ina = dev_get_drvdata(dev); > + int ret; > + > + regcache_cache_only(ina->regmap, false); > + > + /* Software reset the chip */ > + ret = regmap_field_write(ina->fields[F_RST], true); > + if (ret) { > + dev_err(dev, "Unable to reset device\n"); > + return ret; > + } > + > + /* Restore cached register values to hardware */ > + ret = regcache_sync(ina->regmap); > + if (ret) > + return ret; > + > + /* Restore config register value to hardware */ > + ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config); > + if (ret) > + return ret; > + > return 0; > } > +#endif > + > +static const struct dev_pm_ops ina3221_pm = { > + SET_SYSTEM_SLEEP_PM_OPS(ina3221_suspend, ina3221_resume) > +}; > > static const struct of_device_id ina3221_of_match_table[] = { > { .compatible = "ti,ina3221", }, > @@ -435,6 +488,7 @@ static struct i2c_driver ina3221_i2c_driver = { > .driver = { > .name = INA3221_DRIVER_NAME, > .of_match_table = ina3221_of_match_table, > + .pm = &ina3221_pm, > }, > .id_table = ina3221_ids, > }; > -- > 2.17.1 >