linux/drivers/iio/adc/lp8788_adc.c
<<
>>
Prefs
   1/*
   2 * TI LP8788 MFD - ADC driver
   3 *
   4 * Copyright 2012 Texas Instruments
   5 *
   6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/delay.h>
  14#include <linux/iio/iio.h>
  15#include <linux/iio/driver.h>
  16#include <linux/iio/machine.h>
  17#include <linux/mfd/lp8788.h>
  18#include <linux/module.h>
  19#include <linux/mutex.h>
  20#include <linux/platform_device.h>
  21#include <linux/slab.h>
  22
  23/* register address */
  24#define LP8788_ADC_CONF                 0x60
  25#define LP8788_ADC_RAW                  0x61
  26#define LP8788_ADC_DONE                 0x63
  27
  28#define ADC_CONV_START                  1
  29
  30struct lp8788_adc {
  31        struct lp8788 *lp;
  32        struct iio_map *map;
  33        struct mutex lock;
  34};
  35
  36static const int lp8788_scale[LPADC_MAX] = {
  37        [LPADC_VBATT_5P5] = 1343101,
  38        [LPADC_VIN_CHG]   = 3052503,
  39        [LPADC_IBATT]     = 610500,
  40        [LPADC_IC_TEMP]   = 61050,
  41        [LPADC_VBATT_6P0] = 1465201,
  42        [LPADC_VBATT_5P0] = 1221001,
  43        [LPADC_ADC1]      = 610500,
  44        [LPADC_ADC2]      = 610500,
  45        [LPADC_VDD]       = 1025641,
  46        [LPADC_VCOIN]     = 757020,
  47        [LPADC_ADC3]      = 610500,
  48        [LPADC_ADC4]      = 610500,
  49};
  50
  51static int lp8788_get_adc_result(struct lp8788_adc *adc, enum lp8788_adc_id id,
  52                                int *val)
  53{
  54        unsigned int msb;
  55        unsigned int lsb;
  56        unsigned int result;
  57        u8 data;
  58        u8 rawdata[2];
  59        int size = ARRAY_SIZE(rawdata);
  60        int retry = 5;
  61        int ret;
  62
  63        data = (id << 1) | ADC_CONV_START;
  64        ret = lp8788_write_byte(adc->lp, LP8788_ADC_CONF, data);
  65        if (ret)
  66                goto err_io;
  67
  68        /* retry until adc conversion is done */
  69        data = 0;
  70        while (retry--) {
  71                usleep_range(100, 200);
  72
  73                ret = lp8788_read_byte(adc->lp, LP8788_ADC_DONE, &data);
  74                if (ret)
  75                        goto err_io;
  76
  77                /* conversion done */
  78                if (data)
  79                        break;
  80        }
  81
  82        ret = lp8788_read_multi_bytes(adc->lp, LP8788_ADC_RAW, rawdata, size);
  83        if (ret)
  84                goto err_io;
  85
  86        msb = (rawdata[0] << 4) & 0x00000ff0;
  87        lsb = (rawdata[1] >> 4) & 0x0000000f;
  88        result = msb | lsb;
  89        *val = result;
  90
  91        return 0;
  92
  93err_io:
  94        return ret;
  95}
  96
  97static int lp8788_adc_read_raw(struct iio_dev *indio_dev,
  98                        struct iio_chan_spec const *chan,
  99                        int *val, int *val2, long mask)
 100{
 101        struct lp8788_adc *adc = iio_priv(indio_dev);
 102        enum lp8788_adc_id id = chan->channel;
 103        int ret;
 104
 105        mutex_lock(&adc->lock);
 106
 107        switch (mask) {
 108        case IIO_CHAN_INFO_RAW:
 109                ret = lp8788_get_adc_result(adc, id, val) ? -EIO : IIO_VAL_INT;
 110                break;
 111        case IIO_CHAN_INFO_SCALE:
 112                *val = lp8788_scale[id] / 1000000;
 113                *val2 = lp8788_scale[id] % 1000000;
 114                ret = IIO_VAL_INT_PLUS_MICRO;
 115                break;
 116        default:
 117                ret = -EINVAL;
 118                break;
 119        }
 120
 121        mutex_unlock(&adc->lock);
 122
 123        return ret;
 124}
 125
 126static const struct iio_info lp8788_adc_info = {
 127        .read_raw = &lp8788_adc_read_raw,
 128        .driver_module = THIS_MODULE,
 129};
 130
 131#define LP8788_CHAN(_id, _type) {                               \
 132                .type = _type,                                  \
 133                .indexed = 1,                                   \
 134                .channel = LPADC_##_id,                         \
 135                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |  \
 136                        BIT(IIO_CHAN_INFO_SCALE),               \
 137                .datasheet_name = #_id,                         \
 138}
 139
 140static const struct iio_chan_spec lp8788_adc_channels[] = {
 141        [LPADC_VBATT_5P5] = LP8788_CHAN(VBATT_5P5, IIO_VOLTAGE),
 142        [LPADC_VIN_CHG]   = LP8788_CHAN(VIN_CHG, IIO_VOLTAGE),
 143        [LPADC_IBATT]     = LP8788_CHAN(IBATT, IIO_CURRENT),
 144        [LPADC_IC_TEMP]   = LP8788_CHAN(IC_TEMP, IIO_TEMP),
 145        [LPADC_VBATT_6P0] = LP8788_CHAN(VBATT_6P0, IIO_VOLTAGE),
 146        [LPADC_VBATT_5P0] = LP8788_CHAN(VBATT_5P0, IIO_VOLTAGE),
 147        [LPADC_ADC1]      = LP8788_CHAN(ADC1, IIO_VOLTAGE),
 148        [LPADC_ADC2]      = LP8788_CHAN(ADC2, IIO_VOLTAGE),
 149        [LPADC_VDD]       = LP8788_CHAN(VDD, IIO_VOLTAGE),
 150        [LPADC_VCOIN]     = LP8788_CHAN(VCOIN, IIO_VOLTAGE),
 151        [LPADC_ADC3]      = LP8788_CHAN(ADC3, IIO_VOLTAGE),
 152        [LPADC_ADC4]      = LP8788_CHAN(ADC4, IIO_VOLTAGE),
 153};
 154
 155/* default maps used by iio consumer (lp8788-charger driver) */
 156static struct iio_map lp8788_default_iio_maps[] = {
 157        {
 158                .consumer_dev_name = "lp8788-charger",
 159                .consumer_channel = "lp8788_vbatt_5p0",
 160                .adc_channel_label = "VBATT_5P0",
 161        },
 162        {
 163                .consumer_dev_name = "lp8788-charger",
 164                .consumer_channel = "lp8788_adc1",
 165                .adc_channel_label = "ADC1",
 166        },
 167        { }
 168};
 169
 170static int lp8788_iio_map_register(struct iio_dev *indio_dev,
 171                                struct lp8788_platform_data *pdata,
 172                                struct lp8788_adc *adc)
 173{
 174        struct iio_map *map;
 175        int ret;
 176
 177        map = (!pdata || !pdata->adc_pdata) ?
 178                lp8788_default_iio_maps : pdata->adc_pdata;
 179
 180        ret = iio_map_array_register(indio_dev, map);
 181        if (ret) {
 182                dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
 183                return ret;
 184        }
 185
 186        adc->map = map;
 187        return 0;
 188}
 189
 190static int lp8788_adc_probe(struct platform_device *pdev)
 191{
 192        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 193        struct iio_dev *indio_dev;
 194        struct lp8788_adc *adc;
 195        int ret;
 196
 197        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
 198        if (!indio_dev)
 199                return -ENOMEM;
 200
 201        adc = iio_priv(indio_dev);
 202        adc->lp = lp;
 203        platform_set_drvdata(pdev, indio_dev);
 204
 205        indio_dev->dev.of_node = pdev->dev.of_node;
 206        ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc);
 207        if (ret)
 208                return ret;
 209
 210        mutex_init(&adc->lock);
 211
 212        indio_dev->dev.parent = &pdev->dev;
 213        indio_dev->name = pdev->name;
 214        indio_dev->modes = INDIO_DIRECT_MODE;
 215        indio_dev->info = &lp8788_adc_info;
 216        indio_dev->channels = lp8788_adc_channels;
 217        indio_dev->num_channels = ARRAY_SIZE(lp8788_adc_channels);
 218
 219        ret = iio_device_register(indio_dev);
 220        if (ret) {
 221                dev_err(&pdev->dev, "iio dev register err: %d\n", ret);
 222                goto err_iio_device;
 223        }
 224
 225        return 0;
 226
 227err_iio_device:
 228        iio_map_array_unregister(indio_dev);
 229        return ret;
 230}
 231
 232static int lp8788_adc_remove(struct platform_device *pdev)
 233{
 234        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 235
 236        iio_device_unregister(indio_dev);
 237        iio_map_array_unregister(indio_dev);
 238
 239        return 0;
 240}
 241
 242static struct platform_driver lp8788_adc_driver = {
 243        .probe = lp8788_adc_probe,
 244        .remove = lp8788_adc_remove,
 245        .driver = {
 246                .name = LP8788_DEV_ADC,
 247        },
 248};
 249module_platform_driver(lp8788_adc_driver);
 250
 251MODULE_DESCRIPTION("Texas Instruments LP8788 ADC Driver");
 252MODULE_AUTHOR("Milo Kim");
 253MODULE_LICENSE("GPL");
 254MODULE_ALIAS("platform:lp8788-adc");
 255