mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 20:22:08 +02:00
iio: adc: Add QCOM SPMI PMIC5 GEN3 ADC driver
Add support for QCOM SPMI PMIC5 GEN3 ADC driver that supports hardware based offset and gain compensation. The ADC peripheral can measure both voltage and current channels whose input signal is connected to the PMIC ADC AMUX. The PMIC5 GEN3 ADC peripheral uses registers defined in SDAM. The register set and configuration have been refreshed compared to the prior QCOM PMIC7 ADC family. Change-Id: I3512c3c067d9102406aa92c389d66283f0b12103 Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org> [quic_subbaram@quicinc.com: Fixed merge conflicts in qcom-vadc-common.h due to location change; Made changes in qcom-vadc-common.c to re-use existing qcom_vadc_map_temp_voltage(); Added entire include/linux/adc-tm-clients.h as it doesn't exist anymore but needed to compile qcom-spmi-adc5-gen3.c and removed the APIs used when CONFIG_QTI_ADC_TM is enabled.] Signed-off-by: Subbaraman Narayanamurthy <quic_subbaram@quicinc.com> [quic_collinsd@quicinc.com: changed struct vadc_prescale_ratio to struct u32_fract and changed prescale "num" and "den" to "numerator" and "denominator" respectively] Signed-off-by: David Collins <quic_collinsd@quicinc.com>
This commit is contained in:
parent
7945098ab3
commit
9d4f6e0a3a
|
|
@ -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
|
||||
|
|
|
|||
1737
drivers/iio/adc/qcom-spmi-adc5-gen3.c
Normal file
1737
drivers/iio/adc/qcom-spmi-adc5-gen3.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -1139,6 +1139,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,
|
||||
|
|
|
|||
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>
|
||||
|
||||
|
|
@ -60,6 +61,8 @@
|
|||
#define R_PU_100K 100000
|
||||
#define RATIO_MAX_ADC7 BIT(14)
|
||||
|
||||
#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
|
||||
|
|
@ -85,6 +88,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.
|
||||
|
|
@ -201,4 +252,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