linux/drivers/iio/adc/lpc32xx_adc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *  lpc32xx_adc.c - Support for ADC in LPC32XX
   4 *
   5 *  3-channel, 10-bit ADC
   6 *
   7 *  Copyright (C) 2011, 2012 Roland Stigge <stigge@antcom.de>
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/completion.h>
  12#include <linux/err.h>
  13#include <linux/iio/iio.h>
  14#include <linux/interrupt.h>
  15#include <linux/io.h>
  16#include <linux/module.h>
  17#include <linux/mod_devicetable.h>
  18#include <linux/platform_device.h>
  19#include <linux/regulator/consumer.h>
  20
  21/*
  22 * LPC32XX registers definitions
  23 */
  24#define LPC32XXAD_SELECT(x)     ((x) + 0x04)
  25#define LPC32XXAD_CTRL(x)       ((x) + 0x08)
  26#define LPC32XXAD_VALUE(x)      ((x) + 0x48)
  27
  28/* Bit definitions for LPC32XXAD_SELECT: */
  29/* constant, always write this value! */
  30#define LPC32XXAD_REFm         0x00000200
  31/* constant, always write this value! */
  32#define LPC32XXAD_REFp          0x00000080
  33 /* multiple of this is the channel number: 0, 1, 2 */
  34#define LPC32XXAD_IN            0x00000010
  35/* constant, always write this value! */
  36#define LPC32XXAD_INTERNAL      0x00000004
  37
  38/* Bit definitions for LPC32XXAD_CTRL: */
  39#define LPC32XXAD_STROBE        0x00000002
  40#define LPC32XXAD_PDN_CTRL      0x00000004
  41
  42/* Bit definitions for LPC32XXAD_VALUE: */
  43#define LPC32XXAD_VALUE_MASK    0x000003FF
  44
  45#define LPC32XXAD_NAME "lpc32xx-adc"
  46
  47struct lpc32xx_adc_state {
  48        void __iomem *adc_base;
  49        struct clk *clk;
  50        struct completion completion;
  51        struct regulator *vref;
  52
  53        u32 value;
  54};
  55
  56static int lpc32xx_read_raw(struct iio_dev *indio_dev,
  57                            struct iio_chan_spec const *chan,
  58                            int *val,
  59                            int *val2,
  60                            long mask)
  61{
  62        struct lpc32xx_adc_state *st = iio_priv(indio_dev);
  63        int ret;
  64
  65        switch (mask) {
  66        case IIO_CHAN_INFO_RAW:
  67                mutex_lock(&indio_dev->mlock);
  68                ret = clk_prepare_enable(st->clk);
  69                if (ret) {
  70                        mutex_unlock(&indio_dev->mlock);
  71                        return ret;
  72                }
  73                /* Measurement setup */
  74                __raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
  75                             LPC32XXAD_REFp | LPC32XXAD_REFm,
  76                             LPC32XXAD_SELECT(st->adc_base));
  77                /* Trigger conversion */
  78                __raw_writel(LPC32XXAD_PDN_CTRL | LPC32XXAD_STROBE,
  79                             LPC32XXAD_CTRL(st->adc_base));
  80                wait_for_completion(&st->completion); /* set by ISR */
  81                clk_disable_unprepare(st->clk);
  82                *val = st->value;
  83                mutex_unlock(&indio_dev->mlock);
  84
  85                return IIO_VAL_INT;
  86
  87        case IIO_CHAN_INFO_SCALE:
  88                *val = regulator_get_voltage(st->vref) / 1000;
  89                *val2 =  10;
  90
  91                return IIO_VAL_FRACTIONAL_LOG2;
  92        default:
  93                return -EINVAL;
  94        }
  95}
  96
  97static const struct iio_info lpc32xx_adc_iio_info = {
  98        .read_raw = &lpc32xx_read_raw,
  99};
 100
 101#define LPC32XX_ADC_CHANNEL_BASE(_index)                \
 102        .type = IIO_VOLTAGE,                            \
 103        .indexed = 1,                                   \
 104        .channel = _index,                              \
 105        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
 106        .address = LPC32XXAD_IN * _index,               \
 107        .scan_index = _index,
 108
 109#define LPC32XX_ADC_CHANNEL(_index) {           \
 110        LPC32XX_ADC_CHANNEL_BASE(_index)        \
 111}
 112
 113#define LPC32XX_ADC_SCALE_CHANNEL(_index) {                     \
 114        LPC32XX_ADC_CHANNEL_BASE(_index)                        \
 115        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)    \
 116}
 117
 118static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
 119        LPC32XX_ADC_CHANNEL(0),
 120        LPC32XX_ADC_CHANNEL(1),
 121        LPC32XX_ADC_CHANNEL(2),
 122};
 123
 124static const struct iio_chan_spec lpc32xx_adc_iio_scale_channels[] = {
 125        LPC32XX_ADC_SCALE_CHANNEL(0),
 126        LPC32XX_ADC_SCALE_CHANNEL(1),
 127        LPC32XX_ADC_SCALE_CHANNEL(2),
 128};
 129
 130static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id)
 131{
 132        struct lpc32xx_adc_state *st = dev_id;
 133
 134        /* Read value and clear irq */
 135        st->value = __raw_readl(LPC32XXAD_VALUE(st->adc_base)) &
 136                LPC32XXAD_VALUE_MASK;
 137        complete(&st->completion);
 138
 139        return IRQ_HANDLED;
 140}
 141
 142static int lpc32xx_adc_probe(struct platform_device *pdev)
 143{
 144        struct lpc32xx_adc_state *st = NULL;
 145        struct resource *res;
 146        int retval = -ENODEV;
 147        struct iio_dev *iodev = NULL;
 148        int irq;
 149
 150        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 151        if (!res) {
 152                dev_err(&pdev->dev, "failed to get platform I/O memory\n");
 153                return -ENXIO;
 154        }
 155
 156        iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
 157        if (!iodev)
 158                return -ENOMEM;
 159
 160        st = iio_priv(iodev);
 161
 162        st->adc_base = devm_ioremap(&pdev->dev, res->start,
 163                                    resource_size(res));
 164        if (!st->adc_base) {
 165                dev_err(&pdev->dev, "failed mapping memory\n");
 166                return -EBUSY;
 167        }
 168
 169        st->clk = devm_clk_get(&pdev->dev, NULL);
 170        if (IS_ERR(st->clk)) {
 171                dev_err(&pdev->dev, "failed getting clock\n");
 172                return PTR_ERR(st->clk);
 173        }
 174
 175        irq = platform_get_irq(pdev, 0);
 176        if (irq <= 0)
 177                return -ENXIO;
 178
 179        retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
 180                                  LPC32XXAD_NAME, st);
 181        if (retval < 0) {
 182                dev_err(&pdev->dev, "failed requesting interrupt\n");
 183                return retval;
 184        }
 185
 186        st->vref = devm_regulator_get(&pdev->dev, "vref");
 187        if (IS_ERR(st->vref)) {
 188                iodev->channels = lpc32xx_adc_iio_channels;
 189                dev_info(&pdev->dev,
 190                         "Missing vref regulator: No scaling available\n");
 191        } else {
 192                iodev->channels = lpc32xx_adc_iio_scale_channels;
 193        }
 194
 195        platform_set_drvdata(pdev, iodev);
 196
 197        init_completion(&st->completion);
 198
 199        iodev->name = LPC32XXAD_NAME;
 200        iodev->info = &lpc32xx_adc_iio_info;
 201        iodev->modes = INDIO_DIRECT_MODE;
 202        iodev->num_channels = ARRAY_SIZE(lpc32xx_adc_iio_channels);
 203
 204        retval = devm_iio_device_register(&pdev->dev, iodev);
 205        if (retval)
 206                return retval;
 207
 208        dev_info(&pdev->dev, "LPC32XX ADC driver loaded, IRQ %d\n", irq);
 209
 210        return 0;
 211}
 212
 213static const struct of_device_id lpc32xx_adc_match[] = {
 214        { .compatible = "nxp,lpc3220-adc" },
 215        {},
 216};
 217MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
 218
 219static struct platform_driver lpc32xx_adc_driver = {
 220        .probe          = lpc32xx_adc_probe,
 221        .driver         = {
 222                .name   = LPC32XXAD_NAME,
 223                .of_match_table = lpc32xx_adc_match,
 224        },
 225};
 226
 227module_platform_driver(lpc32xx_adc_driver);
 228
 229MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
 230MODULE_DESCRIPTION("LPC32XX ADC driver");
 231MODULE_LICENSE("GPL");
 232