Increased resolution of mapping between raw adc code and temperature for thermistors. Adjust thresholds written to ensure interrupts get triggered correctly for temperatures read. In addition, measure temperature causing threshold violation and provide it directly to thermal framework instead of waiting for thermal framework to read it. Change-Id: I4330c659a91021ef44fa17c9c79e379105aa8fc3 Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
1076 lines
21 KiB
C
1076 lines
21 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
#include <linux/bug.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/math64.h>
|
|
#include <linux/log2.h>
|
|
#include <linux/err.h>
|
|
#include <linux/module.h>
|
|
|
|
#include "qcom-vadc-common.h"
|
|
|
|
/* Voltage to temperature */
|
|
static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
|
|
{1758, -40},
|
|
{1742, -35},
|
|
{1719, -30},
|
|
{1691, -25},
|
|
{1654, -20},
|
|
{1608, -15},
|
|
{1551, -10},
|
|
{1483, -5},
|
|
{1404, 0},
|
|
{1315, 5},
|
|
{1218, 10},
|
|
{1114, 15},
|
|
{1007, 20},
|
|
{900, 25},
|
|
{795, 30},
|
|
{696, 35},
|
|
{605, 40},
|
|
{522, 45},
|
|
{448, 50},
|
|
{383, 55},
|
|
{327, 60},
|
|
{278, 65},
|
|
{237, 70},
|
|
{202, 75},
|
|
{172, 80},
|
|
{146, 85},
|
|
{125, 90},
|
|
{107, 95},
|
|
{92, 100},
|
|
{79, 105},
|
|
{68, 110},
|
|
{59, 115},
|
|
{51, 120},
|
|
{44, 125}
|
|
};
|
|
|
|
/*
|
|
* Voltage to temperature table for 100k pull up for NTCG104EF104 with
|
|
* 1.875V reference.
|
|
*/
|
|
static const struct vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
|
|
{ 1831000, -40000 },
|
|
{ 1814000, -35000 },
|
|
{ 1791000, -30000 },
|
|
{ 1761000, -25000 },
|
|
{ 1723000, -20000 },
|
|
{ 1675000, -15000 },
|
|
{ 1616000, -10000 },
|
|
{ 1545000, -5000 },
|
|
{ 1463000, 0 },
|
|
{ 1370000, 5000 },
|
|
{ 1268000, 10000 },
|
|
{ 1160000, 15000 },
|
|
{ 1049000, 20000 },
|
|
{ 937000, 25000 },
|
|
{ 828000, 30000 },
|
|
{ 726000, 35000 },
|
|
{ 630000, 40000 },
|
|
{ 544000, 45000 },
|
|
{ 467000, 50000 },
|
|
{ 399000, 55000 },
|
|
{ 340000, 60000 },
|
|
{ 290000, 65000 },
|
|
{ 247000, 70000 },
|
|
{ 209000, 75000 },
|
|
{ 179000, 80000 },
|
|
{ 153000, 85000 },
|
|
{ 130000, 90000 },
|
|
{ 112000, 95000 },
|
|
{ 96000, 100000 },
|
|
{ 82000, 105000 },
|
|
{ 71000, 110000 },
|
|
{ 62000, 115000 },
|
|
{ 53000, 120000 },
|
|
{ 46000, 125000 },
|
|
};
|
|
|
|
/*
|
|
* Voltage to temperature table for 100k pull up for bat_therm with
|
|
* Alium.
|
|
*/
|
|
static const struct vadc_map_pt adcmap_batt_therm_100k[] = {
|
|
{1840, -400},
|
|
{1835, -380},
|
|
{1828, -360},
|
|
{1821, -340},
|
|
{1813, -320},
|
|
{1803, -300},
|
|
{1793, -280},
|
|
{1781, -260},
|
|
{1768, -240},
|
|
{1753, -220},
|
|
{1737, -200},
|
|
{1719, -180},
|
|
{1700, -160},
|
|
{1679, -140},
|
|
{1655, -120},
|
|
{1630, -100},
|
|
{1603, -80},
|
|
{1574, -60},
|
|
{1543, -40},
|
|
{1510, -20},
|
|
{1475, 0},
|
|
{1438, 20},
|
|
{1400, 40},
|
|
{1360, 60},
|
|
{1318, 80},
|
|
{1276, 100},
|
|
{1232, 120},
|
|
{1187, 140},
|
|
{1142, 160},
|
|
{1097, 180},
|
|
{1051, 200},
|
|
{1005, 220},
|
|
{960, 240},
|
|
{915, 260},
|
|
{871, 280},
|
|
{828, 300},
|
|
{786, 320},
|
|
{745, 340},
|
|
{705, 360},
|
|
{666, 380},
|
|
{629, 400},
|
|
{594, 420},
|
|
{560, 440},
|
|
{527, 460},
|
|
{497, 480},
|
|
{467, 500},
|
|
{439, 520},
|
|
{413, 540},
|
|
{388, 560},
|
|
{365, 580},
|
|
{343, 600},
|
|
{322, 620},
|
|
{302, 640},
|
|
{284, 660},
|
|
{267, 680},
|
|
{251, 700},
|
|
{235, 720},
|
|
{221, 740},
|
|
{208, 760},
|
|
{195, 780},
|
|
{184, 800},
|
|
{173, 820},
|
|
{163, 840},
|
|
{153, 860},
|
|
{144, 880},
|
|
{136, 900},
|
|
{128, 920},
|
|
{120, 940},
|
|
{114, 960},
|
|
{107, 980}
|
|
};
|
|
|
|
/*
|
|
* Voltage to temperature table for 100k pull up for bat_therm with
|
|
* MLP356477.
|
|
*/
|
|
static const struct vadc_map_pt adcmap_batt_therm_100k_6125[] = {
|
|
{1770, -400},
|
|
{1757, -380},
|
|
{1743, -360},
|
|
{1727, -340},
|
|
{1710, -320},
|
|
{1691, -300},
|
|
{1671, -280},
|
|
{1650, -260},
|
|
{1627, -240},
|
|
{1602, -220},
|
|
{1576, -200},
|
|
{1548, -180},
|
|
{1519, -160},
|
|
{1488, -140},
|
|
{1456, -120},
|
|
{1423, -100},
|
|
{1388, -80},
|
|
{1353, -60},
|
|
{1316, -40},
|
|
{1278, -20},
|
|
{1240, 0},
|
|
{1201, 20},
|
|
{1162, 40},
|
|
{1122, 60},
|
|
{1082, 80},
|
|
{1042, 100},
|
|
{1003, 120},
|
|
{964, 140},
|
|
{925, 160},
|
|
{887, 180},
|
|
{849, 200},
|
|
{812, 220},
|
|
{777, 240},
|
|
{742, 260},
|
|
{708, 280},
|
|
{675, 300},
|
|
{643, 320},
|
|
{613, 340},
|
|
{583, 360},
|
|
{555, 380},
|
|
{528, 400},
|
|
{502, 420},
|
|
{477, 440},
|
|
{453, 460},
|
|
{430, 480},
|
|
{409, 500},
|
|
{388, 520},
|
|
{369, 540},
|
|
{350, 560},
|
|
{333, 580},
|
|
{316, 600},
|
|
{300, 620},
|
|
{285, 640},
|
|
{271, 660},
|
|
{257, 680},
|
|
{245, 700},
|
|
{233, 720},
|
|
{221, 740},
|
|
{210, 760},
|
|
{200, 780},
|
|
{190, 800},
|
|
{181, 820},
|
|
{173, 840},
|
|
{164, 860},
|
|
{157, 880},
|
|
{149, 900},
|
|
{142, 920},
|
|
{136, 940},
|
|
{129, 960},
|
|
{124, 980},
|
|
};
|
|
|
|
/*
|
|
* Voltage to temperature table for 30k pull up for bat_therm with
|
|
* Alium.
|
|
*/
|
|
static const struct vadc_map_pt adcmap_batt_therm_30k[] = {
|
|
{1864, -400},
|
|
{1863, -380},
|
|
{1861, -360},
|
|
{1858, -340},
|
|
{1856, -320},
|
|
{1853, -300},
|
|
{1850, -280},
|
|
{1846, -260},
|
|
{1842, -240},
|
|
{1837, -220},
|
|
{1831, -200},
|
|
{1825, -180},
|
|
{1819, -160},
|
|
{1811, -140},
|
|
{1803, -120},
|
|
{1794, -100},
|
|
{1784, -80},
|
|
{1773, -60},
|
|
{1761, -40},
|
|
{1748, -20},
|
|
{1734, 0},
|
|
{1718, 20},
|
|
{1702, 40},
|
|
{1684, 60},
|
|
{1664, 80},
|
|
{1643, 100},
|
|
{1621, 120},
|
|
{1597, 140},
|
|
{1572, 160},
|
|
{1546, 180},
|
|
{1518, 200},
|
|
{1489, 220},
|
|
{1458, 240},
|
|
{1426, 260},
|
|
{1393, 280},
|
|
{1359, 300},
|
|
{1324, 320},
|
|
{1288, 340},
|
|
{1252, 360},
|
|
{1214, 380},
|
|
{1176, 400},
|
|
{1138, 420},
|
|
{1100, 440},
|
|
{1061, 460},
|
|
{1023, 480},
|
|
{985, 500},
|
|
{947, 520},
|
|
{910, 540},
|
|
{873, 560},
|
|
{836, 580},
|
|
{801, 600},
|
|
{766, 620},
|
|
{732, 640},
|
|
{699, 660},
|
|
{668, 680},
|
|
{637, 700},
|
|
{607, 720},
|
|
{578, 740},
|
|
{550, 760},
|
|
{524, 780},
|
|
{498, 800},
|
|
{474, 820},
|
|
{451, 840},
|
|
{428, 860},
|
|
{407, 880},
|
|
{387, 900},
|
|
{367, 920},
|
|
{349, 940},
|
|
{332, 960},
|
|
{315, 980}
|
|
};
|
|
|
|
/*
|
|
* Voltage to temperature table for 30k pull up for bat_therm with
|
|
* MLP356477.
|
|
*/
|
|
static const struct vadc_map_pt adcmap_batt_therm_30k_6125[] = {
|
|
{1842, -400},
|
|
{1838, -380},
|
|
{1833, -360},
|
|
{1828, -340},
|
|
{1822, -320},
|
|
{1816, -300},
|
|
{1809, -280},
|
|
{1801, -260},
|
|
{1793, -240},
|
|
{1784, -220},
|
|
{1774, -200},
|
|
{1763, -180},
|
|
{1752, -160},
|
|
{1739, -140},
|
|
{1726, -120},
|
|
{1712, -100},
|
|
{1697, -80},
|
|
{1680, -60},
|
|
{1663, -40},
|
|
{1645, -20},
|
|
{1625, 0},
|
|
{1605, 20},
|
|
{1583, 40},
|
|
{1561, 60},
|
|
{1537, 80},
|
|
{1513, 100},
|
|
{1487, 120},
|
|
{1461, 140},
|
|
{1433, 160},
|
|
{1405, 180},
|
|
{1376, 200},
|
|
{1347, 220},
|
|
{1316, 240},
|
|
{1286, 260},
|
|
{1254, 280},
|
|
{1223, 300},
|
|
{1191, 320},
|
|
{1159, 340},
|
|
{1126, 360},
|
|
{1094, 380},
|
|
{1062, 400},
|
|
{1029, 420},
|
|
{997, 440},
|
|
{966, 460},
|
|
{934, 480},
|
|
{903, 500},
|
|
{873, 520},
|
|
{843, 540},
|
|
{813, 560},
|
|
{784, 580},
|
|
{756, 600},
|
|
{728, 620},
|
|
{702, 640},
|
|
{675, 660},
|
|
{650, 680},
|
|
{625, 700},
|
|
{601, 720},
|
|
{578, 740},
|
|
{556, 760},
|
|
{534, 780},
|
|
{513, 800},
|
|
{493, 820},
|
|
{474, 840},
|
|
{455, 860},
|
|
{437, 880},
|
|
{420, 900},
|
|
{403, 920},
|
|
{387, 940},
|
|
{372, 960},
|
|
{357, 980},
|
|
};
|
|
|
|
/*
|
|
* Voltage to temperature table for 400k pull up for bat_therm with
|
|
* Alium.
|
|
*/
|
|
static const struct vadc_map_pt adcmap_batt_therm_400k[] = {
|
|
{1744, -400},
|
|
{1724, -380},
|
|
{1701, -360},
|
|
{1676, -340},
|
|
{1648, -320},
|
|
{1618, -300},
|
|
{1584, -280},
|
|
{1548, -260},
|
|
{1509, -240},
|
|
{1468, -220},
|
|
{1423, -200},
|
|
{1377, -180},
|
|
{1328, -160},
|
|
{1277, -140},
|
|
{1225, -120},
|
|
{1171, -100},
|
|
{1117, -80},
|
|
{1062, -60},
|
|
{1007, -40},
|
|
{953, -20},
|
|
{899, 0},
|
|
{847, 20},
|
|
{795, 40},
|
|
{745, 60},
|
|
{697, 80},
|
|
{651, 100},
|
|
{607, 120},
|
|
{565, 140},
|
|
{526, 160},
|
|
{488, 180},
|
|
{453, 200},
|
|
{420, 220},
|
|
{390, 240},
|
|
{361, 260},
|
|
{334, 280},
|
|
{309, 300},
|
|
{286, 320},
|
|
{265, 340},
|
|
{245, 360},
|
|
{227, 380},
|
|
{210, 400},
|
|
{195, 420},
|
|
{180, 440},
|
|
{167, 460},
|
|
{155, 480},
|
|
{144, 500},
|
|
{133, 520},
|
|
{124, 540},
|
|
{115, 560},
|
|
{107, 580},
|
|
{99, 600},
|
|
{92, 620},
|
|
{86, 640},
|
|
{80, 660},
|
|
{75, 680},
|
|
{70, 700},
|
|
{65, 720},
|
|
{61, 740},
|
|
{57, 760},
|
|
{53, 780},
|
|
{50, 800},
|
|
{46, 820},
|
|
{43, 840},
|
|
{41, 860},
|
|
{38, 880},
|
|
{36, 900},
|
|
{34, 920},
|
|
{32, 940},
|
|
{30, 960},
|
|
{28, 980}
|
|
};
|
|
|
|
/*
|
|
* Voltage to temperature table for 400k pull up for bat_therm with
|
|
* MLP356477.
|
|
*/
|
|
static const struct vadc_map_pt adcmap_batt_therm_400k_6125[] = {
|
|
{1516, -400},
|
|
{1478, -380},
|
|
{1438, -360},
|
|
{1396, -340},
|
|
{1353, -320},
|
|
{1307, -300},
|
|
{1261, -280},
|
|
{1213, -260},
|
|
{1164, -240},
|
|
{1115, -220},
|
|
{1066, -200},
|
|
{1017, -180},
|
|
{968, -160},
|
|
{920, -140},
|
|
{872, -120},
|
|
{826, -100},
|
|
{781, -80},
|
|
{737, -60},
|
|
{694, -40},
|
|
{654, -20},
|
|
{615, 0},
|
|
{578, 20},
|
|
{542, 40},
|
|
{509, 60},
|
|
{477, 80},
|
|
{447, 100},
|
|
{419, 120},
|
|
{392, 140},
|
|
{367, 160},
|
|
{343, 180},
|
|
{321, 200},
|
|
{301, 220},
|
|
{282, 240},
|
|
{264, 260},
|
|
{247, 280},
|
|
{231, 300},
|
|
{216, 320},
|
|
{203, 340},
|
|
{190, 360},
|
|
{178, 380},
|
|
{167, 400},
|
|
{157, 420},
|
|
{147, 440},
|
|
{138, 460},
|
|
{130, 480},
|
|
{122, 500},
|
|
{115, 520},
|
|
{108, 540},
|
|
{102, 560},
|
|
{96, 580},
|
|
{90, 600},
|
|
{85, 620},
|
|
{80, 640},
|
|
{76, 660},
|
|
{72, 680},
|
|
{68, 700},
|
|
{64, 720},
|
|
{61, 740},
|
|
{57, 760},
|
|
{54, 780},
|
|
{52, 800},
|
|
{49, 820},
|
|
{46, 840},
|
|
{44, 860},
|
|
{42, 880},
|
|
{40, 900},
|
|
{38, 920},
|
|
{36, 940},
|
|
{34, 960},
|
|
{32, 980},
|
|
};
|
|
|
|
struct lut_table {
|
|
const struct vadc_map_pt *table;
|
|
u32 tablesize;
|
|
};
|
|
|
|
static const struct lut_table lut_table_30[] = {
|
|
{adcmap_batt_therm_30k, ARRAY_SIZE(adcmap_batt_therm_30k)},
|
|
{adcmap_batt_therm_30k_6125, ARRAY_SIZE(adcmap_batt_therm_30k_6125)},
|
|
};
|
|
|
|
static const struct lut_table lut_table_100[] = {
|
|
{adcmap_batt_therm_100k, ARRAY_SIZE(adcmap_batt_therm_100k)},
|
|
{adcmap_batt_therm_100k_6125, ARRAY_SIZE(adcmap_batt_therm_100k_6125)},
|
|
};
|
|
|
|
static const struct lut_table lut_table_400[] = {
|
|
{adcmap_batt_therm_400k, ARRAY_SIZE(adcmap_batt_therm_400k)},
|
|
{adcmap_batt_therm_400k_6125, ARRAY_SIZE(adcmap_batt_therm_400k_6125)},
|
|
};
|
|
|
|
static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
|
|
u32 tablesize, s32 input, s64 *output)
|
|
{
|
|
bool descending = 1;
|
|
u32 i = 0;
|
|
|
|
if (!pts)
|
|
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) && (pts[i].x < input)) {
|
|
/* table entry is less than measured*/
|
|
/* value and table is descending, stop */
|
|
break;
|
|
} else if ((!descending) &&
|
|
(pts[i].x > input)) {
|
|
/* table entry is greater than measured*/
|
|
/*value and table is ascending, stop */
|
|
break;
|
|
}
|
|
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 = (((s32)((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 void qcom_vadc_scale_calib(const struct vadc_linear_graph *calib_graph,
|
|
u16 adc_code,
|
|
bool absolute,
|
|
s64 *scale_voltage)
|
|
{
|
|
*scale_voltage = (adc_code - calib_graph->gnd);
|
|
*scale_voltage *= calib_graph->dx;
|
|
*scale_voltage = div64_s64(*scale_voltage, calib_graph->dy);
|
|
if (absolute)
|
|
*scale_voltage += calib_graph->dx;
|
|
|
|
if (*scale_voltage < 0)
|
|
*scale_voltage = 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_volt(const struct vadc_linear_graph *calib_graph,
|
|
const struct vadc_prescale_ratio *prescale,
|
|
bool absolute, u16 adc_code,
|
|
int *result_uv)
|
|
{
|
|
s64 voltage = 0, result = 0;
|
|
|
|
qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
|
|
|
|
voltage = voltage * prescale->den;
|
|
result = div64_s64(voltage, prescale->num);
|
|
*result_uv = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph,
|
|
const struct vadc_prescale_ratio *prescale,
|
|
bool absolute, u16 adc_code,
|
|
int *result_mdec)
|
|
{
|
|
s64 voltage = 0, result = 0;
|
|
int ret;
|
|
|
|
qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
|
|
|
|
if (absolute)
|
|
voltage = div64_s64(voltage, 1000);
|
|
|
|
ret = qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb,
|
|
ARRAY_SIZE(adcmap_100k_104ef_104fb),
|
|
voltage, &result);
|
|
if (ret)
|
|
return ret;
|
|
|
|
result *= 1000;
|
|
*result_mdec = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph,
|
|
const struct vadc_prescale_ratio *prescale,
|
|
bool absolute,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0;
|
|
u64 temp; /* Temporary variable for do_div */
|
|
|
|
qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
|
|
|
|
if (voltage > 0) {
|
|
temp = voltage * prescale->den;
|
|
do_div(temp, prescale->num * 2);
|
|
voltage = temp;
|
|
} else {
|
|
voltage = 0;
|
|
}
|
|
|
|
voltage -= KELVINMIL_CELSIUSMIL;
|
|
*result_mdec = voltage;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph,
|
|
const struct vadc_prescale_ratio *prescale,
|
|
bool absolute,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, result = 0;
|
|
|
|
qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
|
|
|
|
voltage = voltage * prescale->den;
|
|
voltage = div64_s64(voltage, prescale->num);
|
|
voltage = ((PMI_CHG_SCALE_1) * (voltage * 2));
|
|
voltage = (voltage + PMI_CHG_SCALE_2);
|
|
result = div64_s64(voltage, 1000000);
|
|
*result_mdec = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_calib_volt(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
u16 adc_code, int *result_uv)
|
|
{
|
|
s64 voltage = 0, result = 0, adc_vdd_ref_mv = 1875;
|
|
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
|
|
voltage = div64_s64(voltage, data->full_scale_code_volt);
|
|
voltage = voltage * prescale->den;
|
|
result = div64_s64(voltage, prescale->num);
|
|
*result_uv = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_calib_therm(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, result = 0;
|
|
int ret;
|
|
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * ADC_HC_VDD_REF * 1000;
|
|
voltage = div64_s64(voltage, (data->full_scale_code_volt
|
|
* 1000));
|
|
ret = qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref,
|
|
ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref),
|
|
voltage, &result);
|
|
if (ret)
|
|
return ret;
|
|
|
|
*result_mdec = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_calib_batt_therm_100(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
unsigned int lut_index,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, result = 0, adc_vdd_ref_mv = 1875;
|
|
int ret;
|
|
u32 size;
|
|
const struct vadc_map_pt *lut;
|
|
|
|
if (lut_index >= ARRAY_SIZE(lut_table_100)) {
|
|
pr_err("LUT index out of range\n");
|
|
return -EINVAL;
|
|
}
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
|
|
voltage = div64_s64(voltage, (data->full_scale_code_volt
|
|
* 1000));
|
|
|
|
lut = lut_table_100[lut_index].table;
|
|
size = lut_table_100[lut_index].tablesize;
|
|
|
|
ret = qcom_vadc_map_voltage_temp(lut, size, voltage, &result);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
*result_mdec = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_calib_batt_therm_30(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
unsigned int lut_index,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, result = 0, adc_vdd_ref_mv = 1875;
|
|
int ret;
|
|
u32 size;
|
|
const struct vadc_map_pt *lut;
|
|
|
|
if (lut_index >= ARRAY_SIZE(lut_table_30)) {
|
|
pr_err("LUT index out of range\n");
|
|
return -EINVAL;
|
|
}
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
|
|
voltage = div64_s64(voltage, (data->full_scale_code_volt
|
|
* 1000));
|
|
|
|
lut = lut_table_30[lut_index].table;
|
|
size = lut_table_30[lut_index].tablesize;
|
|
|
|
ret = qcom_vadc_map_voltage_temp(lut, size, voltage, &result);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
*result_mdec = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_calib_batt_therm_400(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
unsigned int lut_index,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, result = 0, adc_vdd_ref_mv = 1875;
|
|
int ret;
|
|
u32 size;
|
|
const struct vadc_map_pt *lut;
|
|
|
|
if (lut_index >= ARRAY_SIZE(lut_table_400)) {
|
|
pr_err("LUT index out of range\n");
|
|
return -EINVAL;
|
|
}
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
|
|
voltage = div64_s64(voltage, (data->full_scale_code_volt
|
|
* 1000));
|
|
|
|
lut = lut_table_400[lut_index].table;
|
|
size = lut_table_400[lut_index].tablesize;
|
|
|
|
ret = qcom_vadc_map_voltage_temp(lut, size, voltage, &result);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
*result_mdec = result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_calib_die_temp(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, adc_vdd_ref_mv = 1875;
|
|
u64 temp; /* Temporary variable for do_div */
|
|
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
|
|
voltage = div64_s64(voltage, data->full_scale_code_volt);
|
|
if (voltage > 0) {
|
|
temp = voltage * prescale->den;
|
|
do_div(temp, prescale->num * 2);
|
|
voltage = temp;
|
|
} else {
|
|
voltage = 0;
|
|
}
|
|
|
|
voltage -= KELVINMIL_CELSIUSMIL;
|
|
*result_mdec = voltage;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_smb_temp(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, adc_vdd_ref_mv = 1875;
|
|
u64 temp;
|
|
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
|
|
voltage = div64_s64(voltage, data->full_scale_code_volt);
|
|
if (voltage > 0) {
|
|
temp = voltage * prescale->den;
|
|
temp *= 100;
|
|
do_div(temp, prescale->num * PMIC5_SMB_TEMP_SCALE_FACTOR);
|
|
voltage = temp;
|
|
} else {
|
|
voltage = 0;
|
|
}
|
|
|
|
voltage = PMIC5_SMB_TEMP_CONSTANT - voltage;
|
|
*result_mdec = voltage;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_vadc_scale_hw_chg5_temp(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
u16 adc_code, int *result_mdec)
|
|
{
|
|
s64 voltage = 0, adc_vdd_ref_mv = 1875;
|
|
u64 temp;
|
|
|
|
if (adc_code > VADC5_MAX_CODE)
|
|
adc_code = 0;
|
|
|
|
/* (ADC code * vref_vadc (1.875V)) / full_scale_code */
|
|
voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
|
|
voltage = div64_s64(voltage, data->full_scale_code_volt);
|
|
if (voltage > 0) {
|
|
temp = voltage * prescale->den;
|
|
do_div(temp, prescale->num * 4);
|
|
voltage = temp;
|
|
} else {
|
|
voltage = 0;
|
|
}
|
|
|
|
voltage = PMIC5_CHG_TEMP_SCALE_FACTOR - voltage;
|
|
*result_mdec = voltage;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int qcom_adc_scale_hw_calib_cur(
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data,
|
|
u16 adc_code, int *result_uamps)
|
|
{
|
|
s64 voltage = 0, result = 0;
|
|
|
|
if ((adc_code & ADC_USR_DATA_CHECK) == 0) {
|
|
voltage = (s64) adc_code * data->full_scale_code_cur * 1000;
|
|
voltage = div64_s64(voltage, VADC5_MAX_CODE);
|
|
voltage = voltage * prescale->den;
|
|
result = div64_s64(voltage, prescale->num);
|
|
*result_uamps = result;
|
|
} else {
|
|
adc_code = ~adc_code + 1;
|
|
voltage = (s64) adc_code;
|
|
voltage = (s64) adc_code * data->full_scale_code_cur * 1000;
|
|
voltage = div64_s64(voltage, VADC5_MAX_CODE);
|
|
voltage = voltage * prescale->den;
|
|
result = div64_s64(voltage, prescale->num);
|
|
*result_uamps = -result;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
|
|
const struct vadc_linear_graph *calib_graph,
|
|
const struct vadc_prescale_ratio *prescale,
|
|
bool absolute,
|
|
u16 adc_code, int *result)
|
|
{
|
|
switch (scaletype) {
|
|
case SCALE_DEFAULT:
|
|
return qcom_vadc_scale_volt(calib_graph, prescale,
|
|
absolute, adc_code,
|
|
result);
|
|
case SCALE_THERM_100K_PULLUP:
|
|
case SCALE_XOTHERM:
|
|
return qcom_vadc_scale_therm(calib_graph, prescale,
|
|
absolute, adc_code,
|
|
result);
|
|
case SCALE_PMIC_THERM:
|
|
return qcom_vadc_scale_die_temp(calib_graph, prescale,
|
|
absolute, adc_code,
|
|
result);
|
|
case SCALE_PMI_CHG_TEMP:
|
|
return qcom_vadc_scale_chg_temp(calib_graph, prescale,
|
|
absolute, adc_code,
|
|
result);
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(qcom_vadc_scale);
|
|
|
|
int qcom_vadc_hw_scale(enum vadc_scale_fn_type scaletype,
|
|
const struct vadc_prescale_ratio *prescale,
|
|
const struct adc_data *data, unsigned int lut_index,
|
|
u16 adc_code, int *result)
|
|
{
|
|
switch (scaletype) {
|
|
case SCALE_HW_CALIB_DEFAULT:
|
|
return qcom_vadc_scale_hw_calib_volt(prescale, data,
|
|
adc_code, result);
|
|
case SCALE_HW_CALIB_THERM_100K_PULLUP:
|
|
case SCALE_HW_CALIB_XOTHERM:
|
|
return qcom_vadc_scale_hw_calib_therm(prescale, data,
|
|
adc_code, result);
|
|
case SCALE_HW_CALIB_BATT_THERM_100K:
|
|
return qcom_vadc_scale_hw_calib_batt_therm_100(prescale,
|
|
data, lut_index, adc_code, result);
|
|
case SCALE_HW_CALIB_BATT_THERM_30K:
|
|
return qcom_vadc_scale_hw_calib_batt_therm_30(prescale,
|
|
data, lut_index, adc_code, result);
|
|
case SCALE_HW_CALIB_BATT_THERM_400K:
|
|
return qcom_vadc_scale_hw_calib_batt_therm_400(prescale,
|
|
data, lut_index, adc_code, result);
|
|
case SCALE_HW_CALIB_PMIC_THERM:
|
|
return qcom_vadc_scale_hw_calib_die_temp(prescale, data,
|
|
adc_code, result);
|
|
case SCALE_HW_CALIB_CUR:
|
|
return qcom_adc_scale_hw_calib_cur(prescale, data,
|
|
adc_code, result);
|
|
case SCALE_HW_CALIB_PM5_CHG_TEMP:
|
|
return qcom_vadc_scale_hw_chg5_temp(prescale, data,
|
|
adc_code, result);
|
|
case SCALE_HW_CALIB_PM5_SMB_TEMP:
|
|
return qcom_vadc_scale_hw_smb_temp(prescale, data,
|
|
adc_code, result);
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(qcom_vadc_hw_scale);
|
|
|
|
int qcom_vadc_decimation_from_dt(u32 value)
|
|
{
|
|
if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
|
|
value > VADC_DECIMATION_MAX)
|
|
return -EINVAL;
|
|
|
|
return __ffs64(value / VADC_DECIMATION_MIN);
|
|
}
|
|
EXPORT_SYMBOL(qcom_vadc_decimation_from_dt);
|
|
|
|
int qcom_adc5_decimation_from_dt(u32 value, const unsigned int *decimation)
|
|
{
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < ADC_DECIMATION_SAMPLES_MAX; i++) {
|
|
if (value == decimation[i])
|
|
return i;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
EXPORT_SYMBOL(qcom_adc5_decimation_from_dt);
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_DESCRIPTION("Qualcomm ADC common functionality");
|