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