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/delay.h>
  25#include <linux/reset.h>
  26#include <linux/regulator/consumer.h>
  27#include <linux/iio/iio.h>
  28
  29#define SARADC_DATA                     0x00
  30
  31#define SARADC_STAS                     0x04
  32#define SARADC_STAS_BUSY                BIT(0)
  33
  34#define SARADC_CTRL                     0x08
  35#define SARADC_CTRL_IRQ_STATUS          BIT(6)
  36#define SARADC_CTRL_IRQ_ENABLE          BIT(5)
  37#define SARADC_CTRL_POWER_CTRL          BIT(3)
  38#define SARADC_CTRL_CHN_MASK            0x7
  39
  40#define SARADC_DLY_PU_SOC               0x0c
  41#define SARADC_DLY_PU_SOC_MASK          0x3f
  42
  43#define SARADC_TIMEOUT                  msecs_to_jiffies(100)
  44
  45struct rockchip_saradc_data {
  46        int                             num_bits;
  47        const struct iio_chan_spec      *channels;
  48        int                             num_channels;
  49        unsigned long                   clk_rate;
  50};
  51
  52struct rockchip_saradc {
  53        void __iomem            *regs;
  54        struct clk              *pclk;
  55        struct clk              *clk;
  56        struct completion       completion;
  57        struct regulator        *vref;
  58        struct reset_control    *reset;
  59        const struct rockchip_saradc_data *data;
  60        u16                     last_val;
  61};
  62
  63static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
  64                                    struct iio_chan_spec const *chan,
  65                                    int *val, int *val2, long mask)
  66{
  67        struct rockchip_saradc *info = iio_priv(indio_dev);
  68        int ret;
  69
  70        switch (mask) {
  71        case IIO_CHAN_INFO_RAW:
  72                mutex_lock(&indio_dev->mlock);
  73
  74                reinit_completion(&info->completion);
  75
  76                /* 8 clock periods as delay between power up and start cmd */
  77                writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
  78
  79                /* Select the channel to be used and trigger conversion */
  80                writel(SARADC_CTRL_POWER_CTRL
  81                                | (chan->channel & SARADC_CTRL_CHN_MASK)
  82                                | SARADC_CTRL_IRQ_ENABLE,
  83                       info->regs + SARADC_CTRL);
  84
  85                if (!wait_for_completion_timeout(&info->completion,
  86                                                 SARADC_TIMEOUT)) {
  87                        writel_relaxed(0, info->regs + SARADC_CTRL);
  88                        mutex_unlock(&indio_dev->mlock);
  89                        return -ETIMEDOUT;
  90                }
  91
  92                *val = info->last_val;
  93                mutex_unlock(&indio_dev->mlock);
  94                return IIO_VAL_INT;
  95        case IIO_CHAN_INFO_SCALE:
  96                ret = regulator_get_voltage(info->vref);
  97                if (ret < 0) {
  98                        dev_err(&indio_dev->dev, "failed to get voltage\n");
  99                        return ret;
 100                }
 101
 102                *val = ret / 1000;
 103                *val2 = info->data->num_bits;
 104                return IIO_VAL_FRACTIONAL_LOG2;
 105        default:
 106                return -EINVAL;
 107        }
 108}
 109
 110static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
 111{
 112        struct rockchip_saradc *info = dev_id;
 113
 114        /* Read value */
 115        info->last_val = readl_relaxed(info->regs + SARADC_DATA);
 116        info->last_val &= GENMASK(info->data->num_bits - 1, 0);
 117
 118        /* Clear irq & power down adc */
 119        writel_relaxed(0, info->regs + SARADC_CTRL);
 120
 121        complete(&info->completion);
 122
 123        return IRQ_HANDLED;
 124}
 125
 126static const struct iio_info rockchip_saradc_iio_info = {
 127        .read_raw = rockchip_saradc_read_raw,
 128        .driver_module = THIS_MODULE,
 129};
 130
 131#define ADC_CHANNEL(_index, _id) {                              \
 132        .type = IIO_VOLTAGE,                                    \
 133        .indexed = 1,                                           \
 134        .channel = _index,                                      \
 135        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
 136        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
 137        .datasheet_name = _id,                                  \
 138}
 139
 140static const struct iio_chan_spec rockchip_saradc_iio_channels[] = {
 141        ADC_CHANNEL(0, "adc0"),
 142        ADC_CHANNEL(1, "adc1"),
 143        ADC_CHANNEL(2, "adc2"),
 144};
 145
 146static const struct rockchip_saradc_data saradc_data = {
 147        .num_bits = 10,
 148        .channels = rockchip_saradc_iio_channels,
 149        .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels),
 150        .clk_rate = 1000000,
 151};
 152
 153static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = {
 154        ADC_CHANNEL(0, "adc0"),
 155        ADC_CHANNEL(1, "adc1"),
 156};
 157
 158static const struct rockchip_saradc_data rk3066_tsadc_data = {
 159        .num_bits = 12,
 160        .channels = rockchip_rk3066_tsadc_iio_channels,
 161        .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels),
 162        .clk_rate = 50000,
 163};
 164
 165static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
 166        ADC_CHANNEL(0, "adc0"),
 167        ADC_CHANNEL(1, "adc1"),
 168        ADC_CHANNEL(2, "adc2"),
 169        ADC_CHANNEL(3, "adc3"),
 170        ADC_CHANNEL(4, "adc4"),
 171        ADC_CHANNEL(5, "adc5"),
 172};
 173
 174static const struct rockchip_saradc_data rk3399_saradc_data = {
 175        .num_bits = 10,
 176        .channels = rockchip_rk3399_saradc_iio_channels,
 177        .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
 178        .clk_rate = 1000000,
 179};
 180
 181static const struct of_device_id rockchip_saradc_match[] = {
 182        {
 183                .compatible = "rockchip,saradc",
 184                .data = &saradc_data,
 185        }, {
 186                .compatible = "rockchip,rk3066-tsadc",
 187                .data = &rk3066_tsadc_data,
 188        }, {
 189                .compatible = "rockchip,rk3399-saradc",
 190                .data = &rk3399_saradc_data,
 191        },
 192        {},
 193};
 194MODULE_DEVICE_TABLE(of, rockchip_saradc_match);
 195
 196/**
 197 * Reset SARADC Controller.
 198 */
 199static void rockchip_saradc_reset_controller(struct reset_control *reset)
 200{
 201        reset_control_assert(reset);
 202        usleep_range(10, 20);
 203        reset_control_deassert(reset);
 204}
 205
 206static int rockchip_saradc_probe(struct platform_device *pdev)
 207{
 208        struct rockchip_saradc *info = NULL;
 209        struct device_node *np = pdev->dev.of_node;
 210        struct iio_dev *indio_dev = NULL;
 211        struct resource *mem;
 212        const struct of_device_id *match;
 213        int ret;
 214        int irq;
 215
 216        if (!np)
 217                return -ENODEV;
 218
 219        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
 220        if (!indio_dev) {
 221                dev_err(&pdev->dev, "failed allocating iio device\n");
 222                return -ENOMEM;
 223        }
 224        info = iio_priv(indio_dev);
 225
 226        match = of_match_device(rockchip_saradc_match, &pdev->dev);
 227        if (!match) {
 228                dev_err(&pdev->dev, "failed to match device\n");
 229                return -ENODEV;
 230        }
 231
 232        info->data = match->data;
 233
 234        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 235        info->regs = devm_ioremap_resource(&pdev->dev, mem);
 236        if (IS_ERR(info->regs))
 237                return PTR_ERR(info->regs);
 238
 239        /*
 240         * The reset should be an optional property, as it should work
 241         * with old devicetrees as well
 242         */
 243        info->reset = devm_reset_control_get_exclusive(&pdev->dev,
 244                                                       "saradc-apb");
 245        if (IS_ERR(info->reset)) {
 246                ret = PTR_ERR(info->reset);
 247                if (ret != -ENOENT)
 248                        return ret;
 249
 250                dev_dbg(&pdev->dev, "no reset control found\n");
 251                info->reset = NULL;
 252        }
 253
 254        init_completion(&info->completion);
 255
 256        irq = platform_get_irq(pdev, 0);
 257        if (irq < 0) {
 258                dev_err(&pdev->dev, "no irq resource?\n");
 259                return irq;
 260        }
 261
 262        ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,
 263                               0, dev_name(&pdev->dev), info);
 264        if (ret < 0) {
 265                dev_err(&pdev->dev, "failed requesting irq %d\n", irq);
 266                return ret;
 267        }
 268
 269        info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
 270        if (IS_ERR(info->pclk)) {
 271                dev_err(&pdev->dev, "failed to get pclk\n");
 272                return PTR_ERR(info->pclk);
 273        }
 274
 275        info->clk = devm_clk_get(&pdev->dev, "saradc");
 276        if (IS_ERR(info->clk)) {
 277                dev_err(&pdev->dev, "failed to get adc clock\n");
 278                return PTR_ERR(info->clk);
 279        }
 280
 281        info->vref = devm_regulator_get(&pdev->dev, "vref");
 282        if (IS_ERR(info->vref)) {
 283                dev_err(&pdev->dev, "failed to get regulator, %ld\n",
 284                        PTR_ERR(info->vref));
 285                return PTR_ERR(info->vref);
 286        }
 287
 288        if (info->reset)
 289                rockchip_saradc_reset_controller(info->reset);
 290
 291        /*
 292         * Use a default value for the converter clock.
 293         * This may become user-configurable in the future.
 294         */
 295        ret = clk_set_rate(info->clk, info->data->clk_rate);
 296        if (ret < 0) {
 297                dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret);
 298                return ret;
 299        }
 300
 301        ret = regulator_enable(info->vref);
 302        if (ret < 0) {
 303                dev_err(&pdev->dev, "failed to enable vref regulator\n");
 304                return ret;
 305        }
 306
 307        ret = clk_prepare_enable(info->pclk);
 308        if (ret < 0) {
 309                dev_err(&pdev->dev, "failed to enable pclk\n");
 310                goto err_reg_voltage;
 311        }
 312
 313        ret = clk_prepare_enable(info->clk);
 314        if (ret < 0) {
 315                dev_err(&pdev->dev, "failed to enable converter clock\n");
 316                goto err_pclk;
 317        }
 318
 319        platform_set_drvdata(pdev, indio_dev);
 320
 321        indio_dev->name = dev_name(&pdev->dev);
 322        indio_dev->dev.parent = &pdev->dev;
 323        indio_dev->dev.of_node = pdev->dev.of_node;
 324        indio_dev->info = &rockchip_saradc_iio_info;
 325        indio_dev->modes = INDIO_DIRECT_MODE;
 326
 327        indio_dev->channels = info->data->channels;
 328        indio_dev->num_channels = info->data->num_channels;
 329
 330        ret = iio_device_register(indio_dev);
 331        if (ret)
 332                goto err_clk;
 333
 334        return 0;
 335
 336err_clk:
 337        clk_disable_unprepare(info->clk);
 338err_pclk:
 339        clk_disable_unprepare(info->pclk);
 340err_reg_voltage:
 341        regulator_disable(info->vref);
 342        return ret;
 343}
 344
 345static int rockchip_saradc_remove(struct platform_device *pdev)
 346{
 347        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 348        struct rockchip_saradc *info = iio_priv(indio_dev);
 349
 350        iio_device_unregister(indio_dev);
 351        clk_disable_unprepare(info->clk);
 352        clk_disable_unprepare(info->pclk);
 353        regulator_disable(info->vref);
 354
 355        return 0;
 356}
 357
 358#ifdef CONFIG_PM_SLEEP
 359static int rockchip_saradc_suspend(struct device *dev)
 360{
 361        struct iio_dev *indio_dev = dev_get_drvdata(dev);
 362        struct rockchip_saradc *info = iio_priv(indio_dev);
 363
 364        clk_disable_unprepare(info->clk);
 365        clk_disable_unprepare(info->pclk);
 366        regulator_disable(info->vref);
 367
 368        return 0;
 369}
 370
 371static int rockchip_saradc_resume(struct device *dev)
 372{
 373        struct iio_dev *indio_dev = dev_get_drvdata(dev);
 374        struct rockchip_saradc *info = iio_priv(indio_dev);
 375        int ret;
 376
 377        ret = regulator_enable(info->vref);
 378        if (ret)
 379                return ret;
 380
 381        ret = clk_prepare_enable(info->pclk);
 382        if (ret)
 383                return ret;
 384
 385        ret = clk_prepare_enable(info->clk);
 386        if (ret)
 387                return ret;
 388
 389        return ret;
 390}
 391#endif
 392
 393static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,
 394                         rockchip_saradc_suspend, rockchip_saradc_resume);
 395
 396static struct platform_driver rockchip_saradc_driver = {
 397        .probe          = rockchip_saradc_probe,
 398        .remove         = rockchip_saradc_remove,
 399        .driver         = {
 400                .name   = "rockchip-saradc",
 401                .of_match_table = rockchip_saradc_match,
 402                .pm     = &rockchip_saradc_pm_ops,
 403        },
 404};
 405
 406module_platform_driver(rockchip_saradc_driver);
 407
 408MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
 409MODULE_DESCRIPTION("Rockchip SARADC driver");
 410MODULE_LICENSE("GPL v2");
 411