14396f45dSChiYuan Huang // SPDX-License-Identifier: GPL-2.0
24396f45dSChiYuan Huang /*
34396f45dSChiYuan Huang * Copyright (c) 2022 Richtek Technology Corp.
44396f45dSChiYuan Huang *
54396f45dSChiYuan Huang * ChiYuan Huang <cy_huang@richtek.com>
64396f45dSChiYuan Huang */
74396f45dSChiYuan Huang
84396f45dSChiYuan Huang #include <linux/bitops.h>
94396f45dSChiYuan Huang #include <linux/delay.h>
104396f45dSChiYuan Huang #include <linux/i2c.h>
114396f45dSChiYuan Huang #include <linux/kernel.h>
124396f45dSChiYuan Huang #include <linux/mod_devicetable.h>
134396f45dSChiYuan Huang #include <linux/module.h>
144396f45dSChiYuan Huang #include <linux/pm_runtime.h>
154396f45dSChiYuan Huang #include <linux/property.h>
164396f45dSChiYuan Huang #include <linux/regmap.h>
174396f45dSChiYuan Huang #include <linux/sysfs.h>
184396f45dSChiYuan Huang #include <linux/types.h>
194396f45dSChiYuan Huang #include <linux/util_macros.h>
204396f45dSChiYuan Huang
214396f45dSChiYuan Huang #include <linux/iio/buffer.h>
224396f45dSChiYuan Huang #include <linux/iio/iio.h>
234396f45dSChiYuan Huang #include <linux/iio/sysfs.h>
244396f45dSChiYuan Huang #include <linux/iio/trigger_consumer.h>
254396f45dSChiYuan Huang #include <linux/iio/triggered_buffer.h>
264396f45dSChiYuan Huang
274396f45dSChiYuan Huang #define RTQ6056_REG_CONFIG 0x00
284396f45dSChiYuan Huang #define RTQ6056_REG_SHUNTVOLT 0x01
294396f45dSChiYuan Huang #define RTQ6056_REG_BUSVOLT 0x02
304396f45dSChiYuan Huang #define RTQ6056_REG_POWER 0x03
314396f45dSChiYuan Huang #define RTQ6056_REG_CURRENT 0x04
324396f45dSChiYuan Huang #define RTQ6056_REG_CALIBRATION 0x05
334396f45dSChiYuan Huang #define RTQ6056_REG_MASKENABLE 0x06
344396f45dSChiYuan Huang #define RTQ6056_REG_ALERTLIMIT 0x07
354396f45dSChiYuan Huang #define RTQ6056_REG_MANUFACTID 0xFE
364396f45dSChiYuan Huang #define RTQ6056_REG_DIEID 0xFF
374396f45dSChiYuan Huang
384396f45dSChiYuan Huang #define RTQ6056_VENDOR_ID 0x1214
394396f45dSChiYuan Huang #define RTQ6056_DEFAULT_CONFIG 0x4127
404396f45dSChiYuan Huang #define RTQ6056_CONT_ALLON 7
414396f45dSChiYuan Huang
424396f45dSChiYuan Huang enum {
434396f45dSChiYuan Huang RTQ6056_CH_VSHUNT = 0,
444396f45dSChiYuan Huang RTQ6056_CH_VBUS,
454396f45dSChiYuan Huang RTQ6056_CH_POWER,
464396f45dSChiYuan Huang RTQ6056_CH_CURRENT,
474396f45dSChiYuan Huang RTQ6056_MAX_CHANNEL
484396f45dSChiYuan Huang };
494396f45dSChiYuan Huang
504396f45dSChiYuan Huang enum {
514396f45dSChiYuan Huang F_OPMODE = 0,
524396f45dSChiYuan Huang F_VSHUNTCT,
534396f45dSChiYuan Huang F_VBUSCT,
544396f45dSChiYuan Huang F_AVG,
554396f45dSChiYuan Huang F_RESET,
564396f45dSChiYuan Huang F_MAX_FIELDS
574396f45dSChiYuan Huang };
584396f45dSChiYuan Huang
594396f45dSChiYuan Huang struct rtq6056_priv {
604396f45dSChiYuan Huang struct device *dev;
614396f45dSChiYuan Huang struct regmap *regmap;
624396f45dSChiYuan Huang struct regmap_field *rm_fields[F_MAX_FIELDS];
634396f45dSChiYuan Huang u32 shunt_resistor_uohm;
644396f45dSChiYuan Huang int vshuntct_us;
654396f45dSChiYuan Huang int vbusct_us;
664396f45dSChiYuan Huang int avg_sample;
674396f45dSChiYuan Huang };
684396f45dSChiYuan Huang
694396f45dSChiYuan Huang static const struct reg_field rtq6056_reg_fields[F_MAX_FIELDS] = {
704396f45dSChiYuan Huang [F_OPMODE] = REG_FIELD(RTQ6056_REG_CONFIG, 0, 2),
714396f45dSChiYuan Huang [F_VSHUNTCT] = REG_FIELD(RTQ6056_REG_CONFIG, 3, 5),
724396f45dSChiYuan Huang [F_VBUSCT] = REG_FIELD(RTQ6056_REG_CONFIG, 6, 8),
734396f45dSChiYuan Huang [F_AVG] = REG_FIELD(RTQ6056_REG_CONFIG, 9, 11),
744396f45dSChiYuan Huang [F_RESET] = REG_FIELD(RTQ6056_REG_CONFIG, 15, 15),
754396f45dSChiYuan Huang };
764396f45dSChiYuan Huang
774396f45dSChiYuan Huang static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1] = {
784396f45dSChiYuan Huang {
794396f45dSChiYuan Huang .type = IIO_VOLTAGE,
804396f45dSChiYuan Huang .indexed = 1,
814396f45dSChiYuan Huang .channel = 0,
824396f45dSChiYuan Huang .address = RTQ6056_REG_SHUNTVOLT,
834396f45dSChiYuan Huang .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
844396f45dSChiYuan Huang BIT(IIO_CHAN_INFO_SCALE) |
854396f45dSChiYuan Huang BIT(IIO_CHAN_INFO_SAMP_FREQ),
864396f45dSChiYuan Huang .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
874396f45dSChiYuan Huang .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
884396f45dSChiYuan Huang .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
894396f45dSChiYuan Huang .scan_index = 0,
904396f45dSChiYuan Huang .scan_type = {
914396f45dSChiYuan Huang .sign = 's',
924396f45dSChiYuan Huang .realbits = 16,
934396f45dSChiYuan Huang .storagebits = 16,
944396f45dSChiYuan Huang .endianness = IIO_CPU,
954396f45dSChiYuan Huang },
964396f45dSChiYuan Huang },
974396f45dSChiYuan Huang {
984396f45dSChiYuan Huang .type = IIO_VOLTAGE,
994396f45dSChiYuan Huang .indexed = 1,
1004396f45dSChiYuan Huang .channel = 1,
1014396f45dSChiYuan Huang .address = RTQ6056_REG_BUSVOLT,
1024396f45dSChiYuan Huang .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1034396f45dSChiYuan Huang BIT(IIO_CHAN_INFO_SCALE) |
1044396f45dSChiYuan Huang BIT(IIO_CHAN_INFO_SAMP_FREQ),
1054396f45dSChiYuan Huang .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
1064396f45dSChiYuan Huang .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
1074396f45dSChiYuan Huang .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
1084396f45dSChiYuan Huang .scan_index = 1,
1094396f45dSChiYuan Huang .scan_type = {
1104396f45dSChiYuan Huang .sign = 'u',
1114396f45dSChiYuan Huang .realbits = 16,
1124396f45dSChiYuan Huang .storagebits = 16,
1134396f45dSChiYuan Huang .endianness = IIO_CPU,
1144396f45dSChiYuan Huang },
1154396f45dSChiYuan Huang },
1164396f45dSChiYuan Huang {
1174396f45dSChiYuan Huang .type = IIO_POWER,
1184396f45dSChiYuan Huang .indexed = 1,
1194396f45dSChiYuan Huang .channel = 2,
1204396f45dSChiYuan Huang .address = RTQ6056_REG_POWER,
1214396f45dSChiYuan Huang .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1224396f45dSChiYuan Huang BIT(IIO_CHAN_INFO_SCALE) |
1234396f45dSChiYuan Huang BIT(IIO_CHAN_INFO_SAMP_FREQ),
1244396f45dSChiYuan Huang .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
1254396f45dSChiYuan Huang .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
1264396f45dSChiYuan Huang .scan_index = 2,
1274396f45dSChiYuan Huang .scan_type = {
1284396f45dSChiYuan Huang .sign = 'u',
1294396f45dSChiYuan Huang .realbits = 16,
1304396f45dSChiYuan Huang .storagebits = 16,
1314396f45dSChiYuan Huang .endianness = IIO_CPU,
1324396f45dSChiYuan Huang },
1334396f45dSChiYuan Huang },
1344396f45dSChiYuan Huang {
1354396f45dSChiYuan Huang .type = IIO_CURRENT,
1364396f45dSChiYuan Huang .indexed = 1,
1374396f45dSChiYuan Huang .channel = 3,
1384396f45dSChiYuan Huang .address = RTQ6056_REG_CURRENT,
1394396f45dSChiYuan Huang .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1404396f45dSChiYuan Huang BIT(IIO_CHAN_INFO_SAMP_FREQ),
1414396f45dSChiYuan Huang .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
1424396f45dSChiYuan Huang .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
1434396f45dSChiYuan Huang .scan_index = 3,
1444396f45dSChiYuan Huang .scan_type = {
1454396f45dSChiYuan Huang .sign = 's',
1464396f45dSChiYuan Huang .realbits = 16,
1474396f45dSChiYuan Huang .storagebits = 16,
1484396f45dSChiYuan Huang .endianness = IIO_CPU,
1494396f45dSChiYuan Huang },
1504396f45dSChiYuan Huang },
1514396f45dSChiYuan Huang IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL),
1524396f45dSChiYuan Huang };
1534396f45dSChiYuan Huang
rtq6056_adc_read_channel(struct rtq6056_priv * priv,struct iio_chan_spec const * ch,int * val)1544396f45dSChiYuan Huang static int rtq6056_adc_read_channel(struct rtq6056_priv *priv,
1554396f45dSChiYuan Huang struct iio_chan_spec const *ch,
1564396f45dSChiYuan Huang int *val)
1574396f45dSChiYuan Huang {
1584396f45dSChiYuan Huang struct device *dev = priv->dev;
1594396f45dSChiYuan Huang unsigned int addr = ch->address;
1604396f45dSChiYuan Huang unsigned int regval;
1614396f45dSChiYuan Huang int ret;
1624396f45dSChiYuan Huang
1634396f45dSChiYuan Huang pm_runtime_get_sync(dev);
1644396f45dSChiYuan Huang ret = regmap_read(priv->regmap, addr, ®val);
1654396f45dSChiYuan Huang pm_runtime_mark_last_busy(dev);
1664396f45dSChiYuan Huang pm_runtime_put(dev);
1674396f45dSChiYuan Huang if (ret)
1684396f45dSChiYuan Huang return ret;
1694396f45dSChiYuan Huang
1704396f45dSChiYuan Huang /* Power and VBUS is unsigned 16-bit, others are signed 16-bit */
1714396f45dSChiYuan Huang if (addr == RTQ6056_REG_BUSVOLT || addr == RTQ6056_REG_POWER)
1724396f45dSChiYuan Huang *val = regval;
1734396f45dSChiYuan Huang else
1744396f45dSChiYuan Huang *val = sign_extend32(regval, 16);
1754396f45dSChiYuan Huang
1764396f45dSChiYuan Huang return IIO_VAL_INT;
1774396f45dSChiYuan Huang }
1784396f45dSChiYuan Huang
rtq6056_adc_read_scale(struct iio_chan_spec const * ch,int * val,int * val2)1794396f45dSChiYuan Huang static int rtq6056_adc_read_scale(struct iio_chan_spec const *ch, int *val,
1804396f45dSChiYuan Huang int *val2)
1814396f45dSChiYuan Huang {
1824396f45dSChiYuan Huang switch (ch->address) {
1834396f45dSChiYuan Huang case RTQ6056_REG_SHUNTVOLT:
1844396f45dSChiYuan Huang /* VSHUNT lsb 2.5uV */
1854396f45dSChiYuan Huang *val = 2500;
1864396f45dSChiYuan Huang *val2 = 1000000;
1874396f45dSChiYuan Huang return IIO_VAL_FRACTIONAL;
1884396f45dSChiYuan Huang case RTQ6056_REG_BUSVOLT:
1894396f45dSChiYuan Huang /* VBUS lsb 1.25mV */
1904396f45dSChiYuan Huang *val = 1250;
1914396f45dSChiYuan Huang *val2 = 1000;
1924396f45dSChiYuan Huang return IIO_VAL_FRACTIONAL;
1934396f45dSChiYuan Huang case RTQ6056_REG_POWER:
1944396f45dSChiYuan Huang /* Power lsb 25mW */
1954396f45dSChiYuan Huang *val = 25;
1964396f45dSChiYuan Huang return IIO_VAL_INT;
1974396f45dSChiYuan Huang default:
1984396f45dSChiYuan Huang return -EINVAL;
1994396f45dSChiYuan Huang }
2004396f45dSChiYuan Huang }
2014396f45dSChiYuan Huang
2024396f45dSChiYuan Huang /*
2034396f45dSChiYuan Huang * Sample frequency for channel VSHUNT and VBUS. The indices correspond
2044396f45dSChiYuan Huang * with the bit value expected by the chip. And it can be found at
2054396f45dSChiYuan Huang * https://www.richtek.com/assets/product_file/RTQ6056/DSQ6056-00.pdf
2064396f45dSChiYuan Huang */
2074396f45dSChiYuan Huang static const int rtq6056_samp_freq_list[] = {
2084396f45dSChiYuan Huang 7194, 4926, 3717, 1904, 964, 485, 243, 122,
2094396f45dSChiYuan Huang };
2104396f45dSChiYuan Huang
rtq6056_adc_set_samp_freq(struct rtq6056_priv * priv,struct iio_chan_spec const * ch,int val)2114396f45dSChiYuan Huang static int rtq6056_adc_set_samp_freq(struct rtq6056_priv *priv,
2124396f45dSChiYuan Huang struct iio_chan_spec const *ch, int val)
2134396f45dSChiYuan Huang {
2144396f45dSChiYuan Huang struct regmap_field *rm_field;
2154396f45dSChiYuan Huang unsigned int selector;
2164396f45dSChiYuan Huang int *ct, ret;
2174396f45dSChiYuan Huang
2184396f45dSChiYuan Huang if (val > 7194 || val < 122)
2194396f45dSChiYuan Huang return -EINVAL;
2204396f45dSChiYuan Huang
2214396f45dSChiYuan Huang if (ch->address == RTQ6056_REG_SHUNTVOLT) {
2224396f45dSChiYuan Huang rm_field = priv->rm_fields[F_VSHUNTCT];
2234396f45dSChiYuan Huang ct = &priv->vshuntct_us;
2244396f45dSChiYuan Huang } else if (ch->address == RTQ6056_REG_BUSVOLT) {
2254396f45dSChiYuan Huang rm_field = priv->rm_fields[F_VBUSCT];
2264396f45dSChiYuan Huang ct = &priv->vbusct_us;
2274396f45dSChiYuan Huang } else
2284396f45dSChiYuan Huang return -EINVAL;
2294396f45dSChiYuan Huang
2304396f45dSChiYuan Huang selector = find_closest_descending(val, rtq6056_samp_freq_list,
2314396f45dSChiYuan Huang ARRAY_SIZE(rtq6056_samp_freq_list));
2324396f45dSChiYuan Huang
2334396f45dSChiYuan Huang ret = regmap_field_write(rm_field, selector);
2344396f45dSChiYuan Huang if (ret)
2354396f45dSChiYuan Huang return ret;
2364396f45dSChiYuan Huang
2374396f45dSChiYuan Huang *ct = 1000000 / rtq6056_samp_freq_list[selector];
2384396f45dSChiYuan Huang
2394396f45dSChiYuan Huang return 0;
2404396f45dSChiYuan Huang }
2414396f45dSChiYuan Huang
2424396f45dSChiYuan Huang /*
2434396f45dSChiYuan Huang * Available averaging rate for rtq6056. The indices correspond with the bit
2444396f45dSChiYuan Huang * value expected by the chip. And it can be found at
2454396f45dSChiYuan Huang * https://www.richtek.com/assets/product_file/RTQ6056/DSQ6056-00.pdf
2464396f45dSChiYuan Huang */
2474396f45dSChiYuan Huang static const int rtq6056_avg_sample_list[] = {
2484396f45dSChiYuan Huang 1, 4, 16, 64, 128, 256, 512, 1024,
2494396f45dSChiYuan Huang };
2504396f45dSChiYuan Huang
rtq6056_adc_set_average(struct rtq6056_priv * priv,int val)2514396f45dSChiYuan Huang static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val)
2524396f45dSChiYuan Huang {
2534396f45dSChiYuan Huang unsigned int selector;
2544396f45dSChiYuan Huang int ret;
2554396f45dSChiYuan Huang
2564396f45dSChiYuan Huang if (val > 1024 || val < 1)
2574396f45dSChiYuan Huang return -EINVAL;
2584396f45dSChiYuan Huang
2594396f45dSChiYuan Huang selector = find_closest(val, rtq6056_avg_sample_list,
2604396f45dSChiYuan Huang ARRAY_SIZE(rtq6056_avg_sample_list));
2614396f45dSChiYuan Huang
2624396f45dSChiYuan Huang ret = regmap_field_write(priv->rm_fields[F_AVG], selector);
2634396f45dSChiYuan Huang if (ret)
2644396f45dSChiYuan Huang return ret;
2654396f45dSChiYuan Huang
2664396f45dSChiYuan Huang priv->avg_sample = rtq6056_avg_sample_list[selector];
2674396f45dSChiYuan Huang
2684396f45dSChiYuan Huang return 0;
2694396f45dSChiYuan Huang }
2704396f45dSChiYuan Huang
rtq6056_adc_get_sample_freq(struct rtq6056_priv * priv,struct iio_chan_spec const * ch,int * val)2714396f45dSChiYuan Huang static int rtq6056_adc_get_sample_freq(struct rtq6056_priv *priv,
2724396f45dSChiYuan Huang struct iio_chan_spec const *ch, int *val)
2734396f45dSChiYuan Huang {
2744396f45dSChiYuan Huang int sample_time;
2754396f45dSChiYuan Huang
2764396f45dSChiYuan Huang if (ch->address == RTQ6056_REG_SHUNTVOLT)
2774396f45dSChiYuan Huang sample_time = priv->vshuntct_us;
2784396f45dSChiYuan Huang else if (ch->address == RTQ6056_REG_BUSVOLT)
2794396f45dSChiYuan Huang sample_time = priv->vbusct_us;
2804396f45dSChiYuan Huang else {
2814396f45dSChiYuan Huang sample_time = priv->vshuntct_us + priv->vbusct_us;
2824396f45dSChiYuan Huang sample_time *= priv->avg_sample;
2834396f45dSChiYuan Huang }
2844396f45dSChiYuan Huang
2854396f45dSChiYuan Huang *val = 1000000 / sample_time;
2864396f45dSChiYuan Huang
2874396f45dSChiYuan Huang return IIO_VAL_INT;
2884396f45dSChiYuan Huang }
2894396f45dSChiYuan Huang
rtq6056_adc_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)2904396f45dSChiYuan Huang static int rtq6056_adc_read_raw(struct iio_dev *indio_dev,
2914396f45dSChiYuan Huang struct iio_chan_spec const *chan, int *val,
2924396f45dSChiYuan Huang int *val2, long mask)
2934396f45dSChiYuan Huang {
2944396f45dSChiYuan Huang struct rtq6056_priv *priv = iio_priv(indio_dev);
2954396f45dSChiYuan Huang
2964396f45dSChiYuan Huang switch (mask) {
2974396f45dSChiYuan Huang case IIO_CHAN_INFO_RAW:
2984396f45dSChiYuan Huang return rtq6056_adc_read_channel(priv, chan, val);
2994396f45dSChiYuan Huang case IIO_CHAN_INFO_SCALE:
3004396f45dSChiYuan Huang return rtq6056_adc_read_scale(chan, val, val2);
3014396f45dSChiYuan Huang case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
3024396f45dSChiYuan Huang *val = priv->avg_sample;
3034396f45dSChiYuan Huang return IIO_VAL_INT;
3044396f45dSChiYuan Huang case IIO_CHAN_INFO_SAMP_FREQ:
3054396f45dSChiYuan Huang return rtq6056_adc_get_sample_freq(priv, chan, val);
3064396f45dSChiYuan Huang default:
3074396f45dSChiYuan Huang return -EINVAL;
3084396f45dSChiYuan Huang }
3094396f45dSChiYuan Huang }
3104396f45dSChiYuan Huang
rtq6056_adc_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)3114396f45dSChiYuan Huang static int rtq6056_adc_read_avail(struct iio_dev *indio_dev,
3124396f45dSChiYuan Huang struct iio_chan_spec const *chan,
3134396f45dSChiYuan Huang const int **vals, int *type, int *length,
3144396f45dSChiYuan Huang long mask)
3154396f45dSChiYuan Huang {
3164396f45dSChiYuan Huang switch (mask) {
3174396f45dSChiYuan Huang case IIO_CHAN_INFO_SAMP_FREQ:
3184396f45dSChiYuan Huang *vals = rtq6056_samp_freq_list;
3194396f45dSChiYuan Huang *type = IIO_VAL_INT;
3204396f45dSChiYuan Huang *length = ARRAY_SIZE(rtq6056_samp_freq_list);
3214396f45dSChiYuan Huang return IIO_AVAIL_LIST;
3224396f45dSChiYuan Huang case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
3234396f45dSChiYuan Huang *vals = rtq6056_avg_sample_list;
3244396f45dSChiYuan Huang *type = IIO_VAL_INT;
3254396f45dSChiYuan Huang *length = ARRAY_SIZE(rtq6056_avg_sample_list);
3264396f45dSChiYuan Huang return IIO_AVAIL_LIST;
3274396f45dSChiYuan Huang default:
3284396f45dSChiYuan Huang return -EINVAL;
3294396f45dSChiYuan Huang }
3304396f45dSChiYuan Huang }
3314396f45dSChiYuan Huang
rtq6056_adc_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)3324396f45dSChiYuan Huang static int rtq6056_adc_write_raw(struct iio_dev *indio_dev,
3334396f45dSChiYuan Huang struct iio_chan_spec const *chan, int val,
3344396f45dSChiYuan Huang int val2, long mask)
3354396f45dSChiYuan Huang {
3364396f45dSChiYuan Huang struct rtq6056_priv *priv = iio_priv(indio_dev);
3374396f45dSChiYuan Huang int ret;
3384396f45dSChiYuan Huang
3394396f45dSChiYuan Huang ret = iio_device_claim_direct_mode(indio_dev);
3404396f45dSChiYuan Huang if (ret)
3414396f45dSChiYuan Huang return ret;
3424396f45dSChiYuan Huang
3434396f45dSChiYuan Huang switch (mask) {
3444396f45dSChiYuan Huang case IIO_CHAN_INFO_SAMP_FREQ:
3454396f45dSChiYuan Huang ret = rtq6056_adc_set_samp_freq(priv, chan, val);
3464396f45dSChiYuan Huang break;
3474396f45dSChiYuan Huang case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
3484396f45dSChiYuan Huang ret = rtq6056_adc_set_average(priv, val);
3494396f45dSChiYuan Huang break;
3504396f45dSChiYuan Huang default:
3514396f45dSChiYuan Huang ret = -EINVAL;
3524396f45dSChiYuan Huang break;
3534396f45dSChiYuan Huang }
3544396f45dSChiYuan Huang
3554396f45dSChiYuan Huang iio_device_release_direct_mode(indio_dev);
3564396f45dSChiYuan Huang
3574396f45dSChiYuan Huang return ret;
3584396f45dSChiYuan Huang }
3594396f45dSChiYuan Huang
3604396f45dSChiYuan Huang static const char *rtq6056_channel_labels[RTQ6056_MAX_CHANNEL] = {
3614396f45dSChiYuan Huang [RTQ6056_CH_VSHUNT] = "Vshunt",
3624396f45dSChiYuan Huang [RTQ6056_CH_VBUS] = "Vbus",
3634396f45dSChiYuan Huang [RTQ6056_CH_POWER] = "Power",
3644396f45dSChiYuan Huang [RTQ6056_CH_CURRENT] = "Current",
3654396f45dSChiYuan Huang };
3664396f45dSChiYuan Huang
rtq6056_adc_read_label(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,char * label)3674396f45dSChiYuan Huang static int rtq6056_adc_read_label(struct iio_dev *indio_dev,
3684396f45dSChiYuan Huang struct iio_chan_spec const *chan,
3694396f45dSChiYuan Huang char *label)
3704396f45dSChiYuan Huang {
3714396f45dSChiYuan Huang return sysfs_emit(label, "%s\n", rtq6056_channel_labels[chan->channel]);
3724396f45dSChiYuan Huang }
3734396f45dSChiYuan Huang
rtq6056_set_shunt_resistor(struct rtq6056_priv * priv,int resistor_uohm)3744396f45dSChiYuan Huang static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv,
3754396f45dSChiYuan Huang int resistor_uohm)
3764396f45dSChiYuan Huang {
3774396f45dSChiYuan Huang unsigned int calib_val;
3784396f45dSChiYuan Huang int ret;
3794396f45dSChiYuan Huang
3804396f45dSChiYuan Huang if (resistor_uohm <= 0) {
3814396f45dSChiYuan Huang dev_err(priv->dev, "Invalid resistor [%d]\n", resistor_uohm);
3824396f45dSChiYuan Huang return -EINVAL;
3834396f45dSChiYuan Huang }
3844396f45dSChiYuan Huang
3854396f45dSChiYuan Huang /* calibration = 5120000 / (Rshunt (uOhm) * current lsb (1mA)) */
3864396f45dSChiYuan Huang calib_val = 5120000 / resistor_uohm;
3874396f45dSChiYuan Huang ret = regmap_write(priv->regmap, RTQ6056_REG_CALIBRATION, calib_val);
3884396f45dSChiYuan Huang if (ret)
3894396f45dSChiYuan Huang return ret;
3904396f45dSChiYuan Huang
3914396f45dSChiYuan Huang priv->shunt_resistor_uohm = resistor_uohm;
3924396f45dSChiYuan Huang
3934396f45dSChiYuan Huang return 0;
3944396f45dSChiYuan Huang }
3954396f45dSChiYuan Huang
shunt_resistor_show(struct device * dev,struct device_attribute * attr,char * buf)3964396f45dSChiYuan Huang static ssize_t shunt_resistor_show(struct device *dev,
3974396f45dSChiYuan Huang struct device_attribute *attr, char *buf)
3984396f45dSChiYuan Huang {
3994396f45dSChiYuan Huang struct rtq6056_priv *priv = iio_priv(dev_to_iio_dev(dev));
4004396f45dSChiYuan Huang int vals[2] = { priv->shunt_resistor_uohm, 1000000 };
4014396f45dSChiYuan Huang
4024396f45dSChiYuan Huang return iio_format_value(buf, IIO_VAL_FRACTIONAL, 1, vals);
4034396f45dSChiYuan Huang }
4044396f45dSChiYuan Huang
shunt_resistor_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)4054396f45dSChiYuan Huang static ssize_t shunt_resistor_store(struct device *dev,
4064396f45dSChiYuan Huang struct device_attribute *attr,
4074396f45dSChiYuan Huang const char *buf, size_t len)
4084396f45dSChiYuan Huang {
4094396f45dSChiYuan Huang struct iio_dev *indio_dev = dev_to_iio_dev(dev);
4104396f45dSChiYuan Huang struct rtq6056_priv *priv = iio_priv(indio_dev);
4114396f45dSChiYuan Huang int val, val_fract, ret;
4124396f45dSChiYuan Huang
4134396f45dSChiYuan Huang ret = iio_device_claim_direct_mode(indio_dev);
4144396f45dSChiYuan Huang if (ret)
4154396f45dSChiYuan Huang return ret;
4164396f45dSChiYuan Huang
4174396f45dSChiYuan Huang ret = iio_str_to_fixpoint(buf, 100000, &val, &val_fract);
4184396f45dSChiYuan Huang if (ret)
4194396f45dSChiYuan Huang goto out_store;
4204396f45dSChiYuan Huang
4214396f45dSChiYuan Huang ret = rtq6056_set_shunt_resistor(priv, val * 1000000 + val_fract);
4224396f45dSChiYuan Huang
4234396f45dSChiYuan Huang out_store:
4244396f45dSChiYuan Huang iio_device_release_direct_mode(indio_dev);
4254396f45dSChiYuan Huang
4264396f45dSChiYuan Huang return ret ?: len;
4274396f45dSChiYuan Huang }
4284396f45dSChiYuan Huang
4294396f45dSChiYuan Huang static IIO_DEVICE_ATTR_RW(shunt_resistor, 0);
4304396f45dSChiYuan Huang
4314396f45dSChiYuan Huang static struct attribute *rtq6056_attributes[] = {
4324396f45dSChiYuan Huang &iio_dev_attr_shunt_resistor.dev_attr.attr,
4334396f45dSChiYuan Huang NULL
4344396f45dSChiYuan Huang };
4354396f45dSChiYuan Huang
4364396f45dSChiYuan Huang static const struct attribute_group rtq6056_attribute_group = {
4374396f45dSChiYuan Huang .attrs = rtq6056_attributes,
4384396f45dSChiYuan Huang };
4394396f45dSChiYuan Huang
4404396f45dSChiYuan Huang static const struct iio_info rtq6056_info = {
4414396f45dSChiYuan Huang .attrs = &rtq6056_attribute_group,
4424396f45dSChiYuan Huang .read_raw = rtq6056_adc_read_raw,
4434396f45dSChiYuan Huang .read_avail = rtq6056_adc_read_avail,
4444396f45dSChiYuan Huang .write_raw = rtq6056_adc_write_raw,
4454396f45dSChiYuan Huang .read_label = rtq6056_adc_read_label,
4464396f45dSChiYuan Huang };
4474396f45dSChiYuan Huang
rtq6056_buffer_trigger_handler(int irq,void * p)4484396f45dSChiYuan Huang static irqreturn_t rtq6056_buffer_trigger_handler(int irq, void *p)
4494396f45dSChiYuan Huang {
4504396f45dSChiYuan Huang struct iio_poll_func *pf = p;
4514396f45dSChiYuan Huang struct iio_dev *indio_dev = pf->indio_dev;
4524396f45dSChiYuan Huang struct rtq6056_priv *priv = iio_priv(indio_dev);
4534396f45dSChiYuan Huang struct device *dev = priv->dev;
4544396f45dSChiYuan Huang struct {
4554396f45dSChiYuan Huang u16 vals[RTQ6056_MAX_CHANNEL];
4564396f45dSChiYuan Huang s64 timestamp __aligned(8);
4574396f45dSChiYuan Huang } data;
4584396f45dSChiYuan Huang unsigned int raw;
4594396f45dSChiYuan Huang int i = 0, bit, ret;
4604396f45dSChiYuan Huang
4614396f45dSChiYuan Huang memset(&data, 0, sizeof(data));
4624396f45dSChiYuan Huang
4634396f45dSChiYuan Huang pm_runtime_get_sync(dev);
4644396f45dSChiYuan Huang
4654396f45dSChiYuan Huang for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) {
4664396f45dSChiYuan Huang unsigned int addr = rtq6056_channels[bit].address;
4674396f45dSChiYuan Huang
4684396f45dSChiYuan Huang ret = regmap_read(priv->regmap, addr, &raw);
4694396f45dSChiYuan Huang if (ret)
4704396f45dSChiYuan Huang goto out;
4714396f45dSChiYuan Huang
4724396f45dSChiYuan Huang data.vals[i++] = raw;
4734396f45dSChiYuan Huang }
4744396f45dSChiYuan Huang
4754396f45dSChiYuan Huang iio_push_to_buffers_with_timestamp(indio_dev, &data, iio_get_time_ns(indio_dev));
4764396f45dSChiYuan Huang
4774396f45dSChiYuan Huang out:
4784396f45dSChiYuan Huang pm_runtime_mark_last_busy(dev);
4794396f45dSChiYuan Huang pm_runtime_put(dev);
4804396f45dSChiYuan Huang
4814396f45dSChiYuan Huang iio_trigger_notify_done(indio_dev->trig);
4824396f45dSChiYuan Huang
4834396f45dSChiYuan Huang return IRQ_HANDLED;
4844396f45dSChiYuan Huang }
4854396f45dSChiYuan Huang
rtq6056_enter_shutdown_state(void * dev)4864396f45dSChiYuan Huang static void rtq6056_enter_shutdown_state(void *dev)
4874396f45dSChiYuan Huang {
4884396f45dSChiYuan Huang struct rtq6056_priv *priv = dev_get_drvdata(dev);
4894396f45dSChiYuan Huang
4904396f45dSChiYuan Huang /* Enter shutdown state */
4914396f45dSChiYuan Huang regmap_field_write(priv->rm_fields[F_OPMODE], 0);
4924396f45dSChiYuan Huang }
4934396f45dSChiYuan Huang
rtq6056_is_readable_reg(struct device * dev,unsigned int reg)4944396f45dSChiYuan Huang static bool rtq6056_is_readable_reg(struct device *dev, unsigned int reg)
4954396f45dSChiYuan Huang {
4964396f45dSChiYuan Huang switch (reg) {
4974396f45dSChiYuan Huang case RTQ6056_REG_CONFIG ... RTQ6056_REG_ALERTLIMIT:
4984396f45dSChiYuan Huang case RTQ6056_REG_MANUFACTID ... RTQ6056_REG_DIEID:
4994396f45dSChiYuan Huang return true;
5004396f45dSChiYuan Huang default:
5014396f45dSChiYuan Huang return false;
5024396f45dSChiYuan Huang }
5034396f45dSChiYuan Huang }
5044396f45dSChiYuan Huang
rtq6056_is_writeable_reg(struct device * dev,unsigned int reg)5054396f45dSChiYuan Huang static bool rtq6056_is_writeable_reg(struct device *dev, unsigned int reg)
5064396f45dSChiYuan Huang {
5074396f45dSChiYuan Huang switch (reg) {
5084396f45dSChiYuan Huang case RTQ6056_REG_CONFIG:
5094396f45dSChiYuan Huang case RTQ6056_REG_CALIBRATION ... RTQ6056_REG_ALERTLIMIT:
5104396f45dSChiYuan Huang return true;
5114396f45dSChiYuan Huang default:
5124396f45dSChiYuan Huang return false;
5134396f45dSChiYuan Huang }
5144396f45dSChiYuan Huang }
5154396f45dSChiYuan Huang
5164396f45dSChiYuan Huang static const struct regmap_config rtq6056_regmap_config = {
5174396f45dSChiYuan Huang .reg_bits = 8,
5184396f45dSChiYuan Huang .val_bits = 16,
5194396f45dSChiYuan Huang .val_format_endian = REGMAP_ENDIAN_BIG,
5204396f45dSChiYuan Huang .max_register = RTQ6056_REG_DIEID,
5214396f45dSChiYuan Huang .readable_reg = rtq6056_is_readable_reg,
5224396f45dSChiYuan Huang .writeable_reg = rtq6056_is_writeable_reg,
5234396f45dSChiYuan Huang };
5244396f45dSChiYuan Huang
rtq6056_probe(struct i2c_client * i2c)5254396f45dSChiYuan Huang static int rtq6056_probe(struct i2c_client *i2c)
5264396f45dSChiYuan Huang {
5274396f45dSChiYuan Huang struct iio_dev *indio_dev;
5284396f45dSChiYuan Huang struct rtq6056_priv *priv;
5294396f45dSChiYuan Huang struct device *dev = &i2c->dev;
5304396f45dSChiYuan Huang struct regmap *regmap;
5314396f45dSChiYuan Huang unsigned int vendor_id, shunt_resistor_uohm;
5324396f45dSChiYuan Huang int ret;
5334396f45dSChiYuan Huang
5344396f45dSChiYuan Huang if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA))
5354396f45dSChiYuan Huang return -EOPNOTSUPP;
5364396f45dSChiYuan Huang
5374396f45dSChiYuan Huang indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
5384396f45dSChiYuan Huang if (!indio_dev)
5394396f45dSChiYuan Huang return -ENOMEM;
5404396f45dSChiYuan Huang
5414396f45dSChiYuan Huang priv = iio_priv(indio_dev);
5424396f45dSChiYuan Huang priv->dev = dev;
5434396f45dSChiYuan Huang priv->vshuntct_us = priv->vbusct_us = 1037;
5444396f45dSChiYuan Huang priv->avg_sample = 1;
5454396f45dSChiYuan Huang i2c_set_clientdata(i2c, priv);
5464396f45dSChiYuan Huang
5474396f45dSChiYuan Huang regmap = devm_regmap_init_i2c(i2c, &rtq6056_regmap_config);
5484396f45dSChiYuan Huang if (IS_ERR(regmap))
5494396f45dSChiYuan Huang return dev_err_probe(dev, PTR_ERR(regmap),
5504396f45dSChiYuan Huang "Failed to init regmap\n");
5514396f45dSChiYuan Huang
5524396f45dSChiYuan Huang priv->regmap = regmap;
5534396f45dSChiYuan Huang
5544396f45dSChiYuan Huang ret = regmap_read(regmap, RTQ6056_REG_MANUFACTID, &vendor_id);
5554396f45dSChiYuan Huang if (ret)
5564396f45dSChiYuan Huang return dev_err_probe(dev, ret,
5574396f45dSChiYuan Huang "Failed to get manufacturer info\n");
5584396f45dSChiYuan Huang
5594396f45dSChiYuan Huang if (vendor_id != RTQ6056_VENDOR_ID)
5604396f45dSChiYuan Huang return dev_err_probe(dev, -ENODEV,
5614396f45dSChiYuan Huang "Invalid vendor id 0x%04x\n", vendor_id);
5624396f45dSChiYuan Huang
5634396f45dSChiYuan Huang ret = devm_regmap_field_bulk_alloc(dev, regmap, priv->rm_fields,
5644396f45dSChiYuan Huang rtq6056_reg_fields, F_MAX_FIELDS);
5654396f45dSChiYuan Huang if (ret)
5664396f45dSChiYuan Huang return dev_err_probe(dev, ret, "Failed to init regmap field\n");
5674396f45dSChiYuan Huang
5684396f45dSChiYuan Huang /*
5694396f45dSChiYuan Huang * By default, configure average sample as 1, bus and shunt conversion
5704396f45dSChiYuan Huang * time as 1037 microsecond, and operating mode to all on.
5714396f45dSChiYuan Huang */
5724396f45dSChiYuan Huang ret = regmap_write(regmap, RTQ6056_REG_CONFIG, RTQ6056_DEFAULT_CONFIG);
5734396f45dSChiYuan Huang if (ret)
5744396f45dSChiYuan Huang return dev_err_probe(dev, ret,
5754396f45dSChiYuan Huang "Failed to enable continuous sensing\n");
5764396f45dSChiYuan Huang
5774396f45dSChiYuan Huang ret = devm_add_action_or_reset(dev, rtq6056_enter_shutdown_state, dev);
5784396f45dSChiYuan Huang if (ret)
5794396f45dSChiYuan Huang return ret;
5804396f45dSChiYuan Huang
5814396f45dSChiYuan Huang pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
5824396f45dSChiYuan Huang pm_runtime_use_autosuspend(dev);
5834396f45dSChiYuan Huang pm_runtime_set_active(dev);
5844396f45dSChiYuan Huang pm_runtime_mark_last_busy(dev);
5854396f45dSChiYuan Huang ret = devm_pm_runtime_enable(dev);
5864396f45dSChiYuan Huang if (ret)
5874396f45dSChiYuan Huang return dev_err_probe(dev, ret, "Failed to enable pm_runtime\n");
5884396f45dSChiYuan Huang
5894396f45dSChiYuan Huang /* By default, use 2000 micro-Ohm resistor */
5904396f45dSChiYuan Huang shunt_resistor_uohm = 2000;
5914396f45dSChiYuan Huang device_property_read_u32(dev, "shunt-resistor-micro-ohms",
5924396f45dSChiYuan Huang &shunt_resistor_uohm);
5934396f45dSChiYuan Huang
5944396f45dSChiYuan Huang ret = rtq6056_set_shunt_resistor(priv, shunt_resistor_uohm);
5954396f45dSChiYuan Huang if (ret)
5964396f45dSChiYuan Huang return dev_err_probe(dev, ret,
5974396f45dSChiYuan Huang "Failed to init shunt resistor\n");
5984396f45dSChiYuan Huang
5994396f45dSChiYuan Huang indio_dev->name = "rtq6056";
6004396f45dSChiYuan Huang indio_dev->modes = INDIO_DIRECT_MODE;
6014396f45dSChiYuan Huang indio_dev->channels = rtq6056_channels;
6024396f45dSChiYuan Huang indio_dev->num_channels = ARRAY_SIZE(rtq6056_channels);
6034396f45dSChiYuan Huang indio_dev->info = &rtq6056_info;
6044396f45dSChiYuan Huang
6054396f45dSChiYuan Huang ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
6064396f45dSChiYuan Huang rtq6056_buffer_trigger_handler,
6074396f45dSChiYuan Huang NULL);
6084396f45dSChiYuan Huang if (ret)
6094396f45dSChiYuan Huang return dev_err_probe(dev, ret,
6104396f45dSChiYuan Huang "Failed to allocate iio trigger buffer\n");
6114396f45dSChiYuan Huang
6124396f45dSChiYuan Huang return devm_iio_device_register(dev, indio_dev);
6134396f45dSChiYuan Huang }
6144396f45dSChiYuan Huang
rtq6056_runtime_suspend(struct device * dev)6154396f45dSChiYuan Huang static int rtq6056_runtime_suspend(struct device *dev)
6164396f45dSChiYuan Huang {
6174396f45dSChiYuan Huang struct rtq6056_priv *priv = dev_get_drvdata(dev);
6184396f45dSChiYuan Huang
6194396f45dSChiYuan Huang /* Configure to shutdown mode */
6204396f45dSChiYuan Huang return regmap_field_write(priv->rm_fields[F_OPMODE], 0);
6214396f45dSChiYuan Huang }
6224396f45dSChiYuan Huang
rtq6056_runtime_resume(struct device * dev)6234396f45dSChiYuan Huang static int rtq6056_runtime_resume(struct device *dev)
6244396f45dSChiYuan Huang {
6254396f45dSChiYuan Huang struct rtq6056_priv *priv = dev_get_drvdata(dev);
6264396f45dSChiYuan Huang int sample_rdy_time_us, ret;
6274396f45dSChiYuan Huang
6284396f45dSChiYuan Huang ret = regmap_field_write(priv->rm_fields[F_OPMODE], RTQ6056_CONT_ALLON);
6294396f45dSChiYuan Huang if (ret)
6304396f45dSChiYuan Huang return ret;
6314396f45dSChiYuan Huang
6324396f45dSChiYuan Huang sample_rdy_time_us = priv->vbusct_us + priv->vshuntct_us;
6334396f45dSChiYuan Huang sample_rdy_time_us *= priv->avg_sample;
6344396f45dSChiYuan Huang
6354396f45dSChiYuan Huang usleep_range(sample_rdy_time_us, sample_rdy_time_us + 100);
6364396f45dSChiYuan Huang
6374396f45dSChiYuan Huang return 0;
6384396f45dSChiYuan Huang }
6394396f45dSChiYuan Huang
6404396f45dSChiYuan Huang static DEFINE_RUNTIME_DEV_PM_OPS(rtq6056_pm_ops, rtq6056_runtime_suspend,
6414396f45dSChiYuan Huang rtq6056_runtime_resume, NULL);
6424396f45dSChiYuan Huang
6434396f45dSChiYuan Huang static const struct of_device_id rtq6056_device_match[] = {
6444396f45dSChiYuan Huang { .compatible = "richtek,rtq6056" },
6454396f45dSChiYuan Huang {}
6464396f45dSChiYuan Huang };
6474396f45dSChiYuan Huang MODULE_DEVICE_TABLE(of, rtq6056_device_match);
6484396f45dSChiYuan Huang
6494396f45dSChiYuan Huang static struct i2c_driver rtq6056_driver = {
6504396f45dSChiYuan Huang .driver = {
6514396f45dSChiYuan Huang .name = "rtq6056",
6524396f45dSChiYuan Huang .of_match_table = rtq6056_device_match,
6534396f45dSChiYuan Huang .pm = pm_ptr(&rtq6056_pm_ops),
6544396f45dSChiYuan Huang },
655*7cf15f42SUwe Kleine-König .probe = rtq6056_probe,
6564396f45dSChiYuan Huang };
6574396f45dSChiYuan Huang module_i2c_driver(rtq6056_driver);
6584396f45dSChiYuan Huang
6594396f45dSChiYuan Huang MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
6604396f45dSChiYuan Huang MODULE_DESCRIPTION("Richtek RTQ6056 Driver");
6614396f45dSChiYuan Huang MODULE_LICENSE("GPL v2");
662