linux/drivers/iio/adc/qcom-spmi-iadc.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 and
   6 * only version 2 as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 */
  13
  14#include <linux/bitops.h>
  15#include <linux/completion.h>
  16#include <linux/delay.h>
  17#include <linux/err.h>
  18#include <linux/iio/iio.h>
  19#include <linux/interrupt.h>
  20#include <linux/kernel.h>
  21#include <linux/mutex.h>
  22#include <linux/module.h>
  23#include <linux/of.h>
  24#include <linux/of_device.h>
  25#include <linux/platform_device.h>
  26#include <linux/regmap.h>
  27#include <linux/slab.h>
  28
  29/* IADC register and bit definition */
  30#define IADC_REVISION2                          0x1
  31#define IADC_REVISION2_SUPPORTED_IADC           1
  32
  33#define IADC_PERPH_TYPE                         0x4
  34#define IADC_PERPH_TYPE_ADC                     8
  35
  36#define IADC_PERPH_SUBTYPE                      0x5
  37#define IADC_PERPH_SUBTYPE_IADC                 3
  38
  39#define IADC_STATUS1                            0x8
  40#define IADC_STATUS1_OP_MODE                    4
  41#define IADC_STATUS1_REQ_STS                    BIT(1)
  42#define IADC_STATUS1_EOC                        BIT(0)
  43#define IADC_STATUS1_REQ_STS_EOC_MASK           0x3
  44
  45#define IADC_MODE_CTL                           0x40
  46#define IADC_OP_MODE_SHIFT                      3
  47#define IADC_OP_MODE_NORMAL                     0
  48#define IADC_TRIM_EN                            BIT(0)
  49
  50#define IADC_EN_CTL1                            0x46
  51#define IADC_EN_CTL1_SET                        BIT(7)
  52
  53#define IADC_CH_SEL_CTL                         0x48
  54
  55#define IADC_DIG_PARAM                          0x50
  56#define IADC_DIG_DEC_RATIO_SEL_SHIFT            2
  57
  58#define IADC_HW_SETTLE_DELAY                    0x51
  59
  60#define IADC_CONV_REQ                           0x52
  61#define IADC_CONV_REQ_SET                       BIT(7)
  62
  63#define IADC_FAST_AVG_CTL                       0x5a
  64#define IADC_FAST_AVG_EN                        0x5b
  65#define IADC_FAST_AVG_EN_SET                    BIT(7)
  66
  67#define IADC_PERH_RESET_CTL3                    0xda
  68#define IADC_FOLLOW_WARM_RB                     BIT(2)
  69
  70#define IADC_DATA                               0x60    /* 16 bits */
  71
  72#define IADC_SEC_ACCESS                         0xd0
  73#define IADC_SEC_ACCESS_DATA                    0xa5
  74
  75#define IADC_NOMINAL_RSENSE                     0xf4
  76#define IADC_NOMINAL_RSENSE_SIGN_MASK           BIT(7)
  77
  78#define IADC_REF_GAIN_MICRO_VOLTS               17857
  79
  80#define IADC_INT_RSENSE_DEVIATION               15625   /* nano Ohms per bit */
  81
  82#define IADC_INT_RSENSE_IDEAL_VALUE             10000   /* micro Ohms */
  83#define IADC_INT_RSENSE_DEFAULT_VALUE           7800    /* micro Ohms */
  84#define IADC_INT_RSENSE_DEFAULT_GF              9000    /* micro Ohms */
  85#define IADC_INT_RSENSE_DEFAULT_SMIC            9700    /* micro Ohms */
  86
  87#define IADC_CONV_TIME_MIN_US                   2000
  88#define IADC_CONV_TIME_MAX_US                   2100
  89
  90#define IADC_DEF_PRESCALING                     0 /* 1:1 */
  91#define IADC_DEF_DECIMATION                     0 /* 512 */
  92#define IADC_DEF_HW_SETTLE_TIME                 0 /* 0 us */
  93#define IADC_DEF_AVG_SAMPLES                    0 /* 1 sample */
  94
  95/* IADC channel list */
  96#define IADC_INT_RSENSE                         0
  97#define IADC_EXT_RSENSE                         1
  98#define IADC_GAIN_17P857MV                      3
  99#define IADC_EXT_OFFSET_CSP_CSN                 5
 100#define IADC_INT_OFFSET_CSP2_CSN2               6
 101
 102/**
 103 * struct iadc_chip - IADC Current ADC device structure.
 104 * @regmap: regmap for register read/write.
 105 * @dev: This device pointer.
 106 * @base: base offset for the ADC peripheral.
 107 * @rsense: Values of the internal and external sense resister in micro Ohms.
 108 * @poll_eoc: Poll for end of conversion instead of waiting for IRQ.
 109 * @offset: Raw offset values for the internal and external channels.
 110 * @gain: Raw gain of the channels.
 111 * @lock: ADC lock for access to the peripheral.
 112 * @complete: ADC notification after end of conversion interrupt is received.
 113 */
 114struct iadc_chip {
 115        struct regmap   *regmap;
 116        struct device   *dev;
 117        u16             base;
 118        bool            poll_eoc;
 119        u32             rsense[2];
 120        u16             offset[2];
 121        u16             gain;
 122        struct mutex    lock;
 123        struct completion complete;
 124};
 125
 126static int iadc_read(struct iadc_chip *iadc, u16 offset, u8 *data)
 127{
 128        unsigned int val;
 129        int ret;
 130
 131        ret = regmap_read(iadc->regmap, iadc->base + offset, &val);
 132        if (ret < 0)
 133                return ret;
 134
 135        *data = val;
 136        return 0;
 137}
 138
 139static int iadc_write(struct iadc_chip *iadc, u16 offset, u8 data)
 140{
 141        return regmap_write(iadc->regmap, iadc->base + offset, data);
 142}
 143
 144static int iadc_reset(struct iadc_chip *iadc)
 145{
 146        u8 data;
 147        int ret;
 148
 149        ret = iadc_write(iadc, IADC_SEC_ACCESS, IADC_SEC_ACCESS_DATA);
 150        if (ret < 0)
 151                return ret;
 152
 153        ret = iadc_read(iadc, IADC_PERH_RESET_CTL3, &data);
 154        if (ret < 0)
 155                return ret;
 156
 157        ret = iadc_write(iadc, IADC_SEC_ACCESS, IADC_SEC_ACCESS_DATA);
 158        if (ret < 0)
 159                return ret;
 160
 161        data |= IADC_FOLLOW_WARM_RB;
 162
 163        return iadc_write(iadc, IADC_PERH_RESET_CTL3, data);
 164}
 165
 166static int iadc_set_state(struct iadc_chip *iadc, bool state)
 167{
 168        return iadc_write(iadc, IADC_EN_CTL1, state ? IADC_EN_CTL1_SET : 0);
 169}
 170
 171static void iadc_status_show(struct iadc_chip *iadc)
 172{
 173        u8 mode, sta1, chan, dig, en, req;
 174        int ret;
 175
 176        ret = iadc_read(iadc, IADC_MODE_CTL, &mode);
 177        if (ret < 0)
 178                return;
 179
 180        ret = iadc_read(iadc, IADC_DIG_PARAM, &dig);
 181        if (ret < 0)
 182                return;
 183
 184        ret = iadc_read(iadc, IADC_CH_SEL_CTL, &chan);
 185        if (ret < 0)
 186                return;
 187
 188        ret = iadc_read(iadc, IADC_CONV_REQ, &req);
 189        if (ret < 0)
 190                return;
 191
 192        ret = iadc_read(iadc, IADC_STATUS1, &sta1);
 193        if (ret < 0)
 194                return;
 195
 196        ret = iadc_read(iadc, IADC_EN_CTL1, &en);
 197        if (ret < 0)
 198                return;
 199
 200        dev_err(iadc->dev,
 201                "mode:%02x en:%02x chan:%02x dig:%02x req:%02x sta1:%02x\n",
 202                mode, en, chan, dig, req, sta1);
 203}
 204
 205static int iadc_configure(struct iadc_chip *iadc, int channel)
 206{
 207        u8 decim, mode;
 208        int ret;
 209
 210        /* Mode selection */
 211        mode = (IADC_OP_MODE_NORMAL << IADC_OP_MODE_SHIFT) | IADC_TRIM_EN;
 212        ret = iadc_write(iadc, IADC_MODE_CTL, mode);
 213        if (ret < 0)
 214                return ret;
 215
 216        /* Channel selection */
 217        ret = iadc_write(iadc, IADC_CH_SEL_CTL, channel);
 218        if (ret < 0)
 219                return ret;
 220
 221        /* Digital parameter setup */
 222        decim = IADC_DEF_DECIMATION << IADC_DIG_DEC_RATIO_SEL_SHIFT;
 223        ret = iadc_write(iadc, IADC_DIG_PARAM, decim);
 224        if (ret < 0)
 225                return ret;
 226
 227        /* HW settle time delay */
 228        ret = iadc_write(iadc, IADC_HW_SETTLE_DELAY, IADC_DEF_HW_SETTLE_TIME);
 229        if (ret < 0)
 230                return ret;
 231
 232        ret = iadc_write(iadc, IADC_FAST_AVG_CTL, IADC_DEF_AVG_SAMPLES);
 233        if (ret < 0)
 234                return ret;
 235
 236        if (IADC_DEF_AVG_SAMPLES)
 237                ret = iadc_write(iadc, IADC_FAST_AVG_EN, IADC_FAST_AVG_EN_SET);
 238        else
 239                ret = iadc_write(iadc, IADC_FAST_AVG_EN, 0);
 240
 241        if (ret < 0)
 242                return ret;
 243
 244        if (!iadc->poll_eoc)
 245                reinit_completion(&iadc->complete);
 246
 247        ret = iadc_set_state(iadc, true);
 248        if (ret < 0)
 249                return ret;
 250
 251        /* Request conversion */
 252        return iadc_write(iadc, IADC_CONV_REQ, IADC_CONV_REQ_SET);
 253}
 254
 255static int iadc_poll_wait_eoc(struct iadc_chip *iadc, unsigned int interval_us)
 256{
 257        unsigned int count, retry;
 258        int ret;
 259        u8 sta1;
 260
 261        retry = interval_us / IADC_CONV_TIME_MIN_US;
 262
 263        for (count = 0; count < retry; count++) {
 264                ret = iadc_read(iadc, IADC_STATUS1, &sta1);
 265                if (ret < 0)
 266                        return ret;
 267
 268                sta1 &= IADC_STATUS1_REQ_STS_EOC_MASK;
 269                if (sta1 == IADC_STATUS1_EOC)
 270                        return 0;
 271
 272                usleep_range(IADC_CONV_TIME_MIN_US, IADC_CONV_TIME_MAX_US);
 273        }
 274
 275        iadc_status_show(iadc);
 276
 277        return -ETIMEDOUT;
 278}
 279
 280static int iadc_read_result(struct iadc_chip *iadc, u16 *data)
 281{
 282        return regmap_bulk_read(iadc->regmap, iadc->base + IADC_DATA, data, 2);
 283}
 284
 285static int iadc_do_conversion(struct iadc_chip *iadc, int chan, u16 *data)
 286{
 287        unsigned int wait;
 288        int ret;
 289
 290        ret = iadc_configure(iadc, chan);
 291        if (ret < 0)
 292                goto exit;
 293
 294        wait = BIT(IADC_DEF_AVG_SAMPLES) * IADC_CONV_TIME_MIN_US * 2;
 295
 296        if (iadc->poll_eoc) {
 297                ret = iadc_poll_wait_eoc(iadc, wait);
 298        } else {
 299                ret = wait_for_completion_timeout(&iadc->complete,
 300                        usecs_to_jiffies(wait));
 301                if (!ret)
 302                        ret = -ETIMEDOUT;
 303                else
 304                        /* double check conversion status */
 305                        ret = iadc_poll_wait_eoc(iadc, IADC_CONV_TIME_MIN_US);
 306        }
 307
 308        if (!ret)
 309                ret = iadc_read_result(iadc, data);
 310exit:
 311        iadc_set_state(iadc, false);
 312        if (ret < 0)
 313                dev_err(iadc->dev, "conversion failed\n");
 314
 315        return ret;
 316}
 317
 318static int iadc_read_raw(struct iio_dev *indio_dev,
 319                         struct iio_chan_spec const *chan,
 320                         int *val, int *val2, long mask)
 321{
 322        struct iadc_chip *iadc = iio_priv(indio_dev);
 323        s32 isense_ua, vsense_uv;
 324        u16 adc_raw, vsense_raw;
 325        int ret;
 326
 327        switch (mask) {
 328        case IIO_CHAN_INFO_RAW:
 329                mutex_lock(&iadc->lock);
 330                ret = iadc_do_conversion(iadc, chan->channel, &adc_raw);
 331                mutex_unlock(&iadc->lock);
 332                if (ret < 0)
 333                        return ret;
 334
 335                vsense_raw = adc_raw - iadc->offset[chan->channel];
 336
 337                vsense_uv = vsense_raw * IADC_REF_GAIN_MICRO_VOLTS;
 338                vsense_uv /= (s32)iadc->gain - iadc->offset[chan->channel];
 339
 340                isense_ua = vsense_uv / iadc->rsense[chan->channel];
 341
 342                dev_dbg(iadc->dev, "off %d gain %d adc %d %duV I %duA\n",
 343                        iadc->offset[chan->channel], iadc->gain,
 344                        adc_raw, vsense_uv, isense_ua);
 345
 346                *val = isense_ua;
 347                return IIO_VAL_INT;
 348        case IIO_CHAN_INFO_SCALE:
 349                *val = 0;
 350                *val2 = 1000;
 351                return IIO_VAL_INT_PLUS_MICRO;
 352        }
 353
 354        return -EINVAL;
 355}
 356
 357static const struct iio_info iadc_info = {
 358        .read_raw = iadc_read_raw,
 359        .driver_module = THIS_MODULE,
 360};
 361
 362static irqreturn_t iadc_isr(int irq, void *dev_id)
 363{
 364        struct iadc_chip *iadc = dev_id;
 365
 366        complete(&iadc->complete);
 367
 368        return IRQ_HANDLED;
 369}
 370
 371static int iadc_update_offset(struct iadc_chip *iadc)
 372{
 373        int ret;
 374
 375        ret = iadc_do_conversion(iadc, IADC_GAIN_17P857MV, &iadc->gain);
 376        if (ret < 0)
 377                return ret;
 378
 379        ret = iadc_do_conversion(iadc, IADC_INT_OFFSET_CSP2_CSN2,
 380                                 &iadc->offset[IADC_INT_RSENSE]);
 381        if (ret < 0)
 382                return ret;
 383
 384        if (iadc->gain == iadc->offset[IADC_INT_RSENSE]) {
 385                dev_err(iadc->dev, "error: internal offset == gain %d\n",
 386                        iadc->gain);
 387                return -EINVAL;
 388        }
 389
 390        ret = iadc_do_conversion(iadc, IADC_EXT_OFFSET_CSP_CSN,
 391                                 &iadc->offset[IADC_EXT_RSENSE]);
 392        if (ret < 0)
 393                return ret;
 394
 395        if (iadc->gain == iadc->offset[IADC_EXT_RSENSE]) {
 396                dev_err(iadc->dev, "error: external offset == gain %d\n",
 397                        iadc->gain);
 398                return -EINVAL;
 399        }
 400
 401        return 0;
 402}
 403
 404static int iadc_version_check(struct iadc_chip *iadc)
 405{
 406        u8 val;
 407        int ret;
 408
 409        ret = iadc_read(iadc, IADC_PERPH_TYPE, &val);
 410        if (ret < 0)
 411                return ret;
 412
 413        if (val < IADC_PERPH_TYPE_ADC) {
 414                dev_err(iadc->dev, "%d is not ADC\n", val);
 415                return -EINVAL;
 416        }
 417
 418        ret = iadc_read(iadc, IADC_PERPH_SUBTYPE, &val);
 419        if (ret < 0)
 420                return ret;
 421
 422        if (val < IADC_PERPH_SUBTYPE_IADC) {
 423                dev_err(iadc->dev, "%d is not IADC\n", val);
 424                return -EINVAL;
 425        }
 426
 427        ret = iadc_read(iadc, IADC_REVISION2, &val);
 428        if (ret < 0)
 429                return ret;
 430
 431        if (val < IADC_REVISION2_SUPPORTED_IADC) {
 432                dev_err(iadc->dev, "revision %d not supported\n", val);
 433                return -EINVAL;
 434        }
 435
 436        return 0;
 437}
 438
 439static int iadc_rsense_read(struct iadc_chip *iadc, struct device_node *node)
 440{
 441        int ret, sign, int_sense;
 442        u8 deviation;
 443
 444        ret = of_property_read_u32(node, "qcom,external-resistor-micro-ohms",
 445                                   &iadc->rsense[IADC_EXT_RSENSE]);
 446        if (ret < 0)
 447                iadc->rsense[IADC_EXT_RSENSE] = IADC_INT_RSENSE_IDEAL_VALUE;
 448
 449        if (!iadc->rsense[IADC_EXT_RSENSE]) {
 450                dev_err(iadc->dev, "external resistor can't be zero Ohms");
 451                return -EINVAL;
 452        }
 453
 454        ret = iadc_read(iadc, IADC_NOMINAL_RSENSE, &deviation);
 455        if (ret < 0)
 456                return ret;
 457
 458        /*
 459         * Deviation value stored is an offset from 10 mili Ohms, bit 7 is
 460         * the sign, the remaining bits have an LSB of 15625 nano Ohms.
 461         */
 462        sign = (deviation & IADC_NOMINAL_RSENSE_SIGN_MASK) ? -1 : 1;
 463
 464        deviation &= ~IADC_NOMINAL_RSENSE_SIGN_MASK;
 465
 466        /* Scale it to nono Ohms */
 467        int_sense = IADC_INT_RSENSE_IDEAL_VALUE * 1000;
 468        int_sense += sign * deviation * IADC_INT_RSENSE_DEVIATION;
 469        int_sense /= 1000; /* micro Ohms */
 470
 471        iadc->rsense[IADC_INT_RSENSE] = int_sense;
 472        return 0;
 473}
 474
 475static const struct iio_chan_spec iadc_channels[] = {
 476        {
 477                .type = IIO_CURRENT,
 478                .datasheet_name = "INTERNAL_RSENSE",
 479                .channel = 0,
 480                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 481                                      BIT(IIO_CHAN_INFO_SCALE),
 482                .indexed = 1,
 483        },
 484        {
 485                .type = IIO_CURRENT,
 486                .datasheet_name = "EXTERNAL_RSENSE",
 487                .channel = 1,
 488                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 489                                      BIT(IIO_CHAN_INFO_SCALE),
 490                .indexed = 1,
 491        },
 492};
 493
 494static int iadc_probe(struct platform_device *pdev)
 495{
 496        struct device_node *node = pdev->dev.of_node;
 497        struct device *dev = &pdev->dev;
 498        struct iio_dev *indio_dev;
 499        struct iadc_chip *iadc;
 500        int ret, irq_eoc;
 501        u32 res;
 502
 503        indio_dev = devm_iio_device_alloc(dev, sizeof(*iadc));
 504        if (!indio_dev)
 505                return -ENOMEM;
 506
 507        iadc = iio_priv(indio_dev);
 508        iadc->dev = dev;
 509
 510        iadc->regmap = dev_get_regmap(dev->parent, NULL);
 511        if (!iadc->regmap)
 512                return -ENODEV;
 513
 514        init_completion(&iadc->complete);
 515        mutex_init(&iadc->lock);
 516
 517        ret = of_property_read_u32(node, "reg", &res);
 518        if (ret < 0)
 519                return -ENODEV;
 520
 521        iadc->base = res;
 522
 523        ret = iadc_version_check(iadc);
 524        if (ret < 0)
 525                return -ENODEV;
 526
 527        ret = iadc_rsense_read(iadc, node);
 528        if (ret < 0)
 529                return -ENODEV;
 530
 531        dev_dbg(iadc->dev, "sense resistors %d and %d micro Ohm\n",
 532                iadc->rsense[IADC_INT_RSENSE],
 533                iadc->rsense[IADC_EXT_RSENSE]);
 534
 535        irq_eoc = platform_get_irq(pdev, 0);
 536        if (irq_eoc == -EPROBE_DEFER)
 537                return irq_eoc;
 538
 539        if (irq_eoc < 0)
 540                iadc->poll_eoc = true;
 541
 542        ret = iadc_reset(iadc);
 543        if (ret < 0) {
 544                dev_err(dev, "reset failed\n");
 545                return ret;
 546        }
 547
 548        if (!iadc->poll_eoc) {
 549                ret = devm_request_irq(dev, irq_eoc, iadc_isr, 0,
 550                                        "spmi-iadc", iadc);
 551                if (!ret)
 552                        enable_irq_wake(irq_eoc);
 553                else
 554                        return ret;
 555        } else {
 556                device_init_wakeup(iadc->dev, 1);
 557        }
 558
 559        ret = iadc_update_offset(iadc);
 560        if (ret < 0) {
 561                dev_err(dev, "failed offset calibration\n");
 562                return ret;
 563        }
 564
 565        indio_dev->dev.parent = dev;
 566        indio_dev->dev.of_node = node;
 567        indio_dev->name = pdev->name;
 568        indio_dev->modes = INDIO_DIRECT_MODE;
 569        indio_dev->info = &iadc_info;
 570        indio_dev->channels = iadc_channels;
 571        indio_dev->num_channels = ARRAY_SIZE(iadc_channels);
 572
 573        return devm_iio_device_register(dev, indio_dev);
 574}
 575
 576static const struct of_device_id iadc_match_table[] = {
 577        { .compatible = "qcom,spmi-iadc" },
 578        { }
 579};
 580
 581MODULE_DEVICE_TABLE(of, iadc_match_table);
 582
 583static struct platform_driver iadc_driver = {
 584        .driver = {
 585                   .name = "qcom-spmi-iadc",
 586                   .of_match_table = iadc_match_table,
 587        },
 588        .probe = iadc_probe,
 589};
 590
 591module_platform_driver(iadc_driver);
 592
 593MODULE_ALIAS("platform:qcom-spmi-iadc");
 594MODULE_DESCRIPTION("Qualcomm SPMI PMIC current ADC driver");
 595MODULE_LICENSE("GPL v2");
 596MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");
 597