mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
hwmon: Add MSM adc driver
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
This commit is contained in:
parent
1eaf2cb162
commit
1d3a4b012c
8 changed files with 2540 additions and 0 deletions
|
@ -838,6 +838,19 @@ config SENSORS_NTC_THERMISTOR
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called ntc-thermistor.
|
||||
|
||||
config SENSORS_MSM_ADC
|
||||
tristate "MSM ADC Driver for current measurement"
|
||||
depends on ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_FSM9XXX || ARCH_MSM7X27A
|
||||
default n
|
||||
help
|
||||
Provides interface for measuring the ADC's on AMUX channels of XOADC,
|
||||
MPP's and the XOTHERM on pmic8058 for msm8x60 and provides post processing
|
||||
of the channel for the ADC Raw Data. For reading LTC and EPM ADC channels
|
||||
say yes here to include support for measuring current in real-time
|
||||
from various power-rails on the Fluid board. The ADC circuit
|
||||
internally uses an array of LTC2499 and EPM ADCs in a differential
|
||||
configuration to provide a flat set of channels that can be addressed.
|
||||
|
||||
config SENSORS_PC87360
|
||||
tristate "National Semiconductor PC87360 family"
|
||||
depends on !PPC
|
||||
|
|
|
@ -127,6 +127,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
|
|||
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_WPCE775X) += wpce775x.o
|
||||
obj-$(CONFIG_SENSORS_MSM_ADC) += msm_adc.o m_adcproc.o
|
||||
|
||||
obj-$(CONFIG_PMBUS) += pmbus/
|
||||
|
||||
|
|
469
drivers/hwmon/m_adcproc.c
Normal file
469
drivers/hwmon/m_adcproc.c
Normal file
|
@ -0,0 +1,469 @@
|
|||
/* Copyright (c) 2010-2011, Code Aurora Forum. 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/msm_adc.h>
|
||||
|
||||
#define KELVINMIL_DEGMIL 273160
|
||||
|
||||
static const struct adc_map_pt adcmap_batttherm[] = {
|
||||
{2020, -30},
|
||||
{1923, -20},
|
||||
{1796, -10},
|
||||
{1640, 0},
|
||||
{1459, 10},
|
||||
{1260, 20},
|
||||
{1159, 25},
|
||||
{1059, 30},
|
||||
{871, 40},
|
||||
{706, 50},
|
||||
{567, 60},
|
||||
{453, 70},
|
||||
{364, 80}
|
||||
};
|
||||
|
||||
static const struct adc_map_pt adcmap_msmtherm[] = {
|
||||
{2150, -30},
|
||||
{2107, -20},
|
||||
{2037, -10},
|
||||
{1929, 0},
|
||||
{1776, 10},
|
||||
{1579, 20},
|
||||
{1467, 25},
|
||||
{1349, 30},
|
||||
{1108, 40},
|
||||
{878, 50},
|
||||
{677, 60},
|
||||
{513, 70},
|
||||
{385, 80},
|
||||
{287, 90},
|
||||
{215, 100},
|
||||
{186, 110},
|
||||
{107, 120}
|
||||
};
|
||||
|
||||
static const struct adc_map_pt adcmap_ntcg104ef104fb[] = {
|
||||
{696483, -40960},
|
||||
{649148, -39936},
|
||||
{605368, -38912},
|
||||
{564809, -37888},
|
||||
{527215, -36864},
|
||||
{492322, -35840},
|
||||
{460007, -34816},
|
||||
{429982, -33792},
|
||||
{402099, -32768},
|
||||
{376192, -31744},
|
||||
{352075, -30720},
|
||||
{329714, -29696},
|
||||
{308876, -28672},
|
||||
{289480, -27648},
|
||||
{271417, -26624},
|
||||
{254574, -25600},
|
||||
{238903, -24576},
|
||||
{224276, -23552},
|
||||
{210631, -22528},
|
||||
{197896, -21504},
|
||||
{186007, -20480},
|
||||
{174899, -19456},
|
||||
{164521, -18432},
|
||||
{154818, -17408},
|
||||
{145744, -16384},
|
||||
{137265, -15360},
|
||||
{129307, -14336},
|
||||
{121866, -13312},
|
||||
{114896, -12288},
|
||||
{108365, -11264},
|
||||
{102252, -10240},
|
||||
{96499, -9216},
|
||||
{91111, -8192},
|
||||
{86055, -7168},
|
||||
{81308, -6144},
|
||||
{76857, -5120},
|
||||
{72660, -4096},
|
||||
{68722, -3072},
|
||||
{65020, -2048},
|
||||
{61538, -1024},
|
||||
{58261, 0},
|
||||
{55177, 1024},
|
||||
{52274, 2048},
|
||||
{49538, 3072},
|
||||
{46962, 4096},
|
||||
{44531, 5120},
|
||||
{42243, 6144},
|
||||
{40083, 7168},
|
||||
{38045, 8192},
|
||||
{36122, 9216},
|
||||
{34308, 10240},
|
||||
{32592, 11264},
|
||||
{30972, 12288},
|
||||
{29442, 13312},
|
||||
{27995, 14336},
|
||||
{26624, 15360},
|
||||
{25333, 16384},
|
||||
{24109, 17408},
|
||||
{22951, 18432},
|
||||
{21854, 19456},
|
||||
{20807, 20480},
|
||||
{19831, 21504},
|
||||
{18899, 22528},
|
||||
{18016, 23552},
|
||||
{17178, 24576},
|
||||
{16384, 25600},
|
||||
{15631, 26624},
|
||||
{14916, 27648},
|
||||
{14237, 28672},
|
||||
{13593, 29696},
|
||||
{12976, 30720},
|
||||
{12400, 31744},
|
||||
{11848, 32768},
|
||||
{11324, 33792},
|
||||
{10825, 34816},
|
||||
{10354, 35840},
|
||||
{9900, 36864},
|
||||
{9471, 37888},
|
||||
{9062, 38912},
|
||||
{8674, 39936},
|
||||
{8306, 40960},
|
||||
{7951, 41984},
|
||||
{7616, 43008},
|
||||
{7296, 44032},
|
||||
{6991, 45056},
|
||||
{6701, 46080},
|
||||
{6424, 47104},
|
||||
{6160, 48128},
|
||||
{5908, 49152},
|
||||
{5667, 50176},
|
||||
{5439, 51200},
|
||||
{5219, 52224},
|
||||
{5010, 53248},
|
||||
{4810, 54272},
|
||||
{4619, 55296},
|
||||
{4440, 56320},
|
||||
{4263, 57344},
|
||||
{4097, 58368},
|
||||
{3938, 59392},
|
||||
{3785, 60416},
|
||||
{3637, 61440},
|
||||
{3501, 62464},
|
||||
{3368, 63488},
|
||||
{3240, 64512},
|
||||
{3118, 65536},
|
||||
{2998, 66560},
|
||||
{2889, 67584},
|
||||
{2782, 68608},
|
||||
{2680, 69632},
|
||||
{2581, 70656},
|
||||
{2490, 71680},
|
||||
{2397, 72704},
|
||||
{2310, 73728},
|
||||
{2227, 74752},
|
||||
{2147, 75776},
|
||||
{2064, 76800},
|
||||
{1998, 77824},
|
||||
{1927, 78848},
|
||||
{1860, 79872},
|
||||
{1795, 80896},
|
||||
{1736, 81920},
|
||||
{1673, 82944},
|
||||
{1615, 83968},
|
||||
{1560, 84992},
|
||||
{1507, 86016},
|
||||
{1456, 87040},
|
||||
{1407, 88064},
|
||||
{1360, 89088},
|
||||
{1314, 90112},
|
||||
{1271, 91136},
|
||||
{1228, 92160},
|
||||
{1189, 93184},
|
||||
{1150, 94208},
|
||||
{1112, 95232},
|
||||
{1076, 96256},
|
||||
{1042, 97280},
|
||||
{1008, 98304},
|
||||
{976, 99328},
|
||||
{945, 100352},
|
||||
{915, 101376},
|
||||
{886, 102400},
|
||||
{859, 103424},
|
||||
{832, 104448},
|
||||
{807, 105472},
|
||||
{782, 106496},
|
||||
{756, 107520},
|
||||
{735, 108544},
|
||||
{712, 109568},
|
||||
{691, 110592},
|
||||
{670, 111616},
|
||||
{650, 112640},
|
||||
{631, 113664},
|
||||
{612, 114688},
|
||||
{594, 115712},
|
||||
{577, 116736},
|
||||
{560, 117760},
|
||||
{544, 118784},
|
||||
{528, 119808},
|
||||
{513, 120832},
|
||||
{498, 121856},
|
||||
{483, 122880},
|
||||
{470, 123904},
|
||||
{457, 124928},
|
||||
{444, 125952},
|
||||
{431, 126976},
|
||||
{419, 128000}
|
||||
};
|
||||
|
||||
static int32_t
|
||||
adc_map_linear(const struct 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;
|
||||
}
|
||||
|
||||
int32_t scale_default(int32_t adc_code,
|
||||
const struct adc_properties *adc_properties,
|
||||
const struct chan_properties *chan_properties,
|
||||
struct adc_chan_result *adc_chan_result)
|
||||
{
|
||||
bool negative_rawfromoffset = 0;
|
||||
int32_t rawfromoffset = adc_code - chan_properties->adc_graph->offset;
|
||||
|
||||
if (!chan_properties->gain_numerator ||
|
||||
!chan_properties->gain_denominator)
|
||||
return -EINVAL;
|
||||
|
||||
adc_chan_result->adc_code = adc_code;
|
||||
if (rawfromoffset < 0) {
|
||||
if (adc_properties->bipolar) {
|
||||
rawfromoffset = (rawfromoffset ^ -1) + 1;
|
||||
negative_rawfromoffset = 1;
|
||||
} else
|
||||
rawfromoffset = 0;
|
||||
}
|
||||
|
||||
if (rawfromoffset >= 1 << adc_properties->bitresolution)
|
||||
rawfromoffset = (1 << adc_properties->bitresolution) - 1;
|
||||
|
||||
adc_chan_result->measurement = (int64_t)rawfromoffset*
|
||||
chan_properties->adc_graph->dx*
|
||||
chan_properties->gain_denominator;
|
||||
|
||||
/* do_div only perform positive integer division! */
|
||||
do_div(adc_chan_result->measurement, chan_properties->adc_graph->dy*
|
||||
chan_properties->gain_numerator);
|
||||
|
||||
if (negative_rawfromoffset)
|
||||
adc_chan_result->measurement =
|
||||
(adc_chan_result->measurement ^ -1) + 1;
|
||||
|
||||
/* 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 = (int32_t) adc_chan_result->measurement;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t scale_batt_therm(int32_t adc_code,
|
||||
const struct adc_properties *adc_properties,
|
||||
const struct chan_properties *chan_properties,
|
||||
struct adc_chan_result *adc_chan_result)
|
||||
{
|
||||
scale_default(adc_code, adc_properties, chan_properties,
|
||||
adc_chan_result);
|
||||
/* convert mV ---> degC using the table */
|
||||
return adc_map_linear(
|
||||
adcmap_batttherm,
|
||||
sizeof(adcmap_batttherm)/sizeof(adcmap_batttherm[0]),
|
||||
adc_chan_result->physical,
|
||||
&adc_chan_result->physical);
|
||||
}
|
||||
|
||||
int32_t scale_msm_therm(int32_t adc_code,
|
||||
const struct adc_properties *adc_properties,
|
||||
const struct chan_properties *chan_properties,
|
||||
struct adc_chan_result *adc_chan_result)
|
||||
{
|
||||
scale_default(adc_code, adc_properties, chan_properties,
|
||||
adc_chan_result);
|
||||
/* convert mV ---> degC using the table */
|
||||
return adc_map_linear(
|
||||
adcmap_msmtherm,
|
||||
sizeof(adcmap_msmtherm)/sizeof(adcmap_msmtherm[0]),
|
||||
adc_chan_result->physical,
|
||||
&adc_chan_result->physical);
|
||||
}
|
||||
|
||||
int32_t scale_pmic_therm(int32_t adc_code,
|
||||
const struct adc_properties *adc_properties,
|
||||
const struct chan_properties *chan_properties,
|
||||
struct adc_chan_result *adc_chan_result)
|
||||
{
|
||||
/* 2mV/K */
|
||||
int32_t rawfromoffset = adc_code - chan_properties->adc_graph->offset;
|
||||
|
||||
if (!chan_properties->gain_numerator ||
|
||||
!chan_properties->gain_denominator)
|
||||
return -EINVAL;
|
||||
|
||||
adc_chan_result->adc_code = adc_code;
|
||||
if (rawfromoffset > 0) {
|
||||
if (rawfromoffset >= 1 << adc_properties->bitresolution)
|
||||
rawfromoffset = (1 << adc_properties->bitresolution)
|
||||
- 1;
|
||||
adc_chan_result->measurement = (int64_t)rawfromoffset*
|
||||
chan_properties->adc_graph->dx*
|
||||
chan_properties->gain_denominator*1000;
|
||||
do_div(adc_chan_result->measurement,
|
||||
chan_properties->adc_graph->dy*
|
||||
chan_properties->gain_numerator*2);
|
||||
} else {
|
||||
adc_chan_result->measurement = 0;
|
||||
}
|
||||
/* Note: adc_chan_result->measurement is in the unit of
|
||||
adc_properties.adc_reference */
|
||||
adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
|
||||
/* Change to .001 deg C */
|
||||
adc_chan_result->physical -= KELVINMIL_DEGMIL;
|
||||
adc_chan_result->measurement <<= 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Scales the ADC code to 0.001 degrees C using the map
|
||||
* table for the XO thermistor.
|
||||
*/
|
||||
int32_t tdkntcgtherm(int32_t adc_code,
|
||||
const struct adc_properties *adc_properties,
|
||||
const struct chan_properties *chan_properties,
|
||||
struct adc_chan_result *adc_chan_result)
|
||||
{
|
||||
int32_t offset = chan_properties->adc_graph->offset,
|
||||
dy = chan_properties->adc_graph->dy,
|
||||
dx = chan_properties->adc_graph->dx,
|
||||
fullscale_calibrated_adc_code;
|
||||
|
||||
uint32_t rt_r25;
|
||||
uint32_t num1, num2, denom;
|
||||
|
||||
adc_chan_result->adc_code = adc_code;
|
||||
fullscale_calibrated_adc_code = dy + offset;
|
||||
/* The above is a short cut in math that would reduce a lot of
|
||||
computation whereas the below expression
|
||||
(adc_properties->adc_reference*dy+dx*offset+(dx>>1))/dx
|
||||
is a more generic formula when the 2 reference voltages are
|
||||
different than 0 and full scale voltage. */
|
||||
|
||||
if ((dy == 0) || (dx == 0) ||
|
||||
(offset >= fullscale_calibrated_adc_code)) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (adc_code >= fullscale_calibrated_adc_code) {
|
||||
rt_r25 = (uint32_t)-1;
|
||||
} else if (adc_code <= offset) {
|
||||
rt_r25 = 0;
|
||||
} else {
|
||||
/* The formula used is (adc_code of current reading - offset)/
|
||||
* (the calibrated fullscale adc code - adc_code of current reading).
|
||||
* For this channel, at this time, chan_properties->gain_numerator =
|
||||
* chan_properties->gain_denominator = 1, so no need to incorporate
|
||||
* into the formula even though we could and multiply/divide by 1
|
||||
* which yields the same result but expensive on computation. */
|
||||
num1 = (adc_code - offset) << 14;
|
||||
num2 = (fullscale_calibrated_adc_code - adc_code) >> 1;
|
||||
denom = fullscale_calibrated_adc_code - adc_code;
|
||||
|
||||
if ((int)denom <= 0)
|
||||
rt_r25 = 0x7FFFFFFF;
|
||||
else
|
||||
rt_r25 = (num1 + num2) / denom;
|
||||
}
|
||||
|
||||
if (rt_r25 > 0x7FFFFFFF)
|
||||
rt_r25 = 0x7FFFFFFF;
|
||||
|
||||
adc_map_linear(adcmap_ntcg104ef104fb,
|
||||
sizeof(adcmap_ntcg104ef104fb)/sizeof(adcmap_ntcg104ef104fb[0]),
|
||||
(int32_t)rt_r25, &adc_chan_result->physical);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t scale_xtern_chgr_cur(int32_t adc_code,
|
||||
const struct adc_properties *adc_properties,
|
||||
const struct chan_properties *chan_properties,
|
||||
struct adc_chan_result *adc_chan_result)
|
||||
{
|
||||
int32_t rawfromoffset = adc_code - chan_properties->adc_graph->offset;
|
||||
|
||||
if (!chan_properties->gain_numerator ||
|
||||
!chan_properties->gain_denominator)
|
||||
return -EINVAL;
|
||||
|
||||
adc_chan_result->adc_code = adc_code;
|
||||
if (rawfromoffset > 0) {
|
||||
if (rawfromoffset >= 1 << adc_properties->bitresolution)
|
||||
rawfromoffset = (1 << adc_properties->bitresolution)
|
||||
- 1;
|
||||
adc_chan_result->measurement = ((int64_t)rawfromoffset * 5)*
|
||||
chan_properties->adc_graph->dx*
|
||||
chan_properties->gain_denominator;
|
||||
do_div(adc_chan_result->measurement,
|
||||
chan_properties->adc_graph->dy*
|
||||
chan_properties->gain_numerator);
|
||||
} else {
|
||||
adc_chan_result->measurement = 0;
|
||||
}
|
||||
adc_chan_result->physical = (int32_t) adc_chan_result->measurement;
|
||||
|
||||
return 0;
|
||||
}
|
1533
drivers/hwmon/msm_adc.c
Normal file
1533
drivers/hwmon/msm_adc.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -256,6 +256,7 @@ header-y += mroute.h
|
|||
header-y += mroute6.h
|
||||
header-y += msdos_fs.h
|
||||
header-y += msg.h
|
||||
header-y += msm_adc.h
|
||||
header-y += mtio.h
|
||||
header-y += n_r3964.h
|
||||
header-y += nbd.h
|
||||
|
|
30
include/linux/m_adcproc.h
Normal file
30
include/linux/m_adcproc.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* Copyright (c) 2010-2011, Code Aurora Forum. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _M_ADC_PROC_H
|
||||
#define _M_ADC_PROC_H
|
||||
|
||||
#include <linux/msm_adc.h>
|
||||
int32_t tdkntcgtherm(int32_t adc_code, const struct adc_properties *,
|
||||
const struct chan_properties *, struct adc_chan_result *);
|
||||
int32_t scale_default(int32_t adc_code, const struct adc_properties *,
|
||||
const struct chan_properties *, struct adc_chan_result *);
|
||||
int32_t scale_msm_therm(int32_t adc_code, const struct adc_properties *,
|
||||
const struct chan_properties *, struct adc_chan_result *);
|
||||
int32_t scale_batt_therm(int32_t adc_code, const struct adc_properties *,
|
||||
const struct chan_properties *, struct adc_chan_result *);
|
||||
int32_t scale_pmic_therm(int32_t adc_code, const struct adc_properties *,
|
||||
const struct chan_properties *, struct adc_chan_result *);
|
||||
int32_t scale_xtern_chgr_cur(int32_t adc_code, const struct adc_properties *,
|
||||
const struct chan_properties *, struct adc_chan_result *);
|
||||
#endif /* _M_ADC_PROC_H */
|
372
include/linux/msm_adc.h
Normal file
372
include/linux/msm_adc.h
Normal file
|
@ -0,0 +1,372 @@
|
|||
#ifndef __MSM_ADC_H
|
||||
#define __MSM_ADC_H
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
#define MSM_ADC_MAX_CHAN_STR 64
|
||||
|
||||
/* must be <= to the max buffer size in the modem implementation */
|
||||
#define MSM_ADC_DEV_MAX_INFLIGHT 9
|
||||
|
||||
#define MSM_ADC_IOCTL_CODE 0x90
|
||||
|
||||
struct msm_adc_conversion {
|
||||
/* hwmon channel number - this is not equivalent to the DAL chan */
|
||||
uint32_t chan;
|
||||
/* returned result in ms */
|
||||
int result;
|
||||
};
|
||||
|
||||
struct adc_chan_result {
|
||||
/* The channel number of the requesting/requested conversion */
|
||||
uint32_t chan;
|
||||
/* The pre-calibrated digital output of a given ADC relative to the
|
||||
ADC reference */
|
||||
int32_t adc_code;
|
||||
/* in units specific for a given ADC; most ADC uses reference voltage
|
||||
* but some ADC uses reference current. This measurement here is
|
||||
* a number relative to a reference of a given ADC */
|
||||
int64_t measurement;
|
||||
/* The data meaningful for each individual channel whether it is
|
||||
* voltage, current, temperature, etc. */
|
||||
int64_t physical;
|
||||
};
|
||||
|
||||
/*
|
||||
* Issue a blocking adc conversion request. Once the call returns, the data
|
||||
* can be found in the 'physical' field of adc_chan_result. This call will
|
||||
* return ENODATA if there is an invalid result returned by the modem driver.
|
||||
*/
|
||||
#define MSM_ADC_REQUEST _IOWR(MSM_ADC_IOCTL_CODE, 1, \
|
||||
struct adc_chan_result)
|
||||
|
||||
/*
|
||||
* Issue a non-blocking adc conversion request. The results from this
|
||||
* request can be obtained by calling AIO_READ once the transfer is
|
||||
* completed. To verify completion, the blocking call AIO_POLL can be used.
|
||||
* If there are no slot resources, this call will return an error with errno
|
||||
* set to EWOULDBLOCK.
|
||||
*/
|
||||
#define MSM_ADC_AIO_REQUEST _IOWR(MSM_ADC_IOCTL_CODE, 2, \
|
||||
struct adc_chan_result)
|
||||
|
||||
/*
|
||||
* Same non-blocking semantics as AIO_REQUEST, except this call will block
|
||||
* if there are no available slot resources. This call can fail with errno
|
||||
* set to EDEADLK if there are no resources and the file descriptor in question
|
||||
* has outstanding conversion requests already. This is done so the client
|
||||
* does not block on resources that can only be freed by reading the results --
|
||||
* effectively deadlocking the system. In this case, the client must read
|
||||
* pending results before proceeding to free up resources.
|
||||
*/
|
||||
#define MSM_ADC_AIO_REQUEST_BLOCK_RES _IOWR(MSM_ADC_IOCTL_CODE, 3, \
|
||||
struct adc_chan_result)
|
||||
|
||||
/*
|
||||
* Returns the number of pending results that are associated with a particular
|
||||
* file descriptor. If there are no pending results, this call will block until
|
||||
* there is at least one. If there are no requests queued at all on this file
|
||||
* descriptor, this call will fail with EDEADLK. This is to prevent deadlock in
|
||||
* a single-threaded scenario where POLL would never return.
|
||||
*/
|
||||
#define MSM_ADC_AIO_POLL _IOR(MSM_ADC_IOCTL_CODE, 4, \
|
||||
uint32_t)
|
||||
|
||||
#define MSM_ADC_FLUID_INIT _IOR(MSM_ADC_IOCTL_CODE, 5, \
|
||||
uint32_t)
|
||||
|
||||
#define MSM_ADC_FLUID_DEINIT _IOR(MSM_ADC_IOCTL_CODE, 6, \
|
||||
uint32_t)
|
||||
|
||||
struct msm_adc_aio_result {
|
||||
uint32_t chan;
|
||||
int result;
|
||||
};
|
||||
|
||||
/*
|
||||
* Read the results from an AIO / non-blocking conversion request. AIO_POLL
|
||||
* should be used before using this command to verify how many pending requests
|
||||
* are available for the file descriptor. This call will fail with errno set to
|
||||
* ENOMSG if there are no pending messages to be read at the time of the call.
|
||||
* The call will return ENODATA if there is an invalid result returned by the
|
||||
* modem driver.
|
||||
*/
|
||||
#define MSM_ADC_AIO_READ _IOR(MSM_ADC_IOCTL_CODE, 5, \
|
||||
struct adc_chan_result)
|
||||
|
||||
struct msm_adc_lookup {
|
||||
/* channel name (input) */
|
||||
char name[MSM_ADC_MAX_CHAN_STR];
|
||||
/* local channel index (output) */
|
||||
uint32_t chan_idx;
|
||||
};
|
||||
|
||||
/*
|
||||
* Look up a channel name and get back an index that can be used
|
||||
* as a parameter to the conversion request commands.
|
||||
*/
|
||||
#define MSM_ADC_LOOKUP _IOWR(MSM_ADC_IOCTL_CODE, 6, \
|
||||
struct msm_adc_lookup)
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define MSM_ADC_MAX_NUM_DEVS 3
|
||||
|
||||
enum {
|
||||
ADC_CONFIG_TYPE1,
|
||||
ADC_CONFIG_TYPE2,
|
||||
ADC_CONFIG_NONE = 0xffffffff
|
||||
};
|
||||
|
||||
enum {
|
||||
ADC_CALIB_CONFIG_TYPE1,
|
||||
ADC_CALIB_CONFIG_TYPE2,
|
||||
ADC_CALIB_CONFIG_TYPE3,
|
||||
ADC_CALIB_CONFIG_TYPE4,
|
||||
ADC_CALIB_CONFIG_TYPE5,
|
||||
ADC_CALIB_CONFIG_TYPE6,
|
||||
ADC_CALIB_CONFIG_TYPE7,
|
||||
ADC_CALIB_CONFIG_NONE = 0xffffffff
|
||||
};
|
||||
|
||||
enum {
|
||||
/* CHAN_PATH_TYPEn is specific for each ADC driver
|
||||
and can be used however way it wants*/
|
||||
CHAN_PATH_TYPE1,
|
||||
CHAN_PATH_TYPE2,
|
||||
CHAN_PATH_TYPE3,
|
||||
CHAN_PATH_TYPE4,
|
||||
CHAN_PATH_TYPE5,
|
||||
CHAN_PATH_TYPE6,
|
||||
CHAN_PATH_TYPE7,
|
||||
CHAN_PATH_TYPE8,
|
||||
CHAN_PATH_TYPE9,
|
||||
CHAN_PATH_TYPE10,
|
||||
CHAN_PATH_TYPE11,
|
||||
CHAN_PATH_TYPE12,
|
||||
CHAN_PATH_TYPE13,
|
||||
CHAN_PATH_TYPE14,
|
||||
CHAN_PATH_TYPE15,
|
||||
CHAN_PATH_TYPE16,
|
||||
/* A given channel connects directly to the ADC */
|
||||
CHAN_PATH_TYPE_NONE = 0xffffffff
|
||||
};
|
||||
|
||||
#define CHANNEL_ADC_BATT_ID 0
|
||||
#define CHANNEL_ADC_BATT_THERM 1
|
||||
#define CHANNEL_ADC_BATT_AMON 2
|
||||
#define CHANNEL_ADC_VBATT 3
|
||||
#define CHANNEL_ADC_VCOIN 4
|
||||
#define CHANNEL_ADC_VCHG 5
|
||||
#define CHANNEL_ADC_CHG_MONITOR 6
|
||||
#define CHANNEL_ADC_VPH_PWR 7
|
||||
#define CHANNEL_ADC_USB_VBUS 8
|
||||
#define CHANNEL_ADC_DIE_TEMP 9
|
||||
#define CHANNEL_ADC_DIE_TEMP_4K 0xa
|
||||
#define CHANNEL_ADC_XOTHERM 0xb
|
||||
#define CHANNEL_ADC_XOTHERM_4K 0xc
|
||||
#define CHANNEL_ADC_HDSET 0xd
|
||||
#define CHANNEL_ADC_MSM_THERM 0xe
|
||||
#define CHANNEL_ADC_625_REF 0xf
|
||||
#define CHANNEL_ADC_1250_REF 0x10
|
||||
#define CHANNEL_ADC_325_REF 0x11
|
||||
#define CHANNEL_ADC_FSM_THERM 0x12
|
||||
#define CHANNEL_ADC_PA_THERM 0x13
|
||||
|
||||
enum {
|
||||
CALIB_STARTED,
|
||||
CALIB_NOT_REQUIRED = 0xffffffff,
|
||||
};
|
||||
|
||||
struct linear_graph {
|
||||
int32_t offset;
|
||||
int32_t dy; /* Slope numerator */
|
||||
int32_t dx; /* Slope denominator */
|
||||
};
|
||||
|
||||
struct adc_map_pt {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
struct adc_properties {
|
||||
uint32_t adc_reference; /* milli-voltage for this adc */
|
||||
uint32_t bitresolution;
|
||||
bool bipolar;
|
||||
uint32_t conversiontime;
|
||||
};
|
||||
|
||||
struct chan_properties {
|
||||
uint32_t gain_numerator;
|
||||
uint32_t gain_denominator;
|
||||
struct linear_graph *adc_graph;
|
||||
/* this maybe the same as adc_properties.ConversionTime
|
||||
if channel does not change the adc properties */
|
||||
uint32_t chan_conv_time;
|
||||
};
|
||||
|
||||
struct msm_adc_channels {
|
||||
char *name;
|
||||
uint32_t channel_name;
|
||||
uint32_t adc_dev_instance;
|
||||
struct adc_access_fn *adc_access_fn;
|
||||
uint32_t chan_path_type;
|
||||
uint32_t adc_config_type;
|
||||
uint32_t adc_calib_type;
|
||||
int32_t (*chan_processor)(int32_t, const struct adc_properties *,
|
||||
const struct chan_properties *, struct adc_chan_result *);
|
||||
|
||||
};
|
||||
|
||||
struct msm_adc_platform_data {
|
||||
struct msm_adc_channels *channel;
|
||||
uint32_t num_chan_supported;
|
||||
uint32_t num_adc;
|
||||
uint32_t chan_per_adc;
|
||||
char **dev_names;
|
||||
uint32_t target_hw;
|
||||
uint32_t gpio_config;
|
||||
u32 (*adc_gpio_enable) (int);
|
||||
u32 (*adc_gpio_disable) (int);
|
||||
u32 (*adc_fluid_enable) (void);
|
||||
u32 (*adc_fluid_disable) (void);
|
||||
};
|
||||
|
||||
enum hw_type {
|
||||
MSM_7x30,
|
||||
MSM_8x60,
|
||||
FSM_9xxx,
|
||||
MSM_8x25,
|
||||
};
|
||||
|
||||
enum epm_gpio_config {
|
||||
MPROC_CONFIG,
|
||||
APROC_CONFIG
|
||||
};
|
||||
|
||||
enum adc_request {
|
||||
START_OF_CONV,
|
||||
END_OF_CONV,
|
||||
START_OF_CALIBRATION,
|
||||
END_OF_CALIBRATION,
|
||||
};
|
||||
|
||||
struct adc_dev_spec {
|
||||
uint32_t hwmon_dev_idx;
|
||||
struct dal_dev_spec {
|
||||
uint32_t dev_idx;
|
||||
uint32_t chan_idx;
|
||||
} dal;
|
||||
};
|
||||
|
||||
struct dal_conv_request {
|
||||
struct dal_dev_spec target;
|
||||
void *cb_h;
|
||||
};
|
||||
|
||||
struct dal_adc_result {
|
||||
uint32_t status;
|
||||
uint32_t token;
|
||||
uint32_t dev_idx;
|
||||
uint32_t chan_idx;
|
||||
int physical;
|
||||
uint32_t percent;
|
||||
uint32_t microvolts;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
struct dal_conv_slot {
|
||||
void *cb_h;
|
||||
struct dal_adc_result result;
|
||||
struct completion comp;
|
||||
struct list_head list;
|
||||
uint32_t idx;
|
||||
uint32_t chan_idx;
|
||||
bool blocking;
|
||||
struct msm_client_data *client;
|
||||
};
|
||||
|
||||
struct dal_translation {
|
||||
uint32_t dal_dev_idx;
|
||||
uint32_t hwmon_dev_idx;
|
||||
uint32_t hwmon_start;
|
||||
uint32_t hwmon_end;
|
||||
};
|
||||
|
||||
struct msm_client_data {
|
||||
struct list_head complete_list;
|
||||
bool online;
|
||||
int32_t adc_chan;
|
||||
uint32_t num_complete;
|
||||
uint32_t num_outstanding;
|
||||
wait_queue_head_t data_wait;
|
||||
wait_queue_head_t outst_wait;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
struct adc_conv_slot {
|
||||
void *cb_h;
|
||||
union {
|
||||
struct adc_chan_result result;
|
||||
struct dal_adc_result dal_result;
|
||||
} conv;
|
||||
struct completion comp;
|
||||
struct completion *compk;
|
||||
struct list_head list;
|
||||
uint32_t idx;
|
||||
enum adc_request adc_request;
|
||||
bool blocking;
|
||||
struct msm_client_data *client;
|
||||
struct work_struct work;
|
||||
struct chan_properties chan_properties;
|
||||
uint32_t chan_path;
|
||||
uint32_t chan_adc_config;
|
||||
uint32_t chan_adc_calib;
|
||||
};
|
||||
|
||||
struct adc_access_fn {
|
||||
int32_t (*adc_select_chan_and_start_conv)(uint32_t,
|
||||
struct adc_conv_slot*);
|
||||
int32_t (*adc_read_adc_code)(uint32_t dev_instance, int32_t *data);
|
||||
struct adc_properties *(*adc_get_properties)(uint32_t dev_instance);
|
||||
void (*adc_slot_request)(uint32_t dev_instance,
|
||||
struct adc_conv_slot **);
|
||||
void (*adc_restore_slot)(uint32_t dev_instance,
|
||||
struct adc_conv_slot *slot);
|
||||
int32_t (*adc_calibrate)(uint32_t dev_instance, struct adc_conv_slot*,
|
||||
int *);
|
||||
};
|
||||
|
||||
void msm_adc_wq_work(struct work_struct *work);
|
||||
void msm_adc_conv_cb(void *context, u32 param, void *evt_buf, u32 len);
|
||||
#ifdef CONFIG_SENSORS_MSM_ADC
|
||||
int32_t adc_channel_open(uint32_t channel, void **h);
|
||||
int32_t adc_channel_close(void *h);
|
||||
int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt);
|
||||
int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result);
|
||||
#else
|
||||
static inline int32_t adc_channel_open(uint32_t channel, void **h)
|
||||
{
|
||||
pr_err("%s.not supported.\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int32_t adc_channel_close(void *h)
|
||||
{
|
||||
pr_err("%s.not supported.\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int32_t
|
||||
adc_channel_request_conv(void *h, struct completion *conv_complete_evt)
|
||||
{
|
||||
pr_err("%s.not supported.\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int32_t
|
||||
adc_channel_read_result(void *h, struct adc_chan_result *chan_result)
|
||||
{
|
||||
pr_err("%s.not supported.\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_SENSORS_MSM_ADC */
|
||||
#endif
|
||||
#endif /* __MSM_ADC_H */
|
121
include/linux/pmic8058-xoadc.h
Normal file
121
include/linux/pmic8058-xoadc.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* Copyright (c) 2010-2011, Code Aurora Forum. 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.
|
||||
*
|
||||
* Qualcomm XOADC Driver header file
|
||||
*/
|
||||
|
||||
#ifndef _PMIC8058_XOADC_H_
|
||||
#define _PMIC8058_XOADC_H_
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct xoadc_conv_state {
|
||||
struct adc_conv_slot *context;
|
||||
struct list_head slots;
|
||||
struct mutex list_lock;
|
||||
};
|
||||
|
||||
#define CHANNEL_VCOIN 0
|
||||
#define CHANNEL_VBAT 1
|
||||
#define CHANNEL_VCHG 2
|
||||
#define CHANNEL_CHG_MONITOR 3
|
||||
#define CHANNEL_VPH_PWR 4
|
||||
#define CHANNEL_MPP5 5
|
||||
#define CHANNEL_MPP6 6
|
||||
#define CHANNEL_MPP7 7
|
||||
#define CHANNEL_MPP8 8
|
||||
#define CHANNEL_MPP9 9
|
||||
#define CHANNEL_USB_VBUS 0Xa
|
||||
#define CHANNEL_DIE_TEMP 0Xb
|
||||
#define CHANNEL_INTERNAL 0xc
|
||||
#define CHANNEL_125V 0xd
|
||||
#define CHANNEL_INTERNAL_2 0Xe
|
||||
#define CHANNEL_MUXOFF 0xf
|
||||
|
||||
#define XOADC_MPP_3 0x2
|
||||
#define XOADC_MPP_4 0X3
|
||||
#define XOADC_MPP_5 0x4
|
||||
#define XOADC_MPP_7 0x6
|
||||
#define XOADC_MPP_8 0x7
|
||||
#define XOADC_MPP_10 0X9
|
||||
|
||||
#define XOADC_PMIC_0 0x0
|
||||
|
||||
#define CHANNEL_ADC_625_MV 625
|
||||
|
||||
struct xoadc_platform_data {
|
||||
struct adc_properties *xoadc_prop;
|
||||
u32 (*xoadc_setup) (void);
|
||||
void (*xoadc_shutdown) (void);
|
||||
void (*xoadc_mpp_config) (void);
|
||||
int (*xoadc_vreg_set) (int);
|
||||
int (*xoadc_vreg_setup) (void);
|
||||
void (*xoadc_vreg_shutdown) (void);
|
||||
u32 xoadc_num;
|
||||
u32 xoadc_wakeup;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PMIC8058_XOADC
|
||||
int32_t pm8058_xoadc_read_adc_code(uint32_t adc_instance, int32_t *data);
|
||||
|
||||
int32_t pm8058_xoadc_select_chan_and_start_conv(uint32_t adc_instance,
|
||||
struct adc_conv_slot *slot);
|
||||
|
||||
void pm8058_xoadc_slot_request(uint32_t adc_instance,
|
||||
struct adc_conv_slot **slot);
|
||||
|
||||
void pm8058_xoadc_restore_slot(uint32_t adc_instance,
|
||||
struct adc_conv_slot *slot);
|
||||
|
||||
struct adc_properties *pm8058_xoadc_get_properties(uint32_t dev_instance);
|
||||
|
||||
int32_t pm8058_xoadc_calibrate(uint32_t dev_instance,
|
||||
struct adc_conv_slot *slot, int * calib_status);
|
||||
|
||||
int32_t pm8058_xoadc_registered(void);
|
||||
|
||||
int32_t pm8058_xoadc_calib_device(uint32_t adc_instance);
|
||||
|
||||
#else
|
||||
|
||||
static inline int32_t pm8058_xoadc_read_adc_code(uint32_t adc_instance,
|
||||
int32_t *data)
|
||||
{ return -ENXIO; }
|
||||
|
||||
static inline int32_t pm8058_xoadc_select_chan_and_start_conv(
|
||||
uint32_t adc_instance, struct adc_conv_slot *slot)
|
||||
{ return -ENXIO; }
|
||||
|
||||
static inline void pm8058_xoadc_slot_request(uint32_t adc_instance,
|
||||
struct adc_conv_slot **slot)
|
||||
{ return; }
|
||||
|
||||
static inline void pm8058_xoadc_restore_slot(uint32_t adc_instance,
|
||||
struct adc_conv_slot *slot)
|
||||
{ return; }
|
||||
|
||||
static inline struct adc_properties *pm8058_xoadc_get_properties(
|
||||
uint32_t dev_instance)
|
||||
{ return NULL; }
|
||||
|
||||
static inline int32_t pm8058_xoadc_calibrate(uint32_t dev_instance,
|
||||
struct adc_conv_slot *slot, int *calib_status)
|
||||
{ return -ENXIO; }
|
||||
|
||||
static inline int32_t pm8058_xoadc_registered(void)
|
||||
{ return -ENXIO; }
|
||||
|
||||
static inline int32_t pm8058_xoadc_calib_device(uint32_t adc_instance)
|
||||
{ return -ENXIO; }
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in a new issue