187a25333SAndreas Kemnade // SPDX-License-Identifier: GPL-2.0+ 287a25333SAndreas Kemnade /* 387a25333SAndreas Kemnade * ADC driver for the RICOH RN5T618 power management chip family 487a25333SAndreas Kemnade * 587a25333SAndreas Kemnade * Copyright (C) 2019 Andreas Kemnade 687a25333SAndreas Kemnade */ 787a25333SAndreas Kemnade 887a25333SAndreas Kemnade #include <linux/kernel.h> 987a25333SAndreas Kemnade #include <linux/device.h> 1087a25333SAndreas Kemnade #include <linux/errno.h> 1187a25333SAndreas Kemnade #include <linux/interrupt.h> 1287a25333SAndreas Kemnade #include <linux/init.h> 1387a25333SAndreas Kemnade #include <linux/module.h> 1487a25333SAndreas Kemnade #include <linux/mfd/rn5t618.h> 1587a25333SAndreas Kemnade #include <linux/platform_device.h> 1687a25333SAndreas Kemnade #include <linux/completion.h> 1787a25333SAndreas Kemnade #include <linux/regmap.h> 1887a25333SAndreas Kemnade #include <linux/iio/iio.h> 191a844ddfSAndreas Kemnade #include <linux/iio/driver.h> 201a844ddfSAndreas Kemnade #include <linux/iio/machine.h> 2187a25333SAndreas Kemnade #include <linux/slab.h> 2287a25333SAndreas Kemnade 2387a25333SAndreas Kemnade #define RN5T618_ADC_CONVERSION_TIMEOUT (msecs_to_jiffies(500)) 2487a25333SAndreas Kemnade #define RN5T618_REFERENCE_VOLT 2500 2587a25333SAndreas Kemnade 2687a25333SAndreas Kemnade /* mask for selecting channels for single conversion */ 2787a25333SAndreas Kemnade #define RN5T618_ADCCNT3_CHANNEL_MASK 0x7 2887a25333SAndreas Kemnade /* average 4-time conversion mode */ 2987a25333SAndreas Kemnade #define RN5T618_ADCCNT3_AVG BIT(3) 3087a25333SAndreas Kemnade /* set for starting a single conversion, gets cleared by hw when done */ 3187a25333SAndreas Kemnade #define RN5T618_ADCCNT3_GODONE BIT(4) 3287a25333SAndreas Kemnade /* automatic conversion, period is in ADCCNT2, selected channels are 3387a25333SAndreas Kemnade * in ADCCNT1 3487a25333SAndreas Kemnade */ 3587a25333SAndreas Kemnade #define RN5T618_ADCCNT3_AUTO BIT(5) 3687a25333SAndreas Kemnade #define RN5T618_ADCEND_IRQ BIT(0) 3787a25333SAndreas Kemnade 3887a25333SAndreas Kemnade struct rn5t618_adc_data { 3987a25333SAndreas Kemnade struct device *dev; 4087a25333SAndreas Kemnade struct rn5t618 *rn5t618; 4187a25333SAndreas Kemnade struct completion conv_completion; 4287a25333SAndreas Kemnade int irq; 4387a25333SAndreas Kemnade }; 4487a25333SAndreas Kemnade 4587a25333SAndreas Kemnade enum rn5t618_channels { 4687a25333SAndreas Kemnade LIMMON = 0, 4787a25333SAndreas Kemnade VBAT, 4887a25333SAndreas Kemnade VADP, 4987a25333SAndreas Kemnade VUSB, 5087a25333SAndreas Kemnade VSYS, 5187a25333SAndreas Kemnade VTHM, 5287a25333SAndreas Kemnade AIN1, 5387a25333SAndreas Kemnade AIN0 5487a25333SAndreas Kemnade }; 5587a25333SAndreas Kemnade 5684cd574eSAndy Shevchenko static const struct u16_fract rn5t618_ratios[8] = { 5787a25333SAndreas Kemnade [LIMMON] = {50, 32}, /* measured across 20mOhm, amplified by 32 */ 5887a25333SAndreas Kemnade [VBAT] = {2, 1}, 5987a25333SAndreas Kemnade [VADP] = {3, 1}, 6087a25333SAndreas Kemnade [VUSB] = {3, 1}, 6187a25333SAndreas Kemnade [VSYS] = {3, 1}, 6287a25333SAndreas Kemnade [VTHM] = {1, 1}, 6387a25333SAndreas Kemnade [AIN1] = {1, 1}, 6487a25333SAndreas Kemnade [AIN0] = {1, 1}, 6587a25333SAndreas Kemnade }; 6687a25333SAndreas Kemnade 6787a25333SAndreas Kemnade static int rn5t618_read_adc_reg(struct rn5t618 *rn5t618, int reg, u16 *val) 6887a25333SAndreas Kemnade { 6987a25333SAndreas Kemnade u8 data[2]; 7087a25333SAndreas Kemnade int ret; 7187a25333SAndreas Kemnade 7287a25333SAndreas Kemnade ret = regmap_bulk_read(rn5t618->regmap, reg, data, sizeof(data)); 7387a25333SAndreas Kemnade if (ret < 0) 7487a25333SAndreas Kemnade return ret; 7587a25333SAndreas Kemnade 7687a25333SAndreas Kemnade *val = (data[0] << 4) | (data[1] & 0xF); 7787a25333SAndreas Kemnade 7887a25333SAndreas Kemnade return 0; 7987a25333SAndreas Kemnade } 8087a25333SAndreas Kemnade 8187a25333SAndreas Kemnade static irqreturn_t rn5t618_adc_irq(int irq, void *data) 8287a25333SAndreas Kemnade { 8387a25333SAndreas Kemnade struct rn5t618_adc_data *adc = data; 8487a25333SAndreas Kemnade unsigned int r = 0; 8587a25333SAndreas Kemnade int ret; 8687a25333SAndreas Kemnade 8787a25333SAndreas Kemnade /* clear low & high threshold irqs */ 8887a25333SAndreas Kemnade regmap_write(adc->rn5t618->regmap, RN5T618_IR_ADC1, 0); 8987a25333SAndreas Kemnade regmap_write(adc->rn5t618->regmap, RN5T618_IR_ADC2, 0); 9087a25333SAndreas Kemnade 9187a25333SAndreas Kemnade ret = regmap_read(adc->rn5t618->regmap, RN5T618_IR_ADC3, &r); 9287a25333SAndreas Kemnade if (ret < 0) 9387a25333SAndreas Kemnade dev_err(adc->dev, "failed to read IRQ status: %d\n", ret); 9487a25333SAndreas Kemnade 9587a25333SAndreas Kemnade regmap_write(adc->rn5t618->regmap, RN5T618_IR_ADC3, 0); 9687a25333SAndreas Kemnade 9787a25333SAndreas Kemnade if (r & RN5T618_ADCEND_IRQ) 9887a25333SAndreas Kemnade complete(&adc->conv_completion); 9987a25333SAndreas Kemnade 10087a25333SAndreas Kemnade return IRQ_HANDLED; 10187a25333SAndreas Kemnade } 10287a25333SAndreas Kemnade 10387a25333SAndreas Kemnade static int rn5t618_adc_read(struct iio_dev *iio_dev, 10487a25333SAndreas Kemnade const struct iio_chan_spec *chan, 10587a25333SAndreas Kemnade int *val, int *val2, long mask) 10687a25333SAndreas Kemnade { 10787a25333SAndreas Kemnade struct rn5t618_adc_data *adc = iio_priv(iio_dev); 10887a25333SAndreas Kemnade u16 raw; 10987a25333SAndreas Kemnade int ret; 11087a25333SAndreas Kemnade 11187a25333SAndreas Kemnade if (mask == IIO_CHAN_INFO_SCALE) { 11287a25333SAndreas Kemnade *val = RN5T618_REFERENCE_VOLT * 11387a25333SAndreas Kemnade rn5t618_ratios[chan->channel].numerator; 11487a25333SAndreas Kemnade *val2 = rn5t618_ratios[chan->channel].denominator * 4095; 11587a25333SAndreas Kemnade 11687a25333SAndreas Kemnade return IIO_VAL_FRACTIONAL; 11787a25333SAndreas Kemnade } 11887a25333SAndreas Kemnade 11987a25333SAndreas Kemnade /* select channel */ 12087a25333SAndreas Kemnade ret = regmap_update_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, 12187a25333SAndreas Kemnade RN5T618_ADCCNT3_CHANNEL_MASK, 12287a25333SAndreas Kemnade chan->channel); 12387a25333SAndreas Kemnade if (ret < 0) 12487a25333SAndreas Kemnade return ret; 12587a25333SAndreas Kemnade 12687a25333SAndreas Kemnade ret = regmap_write(adc->rn5t618->regmap, RN5T618_EN_ADCIR3, 12787a25333SAndreas Kemnade RN5T618_ADCEND_IRQ); 12887a25333SAndreas Kemnade if (ret < 0) 12987a25333SAndreas Kemnade return ret; 13087a25333SAndreas Kemnade 13187a25333SAndreas Kemnade ret = regmap_update_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, 13287a25333SAndreas Kemnade RN5T618_ADCCNT3_AVG, 13387a25333SAndreas Kemnade mask == IIO_CHAN_INFO_AVERAGE_RAW ? 13487a25333SAndreas Kemnade RN5T618_ADCCNT3_AVG : 0); 13587a25333SAndreas Kemnade if (ret < 0) 13687a25333SAndreas Kemnade return ret; 13787a25333SAndreas Kemnade 13887a25333SAndreas Kemnade init_completion(&adc->conv_completion); 13987a25333SAndreas Kemnade /* single conversion */ 140*cb3f8e0cSTrevor Gamblin ret = regmap_set_bits(adc->rn5t618->regmap, RN5T618_ADCCNT3, 14187a25333SAndreas Kemnade RN5T618_ADCCNT3_GODONE); 14287a25333SAndreas Kemnade if (ret < 0) 14387a25333SAndreas Kemnade return ret; 14487a25333SAndreas Kemnade 14587a25333SAndreas Kemnade ret = wait_for_completion_timeout(&adc->conv_completion, 14687a25333SAndreas Kemnade RN5T618_ADC_CONVERSION_TIMEOUT); 14787a25333SAndreas Kemnade if (ret == 0) { 14887a25333SAndreas Kemnade dev_warn(adc->dev, "timeout waiting for adc result\n"); 14987a25333SAndreas Kemnade return -ETIMEDOUT; 15087a25333SAndreas Kemnade } 15187a25333SAndreas Kemnade 15287a25333SAndreas Kemnade ret = rn5t618_read_adc_reg(adc->rn5t618, 15387a25333SAndreas Kemnade RN5T618_ILIMDATAH + 2 * chan->channel, 15487a25333SAndreas Kemnade &raw); 15587a25333SAndreas Kemnade if (ret < 0) 15687a25333SAndreas Kemnade return ret; 15787a25333SAndreas Kemnade 15887a25333SAndreas Kemnade *val = raw; 15987a25333SAndreas Kemnade 16087a25333SAndreas Kemnade return IIO_VAL_INT; 16187a25333SAndreas Kemnade } 16287a25333SAndreas Kemnade 16387a25333SAndreas Kemnade static const struct iio_info rn5t618_adc_iio_info = { 16487a25333SAndreas Kemnade .read_raw = &rn5t618_adc_read, 16587a25333SAndreas Kemnade }; 16687a25333SAndreas Kemnade 16787a25333SAndreas Kemnade #define RN5T618_ADC_CHANNEL(_channel, _type, _name) { \ 16887a25333SAndreas Kemnade .type = _type, \ 16987a25333SAndreas Kemnade .channel = _channel, \ 17087a25333SAndreas Kemnade .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 17187a25333SAndreas Kemnade BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \ 17287a25333SAndreas Kemnade BIT(IIO_CHAN_INFO_SCALE), \ 17387a25333SAndreas Kemnade .datasheet_name = _name, \ 17487a25333SAndreas Kemnade .indexed = 1. \ 17587a25333SAndreas Kemnade } 17687a25333SAndreas Kemnade 17787a25333SAndreas Kemnade static const struct iio_chan_spec rn5t618_adc_iio_channels[] = { 17887a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(LIMMON, IIO_CURRENT, "LIMMON"), 17987a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(VBAT, IIO_VOLTAGE, "VBAT"), 18087a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(VADP, IIO_VOLTAGE, "VADP"), 18187a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(VUSB, IIO_VOLTAGE, "VUSB"), 18287a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(VSYS, IIO_VOLTAGE, "VSYS"), 18387a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(VTHM, IIO_VOLTAGE, "VTHM"), 18487a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(AIN1, IIO_VOLTAGE, "AIN1"), 18587a25333SAndreas Kemnade RN5T618_ADC_CHANNEL(AIN0, IIO_VOLTAGE, "AIN0") 18687a25333SAndreas Kemnade }; 18787a25333SAndreas Kemnade 1881a844ddfSAndreas Kemnade static struct iio_map rn5t618_maps[] = { 1891a844ddfSAndreas Kemnade IIO_MAP("VADP", "rn5t618-power", "vadp"), 1901a844ddfSAndreas Kemnade IIO_MAP("VUSB", "rn5t618-power", "vusb"), 1911a844ddfSAndreas Kemnade { /* sentinel */ } 1921a844ddfSAndreas Kemnade }; 1931a844ddfSAndreas Kemnade 19487a25333SAndreas Kemnade static int rn5t618_adc_probe(struct platform_device *pdev) 19587a25333SAndreas Kemnade { 19687a25333SAndreas Kemnade int ret; 19787a25333SAndreas Kemnade struct iio_dev *iio_dev; 19887a25333SAndreas Kemnade struct rn5t618_adc_data *adc; 19987a25333SAndreas Kemnade struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent); 20087a25333SAndreas Kemnade 20187a25333SAndreas Kemnade iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc)); 20287a25333SAndreas Kemnade if (!iio_dev) { 20387a25333SAndreas Kemnade dev_err(&pdev->dev, "failed allocating iio device\n"); 20487a25333SAndreas Kemnade return -ENOMEM; 20587a25333SAndreas Kemnade } 20687a25333SAndreas Kemnade 20787a25333SAndreas Kemnade adc = iio_priv(iio_dev); 20887a25333SAndreas Kemnade adc->dev = &pdev->dev; 20987a25333SAndreas Kemnade adc->rn5t618 = rn5t618; 21087a25333SAndreas Kemnade 21187a25333SAndreas Kemnade if (rn5t618->irq_data) 21287a25333SAndreas Kemnade adc->irq = regmap_irq_get_virq(rn5t618->irq_data, 21387a25333SAndreas Kemnade RN5T618_IRQ_ADC); 21487a25333SAndreas Kemnade 21587a25333SAndreas Kemnade if (adc->irq <= 0) { 21687a25333SAndreas Kemnade dev_err(&pdev->dev, "get virq failed\n"); 21787a25333SAndreas Kemnade return -EINVAL; 21887a25333SAndreas Kemnade } 21987a25333SAndreas Kemnade 22087a25333SAndreas Kemnade init_completion(&adc->conv_completion); 22187a25333SAndreas Kemnade 22287a25333SAndreas Kemnade iio_dev->name = dev_name(&pdev->dev); 22387a25333SAndreas Kemnade iio_dev->info = &rn5t618_adc_iio_info; 22487a25333SAndreas Kemnade iio_dev->modes = INDIO_DIRECT_MODE; 22587a25333SAndreas Kemnade iio_dev->channels = rn5t618_adc_iio_channels; 22687a25333SAndreas Kemnade iio_dev->num_channels = ARRAY_SIZE(rn5t618_adc_iio_channels); 22787a25333SAndreas Kemnade 22887a25333SAndreas Kemnade /* stop any auto-conversion */ 22987a25333SAndreas Kemnade ret = regmap_write(rn5t618->regmap, RN5T618_ADCCNT3, 0); 23087a25333SAndreas Kemnade if (ret < 0) 23187a25333SAndreas Kemnade return ret; 23287a25333SAndreas Kemnade 23387a25333SAndreas Kemnade platform_set_drvdata(pdev, iio_dev); 23487a25333SAndreas Kemnade 23587a25333SAndreas Kemnade ret = devm_request_threaded_irq(adc->dev, adc->irq, NULL, 23687a25333SAndreas Kemnade rn5t618_adc_irq, 23787a25333SAndreas Kemnade IRQF_ONESHOT, dev_name(adc->dev), 23887a25333SAndreas Kemnade adc); 23987a25333SAndreas Kemnade if (ret < 0) { 24087a25333SAndreas Kemnade dev_err(adc->dev, "request irq %d failed: %d\n", adc->irq, ret); 24187a25333SAndreas Kemnade return ret; 24287a25333SAndreas Kemnade } 24387a25333SAndreas Kemnade 244bdf48481SAlexandru Ardelean ret = devm_iio_map_array_register(adc->dev, iio_dev, rn5t618_maps); 2451a844ddfSAndreas Kemnade if (ret < 0) 2461a844ddfSAndreas Kemnade return ret; 2471a844ddfSAndreas Kemnade 24887a25333SAndreas Kemnade return devm_iio_device_register(adc->dev, iio_dev); 24987a25333SAndreas Kemnade } 25087a25333SAndreas Kemnade 25187a25333SAndreas Kemnade static struct platform_driver rn5t618_adc_driver = { 25287a25333SAndreas Kemnade .driver = { 25387a25333SAndreas Kemnade .name = "rn5t618-adc", 25487a25333SAndreas Kemnade }, 25587a25333SAndreas Kemnade .probe = rn5t618_adc_probe, 25687a25333SAndreas Kemnade }; 25787a25333SAndreas Kemnade 25887a25333SAndreas Kemnade module_platform_driver(rn5t618_adc_driver); 25987a25333SAndreas Kemnade MODULE_ALIAS("platform:rn5t618-adc"); 26087a25333SAndreas Kemnade MODULE_DESCRIPTION("RICOH RN5T618 ADC driver"); 26187a25333SAndreas Kemnade MODULE_LICENSE("GPL"); 262