791 lines
17 KiB
C
791 lines
17 KiB
C
/*
|
|
* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
#include <linux/kernel.h>
|
|
#include <linux/err.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
|
|
#define KELVINMIL_DEGMIL 273160
|
|
|
|
/* Units for temperature below (on x axis) is in 0.1DegC as
|
|
required by the battery driver. Note the resolution used
|
|
here to compute the table was done for DegC to milli-volts.
|
|
In consideration to limit the size of the table for the given
|
|
temperature range below, the result is linearly interpolated
|
|
and provided to the battery driver in the units desired for
|
|
their framework which is 0.1DegC. True resolution of 0.1DegC
|
|
will result in the below table size to increase by 10 times */
|
|
static const struct pm8xxx_adc_map_pt adcmap_btm_threshold[] = {
|
|
{-300, 1642},
|
|
{-200, 1544},
|
|
{-100, 1414},
|
|
{0, 1260},
|
|
{10, 1244},
|
|
{20, 1228},
|
|
{30, 1212},
|
|
{40, 1195},
|
|
{50, 1179},
|
|
{60, 1162},
|
|
{70, 1146},
|
|
{80, 1129},
|
|
{90, 1113},
|
|
{100, 1097},
|
|
{110, 1080},
|
|
{120, 1064},
|
|
{130, 1048},
|
|
{140, 1032},
|
|
{150, 1016},
|
|
{160, 1000},
|
|
{170, 985},
|
|
{180, 969},
|
|
{190, 954},
|
|
{200, 939},
|
|
{210, 924},
|
|
{220, 909},
|
|
{230, 894},
|
|
{240, 880},
|
|
{250, 866},
|
|
{260, 852},
|
|
{270, 838},
|
|
{280, 824},
|
|
{290, 811},
|
|
{300, 798},
|
|
{310, 785},
|
|
{320, 773},
|
|
{330, 760},
|
|
{340, 748},
|
|
{350, 736},
|
|
{360, 725},
|
|
{370, 713},
|
|
{380, 702},
|
|
{390, 691},
|
|
{400, 681},
|
|
{410, 670},
|
|
{420, 660},
|
|
{430, 650},
|
|
{440, 640},
|
|
{450, 631},
|
|
{460, 622},
|
|
{470, 613},
|
|
{480, 604},
|
|
{490, 595},
|
|
{500, 587},
|
|
{510, 579},
|
|
{520, 571},
|
|
{530, 563},
|
|
{540, 556},
|
|
{550, 548},
|
|
{560, 541},
|
|
{570, 534},
|
|
{580, 527},
|
|
{590, 521},
|
|
{600, 514},
|
|
{610, 508},
|
|
{620, 502},
|
|
{630, 496},
|
|
{640, 490},
|
|
{650, 485},
|
|
{660, 281},
|
|
{670, 274},
|
|
{680, 267},
|
|
{690, 260},
|
|
{700, 254},
|
|
{710, 247},
|
|
{720, 241},
|
|
{730, 235},
|
|
{740, 229},
|
|
{750, 224},
|
|
{760, 218},
|
|
{770, 213},
|
|
{780, 208},
|
|
{790, 203}
|
|
};
|
|
|
|
static const struct pm8xxx_adc_map_pt adcmap_pa_therm[] = {
|
|
{1731, -30},
|
|
{1726, -29},
|
|
{1721, -28},
|
|
{1715, -27},
|
|
{1710, -26},
|
|
{1703, -25},
|
|
{1697, -24},
|
|
{1690, -23},
|
|
{1683, -22},
|
|
{1675, -21},
|
|
{1667, -20},
|
|
{1659, -19},
|
|
{1650, -18},
|
|
{1641, -17},
|
|
{1632, -16},
|
|
{1622, -15},
|
|
{1611, -14},
|
|
{1600, -13},
|
|
{1589, -12},
|
|
{1577, -11},
|
|
{1565, -10},
|
|
{1552, -9},
|
|
{1539, -8},
|
|
{1525, -7},
|
|
{1511, -6},
|
|
{1496, -5},
|
|
{1481, -4},
|
|
{1465, -3},
|
|
{1449, -2},
|
|
{1432, -1},
|
|
{1415, 0},
|
|
{1398, 1},
|
|
{1380, 2},
|
|
{1362, 3},
|
|
{1343, 4},
|
|
{1324, 5},
|
|
{1305, 6},
|
|
{1285, 7},
|
|
{1265, 8},
|
|
{1245, 9},
|
|
{1224, 10},
|
|
{1203, 11},
|
|
{1182, 12},
|
|
{1161, 13},
|
|
{1139, 14},
|
|
{1118, 15},
|
|
{1096, 16},
|
|
{1074, 17},
|
|
{1052, 18},
|
|
{1030, 19},
|
|
{1008, 20},
|
|
{986, 21},
|
|
{964, 22},
|
|
{943, 23},
|
|
{921, 24},
|
|
{899, 25},
|
|
{878, 26},
|
|
{857, 27},
|
|
{836, 28},
|
|
{815, 29},
|
|
{794, 30},
|
|
{774, 31},
|
|
{754, 32},
|
|
{734, 33},
|
|
{714, 34},
|
|
{695, 35},
|
|
{676, 36},
|
|
{657, 37},
|
|
{639, 38},
|
|
{621, 39},
|
|
{604, 40},
|
|
{586, 41},
|
|
{570, 42},
|
|
{553, 43},
|
|
{537, 44},
|
|
{521, 45},
|
|
{506, 46},
|
|
{491, 47},
|
|
{476, 48},
|
|
{462, 49},
|
|
{448, 50},
|
|
{435, 51},
|
|
{421, 52},
|
|
{409, 53},
|
|
{396, 54},
|
|
{384, 55},
|
|
{372, 56},
|
|
{361, 57},
|
|
{350, 58},
|
|
{339, 59},
|
|
{329, 60},
|
|
{318, 61},
|
|
{309, 62},
|
|
{299, 63},
|
|
{290, 64},
|
|
{281, 65},
|
|
{272, 66},
|
|
{264, 67},
|
|
{256, 68},
|
|
{248, 69},
|
|
{240, 70},
|
|
{233, 71},
|
|
{226, 72},
|
|
{219, 73},
|
|
{212, 74},
|
|
{206, 75},
|
|
{199, 76},
|
|
{193, 77},
|
|
{187, 78},
|
|
{182, 79},
|
|
{176, 80},
|
|
{171, 81},
|
|
{166, 82},
|
|
{161, 83},
|
|
{156, 84},
|
|
{151, 85},
|
|
{147, 86},
|
|
{142, 87},
|
|
{138, 88},
|
|
{134, 89},
|
|
{130, 90},
|
|
{126, 91},
|
|
{122, 92},
|
|
{119, 93},
|
|
{115, 94},
|
|
{112, 95},
|
|
{109, 96},
|
|
{106, 97},
|
|
{103, 98},
|
|
{100, 99},
|
|
{97, 100},
|
|
{94, 101},
|
|
{91, 102},
|
|
{89, 103},
|
|
{86, 104},
|
|
{84, 105},
|
|
{82, 106},
|
|
{79, 107},
|
|
{77, 108},
|
|
{75, 109},
|
|
{73, 110},
|
|
{71, 111},
|
|
{69, 112},
|
|
{67, 113},
|
|
{65, 114},
|
|
{64, 115},
|
|
{62, 116},
|
|
{60, 117},
|
|
{59, 118},
|
|
{57, 119},
|
|
{56, 120},
|
|
{54, 121},
|
|
{53, 122},
|
|
{51, 123},
|
|
{50, 124},
|
|
{49, 125}
|
|
};
|
|
|
|
static const struct pm8xxx_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
|
|
{374682, -40960},
|
|
{360553, -39936},
|
|
{346630, -38912},
|
|
{332940, -37888},
|
|
{319510, -36864},
|
|
{306363, -35840},
|
|
{293521, -34816},
|
|
{281001, -33792},
|
|
{268818, -32768},
|
|
{256987, -31744},
|
|
{245516, -30720},
|
|
{234413, -29696},
|
|
{223685, -28672},
|
|
{213333, -27648},
|
|
{203360, -26624},
|
|
{193763, -25600},
|
|
{184541, -24576},
|
|
{175691, -23552},
|
|
{167205, -22528},
|
|
{159079, -21504},
|
|
{151304, -20480},
|
|
{143872, -19456},
|
|
{136775, -18432},
|
|
{130001, -17408},
|
|
{123542, -16384},
|
|
{117387, -15360},
|
|
{111526, -14336},
|
|
{105946, -13312},
|
|
{100639, -12288},
|
|
{95592, -11264},
|
|
{90795, -10240},
|
|
{86238, -9216},
|
|
{81909, -8192},
|
|
{77800, -7168},
|
|
{73899, -6144},
|
|
{70197, -5120},
|
|
{66685, -4096},
|
|
{63354, -3072},
|
|
{60194, -2048},
|
|
{57198, -1024},
|
|
{54356, 0},
|
|
{51662, 1024},
|
|
{49108, 2048},
|
|
{46687, 3072},
|
|
{44391, 4096},
|
|
{42215, 5120},
|
|
{40151, 6144},
|
|
{38195, 7168},
|
|
{36340, 8192},
|
|
{34582, 9216},
|
|
{32914, 10240},
|
|
{31333, 11264},
|
|
{29833, 12288},
|
|
{28410, 13312},
|
|
{27061, 14336},
|
|
{25781, 15360},
|
|
{24566, 16384},
|
|
{23413, 17408},
|
|
{22319, 18432},
|
|
{21280, 19456},
|
|
{20294, 20480},
|
|
{19358, 21504},
|
|
{18469, 22528},
|
|
{17624, 23552},
|
|
{16822, 24576},
|
|
{16060, 25600},
|
|
{15335, 26624},
|
|
{14646, 27648},
|
|
{13992, 28672},
|
|
{13369, 29696},
|
|
{12777, 30720},
|
|
{12214, 31744},
|
|
{11678, 32768},
|
|
{11168, 33792},
|
|
{10682, 34816},
|
|
{10220, 35840},
|
|
{9780, 36864},
|
|
{9361, 37888},
|
|
{8962, 38912},
|
|
{8582, 39936},
|
|
{8219, 40960},
|
|
{7874, 41984},
|
|
{7545, 43008},
|
|
{7231, 44032},
|
|
{6931, 45056},
|
|
{6646, 46080},
|
|
{6373, 47104},
|
|
{6113, 48128},
|
|
{5865, 49152},
|
|
{5628, 50176},
|
|
{5402, 51200},
|
|
{5185, 52224},
|
|
{4979, 53248},
|
|
{4782, 54272},
|
|
{4593, 55296},
|
|
{4413, 56320},
|
|
{4241, 57344},
|
|
{4076, 58368},
|
|
{3919, 59392},
|
|
{3768, 60416},
|
|
{3624, 61440},
|
|
{3486, 62464},
|
|
{3354, 63488},
|
|
{3227, 64512},
|
|
{3106, 65536},
|
|
{2990, 66560},
|
|
{2879, 67584},
|
|
{2773, 68608},
|
|
{2671, 69632},
|
|
{2573, 70656},
|
|
{2479, 71680},
|
|
{2390, 72704},
|
|
{2303, 73728},
|
|
{2221, 74752},
|
|
{2142, 75776},
|
|
{2066, 76800},
|
|
{1993, 77824},
|
|
{1923, 78848},
|
|
{1855, 79872},
|
|
{1791, 80896},
|
|
{1729, 81920},
|
|
{1669, 82944},
|
|
{1612, 83968},
|
|
{1557, 84992},
|
|
{1504, 86016},
|
|
{1453, 87040},
|
|
{1404, 88064},
|
|
{1357, 89088},
|
|
{1312, 90112},
|
|
{1269, 91136},
|
|
{1227, 92160},
|
|
{1187, 93184},
|
|
{1148, 94208},
|
|
{1111, 95232},
|
|
{1075, 96256},
|
|
{1040, 97280},
|
|
{1007, 98304},
|
|
{975, 99328},
|
|
{944, 100352},
|
|
{914, 101376},
|
|
{886, 102400},
|
|
{858, 103424},
|
|
{831, 104448},
|
|
{806, 105472},
|
|
{781, 106496},
|
|
{757, 107520},
|
|
{734, 108544},
|
|
{712, 109568},
|
|
{690, 110592},
|
|
{670, 111616},
|
|
{650, 112640},
|
|
{630, 113664},
|
|
{612, 114688},
|
|
{594, 115712},
|
|
{576, 116736},
|
|
{559, 117760},
|
|
{543, 118784},
|
|
{527, 119808},
|
|
{512, 120832},
|
|
{498, 121856},
|
|
{483, 122880},
|
|
{470, 123904},
|
|
{456, 124928},
|
|
{444, 125952},
|
|
{431, 126976},
|
|
{419, 128000},
|
|
{408, 129024},
|
|
{396, 130048}
|
|
};
|
|
|
|
static int32_t pm8xxx_adc_map_linear(const struct pm8xxx_adc_map_pt *pts,
|
|
uint32_t tablesize, int32_t input, int64_t *output)
|
|
{
|
|
bool descending = 1;
|
|
uint32_t i = 0;
|
|
|
|
if ((pts == NULL) || (output == NULL))
|
|
return -EINVAL;
|
|
|
|
/* Check if table is descending or ascending */
|
|
if (tablesize > 1) {
|
|
if (pts[0].x < pts[1].x)
|
|
descending = 0;
|
|
}
|
|
|
|
while (i < tablesize) {
|
|
if ((descending == 1) && (pts[i].x < input)) {
|
|
/* table entry is less than measured
|
|
value and table is descending, stop */
|
|
break;
|
|
} else if ((descending == 0) &&
|
|
(pts[i].x > input)) {
|
|
/* table entry is greater than measured
|
|
value and table is ascending, stop */
|
|
break;
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if (i == 0)
|
|
*output = pts[0].y;
|
|
else if (i == tablesize)
|
|
*output = pts[tablesize-1].y;
|
|
else {
|
|
/* result is between search_index and search_index-1 */
|
|
/* interpolate linearly */
|
|
*output = (((int32_t) ((pts[i].y - pts[i-1].y)*
|
|
(input - pts[i-1].x))/
|
|
(pts[i].x - pts[i-1].x))+
|
|
pts[i-1].y);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t pm8xxx_adc_map_batt_therm(const struct pm8xxx_adc_map_pt *pts,
|
|
uint32_t tablesize, int32_t input, int64_t *output)
|
|
{
|
|
bool descending = 1;
|
|
uint32_t i = 0;
|
|
|
|
if ((pts == NULL) || (output == NULL))
|
|
return -EINVAL;
|
|
|
|
/* Check if table is descending or ascending */
|
|
if (tablesize > 1) {
|
|
if (pts[0].y < pts[1].y)
|
|
descending = 0;
|
|
}
|
|
|
|
while (i < tablesize) {
|
|
if ((descending == 1) && (pts[i].y < input)) {
|
|
/* table entry is less than measured
|
|
value and table is descending, stop */
|
|
break;
|
|
} else if ((descending == 0) && (pts[i].y > input)) {
|
|
/* table entry is greater than measured
|
|
value and table is ascending, stop */
|
|
break;
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if (i == 0) {
|
|
*output = pts[0].x;
|
|
} else if (i == tablesize) {
|
|
*output = pts[tablesize-1].x;
|
|
} else {
|
|
/* result is between search_index and search_index-1 */
|
|
/* interpolate linearly */
|
|
*output = (((int32_t) ((pts[i].x - pts[i-1].x)*
|
|
(input - pts[i-1].y))/
|
|
(pts[i].y - pts[i-1].y))+
|
|
pts[i-1].x);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t pm8xxx_adc_scale_default(int32_t adc_code,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties,
|
|
struct pm8xxx_adc_chan_result *adc_chan_result)
|
|
{
|
|
bool negative_rawfromoffset = 0, negative_offset = 0;
|
|
int64_t scale_voltage = 0;
|
|
|
|
if (!chan_properties || !chan_properties->offset_gain_numerator ||
|
|
!chan_properties->offset_gain_denominator || !adc_properties
|
|
|| !adc_chan_result)
|
|
return -EINVAL;
|
|
|
|
scale_voltage = (adc_code -
|
|
chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
|
|
* chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
|
|
if (scale_voltage < 0) {
|
|
negative_offset = 1;
|
|
scale_voltage = -scale_voltage;
|
|
}
|
|
do_div(scale_voltage,
|
|
chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
|
|
if (negative_offset)
|
|
scale_voltage = -scale_voltage;
|
|
scale_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
|
|
|
|
if (scale_voltage < 0) {
|
|
if (adc_properties->bipolar) {
|
|
scale_voltage = -scale_voltage;
|
|
negative_rawfromoffset = 1;
|
|
} else {
|
|
scale_voltage = 0;
|
|
}
|
|
}
|
|
|
|
adc_chan_result->measurement = scale_voltage *
|
|
chan_properties->offset_gain_denominator;
|
|
|
|
/* do_div only perform positive integer division! */
|
|
do_div(adc_chan_result->measurement,
|
|
chan_properties->offset_gain_numerator);
|
|
|
|
if (negative_rawfromoffset)
|
|
adc_chan_result->measurement = -adc_chan_result->measurement;
|
|
|
|
/* Note: adc_chan_result->measurement is in the unit of
|
|
* adc_properties.adc_reference. For generic channel processing,
|
|
* channel measurement is a scale/ratio relative to the adc
|
|
* reference input */
|
|
adc_chan_result->physical = adc_chan_result->measurement;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_default);
|
|
|
|
static int64_t pm8xxx_adc_scale_ratiometric_calib(int32_t adc_code,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties)
|
|
{
|
|
int64_t adc_voltage = 0;
|
|
bool negative_offset = 0;
|
|
|
|
if (!chan_properties || !chan_properties->offset_gain_numerator ||
|
|
!chan_properties->offset_gain_denominator || !adc_properties)
|
|
return -EINVAL;
|
|
|
|
adc_voltage = (adc_code -
|
|
chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd)
|
|
* adc_properties->adc_vdd_reference;
|
|
if (adc_voltage < 0) {
|
|
negative_offset = 1;
|
|
adc_voltage = -adc_voltage;
|
|
}
|
|
do_div(adc_voltage,
|
|
chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy);
|
|
if (negative_offset)
|
|
adc_voltage = -adc_voltage;
|
|
|
|
return adc_voltage;
|
|
}
|
|
|
|
int32_t pm8xxx_adc_scale_batt_therm(int32_t adc_code,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties,
|
|
struct pm8xxx_adc_chan_result *adc_chan_result)
|
|
{
|
|
int64_t bat_voltage = 0;
|
|
|
|
bat_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
|
|
adc_properties, chan_properties);
|
|
|
|
return pm8xxx_adc_map_batt_therm(
|
|
adcmap_btm_threshold,
|
|
ARRAY_SIZE(adcmap_btm_threshold),
|
|
bat_voltage,
|
|
&adc_chan_result->physical);
|
|
}
|
|
EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_therm);
|
|
|
|
int32_t pm8xxx_adc_scale_pa_therm(int32_t adc_code,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties,
|
|
struct pm8xxx_adc_chan_result *adc_chan_result)
|
|
{
|
|
int64_t pa_voltage = 0;
|
|
|
|
pa_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
|
|
adc_properties, chan_properties);
|
|
|
|
return pm8xxx_adc_map_linear(
|
|
adcmap_pa_therm,
|
|
ARRAY_SIZE(adcmap_pa_therm),
|
|
pa_voltage,
|
|
&adc_chan_result->physical);
|
|
}
|
|
EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pa_therm);
|
|
|
|
int32_t pm8xxx_adc_scale_batt_id(int32_t adc_code,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties,
|
|
struct pm8xxx_adc_chan_result *adc_chan_result)
|
|
{
|
|
int64_t batt_id_voltage = 0;
|
|
|
|
batt_id_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
|
|
adc_properties, chan_properties);
|
|
adc_chan_result->physical = batt_id_voltage;
|
|
adc_chan_result->physical = adc_chan_result->measurement;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_id);
|
|
|
|
int32_t pm8xxx_adc_scale_pmic_therm(int32_t adc_code,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties,
|
|
struct pm8xxx_adc_chan_result *adc_chan_result)
|
|
{
|
|
int64_t pmic_voltage = 0;
|
|
bool negative_offset = 0;
|
|
|
|
if (!chan_properties || !chan_properties->offset_gain_numerator ||
|
|
!chan_properties->offset_gain_denominator || !adc_properties
|
|
|| !adc_chan_result)
|
|
return -EINVAL;
|
|
|
|
pmic_voltage = (adc_code -
|
|
chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
|
|
* chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
|
|
if (pmic_voltage < 0) {
|
|
negative_offset = 1;
|
|
pmic_voltage = -pmic_voltage;
|
|
}
|
|
do_div(pmic_voltage,
|
|
chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
|
|
if (negative_offset)
|
|
pmic_voltage = -pmic_voltage;
|
|
pmic_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
|
|
|
|
if (pmic_voltage > 0) {
|
|
/* 2mV/K */
|
|
adc_chan_result->measurement = pmic_voltage*
|
|
chan_properties->offset_gain_denominator;
|
|
|
|
do_div(adc_chan_result->measurement,
|
|
chan_properties->offset_gain_numerator * 2);
|
|
} else {
|
|
adc_chan_result->measurement = 0;
|
|
}
|
|
/* Change to .001 deg C */
|
|
adc_chan_result->measurement -= KELVINMIL_DEGMIL;
|
|
adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pmic_therm);
|
|
|
|
/* Scales the ADC code to 0.001 degrees C using the map
|
|
* table for the XO thermistor.
|
|
*/
|
|
int32_t pm8xxx_adc_tdkntcg_therm(int32_t adc_code,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties,
|
|
struct pm8xxx_adc_chan_result *adc_chan_result)
|
|
{
|
|
int64_t xo_thm = 0;
|
|
uint32_t num1 = 0;
|
|
uint32_t num2 = 0;
|
|
uint32_t dnum = 0;
|
|
uint32_t rt_r25 = 0;
|
|
|
|
if (!chan_properties || !chan_properties->offset_gain_numerator ||
|
|
!chan_properties->offset_gain_denominator || !adc_properties
|
|
|| !adc_chan_result)
|
|
return -EINVAL;
|
|
|
|
xo_thm = pm8xxx_adc_scale_ratiometric_calib(adc_code,
|
|
adc_properties, chan_properties);
|
|
if (xo_thm < 0)
|
|
xo_thm = -xo_thm;
|
|
|
|
num1 = xo_thm << 14;
|
|
num2 = (adc_properties->adc_vdd_reference - xo_thm) >> 1;
|
|
dnum = (adc_properties->adc_vdd_reference - xo_thm);
|
|
|
|
if (dnum == 0)
|
|
rt_r25 = 0x7FFFFFFF ;
|
|
else
|
|
rt_r25 = (num1 + num2)/dnum ;
|
|
|
|
pm8xxx_adc_map_linear(adcmap_ntcg_104ef_104fb,
|
|
ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
|
|
rt_r25, &adc_chan_result->physical);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pm8xxx_adc_tdkntcg_therm);
|
|
|
|
int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *btm_param,
|
|
const struct pm8xxx_adc_properties *adc_properties,
|
|
const struct pm8xxx_adc_chan_properties *chan_properties)
|
|
{
|
|
int rc;
|
|
|
|
rc = pm8xxx_adc_map_linear(
|
|
adcmap_btm_threshold,
|
|
ARRAY_SIZE(adcmap_btm_threshold),
|
|
(btm_param->low_thr_temp),
|
|
&btm_param->low_thr_voltage);
|
|
if (rc)
|
|
return rc;
|
|
|
|
btm_param->low_thr_voltage *=
|
|
chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
|
|
do_div(btm_param->low_thr_voltage, adc_properties->adc_vdd_reference);
|
|
btm_param->low_thr_voltage +=
|
|
chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
|
|
|
|
rc = pm8xxx_adc_map_linear(
|
|
adcmap_btm_threshold,
|
|
ARRAY_SIZE(adcmap_btm_threshold),
|
|
(btm_param->high_thr_temp),
|
|
&btm_param->high_thr_voltage);
|
|
if (rc)
|
|
return rc;
|
|
|
|
btm_param->high_thr_voltage *=
|
|
chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
|
|
do_div(btm_param->high_thr_voltage, adc_properties->adc_vdd_reference);
|
|
btm_param->high_thr_voltage +=
|
|
chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
|
|
|
|
|
|
return rc;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pm8xxx_adc_batt_scaler);
|