linux/drivers/iio/adc/rockchip_saradc.c
<<
>>
Prefs
   1/*
   2 * Rockchip Successive Approximation Register (SAR) A/D Converter
   3 * Copyright (C) 2014 ROCKCHIP, Inc.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/platform_device.h>
  18#include <linux/interrupt.h>
  19#include <linux/io.h>
  20#include <linux/of.h>
  21#include <linux/of_device.h>
  22#include <linux/clk.h>
  23#include <linux/completion.h>
  24#include <linux/regulator/consumer.h>
  25#include <linux/iio/iio.h>
  26
  27#define SARADC_DATA                     0x00
  28
  29#define SARADC_STAS                     0x04
  30#define SARADC_STAS_BUSY                BIT(0)
  31
  32#define SARADC_CTRL                     0x08
  33#define SARADC_CTRL_IRQ_STATUS          BIT(6)
  34#define SARADC_CTRL_IRQ_ENABLE          BIT(5)
  35#define SARADC_CTRL_POWER_CTRL          BIT(3)
  36#define SARADC_CTRL_CHN_MASK            0x7
  37
  38#define SARADC_DLY_PU_SOC               0x0c
  39#define SARADC_DLY_PU_SOC_MASK          0x3f
  40
  41#define SARADC_TIMEOUT                  msecs_to_jiffies(100)
  42
  43struct rockchip_saradc_data {
  44        int                             num_bits;
  45        const struct iio_chan_spec      *channels;
  46        int                             num_channels;
  47        unsigned long                   clk_rate;
  48};
  49
  50struct rockchip_saradc {
  51        void __iomem            *regs;
  52        struct clk              *pclk;
  53        struct clk              *clk;
  54        struct completion       completion;
  55        struct regulator        *vref;
  56        const struct rockchip_saradc_data *data;
  57        u16                     last_val;
  58};
  59
  60static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
  61                                    struct iio_chan_spec const *chan,
  62                                    int *val, int *val2, long mask)
  63{
  64        struct rockchip_saradc *info = iio_priv(indio_dev);
  65        int ret;
  66
  67        switch (mask) {
  68        case IIO_CHAN_INFO_RAW:
  69                mutex_lock(&indio_dev->mlock);
  70
  71                reinit_completion(&info->completion);
  72
  73                /* 8 clock periods as delay between power up and start cmd */
  74                writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
  75
  76                /* Select the channel to be used and trigger conversion */
  77                writel(SARADC_CTRL_POWER_CTRL
  78                                | (chan->channel & SARADC_CTRL_CHN_MASK)
  79                                | SARADC_CTRL_IRQ_ENABLE,
  80                       info->regs + SARADC_CTRL);
  81
  82                if (!wait_for_completion_timeout(&info->completion,
  83                                                 SARADC_TIMEOUT)) {
  84                        writel_relaxed(0, info->regs + SARADC_CTRL);
  85                        mutex_unlock(&indio_dev->mlock);
  86                        return -ETIMEDOUT;
  87                }
  88
  89                *val = info->last_val;
  90                mutex_unlock(&indio_dev->mlock);
  91                return IIO_VAL_INT;
  92        case IIO_CHAN_INFO_SCALE:
  93                ret = regulator_get_voltage(info->vref);
  94                if (ret < 0) {
  95                        dev_err(&indio_dev->dev, "failed to get voltage\n");
  96                        return ret;
  97                }
  98
  99                *val = ret / 1000;
 100                *val2 = info->data->num_bits;
 101                return IIO_VAL_FRACTIONAL_LOG2;
 102        default:
 103                return -EINVAL;
 104        }
 105}
 106
 107static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
 108{
 109        struct rockchip_saradc *info = (struct rockchip_saradc *)dev_id;
 110
 111        /* Read value */
 112        info->last_val = readl_relaxed(info->regs + SARADC_DATA);
 113        info->last_val &= GENMASK(info->data->num_bits - 1, 0);
 114
 115        /* Clear irq & power down adc */
 116        writel_relaxed(0, info->regs + SARADC_CTRL);
 117
 118        complete(&info->completion);
 119
 120        return IRQ_HANDLED;
 121}
 122
 123static const struct iio_info rockchip_saradc_iio_info = {
 124        .read_raw = rockchip_saradc_read_raw,
 125        .driver_module = THIS_MODULE,
 126};
 127
 128#define ADC_CHANNEL(_index, _id) {                              \
 129        .type = IIO_VOLTAGE,                                    \
 130        .indexed = 1,                                           \
 131        .channel = _index,                                      \
 132        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
 133        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
 134        .datasheet_name = _id,                                  \
 135}
 136
 137static const struct iio_chan_spec rockchip_saradc_iio_channels[] = {
 138        ADC_CHANNEL(0, "adc0"),
 139        ADC_CHANNEL(1, "adc1"),
 140        ADC_CHANNEL(2, "adc2"),
 141};
 142
 143static const struct rockchip_saradc_data saradc_data = {
 144        .num_bits = 10,
 145        .channels = rockchip_saradc_iio_channels,
 146        .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels),
 147        .clk_rate = 1000000,
 148};
 149
 150static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = {
 151        ADC_CHANNEL(0, "adc0"),
 152        ADC_CHANNEL(1, "adc1"),
 153};
 154
 155static const struct rockchip_saradc_data rk3066_tsadc_data = {
 156        .num_bits = 12,
 157        .channels = rockchip_rk3066_tsadc_iio_channels,
 158        .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels),
 159        .clk_rate = 50000,
 160};
 161
 162static const struct of_device_id rockchip_saradc_match[] = {
 163        {
 164                .compatible = "rockchip,saradc",
 165                .data = &saradc_data,
 166        }, {
 167                .compatible = "rockchip,rk3066-tsadc",
 168                .data = &rk3066_tsadc_data,
 169        },
 170        {},
 171};
 172MODULE_DEVICE_TABLE(of, rockchip_saradc_match);
 173
 174static int rockchip_saradc_probe(struct platform_device *pdev)
 175{
 176        struct rockchip_saradc *info = NULL;
 177        struct device_node *np = pdev->dev.of_node;
 178        struct iio_dev *indio_dev = NULL;
 179        struct resource *mem;
 180        const struct of_device_id *match;
 181        int ret;
 182        int irq;
 183
 184        if (!np)
 185                return -ENODEV;
 186
 187        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
 188        if (!indio_dev) {
 189                dev_err(&pdev->dev, "failed allocating iio device\n");
 190                return -ENOMEM;
 191        }
 192        info = iio_priv(indio_dev);
 193
 194        match = of_match_device(rockchip_saradc_match, &pdev->dev);
 195        info->data = match->data;
 196
 197        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 198        info->regs = devm_ioremap_resource(&pdev->dev, mem);
 199        if (IS_ERR(info->regs))
 200                return PTR_ERR(info->regs);
 201
 202        init_completion(&info->completion);
 203
 204        irq = platform_get_irq(pdev, 0);
 205        if (irq < 0) {
 206                dev_err(&pdev->dev, "no irq resource?\n");
 207                return irq;
 208        }
 209
 210        ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,
 211                               0, dev_name(&pdev->dev), info);
 212        if (ret < 0) {
 213                dev_err(&pdev->dev, "failed requesting irq %d\n", irq);
 214                return ret;
 215        }
 216
 217        info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
 218        if (IS_ERR(info->pclk)) {
 219                dev_err(&pdev->dev, "failed to get pclk\n");
 220                return PTR_ERR(info->pclk);
 221        }
 222
 223        info->clk = devm_clk_get(&pdev->dev, "saradc");
 224        if (IS_ERR(info->clk)) {
 225                dev_err(&pdev->dev, "failed to get adc clock\n");
 226                return PTR_ERR(info->clk);
 227        }
 228
 229        info->vref = devm_regulator_get(&pdev->dev, "vref");
 230        if (IS_ERR(info->vref)) {
 231                dev_err(&pdev->dev, "failed to get regulator, %ld\n",
 232                        PTR_ERR(info->vref));
 233                return PTR_ERR(info->vref);
 234        }
 235
 236        /*
 237         * Use a default value for the converter clock.
 238         * This may become user-configurable in the future.
 239         */
 240        ret = clk_set_rate(info->clk, info->data->clk_rate);
 241        if (ret < 0) {
 242                dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret);
 243                return ret;
 244        }
 245
 246        ret = regulator_enable(info->vref);
 247        if (ret < 0) {
 248                dev_err(&pdev->dev, "failed to enable vref regulator\n");
 249                return ret;
 250        }
 251
 252        ret = clk_prepare_enable(info->pclk);
 253        if (ret < 0) {
 254                dev_err(&pdev->dev, "failed to enable pclk\n");
 255                goto err_reg_voltage;
 256        }
 257
 258        ret = clk_prepare_enable(info->clk);
 259        if (ret < 0) {
 260                dev_err(&pdev->dev, "failed to enable converter clock\n");
 261                goto err_pclk;
 262        }
 263
 264        platform_set_drvdata(pdev, indio_dev);
 265
 266        indio_dev->name = dev_name(&pdev->dev);
 267        indio_dev->dev.parent = &pdev->dev;
 268        indio_dev->dev.of_node = pdev->dev.of_node;
 269        indio_dev->info = &rockchip_saradc_iio_info;
 270        indio_dev->modes = INDIO_DIRECT_MODE;
 271
 272        indio_dev->channels = info->data->channels;
 273        indio_dev->num_channels = info->data->num_channels;
 274
 275        ret = iio_device_register(indio_dev);
 276        if (ret)
 277                goto err_clk;
 278
 279        return 0;
 280
 281err_clk:
 282        clk_disable_unprepare(info->clk);
 283err_pclk:
 284        clk_disable_unprepare(info->pclk);
 285err_reg_voltage:
 286        regulator_disable(info->vref);
 287        return ret;
 288}
 289
 290static int rockchip_saradc_remove(struct platform_device *pdev)
 291{
 292        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 293        struct rockchip_saradc *info = iio_priv(indio_dev);
 294
 295        iio_device_unregister(indio_dev);
 296        clk_disable_unprepare(info->clk);
 297        clk_disable_unprepare(info->pclk);
 298        regulator_disable(info->vref);
 299
 300        return 0;
 301}
 302
 303#ifdef CONFIG_PM_SLEEP
 304static int rockchip_saradc_suspend(struct device *dev)
 305{
 306        struct iio_dev *indio_dev = dev_get_drvdata(dev);
 307        struct rockchip_saradc *info = iio_priv(indio_dev);
 308
 309        clk_disable_unprepare(info->clk);
 310        clk_disable_unprepare(info->pclk);
 311        regulator_disable(info->vref);
 312
 313        return 0;
 314}
 315
 316static int rockchip_saradc_resume(struct device *dev)
 317{
 318        struct iio_dev *indio_dev = dev_get_drvdata(dev);
 319        struct rockchip_saradc *info = iio_priv(indio_dev);
 320        int ret;
 321
 322        ret = regulator_enable(info->vref);
 323        if (ret)
 324                return ret;
 325
 326        ret = clk_prepare_enable(info->pclk);
 327        if (ret)
 328                return ret;
 329
 330        ret = clk_prepare_enable(info->clk);
 331        if (ret)
 332                return ret;
 333
 334        return ret;
 335}
 336#endif
 337
 338static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,
 339                         rockchip_saradc_suspend, rockchip_saradc_resume);
 340
 341static struct platform_driver rockchip_saradc_driver = {
 342        .probe          = rockchip_saradc_probe,
 343        .remove         = rockchip_saradc_remove,
 344        .driver         = {
 345                .name   = "rockchip-saradc",
 346                .of_match_table = rockchip_saradc_match,
 347                .pm     = &rockchip_saradc_pm_ops,
 348        },
 349};
 350
 351module_platform_driver(rockchip_saradc_driver);
 352
 353MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
 354MODULE_DESCRIPTION("Rockchip SARADC driver");
 355MODULE_LICENSE("GPL v2");
 356