mirror of
https://github.com/torvalds/linux.git
synced 2026-07-30 19:21:28 +02:00
Merge "iio: adc: qcom-spmi-adc5-gen3: Fix calls to qcom_adc5_hw_scale()"
This commit is contained in:
commit
fdf4d5a92f
|
|
@ -872,6 +872,26 @@ config QCOM_SPMI_ADC5
|
|||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-spmi-adc5.
|
||||
|
||||
config QCOM_SPMI_ADC5_GEN3
|
||||
tristate "Qualcomm Technologies Inc. SPMI PMIC5 GEN3 ADC"
|
||||
depends on SPMI
|
||||
select REGMAP_SPMI
|
||||
select QCOM_VADC_COMMON
|
||||
help
|
||||
This is the IIO Voltage PMIC5 Gen3 ADC driver for Qualcomm Technologies Inc.
|
||||
|
||||
The driver supports multiple channels read. The ADC is a 16-bit
|
||||
sigma-delta ADC. The hardware supports calibrated results for
|
||||
conversion requests and clients include reading voltage phone
|
||||
power, on board system thermistors connected to the PMIC ADC,
|
||||
PMIC die temperature, charger temperature, battery current, USB voltage
|
||||
input, voltage signals connected to supported PMIC GPIO inputs. The
|
||||
hardware supports internal pull-up for thermistors and can choose between
|
||||
a 100k, 30k and 400k pull up using the ADC channels.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-spmi-adc5-gen3.
|
||||
|
||||
config RCAR_GYRO_ADC
|
||||
tristate "Renesas R-Car GyroADC driver"
|
||||
depends on ARCH_RCAR_GEN2 || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ obj-$(CONFIG_NAU7802) += nau7802.o
|
|||
obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
|
||||
obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
|
||||
obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
|
||||
obj-$(CONFIG_QCOM_SPMI_ADC5_GEN3) += qcom-spmi-adc5-gen3.o
|
||||
obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
|
||||
obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o
|
||||
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
|
||||
|
|
|
|||
1764
drivers/iio/adc/qcom-spmi-adc5-gen3.c
Normal file
1764
drivers/iio/adc/qcom-spmi-adc5-gen3.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/math64.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
|
@ -90,6 +91,23 @@
|
|||
#define ADC_APP_SID_MASK GENMASK(3, 0)
|
||||
#define ADC7_CONV_TIMEOUT_MS 501
|
||||
|
||||
/* For ADC_PBS on PMIC7 with SW calibration */
|
||||
#define ADC7_SW_CALIB_PBS_CALREF_FLAG 0x57
|
||||
#define ADC7_SW_CALIB_PBS_CALREF_RDY BIT(7)
|
||||
|
||||
#define ADC7_SW_CALIB_PBS_GND_REF_D0 0x58
|
||||
#define ADC7_SW_CALIB_PBS_GND_REF_D1 0x59
|
||||
#define ADC7_SW_CALIB_PBS_VREF_VADC_DELTA_D0 0x5a
|
||||
#define ADC7_SW_CALIB_PBS_VREF_VADC_DELTA_D1 0x5b
|
||||
#define ADC7_SW_CALIB_PBS_VREF_MBG_DELTA_D0 0x5c
|
||||
#define ADC7_SW_CALIB_PBS_VREF_MBG_DELTA_D1 0x5d
|
||||
|
||||
/* For ADC_CMN on PMIC7 with SW calibration */
|
||||
#define ADC7_SW_CALIB_CMN_PBUS_WRITE_SYNC_CTL 0x4e
|
||||
#define ADC7_PBUS_WRITE_SYNC_SW_CLK_REQ BIT(2)
|
||||
#define ADC7_PBUS_WRITE_SYNC_SW_CLK_REQ_MODE BIT(1)
|
||||
#define ADC7_PBUS_WRITE_SYNC_BYPASS BIT(0)
|
||||
|
||||
enum adc5_cal_method {
|
||||
ADC5_NO_CAL = 0,
|
||||
ADC5_RATIOMETRIC_CAL,
|
||||
|
|
@ -135,6 +153,8 @@ struct adc5_channel_prop {
|
|||
* @regmap: SPMI ADC5 peripheral register map field.
|
||||
* @dev: SPMI ADC5 device.
|
||||
* @base: base address for the ADC peripheral.
|
||||
* @cmn_base: base address for the ADC_CMN peripheral, needed
|
||||
* for SW calibrated ADC.
|
||||
* @nchannels: number of ADC channels.
|
||||
* @chan_props: array of ADC channel properties.
|
||||
* @iio_chans: array of IIO channels specification.
|
||||
|
|
@ -147,6 +167,7 @@ struct adc5_chip {
|
|||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
u16 base;
|
||||
u16 cmn_base;
|
||||
unsigned int nchannels;
|
||||
struct adc5_channel_prop *chan_props;
|
||||
struct iio_chan_spec *iio_chans;
|
||||
|
|
@ -154,21 +175,55 @@ struct adc5_chip {
|
|||
struct completion complete;
|
||||
struct mutex lock;
|
||||
const struct adc5_data *data;
|
||||
int irq_eoc;
|
||||
};
|
||||
|
||||
static int adc5_read(struct adc5_chip *adc, u16 offset, u8 *data, int len)
|
||||
{
|
||||
return regmap_bulk_read(adc->regmap, adc->base + offset, data, len);
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(adc->regmap, adc->base + offset, data, len);
|
||||
if (ret)
|
||||
pr_err("adc read to register %#x of length:%d failed, ret=%d\n",
|
||||
offset, len, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc5_write(struct adc5_chip *adc, u16 offset, u8 *data, int len)
|
||||
{
|
||||
return regmap_bulk_write(adc->regmap, adc->base + offset, data, len);
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_write(adc->regmap, adc->base + offset, data, len);
|
||||
if (ret)
|
||||
pr_err("adc write to register %#x of length:%d failed, ret=%d\n",
|
||||
offset, len, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc5_masked_write(struct adc5_chip *adc, u16 offset, u8 mask, u8 val)
|
||||
{
|
||||
return regmap_update_bits(adc->regmap, adc->base + offset, mask, val);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(adc->regmap, adc->base + offset, mask, val);
|
||||
if (ret)
|
||||
pr_err("adc masked write to register %#x with mask:0x%x failed, ret=%d\n",
|
||||
offset, mask, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc5_cmn_write(struct adc5_chip *adc, u16 offset, u8 *data, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_write(adc->regmap, adc->cmn_base + offset, data, len);
|
||||
if (ret)
|
||||
pr_err("adc_cmn write to register %#x of length:%d failed, ret=%d\n",
|
||||
offset, len, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)
|
||||
|
|
@ -176,11 +231,11 @@ static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)
|
|||
int ret;
|
||||
u8 rslt_lsb, rslt_msb;
|
||||
|
||||
ret = adc5_read(adc, ADC5_USR_DATA0, &rslt_lsb, sizeof(rslt_lsb));
|
||||
ret = adc5_read(adc, ADC5_USR_DATA0, &rslt_lsb, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adc5_read(adc, ADC5_USR_DATA1, &rslt_msb, sizeof(rslt_lsb));
|
||||
ret = adc5_read(adc, ADC5_USR_DATA1, &rslt_msb, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -317,6 +372,52 @@ static int adc7_configure(struct adc5_chip *adc,
|
|||
return adc5_write(adc, ADC5_USR_CONV_REQ, &conv_req, 1);
|
||||
}
|
||||
|
||||
static int adc7_sw_calib_configure(struct adc5_chip *adc,
|
||||
struct adc5_channel_prop *prop)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[5], val = 0;
|
||||
|
||||
/* Read registers 0x42 through 0x46 */
|
||||
ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Digital param selection */
|
||||
adc5_update_dig_param(adc, prop, &buf[0]);
|
||||
|
||||
/* Update fast average sample value */
|
||||
buf[1] &= (u8) ~ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK;
|
||||
buf[1] |= prop->avg_samples | ADC5_USR_FAST_AVG_CTL_EN;
|
||||
|
||||
/* Select ADC channel */
|
||||
buf[2] = prop->channel;
|
||||
|
||||
/* Select HW settle delay for channel */
|
||||
buf[3] &= (u8) ~ADC5_USR_HW_SETTLE_DELAY_MASK;
|
||||
buf[3] |= prop->hw_settle_time;
|
||||
|
||||
/* Select ADC enable */
|
||||
buf[4] |= ADC5_USR_EN_CTL1_ADC_EN;
|
||||
|
||||
if (!adc->poll_eoc)
|
||||
reinit_completion(&adc->complete);
|
||||
|
||||
ret = adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = ADC7_PBUS_WRITE_SYNC_SW_CLK_REQ | ADC7_PBUS_WRITE_SYNC_SW_CLK_REQ_MODE;
|
||||
|
||||
ret = adc5_cmn_write(adc, ADC7_SW_CALIB_CMN_PBUS_WRITE_SYNC_CTL, &val, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Select CONV request */
|
||||
val = ADC5_USR_CONV_REQ_REQ;
|
||||
return adc5_write(adc, ADC5_USR_CONV_REQ, &val, 1);
|
||||
}
|
||||
|
||||
static int adc5_do_conversion(struct adc5_chip *adc,
|
||||
struct adc5_channel_prop *prop,
|
||||
struct iio_chan_spec const *chan,
|
||||
|
|
@ -427,6 +528,59 @@ static int adc7_do_conversion(struct adc5_chip *adc,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define ADC7_SW_CALIB_CONV_TIMEOUT_MS 150
|
||||
static int adc7_sw_calib_do_conversion(struct adc5_chip *adc,
|
||||
struct adc5_channel_prop *prop, u16 *adc_code_volt)
|
||||
{
|
||||
int ret;
|
||||
unsigned long rc;
|
||||
u8 status = 0, val;
|
||||
|
||||
mutex_lock(&adc->lock);
|
||||
|
||||
ret = adc7_sw_calib_configure(adc, prop);
|
||||
if (ret) {
|
||||
pr_err("ADC configure failed with %d\n", ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* No support for polling mode at present*/
|
||||
rc = wait_for_completion_timeout(&adc->complete,
|
||||
msecs_to_jiffies(ADC7_SW_CALIB_CONV_TIMEOUT_MS));
|
||||
if (!rc) {
|
||||
pr_err("Reading ADC channel %s timed out\n",
|
||||
prop->datasheet_name);
|
||||
ret = -ETIMEDOUT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
if (!(status & ADC5_USR_STATUS1_EOC)) {
|
||||
pr_err("ADC channel %s EOC bit not set, status=%#x\n",
|
||||
prop->datasheet_name, status);
|
||||
ret = -EIO;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = adc5_read_voltage_data(adc, adc_code_volt);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
val = 0;
|
||||
ret = adc5_write(adc, ADC5_USR_EN_CTL1, &val, 1);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
ret = adc5_cmn_write(adc, ADC7_SW_CALIB_CMN_PBUS_WRITE_SYNC_CTL, &val, 1);
|
||||
unlock:
|
||||
mutex_unlock(&adc->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef int (*adc_do_conversion)(struct adc5_chip *adc,
|
||||
struct adc5_channel_prop *prop,
|
||||
struct iio_chan_spec const *chan,
|
||||
|
|
@ -441,6 +595,21 @@ static irqreturn_t adc5_isr(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct adc5_channel_prop *adc7_get_channel(struct adc5_chip *adc,
|
||||
unsigned int num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < adc->nchannels; i++) {
|
||||
if (adc->chan_props[i].channel == num)
|
||||
return &adc->chan_props[i];
|
||||
}
|
||||
|
||||
pr_err("Invalid channel %02x\n", num);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int adc5_of_xlate(struct iio_dev *indio_dev,
|
||||
const struct of_phandle_args *iiospec)
|
||||
{
|
||||
|
|
@ -517,6 +686,118 @@ static int adc7_read_raw(struct iio_dev *indio_dev,
|
|||
mask, adc7_do_conversion);
|
||||
}
|
||||
|
||||
static int adc7_calib(struct adc5_chip *adc)
|
||||
{
|
||||
int ret = 0;
|
||||
u16 gnd, vref_1p25, vref_vdd;
|
||||
u8 buf[2];
|
||||
struct adc5_channel_prop *gnd_prop, *vref_1p25_prop, *vref_vdd_prop;
|
||||
|
||||
/* These channels are mandatory, they are used as reference points */
|
||||
gnd_prop = adc7_get_channel(adc, ADC7_REF_GND);
|
||||
if (!gnd_prop) {
|
||||
dev_err(adc->dev, "GND channel not defined for SW calibration\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
vref_1p25_prop = adc7_get_channel(adc, ADC7_1P25VREF);
|
||||
if (!vref_1p25_prop) {
|
||||
dev_err(adc->dev, "1.25VREF channel not defined for SW calibration\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
vref_vdd_prop = adc7_get_channel(adc, ADC7_VREF_VADC);
|
||||
if (!vref_vdd_prop) {
|
||||
dev_err(adc->dev, "VDD channel not defined for SW calibration\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = adc7_sw_calib_do_conversion(adc, gnd_prop, &gnd);
|
||||
if (ret) {
|
||||
dev_err(adc->dev, "Failed to read GND channel, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adc7_sw_calib_do_conversion(adc, vref_1p25_prop, &vref_1p25);
|
||||
if (ret) {
|
||||
dev_err(adc->dev, "Failed to read 1.25VREF channel, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adc7_sw_calib_do_conversion(adc, vref_vdd_prop, &vref_vdd);
|
||||
if (ret) {
|
||||
dev_err(adc->dev, "Failed to read VDD channel, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf[0] = gnd & 0xff;
|
||||
buf[1] = gnd >> 8;
|
||||
ret = adc5_write(adc, ADC7_SW_CALIB_PBS_GND_REF_D0, buf, sizeof(buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vref_vdd -= gnd;
|
||||
buf[0] = vref_vdd & 0xff;
|
||||
buf[1] = vref_vdd >> 8;
|
||||
ret = adc5_write(adc, ADC7_SW_CALIB_PBS_VREF_VADC_DELTA_D0, buf, sizeof(buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vref_1p25 -= gnd;
|
||||
buf[0] = vref_1p25 & 0xff;
|
||||
buf[1] = vref_1p25 >> 8;
|
||||
ret = adc5_write(adc, ADC7_SW_CALIB_PBS_VREF_MBG_DELTA_D0, buf, sizeof(buf));
|
||||
|
||||
if (!ret)
|
||||
dev_dbg(adc->dev, "SW calibration done, gnd:0x%x vref_vdd:0x%x vref_1p25:0x%x\n",
|
||||
gnd, vref_vdd, vref_1p25);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc7_sw_calib_conv(struct adc5_chip *adc, struct adc5_channel_prop *prop, int *val)
|
||||
{
|
||||
int ret = 0;
|
||||
u16 adc_code_volt;
|
||||
|
||||
ret = adc7_calib(adc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adc7_sw_calib_do_conversion(adc, prop, &adc_code_volt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return qcom_adc5_hw_scale(prop->scale_fn_type,
|
||||
prop->prescale,
|
||||
adc->data,
|
||||
adc_code_volt, val);
|
||||
}
|
||||
|
||||
static int adc7_sw_calib_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int *val, int *val2,
|
||||
long mask)
|
||||
{
|
||||
struct adc5_chip *adc = iio_priv(indio_dev);
|
||||
struct adc5_channel_prop *prop;
|
||||
int ret;
|
||||
|
||||
prop = &adc->chan_props[chan->address];
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_PROCESSED:
|
||||
ret = adc7_sw_calib_conv(adc, prop, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_info adc5_info = {
|
||||
.read_raw = adc5_read_raw,
|
||||
.of_xlate = adc5_of_xlate,
|
||||
|
|
@ -527,6 +808,11 @@ static const struct iio_info adc7_info = {
|
|||
.of_xlate = adc7_of_xlate,
|
||||
};
|
||||
|
||||
static const struct iio_info adc7_sw_calib_info = {
|
||||
.read_raw = adc7_sw_calib_read_raw,
|
||||
.of_xlate = adc5_of_xlate,
|
||||
};
|
||||
|
||||
struct adc5_channels {
|
||||
const char *datasheet_name;
|
||||
unsigned int prescale_index;
|
||||
|
|
@ -602,6 +888,8 @@ static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = {
|
|||
SCALE_HW_CALIB_THERM_100K_PULLUP)
|
||||
[ADC5_AMUX_THM2] = ADC5_CHAN_TEMP("amux_thm2", 0,
|
||||
SCALE_HW_CALIB_PM5_SMB_TEMP)
|
||||
[ADC5_PARALLEL_ISENSE] = ADC5_CHAN_VOLT("parallel_isense", 0,
|
||||
SCALE_HW_CALIB_PM5_CUR)
|
||||
[ADC5_GPIO1_100K_PU] = ADC5_CHAN_TEMP("gpio1_100k_pu", 0,
|
||||
SCALE_HW_CALIB_THERM_100K_PULLUP)
|
||||
[ADC5_GPIO2_100K_PU] = ADC5_CHAN_TEMP("gpio2_100k_pu", 0,
|
||||
|
|
@ -617,21 +905,25 @@ static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = {
|
|||
SCALE_HW_CALIB_DEFAULT)
|
||||
[ADC7_1P25VREF] = ADC5_CHAN_VOLT("vref_1p25", 0,
|
||||
SCALE_HW_CALIB_DEFAULT)
|
||||
[ADC7_VREF_VADC] = ADC5_CHAN_VOLT("vref_vadc", 0,
|
||||
SCALE_HW_CALIB_DEFAULT)
|
||||
[ADC7_VPH_PWR] = ADC5_CHAN_VOLT("vph_pwr", 1,
|
||||
SCALE_HW_CALIB_DEFAULT)
|
||||
[ADC7_VBAT_SNS] = ADC5_CHAN_VOLT("vbat_sns", 3,
|
||||
SCALE_HW_CALIB_DEFAULT)
|
||||
[ADC7_AMUX_THM3] = ADC5_CHAN_TEMP("smb_temp", 0,
|
||||
[ADC7_USB_IN_V_16] = ADC5_CHAN_VOLT("usb_in_v_div_16", 8,
|
||||
SCALE_HW_CALIB_DEFAULT)
|
||||
[ADC7_AMUX_THM3] = ADC5_CHAN_TEMP("smb_temp", 9,
|
||||
SCALE_HW_CALIB_PM7_SMB_TEMP)
|
||||
[ADC7_CHG_TEMP] = ADC5_CHAN_TEMP("chg_temp", 0,
|
||||
SCALE_HW_CALIB_PM7_CHG_TEMP)
|
||||
[ADC7_IIN_FB] = ADC5_CHAN_CUR("iin_fb", 9,
|
||||
[ADC7_IIN_FB] = ADC5_CHAN_CUR("iin_fb", 10,
|
||||
SCALE_HW_CALIB_CUR)
|
||||
[ADC7_ICHG_SMB] = ADC5_CHAN_CUR("ichg_smb", 10,
|
||||
[ADC7_IIN_SMB] = ADC5_CHAN_CUR("iin_smb", 12,
|
||||
SCALE_HW_CALIB_CUR)
|
||||
[ADC7_IIN_SMB] = ADC5_CHAN_CUR("iin_smb", 11,
|
||||
[ADC7_ICHG_SMB] = ADC5_CHAN_CUR("ichg_smb", 13,
|
||||
SCALE_HW_CALIB_CUR)
|
||||
[ADC7_ICHG_FB] = ADC5_CHAN_CUR("ichg_fb", 12,
|
||||
[ADC7_ICHG_FB] = ADC5_CHAN_CUR("ichg_fb", 14,
|
||||
SCALE_HW_CALIB_CUR_RAW)
|
||||
[ADC7_DIE_TEMP] = ADC5_CHAN_TEMP("die_temp", 0,
|
||||
SCALE_HW_CALIB_PMIC_THERM_PM7)
|
||||
|
|
@ -682,6 +974,8 @@ static const struct adc5_channels adc5_chans_rev2[ADC5_MAX_CHANNEL] = {
|
|||
SCALE_HW_CALIB_THERM_100K_PULLUP)
|
||||
[ADC5_XO_THERM_100K_PU] = ADC5_CHAN_TEMP("xo_therm_100k_pu", 0,
|
||||
SCALE_HW_CALIB_THERM_100K_PULLUP)
|
||||
[ADC5_GPIO2_100K_PU] = ADC5_CHAN_TEMP("gpio2_100k_pu", 0,
|
||||
SCALE_HW_CALIB_THERM_100K_PULLUP)
|
||||
};
|
||||
|
||||
static int adc5_get_dt_channel_data(struct adc5_chip *adc,
|
||||
|
|
@ -801,6 +1095,8 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
|
|||
|
||||
if (of_property_read_bool(node, "qcom,ratiometric"))
|
||||
prop->cal_method = ADC5_RATIOMETRIC_CAL;
|
||||
else if (of_property_read_bool(node, "qcom,no-cal"))
|
||||
prop->cal_method = ADC5_NO_CAL;
|
||||
else
|
||||
prop->cal_method = ADC5_ABSOLUTE_CAL;
|
||||
|
||||
|
|
@ -816,6 +1112,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
|
|||
}
|
||||
|
||||
static const struct adc5_data adc5_data_pmic = {
|
||||
.name = "pm-adc5",
|
||||
.full_scale_code_volt = 0x70e4,
|
||||
.full_scale_code_cur = 0x2710,
|
||||
.adc_chans = adc5_chans_pmic,
|
||||
|
|
@ -831,6 +1128,7 @@ static const struct adc5_data adc5_data_pmic = {
|
|||
};
|
||||
|
||||
static const struct adc5_data adc7_data_pmic = {
|
||||
.name = "pm-adc7",
|
||||
.full_scale_code_volt = 0x70e4,
|
||||
.adc_chans = adc7_chans_pmic,
|
||||
.info = &adc7_info,
|
||||
|
|
@ -842,7 +1140,19 @@ static const struct adc5_data adc7_data_pmic = {
|
|||
64000, 128000},
|
||||
};
|
||||
|
||||
static const struct adc5_data adc5_data_pmic5_lite = {
|
||||
.name = "pm-adc5-lite",
|
||||
.full_scale_code_volt = 0x70e4,
|
||||
/* On PMI632, IBAT LSB = 5A/32767 */
|
||||
.full_scale_code_cur = 5000,
|
||||
.adc_chans = adc5_chans_pmic,
|
||||
.decimation = (unsigned int []) {250, 420, 840},
|
||||
.hw_settle_1 = (unsigned int []) {15, 100, 200, 300, 400, 500, 600, 700,
|
||||
800, 900, 1, 2, 4, 6, 8, 10},
|
||||
};
|
||||
|
||||
static const struct adc5_data adc5_data_pmic_rev2 = {
|
||||
.name = "pm-adc4-rev2",
|
||||
.full_scale_code_volt = 0x4000,
|
||||
.full_scale_code_cur = 0x1800,
|
||||
.adc_chans = adc5_chans_rev2,
|
||||
|
|
@ -866,10 +1176,18 @@ static const struct of_device_id adc5_match_table[] = {
|
|||
.compatible = "qcom,spmi-adc7",
|
||||
.data = &adc7_data_pmic,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,spmi-adc7-sw-calib",
|
||||
.data = &adc7_data_pmic,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,spmi-adc-rev2",
|
||||
.data = &adc5_data_pmic_rev2,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,spmi-adc5-lite",
|
||||
.data = &adc5_data_pmic5_lite,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adc5_match_table);
|
||||
|
|
@ -936,8 +1254,11 @@ static int adc5_probe(struct platform_device *pdev)
|
|||
struct iio_dev *indio_dev;
|
||||
struct adc5_chip *adc;
|
||||
struct regmap *regmap;
|
||||
int ret, irq_eoc;
|
||||
const char *irq_name;
|
||||
const __be32 *prop_addr;
|
||||
int ret;
|
||||
u32 reg;
|
||||
u8 val;
|
||||
|
||||
regmap = dev_get_regmap(dev->parent, NULL);
|
||||
if (!regmap)
|
||||
|
|
@ -954,7 +1275,27 @@ static int adc5_probe(struct platform_device *pdev)
|
|||
adc = iio_priv(indio_dev);
|
||||
adc->regmap = regmap;
|
||||
adc->dev = dev;
|
||||
adc->base = reg;
|
||||
|
||||
prop_addr = of_get_address(dev->of_node, 0, NULL, NULL);
|
||||
if (!prop_addr) {
|
||||
pr_err("invalid IO resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
adc->base = be32_to_cpu(*prop_addr);
|
||||
|
||||
prop_addr = of_get_address(dev->of_node, 1, NULL, NULL);
|
||||
if (!prop_addr)
|
||||
pr_debug("invalid cmn resource\n");
|
||||
else
|
||||
adc->cmn_base = be32_to_cpu(*prop_addr);
|
||||
|
||||
|
||||
if (of_device_is_compatible(node, "qcom,spmi-adc7-sw-calib")) {
|
||||
if (!adc->cmn_base) {
|
||||
pr_err("ADC_CMN undefined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
init_completion(&adc->complete);
|
||||
mutex_init(&adc->lock);
|
||||
|
|
@ -965,18 +1306,33 @@ static int adc5_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
irq_eoc = platform_get_irq(pdev, 0);
|
||||
if (irq_eoc < 0) {
|
||||
if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL)
|
||||
return irq_eoc;
|
||||
adc->irq_eoc = platform_get_irq(pdev, 0);
|
||||
if (adc->irq_eoc < 0) {
|
||||
if (adc->irq_eoc == -EPROBE_DEFER || adc->irq_eoc == -EINVAL)
|
||||
return adc->irq_eoc;
|
||||
adc->poll_eoc = true;
|
||||
} else {
|
||||
ret = devm_request_irq(dev, irq_eoc, adc5_isr, 0,
|
||||
"pm-adc5", adc);
|
||||
irq_name = "pm-adc5";
|
||||
if (adc->data->name)
|
||||
irq_name = adc->data->name;
|
||||
|
||||
ret = devm_request_irq(dev, adc->irq_eoc, adc5_isr, 0,
|
||||
irq_name, adc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(node, "qcom,spmi-adc7-sw-calib")) {
|
||||
ret = adc7_calib(adc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = ADC7_SW_CALIB_PBS_CALREF_RDY;
|
||||
ret = adc5_write(adc, ADC7_SW_CALIB_PBS_CALREF_FLAG, &val, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
indio_dev->name = pdev->name;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = adc->data->info;
|
||||
|
|
@ -986,10 +1342,39 @@ static int adc5_probe(struct platform_device *pdev)
|
|||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static int adc_restore(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct adc5_chip *adc = dev_get_drvdata(dev);
|
||||
|
||||
if (adc->irq_eoc > 0)
|
||||
ret = devm_request_irq(dev, adc->irq_eoc, adc5_isr, 0,
|
||||
"pm-adc5", adc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adc_freeze(struct device *dev)
|
||||
{
|
||||
struct adc5_chip *adc = dev_get_drvdata(dev);
|
||||
|
||||
if (adc->irq_eoc > 0)
|
||||
devm_free_irq(dev, adc->irq_eoc, adc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops adc_pm_ops = {
|
||||
.freeze = adc_freeze,
|
||||
.thaw = adc_restore,
|
||||
.restore = adc_restore,
|
||||
};
|
||||
|
||||
static struct platform_driver adc5_driver = {
|
||||
.driver = {
|
||||
.name = "qcom-spmi-adc5",
|
||||
.of_match_table = adc5_match_table,
|
||||
.pm = &adc_pm_ops,
|
||||
},
|
||||
.probe = adc5_probe,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -520,6 +520,82 @@ static const struct vadc_map_pt adcmap7_100k[] = {
|
|||
{ 2420, 130048 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Resistance to temperature table for batt_therm.
|
||||
*/
|
||||
static const struct vadc_map_pt adcmap_gen3_batt_therm_100k[] = {
|
||||
{ 5319890, -400 },
|
||||
{ 4555860, -380 },
|
||||
{ 3911780, -360 },
|
||||
{ 3367320, -340 },
|
||||
{ 2905860, -320 },
|
||||
{ 2513730, -300 },
|
||||
{ 2179660, -280 },
|
||||
{ 1894360, -260 },
|
||||
{ 1650110, -240 },
|
||||
{ 1440520, -220 },
|
||||
{ 1260250, -200 },
|
||||
{ 1104850, -180 },
|
||||
{ 970600, -160 },
|
||||
{ 854370, -140 },
|
||||
{ 753530, -120 },
|
||||
{ 665860, -100 },
|
||||
{ 589490, -80 },
|
||||
{ 522830, -60 },
|
||||
{ 464540, -40 },
|
||||
{ 413470, -20 },
|
||||
{ 368640, 0 },
|
||||
{ 329220, 20 },
|
||||
{ 294490, 40 },
|
||||
{ 263850, 60 },
|
||||
{ 236770, 80 },
|
||||
{ 212790, 100 },
|
||||
{ 191530, 120 },
|
||||
{ 172640, 140 },
|
||||
{ 155840, 160 },
|
||||
{ 140880, 180 },
|
||||
{ 127520, 200 },
|
||||
{ 115590, 220 },
|
||||
{ 104910, 240 },
|
||||
{ 95350, 260 },
|
||||
{ 86760, 280 },
|
||||
{ 79050, 300 },
|
||||
{ 72110, 320 },
|
||||
{ 65860, 340 },
|
||||
{ 60220, 360 },
|
||||
{ 55130, 380 },
|
||||
{ 50520, 400 },
|
||||
{ 46350, 420 },
|
||||
{ 42570, 440 },
|
||||
{ 39140, 460 },
|
||||
{ 36030, 480 },
|
||||
{ 33190, 500 },
|
||||
{ 30620, 520 },
|
||||
{ 28260, 540 },
|
||||
{ 26120, 560 },
|
||||
{ 24160, 580 },
|
||||
{ 22370, 600 },
|
||||
{ 20730, 620 },
|
||||
{ 19230, 640 },
|
||||
{ 17850, 660 },
|
||||
{ 16580, 680 },
|
||||
{ 15420, 700 },
|
||||
{ 14350, 720 },
|
||||
{ 13370, 740 },
|
||||
{ 12470, 760 },
|
||||
{ 11630, 780 },
|
||||
{ 10860, 800 },
|
||||
{ 10150, 820 },
|
||||
{ 9490, 840 },
|
||||
{ 8880, 860 },
|
||||
{ 8320, 880 },
|
||||
{ 7800, 900 },
|
||||
{ 7310, 920 },
|
||||
{ 6860, 940 },
|
||||
{ 6450, 960 },
|
||||
{ 6060, 980 }
|
||||
};
|
||||
|
||||
static const struct u32_fract adc5_prescale_ratios[] = {
|
||||
{ .numerator = 1, .denominator = 1 },
|
||||
{ .numerator = 1, .denominator = 3 },
|
||||
|
|
@ -530,10 +606,12 @@ static const struct u32_fract adc5_prescale_ratios[] = {
|
|||
{ .numerator = 10, .denominator = 81 },
|
||||
{ .numerator = 1, .denominator = 10 },
|
||||
{ .numerator = 1, .denominator = 16 },
|
||||
{ .numerator = 40, .denominator = 41 }, /* PM7_SMB_TEMP */
|
||||
/* Prescale ratios for current channels below */
|
||||
{ .numerator = 32, .denominator = 100 }, /* IIN_FB */
|
||||
{ .numerator = 14, .denominator = 100 }, /* ICHG_SMB */
|
||||
{ .numerator = 28, .denominator = 100 }, /* IIN_SMB */
|
||||
{ .numerator = 32, .denominator = 100 }, /* IIN_FB, IIN_SMB */
|
||||
{ .numerator = 16, .denominator = 100 }, /* ICHG_SMB */
|
||||
{ .numerator = 1280, .denominator = 4100 }, /* IIN_SMB_new */
|
||||
{ .numerator = 640, .denominator = 4100 }, /* ICHG_SMB_new */
|
||||
{ .numerator = 1000, .denominator = 305185 }, /* ICHG_FB */
|
||||
{ .numerator = 1000, .denominator = 610370 }, /* ICHG_FB_2X */
|
||||
};
|
||||
|
|
@ -542,14 +620,21 @@ static int qcom_vadc_scale_hw_calib_volt(
|
|||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_uv);
|
||||
/* Current scaling for PMIC7 */
|
||||
static int qcom_vadc_scale_hw_calib_current(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_ua);
|
||||
/* Raw current for PMIC7 */
|
||||
static int qcom_vadc_scale_hw_calib_current_raw(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_ua);
|
||||
/* Current scaling for PMIC5 */
|
||||
static int qcom_vadc5_scale_hw_calib_current(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_ua);
|
||||
static int qcom_vadc_scale_hw_calib_therm(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
|
|
@ -582,6 +667,22 @@ static int qcom_vadc_scale_hw_smb1398_temp(
|
|||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec);
|
||||
static int qcom_vadc_scale_hw_pm2250_s3_die_temp(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec);
|
||||
static int qcom_adc5_gen3_scale_hw_calib_batt_therm_100(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec);
|
||||
static int qcom_adc5_gen3_scale_hw_calib_batt_id_100(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec);
|
||||
static int qcom_adc5_gen3_scale_hw_calib_usb_in_current(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec);
|
||||
static int qcom_vadc_scale_hw_chg5_temp(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
|
|
@ -603,6 +704,7 @@ static struct qcom_adc5_scale_type scale_adc5_fn[] = {
|
|||
[SCALE_HW_CALIB_DEFAULT] = {qcom_vadc_scale_hw_calib_volt},
|
||||
[SCALE_HW_CALIB_CUR] = {qcom_vadc_scale_hw_calib_current},
|
||||
[SCALE_HW_CALIB_CUR_RAW] = {qcom_vadc_scale_hw_calib_current_raw},
|
||||
[SCALE_HW_CALIB_PM5_CUR] = {qcom_vadc5_scale_hw_calib_current},
|
||||
[SCALE_HW_CALIB_THERM_100K_PULLUP] = {qcom_vadc_scale_hw_calib_therm},
|
||||
[SCALE_HW_CALIB_BATT_THERM_100K] = {
|
||||
qcom_vadc_scale_hw_calib_batt_therm_100},
|
||||
|
|
@ -619,6 +721,10 @@ static struct qcom_adc5_scale_type scale_adc5_fn[] = {
|
|||
[SCALE_HW_CALIB_PM5_CHG_TEMP] = {qcom_vadc_scale_hw_chg5_temp},
|
||||
[SCALE_HW_CALIB_PM5_SMB_TEMP] = {qcom_vadc_scale_hw_smb_temp},
|
||||
[SCALE_HW_CALIB_PM5_SMB1398_TEMP] = {qcom_vadc_scale_hw_smb1398_temp},
|
||||
[SCALE_HW_CALIB_PM2250_S3_DIE_TEMP] = {qcom_vadc_scale_hw_pm2250_s3_die_temp},
|
||||
[SCALE_HW_CALIB_PM5_GEN3_BATT_THERM_100K] = {qcom_adc5_gen3_scale_hw_calib_batt_therm_100},
|
||||
[SCALE_HW_CALIB_PM5_GEN3_BATT_ID_100K] = {qcom_adc5_gen3_scale_hw_calib_batt_id_100},
|
||||
[SCALE_HW_CALIB_PM5_GEN3_USB_IN_I] = {qcom_adc5_gen3_scale_hw_calib_usb_in_current},
|
||||
[SCALE_HW_CALIB_PM7_SMB_TEMP] = {qcom_vadc_scale_hw_pm7_smb_temp},
|
||||
[SCALE_HW_CALIB_PM7_CHG_TEMP] = {qcom_vadc_scale_hw_pm7_chg_temp},
|
||||
};
|
||||
|
|
@ -875,6 +981,30 @@ static int qcom_vadc_scale_hw_calib_current(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_vadc5_scale_hw_calib_current(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_ua)
|
||||
{
|
||||
s64 voltage = 0, result = 0;
|
||||
bool positive = true;
|
||||
|
||||
if (adc_code & ADC5_USR_DATA_CHECK) {
|
||||
adc_code = ~adc_code + 1;
|
||||
positive = false;
|
||||
}
|
||||
|
||||
voltage = (s64)(s16) adc_code * data->full_scale_code_cur * 1000;
|
||||
voltage = div64_s64(voltage, VADC5_MAX_CODE);
|
||||
result = div64_s64(voltage * prescale->denominator, prescale->numerator);
|
||||
*result_ua = result;
|
||||
|
||||
if (!positive)
|
||||
*result_ua = -result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_vadc_scale_hw_calib_volt(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
|
|
@ -1059,6 +1189,104 @@ static int qcom_vadc_scale_hw_smb1398_temp(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_vadc_scale_hw_pm2250_s3_die_temp(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec)
|
||||
{
|
||||
s64 voltage = 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);
|
||||
if (voltage > 0) {
|
||||
voltage *= prescale->denominator;
|
||||
voltage = div64_s64(voltage, prescale->numerator);
|
||||
} else {
|
||||
voltage = 0;
|
||||
}
|
||||
|
||||
voltage = PMIC5_PM2250_S3_DIE_TEMP_CONSTANT - voltage;
|
||||
voltage *= 100000;
|
||||
voltage = div64_s64(voltage, PMIC5_PM2250_S3_DIE_TEMP_SCALE_FACTOR);
|
||||
|
||||
*result_mdec = voltage;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_adc5_gen3_scale_hw_calib_batt_therm_100(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec)
|
||||
{
|
||||
s64 resistance = 0;
|
||||
int ret, result = 0;
|
||||
|
||||
if (adc_code >= RATIO_MAX_ADC7)
|
||||
return -EINVAL;
|
||||
|
||||
/* (ADC code * R_PULLUP (100Kohm)) / (full_scale_code - ADC code)*/
|
||||
resistance = (s64) adc_code * R_PU_100K;
|
||||
resistance = div64_s64(resistance, (RATIO_MAX_ADC7 - adc_code));
|
||||
|
||||
ret = qcom_vadc_map_voltage_temp(adcmap_gen3_batt_therm_100k,
|
||||
ARRAY_SIZE(adcmap_gen3_batt_therm_100k),
|
||||
resistance, &result);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*result_mdec = result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_adc5_gen3_scale_hw_calib_batt_id_100(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_mdec)
|
||||
{
|
||||
s64 resistance = 0;
|
||||
|
||||
if (adc_code >= RATIO_MAX_ADC7)
|
||||
return -EINVAL;
|
||||
|
||||
/* (ADC code * R_PULLUP (100Kohm)) / (full_scale_code - ADC code)*/
|
||||
resistance = (s64) adc_code * R_PU_100K;
|
||||
resistance = div64_s64(resistance, (RATIO_MAX_ADC7 - adc_code));
|
||||
|
||||
*result_mdec = (int)resistance;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int qcom_adc5_gen3_scale_hw_calib_usb_in_current(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
u16 adc_code, int *result_ua)
|
||||
{
|
||||
s64 voltage = 0, result = 0;
|
||||
bool positive = true;
|
||||
|
||||
if (adc_code & ADC5_USR_DATA_CHECK) {
|
||||
adc_code = ~adc_code + 1;
|
||||
positive = false;
|
||||
}
|
||||
|
||||
voltage = (s64)(s16) adc_code * 1000000;
|
||||
voltage = div64_s64(voltage, PMIC5_GEN3_USB_IN_I_SCALE_FACTOR);
|
||||
result = div64_s64(voltage * prescale->denominator, prescale->numerator);
|
||||
*result_ua = (int)result;
|
||||
|
||||
if (!positive)
|
||||
*result_ua = -(int)result;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int qcom_vadc_scale_hw_chg5_temp(
|
||||
const struct u32_fract *prescale,
|
||||
const struct adc5_data *data,
|
||||
|
|
@ -1071,6 +1299,95 @@ static int qcom_vadc_scale_hw_chg5_temp(
|
|||
return 0;
|
||||
}
|
||||
|
||||
void adc_tm_scale_therm_voltage_100k_gen3(struct adc_tm_config *param)
|
||||
{
|
||||
int temp, ret;
|
||||
int64_t resistance = 0;
|
||||
|
||||
/*
|
||||
* High temperature maps to lower threshold voltage.
|
||||
* Same API can be used for resistance-temperature table
|
||||
*/
|
||||
resistance = qcom_vadc_map_temp_voltage(adcmap7_100k,
|
||||
ARRAY_SIZE(adcmap7_100k),
|
||||
param->high_thr_temp);
|
||||
|
||||
param->low_thr_voltage = resistance * RATIO_MAX_ADC7;
|
||||
param->low_thr_voltage = div64_s64(param->low_thr_voltage,
|
||||
(resistance + R_PU_100K));
|
||||
|
||||
/*
|
||||
* low_thr_voltage is ADC raw code corresponding to upper temperature
|
||||
* threshold.
|
||||
* Instead of returning the ADC raw code obtained at this point,we first
|
||||
* do a forward conversion on the (low voltage / high temperature) threshold code,
|
||||
* to temperature, to check if that code, when read by TM, would translate to
|
||||
* a temperature greater than or equal to the upper temperature limit (which is
|
||||
* expected). If it is instead lower than the upper limit (not expected for correct
|
||||
* TM functionality), we lower the raw code of the threshold written by 1
|
||||
* to ensure TM does see a violation when it reads raw code corresponding
|
||||
* to the upper limit temperature specified.
|
||||
*/
|
||||
ret = qcom_vadc7_scale_hw_calib_therm(NULL, NULL, param->low_thr_voltage, &temp);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
if (temp < param->high_thr_temp)
|
||||
param->low_thr_voltage--;
|
||||
|
||||
/*
|
||||
* Low temperature maps to higher threshold voltage
|
||||
* Same API can be used for resistance-temperature table
|
||||
*/
|
||||
resistance = qcom_vadc_map_temp_voltage(adcmap7_100k,
|
||||
ARRAY_SIZE(adcmap7_100k),
|
||||
param->low_thr_temp);
|
||||
|
||||
param->high_thr_voltage = resistance * RATIO_MAX_ADC7;
|
||||
param->high_thr_voltage = div64_s64(param->high_thr_voltage,
|
||||
(resistance + R_PU_100K));
|
||||
|
||||
/*
|
||||
* high_thr_voltage is ADC raw code corresponding to lower temperature
|
||||
* threshold.
|
||||
* Similar to what is done above for low_thr voltage, we first
|
||||
* do a forward conversion on the (high voltage / low temperature)threshold code,
|
||||
* to temperature, to check if that code, when read by TM, would translate to a
|
||||
* temperature less than or equal to the lower temperature limit (which is expected).
|
||||
* If it is instead greater than the lower limit (not expected for correct
|
||||
* TM functionality), we increase the raw code of the threshold written by 1
|
||||
* to ensure TM does see a violation when it reads raw code corresponding
|
||||
* to the lower limit temperature specified.
|
||||
*/
|
||||
ret = qcom_vadc7_scale_hw_calib_therm(NULL, NULL, param->high_thr_voltage, &temp);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
if (temp > param->low_thr_temp)
|
||||
param->high_thr_voltage++;
|
||||
}
|
||||
EXPORT_SYMBOL(adc_tm_scale_therm_voltage_100k_gen3);
|
||||
|
||||
int32_t adc_tm_absolute_rthr_gen3(struct adc_tm_config *tm_config)
|
||||
{
|
||||
int64_t low_thr = 0, high_thr = 0;
|
||||
|
||||
low_thr = tm_config->low_thr_voltage;
|
||||
low_thr *= ADC5_FULL_SCALE_CODE;
|
||||
|
||||
low_thr = div64_s64(low_thr, ADC_VDD_REF);
|
||||
tm_config->low_thr_voltage = low_thr;
|
||||
|
||||
high_thr = tm_config->high_thr_voltage;
|
||||
high_thr *= ADC5_FULL_SCALE_CODE;
|
||||
|
||||
high_thr = div64_s64(high_thr, ADC_VDD_REF);
|
||||
tm_config->high_thr_voltage = high_thr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(adc_tm_absolute_rthr_gen3);
|
||||
|
||||
int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
|
||||
const struct vadc_linear_graph *calib_graph,
|
||||
const struct u32_fract *prescale,
|
||||
|
|
|
|||
79
include/dt-bindings/iio/qcom,spmi-adc5-gen3-pm5100.h
Normal file
79
include/dt-bindings/iio/qcom,spmi-adc5-gen3-pm5100.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PM5100_H
|
||||
#define _DT_BINDINGS_QCOM_SPMI_VADC_PM5100_H
|
||||
|
||||
#ifndef PM5100_SID
|
||||
#define PM5100_SID 0
|
||||
#endif
|
||||
|
||||
/* ADC channels for PM5100_ADC for PMIC5 Gen3 */
|
||||
#define PM5100_ADC5_GEN3_OFFSET_REF (PM5100_SID << 8 | 0x0)
|
||||
#define PM5100_ADC5_GEN3_1P25VREF (PM5100_SID << 8 | 0x01)
|
||||
#define PM5100_ADC5_GEN3_VREF_VADC (PM5100_SID << 8 | 0x02)
|
||||
#define PM5100_ADC5_GEN3_DIE_TEMP (PM5100_SID << 8 | 0x03)
|
||||
|
||||
#define PM5100_ADC5_GEN3_AMUX1_THM (PM5100_SID << 8 | 0x04)
|
||||
#define PM5100_ADC5_GEN3_BAT_ID (PM5100_SID << 8 | 0x05)
|
||||
#define PM5100_ADC5_GEN3_BATT_THM (PM5100_SID << 8 | 0x06)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_THM (PM5100_SID << 8 | 0x07)
|
||||
#define PM5100_ADC5_GEN3_AMUX5_THM (PM5100_SID << 8 | 0x08)
|
||||
#define PM5100_ADC5_GEN3_AMUX6_THM (PM5100_SID << 8 | 0x09)
|
||||
#define PM5100_ADC5_GEN3_AMUX1_GPIO10 (PM5100_SID << 8 | 0x0a)
|
||||
#define PM5100_ADC5_GEN3_AMUX2_GPIO11 (PM5100_SID << 8 | 0x0b)
|
||||
#define PM5100_ADC5_GEN3_AMUX3_GPIO (PM5100_SID << 8 | 0x0c)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_GPIO (PM5100_SID << 8 | 0x0d)
|
||||
|
||||
#define PM5100_ADC5_GEN3_CHG_TEMP (PM5100_SID << 8 | 0x10)
|
||||
#define PM5100_ADC5_GEN3_USB_SNS_V_16 (PM5100_SID << 8 | 0x11)
|
||||
#define PM5100_ADC5_GEN3_VIN_DIV16_MUX (PM5100_SID << 8 | 0x12)
|
||||
#define PM5100_ADC5_GEN3_USB_IN_I (PM5100_SID << 8 | 0x17)
|
||||
#define PM5100_ADC5_GEN3_ICHG_FB (PM5100_SID << 8 | 0xa1)
|
||||
|
||||
/* 30k pull-up1 */
|
||||
#define PM5100_ADC5_GEN3_AMUX1_THM_30K_PU (PM5100_SID << 8 | 0x24)
|
||||
#define PM5100_ADC5_GEN3_BAT_ID_30K_PU (PM5100_SID << 8 | 0x25)
|
||||
#define PM5100_ADC5_GEN3_BATT_THM_30K_PU (PM5100_SID << 8 | 0x26)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_THM_30K_PU (PM5100_SID << 8 | 0x27)
|
||||
#define PM5100_ADC5_GEN3_AMUX5_THM_30K_PU (PM5100_SID << 8 | 0x28)
|
||||
#define PM5100_ADC5_GEN3_AMUX6_THM_30K_PU (PM5100_SID << 8 | 0x29)
|
||||
#define PM5100_ADC5_GEN3_AMUX1_GPIO10_30K_PU (PM5100_SID << 8 | 0x2a)
|
||||
#define PM5100_ADC5_GEN3_AMUX2_GPIO11_30K_PU (PM5100_SID << 8 | 0x2b)
|
||||
#define PM5100_ADC5_GEN3_AMUX3_GPIO_30K_PU (PM5100_SID << 8 | 0x2c)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_GPIO_30K_PU (PM5100_SID << 8 | 0x2d)
|
||||
|
||||
/* 100k pull-up2 */
|
||||
#define PM5100_ADC5_GEN3_AMUX1_THM_100K_PU (PM5100_SID << 8 | 0x44)
|
||||
#define PM5100_ADC5_GEN3_BAT_ID_100K_PU (PM5100_SID << 8 | 0x45)
|
||||
#define PM5100_ADC5_GEN3_BATT_THM_100K_PU (PM5100_SID << 8 | 0x46)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_THM_100K_PU (PM5100_SID << 8 | 0x47)
|
||||
#define PM5100_ADC5_GEN3_AMUX5_THM_100K_PU (PM5100_SID << 8 | 0x48)
|
||||
#define PM5100_ADC5_GEN3_AMUX6_THM_100K_PU (PM5100_SID << 8 | 0x49)
|
||||
#define PM5100_ADC5_GEN3_AMUX1_GPIO10_100K_PU (PM5100_SID << 8 | 0x4a)
|
||||
#define PM5100_ADC5_GEN3_AMUX2_GPIO11_100K_PU (PM5100_SID << 8 | 0x4b)
|
||||
#define PM5100_ADC5_GEN3_AMUX3_GPIO_100K_PU (PM5100_SID << 8 | 0x4c)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_GPIO_100K_PU (PM5100_SID << 8 | 0x4d)
|
||||
|
||||
/* 400k pull-up3 */
|
||||
#define PM5100_ADC5_GEN3_AMUX1_THM_400K_PU (PM5100_SID << 8 | 0x64)
|
||||
#define PM5100_ADC5_GEN3_BAT_ID_400K_PU (PM5100_SID << 8 | 0x65)
|
||||
#define PM5100_ADC5_GEN3_BATT_THM_400K_PU (PM5100_SID << 8 | 0x66)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_THM_400K_PU (PM5100_SID << 8 | 0x67)
|
||||
#define PM5100_ADC5_GEN3_AMUX5_THM_400K_PU (PM5100_SID << 8 | 0x68)
|
||||
#define PM5100_ADC5_GEN3_AMUX6_THM_400K_PU (PM5100_SID << 8 | 0x69)
|
||||
#define PM5100_ADC5_GEN3_AMUX1_GPIO10_400K_PU (PM5100_SID << 8 | 0x6a)
|
||||
#define PM5100_ADC5_GEN3_AMUX2_GPIO11_400K_PU (PM5100_SID << 8 | 0x6b)
|
||||
#define PM5100_ADC5_GEN3_AMUX3_GPIO_400K_PU (PM5100_SID << 8 | 0x6c)
|
||||
#define PM5100_ADC5_GEN3_AMUX4_GPIO_400K_PU (PM5100_SID << 8 | 0x6d)
|
||||
|
||||
/* 1/3 Divider */
|
||||
#define PM5100_ADC5_GEN3_GPIO10_DIV3 (PM5100_SID << 8 | 0x8a)
|
||||
#define PM5100_ADC5_GEN3_GPIO11_DIV3 (PM5100_SID << 8 | 0x8b)
|
||||
|
||||
#define PM5100_ADC5_GEN3_VPH_PWR (PM5100_SID << 8 | 0x8e)
|
||||
#define PM5100_ADC5_GEN3_VBAT_SNS_QBG (PM5100_SID << 8 | 0x8f)
|
||||
|
||||
#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PM5100_H */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2012-2014,2018-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2014,2018-2021 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_H
|
||||
|
|
@ -300,4 +300,109 @@
|
|||
#define ADC7_SBUx 0x94
|
||||
#define ADC7_VBAT_2S_MID 0x96
|
||||
|
||||
/* ADC channels for PMIC5 Gen3 */
|
||||
|
||||
#define ADC5_GEN3_OFFSET_REF 0x00
|
||||
#define ADC5_GEN3_1P25VREF 0x01
|
||||
#define ADC5_GEN3_VREF_VADC 0x02
|
||||
#define ADC5_GEN3_DIE_TEMP 0x03
|
||||
|
||||
#define ADC5_GEN3_AMUX1_THM 0x04
|
||||
#define ADC5_GEN3_AMUX2_THM 0x05
|
||||
#define ADC5_GEN3_AMUX3_THM 0x06
|
||||
#define ADC5_GEN3_AMUX4_THM 0x07
|
||||
#define ADC5_GEN3_AMUX5_THM 0x08
|
||||
#define ADC5_GEN3_AMUX6_THM 0x09
|
||||
#define ADC5_GEN3_AMUX1_GPIO 0x0a
|
||||
#define ADC5_GEN3_AMUX2_GPIO 0x0b
|
||||
#define ADC5_GEN3_AMUX3_GPIO 0x0c
|
||||
#define ADC5_GEN3_AMUX4_GPIO 0x0d
|
||||
|
||||
#define ADC5_GEN3_CHG_TEMP 0x10
|
||||
#define ADC5_GEN3_USB_SNS_V_16 0x11
|
||||
#define ADC5_GEN3_VIN_DIV16_MUX 0x12
|
||||
#define ADC5_GEN3_VREF_BAT_THERM 0x15
|
||||
#define ADC5_GEN3_IIN_FB 0x17
|
||||
#define ADC5_GEN3_ICHG_SMB 0x18
|
||||
#define ADC5_GEN3_IIN_SMB 0x19
|
||||
#define ADC5_GEN3_ICHG_FB 0xa1
|
||||
|
||||
/* 30k pull-up1 */
|
||||
#define ADC5_GEN3_AMUX1_THM_30K_PU 0x24
|
||||
#define ADC5_GEN3_AMUX2_THM_30K_PU 0x25
|
||||
#define ADC5_GEN3_AMUX3_THM_30K_PU 0x26
|
||||
#define ADC5_GEN3_AMUX4_THM_30K_PU 0x27
|
||||
#define ADC5_GEN3_AMUX5_THM_30K_PU 0x28
|
||||
#define ADC5_GEN3_AMUX6_THM_30K_PU 0x29
|
||||
#define ADC5_GEN3_AMUX1_GPIO_30K_PU 0x2a
|
||||
#define ADC5_GEN3_AMUX2_GPIO_30K_PU 0x2b
|
||||
#define ADC5_GEN3_AMUX3_GPIO_30K_PU 0x2c
|
||||
#define ADC5_GEN3_AMUX4_GPIO_30K_PU 0x2d
|
||||
|
||||
/* 100k pull-up2 */
|
||||
#define ADC5_GEN3_AMUX1_THM_100K_PU 0x44
|
||||
#define ADC5_GEN3_AMUX2_THM_100K_PU 0x45
|
||||
#define ADC5_GEN3_AMUX3_THM_100K_PU 0x46
|
||||
#define ADC5_GEN3_AMUX4_THM_100K_PU 0x47
|
||||
#define ADC5_GEN3_AMUX5_THM_100K_PU 0x48
|
||||
#define ADC5_GEN3_AMUX6_THM_100K_PU 0x49
|
||||
#define ADC5_GEN3_AMUX1_GPIO_100K_PU 0x4a
|
||||
#define ADC5_GEN3_AMUX2_GPIO_100K_PU 0x4b
|
||||
#define ADC5_GEN3_AMUX3_GPIO_100K_PU 0x4c
|
||||
#define ADC5_GEN3_AMUX4_GPIO_100K_PU 0x4d
|
||||
|
||||
/* 400k pull-up3 */
|
||||
#define ADC5_GEN3_AMUX1_THM_400K_PU 0x64
|
||||
#define ADC5_GEN3_AMUX2_THM_400K_PU 0x65
|
||||
#define ADC5_GEN3_AMUX3_THM_400K_PU 0x66
|
||||
#define ADC5_GEN3_AMUX4_THM_400K_PU 0x67
|
||||
#define ADC5_GEN3_AMUX5_THM_400K_PU 0x68
|
||||
#define ADC5_GEN3_AMUX6_THM_400K_PU 0x69
|
||||
#define ADC5_GEN3_AMUX1_GPIO_400K_PU 0x6a
|
||||
#define ADC5_GEN3_AMUX2_GPIO_400K_PU 0x6b
|
||||
#define ADC5_GEN3_AMUX3_GPIO_400K_PU 0x6c
|
||||
#define ADC5_GEN3_AMUX4_GPIO_400K_PU 0x6d
|
||||
|
||||
/* 1/3 Divider */
|
||||
#define ADC5_GEN3_AMUX1_GPIO_DIV3 0x8a
|
||||
#define ADC5_GEN3_AMUX2_GPIO_DIV3 0x8b
|
||||
#define ADC5_GEN3_AMUX3_GPIO_DIV3 0x8c
|
||||
|
||||
#define ADC5_GEN3_VPH_PWR 0x8e
|
||||
#define ADC5_GEN3_VBAT_SNS_QBG 0x8f
|
||||
|
||||
#define ADC5_GEN3_VBAT_SNS_CHGR 0x94
|
||||
#define ADC5_GEN3_VBAT_2S_MID_QBG 0x96
|
||||
#define ADC5_GEN3_VBAT_2S_MID_CHGR 0x9d
|
||||
|
||||
#define ADC5_OFFSET_EXT2 0xf8
|
||||
|
||||
/* VADC scale function index */
|
||||
#define ADC_SCALE_DEFAULT 0
|
||||
#define ADC_SCALE_THERM_100K_PULLUP 1
|
||||
#define ADC_SCALE_PMIC_THERM 2
|
||||
#define ADC_SCALE_XOTHERM 3
|
||||
#define ADC_SCALE_PMI_CHG_TEMP 4
|
||||
#define ADC_SCALE_HW_CALIB_DEFAULT 5
|
||||
#define ADC_SCALE_HW_CALIB_THERM_100K_PULLUP 6
|
||||
#define ADC_SCALE_HW_CALIB_XOTHERM 7
|
||||
#define ADC_SCALE_HW_CALIB_THERM_100K_PU_PM7 8
|
||||
#define ADC_SCALE_HW_CALIB_PMIC_THERM 9
|
||||
#define ADC_SCALE_HW_CALIB_PMIC_THERM_PM7 10
|
||||
#define ADC_SCALE_HW_CALIB_PM5_CHG_TEMP 11
|
||||
#define ADC_SCALE_HW_CALIB_PM5_SMB_TEMP 12
|
||||
#define ADC_SCALE_HW_CALIB_BATT_THERM_100K 13
|
||||
#define ADC_SCALE_HW_CALIB_BATT_THERM_30K 14
|
||||
#define ADC_SCALE_HW_CALIB_BATT_THERM_400K 15
|
||||
#define ADC_SCALE_HW_CALIB_PM5_SMB1398_TEMP 16
|
||||
#define ADC_SCALE_HW_CALIB_PM7_SMB_TEMP 17
|
||||
#define ADC_SCALE_HW_CALIB_PM7_CHG_TEMP 18
|
||||
#define ADC_SCALE_HW_CALIB_CUR 19
|
||||
#define ADC_SCALE_HW_CALIB_CUR_RAW 20
|
||||
#define ADC_SCALE_HW_CALIB_PM2250_S3_DIE_TEMP 21
|
||||
#define ADC_SCALE_HW_CALIB_PM5_CUR 22
|
||||
#define ADC_SCALE_HW_CALIB_PM5_GEN3_BATT_THERM_100K 23
|
||||
#define ADC_SCALE_HW_CALIB_PM5_GEN3_BATT_ID_100K 24
|
||||
#define ADC_SCALE_HW_CALIB_PM5_GEN3_USB_IN_I 25
|
||||
|
||||
#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_H */
|
||||
|
|
|
|||
102
include/linux/adc-tm-clients.h
Normal file
102
include/linux/adc-tm-clients.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __QCOM_ADC_TM_H_CLIENTS__
|
||||
#define __QCOM_ADC_TM_H_CLIENTS__
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct adc_tm_chip;
|
||||
struct adc5_chip;
|
||||
|
||||
/**
|
||||
* enum adc_tm_state - This lets the client know whether the threshold
|
||||
* that was crossed was high/low.
|
||||
* %ADC_TM_HIGH_STATE: Client is notified of crossing the requested high
|
||||
* voltage threshold.
|
||||
* %ADC_TM_COOL_STATE: Client is notified of crossing the requested cool
|
||||
* temperature threshold.
|
||||
* %ADC_TM_LOW_STATE: Client is notified of crossing the requested low
|
||||
* voltage threshold.
|
||||
* %ADC_TM_WARM_STATE: Client is notified of crossing the requested high
|
||||
* temperature threshold.
|
||||
*/
|
||||
enum adc_tm_state {
|
||||
ADC_TM_HIGH_STATE = 0,
|
||||
ADC_TM_COOL_STATE = ADC_TM_HIGH_STATE,
|
||||
ADC_TM_LOW_STATE,
|
||||
ADC_TM_WARM_STATE = ADC_TM_LOW_STATE,
|
||||
ADC_TM_STATE_NUM,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum adc_tm_state_request - Request to enable/disable the corresponding
|
||||
* high/low voltage/temperature thresholds.
|
||||
* %ADC_TM_HIGH_THR_ENABLE: Enable high voltage threshold.
|
||||
* %ADC_TM_COOL_THR_ENABLE = Enables cool temperature threshold.
|
||||
* %ADC_TM_LOW_THR_ENABLE: Enable low voltage/temperature threshold.
|
||||
* %ADC_TM_WARM_THR_ENABLE = Enables warm temperature threshold.
|
||||
* %ADC_TM_HIGH_LOW_THR_ENABLE: Enable high and low voltage/temperature
|
||||
* threshold.
|
||||
* %ADC_TM_HIGH_THR_DISABLE: Disable high voltage/temperature threshold.
|
||||
* %ADC_TM_COOL_THR_ENABLE = Disables cool temperature threshold.
|
||||
* %ADC_TM_LOW_THR_DISABLE: Disable low voltage/temperature threshold.
|
||||
* %ADC_TM_WARM_THR_ENABLE = Disables warm temperature threshold.
|
||||
* %ADC_TM_HIGH_THR_DISABLE: Disable high and low voltage/temperature
|
||||
* threshold.
|
||||
*/
|
||||
enum adc_tm_state_request {
|
||||
ADC_TM_HIGH_THR_ENABLE = 0,
|
||||
ADC_TM_COOL_THR_ENABLE = ADC_TM_HIGH_THR_ENABLE,
|
||||
ADC_TM_LOW_THR_ENABLE,
|
||||
ADC_TM_WARM_THR_ENABLE = ADC_TM_LOW_THR_ENABLE,
|
||||
ADC_TM_HIGH_LOW_THR_ENABLE,
|
||||
ADC_TM_HIGH_THR_DISABLE,
|
||||
ADC_TM_COOL_THR_DISABLE = ADC_TM_HIGH_THR_DISABLE,
|
||||
ADC_TM_LOW_THR_DISABLE,
|
||||
ADC_TM_WARM_THR_DISABLE = ADC_TM_LOW_THR_DISABLE,
|
||||
ADC_TM_HIGH_LOW_THR_DISABLE,
|
||||
ADC_TM_THR_NUM,
|
||||
};
|
||||
|
||||
struct adc_tm_param {
|
||||
unsigned long id;
|
||||
int low_thr;
|
||||
int high_thr;
|
||||
uint32_t channel;
|
||||
enum adc_tm_state_request state_request;
|
||||
void *btm_ctx;
|
||||
void (*threshold_notification)(enum adc_tm_state state,
|
||||
void *ctx);
|
||||
};
|
||||
|
||||
struct device;
|
||||
|
||||
/* Public API */
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_SPMI_ADC5_GEN3)
|
||||
struct adc5_chip *get_adc_tm_gen3(struct device *dev, const char *name);
|
||||
int32_t adc_tm_channel_measure_gen3(struct adc5_chip *chip,
|
||||
struct adc_tm_param *param);
|
||||
int32_t adc_tm_disable_chan_meas_gen3(struct adc5_chip *chip,
|
||||
struct adc_tm_param *param);
|
||||
#else
|
||||
static inline struct adc5_chip *get_adc_tm_gen3(
|
||||
struct device *dev, const char *name)
|
||||
{ return ERR_PTR(-ENXIO); }
|
||||
|
||||
static inline int32_t adc_tm_channel_measure_gen3(
|
||||
struct adc5_chip *chip,
|
||||
struct adc_tm_param *param)
|
||||
{ return -ENXIO; }
|
||||
static inline int32_t adc_tm_disable_chan_meas_gen3(
|
||||
struct adc5_chip *chip,
|
||||
struct adc_tm_param *param)
|
||||
{ return -ENXIO; }
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __QCOM_ADC_TM_H_CLIENTS__ */
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef QCOM_VADC_COMMON_H
|
||||
#define QCOM_VADC_COMMON_H
|
||||
|
||||
#include <linux/adc-tm-clients.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
|
@ -47,6 +48,9 @@
|
|||
#define PMIC5_SMB1398_TEMP_CONSTANT 268235
|
||||
#define PMIC5_SMB1398_TEMP_SCALE_FACTOR 340
|
||||
|
||||
#define PMIC5_PM2250_S3_DIE_TEMP_SCALE_FACTOR 187263
|
||||
#define PMIC5_PM2250_S3_DIE_TEMP_CONSTANT 720100
|
||||
|
||||
#define PMI_CHG_SCALE_1 -138890
|
||||
#define PMI_CHG_SCALE_2 391750000000LL
|
||||
|
||||
|
|
@ -57,6 +61,10 @@
|
|||
#define R_PU_100K 100000
|
||||
#define RATIO_MAX_ADC7 BIT(14)
|
||||
|
||||
#define PMIC5_GEN3_USB_IN_I_SCALE_FACTOR 9248
|
||||
|
||||
#define ADC_VDD_REF 1875000
|
||||
|
||||
/*
|
||||
* VADC_CALIB_ABSOLUTE: uses the 625mV and 1.25V as reference channels.
|
||||
* VADC_CALIB_RATIOMETRIC: uses the reference voltage (1.8V) and GND for
|
||||
|
|
@ -82,6 +90,54 @@ struct vadc_linear_graph {
|
|||
s32 gnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum adc_tm_rscale_fn_type - Scaling function used to convert the
|
||||
* channels input voltage/temperature to corresponding ADC code that is
|
||||
* applied for thresholds. Check the corresponding channels scaling to
|
||||
* determine the appropriate temperature/voltage units that are passed
|
||||
* to the scaling function. Example battery follows the power supply
|
||||
* framework that needs its units to be in decidegreesC so it passes
|
||||
* deci-degreesC. PA_THERM clients pass the temperature in degrees.
|
||||
* The order below should match the one in the driver for
|
||||
* adc_tm_rscale_fn[].
|
||||
*/
|
||||
enum adc_tm_rscale_fn_type {
|
||||
SCALE_R_ABSOLUTE = 0,
|
||||
SCALE_RSCALE_NONE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct adc_tm_config - Represent ADC Thermal Monitor configuration.
|
||||
* @high_thr_temp: Temperature at which high threshold notification is required.
|
||||
* @low_thr_temp: Temperature at which low threshold notification is required.
|
||||
* @low_thr_voltage : Low threshold voltage ADC code used for reverse
|
||||
* calibration.
|
||||
* @high_thr_voltage: High threshold voltage ADC code used for reverse
|
||||
* calibration.
|
||||
*/
|
||||
struct adc_tm_config {
|
||||
int high_thr_temp;
|
||||
int low_thr_temp;
|
||||
int64_t high_thr_voltage;
|
||||
int64_t low_thr_voltage;
|
||||
};
|
||||
|
||||
struct adc_tm_reverse_scale_fn {
|
||||
int32_t (*chan)(struct adc_tm_config *tm_config);
|
||||
};
|
||||
|
||||
struct adc_tm_client_info {
|
||||
struct list_head list;
|
||||
struct adc_tm_param *param;
|
||||
int32_t low_thr_requested;
|
||||
int32_t high_thr_requested;
|
||||
bool notify_low_thr;
|
||||
bool notify_high_thr;
|
||||
bool high_thr_set;
|
||||
bool low_thr_set;
|
||||
enum adc_tm_state_request state_request;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum vadc_scale_fn_type - Scaling function to convert ADC code to
|
||||
* physical scaled units for the channel.
|
||||
|
|
@ -107,13 +163,13 @@ struct vadc_linear_graph {
|
|||
* charger temperature.
|
||||
* SCALE_HW_CALIB_PM5_SMB_TEMP: Returns result in millidegrees for PMIC5
|
||||
* SMB1390 temperature.
|
||||
* SCALE_HW_CALIB_BATT_THERM_100K: Returns battery thermistor voltage in
|
||||
* SCALE_HW_CALIB_BATT_THERM_100K: Returns battery thermistor temperature in
|
||||
* decidegC using 100k pullup. The hardware applies offset/slope to adc
|
||||
* code.
|
||||
* SCALE_HW_CALIB_BATT_THERM_30K: Returns battery thermistor voltage in
|
||||
* SCALE_HW_CALIB_BATT_THERM_30K: Returns battery thermistor temperature in
|
||||
* decidegC using 30k pullup. The hardware applies offset/slope to adc
|
||||
* code.
|
||||
* SCALE_HW_CALIB_BATT_THERM_400K: Returns battery thermistor voltage in
|
||||
* SCALE_HW_CALIB_BATT_THERM_400K: Returns battery thermistor temperature in
|
||||
* decidegC using 400k pullup. The hardware applies offset/slope to adc
|
||||
* code.
|
||||
* SCALE_HW_CALIB_PM5_SMB1398_TEMP: Returns result in millidegrees for PMIC5
|
||||
|
|
@ -126,6 +182,17 @@ struct vadc_linear_graph {
|
|||
* use voltage scaling.
|
||||
* SCALE_HW_CALIB_CUR_RAW: Returns result in microamperes for PMIC7 channels
|
||||
* that use raw ADC code.
|
||||
* SCALE_HW_CALIB_PM2250_S3_DIE_TEMP: Returns result in millidegrees for
|
||||
* S3 die temperature channel on PM2250.
|
||||
* SCALE_HW_CALIB_PM5_CUR: Returns result in microamperes for PMIC5 channels
|
||||
* that use voltage scaling.
|
||||
* SCALE_HW_CALIB_PM5_GEN3_BATT_THERM_100K: Returns battery thermistor
|
||||
* temperature in decidegC using 100k pullup. The hardware applies
|
||||
* offset/slope to adc code.
|
||||
* SCALE_HW_CALIB_PM5_GEN3_BATT_ID_100K: Returns battery ID resistance
|
||||
* in ohms using 100k pullup. The hardware applies offset/slope to
|
||||
* adc code.
|
||||
* SCALE_HW_CALIB_PM5_GEN3_USB_IN_I: Returns USB input current in microamperes.
|
||||
*/
|
||||
enum vadc_scale_fn_type {
|
||||
SCALE_DEFAULT = 0,
|
||||
|
|
@ -149,10 +216,16 @@ enum vadc_scale_fn_type {
|
|||
SCALE_HW_CALIB_PM7_CHG_TEMP,
|
||||
SCALE_HW_CALIB_CUR,
|
||||
SCALE_HW_CALIB_CUR_RAW,
|
||||
SCALE_HW_CALIB_PM2250_S3_DIE_TEMP,
|
||||
SCALE_HW_CALIB_PM5_CUR,
|
||||
SCALE_HW_CALIB_PM5_GEN3_BATT_THERM_100K,
|
||||
SCALE_HW_CALIB_PM5_GEN3_BATT_ID_100K,
|
||||
SCALE_HW_CALIB_PM5_GEN3_USB_IN_I,
|
||||
SCALE_HW_CALIB_INVALID,
|
||||
};
|
||||
|
||||
struct adc5_data {
|
||||
const char *name;
|
||||
const u32 full_scale_code_volt;
|
||||
const u32 full_scale_code_cur;
|
||||
const struct adc5_channels *adc_chans;
|
||||
|
|
@ -191,4 +264,8 @@ int qcom_adc5_decimation_from_dt(u32 value, const unsigned int *decimation);
|
|||
|
||||
int qcom_vadc_decimation_from_dt(u32 value);
|
||||
|
||||
void adc_tm_scale_therm_voltage_100k_gen3(struct adc_tm_config *param);
|
||||
|
||||
int32_t adc_tm_absolute_rthr_gen3(struct adc_tm_config *tm_config);
|
||||
|
||||
#endif /* QCOM_VADC_COMMON_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user