diff options
Diffstat (limited to 'drivers/iio/adc/mt6359-auxadc.c')
-rw-r--r-- | drivers/iio/adc/mt6359-auxadc.c | 440 |
1 files changed, 371 insertions, 69 deletions
diff --git a/drivers/iio/adc/mt6359-auxadc.c b/drivers/iio/adc/mt6359-auxadc.c index eecf88b05c6f..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,6 +888,8 @@ 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 }, + { .compatible = "mediatek,mt6363-auxadc", .data = &mt6363_chip_info }, + { .compatible = "mediatek,mt6373-auxadc", .data = &mt6373_chip_info }, { } }; MODULE_DEVICE_TABLE(of, mt6359_auxadc_of_match); |