From nobody Fri Dec 26 23:21:31 2025 Received: from mg.richtek.com (mg.richtek.com [220.130.44.152]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6F6ADE544; Tue, 2 Jan 2024 11:28:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=richtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=richtek.com X-MailGates: (SIP:2,PASS,NONE)(compute_score:DELIVER,40,3) Received: from 192.168.10.47 by mg.richtek.com with MailGates ESMTPS Server V6.0(636824:0:AUTH_RELAY) (envelope-from ) (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256/256); Tue, 02 Jan 2024 19:28:25 +0800 (CST) Received: from ex3.rt.l (192.168.10.46) by ex4.rt.l (192.168.10.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.27; Tue, 2 Jan 2024 19:28:24 +0800 Received: from linuxcarl2.richtek.com (192.168.10.154) by ex3.rt.l (192.168.10.45) with Microsoft SMTP Server id 15.2.1258.27 via Frontend Transport; Tue, 2 Jan 2024 19:28:24 +0800 From: To: Jonathan Cameron , Krzysztof Kozlowski , Conor Dooley CC: Lars-Peter Clausen , Rob Herring , ChiYuan Huang , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , , , Subject: [PATCH v3 2/2] iio: adc: rtq6056: Add support for the whole RTQ6056 family Date: Tue, 2 Jan 2024 19:28:22 +0800 Message-ID: X-Mailer: git-send-email 1.8.3.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: ChiYuan Huang RTQ6053 and RTQ6059 are the same series of RTQ6056. The respective differences with RTQ6056 are listed below RTQ6053 - chip package type RTQ6059 - Reduce the pinout for vbus sensing pin - Some internal ADC scaling change Signed-off-by: ChiYuan Huang --- v3 - Resotre the enum for control field. - Put all the predefined datas/callbacks in dev_data. - Remove the unused 'rtq6059_info'. - Change 'default_conv_time' to 'default_conv_time_us'. - Move the comment for default config above the dev_data setting line. v2 - Remove rtq6053 in DT match table and make rtq6053 fallback compatible with rtq6056 --- drivers/iio/adc/rtq6056.c | 270 +++++++++++++++++++++++++++++++++++--- 1 file changed, 251 insertions(+), 19 deletions(-) diff --git a/drivers/iio/adc/rtq6056.c b/drivers/iio/adc/rtq6056.c index ad4cea6839b2..c87d78e161ce 100644 --- a/drivers/iio/adc/rtq6056.c +++ b/drivers/iio/adc/rtq6056.c @@ -39,6 +39,16 @@ #define RTQ6056_DEFAULT_CONFIG 0x4127 #define RTQ6056_CONT_ALLON 7 =20 +#define RTQ6059_DEFAULT_CONFIG 0x3C47 +#define RTQ6059_VBUS_LSB_OFFSET 3 +#define RTQ6059_AVG_BASE 8 + +enum { + RICHTEK_DEV_RTQ6056 =3D 0, + RICHTEK_DEV_RTQ6059, + RICHTEK_DEV_MAX +}; + enum { RTQ6056_CH_VSHUNT =3D 0, RTQ6056_CH_VBUS, @@ -56,10 +66,28 @@ enum { F_MAX_FIELDS }; =20 +struct rtq6056_priv; + +struct richtek_dev_data { + bool fixed_samp_freq; + u8 vbus_offset; + int default_conv_time_us; + unsigned int default_config; + unsigned int calib_coefficient; + const int *avg_sample_list; + int avg_sample_list_length; + const struct reg_field *reg_fields; + const struct iio_chan_spec *channels; + int num_channels; + int (*read_scale)(struct iio_chan_spec const *ch, int *val, int *val2); + int (*set_average)(struct rtq6056_priv *priv, int val); +}; + struct rtq6056_priv { struct device *dev; struct regmap *regmap; struct regmap_field *rm_fields[F_MAX_FIELDS]; + const struct richtek_dev_data *devdata; u32 shunt_resistor_uohm; int vshuntct_us; int vbusct_us; @@ -74,6 +102,14 @@ static const struct reg_field rtq6056_reg_fields[F_MAX_= FIELDS] =3D { [F_RESET] =3D REG_FIELD(RTQ6056_REG_CONFIG, 15, 15), }; =20 +static const struct reg_field rtq6059_reg_fields[F_MAX_FIELDS] =3D { + [F_OPMODE] =3D REG_FIELD(RTQ6056_REG_CONFIG, 0, 2), + [F_VSHUNTCT] =3D REG_FIELD(RTQ6056_REG_CONFIG, 3, 6), + [F_VBUSCT] =3D REG_FIELD(RTQ6056_REG_CONFIG, 7, 10), + [F_AVG] =3D REG_FIELD(RTQ6056_REG_CONFIG, 11, 12), + [F_RESET] =3D REG_FIELD(RTQ6056_REG_CONFIG, 15, 15), +}; + static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1= ] =3D { { .type =3D IIO_VOLTAGE, @@ -151,10 +187,93 @@ static const struct iio_chan_spec rtq6056_channels[RT= Q6056_MAX_CHANNEL + 1] =3D { IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL), }; =20 +/* + * Difference between RTQ6056 and RTQ6059 + * - Fixed sampling conversion time + * - Average sample numbers + * - Channel scale + * - calibration coefficient + */ +static const struct iio_chan_spec rtq6059_channels[RTQ6056_MAX_CHANNEL + 1= ] =3D { + { + .type =3D IIO_VOLTAGE, + .indexed =3D 1, + .channel =3D 0, + .address =3D RTQ6056_REG_SHUNTVOLT, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all_available =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RA= TIO), + .scan_index =3D 0, + .scan_type =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU, + }, + }, + { + .type =3D IIO_VOLTAGE, + .indexed =3D 1, + .channel =3D 1, + .address =3D RTQ6056_REG_BUSVOLT, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all_available =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RA= TIO), + .scan_index =3D 1, + .scan_type =3D { + .sign =3D 'u', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU, + }, + }, + { + .type =3D IIO_POWER, + .indexed =3D 1, + .channel =3D 2, + .address =3D RTQ6056_REG_POWER, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all_available =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RA= TIO), + .scan_index =3D 2, + .scan_type =3D { + .sign =3D 'u', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU, + }, + }, + { + .type =3D IIO_CURRENT, + .indexed =3D 1, + .channel =3D 3, + .address =3D RTQ6056_REG_CURRENT, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_all_available =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RA= TIO), + .scan_index =3D 3, + .scan_type =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL), +}; + static int rtq6056_adc_read_channel(struct rtq6056_priv *priv, struct iio_chan_spec const *ch, int *val) { + const struct richtek_dev_data *devdata =3D priv->devdata; struct device *dev =3D priv->dev; unsigned int addr =3D ch->address; unsigned int regval; @@ -168,10 +287,21 @@ static int rtq6056_adc_read_channel(struct rtq6056_pr= iv *priv, return ret; =20 /* Power and VBUS is unsigned 16-bit, others are signed 16-bit */ - if (addr =3D=3D RTQ6056_REG_BUSVOLT || addr =3D=3D RTQ6056_REG_POWER) + switch (addr) { + case RTQ6056_REG_BUSVOLT: + regval >>=3D devdata->vbus_offset; *val =3D regval; - else + break; + case RTQ6056_REG_POWER: + *val =3D regval; + break; + case RTQ6056_REG_SHUNTVOLT: + case RTQ6056_REG_CURRENT: *val =3D sign_extend32(regval, 16); + break; + default: + return -EINVAL; + } =20 return IIO_VAL_INT; } @@ -199,6 +329,28 @@ static int rtq6056_adc_read_scale(struct iio_chan_spec= const *ch, int *val, } } =20 +static int rtq6059_adc_read_scale(struct iio_chan_spec const *ch, int *val, + int *val2) +{ + switch (ch->address) { + case RTQ6056_REG_SHUNTVOLT: + /* VSHUNT lsb 10uV */ + *val =3D 10000; + *val2 =3D 1000000; + return IIO_VAL_FRACTIONAL; + case RTQ6056_REG_BUSVOLT: + /* VBUS lsb 4mV */ + *val =3D 4; + return IIO_VAL_INT; + case RTQ6056_REG_POWER: + /* Power lsb 20mW */ + *val =3D 20; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + /* * Sample frequency for channel VSHUNT and VBUS. The indices correspond * with the bit value expected by the chip. And it can be found at @@ -248,6 +400,10 @@ static const int rtq6056_avg_sample_list[] =3D { 1, 4, 16, 64, 128, 256, 512, 1024, }; =20 +static const int rtq6059_avg_sample_list[] =3D { + 1, 2, 4, 8, 16, 32, 64, 128, +}; + static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val) { unsigned int selector; @@ -268,6 +424,30 @@ static int rtq6056_adc_set_average(struct rtq6056_priv= *priv, int val) return 0; } =20 +static int rtq6059_adc_set_average(struct rtq6056_priv *priv, int val) +{ + unsigned int selector; + int ret; + + if (val > 128 || val < 1) + return -EINVAL; + + /* The supported average sample is 2^x (x from 0 to 7) */ + selector =3D fls(val) - 1; + + ret =3D regmap_field_write(priv->rm_fields[F_VBUSCT], + RTQ6059_AVG_BASE + selector); + if (ret) + return ret; + + ret =3D regmap_field_write(priv->rm_fields[F_VSHUNTCT], + RTQ6059_AVG_BASE + selector); + + priv->avg_sample =3D BIT(selector + 1); + + return 0; +} + static int rtq6056_adc_get_sample_freq(struct rtq6056_priv *priv, struct iio_chan_spec const *ch, int *val) { @@ -292,12 +472,13 @@ static int rtq6056_adc_read_raw(struct iio_dev *indio= _dev, int *val2, long mask) { struct rtq6056_priv *priv =3D iio_priv(indio_dev); + const struct richtek_dev_data *devdata =3D priv->devdata; =20 switch (mask) { case IIO_CHAN_INFO_RAW: return rtq6056_adc_read_channel(priv, chan, val); case IIO_CHAN_INFO_SCALE: - return rtq6056_adc_read_scale(chan, val, val2); + return devdata->read_scale(chan, val, val2); case IIO_CHAN_INFO_OVERSAMPLING_RATIO: *val =3D priv->avg_sample; return IIO_VAL_INT; @@ -313,6 +494,9 @@ static int rtq6056_adc_read_avail(struct iio_dev *indio= _dev, const int **vals, int *type, int *length, long mask) { + struct rtq6056_priv *priv =3D iio_priv(indio_dev); + const struct richtek_dev_data *devdata =3D priv->devdata; + switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: *vals =3D rtq6056_samp_freq_list; @@ -320,9 +504,9 @@ static int rtq6056_adc_read_avail(struct iio_dev *indio= _dev, *length =3D ARRAY_SIZE(rtq6056_samp_freq_list); return IIO_AVAIL_LIST; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - *vals =3D rtq6056_avg_sample_list; + *vals =3D devdata->avg_sample_list; + *length =3D devdata->avg_sample_list_length; *type =3D IIO_VAL_INT; - *length =3D ARRAY_SIZE(rtq6056_avg_sample_list); return IIO_AVAIL_LIST; default: return -EINVAL; @@ -334,6 +518,7 @@ static int rtq6056_adc_write_raw(struct iio_dev *indio_= dev, int val2, long mask) { struct rtq6056_priv *priv =3D iio_priv(indio_dev); + const struct richtek_dev_data *devdata =3D priv->devdata; int ret; =20 ret =3D iio_device_claim_direct_mode(indio_dev); @@ -342,10 +527,13 @@ static int rtq6056_adc_write_raw(struct iio_dev *indi= o_dev, =20 switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: - ret =3D rtq6056_adc_set_samp_freq(priv, chan, val); + if (devdata->fixed_samp_freq) + ret =3D -EINVAL; + else + ret =3D rtq6056_adc_set_samp_freq(priv, chan, val); break; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - ret =3D rtq6056_adc_set_average(priv, val); + ret =3D devdata->set_average(priv, val); break; default: ret =3D -EINVAL; @@ -374,6 +562,7 @@ static int rtq6056_adc_read_label(struct iio_dev *indio= _dev, static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv, int resistor_uohm) { + const struct richtek_dev_data *devdata =3D priv->devdata; unsigned int calib_val; int ret; =20 @@ -382,8 +571,8 @@ static int rtq6056_set_shunt_resistor(struct rtq6056_pr= iv *priv, return -EINVAL; } =20 - /* calibration =3D 5120000 / (Rshunt (uOhm) * current lsb (1mA)) */ - calib_val =3D 5120000 / resistor_uohm; + /* calibration =3D coefficient / (Rshunt (uOhm) * current lsb (1mA)) */ + calib_val =3D devdata->calib_coefficient / resistor_uohm; ret =3D regmap_write(priv->regmap, RTQ6056_REG_CALIBRATION, calib_val); if (ret) return ret; @@ -450,6 +639,7 @@ static irqreturn_t rtq6056_buffer_trigger_handler(int i= rq, void *p) struct iio_poll_func *pf =3D p; struct iio_dev *indio_dev =3D pf->indio_dev; struct rtq6056_priv *priv =3D iio_priv(indio_dev); + const struct richtek_dev_data *devdata =3D priv->devdata; struct device *dev =3D priv->dev; struct { u16 vals[RTQ6056_MAX_CHANNEL]; @@ -469,6 +659,9 @@ static irqreturn_t rtq6056_buffer_trigger_handler(int i= rq, void *p) if (ret) goto out; =20 + if (addr =3D=3D RTQ6056_REG_BUSVOLT) + raw >>=3D devdata->vbus_offset; + data.vals[i++] =3D raw; } =20 @@ -528,20 +721,26 @@ static int rtq6056_probe(struct i2c_client *i2c) struct rtq6056_priv *priv; struct device *dev =3D &i2c->dev; struct regmap *regmap; + const struct richtek_dev_data *devdata; unsigned int vendor_id, shunt_resistor_uohm; int ret; =20 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA)) return -EOPNOTSUPP; =20 + devdata =3D device_get_match_data(dev); + if (!devdata) + return dev_err_probe(dev, -EINVAL, "Invalid dev data\n"); + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*priv)); if (!indio_dev) return -ENOMEM; =20 priv =3D iio_priv(indio_dev); priv->dev =3D dev; - priv->vshuntct_us =3D priv->vbusct_us =3D 1037; + priv->vshuntct_us =3D priv->vbusct_us =3D devdata->default_conv_time_us; priv->avg_sample =3D 1; + priv->devdata =3D devdata; i2c_set_clientdata(i2c, priv); =20 regmap =3D devm_regmap_init_i2c(i2c, &rtq6056_regmap_config); @@ -561,15 +760,11 @@ static int rtq6056_probe(struct i2c_client *i2c) "Invalid vendor id 0x%04x\n", vendor_id); =20 ret =3D devm_regmap_field_bulk_alloc(dev, regmap, priv->rm_fields, - rtq6056_reg_fields, F_MAX_FIELDS); + devdata->reg_fields, F_MAX_FIELDS); if (ret) return dev_err_probe(dev, ret, "Failed to init regmap field\n"); =20 - /* - * By default, configure average sample as 1, bus and shunt conversion - * time as 1037 microsecond, and operating mode to all on. - */ - ret =3D regmap_write(regmap, RTQ6056_REG_CONFIG, RTQ6056_DEFAULT_CONFIG); + ret =3D regmap_write(regmap, RTQ6056_REG_CONFIG, devdata->default_config); if (ret) return dev_err_probe(dev, ret, "Failed to enable continuous sensing\n"); @@ -598,8 +793,8 @@ static int rtq6056_probe(struct i2c_client *i2c) =20 indio_dev->name =3D "rtq6056"; indio_dev->modes =3D INDIO_DIRECT_MODE; - indio_dev->channels =3D rtq6056_channels; - indio_dev->num_channels =3D ARRAY_SIZE(rtq6056_channels); + indio_dev->channels =3D devdata->channels; + indio_dev->num_channels =3D RTQ6056_MAX_CHANNEL + 1; indio_dev->info =3D &rtq6056_info; =20 ret =3D devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, @@ -640,8 +835,45 @@ static int rtq6056_runtime_resume(struct device *dev) static DEFINE_RUNTIME_DEV_PM_OPS(rtq6056_pm_ops, rtq6056_runtime_suspend, rtq6056_runtime_resume, NULL); =20 +static const struct richtek_dev_data rtq6056_devdata =3D { + .default_conv_time_us =3D 1037, + .calib_coefficient =3D 5120000, + /* + * By default, configure average sample as 1, bus and shunt conversion + * time as 1037 microsecond, and operating mode to all on. + */ + .default_config =3D RTQ6056_DEFAULT_CONFIG, + .avg_sample_list =3D rtq6056_avg_sample_list, + .avg_sample_list_length =3D ARRAY_SIZE(rtq6056_avg_sample_list), + .reg_fields =3D rtq6056_reg_fields, + .channels =3D rtq6056_channels, + .num_channels =3D ARRAY_SIZE(rtq6056_channels), + .read_scale =3D rtq6056_adc_read_scale, + .set_average =3D rtq6056_adc_set_average, +}; + +static const struct richtek_dev_data rtq6059_devdata =3D { + .fixed_samp_freq =3D true, + .vbus_offset =3D RTQ6059_VBUS_LSB_OFFSET, + .default_conv_time_us =3D 532, + .calib_coefficient =3D 40960000, + /* + * By default, configure average sample as 1, bus and shunt conversion + * time as 532 microsecond, and operating mode to all on. + */ + .default_config =3D RTQ6059_DEFAULT_CONFIG, + .avg_sample_list =3D rtq6059_avg_sample_list, + .avg_sample_list_length =3D ARRAY_SIZE(rtq6059_avg_sample_list), + .reg_fields =3D rtq6059_reg_fields, + .channels =3D rtq6059_channels, + .num_channels =3D ARRAY_SIZE(rtq6059_channels), + .read_scale =3D rtq6059_adc_read_scale, + .set_average =3D rtq6059_adc_set_average, +}; + static const struct of_device_id rtq6056_device_match[] =3D { - { .compatible =3D "richtek,rtq6056" }, + { .compatible =3D "richtek,rtq6056", .data =3D &rtq6056_devdata }, + { .compatible =3D "richtek,rtq6059", .data =3D &rtq6059_devdata }, {} }; MODULE_DEVICE_TABLE(of, rtq6056_device_match); --=20 2.34.1