linux/drivers/iio/adc/qcom-vadc-common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/bug.h>
   3#include <linux/kernel.h>
   4#include <linux/bitops.h>
   5#include <linux/math64.h>
   6#include <linux/log2.h>
   7#include <linux/err.h>
   8#include <linux/module.h>
   9#include <linux/units.h>
  10
  11#include "qcom-vadc-common.h"
  12
  13/* Voltage to temperature */
  14static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
  15        {1758,  -40},
  16        {1742,  -35},
  17        {1719,  -30},
  18        {1691,  -25},
  19        {1654,  -20},
  20        {1608,  -15},
  21        {1551,  -10},
  22        {1483,  -5},
  23        {1404,  0},
  24        {1315,  5},
  25        {1218,  10},
  26        {1114,  15},
  27        {1007,  20},
  28        {900,   25},
  29        {795,   30},
  30        {696,   35},
  31        {605,   40},
  32        {522,   45},
  33        {448,   50},
  34        {383,   55},
  35        {327,   60},
  36        {278,   65},
  37        {237,   70},
  38        {202,   75},
  39        {172,   80},
  40        {146,   85},
  41        {125,   90},
  42        {107,   95},
  43        {92,    100},
  44        {79,    105},
  45        {68,    110},
  46        {59,    115},
  47        {51,    120},
  48        {44,    125}
  49};
  50
  51/*
  52 * Voltage to temperature table for 100k pull up for NTCG104EF104 with
  53 * 1.875V reference.
  54 */
  55static const struct vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
  56        { 1831, -40000 },
  57        { 1814, -35000 },
  58        { 1791, -30000 },
  59        { 1761, -25000 },
  60        { 1723, -20000 },
  61        { 1675, -15000 },
  62        { 1616, -10000 },
  63        { 1545, -5000 },
  64        { 1463, 0 },
  65        { 1370, 5000 },
  66        { 1268, 10000 },
  67        { 1160, 15000 },
  68        { 1049, 20000 },
  69        { 937,  25000 },
  70        { 828,  30000 },
  71        { 726,  35000 },
  72        { 630,  40000 },
  73        { 544,  45000 },
  74        { 467,  50000 },
  75        { 399,  55000 },
  76        { 340,  60000 },
  77        { 290,  65000 },
  78        { 247,  70000 },
  79        { 209,  75000 },
  80        { 179,  80000 },
  81        { 153,  85000 },
  82        { 130,  90000 },
  83        { 112,  95000 },
  84        { 96,   100000 },
  85        { 82,   105000 },
  86        { 71,   110000 },
  87        { 62,   115000 },
  88        { 53,   120000 },
  89        { 46,   125000 },
  90};
  91
  92static const struct vadc_map_pt adcmap7_die_temp[] = {
  93        { 433700, 1967},
  94        { 473100, 1964},
  95        { 512400, 1957},
  96        { 551500, 1949},
  97        { 590500, 1940},
  98        { 629300, 1930},
  99        { 667900, 1921},
 100        { 706400, 1910},
 101        { 744600, 1896},
 102        { 782500, 1878},
 103        { 820100, 1859},
 104        { 857300, 0},
 105};
 106
 107/*
 108 * Resistance to temperature table for 100k pull up for NTCG104EF104.
 109 */
 110static const struct vadc_map_pt adcmap7_100k[] = {
 111        { 4250657, -40960 },
 112        { 3962085, -39936 },
 113        { 3694875, -38912 },
 114        { 3447322, -37888 },
 115        { 3217867, -36864 },
 116        { 3005082, -35840 },
 117        { 2807660, -34816 },
 118        { 2624405, -33792 },
 119        { 2454218, -32768 },
 120        { 2296094, -31744 },
 121        { 2149108, -30720 },
 122        { 2012414, -29696 },
 123        { 1885232, -28672 },
 124        { 1766846, -27648 },
 125        { 1656598, -26624 },
 126        { 1553884, -25600 },
 127        { 1458147, -24576 },
 128        { 1368873, -23552 },
 129        { 1285590, -22528 },
 130        { 1207863, -21504 },
 131        { 1135290, -20480 },
 132        { 1067501, -19456 },
 133        { 1004155, -18432 },
 134        { 944935, -17408 },
 135        { 889550, -16384 },
 136        { 837731, -15360 },
 137        { 789229, -14336 },
 138        { 743813, -13312 },
 139        { 701271, -12288 },
 140        { 661405, -11264 },
 141        { 624032, -10240 },
 142        { 588982, -9216 },
 143        { 556100, -8192 },
 144        { 525239, -7168 },
 145        { 496264, -6144 },
 146        { 469050, -5120 },
 147        { 443480, -4096 },
 148        { 419448, -3072 },
 149        { 396851, -2048 },
 150        { 375597, -1024 },
 151        { 355598, 0 },
 152        { 336775, 1024 },
 153        { 319052, 2048 },
 154        { 302359, 3072 },
 155        { 286630, 4096 },
 156        { 271806, 5120 },
 157        { 257829, 6144 },
 158        { 244646, 7168 },
 159        { 232209, 8192 },
 160        { 220471, 9216 },
 161        { 209390, 10240 },
 162        { 198926, 11264 },
 163        { 189040, 12288 },
 164        { 179698, 13312 },
 165        { 170868, 14336 },
 166        { 162519, 15360 },
 167        { 154622, 16384 },
 168        { 147150, 17408 },
 169        { 140079, 18432 },
 170        { 133385, 19456 },
 171        { 127046, 20480 },
 172        { 121042, 21504 },
 173        { 115352, 22528 },
 174        { 109960, 23552 },
 175        { 104848, 24576 },
 176        { 100000, 25600 },
 177        { 95402, 26624 },
 178        { 91038, 27648 },
 179        { 86897, 28672 },
 180        { 82965, 29696 },
 181        { 79232, 30720 },
 182        { 75686, 31744 },
 183        { 72316, 32768 },
 184        { 69114, 33792 },
 185        { 66070, 34816 },
 186        { 63176, 35840 },
 187        { 60423, 36864 },
 188        { 57804, 37888 },
 189        { 55312, 38912 },
 190        { 52940, 39936 },
 191        { 50681, 40960 },
 192        { 48531, 41984 },
 193        { 46482, 43008 },
 194        { 44530, 44032 },
 195        { 42670, 45056 },
 196        { 40897, 46080 },
 197        { 39207, 47104 },
 198        { 37595, 48128 },
 199        { 36057, 49152 },
 200        { 34590, 50176 },
 201        { 33190, 51200 },
 202        { 31853, 52224 },
 203        { 30577, 53248 },
 204        { 29358, 54272 },
 205        { 28194, 55296 },
 206        { 27082, 56320 },
 207        { 26020, 57344 },
 208        { 25004, 58368 },
 209        { 24033, 59392 },
 210        { 23104, 60416 },
 211        { 22216, 61440 },
 212        { 21367, 62464 },
 213        { 20554, 63488 },
 214        { 19776, 64512 },
 215        { 19031, 65536 },
 216        { 18318, 66560 },
 217        { 17636, 67584 },
 218        { 16982, 68608 },
 219        { 16355, 69632 },
 220        { 15755, 70656 },
 221        { 15180, 71680 },
 222        { 14628, 72704 },
 223        { 14099, 73728 },
 224        { 13592, 74752 },
 225        { 13106, 75776 },
 226        { 12640, 76800 },
 227        { 12192, 77824 },
 228        { 11762, 78848 },
 229        { 11350, 79872 },
 230        { 10954, 80896 },
 231        { 10574, 81920 },
 232        { 10209, 82944 },
 233        { 9858, 83968 },
 234        { 9521, 84992 },
 235        { 9197, 86016 },
 236        { 8886, 87040 },
 237        { 8587, 88064 },
 238        { 8299, 89088 },
 239        { 8023, 90112 },
 240        { 7757, 91136 },
 241        { 7501, 92160 },
 242        { 7254, 93184 },
 243        { 7017, 94208 },
 244        { 6789, 95232 },
 245        { 6570, 96256 },
 246        { 6358, 97280 },
 247        { 6155, 98304 },
 248        { 5959, 99328 },
 249        { 5770, 100352 },
 250        { 5588, 101376 },
 251        { 5412, 102400 },
 252        { 5243, 103424 },
 253        { 5080, 104448 },
 254        { 4923, 105472 },
 255        { 4771, 106496 },
 256        { 4625, 107520 },
 257        { 4484, 108544 },
 258        { 4348, 109568 },
 259        { 4217, 110592 },
 260        { 4090, 111616 },
 261        { 3968, 112640 },
 262        { 3850, 113664 },
 263        { 3736, 114688 },
 264        { 3626, 115712 },
 265        { 3519, 116736 },
 266        { 3417, 117760 },
 267        { 3317, 118784 },
 268        { 3221, 119808 },
 269        { 3129, 120832 },
 270        { 3039, 121856 },
 271        { 2952, 122880 },
 272        { 2868, 123904 },
 273        { 2787, 124928 },
 274        { 2709, 125952 },
 275        { 2633, 126976 },
 276        { 2560, 128000 },
 277        { 2489, 129024 },
 278        { 2420, 130048 }
 279};
 280
 281static int qcom_vadc_scale_hw_calib_volt(
 282                                const struct vadc_prescale_ratio *prescale,
 283                                const struct adc5_data *data,
 284                                u16 adc_code, int *result_uv);
 285static int qcom_vadc_scale_hw_calib_therm(
 286                                const struct vadc_prescale_ratio *prescale,
 287                                const struct adc5_data *data,
 288                                u16 adc_code, int *result_mdec);
 289static int qcom_vadc7_scale_hw_calib_therm(
 290                                const struct vadc_prescale_ratio *prescale,
 291                                const struct adc5_data *data,
 292                                u16 adc_code, int *result_mdec);
 293static int qcom_vadc_scale_hw_smb_temp(
 294                                const struct vadc_prescale_ratio *prescale,
 295                                const struct adc5_data *data,
 296                                u16 adc_code, int *result_mdec);
 297static int qcom_vadc_scale_hw_chg5_temp(
 298                                const struct vadc_prescale_ratio *prescale,
 299                                const struct adc5_data *data,
 300                                u16 adc_code, int *result_mdec);
 301static int qcom_vadc_scale_hw_calib_die_temp(
 302                                const struct vadc_prescale_ratio *prescale,
 303                                const struct adc5_data *data,
 304                                u16 adc_code, int *result_mdec);
 305static int qcom_vadc7_scale_hw_calib_die_temp(
 306                                const struct vadc_prescale_ratio *prescale,
 307                                const struct adc5_data *data,
 308                                u16 adc_code, int *result_mdec);
 309
 310static struct qcom_adc5_scale_type scale_adc5_fn[] = {
 311        [SCALE_HW_CALIB_DEFAULT] = {qcom_vadc_scale_hw_calib_volt},
 312        [SCALE_HW_CALIB_THERM_100K_PULLUP] = {qcom_vadc_scale_hw_calib_therm},
 313        [SCALE_HW_CALIB_XOTHERM] = {qcom_vadc_scale_hw_calib_therm},
 314        [SCALE_HW_CALIB_THERM_100K_PU_PM7] = {
 315                                        qcom_vadc7_scale_hw_calib_therm},
 316        [SCALE_HW_CALIB_PMIC_THERM] = {qcom_vadc_scale_hw_calib_die_temp},
 317        [SCALE_HW_CALIB_PMIC_THERM_PM7] = {
 318                                        qcom_vadc7_scale_hw_calib_die_temp},
 319        [SCALE_HW_CALIB_PM5_CHG_TEMP] = {qcom_vadc_scale_hw_chg5_temp},
 320        [SCALE_HW_CALIB_PM5_SMB_TEMP] = {qcom_vadc_scale_hw_smb_temp},
 321};
 322
 323static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
 324                                      u32 tablesize, s32 input, int *output)
 325{
 326        bool descending = 1;
 327        u32 i = 0;
 328
 329        if (!pts)
 330                return -EINVAL;
 331
 332        /* Check if table is descending or ascending */
 333        if (tablesize > 1) {
 334                if (pts[0].x < pts[1].x)
 335                        descending = 0;
 336        }
 337
 338        while (i < tablesize) {
 339                if ((descending) && (pts[i].x < input)) {
 340                        /* table entry is less than measured*/
 341                         /* value and table is descending, stop */
 342                        break;
 343                } else if ((!descending) &&
 344                                (pts[i].x > input)) {
 345                        /* table entry is greater than measured*/
 346                        /*value and table is ascending, stop */
 347                        break;
 348                }
 349                i++;
 350        }
 351
 352        if (i == 0) {
 353                *output = pts[0].y;
 354        } else if (i == tablesize) {
 355                *output = pts[tablesize - 1].y;
 356        } else {
 357                /* result is between search_index and search_index-1 */
 358                /* interpolate linearly */
 359                *output = (((s32)((pts[i].y - pts[i - 1].y) *
 360                        (input - pts[i - 1].x)) /
 361                        (pts[i].x - pts[i - 1].x)) +
 362                        pts[i - 1].y);
 363        }
 364
 365        return 0;
 366}
 367
 368static void qcom_vadc_scale_calib(const struct vadc_linear_graph *calib_graph,
 369                                  u16 adc_code,
 370                                  bool absolute,
 371                                  s64 *scale_voltage)
 372{
 373        *scale_voltage = (adc_code - calib_graph->gnd);
 374        *scale_voltage *= calib_graph->dx;
 375        *scale_voltage = div64_s64(*scale_voltage, calib_graph->dy);
 376        if (absolute)
 377                *scale_voltage += calib_graph->dx;
 378
 379        if (*scale_voltage < 0)
 380                *scale_voltage = 0;
 381}
 382
 383static int qcom_vadc_scale_volt(const struct vadc_linear_graph *calib_graph,
 384                                const struct vadc_prescale_ratio *prescale,
 385                                bool absolute, u16 adc_code,
 386                                int *result_uv)
 387{
 388        s64 voltage = 0, result = 0;
 389
 390        qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
 391
 392        voltage = voltage * prescale->den;
 393        result = div64_s64(voltage, prescale->num);
 394        *result_uv = result;
 395
 396        return 0;
 397}
 398
 399static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph,
 400                                 const struct vadc_prescale_ratio *prescale,
 401                                 bool absolute, u16 adc_code,
 402                                 int *result_mdec)
 403{
 404        s64 voltage = 0;
 405        int ret;
 406
 407        qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
 408
 409        if (absolute)
 410                voltage = div64_s64(voltage, 1000);
 411
 412        ret = qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb,
 413                                         ARRAY_SIZE(adcmap_100k_104ef_104fb),
 414                                         voltage, result_mdec);
 415        if (ret)
 416                return ret;
 417
 418        *result_mdec *= 1000;
 419
 420        return 0;
 421}
 422
 423static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph,
 424                                    const struct vadc_prescale_ratio *prescale,
 425                                    bool absolute,
 426                                    u16 adc_code, int *result_mdec)
 427{
 428        s64 voltage = 0;
 429        u64 temp; /* Temporary variable for do_div */
 430
 431        qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
 432
 433        if (voltage > 0) {
 434                temp = voltage * prescale->den;
 435                do_div(temp, prescale->num * 2);
 436                voltage = temp;
 437        } else {
 438                voltage = 0;
 439        }
 440
 441        *result_mdec = milli_kelvin_to_millicelsius(voltage);
 442
 443        return 0;
 444}
 445
 446static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph,
 447                                    const struct vadc_prescale_ratio *prescale,
 448                                    bool absolute,
 449                                    u16 adc_code, int *result_mdec)
 450{
 451        s64 voltage = 0, result = 0;
 452
 453        qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
 454
 455        voltage = voltage * prescale->den;
 456        voltage = div64_s64(voltage, prescale->num);
 457        voltage = ((PMI_CHG_SCALE_1) * (voltage * 2));
 458        voltage = (voltage + PMI_CHG_SCALE_2);
 459        result =  div64_s64(voltage, 1000000);
 460        *result_mdec = result;
 461
 462        return 0;
 463}
 464
 465static int qcom_vadc_scale_code_voltage_factor(u16 adc_code,
 466                                const struct vadc_prescale_ratio *prescale,
 467                                const struct adc5_data *data,
 468                                unsigned int factor)
 469{
 470        s64 voltage, temp, adc_vdd_ref_mv = 1875;
 471
 472        /*
 473         * The normal data range is between 0V to 1.875V. On cases where
 474         * we read low voltage values, the ADC code can go beyond the
 475         * range and the scale result is incorrect so we clamp the values
 476         * for the cases where the code represents a value below 0V
 477         */
 478        if (adc_code > VADC5_MAX_CODE)
 479                adc_code = 0;
 480
 481        /* (ADC code * vref_vadc (1.875V)) / full_scale_code */
 482        voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
 483        voltage = div64_s64(voltage, data->full_scale_code_volt);
 484        if (voltage > 0) {
 485                voltage *= prescale->den;
 486                temp = prescale->num * factor;
 487                voltage = div64_s64(voltage, temp);
 488        } else {
 489                voltage = 0;
 490        }
 491
 492        return (int) voltage;
 493}
 494
 495static int qcom_vadc7_scale_hw_calib_therm(
 496                                const struct vadc_prescale_ratio *prescale,
 497                                const struct adc5_data *data,
 498                                u16 adc_code, int *result_mdec)
 499{
 500        s64 resistance = adc_code;
 501        int ret, result;
 502
 503        if (adc_code >= RATIO_MAX_ADC7)
 504                return -EINVAL;
 505
 506        /* (ADC code * R_PULLUP (100Kohm)) / (full_scale_code - ADC code)*/
 507        resistance *= R_PU_100K;
 508        resistance = div64_s64(resistance, RATIO_MAX_ADC7 - adc_code);
 509
 510        ret = qcom_vadc_map_voltage_temp(adcmap7_100k,
 511                                 ARRAY_SIZE(adcmap7_100k),
 512                                 resistance, &result);
 513        if (ret)
 514                return ret;
 515
 516        *result_mdec = result;
 517
 518        return 0;
 519}
 520
 521static int qcom_vadc_scale_hw_calib_volt(
 522                                const struct vadc_prescale_ratio *prescale,
 523                                const struct adc5_data *data,
 524                                u16 adc_code, int *result_uv)
 525{
 526        *result_uv = qcom_vadc_scale_code_voltage_factor(adc_code,
 527                                prescale, data, 1);
 528
 529        return 0;
 530}
 531
 532static int qcom_vadc_scale_hw_calib_therm(
 533                                const struct vadc_prescale_ratio *prescale,
 534                                const struct adc5_data *data,
 535                                u16 adc_code, int *result_mdec)
 536{
 537        int voltage;
 538
 539        voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
 540                                prescale, data, 1000);
 541
 542        /* Map voltage to temperature from look-up table */
 543        return qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref,
 544                                 ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref),
 545                                 voltage, result_mdec);
 546}
 547
 548static int qcom_vadc_scale_hw_calib_die_temp(
 549                                const struct vadc_prescale_ratio *prescale,
 550                                const struct adc5_data *data,
 551                                u16 adc_code, int *result_mdec)
 552{
 553        *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code,
 554                                prescale, data, 2);
 555        *result_mdec = milli_kelvin_to_millicelsius(*result_mdec);
 556
 557        return 0;
 558}
 559
 560static int qcom_vadc7_scale_hw_calib_die_temp(
 561                                const struct vadc_prescale_ratio *prescale,
 562                                const struct adc5_data *data,
 563                                u16 adc_code, int *result_mdec)
 564{
 565
 566        int voltage, vtemp0, temp, i;
 567
 568        voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
 569                                prescale, data, 1);
 570
 571        if (adcmap7_die_temp[0].x > voltage) {
 572                *result_mdec = DIE_TEMP_ADC7_SCALE_1;
 573                return 0;
 574        }
 575
 576        if (adcmap7_die_temp[ARRAY_SIZE(adcmap7_die_temp) - 1].x <= voltage) {
 577                *result_mdec = DIE_TEMP_ADC7_MAX;
 578                return 0;
 579        }
 580
 581        for (i = 0; i < ARRAY_SIZE(adcmap7_die_temp); i++)
 582                if (adcmap7_die_temp[i].x > voltage)
 583                        break;
 584
 585        vtemp0 = adcmap7_die_temp[i - 1].x;
 586        voltage = voltage - vtemp0;
 587        temp = div64_s64(voltage * DIE_TEMP_ADC7_SCALE_FACTOR,
 588                adcmap7_die_temp[i - 1].y);
 589        temp += DIE_TEMP_ADC7_SCALE_1 + (DIE_TEMP_ADC7_SCALE_2 * (i - 1));
 590        *result_mdec = temp;
 591
 592        return 0;
 593}
 594
 595static int qcom_vadc_scale_hw_smb_temp(
 596                                const struct vadc_prescale_ratio *prescale,
 597                                const struct adc5_data *data,
 598                                u16 adc_code, int *result_mdec)
 599{
 600        *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code * 100,
 601                                prescale, data, PMIC5_SMB_TEMP_SCALE_FACTOR);
 602        *result_mdec = PMIC5_SMB_TEMP_CONSTANT - *result_mdec;
 603
 604        return 0;
 605}
 606
 607static int qcom_vadc_scale_hw_chg5_temp(
 608                                const struct vadc_prescale_ratio *prescale,
 609                                const struct adc5_data *data,
 610                                u16 adc_code, int *result_mdec)
 611{
 612        *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code,
 613                                prescale, data, 4);
 614        *result_mdec = PMIC5_CHG_TEMP_SCALE_FACTOR - *result_mdec;
 615
 616        return 0;
 617}
 618
 619int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
 620                    const struct vadc_linear_graph *calib_graph,
 621                    const struct vadc_prescale_ratio *prescale,
 622                    bool absolute,
 623                    u16 adc_code, int *result)
 624{
 625        switch (scaletype) {
 626        case SCALE_DEFAULT:
 627                return qcom_vadc_scale_volt(calib_graph, prescale,
 628                                            absolute, adc_code,
 629                                            result);
 630        case SCALE_THERM_100K_PULLUP:
 631        case SCALE_XOTHERM:
 632                return qcom_vadc_scale_therm(calib_graph, prescale,
 633                                             absolute, adc_code,
 634                                             result);
 635        case SCALE_PMIC_THERM:
 636                return qcom_vadc_scale_die_temp(calib_graph, prescale,
 637                                                absolute, adc_code,
 638                                                result);
 639        case SCALE_PMI_CHG_TEMP:
 640                return qcom_vadc_scale_chg_temp(calib_graph, prescale,
 641                                                absolute, adc_code,
 642                                                result);
 643        default:
 644                return -EINVAL;
 645        }
 646}
 647EXPORT_SYMBOL(qcom_vadc_scale);
 648
 649int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
 650                    const struct vadc_prescale_ratio *prescale,
 651                    const struct adc5_data *data,
 652                    u16 adc_code, int *result)
 653{
 654        if (!(scaletype >= SCALE_HW_CALIB_DEFAULT &&
 655                scaletype < SCALE_HW_CALIB_INVALID)) {
 656                pr_err("Invalid scale type %d\n", scaletype);
 657                return -EINVAL;
 658        }
 659
 660        return scale_adc5_fn[scaletype].scale_fn(prescale, data,
 661                                        adc_code, result);
 662}
 663EXPORT_SYMBOL(qcom_adc5_hw_scale);
 664
 665int qcom_vadc_decimation_from_dt(u32 value)
 666{
 667        if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
 668            value > VADC_DECIMATION_MAX)
 669                return -EINVAL;
 670
 671        return __ffs64(value / VADC_DECIMATION_MIN);
 672}
 673EXPORT_SYMBOL(qcom_vadc_decimation_from_dt);
 674
 675MODULE_LICENSE("GPL v2");
 676MODULE_DESCRIPTION("Qualcomm ADC common functionality");
 677