linux/drivers/iio/adc/fsl-imx25-gcq.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
   4 *
   5 * This is the driver for the imx25 GCQ (Generic Conversion Queue)
   6 * connected to the imx25 ADC.
   7 */
   8
   9#include <dt-bindings/iio/adc/fsl-imx25-gcq.h>
  10#include <linux/clk.h>
  11#include <linux/iio/iio.h>
  12#include <linux/interrupt.h>
  13#include <linux/mfd/imx25-tsadc.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/platform_device.h>
  17#include <linux/regmap.h>
  18#include <linux/regulator/consumer.h>
  19
  20#define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000))
  21
  22static const char * const driver_name = "mx25-gcq";
  23
  24enum mx25_gcq_cfgs {
  25        MX25_CFG_XP = 0,
  26        MX25_CFG_YP,
  27        MX25_CFG_XN,
  28        MX25_CFG_YN,
  29        MX25_CFG_WIPER,
  30        MX25_CFG_INAUX0,
  31        MX25_CFG_INAUX1,
  32        MX25_CFG_INAUX2,
  33        MX25_NUM_CFGS,
  34};
  35
  36struct mx25_gcq_priv {
  37        struct regmap *regs;
  38        struct completion completed;
  39        struct clk *clk;
  40        int irq;
  41        struct regulator *vref[4];
  42        u32 channel_vref_mv[MX25_NUM_CFGS];
  43};
  44
  45#define MX25_CQG_CHAN(chan, id) {\
  46        .type = IIO_VOLTAGE,\
  47        .indexed = 1,\
  48        .channel = chan,\
  49        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
  50                              BIT(IIO_CHAN_INFO_SCALE),\
  51        .datasheet_name = id,\
  52}
  53
  54static const struct iio_chan_spec mx25_gcq_channels[MX25_NUM_CFGS] = {
  55        MX25_CQG_CHAN(MX25_CFG_XP, "xp"),
  56        MX25_CQG_CHAN(MX25_CFG_YP, "yp"),
  57        MX25_CQG_CHAN(MX25_CFG_XN, "xn"),
  58        MX25_CQG_CHAN(MX25_CFG_YN, "yn"),
  59        MX25_CQG_CHAN(MX25_CFG_WIPER, "wiper"),
  60        MX25_CQG_CHAN(MX25_CFG_INAUX0, "inaux0"),
  61        MX25_CQG_CHAN(MX25_CFG_INAUX1, "inaux1"),
  62        MX25_CQG_CHAN(MX25_CFG_INAUX2, "inaux2"),
  63};
  64
  65static const char * const mx25_gcq_refp_names[] = {
  66        [MX25_ADC_REFP_YP] = "yp",
  67        [MX25_ADC_REFP_XP] = "xp",
  68        [MX25_ADC_REFP_INT] = "int",
  69        [MX25_ADC_REFP_EXT] = "ext",
  70};
  71
  72static irqreturn_t mx25_gcq_irq(int irq, void *data)
  73{
  74        struct mx25_gcq_priv *priv = data;
  75        u32 stats;
  76
  77        regmap_read(priv->regs, MX25_ADCQ_SR, &stats);
  78
  79        if (stats & MX25_ADCQ_SR_EOQ) {
  80                regmap_update_bits(priv->regs, MX25_ADCQ_MR,
  81                                   MX25_ADCQ_MR_EOQ_IRQ, MX25_ADCQ_MR_EOQ_IRQ);
  82                complete(&priv->completed);
  83        }
  84
  85        /* Disable conversion queue run */
  86        regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0);
  87
  88        /* Acknowledge all possible irqs */
  89        regmap_write(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR |
  90                     MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR |
  91                     MX25_ADCQ_SR_EOQ | MX25_ADCQ_SR_PD);
  92
  93        return IRQ_HANDLED;
  94}
  95
  96static int mx25_gcq_get_raw_value(struct device *dev,
  97                                  struct iio_chan_spec const *chan,
  98                                  struct mx25_gcq_priv *priv,
  99                                  int *val)
 100{
 101        long timeout;
 102        u32 data;
 103
 104        /* Setup the configuration we want to use */
 105        regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0,
 106                     MX25_ADCQ_ITEM(0, chan->channel));
 107
 108        regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ, 0);
 109
 110        /* Trigger queue for one run */
 111        regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS,
 112                           MX25_ADCQ_CR_FQS);
 113
 114        timeout = wait_for_completion_interruptible_timeout(
 115                &priv->completed, MX25_GCQ_TIMEOUT);
 116        if (timeout < 0) {
 117                dev_err(dev, "ADC wait for measurement failed\n");
 118                return timeout;
 119        } else if (timeout == 0) {
 120                dev_err(dev, "ADC timed out\n");
 121                return -ETIMEDOUT;
 122        }
 123
 124        regmap_read(priv->regs, MX25_ADCQ_FIFO, &data);
 125
 126        *val = MX25_ADCQ_FIFO_DATA(data);
 127
 128        return IIO_VAL_INT;
 129}
 130
 131static int mx25_gcq_read_raw(struct iio_dev *indio_dev,
 132                             struct iio_chan_spec const *chan, int *val,
 133                             int *val2, long mask)
 134{
 135        struct mx25_gcq_priv *priv = iio_priv(indio_dev);
 136        int ret;
 137
 138        switch (mask) {
 139        case IIO_CHAN_INFO_RAW:
 140                mutex_lock(&indio_dev->mlock);
 141                ret = mx25_gcq_get_raw_value(&indio_dev->dev, chan, priv, val);
 142                mutex_unlock(&indio_dev->mlock);
 143                return ret;
 144
 145        case IIO_CHAN_INFO_SCALE:
 146                *val = priv->channel_vref_mv[chan->channel];
 147                *val2 = 12;
 148                return IIO_VAL_FRACTIONAL_LOG2;
 149
 150        default:
 151                return -EINVAL;
 152        }
 153}
 154
 155static const struct iio_info mx25_gcq_iio_info = {
 156        .read_raw = mx25_gcq_read_raw,
 157};
 158
 159static const struct regmap_config mx25_gcq_regconfig = {
 160        .max_register = 0x5c,
 161        .reg_bits = 32,
 162        .val_bits = 32,
 163        .reg_stride = 4,
 164};
 165
 166static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
 167                               struct mx25_gcq_priv *priv)
 168{
 169        struct device_node *np = pdev->dev.of_node;
 170        struct device_node *child;
 171        struct device *dev = &pdev->dev;
 172        unsigned int refp_used[4] = {};
 173        int ret, i;
 174
 175        /*
 176         * Setup all configurations registers with a default conversion
 177         * configuration for each input
 178         */
 179        for (i = 0; i < MX25_NUM_CFGS; ++i)
 180                regmap_write(priv->regs, MX25_ADCQ_CFG(i),
 181                             MX25_ADCQ_CFG_YPLL_OFF |
 182                             MX25_ADCQ_CFG_XNUR_OFF |
 183                             MX25_ADCQ_CFG_XPUL_OFF |
 184                             MX25_ADCQ_CFG_REFP_INT |
 185                             MX25_ADCQ_CFG_IN(i) |
 186                             MX25_ADCQ_CFG_REFN_NGND2);
 187
 188        /*
 189         * First get all regulators to store them in channel_vref_mv if
 190         * necessary. Later we use that information for proper IIO scale
 191         * information.
 192         */
 193        priv->vref[MX25_ADC_REFP_INT] = NULL;
 194        priv->vref[MX25_ADC_REFP_EXT] =
 195                devm_regulator_get_optional(&pdev->dev, "vref-ext");
 196        priv->vref[MX25_ADC_REFP_XP] =
 197                devm_regulator_get_optional(&pdev->dev, "vref-xp");
 198        priv->vref[MX25_ADC_REFP_YP] =
 199                devm_regulator_get_optional(&pdev->dev, "vref-yp");
 200
 201        for_each_child_of_node(np, child) {
 202                u32 reg;
 203                u32 refp = MX25_ADCQ_CFG_REFP_INT;
 204                u32 refn = MX25_ADCQ_CFG_REFN_NGND2;
 205
 206                ret = of_property_read_u32(child, "reg", &reg);
 207                if (ret) {
 208                        dev_err(dev, "Failed to get reg property\n");
 209                        of_node_put(child);
 210                        return ret;
 211                }
 212
 213                if (reg >= MX25_NUM_CFGS) {
 214                        dev_err(dev,
 215                                "reg value is greater than the number of available configuration registers\n");
 216                        of_node_put(child);
 217                        return -EINVAL;
 218                }
 219
 220                of_property_read_u32(child, "fsl,adc-refp", &refp);
 221                of_property_read_u32(child, "fsl,adc-refn", &refn);
 222
 223                switch (refp) {
 224                case MX25_ADC_REFP_EXT:
 225                case MX25_ADC_REFP_XP:
 226                case MX25_ADC_REFP_YP:
 227                        if (IS_ERR(priv->vref[refp])) {
 228                                dev_err(dev, "Error, trying to use external voltage reference without a vref-%s regulator.",
 229                                        mx25_gcq_refp_names[refp]);
 230                                of_node_put(child);
 231                                return PTR_ERR(priv->vref[refp]);
 232                        }
 233                        priv->channel_vref_mv[reg] =
 234                                regulator_get_voltage(priv->vref[refp]);
 235                        /* Conversion from uV to mV */
 236                        priv->channel_vref_mv[reg] /= 1000;
 237                        break;
 238                case MX25_ADC_REFP_INT:
 239                        priv->channel_vref_mv[reg] = 2500;
 240                        break;
 241                default:
 242                        dev_err(dev, "Invalid positive reference %d\n", refp);
 243                        of_node_put(child);
 244                        return -EINVAL;
 245                }
 246
 247                ++refp_used[refp];
 248
 249                /*
 250                 * Shift the read values to the correct positions within the
 251                 * register.
 252                 */
 253                refp = MX25_ADCQ_CFG_REFP(refp);
 254                refn = MX25_ADCQ_CFG_REFN(refn);
 255
 256                if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp) {
 257                        dev_err(dev, "Invalid fsl,adc-refp property value\n");
 258                        of_node_put(child);
 259                        return -EINVAL;
 260                }
 261                if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn) {
 262                        dev_err(dev, "Invalid fsl,adc-refn property value\n");
 263                        of_node_put(child);
 264                        return -EINVAL;
 265                }
 266
 267                regmap_update_bits(priv->regs, MX25_ADCQ_CFG(reg),
 268                                   MX25_ADCQ_CFG_REFP_MASK |
 269                                   MX25_ADCQ_CFG_REFN_MASK,
 270                                   refp | refn);
 271        }
 272        regmap_update_bits(priv->regs, MX25_ADCQ_CR,
 273                           MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST,
 274                           MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST);
 275
 276        regmap_write(priv->regs, MX25_ADCQ_CR,
 277                     MX25_ADCQ_CR_PDMSK | MX25_ADCQ_CR_QSM_FQS);
 278
 279        /* Remove unused regulators */
 280        for (i = 0; i != 4; ++i) {
 281                if (!refp_used[i]) {
 282                        if (!IS_ERR_OR_NULL(priv->vref[i]))
 283                                devm_regulator_put(priv->vref[i]);
 284                        priv->vref[i] = NULL;
 285                }
 286        }
 287
 288        return 0;
 289}
 290
 291static int mx25_gcq_probe(struct platform_device *pdev)
 292{
 293        struct iio_dev *indio_dev;
 294        struct mx25_gcq_priv *priv;
 295        struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent);
 296        struct device *dev = &pdev->dev;
 297        struct resource *res;
 298        void __iomem *mem;
 299        int ret;
 300        int i;
 301
 302        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
 303        if (!indio_dev)
 304                return -ENOMEM;
 305
 306        priv = iio_priv(indio_dev);
 307
 308        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 309        mem = devm_ioremap_resource(dev, res);
 310        if (IS_ERR(mem))
 311                return PTR_ERR(mem);
 312
 313        priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_gcq_regconfig);
 314        if (IS_ERR(priv->regs)) {
 315                dev_err(dev, "Failed to initialize regmap\n");
 316                return PTR_ERR(priv->regs);
 317        }
 318
 319        init_completion(&priv->completed);
 320
 321        ret = mx25_gcq_setup_cfgs(pdev, priv);
 322        if (ret)
 323                return ret;
 324
 325        for (i = 0; i != 4; ++i) {
 326                if (!priv->vref[i])
 327                        continue;
 328
 329                ret = regulator_enable(priv->vref[i]);
 330                if (ret)
 331                        goto err_regulator_disable;
 332        }
 333
 334        priv->clk = tsadc->clk;
 335        ret = clk_prepare_enable(priv->clk);
 336        if (ret) {
 337                dev_err(dev, "Failed to enable clock\n");
 338                goto err_vref_disable;
 339        }
 340
 341        priv->irq = platform_get_irq(pdev, 0);
 342        if (priv->irq <= 0) {
 343                ret = priv->irq;
 344                if (!ret)
 345                        ret = -ENXIO;
 346                goto err_clk_unprepare;
 347        }
 348
 349        ret = request_irq(priv->irq, mx25_gcq_irq, 0, pdev->name, priv);
 350        if (ret) {
 351                dev_err(dev, "Failed requesting IRQ\n");
 352                goto err_clk_unprepare;
 353        }
 354
 355        indio_dev->dev.parent = &pdev->dev;
 356        indio_dev->channels = mx25_gcq_channels;
 357        indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels);
 358        indio_dev->info = &mx25_gcq_iio_info;
 359        indio_dev->name = driver_name;
 360
 361        ret = iio_device_register(indio_dev);
 362        if (ret) {
 363                dev_err(dev, "Failed to register iio device\n");
 364                goto err_irq_free;
 365        }
 366
 367        platform_set_drvdata(pdev, indio_dev);
 368
 369        return 0;
 370
 371err_irq_free:
 372        free_irq(priv->irq, priv);
 373err_clk_unprepare:
 374        clk_disable_unprepare(priv->clk);
 375err_vref_disable:
 376        i = 4;
 377err_regulator_disable:
 378        for (; i-- > 0;) {
 379                if (priv->vref[i])
 380                        regulator_disable(priv->vref[i]);
 381        }
 382        return ret;
 383}
 384
 385static int mx25_gcq_remove(struct platform_device *pdev)
 386{
 387        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 388        struct mx25_gcq_priv *priv = iio_priv(indio_dev);
 389        int i;
 390
 391        iio_device_unregister(indio_dev);
 392        free_irq(priv->irq, priv);
 393        clk_disable_unprepare(priv->clk);
 394        for (i = 4; i-- > 0;) {
 395                if (priv->vref[i])
 396                        regulator_disable(priv->vref[i]);
 397        }
 398
 399        return 0;
 400}
 401
 402static const struct of_device_id mx25_gcq_ids[] = {
 403        { .compatible = "fsl,imx25-gcq", },
 404        { /* Sentinel */ }
 405};
 406MODULE_DEVICE_TABLE(of, mx25_gcq_ids);
 407
 408static struct platform_driver mx25_gcq_driver = {
 409        .driver         = {
 410                .name   = "mx25-gcq",
 411                .of_match_table = mx25_gcq_ids,
 412        },
 413        .probe          = mx25_gcq_probe,
 414        .remove         = mx25_gcq_remove,
 415};
 416module_platform_driver(mx25_gcq_driver);
 417
 418MODULE_DESCRIPTION("ADC driver for Freescale mx25");
 419MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
 420MODULE_LICENSE("GPL v2");
 421