summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/mt6359-auxadc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc/mt6359-auxadc.c')
-rw-r--r--drivers/iio/adc/mt6359-auxadc.c442
1 files changed, 372 insertions, 70 deletions
diff --git a/drivers/iio/adc/mt6359-auxadc.c b/drivers/iio/adc/mt6359-auxadc.c
index a4970cfb49a5..f426a289e867 100644
--- a/drivers/iio/adc/mt6359-auxadc.c
+++ b/drivers/iio/adc/mt6359-auxadc.c
@@ -7,6 +7,7 @@
* Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
+#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/delay.h>
@@ -24,11 +25,11 @@
#include <dt-bindings/iio/adc/mediatek,mt6357-auxadc.h>
#include <dt-bindings/iio/adc/mediatek,mt6358-auxadc.h>
#include <dt-bindings/iio/adc/mediatek,mt6359-auxadc.h>
+#include <dt-bindings/iio/adc/mediatek,mt6363-auxadc.h>
#define AUXADC_AVG_TIME_US 10
#define AUXADC_POLL_DELAY_US 100
#define AUXADC_TIMEOUT_US 32000
-#define AUXADC_VOLT_FULL 1800
#define IMP_STOP_DELAY_US 150
#define IMP_POLL_DELAY_US 1000
@@ -46,6 +47,12 @@
#define MT6359_IMP0_CONV_EN BIT(0)
#define MT6359_IMP1_IRQ_RDY BIT(15)
+#define MT6363_EXT_CHAN_MASK GENMASK(2, 0)
+#define MT6363_EXT_PURES_MASK GENMASK(4, 3)
+ #define MT6363_PULLUP_RES_100K 0
+ #define MT6363_PULLUP_RES_30K 1
+ #define MT6363_PULLUP_RES_OPEN 3
+
enum mtk_pmic_auxadc_regs {
PMIC_AUXADC_ADC0,
PMIC_AUXADC_DCM_CON,
@@ -54,6 +61,8 @@ enum mtk_pmic_auxadc_regs {
PMIC_AUXADC_IMP3,
PMIC_AUXADC_RQST0,
PMIC_AUXADC_RQST1,
+ PMIC_AUXADC_RQST3,
+ PMIC_AUXADC_SDMADC_CON0,
PMIC_HK_TOP_WKEY,
PMIC_HK_TOP_RST_CON0,
PMIC_FGADC_R_CON0,
@@ -75,7 +84,16 @@ enum mtk_pmic_auxadc_channels {
PMIC_AUXADC_CHAN_TSX_TEMP,
PMIC_AUXADC_CHAN_HPOFS_CAL,
PMIC_AUXADC_CHAN_DCXO_TEMP,
+ PMIC_AUXADC_CHAN_VTREF,
PMIC_AUXADC_CHAN_VBIF,
+ PMIC_AUXADC_CHAN_VSYSSNS,
+ PMIC_AUXADC_CHAN_VIN1,
+ PMIC_AUXADC_CHAN_VIN2,
+ PMIC_AUXADC_CHAN_VIN3,
+ PMIC_AUXADC_CHAN_VIN4,
+ PMIC_AUXADC_CHAN_VIN5,
+ PMIC_AUXADC_CHAN_VIN6,
+ PMIC_AUXADC_CHAN_VIN7,
PMIC_AUXADC_CHAN_IBAT,
PMIC_AUXADC_CHAN_VBAT,
PMIC_AUXADC_CHAN_MAX
@@ -101,12 +119,22 @@ struct mt6359_auxadc {
* struct mtk_pmic_auxadc_chan - PMIC AUXADC channel data
* @req_idx: Request register number
* @req_mask: Bitmask to activate a channel
+ * @rdy_idx: Readiness register number
+ * @rdy_mask: Bitmask to determine channel readiness
+ * @ext_sel_idx: PMIC GPIO channel register number
+ * @ext_sel_ch: PMIC GPIO number
+ * @ext_sel_pu: PMIC GPIO channel pullup resistor selector
* @num_samples: Number of AUXADC samples for averaging
* @r_ratio: Resistance ratio fractional
*/
struct mtk_pmic_auxadc_chan {
u8 req_idx;
u16 req_mask;
+ u8 rdy_idx;
+ u16 rdy_mask;
+ s8 ext_sel_idx;
+ u8 ext_sel_ch;
+ u8 ext_sel_pu;
u16 num_samples;
struct u8_fract r_ratio;
};
@@ -119,7 +147,10 @@ struct mtk_pmic_auxadc_chan {
* @desc: PMIC AUXADC channel data
* @regs: List of PMIC specific registers
* @sec_unlock_key: Security unlock key for HK_TOP writes
+ * @vref_mV: AUXADC Reference Voltage (VREF) in millivolts
* @imp_adc_num: ADC channel for battery impedance readings
+ * @is_spmi: Defines whether this PMIC communicates over SPMI
+ * @no_reset: If true, this PMIC does not support ADC reset
* @read_imp: Callback to read impedance channels
*/
struct mtk_pmic_auxadc_info {
@@ -129,18 +160,34 @@ struct mtk_pmic_auxadc_info {
const struct mtk_pmic_auxadc_chan *desc;
const u16 *regs;
u16 sec_unlock_key;
+ u32 vref_mV;
u8 imp_adc_num;
- int (*read_imp)(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat);
+ bool is_spmi;
+ bool no_reset;
+ int (*read_imp)(struct mt6359_auxadc *adc_dev,
+ const struct iio_chan_spec *chan, int *vbat, int *ibat);
};
-#define MTK_PMIC_ADC_CHAN(_ch_idx, _req_idx, _req_bit, _samples, _rnum, _rdiv) \
+#define MTK_PMIC_ADC_EXT_CHAN(_ch_idx, _req_idx, _req_bit, _rdy_idx, _rdy_bit, \
+ _ext_sel_idx, _ext_sel_ch, _ext_sel_pu, \
+ _samples, _rnum, _rdiv) \
[PMIC_AUXADC_CHAN_##_ch_idx] = { \
.req_idx = _req_idx, \
.req_mask = BIT(_req_bit), \
+ .rdy_idx = _rdy_idx, \
+ .rdy_mask = BIT(_rdy_bit), \
+ .ext_sel_idx = _ext_sel_idx, \
+ .ext_sel_ch = _ext_sel_ch, \
+ .ext_sel_pu = _ext_sel_pu, \
.num_samples = _samples, \
.r_ratio = { _rnum, _rdiv } \
}
+#define MTK_PMIC_ADC_CHAN(_ch_idx, _req_idx, _req_bit, _rdy_idx, _rdy_bit, \
+ _samples, _rnum, _rdiv) \
+ MTK_PMIC_ADC_EXT_CHAN(_ch_idx, _req_idx, _req_bit, _rdy_idx, _rdy_bit, \
+ -1, 0, 0, _samples, _rnum, _rdiv)
+
#define MTK_PMIC_IIO_CHAN(_model, _name, _ch_idx, _adc_idx, _nbits, _ch_type) \
{ \
.type = _ch_type, \
@@ -177,21 +224,21 @@ static const struct iio_chan_spec mt6357_auxadc_channels[] = {
};
static const struct mtk_pmic_auxadc_chan mt6357_auxadc_ch_desc[] = {
- MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 3, 1),
- MTK_PMIC_ADC_CHAN(ISENSE, PMIC_AUXADC_RQST0, 0, 128, 3, 1),
- MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1),
- MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1),
- MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1),
- MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 5, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 6, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP0, 8, 128, 3, 1),
+ MTK_PMIC_ADC_CHAN(ISENSE, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP0, 8, 128, 3, 1),
+ MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, PMIC_AUXADC_IMP0, 8, 128, 1, 1),
+ MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, PMIC_AUXADC_IMP0, 8, 256, 1, 1),
+ MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, PMIC_AUXADC_IMP0, 8, 16, 1, 1),
+ MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 5, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 6, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
/* Battery impedance channels */
- MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 3, 1),
+ MTK_PMIC_ADC_CHAN(VBAT, 0, 0, PMIC_AUXADC_IMP0, 8, 128, 3, 1),
};
static const u16 mt6357_auxadc_regs[] = {
@@ -224,22 +271,22 @@ static const struct iio_chan_spec mt6358_auxadc_channels[] = {
};
static const struct mtk_pmic_auxadc_chan mt6358_auxadc_ch_desc[] = {
- MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 3, 1),
- MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 2, 1),
- MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, 8, 3, 2),
- MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1),
- MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1),
- MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1),
- MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 2, 1),
- MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP0, 8, 128, 3, 1),
+ MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, PMIC_AUXADC_IMP0, 8, 8, 2, 1),
+ MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, PMIC_AUXADC_IMP0, 8, 8, 3, 2),
+ MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, PMIC_AUXADC_IMP0, 8, 128, 1, 1),
+ MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, PMIC_AUXADC_IMP0, 8, 256, 1, 1),
+ MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, PMIC_AUXADC_IMP0, 8, 16, 1, 1),
+ MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, PMIC_AUXADC_IMP0, 8, 8, 2, 1),
+ MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, PMIC_AUXADC_IMP0, 8, 8, 1, 1),
/* Battery impedance channels */
- MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 7, 2),
+ MTK_PMIC_ADC_CHAN(VBAT, 0, 0, PMIC_AUXADC_IMP0, 8, 128, 7, 2),
};
static const u16 mt6358_auxadc_regs[] = {
@@ -272,22 +319,22 @@ static const struct iio_chan_spec mt6359_auxadc_channels[] = {
};
static const struct mtk_pmic_auxadc_chan mt6359_auxadc_ch_desc[] = {
- MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 7, 2),
- MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 5, 2),
- MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, 8, 3, 2),
- MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1),
- MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1),
- MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1),
- MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 5, 2),
- MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP1, 15, 128, 7, 2),
+ MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, PMIC_AUXADC_IMP1, 15, 8, 5, 2),
+ MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, PMIC_AUXADC_IMP1, 15, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, PMIC_AUXADC_IMP1, 15 ,8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, PMIC_AUXADC_IMP1, 15, 8, 3, 2),
+ MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, PMIC_AUXADC_IMP1, 15, 128, 1, 1),
+ MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, PMIC_AUXADC_IMP1, 15, 256, 1, 1),
+ MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, PMIC_AUXADC_IMP1, 15, 16, 1, 1),
+ MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, PMIC_AUXADC_IMP1, 15, 8, 5, 2),
+ MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, PMIC_AUXADC_IMP1, 15, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, PMIC_AUXADC_IMP1, 15, 8, 1, 1),
+ MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, PMIC_AUXADC_IMP1, 15, 8, 1, 1),
/* Battery impedance channels */
- MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 7, 2),
- MTK_PMIC_ADC_CHAN(IBAT, 0, 0, 128, 7, 2),
+ MTK_PMIC_ADC_CHAN(VBAT, 0, 0, PMIC_AUXADC_IMP1, 15, 128, 7, 2),
+ MTK_PMIC_ADC_CHAN(IBAT, 0, 0, PMIC_AUXADC_IMP1, 15, 128, 7, 2),
};
static const u16 mt6359_auxadc_regs[] = {
@@ -302,6 +349,107 @@ static const u16 mt6359_auxadc_regs[] = {
[PMIC_AUXADC_IMP3] = 0x120e,
};
+static const struct iio_chan_spec mt6363_auxadc_channels[] = {
+ MTK_PMIC_IIO_CHAN(MT6363, bat_adc, BATADC, 0, 15, IIO_RESISTANCE),
+ MTK_PMIC_IIO_CHAN(MT6363, cdt_v, VCDT, 2, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, sys_sns_v, VSYSSNS, 6, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, tref_v, VTREF, 11, 12, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, vcore_temp, VCORE_TEMP, 38, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, vproc_temp, VPROC_TEMP, 39, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, vgpu_temp, VGPU_TEMP, 40, 12, IIO_TEMP),
+
+ /* For VIN, ADC12 holds the result depending on which GPIO was activated */
+ MTK_PMIC_IIO_CHAN(MT6363, in1_v, VIN1, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in2_v, VIN2, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in3_v, VIN3, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in4_v, VIN4, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in5_v, VIN5, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in6_v, VIN6, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in7_v, VIN7, 45, 15, IIO_VOLTAGE),
+};
+
+static const struct mtk_pmic_auxadc_chan mt6363_auxadc_ch_desc[] = {
+ MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_ADC0, 15, 64, 4, 1),
+ MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 2, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+ MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, PMIC_AUXADC_ADC0, 15, 32, 3, 2),
+ MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+ MTK_PMIC_ADC_CHAN(VSYSSNS, PMIC_AUXADC_RQST1, 6, PMIC_AUXADC_ADC0, 15, 64, 3, 1),
+ MTK_PMIC_ADC_CHAN(VTREF, PMIC_AUXADC_RQST1, 3, PMIC_AUXADC_ADC0, 15, 32, 3, 2),
+ MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST3, 0, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+ MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST3, 1, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+ MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST3, 2, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+
+ MTK_PMIC_ADC_EXT_CHAN(VIN1,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 1, MT6363_PULLUP_RES_100K, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN2,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 2, MT6363_PULLUP_RES_100K, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN3,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 3, MT6363_PULLUP_RES_100K, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN4,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 4, MT6363_PULLUP_RES_100K, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN5,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 5, MT6363_PULLUP_RES_100K, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN6,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 6, MT6363_PULLUP_RES_100K, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN7,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 7, MT6363_PULLUP_RES_100K, 32, 1, 1),
+};
+
+static const u16 mt6363_auxadc_regs[] = {
+ [PMIC_AUXADC_RQST0] = 0x1108,
+ [PMIC_AUXADC_RQST1] = 0x1109,
+ [PMIC_AUXADC_RQST3] = 0x110c,
+ [PMIC_AUXADC_ADC0] = 0x1088,
+ [PMIC_AUXADC_IMP0] = 0x1208,
+ [PMIC_AUXADC_IMP1] = 0x1209,
+};
+
+static const struct iio_chan_spec mt6373_auxadc_channels[] = {
+ MTK_PMIC_IIO_CHAN(MT6363, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, vcore_temp, VCORE_TEMP, 38, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, vproc_temp, VPROC_TEMP, 39, 12, IIO_TEMP),
+ MTK_PMIC_IIO_CHAN(MT6363, vgpu_temp, VGPU_TEMP, 40, 12, IIO_TEMP),
+
+ /* For VIN, ADC12 holds the result depending on which GPIO was activated */
+ MTK_PMIC_IIO_CHAN(MT6363, in1_v, VIN1, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in2_v, VIN2, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in3_v, VIN3, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in4_v, VIN4, 45, 15, IIO_VOLTAGE),
+ MTK_PMIC_IIO_CHAN(MT6363, in5_v, VIN5, 45, 15, IIO_VOLTAGE),
+};
+
+static const struct mtk_pmic_auxadc_chan mt6373_auxadc_ch_desc[] = {
+ MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+ MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST3, 0, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+ MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST3, 1, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+ MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST3, 2, PMIC_AUXADC_ADC0, 15, 32, 1, 1),
+
+ MTK_PMIC_ADC_EXT_CHAN(VIN1,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 1, MT6363_PULLUP_RES_30K, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN2,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 2, MT6363_PULLUP_RES_OPEN, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN3,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 3, MT6363_PULLUP_RES_OPEN, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN4,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 4, MT6363_PULLUP_RES_OPEN, 32, 1, 1),
+ MTK_PMIC_ADC_EXT_CHAN(VIN5,
+ PMIC_AUXADC_RQST1, 4, PMIC_AUXADC_ADC0, 15,
+ PMIC_AUXADC_SDMADC_CON0, 5, MT6363_PULLUP_RES_OPEN, 32, 1, 1),
+};
+
static void mt6358_stop_imp_conv(struct mt6359_auxadc *adc_dev)
{
const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
@@ -313,9 +461,10 @@ static void mt6358_stop_imp_conv(struct mt6359_auxadc *adc_dev)
regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_DCM_CON], MT6358_DCM_CK_SW_EN);
}
-static int mt6358_start_imp_conv(struct mt6359_auxadc *adc_dev)
+static int mt6358_start_imp_conv(struct mt6359_auxadc *adc_dev, const struct iio_chan_spec *chan)
{
const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
+ const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index];
struct regmap *regmap = adc_dev->regmap;
u32 val;
int ret;
@@ -323,8 +472,8 @@ static int mt6358_start_imp_conv(struct mt6359_auxadc *adc_dev)
regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_DCM_CON], MT6358_DCM_CK_SW_EN);
regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP1], MT6358_IMP1_AUTOREPEAT_EN);
- ret = regmap_read_poll_timeout(adc_dev->regmap, cinfo->regs[PMIC_AUXADC_IMP0],
- val, val & MT6358_IMP0_IRQ_RDY,
+ ret = regmap_read_poll_timeout(regmap, cinfo->regs[desc->rdy_idx],
+ val, val & desc->rdy_mask,
IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US);
if (ret) {
mt6358_stop_imp_conv(adc_dev);
@@ -334,7 +483,8 @@ static int mt6358_start_imp_conv(struct mt6359_auxadc *adc_dev)
return 0;
}
-static int mt6358_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat)
+static int mt6358_read_imp(struct mt6359_auxadc *adc_dev,
+ const struct iio_chan_spec *chan, int *vbat, int *ibat)
{
const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
struct regmap *regmap = adc_dev->regmap;
@@ -342,7 +492,7 @@ static int mt6358_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat)
u32 val_v;
int ret;
- ret = mt6358_start_imp_conv(adc_dev);
+ ret = mt6358_start_imp_conv(adc_dev, chan);
if (ret)
return ret;
@@ -359,17 +509,19 @@ static int mt6358_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat)
return 0;
}
-static int mt6359_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat)
+static int mt6359_read_imp(struct mt6359_auxadc *adc_dev,
+ const struct iio_chan_spec *chan, int *vbat, int *ibat)
{
const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
+ const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index];
struct regmap *regmap = adc_dev->regmap;
u32 val, val_v, val_i;
int ret;
/* Start conversion */
regmap_write(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6359_IMP0_CONV_EN);
- ret = regmap_read_poll_timeout(regmap, cinfo->regs[PMIC_AUXADC_IMP1],
- val, val & MT6359_IMP1_IRQ_RDY,
+ ret = regmap_read_poll_timeout(regmap, cinfo->regs[desc->rdy_idx],
+ val, val & desc->rdy_mask,
IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US);
/* Stop conversion regardless of the result */
@@ -404,6 +556,7 @@ static const struct mtk_pmic_auxadc_info mt6357_chip_info = {
.regs = mt6357_auxadc_regs,
.imp_adc_num = MT6357_IMP_ADC_NUM,
.read_imp = mt6358_read_imp,
+ .vref_mV = 1800,
};
static const struct mtk_pmic_auxadc_info mt6358_chip_info = {
@@ -414,6 +567,7 @@ static const struct mtk_pmic_auxadc_info mt6358_chip_info = {
.regs = mt6358_auxadc_regs,
.imp_adc_num = MT6358_IMP_ADC_NUM,
.read_imp = mt6358_read_imp,
+ .vref_mV = 1800,
};
static const struct mtk_pmic_auxadc_info mt6359_chip_info = {
@@ -424,6 +578,29 @@ static const struct mtk_pmic_auxadc_info mt6359_chip_info = {
.regs = mt6359_auxadc_regs,
.sec_unlock_key = 0x6359,
.read_imp = mt6359_read_imp,
+ .vref_mV = 1800,
+};
+
+static const struct mtk_pmic_auxadc_info mt6363_chip_info = {
+ .model_name = "MT6363",
+ .channels = mt6363_auxadc_channels,
+ .num_channels = ARRAY_SIZE(mt6363_auxadc_channels),
+ .desc = mt6363_auxadc_ch_desc,
+ .regs = mt6363_auxadc_regs,
+ .is_spmi = true,
+ .no_reset = true,
+ .vref_mV = 1840,
+};
+
+static const struct mtk_pmic_auxadc_info mt6373_chip_info = {
+ .model_name = "MT6373",
+ .channels = mt6373_auxadc_channels,
+ .num_channels = ARRAY_SIZE(mt6373_auxadc_channels),
+ .desc = mt6373_auxadc_ch_desc,
+ .regs = mt6363_auxadc_regs,
+ .is_spmi = true,
+ .no_reset = true,
+ .vref_mV = 1840,
};
static void mt6359_auxadc_reset(struct mt6359_auxadc *adc_dev)
@@ -431,6 +608,10 @@ static void mt6359_auxadc_reset(struct mt6359_auxadc *adc_dev)
const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
struct regmap *regmap = adc_dev->regmap;
+ /* Some PMICs do not support reset */
+ if (cinfo->no_reset)
+ return;
+
/* Unlock HK_TOP writes */
if (cinfo->sec_unlock_key)
regmap_write(regmap, cinfo->regs[PMIC_HK_TOP_WKEY], cinfo->sec_unlock_key);
@@ -446,13 +627,29 @@ static void mt6359_auxadc_reset(struct mt6359_auxadc *adc_dev)
regmap_write(regmap, cinfo->regs[PMIC_HK_TOP_WKEY], 0);
}
-static int mt6359_auxadc_read_adc(struct mt6359_auxadc *adc_dev,
- const struct iio_chan_spec *chan, int *out)
+/**
+ * mt6359_auxadc_sample_adc_val() - Start ADC channel sampling and read value
+ * @adc_dev: Main driver structure
+ * @chan: IIO Channel spec for requested ADC
+ * @out: Preallocated variable to store the value read from HW
+ *
+ * This function starts the sampling for an ADC channel, waits until all
+ * of the samples are averaged and then reads the value from the HW.
+ *
+ * Note that the caller must stop the ADC sampling on its own, as this
+ * function *never* stops it.
+ *
+ * Return:
+ * Negative number for error;
+ * Upon success returns zero and writes the read value to *out.
+ */
+static int mt6359_auxadc_sample_adc_val(struct mt6359_auxadc *adc_dev,
+ const struct iio_chan_spec *chan, u32 *out)
{
const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index];
struct regmap *regmap = adc_dev->regmap;
- u32 val;
+ u32 reg, rdy_mask, val, lval;
int ret;
/* Request to start sampling for ADC channel */
@@ -463,16 +660,95 @@ static int mt6359_auxadc_read_adc(struct mt6359_auxadc *adc_dev,
/* Wait until all samples are averaged */
fsleep(desc->num_samples * AUXADC_AVG_TIME_US);
- ret = regmap_read_poll_timeout(regmap,
- cinfo->regs[PMIC_AUXADC_ADC0] + (chan->address << 1),
- val, val & PMIC_AUXADC_RDY_BIT,
+ reg = cinfo->regs[PMIC_AUXADC_ADC0] + (chan->address << 1);
+ rdy_mask = PMIC_AUXADC_RDY_BIT;
+
+ /*
+ * Even though for both PWRAP and SPMI cases the ADC HW signals that
+ * the data is ready by setting AUXADC_RDY_BIT, for SPMI the register
+ * read is only 8 bits long: for this case, the check has to be done
+ * on the ADC(x)_H register (high bits) and the rdy_mask needs to be
+ * shifted to the right by the same 8 bits.
+ */
+ if (cinfo->is_spmi) {
+ rdy_mask >>= 8;
+ reg += 1;
+ }
+
+ ret = regmap_read_poll_timeout(regmap, reg, val, val & rdy_mask,
AUXADC_POLL_DELAY_US, AUXADC_TIMEOUT_US);
+ if (ret) {
+ dev_dbg(adc_dev->dev, "ADC read timeout for chan %lu\n", chan->address);
+ return ret;
+ }
+
+ if (cinfo->is_spmi) {
+ ret = regmap_read(regmap, reg - 1, &lval);
+ if (ret)
+ return ret;
+
+ val = (val << 8) | lval;
+ }
+
+ *out = val;
+ return 0;
+}
+
+static int mt6359_auxadc_read_adc(struct mt6359_auxadc *adc_dev,
+ const struct iio_chan_spec *chan, int *out)
+{
+ const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
+ const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index];
+ struct regmap *regmap = adc_dev->regmap;
+ int ret, adc_stop_err;
+ u8 ext_sel;
+ u32 val;
+
+ if (desc->ext_sel_idx >= 0) {
+ ext_sel = FIELD_PREP(MT6363_EXT_PURES_MASK, desc->ext_sel_pu);
+ ext_sel |= FIELD_PREP(MT6363_EXT_CHAN_MASK, desc->ext_sel_ch);
+
+ ret = regmap_update_bits(regmap, cinfo->regs[desc->ext_sel_idx],
+ MT6363_EXT_PURES_MASK | MT6363_EXT_CHAN_MASK,
+ ext_sel);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Get sampled value, then stop sampling unconditionally; the gathered
+ * value is good regardless of if the ADC could be stopped.
+ *
+ * Note that if the ADC cannot be stopped but sampling was ok, this
+ * function will not return any error, but will set the timed_out
+ * status: this is not critical, as the ADC may auto recover and auto
+ * stop after some time (depending on the PMIC model); if not, the next
+ * read attempt will return -ETIMEDOUT and, for models that support it,
+ * reset will be triggered.
+ */
+ ret = mt6359_auxadc_sample_adc_val(adc_dev, chan, &val);
+
+ adc_stop_err = regmap_write(regmap, cinfo->regs[desc->req_idx], 0);
+ if (adc_stop_err) {
+ dev_warn(adc_dev->dev, "Could not stop the ADC: %d\n,", adc_stop_err);
+ adc_dev->timed_out = true;
+ }
+
+ /* If any sampling error occurred, the retrieved value is invalid */
if (ret)
return ret;
- /* Stop sampling */
- regmap_write(regmap, cinfo->regs[desc->req_idx], 0);
+ /* ...and deactivate the ADC GPIO if previously done */
+ if (desc->ext_sel_idx >= 0) {
+ ext_sel = FIELD_PREP(MT6363_EXT_PURES_MASK, MT6363_PULLUP_RES_OPEN);
+
+ ret = regmap_update_bits(regmap, cinfo->regs[desc->ext_sel_idx],
+ MT6363_EXT_PURES_MASK, ext_sel);
+ if (ret)
+ return ret;
+ }
+ /* Everything went fine, give back the ADC reading */
*out = val & GENMASK(chan->scan_type.realbits - 1, 0);
return 0;
}
@@ -493,7 +769,7 @@ static int mt6359_auxadc_read_raw(struct iio_dev *indio_dev,
int ret;
if (mask == IIO_CHAN_INFO_SCALE) {
- *val = desc->r_ratio.numerator * AUXADC_VOLT_FULL;
+ *val = desc->r_ratio.numerator * cinfo->vref_mV;
if (desc->r_ratio.denominator > 1) {
*val2 = desc->r_ratio.denominator;
@@ -506,10 +782,16 @@ static int mt6359_auxadc_read_raw(struct iio_dev *indio_dev,
scoped_guard(mutex, &adc_dev->lock) {
switch (chan->scan_index) {
case PMIC_AUXADC_CHAN_IBAT:
- ret = adc_dev->chip_info->read_imp(adc_dev, NULL, val);
+ if (!adc_dev->chip_info->read_imp)
+ return -EOPNOTSUPP;
+
+ ret = adc_dev->chip_info->read_imp(adc_dev, chan, NULL, val);
break;
case PMIC_AUXADC_CHAN_VBAT:
- ret = adc_dev->chip_info->read_imp(adc_dev, val, NULL);
+ if (!adc_dev->chip_info->read_imp)
+ return -EOPNOTSUPP;
+
+ ret = adc_dev->chip_info->read_imp(adc_dev, chan, val, NULL);
break;
default:
ret = mt6359_auxadc_read_adc(adc_dev, chan, val);
@@ -543,15 +825,36 @@ static const struct iio_info mt6359_auxadc_iio_info = {
static int mt6359_auxadc_probe(struct platform_device *pdev)
{
+ const struct mtk_pmic_auxadc_info *chip_info;
struct device *dev = &pdev->dev;
- struct device *mt6397_mfd_dev = dev->parent;
+ struct device *mfd_dev = dev->parent;
struct mt6359_auxadc *adc_dev;
struct iio_dev *indio_dev;
+ struct device *regmap_dev;
struct regmap *regmap;
int ret;
+ chip_info = device_get_match_data(dev);
+ if (!chip_info)
+ return -EINVAL;
+ /*
+ * The regmap for this device has to be acquired differently for
+ * SoC PMIC Wrapper and SPMI PMIC cases:
+ *
+ * If this is under SPMI, the regmap comes from the direct parent of
+ * this driver: this_device->parent(mfd).
+ * ... or ...
+ * If this is under the SoC PMIC Wrapper, the regmap comes from the
+ * parent of the MT6397 MFD: this_device->parent(mfd)->parent(pwrap)
+ */
+ if (chip_info->is_spmi)
+ regmap_dev = mfd_dev;
+ else
+ regmap_dev = mfd_dev->parent;
+
+
/* Regmap is from SoC PMIC Wrapper, parent of the mt6397 MFD */
- regmap = dev_get_regmap(mt6397_mfd_dev->parent, NULL);
+ regmap = dev_get_regmap(regmap_dev, NULL);
if (!regmap)
return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n");
@@ -562,10 +865,7 @@ static int mt6359_auxadc_probe(struct platform_device *pdev)
adc_dev = iio_priv(indio_dev);
adc_dev->regmap = regmap;
adc_dev->dev = dev;
-
- adc_dev->chip_info = device_get_match_data(dev);
- if (!adc_dev->chip_info)
- return -EINVAL;
+ adc_dev->chip_info = chip_info;
mutex_init(&adc_dev->lock);
@@ -588,7 +888,9 @@ static const struct of_device_id mt6359_auxadc_of_match[] = {
{ .compatible = "mediatek,mt6357-auxadc", .data = &mt6357_chip_info },
{ .compatible = "mediatek,mt6358-auxadc", .data = &mt6358_chip_info },
{ .compatible = "mediatek,mt6359-auxadc", .data = &mt6359_chip_info },
- { /* sentinel */ }
+ { .compatible = "mediatek,mt6363-auxadc", .data = &mt6363_chip_info },
+ { .compatible = "mediatek,mt6373-auxadc", .data = &mt6373_chip_info },
+ { }
};
MODULE_DEVICE_TABLE(of, mt6359_auxadc_of_match);