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        info->data = match->data;
 228
 229        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 230        info->regs = devm_ioremap_resource(&pdev->dev, mem);
 231        if (IS_ERR(info->regs))
 232                return PTR_ERR(info->regs);
 233
 234        /*
 235         * The reset should be an optional property, as it should work
 236         * with old devicetrees as well
 237         */
 238        info->reset = devm_reset_control_get(&pdev->dev, "saradc-apb");
 239        if (IS_ERR(info->reset)) {
 240                ret = PTR_ERR(info->reset);
 241                if (ret != -ENOENT)
 242                        return ret;
 243
 244                dev_dbg(&pdev->dev, "no reset control found\n");
 245                info->reset = NULL;
 246        }
 247
 248        init_completion(&info->completion);
 249
 250        irq = platform_get_irq(pdev, 0);
 251        if (irq < 0) {
 252                dev_err(&pdev->dev, "no irq resource?\n");
 253                return irq;
 254        }
 255
 256        ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,
 257                               0, dev_name(&pdev->dev), info);
 258        if (ret < 0) {
 259                dev_err(&pdev->dev, "failed requesting irq %d\n", irq);
 260                return ret;
 261        }
 262
 263        info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
 264        if (IS_ERR(info->pclk)) {
 265                dev_err(&pdev->dev, "failed to get pclk\n");
 266                return PTR_ERR(info->pclk);
 267        }
 268
 269        info->clk = devm_clk_get(&pdev->dev, "saradc");
 270        if (IS_ERR(info->clk)) {
 271                dev_err(&pdev->dev, "failed to get adc clock\n");
 272                return PTR_ERR(info->clk);
 273        }
 274
 275        info->vref = devm_regulator_get(&pdev->dev, "vref");
 276        if (IS_ERR(info->vref)) {
 277                dev_err(&pdev->dev, "failed to get regulator, %ld\n",
 278                        PTR_ERR(info->vref));
 279                return PTR_ERR(info->vref);
 280        }
 281
 282        if (info->reset)
 283                rockchip_saradc_reset_controller(info->reset);
 284
 285        /*
 286         * Use a default value for the converter clock.
 287         * This may become user-configurable in the future.
 288         */
 289        ret = clk_set_rate(info->clk, info->data->clk_rate);
 290        if (ret < 0) {
 291                dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret);
 292                return ret;
 293        }
 294
 295        ret = regulator_enable(info->vref);
 296        if (ret < 0) {
 297                dev_err(&pdev->dev, "failed to enable vref regulator\n");
 298                return ret;
 299        }
 300
 301        ret = clk_prepare_enable(info->pclk);
 302        if (ret < 0) {
 303                dev_err(&pdev->dev, "failed to enable pclk\n");
 304                goto err_reg_voltage;
 305        }
 306
 307        ret = clk_prepare_enable(info->clk);
 308        if (ret < 0) {
 309                dev_err(&pdev->dev, "failed to enable converter clock\n");
 310                goto err_pclk;
 311        }
 312
 313        platform_set_drvdata(pdev, indio_dev);
 314
 315        indio_dev->name = dev_name(&pdev->dev);
 316        indio_dev->dev.parent = &pdev->dev;
 317        indio_dev->dev.of_node = pdev->dev.of_node;
 318        indio_dev->info = &rockchip_saradc_iio_info;
 319        indio_dev->modes = INDIO_DIRECT_MODE;
 320
 321        indio_dev->channels = info->data->channels;
 322        indio_dev->num_channels = info->data->num_channels;
 323
 324        ret = iio_device_register(indio_dev);
 325        if (ret)
 326                goto err_clk;
 327
 328        return 0;
 329
 330err_clk:
 331        clk_disable_unprepare(info->clk);
 332err_pclk:
 333        clk_disable_unprepare(info->pclk);
 334err_reg_voltage:
 335        regulator_disable(info->vref);
 336        return ret;
 337}
 338
 339static int rockchip_saradc_remove(struct platform_device *pdev)
 340{
 341        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 342        struct rockchip_saradc *info = iio_priv(indio_dev);
 343
 344        iio_device_unregister(indio_dev);
 345        clk_disable_unprepare(info->clk);
 346        clk_disable_unprepare(info->pclk);
 347        regulator_disable(info->vref);
 348
 349        return 0;
 350}
 351
 352#ifdef CONFIG_PM_SLEEP
 353static int rockchip_saradc_suspend(struct device *dev)
 354{
 355        struct iio_dev *indio_dev = dev_get_drvdata(dev);
 356        struct rockchip_saradc *info = iio_priv(indio_dev);
 357
 358        clk_disable_unprepare(info->clk);
 359        clk_disable_unprepare(info->pclk);
 360        regulator_disable(info->vref);
 361
 362        return 0;
 363}
 364
 365static int rockchip_saradc_resume(struct device *dev)
 366{
 367        struct iio_dev *indio_dev = dev_get_drvdata(dev);
 368        struct rockchip_saradc *info = iio_priv(indio_dev);
 369        int ret;
 370
 371        ret = regulator_enable(info->vref);
 372        if (ret)
 373                return ret;
 374
 375        ret = clk_prepare_enable(info->pclk);
 376        if (ret)
 377                return ret;
 378
 379        ret = clk_prepare_enable(info->clk);
 380        if (ret)
 381                return ret;
 382
 383        return ret;
 384}
 385#endif
 386
 387static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,
 388                         rockchip_saradc_suspend, rockchip_saradc_resume);
 389
 390static struct platform_driver rockchip_saradc_driver = {
 391        .probe          = rockchip_saradc_probe,
 392        .remove         = rockchip_saradc_remove,
 393        .driver         = {
 394                .name   = "rockchip-saradc",
 395                .of_match_table = rockchip_saradc_match,
 396                .pm     = &rockchip_saradc_pm_ops,
 397        },
 398};
 399
 400module_platform_driver(rockchip_saradc_driver);
 401
 402MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
 403MODULE_DESCRIPTION("Rockchip SARADC driver");
 404MODULE_LICENSE("GPL v2");
 405