1*28e4b859SHans de Goede // SPDX-License-Identifier: GPL-2.0-only 2*28e4b859SHans de Goede /* 3*28e4b859SHans de Goede * Intel Dollar Cove TI PMIC GPADC Driver 4*28e4b859SHans de Goede * 5*28e4b859SHans de Goede * Copyright (C) 2014 Intel Corporation (Ramakrishna Pallala <ramakrishna.pallala@intel.com>) 6*28e4b859SHans de Goede * Copyright (C) 2024 - 2025 Hans de Goede <hansg@kernel.org> 7*28e4b859SHans de Goede */ 8*28e4b859SHans de Goede 9*28e4b859SHans de Goede #include <linux/bits.h> 10*28e4b859SHans de Goede #include <linux/bitfield.h> 11*28e4b859SHans de Goede #include <linux/bitops.h> 12*28e4b859SHans de Goede #include <linux/cleanup.h> 13*28e4b859SHans de Goede #include <linux/delay.h> 14*28e4b859SHans de Goede #include <linux/device.h> 15*28e4b859SHans de Goede #include <linux/interrupt.h> 16*28e4b859SHans de Goede #include <linux/mfd/intel_soc_pmic.h> 17*28e4b859SHans de Goede #include <linux/mod_devicetable.h> 18*28e4b859SHans de Goede #include <linux/module.h> 19*28e4b859SHans de Goede #include <linux/mutex.h> 20*28e4b859SHans de Goede #include <linux/platform_device.h> 21*28e4b859SHans de Goede #include <linux/regmap.h> 22*28e4b859SHans de Goede #include <linux/wait.h> 23*28e4b859SHans de Goede 24*28e4b859SHans de Goede #include <linux/iio/driver.h> 25*28e4b859SHans de Goede #include <linux/iio/iio.h> 26*28e4b859SHans de Goede #include <linux/iio/machine.h> 27*28e4b859SHans de Goede 28*28e4b859SHans de Goede #define DC_TI_ADC_CNTL_REG 0x50 29*28e4b859SHans de Goede #define DC_TI_ADC_START BIT(0) 30*28e4b859SHans de Goede #define DC_TI_ADC_CH_SEL GENMASK(2, 1) 31*28e4b859SHans de Goede #define DC_TI_ADC_EN BIT(5) 32*28e4b859SHans de Goede #define DC_TI_ADC_EN_EXT_BPTH_BIAS BIT(6) 33*28e4b859SHans de Goede 34*28e4b859SHans de Goede #define DC_TI_VBAT_ZSE_GE_REG 0x53 35*28e4b859SHans de Goede #define DC_TI_VBAT_GE GENMASK(3, 0) 36*28e4b859SHans de Goede #define DC_TI_VBAT_ZSE GENMASK(7, 4) 37*28e4b859SHans de Goede 38*28e4b859SHans de Goede /* VBAT GE gain correction is in 0.0015 increments, ZSE is in 1.0 increments */ 39*28e4b859SHans de Goede #define DC_TI_VBAT_GE_STEP 15 40*28e4b859SHans de Goede #define DC_TI_VBAT_GE_DIV 10000 41*28e4b859SHans de Goede 42*28e4b859SHans de Goede #define DC_TI_ADC_DATA_REG_CH(x) (0x54 + 2 * (x)) 43*28e4b859SHans de Goede 44*28e4b859SHans de Goede enum dc_ti_adc_id { 45*28e4b859SHans de Goede DC_TI_ADC_VBAT, 46*28e4b859SHans de Goede DC_TI_ADC_PMICTEMP, 47*28e4b859SHans de Goede DC_TI_ADC_BATTEMP, 48*28e4b859SHans de Goede DC_TI_ADC_SYSTEMP0, 49*28e4b859SHans de Goede }; 50*28e4b859SHans de Goede 51*28e4b859SHans de Goede struct dc_ti_adc_info { 52*28e4b859SHans de Goede struct mutex lock; /* Protects against concurrent accesses to the ADC */ 53*28e4b859SHans de Goede wait_queue_head_t wait; 54*28e4b859SHans de Goede struct device *dev; 55*28e4b859SHans de Goede struct regmap *regmap; 56*28e4b859SHans de Goede int vbat_zse; 57*28e4b859SHans de Goede int vbat_ge; 58*28e4b859SHans de Goede bool conversion_done; 59*28e4b859SHans de Goede }; 60*28e4b859SHans de Goede 61*28e4b859SHans de Goede static const struct iio_chan_spec dc_ti_adc_channels[] = { 62*28e4b859SHans de Goede { 63*28e4b859SHans de Goede .indexed = 1, 64*28e4b859SHans de Goede .type = IIO_VOLTAGE, 65*28e4b859SHans de Goede .channel = DC_TI_ADC_VBAT, 66*28e4b859SHans de Goede .address = DC_TI_ADC_DATA_REG_CH(0), 67*28e4b859SHans de Goede .datasheet_name = "CH0", 68*28e4b859SHans de Goede .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 69*28e4b859SHans de Goede BIT(IIO_CHAN_INFO_SCALE) | 70*28e4b859SHans de Goede BIT(IIO_CHAN_INFO_PROCESSED), 71*28e4b859SHans de Goede }, { 72*28e4b859SHans de Goede .indexed = 1, 73*28e4b859SHans de Goede .type = IIO_TEMP, 74*28e4b859SHans de Goede .channel = DC_TI_ADC_PMICTEMP, 75*28e4b859SHans de Goede .address = DC_TI_ADC_DATA_REG_CH(1), 76*28e4b859SHans de Goede .datasheet_name = "CH1", 77*28e4b859SHans de Goede .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 78*28e4b859SHans de Goede }, { 79*28e4b859SHans de Goede .indexed = 1, 80*28e4b859SHans de Goede .type = IIO_TEMP, 81*28e4b859SHans de Goede .channel = DC_TI_ADC_BATTEMP, 82*28e4b859SHans de Goede .address = DC_TI_ADC_DATA_REG_CH(2), 83*28e4b859SHans de Goede .datasheet_name = "CH2", 84*28e4b859SHans de Goede .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 85*28e4b859SHans de Goede }, { 86*28e4b859SHans de Goede .indexed = 1, 87*28e4b859SHans de Goede .type = IIO_TEMP, 88*28e4b859SHans de Goede .channel = DC_TI_ADC_SYSTEMP0, 89*28e4b859SHans de Goede .address = DC_TI_ADC_DATA_REG_CH(3), 90*28e4b859SHans de Goede .datasheet_name = "CH3", 91*28e4b859SHans de Goede .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 92*28e4b859SHans de Goede } 93*28e4b859SHans de Goede }; 94*28e4b859SHans de Goede 95*28e4b859SHans de Goede static struct iio_map dc_ti_adc_default_maps[] = { 96*28e4b859SHans de Goede IIO_MAP("CH0", "chtdc_ti_battery", "VBAT"), 97*28e4b859SHans de Goede IIO_MAP("CH1", "chtdc_ti_battery", "PMICTEMP"), 98*28e4b859SHans de Goede IIO_MAP("CH2", "chtdc_ti_battery", "BATTEMP"), 99*28e4b859SHans de Goede IIO_MAP("CH3", "chtdc_ti_battery", "SYSTEMP0"), 100*28e4b859SHans de Goede { } 101*28e4b859SHans de Goede }; 102*28e4b859SHans de Goede 103*28e4b859SHans de Goede static irqreturn_t dc_ti_adc_isr(int irq, void *data) 104*28e4b859SHans de Goede { 105*28e4b859SHans de Goede struct dc_ti_adc_info *info = data; 106*28e4b859SHans de Goede 107*28e4b859SHans de Goede info->conversion_done = true; 108*28e4b859SHans de Goede wake_up(&info->wait); 109*28e4b859SHans de Goede return IRQ_HANDLED; 110*28e4b859SHans de Goede } 111*28e4b859SHans de Goede 112*28e4b859SHans de Goede static int dc_ti_adc_scale(struct dc_ti_adc_info *info, 113*28e4b859SHans de Goede struct iio_chan_spec const *chan, 114*28e4b859SHans de Goede int *val, int *val2) 115*28e4b859SHans de Goede { 116*28e4b859SHans de Goede if (chan->channel != DC_TI_ADC_VBAT) 117*28e4b859SHans de Goede return -EINVAL; 118*28e4b859SHans de Goede 119*28e4b859SHans de Goede /* Vbat ADC scale is 4.6875 mV / unit */ 120*28e4b859SHans de Goede *val = 4; 121*28e4b859SHans de Goede *val2 = 687500; 122*28e4b859SHans de Goede 123*28e4b859SHans de Goede return IIO_VAL_INT_PLUS_MICRO; 124*28e4b859SHans de Goede } 125*28e4b859SHans de Goede 126*28e4b859SHans de Goede static int dc_ti_adc_raw_to_processed(struct dc_ti_adc_info *info, 127*28e4b859SHans de Goede struct iio_chan_spec const *chan, 128*28e4b859SHans de Goede int raw, int *val, int *val2) 129*28e4b859SHans de Goede { 130*28e4b859SHans de Goede if (chan->channel != DC_TI_ADC_VBAT) 131*28e4b859SHans de Goede return -EINVAL; 132*28e4b859SHans de Goede 133*28e4b859SHans de Goede /* Apply calibration */ 134*28e4b859SHans de Goede raw -= info->vbat_zse; 135*28e4b859SHans de Goede raw = raw * (DC_TI_VBAT_GE_DIV - info->vbat_ge * DC_TI_VBAT_GE_STEP) / 136*28e4b859SHans de Goede DC_TI_VBAT_GE_DIV; 137*28e4b859SHans de Goede /* Vbat ADC scale is 4.6875 mV / unit */ 138*28e4b859SHans de Goede raw *= 46875; 139*28e4b859SHans de Goede 140*28e4b859SHans de Goede /* raw is now in 10000 units / mV, convert to milli + milli/1e6 */ 141*28e4b859SHans de Goede *val = raw / 10000; 142*28e4b859SHans de Goede *val2 = (raw % 10000) * 100; 143*28e4b859SHans de Goede 144*28e4b859SHans de Goede return IIO_VAL_INT_PLUS_MICRO; 145*28e4b859SHans de Goede } 146*28e4b859SHans de Goede 147*28e4b859SHans de Goede static int dc_ti_adc_sample(struct dc_ti_adc_info *info, 148*28e4b859SHans de Goede struct iio_chan_spec const *chan, int *val) 149*28e4b859SHans de Goede { 150*28e4b859SHans de Goede int ret, ch = chan->channel; 151*28e4b859SHans de Goede __be16 buf; 152*28e4b859SHans de Goede 153*28e4b859SHans de Goede info->conversion_done = false; 154*28e4b859SHans de Goede 155*28e4b859SHans de Goede /* 156*28e4b859SHans de Goede * As per TI (PMIC Vendor), the ADC enable and ADC start commands should 157*28e4b859SHans de Goede * not be sent together. Hence send the commands separately. 158*28e4b859SHans de Goede */ 159*28e4b859SHans de Goede ret = regmap_set_bits(info->regmap, DC_TI_ADC_CNTL_REG, DC_TI_ADC_EN); 160*28e4b859SHans de Goede if (ret) 161*28e4b859SHans de Goede return ret; 162*28e4b859SHans de Goede 163*28e4b859SHans de Goede ret = regmap_update_bits(info->regmap, DC_TI_ADC_CNTL_REG, 164*28e4b859SHans de Goede DC_TI_ADC_CH_SEL, 165*28e4b859SHans de Goede FIELD_PREP(DC_TI_ADC_CH_SEL, ch)); 166*28e4b859SHans de Goede if (ret) 167*28e4b859SHans de Goede return ret; 168*28e4b859SHans de Goede 169*28e4b859SHans de Goede /* 170*28e4b859SHans de Goede * As per PMIC Vendor, a minimum of 50 ųs delay is required between ADC 171*28e4b859SHans de Goede * Enable and ADC START commands. This is also recommended by Intel 172*28e4b859SHans de Goede * Hardware team after the timing analysis of GPADC signals. Since the 173*28e4b859SHans de Goede * I2C Write transaction to set the channel number also imparts 25 ųs 174*28e4b859SHans de Goede * delay, we need to wait for another 25 ųs before issuing ADC START. 175*28e4b859SHans de Goede */ 176*28e4b859SHans de Goede fsleep(25); 177*28e4b859SHans de Goede 178*28e4b859SHans de Goede ret = regmap_set_bits(info->regmap, DC_TI_ADC_CNTL_REG, 179*28e4b859SHans de Goede DC_TI_ADC_START); 180*28e4b859SHans de Goede if (ret) 181*28e4b859SHans de Goede return ret; 182*28e4b859SHans de Goede 183*28e4b859SHans de Goede /* TI (PMIC Vendor) recommends 5 s timeout for conversion */ 184*28e4b859SHans de Goede ret = wait_event_timeout(info->wait, info->conversion_done, 5 * HZ); 185*28e4b859SHans de Goede if (ret == 0) { 186*28e4b859SHans de Goede ret = -ETIMEDOUT; 187*28e4b859SHans de Goede goto disable_adc; 188*28e4b859SHans de Goede } 189*28e4b859SHans de Goede 190*28e4b859SHans de Goede ret = regmap_bulk_read(info->regmap, chan->address, &buf, sizeof(buf)); 191*28e4b859SHans de Goede if (ret) 192*28e4b859SHans de Goede goto disable_adc; 193*28e4b859SHans de Goede 194*28e4b859SHans de Goede /* The ADC values are 10 bits wide */ 195*28e4b859SHans de Goede *val = be16_to_cpu(buf) & GENMASK(9, 0); 196*28e4b859SHans de Goede 197*28e4b859SHans de Goede disable_adc: 198*28e4b859SHans de Goede regmap_clear_bits(info->regmap, DC_TI_ADC_CNTL_REG, 199*28e4b859SHans de Goede DC_TI_ADC_START | DC_TI_ADC_EN); 200*28e4b859SHans de Goede return ret; 201*28e4b859SHans de Goede } 202*28e4b859SHans de Goede 203*28e4b859SHans de Goede static int dc_ti_adc_read_raw(struct iio_dev *indio_dev, 204*28e4b859SHans de Goede struct iio_chan_spec const *chan, 205*28e4b859SHans de Goede int *val, int *val2, long mask) 206*28e4b859SHans de Goede { 207*28e4b859SHans de Goede struct dc_ti_adc_info *info = iio_priv(indio_dev); 208*28e4b859SHans de Goede int ret; 209*28e4b859SHans de Goede 210*28e4b859SHans de Goede if (mask == IIO_CHAN_INFO_SCALE) 211*28e4b859SHans de Goede return dc_ti_adc_scale(info, chan, val, val2); 212*28e4b859SHans de Goede 213*28e4b859SHans de Goede guard(mutex)(&info->lock); 214*28e4b859SHans de Goede 215*28e4b859SHans de Goede /* 216*28e4b859SHans de Goede * If channel BPTHERM has been selected, first enable the BPTHERM BIAS 217*28e4b859SHans de Goede * which provides the VREF Voltage reference to convert BPTHERM Input 218*28e4b859SHans de Goede * voltage to temperature. 219*28e4b859SHans de Goede */ 220*28e4b859SHans de Goede if (chan->channel == DC_TI_ADC_BATTEMP) { 221*28e4b859SHans de Goede ret = regmap_set_bits(info->regmap, DC_TI_ADC_CNTL_REG, 222*28e4b859SHans de Goede DC_TI_ADC_EN_EXT_BPTH_BIAS); 223*28e4b859SHans de Goede if (ret) 224*28e4b859SHans de Goede return ret; 225*28e4b859SHans de Goede /* 226*28e4b859SHans de Goede * As per PMIC Vendor specifications, BPTHERM BIAS should be 227*28e4b859SHans de Goede * enabled 35 ms before ADC_EN command. 228*28e4b859SHans de Goede */ 229*28e4b859SHans de Goede msleep(35); 230*28e4b859SHans de Goede } 231*28e4b859SHans de Goede 232*28e4b859SHans de Goede ret = dc_ti_adc_sample(info, chan, val); 233*28e4b859SHans de Goede 234*28e4b859SHans de Goede if (chan->channel == DC_TI_ADC_BATTEMP) 235*28e4b859SHans de Goede regmap_clear_bits(info->regmap, DC_TI_ADC_CNTL_REG, 236*28e4b859SHans de Goede DC_TI_ADC_EN_EXT_BPTH_BIAS); 237*28e4b859SHans de Goede 238*28e4b859SHans de Goede if (ret) 239*28e4b859SHans de Goede return ret; 240*28e4b859SHans de Goede 241*28e4b859SHans de Goede switch (mask) { 242*28e4b859SHans de Goede case IIO_CHAN_INFO_RAW: 243*28e4b859SHans de Goede return IIO_VAL_INT; 244*28e4b859SHans de Goede case IIO_CHAN_INFO_PROCESSED: 245*28e4b859SHans de Goede return dc_ti_adc_raw_to_processed(info, chan, *val, val, val2); 246*28e4b859SHans de Goede } 247*28e4b859SHans de Goede 248*28e4b859SHans de Goede return -EINVAL; 249*28e4b859SHans de Goede } 250*28e4b859SHans de Goede 251*28e4b859SHans de Goede static const struct iio_info dc_ti_adc_iio_info = { 252*28e4b859SHans de Goede .read_raw = dc_ti_adc_read_raw, 253*28e4b859SHans de Goede }; 254*28e4b859SHans de Goede 255*28e4b859SHans de Goede static int dc_ti_adc_probe(struct platform_device *pdev) 256*28e4b859SHans de Goede { 257*28e4b859SHans de Goede struct device *dev = &pdev->dev; 258*28e4b859SHans de Goede struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent); 259*28e4b859SHans de Goede struct dc_ti_adc_info *info; 260*28e4b859SHans de Goede struct iio_dev *indio_dev; 261*28e4b859SHans de Goede unsigned int val; 262*28e4b859SHans de Goede int irq, ret; 263*28e4b859SHans de Goede 264*28e4b859SHans de Goede irq = platform_get_irq(pdev, 0); 265*28e4b859SHans de Goede if (irq < 0) 266*28e4b859SHans de Goede return irq; 267*28e4b859SHans de Goede 268*28e4b859SHans de Goede indio_dev = devm_iio_device_alloc(dev, sizeof(*info)); 269*28e4b859SHans de Goede if (!indio_dev) 270*28e4b859SHans de Goede return -ENOMEM; 271*28e4b859SHans de Goede 272*28e4b859SHans de Goede info = iio_priv(indio_dev); 273*28e4b859SHans de Goede 274*28e4b859SHans de Goede ret = devm_mutex_init(dev, &info->lock); 275*28e4b859SHans de Goede if (ret) 276*28e4b859SHans de Goede return ret; 277*28e4b859SHans de Goede 278*28e4b859SHans de Goede init_waitqueue_head(&info->wait); 279*28e4b859SHans de Goede 280*28e4b859SHans de Goede info->dev = dev; 281*28e4b859SHans de Goede info->regmap = pmic->regmap; 282*28e4b859SHans de Goede 283*28e4b859SHans de Goede indio_dev->name = "dc_ti_adc"; 284*28e4b859SHans de Goede indio_dev->channels = dc_ti_adc_channels; 285*28e4b859SHans de Goede indio_dev->num_channels = ARRAY_SIZE(dc_ti_adc_channels); 286*28e4b859SHans de Goede indio_dev->info = &dc_ti_adc_iio_info; 287*28e4b859SHans de Goede indio_dev->modes = INDIO_DIRECT_MODE; 288*28e4b859SHans de Goede 289*28e4b859SHans de Goede ret = regmap_read(info->regmap, DC_TI_VBAT_ZSE_GE_REG, &val); 290*28e4b859SHans de Goede if (ret) 291*28e4b859SHans de Goede return ret; 292*28e4b859SHans de Goede 293*28e4b859SHans de Goede info->vbat_zse = sign_extend32(FIELD_GET(DC_TI_VBAT_ZSE, val), 3); 294*28e4b859SHans de Goede info->vbat_ge = sign_extend32(FIELD_GET(DC_TI_VBAT_GE, val), 3); 295*28e4b859SHans de Goede 296*28e4b859SHans de Goede dev_dbg(dev, "vbat-zse %d vbat-ge %d\n", info->vbat_zse, info->vbat_ge); 297*28e4b859SHans de Goede 298*28e4b859SHans de Goede ret = devm_iio_map_array_register(dev, indio_dev, dc_ti_adc_default_maps); 299*28e4b859SHans de Goede if (ret) 300*28e4b859SHans de Goede return ret; 301*28e4b859SHans de Goede 302*28e4b859SHans de Goede ret = devm_request_threaded_irq(dev, irq, NULL, dc_ti_adc_isr, 303*28e4b859SHans de Goede IRQF_ONESHOT, indio_dev->name, info); 304*28e4b859SHans de Goede if (ret) 305*28e4b859SHans de Goede return ret; 306*28e4b859SHans de Goede 307*28e4b859SHans de Goede return devm_iio_device_register(dev, indio_dev); 308*28e4b859SHans de Goede } 309*28e4b859SHans de Goede 310*28e4b859SHans de Goede static const struct platform_device_id dc_ti_adc_ids[] = { 311*28e4b859SHans de Goede { .name = "chtdc_ti_adc" }, 312*28e4b859SHans de Goede { } 313*28e4b859SHans de Goede }; 314*28e4b859SHans de Goede MODULE_DEVICE_TABLE(platform, dc_ti_adc_ids); 315*28e4b859SHans de Goede 316*28e4b859SHans de Goede static struct platform_driver dc_ti_adc_driver = { 317*28e4b859SHans de Goede .driver = { 318*28e4b859SHans de Goede .name = "dc_ti_adc", 319*28e4b859SHans de Goede }, 320*28e4b859SHans de Goede .probe = dc_ti_adc_probe, 321*28e4b859SHans de Goede .id_table = dc_ti_adc_ids, 322*28e4b859SHans de Goede }; 323*28e4b859SHans de Goede module_platform_driver(dc_ti_adc_driver); 324*28e4b859SHans de Goede 325*28e4b859SHans de Goede MODULE_AUTHOR("Ramakrishna Pallala (Intel)"); 326*28e4b859SHans de Goede MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>"); 327*28e4b859SHans de Goede MODULE_DESCRIPTION("Intel Dollar Cove (TI) GPADC Driver"); 328*28e4b859SHans de Goede MODULE_LICENSE("GPL"); 329