linux/drivers/iio/adc/mt6359-auxadc.c
AngeloGioacchino Del Regno 1a4deda6c6 iio: adc: mt6359: Add support for MediaTek MT6373 PMIC AUXADC
MediaTek MT6373 is a PMIC found on MT8196/MT6991 board designs
and communicates with the SoC over SPMI.

This PMIC integrates an Auxiliary ADC (AUXADC) which has a grand
total of 54 channels, of which usually only 9 are used as this
is usually paired with MT6363 on the same board.

For the Auxiliary ADC part, this reuses the same register layout
as the MT6363 PMIC, but exposes only a subset of the ADC chans.

Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Link: https://patch.msgid.link/20250703141146.171431-7-angelogioacchino.delregno@collabora.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2025-07-13 15:36:26 +01:00

908 lines
32 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* MediaTek MT6359 PMIC AUXADC IIO driver
*
* Copyright (c) 2021 MediaTek Inc.
* Copyright (c) 2024 Collabora Ltd
* Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/iio/iio.h>
#include <linux/mfd/mt6397/core.h>
#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 IMP_STOP_DELAY_US 150
#define IMP_POLL_DELAY_US 1000
/* For PMIC_RG_RESET_VAL and MT6358_IMP0_CLEAR, the bits specific purpose is unknown. */
#define PMIC_RG_RESET_VAL (BIT(0) | BIT(3))
#define PMIC_AUXADC_RDY_BIT BIT(15)
#define MT6357_IMP_ADC_NUM 30
#define MT6358_IMP_ADC_NUM 28
#define MT6358_DCM_CK_SW_EN GENMASK(1, 0)
#define MT6358_IMP0_CLEAR (BIT(14) | BIT(7))
#define MT6358_IMP0_IRQ_RDY BIT(8)
#define MT6358_IMP1_AUTOREPEAT_EN BIT(15)
#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,
PMIC_AUXADC_IMP0,
PMIC_AUXADC_IMP1,
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,
PMIC_AUXADC_REGS_MAX
};
enum mtk_pmic_auxadc_channels {
PMIC_AUXADC_CHAN_BATADC,
PMIC_AUXADC_CHAN_ISENSE,
PMIC_AUXADC_CHAN_VCDT,
PMIC_AUXADC_CHAN_BAT_TEMP,
PMIC_AUXADC_CHAN_BATID,
PMIC_AUXADC_CHAN_CHIP_TEMP,
PMIC_AUXADC_CHAN_VCORE_TEMP,
PMIC_AUXADC_CHAN_VPROC_TEMP,
PMIC_AUXADC_CHAN_VGPU_TEMP,
PMIC_AUXADC_CHAN_ACCDET,
PMIC_AUXADC_CHAN_VDCXO,
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
};
/**
* struct mt6359_auxadc - Main driver structure
* @dev: Device pointer
* @regmap: Regmap from SoC PMIC Wrapper
* @chip_info: PMIC specific chip info
* @lock: Mutex to serialize AUXADC reading vs configuration
* @timed_out: Signals whether the last read timed out
*/
struct mt6359_auxadc {
struct device *dev;
struct regmap *regmap;
const struct mtk_pmic_auxadc_info *chip_info;
struct mutex lock;
bool timed_out;
};
/**
* 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;
};
/**
* struct mtk_pmic_auxadc_info - PMIC specific chip info
* @model_name: PMIC model name
* @channels: IIO specification of ADC channels
* @num_channels: Number of ADC channels
* @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 {
const char *model_name;
const struct iio_chan_spec *channels;
u8 num_channels;
const struct mtk_pmic_auxadc_chan *desc;
const u16 *regs;
u16 sec_unlock_key;
u32 vref_mV;
u8 imp_adc_num;
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_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, \
.channel = _model##_AUXADC_##_ch_idx, \
.address = _adc_idx, \
.scan_index = PMIC_AUXADC_CHAN_##_ch_idx, \
.datasheet_name = __stringify(_name), \
.scan_type = { \
.sign = 'u', \
.realbits = _nbits, \
.storagebits = 16, \
.endianness = IIO_CPU \
}, \
.indexed = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec mt6357_auxadc_channels[] = {
MTK_PMIC_IIO_CHAN(MT6357, bat_adc, BATADC, 0, 15, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6357, isense, ISENSE, 1, 12, IIO_CURRENT),
MTK_PMIC_IIO_CHAN(MT6357, cdt_v, VCDT, 2, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6357, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6357, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6357, acc_det, ACCDET, 5, 12, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6357, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE),
MTK_PMIC_IIO_CHAN(MT6357, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6357, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6357, dcxo_temp, DCXO_TEMP, 36, 15, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6357, vcore_temp, VCORE_TEMP, 40, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6357, vproc_temp, VPROC_TEMP, 41, 12, IIO_TEMP),
/* Battery impedance channels */
MTK_PMIC_IIO_CHAN(MT6357, batt_v, VBAT, 0, 15, IIO_VOLTAGE),
};
static const struct mtk_pmic_auxadc_chan mt6357_auxadc_ch_desc[] = {
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, PMIC_AUXADC_IMP0, 8, 128, 3, 1),
};
static const u16 mt6357_auxadc_regs[] = {
[PMIC_HK_TOP_RST_CON0] = 0x0f90,
[PMIC_AUXADC_DCM_CON] = 0x122e,
[PMIC_AUXADC_ADC0] = 0x1088,
[PMIC_AUXADC_IMP0] = 0x119c,
[PMIC_AUXADC_IMP1] = 0x119e,
[PMIC_AUXADC_RQST0] = 0x110e,
[PMIC_AUXADC_RQST1] = 0x1114,
};
static const struct iio_chan_spec mt6358_auxadc_channels[] = {
MTK_PMIC_IIO_CHAN(MT6358, bat_adc, BATADC, 0, 15, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6358, cdt_v, VCDT, 2, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6358, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6358, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6358, acc_det, ACCDET, 5, 12, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6358, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE),
MTK_PMIC_IIO_CHAN(MT6358, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6358, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6358, dcxo_temp, DCXO_TEMP, 10, 15, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6358, bif_v, VBIF, 11, 12, IIO_VOLTAGE),
MTK_PMIC_IIO_CHAN(MT6358, vcore_temp, VCORE_TEMP, 38, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6358, vproc_temp, VPROC_TEMP, 39, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6358, vgpu_temp, VGPU_TEMP, 40, 12, IIO_TEMP),
/* Battery impedance channels */
MTK_PMIC_IIO_CHAN(MT6358, batt_v, VBAT, 0, 15, IIO_VOLTAGE),
};
static const struct mtk_pmic_auxadc_chan mt6358_auxadc_ch_desc[] = {
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, PMIC_AUXADC_IMP0, 8, 128, 7, 2),
};
static const u16 mt6358_auxadc_regs[] = {
[PMIC_HK_TOP_RST_CON0] = 0x0f90,
[PMIC_AUXADC_DCM_CON] = 0x1260,
[PMIC_AUXADC_ADC0] = 0x1088,
[PMIC_AUXADC_IMP0] = 0x1208,
[PMIC_AUXADC_IMP1] = 0x120a,
[PMIC_AUXADC_RQST0] = 0x1108,
[PMIC_AUXADC_RQST1] = 0x110a,
};
static const struct iio_chan_spec mt6359_auxadc_channels[] = {
MTK_PMIC_IIO_CHAN(MT6359, bat_adc, BATADC, 0, 15, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6359, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6359, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6359, acc_det, ACCDET, 5, 12, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6359, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE),
MTK_PMIC_IIO_CHAN(MT6359, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6359, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE),
MTK_PMIC_IIO_CHAN(MT6359, dcxo_temp, DCXO_TEMP, 10, 15, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6359, bif_v, VBIF, 11, 12, IIO_VOLTAGE),
MTK_PMIC_IIO_CHAN(MT6359, vcore_temp, VCORE_TEMP, 30, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6359, vproc_temp, VPROC_TEMP, 31, 12, IIO_TEMP),
MTK_PMIC_IIO_CHAN(MT6359, vgpu_temp, VGPU_TEMP, 32, 12, IIO_TEMP),
/* Battery impedance channels */
MTK_PMIC_IIO_CHAN(MT6359, batt_v, VBAT, 0, 15, IIO_VOLTAGE),
MTK_PMIC_IIO_CHAN(MT6359, batt_i, IBAT, 0, 15, IIO_CURRENT),
};
static const struct mtk_pmic_auxadc_chan mt6359_auxadc_ch_desc[] = {
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, 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[] = {
[PMIC_FGADC_R_CON0] = 0x0d88,
[PMIC_HK_TOP_WKEY] = 0x0fb4,
[PMIC_HK_TOP_RST_CON0] = 0x0f90,
[PMIC_AUXADC_RQST0] = 0x1108,
[PMIC_AUXADC_RQST1] = 0x110a,
[PMIC_AUXADC_ADC0] = 0x1088,
[PMIC_AUXADC_IMP0] = 0x1208,
[PMIC_AUXADC_IMP1] = 0x120a,
[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;
struct regmap *regmap = adc_dev->regmap;
regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6358_IMP0_CLEAR);
regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6358_IMP0_CLEAR);
regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP1], MT6358_IMP1_AUTOREPEAT_EN);
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, 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;
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(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);
return ret;
}
return 0;
}
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;
u16 reg_adc0 = cinfo->regs[PMIC_AUXADC_ADC0];
u32 val_v;
int ret;
ret = mt6358_start_imp_conv(adc_dev, chan);
if (ret)
return ret;
/* Read the params before stopping */
regmap_read(regmap, reg_adc0 + (cinfo->imp_adc_num << 1), &val_v);
mt6358_stop_imp_conv(adc_dev);
if (vbat)
*vbat = val_v;
if (ibat)
*ibat = 0;
return 0;
}
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[desc->rdy_idx],
val, val & desc->rdy_mask,
IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US);
/* Stop conversion regardless of the result */
regmap_write(regmap, cinfo->regs[PMIC_AUXADC_IMP0], 0);
if (ret)
return ret;
/* If it succeeded, wait for the registers to be populated */
fsleep(IMP_STOP_DELAY_US);
ret = regmap_read(regmap, cinfo->regs[PMIC_AUXADC_IMP3], &val_v);
if (ret)
return ret;
ret = regmap_read(regmap, cinfo->regs[PMIC_FGADC_R_CON0], &val_i);
if (ret)
return ret;
if (vbat)
*vbat = val_v;
if (ibat)
*ibat = val_i;
return 0;
}
static const struct mtk_pmic_auxadc_info mt6357_chip_info = {
.model_name = "MT6357",
.channels = mt6357_auxadc_channels,
.num_channels = ARRAY_SIZE(mt6357_auxadc_channels),
.desc = mt6357_auxadc_ch_desc,
.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 = {
.model_name = "MT6358",
.channels = mt6358_auxadc_channels,
.num_channels = ARRAY_SIZE(mt6358_auxadc_channels),
.desc = mt6358_auxadc_ch_desc,
.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 = {
.model_name = "MT6359",
.channels = mt6359_auxadc_channels,
.num_channels = ARRAY_SIZE(mt6359_auxadc_channels),
.desc = mt6359_auxadc_ch_desc,
.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)
{
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);
/* Assert ADC reset */
regmap_set_bits(regmap, cinfo->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL);
/* De-assert ADC reset. No wait required, as pwrap takes care of that for us. */
regmap_clear_bits(regmap, cinfo->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL);
/* Lock HK_TOP writes again */
if (cinfo->sec_unlock_key)
regmap_write(regmap, cinfo->regs[PMIC_HK_TOP_WKEY], 0);
}
/**
* 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 reg, rdy_mask, val, lval;
int ret;
/* Request to start sampling for ADC channel */
ret = regmap_write(regmap, cinfo->regs[desc->req_idx], desc->req_mask);
if (ret)
return ret;
/* Wait until all samples are averaged */
fsleep(desc->num_samples * AUXADC_AVG_TIME_US);
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;
/* ...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;
}
static int mt6359_auxadc_read_label(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, char *label)
{
return sysfs_emit(label, "%s\n", chan->datasheet_name);
}
static int mt6359_auxadc_read_raw(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
int *val, int *val2, long mask)
{
struct mt6359_auxadc *adc_dev = iio_priv(indio_dev);
const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;
const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index];
int ret;
if (mask == IIO_CHAN_INFO_SCALE) {
*val = desc->r_ratio.numerator * cinfo->vref_mV;
if (desc->r_ratio.denominator > 1) {
*val2 = desc->r_ratio.denominator;
return IIO_VAL_FRACTIONAL;
}
return IIO_VAL_INT;
}
scoped_guard(mutex, &adc_dev->lock) {
switch (chan->scan_index) {
case PMIC_AUXADC_CHAN_IBAT:
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:
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);
break;
}
}
if (ret) {
/*
* If we get more than one timeout, it's possible that the
* AUXADC is stuck: perform a full reset to recover it.
*/
if (ret == -ETIMEDOUT) {
if (adc_dev->timed_out) {
dev_warn(adc_dev->dev, "Resetting stuck ADC!\r\n");
mt6359_auxadc_reset(adc_dev);
}
adc_dev->timed_out = true;
}
return ret;
}
adc_dev->timed_out = false;
return IIO_VAL_INT;
}
static const struct iio_info mt6359_auxadc_iio_info = {
.read_label = mt6359_auxadc_read_label,
.read_raw = mt6359_auxadc_read_raw,
};
static int mt6359_auxadc_probe(struct platform_device *pdev)
{
const struct mtk_pmic_auxadc_info *chip_info;
struct device *dev = &pdev->dev;
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(regmap_dev, NULL);
if (!regmap)
return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n");
indio_dev = devm_iio_device_alloc(dev, sizeof(*adc_dev));
if (!indio_dev)
return -ENOMEM;
adc_dev = iio_priv(indio_dev);
adc_dev->regmap = regmap;
adc_dev->dev = dev;
adc_dev->chip_info = chip_info;
mutex_init(&adc_dev->lock);
mt6359_auxadc_reset(adc_dev);
indio_dev->name = adc_dev->chip_info->model_name;
indio_dev->info = &mt6359_auxadc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adc_dev->chip_info->channels;
indio_dev->num_channels = adc_dev->chip_info->num_channels;
ret = devm_iio_device_register(dev, indio_dev);
if (ret)
return dev_err_probe(dev, ret, "failed to register iio device\n");
return 0;
}
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);
static struct platform_driver mt6359_auxadc_driver = {
.driver = {
.name = "mt6359-auxadc",
.of_match_table = mt6359_auxadc_of_match,
},
.probe = mt6359_auxadc_probe,
};
module_platform_driver(mt6359_auxadc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
MODULE_DESCRIPTION("MediaTek MT6359 PMIC AUXADC Driver");