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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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