linux/drivers/iio/adc/npcm_adc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2019 Nuvoton Technology corporation.
   3
   4#include <linux/clk.h>
   5#include <linux/device.h>
   6#include <linux/mfd/syscon.h>
   7#include <linux/io.h>
   8#include <linux/iio/iio.h>
   9#include <linux/interrupt.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13#include <linux/regmap.h>
  14#include <linux/regulator/consumer.h>
  15#include <linux/spinlock.h>
  16#include <linux/uaccess.h>
  17#include <linux/reset.h>
  18
  19struct npcm_adc {
  20        bool int_status;
  21        u32 adc_sample_hz;
  22        struct device *dev;
  23        void __iomem *regs;
  24        struct clk *adc_clk;
  25        wait_queue_head_t wq;
  26        struct regulator *vref;
  27        struct reset_control *reset;
  28};
  29
  30/* ADC registers */
  31#define NPCM_ADCCON      0x00
  32#define NPCM_ADCDATA     0x04
  33
  34/* ADCCON Register Bits */
  35#define NPCM_ADCCON_ADC_INT_EN          BIT(21)
  36#define NPCM_ADCCON_REFSEL              BIT(19)
  37#define NPCM_ADCCON_ADC_INT_ST          BIT(18)
  38#define NPCM_ADCCON_ADC_EN              BIT(17)
  39#define NPCM_ADCCON_ADC_RST             BIT(16)
  40#define NPCM_ADCCON_ADC_CONV            BIT(13)
  41
  42#define NPCM_ADCCON_CH_MASK             GENMASK(27, 24)
  43#define NPCM_ADCCON_CH(x)               ((x) << 24)
  44#define NPCM_ADCCON_DIV_SHIFT           1
  45#define NPCM_ADCCON_DIV_MASK            GENMASK(8, 1)
  46#define NPCM_ADC_DATA_MASK(x)           ((x) & GENMASK(9, 0))
  47
  48#define NPCM_ADC_ENABLE         (NPCM_ADCCON_ADC_EN | NPCM_ADCCON_ADC_INT_EN)
  49
  50/* ADC General Definition */
  51#define NPCM_RESOLUTION_BITS            10
  52#define NPCM_INT_VREF_MV                2000
  53
  54#define NPCM_ADC_CHAN(ch) {                                     \
  55        .type = IIO_VOLTAGE,                                    \
  56        .indexed = 1,                                           \
  57        .channel = ch,                                          \
  58        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
  59        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
  60                                BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
  61}
  62
  63static const struct iio_chan_spec npcm_adc_iio_channels[] = {
  64        NPCM_ADC_CHAN(0),
  65        NPCM_ADC_CHAN(1),
  66        NPCM_ADC_CHAN(2),
  67        NPCM_ADC_CHAN(3),
  68        NPCM_ADC_CHAN(4),
  69        NPCM_ADC_CHAN(5),
  70        NPCM_ADC_CHAN(6),
  71        NPCM_ADC_CHAN(7),
  72};
  73
  74static irqreturn_t npcm_adc_isr(int irq, void *data)
  75{
  76        u32 regtemp;
  77        struct iio_dev *indio_dev = data;
  78        struct npcm_adc *info = iio_priv(indio_dev);
  79
  80        regtemp = ioread32(info->regs + NPCM_ADCCON);
  81        if (regtemp & NPCM_ADCCON_ADC_INT_ST) {
  82                iowrite32(regtemp, info->regs + NPCM_ADCCON);
  83                wake_up_interruptible(&info->wq);
  84                info->int_status = true;
  85        }
  86
  87        return IRQ_HANDLED;
  88}
  89
  90static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
  91{
  92        int ret;
  93        u32 regtemp;
  94
  95        /* Select ADC channel */
  96        regtemp = ioread32(info->regs + NPCM_ADCCON);
  97        regtemp &= ~NPCM_ADCCON_CH_MASK;
  98        info->int_status = false;
  99        iowrite32(regtemp | NPCM_ADCCON_CH(channel) |
 100                  NPCM_ADCCON_ADC_CONV, info->regs + NPCM_ADCCON);
 101
 102        ret = wait_event_interruptible_timeout(info->wq, info->int_status,
 103                                               msecs_to_jiffies(10));
 104        if (ret == 0) {
 105                regtemp = ioread32(info->regs + NPCM_ADCCON);
 106                if (regtemp & NPCM_ADCCON_ADC_CONV) {
 107                        /* if conversion failed - reset ADC module */
 108                        reset_control_assert(info->reset);
 109                        msleep(100);
 110                        reset_control_deassert(info->reset);
 111                        msleep(100);
 112
 113                        /* Enable ADC and start conversion module */
 114                        iowrite32(NPCM_ADC_ENABLE | NPCM_ADCCON_ADC_CONV,
 115                                  info->regs + NPCM_ADCCON);
 116                        dev_err(info->dev, "RESET ADC Complete\n");
 117                }
 118                return -ETIMEDOUT;
 119        }
 120        if (ret < 0)
 121                return ret;
 122
 123        *val = NPCM_ADC_DATA_MASK(ioread32(info->regs + NPCM_ADCDATA));
 124
 125        return 0;
 126}
 127
 128static int npcm_adc_read_raw(struct iio_dev *indio_dev,
 129                             struct iio_chan_spec const *chan, int *val,
 130                             int *val2, long mask)
 131{
 132        int ret;
 133        int vref_uv;
 134        struct npcm_adc *info = iio_priv(indio_dev);
 135
 136        switch (mask) {
 137        case IIO_CHAN_INFO_RAW:
 138                mutex_lock(&indio_dev->mlock);
 139                ret = npcm_adc_read(info, val, chan->channel);
 140                mutex_unlock(&indio_dev->mlock);
 141                if (ret) {
 142                        dev_err(info->dev, "NPCM ADC read failed\n");
 143                        return ret;
 144                }
 145                return IIO_VAL_INT;
 146        case IIO_CHAN_INFO_SCALE:
 147                if (!IS_ERR(info->vref)) {
 148                        vref_uv = regulator_get_voltage(info->vref);
 149                        *val = vref_uv / 1000;
 150                } else {
 151                        *val = NPCM_INT_VREF_MV;
 152                }
 153                *val2 = NPCM_RESOLUTION_BITS;
 154                return IIO_VAL_FRACTIONAL_LOG2;
 155        case IIO_CHAN_INFO_SAMP_FREQ:
 156                *val = info->adc_sample_hz;
 157                return IIO_VAL_INT;
 158        default:
 159                return -EINVAL;
 160        }
 161
 162        return 0;
 163}
 164
 165static const struct iio_info npcm_adc_iio_info = {
 166        .read_raw = &npcm_adc_read_raw,
 167};
 168
 169static const struct of_device_id npcm_adc_match[] = {
 170        { .compatible = "nuvoton,npcm750-adc", },
 171        { /* sentinel */ }
 172};
 173MODULE_DEVICE_TABLE(of, npcm_adc_match);
 174
 175static int npcm_adc_probe(struct platform_device *pdev)
 176{
 177        int ret;
 178        int irq;
 179        u32 div;
 180        u32 reg_con;
 181        struct npcm_adc *info;
 182        struct iio_dev *indio_dev;
 183        struct device *dev = &pdev->dev;
 184
 185        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
 186        if (!indio_dev)
 187                return -ENOMEM;
 188        info = iio_priv(indio_dev);
 189
 190        info->dev = &pdev->dev;
 191
 192        info->regs = devm_platform_ioremap_resource(pdev, 0);
 193        if (IS_ERR(info->regs))
 194                return PTR_ERR(info->regs);
 195
 196        info->reset = devm_reset_control_get(&pdev->dev, NULL);
 197        if (IS_ERR(info->reset))
 198                return PTR_ERR(info->reset);
 199
 200        info->adc_clk = devm_clk_get(&pdev->dev, NULL);
 201        if (IS_ERR(info->adc_clk)) {
 202                dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n");
 203                return PTR_ERR(info->adc_clk);
 204        }
 205
 206        /* calculate ADC clock sample rate */
 207        reg_con = ioread32(info->regs + NPCM_ADCCON);
 208        div = reg_con & NPCM_ADCCON_DIV_MASK;
 209        div = div >> NPCM_ADCCON_DIV_SHIFT;
 210        info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2);
 211
 212        irq = platform_get_irq(pdev, 0);
 213        if (irq <= 0) {
 214                ret = -EINVAL;
 215                goto err_disable_clk;
 216        }
 217
 218        ret = devm_request_irq(&pdev->dev, irq, npcm_adc_isr, 0,
 219                               "NPCM_ADC", indio_dev);
 220        if (ret < 0) {
 221                dev_err(dev, "failed requesting interrupt\n");
 222                goto err_disable_clk;
 223        }
 224
 225        reg_con = ioread32(info->regs + NPCM_ADCCON);
 226        info->vref = devm_regulator_get_optional(&pdev->dev, "vref");
 227        if (!IS_ERR(info->vref)) {
 228                ret = regulator_enable(info->vref);
 229                if (ret) {
 230                        dev_err(&pdev->dev, "Can't enable ADC reference voltage\n");
 231                        goto err_disable_clk;
 232                }
 233
 234                iowrite32(reg_con & ~NPCM_ADCCON_REFSEL,
 235                          info->regs + NPCM_ADCCON);
 236        } else {
 237                /*
 238                 * Any error which is not ENODEV indicates the regulator
 239                 * has been specified and so is a failure case.
 240                 */
 241                if (PTR_ERR(info->vref) != -ENODEV) {
 242                        ret = PTR_ERR(info->vref);
 243                        goto err_disable_clk;
 244                }
 245
 246                /* Use internal reference */
 247                iowrite32(reg_con | NPCM_ADCCON_REFSEL,
 248                          info->regs + NPCM_ADCCON);
 249        }
 250
 251        init_waitqueue_head(&info->wq);
 252
 253        reg_con = ioread32(info->regs + NPCM_ADCCON);
 254        reg_con |= NPCM_ADC_ENABLE;
 255
 256        /* Enable the ADC Module */
 257        iowrite32(reg_con, info->regs + NPCM_ADCCON);
 258
 259        /* Start ADC conversion */
 260        iowrite32(reg_con | NPCM_ADCCON_ADC_CONV, info->regs + NPCM_ADCCON);
 261
 262        platform_set_drvdata(pdev, indio_dev);
 263        indio_dev->name = dev_name(&pdev->dev);
 264        indio_dev->info = &npcm_adc_iio_info;
 265        indio_dev->modes = INDIO_DIRECT_MODE;
 266        indio_dev->channels = npcm_adc_iio_channels;
 267        indio_dev->num_channels = ARRAY_SIZE(npcm_adc_iio_channels);
 268
 269        ret = iio_device_register(indio_dev);
 270        if (ret) {
 271                dev_err(&pdev->dev, "Couldn't register the device.\n");
 272                goto err_iio_register;
 273        }
 274
 275        pr_info("NPCM ADC driver probed\n");
 276
 277        return 0;
 278
 279err_iio_register:
 280        iowrite32(reg_con & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
 281        if (!IS_ERR(info->vref))
 282                regulator_disable(info->vref);
 283err_disable_clk:
 284        clk_disable_unprepare(info->adc_clk);
 285
 286        return ret;
 287}
 288
 289static int npcm_adc_remove(struct platform_device *pdev)
 290{
 291        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 292        struct npcm_adc *info = iio_priv(indio_dev);
 293        u32 regtemp;
 294
 295        iio_device_unregister(indio_dev);
 296
 297        regtemp = ioread32(info->regs + NPCM_ADCCON);
 298        iowrite32(regtemp & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
 299        if (!IS_ERR(info->vref))
 300                regulator_disable(info->vref);
 301        clk_disable_unprepare(info->adc_clk);
 302
 303        return 0;
 304}
 305
 306static struct platform_driver npcm_adc_driver = {
 307        .probe          = npcm_adc_probe,
 308        .remove         = npcm_adc_remove,
 309        .driver         = {
 310                .name   = "npcm_adc",
 311                .of_match_table = npcm_adc_match,
 312        },
 313};
 314
 315module_platform_driver(npcm_adc_driver);
 316
 317MODULE_DESCRIPTION("Nuvoton NPCM ADC Driver");
 318MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
 319MODULE_LICENSE("GPL v2");
 320