brintos

brintos / linux-shallow public Read only

0
0
Text · 19.4 KiB · a4970cf Raw
607 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * MediaTek MT6359 PMIC AUXADC IIO driver4 *5 * Copyright (c) 2021 MediaTek Inc.6 * Copyright (c) 2024 Collabora Ltd7 * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>8 */9 10#include <linux/bits.h>11#include <linux/cleanup.h>12#include <linux/delay.h>13#include <linux/module.h>14#include <linux/mod_devicetable.h>15#include <linux/platform_device.h>16#include <linux/property.h>17#include <linux/regmap.h>18#include <linux/types.h>19 20#include <linux/iio/iio.h>21 22#include <linux/mfd/mt6397/core.h>23 24#include <dt-bindings/iio/adc/mediatek,mt6357-auxadc.h>25#include <dt-bindings/iio/adc/mediatek,mt6358-auxadc.h>26#include <dt-bindings/iio/adc/mediatek,mt6359-auxadc.h>27 28#define AUXADC_AVG_TIME_US		1029#define AUXADC_POLL_DELAY_US		10030#define AUXADC_TIMEOUT_US		3200031#define AUXADC_VOLT_FULL		180032#define IMP_STOP_DELAY_US		15033#define IMP_POLL_DELAY_US		100034 35/* For PMIC_RG_RESET_VAL and MT6358_IMP0_CLEAR, the bits specific purpose is unknown. */36#define PMIC_RG_RESET_VAL		(BIT(0) | BIT(3))37#define PMIC_AUXADC_RDY_BIT		BIT(15)38#define MT6357_IMP_ADC_NUM		3039#define MT6358_IMP_ADC_NUM		2840 41#define MT6358_DCM_CK_SW_EN		GENMASK(1, 0)42#define MT6358_IMP0_CLEAR		(BIT(14) | BIT(7))43#define MT6358_IMP0_IRQ_RDY		BIT(8)44#define MT6358_IMP1_AUTOREPEAT_EN	BIT(15)45 46#define MT6359_IMP0_CONV_EN		BIT(0)47#define MT6359_IMP1_IRQ_RDY		BIT(15)48 49enum mtk_pmic_auxadc_regs {50	PMIC_AUXADC_ADC0,51	PMIC_AUXADC_DCM_CON,52	PMIC_AUXADC_IMP0,53	PMIC_AUXADC_IMP1,54	PMIC_AUXADC_IMP3,55	PMIC_AUXADC_RQST0,56	PMIC_AUXADC_RQST1,57	PMIC_HK_TOP_WKEY,58	PMIC_HK_TOP_RST_CON0,59	PMIC_FGADC_R_CON0,60	PMIC_AUXADC_REGS_MAX61};62 63enum mtk_pmic_auxadc_channels {64	PMIC_AUXADC_CHAN_BATADC,65	PMIC_AUXADC_CHAN_ISENSE,66	PMIC_AUXADC_CHAN_VCDT,67	PMIC_AUXADC_CHAN_BAT_TEMP,68	PMIC_AUXADC_CHAN_BATID,69	PMIC_AUXADC_CHAN_CHIP_TEMP,70	PMIC_AUXADC_CHAN_VCORE_TEMP,71	PMIC_AUXADC_CHAN_VPROC_TEMP,72	PMIC_AUXADC_CHAN_VGPU_TEMP,73	PMIC_AUXADC_CHAN_ACCDET,74	PMIC_AUXADC_CHAN_VDCXO,75	PMIC_AUXADC_CHAN_TSX_TEMP,76	PMIC_AUXADC_CHAN_HPOFS_CAL,77	PMIC_AUXADC_CHAN_DCXO_TEMP,78	PMIC_AUXADC_CHAN_VBIF,79	PMIC_AUXADC_CHAN_IBAT,80	PMIC_AUXADC_CHAN_VBAT,81	PMIC_AUXADC_CHAN_MAX82};83 84/**85 * struct mt6359_auxadc - Main driver structure86 * @dev:           Device pointer87 * @regmap:        Regmap from SoC PMIC Wrapper88 * @chip_info:     PMIC specific chip info89 * @lock:          Mutex to serialize AUXADC reading vs configuration90 * @timed_out:     Signals whether the last read timed out91 */92struct mt6359_auxadc {93	struct device *dev;94	struct regmap *regmap;95	const struct mtk_pmic_auxadc_info *chip_info;96	struct mutex lock;97	bool timed_out;98};99 100/**101 * struct mtk_pmic_auxadc_chan - PMIC AUXADC channel data102 * @req_idx:       Request register number103 * @req_mask:      Bitmask to activate a channel104 * @num_samples:   Number of AUXADC samples for averaging105 * @r_ratio:       Resistance ratio fractional106 */107struct mtk_pmic_auxadc_chan {108	u8 req_idx;109	u16 req_mask;110	u16 num_samples;111	struct u8_fract r_ratio;112};113 114/**115 * struct mtk_pmic_auxadc_info - PMIC specific chip info116 * @model_name:     PMIC model name117 * @channels:       IIO specification of ADC channels118 * @num_channels:   Number of ADC channels119 * @desc:           PMIC AUXADC channel data120 * @regs:           List of PMIC specific registers121 * @sec_unlock_key: Security unlock key for HK_TOP writes122 * @imp_adc_num:    ADC channel for battery impedance readings123 * @read_imp:       Callback to read impedance channels124 */125struct mtk_pmic_auxadc_info {126	const char *model_name;127	const struct iio_chan_spec *channels;128	u8 num_channels;129	const struct mtk_pmic_auxadc_chan *desc;130	const u16 *regs;131	u16 sec_unlock_key;132	u8 imp_adc_num;133	int (*read_imp)(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat);134};135 136#define MTK_PMIC_ADC_CHAN(_ch_idx, _req_idx, _req_bit, _samples, _rnum, _rdiv)	\137	[PMIC_AUXADC_CHAN_##_ch_idx] = {					\138		.req_idx = _req_idx,						\139		.req_mask = BIT(_req_bit),					\140		.num_samples = _samples,					\141		.r_ratio = { _rnum, _rdiv }					\142	}143 144#define MTK_PMIC_IIO_CHAN(_model, _name, _ch_idx, _adc_idx, _nbits, _ch_type)	\145{										\146	.type = _ch_type,							\147	.channel = _model##_AUXADC_##_ch_idx,					\148	.address = _adc_idx,							\149	.scan_index = PMIC_AUXADC_CHAN_##_ch_idx,				\150	.datasheet_name = __stringify(_name),					\151	.scan_type =  {								\152		.sign = 'u',							\153		.realbits = _nbits,						\154		.storagebits = 16,						\155		.endianness = IIO_CPU						\156	},									\157	.indexed = 1,								\158	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE)	\159}160 161static const struct iio_chan_spec mt6357_auxadc_channels[] = {162	MTK_PMIC_IIO_CHAN(MT6357, bat_adc, BATADC, 0, 15, IIO_RESISTANCE),163	MTK_PMIC_IIO_CHAN(MT6357, isense, ISENSE, 1, 12, IIO_CURRENT),164	MTK_PMIC_IIO_CHAN(MT6357, cdt_v, VCDT, 2, 12, IIO_TEMP),165	MTK_PMIC_IIO_CHAN(MT6357, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP),166	MTK_PMIC_IIO_CHAN(MT6357, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),167	MTK_PMIC_IIO_CHAN(MT6357, acc_det, ACCDET, 5, 12, IIO_RESISTANCE),168	MTK_PMIC_IIO_CHAN(MT6357, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE),169	MTK_PMIC_IIO_CHAN(MT6357, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP),170	MTK_PMIC_IIO_CHAN(MT6357, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE),171	MTK_PMIC_IIO_CHAN(MT6357, dcxo_temp, DCXO_TEMP, 36, 15, IIO_TEMP),172	MTK_PMIC_IIO_CHAN(MT6357, vcore_temp, VCORE_TEMP, 40, 12, IIO_TEMP),173	MTK_PMIC_IIO_CHAN(MT6357, vproc_temp, VPROC_TEMP, 41, 12, IIO_TEMP),174 175	/* Battery impedance channels */176	MTK_PMIC_IIO_CHAN(MT6357, batt_v, VBAT, 0, 15, IIO_VOLTAGE),177};178 179static const struct mtk_pmic_auxadc_chan mt6357_auxadc_ch_desc[] = {180	MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 3, 1),181	MTK_PMIC_ADC_CHAN(ISENSE, PMIC_AUXADC_RQST0, 0, 128, 3, 1),182	MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, 8, 1, 1),183	MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 1, 1),184	MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1),185	MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1),186	MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1),187	MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1),188	MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1),189	MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 1, 1),190	MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 5, 8, 1, 1),191	MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 6, 8, 1, 1),192 193	/* Battery impedance channels */194	MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 3, 1),195};196 197static const u16 mt6357_auxadc_regs[] = {198	[PMIC_HK_TOP_RST_CON0]	= 0x0f90,199	[PMIC_AUXADC_DCM_CON]	= 0x122e,200	[PMIC_AUXADC_ADC0]	= 0x1088,201	[PMIC_AUXADC_IMP0]	= 0x119c,202	[PMIC_AUXADC_IMP1]	= 0x119e,203	[PMIC_AUXADC_RQST0]	= 0x110e,204	[PMIC_AUXADC_RQST1]	= 0x1114,205};206 207static const struct iio_chan_spec mt6358_auxadc_channels[] = {208	MTK_PMIC_IIO_CHAN(MT6358, bat_adc, BATADC, 0, 15, IIO_RESISTANCE),209	MTK_PMIC_IIO_CHAN(MT6358, cdt_v, VCDT, 2, 12, IIO_TEMP),210	MTK_PMIC_IIO_CHAN(MT6358, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP),211	MTK_PMIC_IIO_CHAN(MT6358, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),212	MTK_PMIC_IIO_CHAN(MT6358, acc_det, ACCDET, 5, 12, IIO_RESISTANCE),213	MTK_PMIC_IIO_CHAN(MT6358, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE),214	MTK_PMIC_IIO_CHAN(MT6358, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP),215	MTK_PMIC_IIO_CHAN(MT6358, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE),216	MTK_PMIC_IIO_CHAN(MT6358, dcxo_temp, DCXO_TEMP, 10, 15, IIO_TEMP),217	MTK_PMIC_IIO_CHAN(MT6358, bif_v, VBIF, 11, 12, IIO_VOLTAGE),218	MTK_PMIC_IIO_CHAN(MT6358, vcore_temp, VCORE_TEMP, 38, 12, IIO_TEMP),219	MTK_PMIC_IIO_CHAN(MT6358, vproc_temp, VPROC_TEMP, 39, 12, IIO_TEMP),220	MTK_PMIC_IIO_CHAN(MT6358, vgpu_temp, VGPU_TEMP, 40, 12, IIO_TEMP),221 222	/* Battery impedance channels */223	MTK_PMIC_IIO_CHAN(MT6358, batt_v, VBAT, 0, 15, IIO_VOLTAGE),224};225 226static const struct mtk_pmic_auxadc_chan mt6358_auxadc_ch_desc[] = {227	MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 3, 1),228	MTK_PMIC_ADC_CHAN(VCDT, PMIC_AUXADC_RQST0, 0, 8, 1, 1),229	MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 2, 1),230	MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1),231	MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1),232	MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, 8, 3, 2),233	MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1),234	MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1),235	MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1),236	MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 2, 1),237	MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, 8, 1, 1),238	MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, 8, 1, 1),239	MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, 8, 1, 1),240 241	/* Battery impedance channels */242	MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 7, 2),243};244 245static const u16 mt6358_auxadc_regs[] = {246	[PMIC_HK_TOP_RST_CON0]	= 0x0f90,247	[PMIC_AUXADC_DCM_CON]	= 0x1260,248	[PMIC_AUXADC_ADC0]	= 0x1088,249	[PMIC_AUXADC_IMP0]	= 0x1208,250	[PMIC_AUXADC_IMP1]	= 0x120a,251	[PMIC_AUXADC_RQST0]	= 0x1108,252	[PMIC_AUXADC_RQST1]	= 0x110a,253};254 255static const struct iio_chan_spec mt6359_auxadc_channels[] = {256	MTK_PMIC_IIO_CHAN(MT6359, bat_adc, BATADC, 0, 15, IIO_RESISTANCE),257	MTK_PMIC_IIO_CHAN(MT6359, batt_temp, BAT_TEMP, 3, 12, IIO_TEMP),258	MTK_PMIC_IIO_CHAN(MT6359, chip_temp, CHIP_TEMP, 4, 12, IIO_TEMP),259	MTK_PMIC_IIO_CHAN(MT6359, acc_det, ACCDET, 5, 12, IIO_RESISTANCE),260	MTK_PMIC_IIO_CHAN(MT6359, dcxo_v, VDCXO, 6, 12, IIO_VOLTAGE),261	MTK_PMIC_IIO_CHAN(MT6359, tsx_temp, TSX_TEMP, 7, 15, IIO_TEMP),262	MTK_PMIC_IIO_CHAN(MT6359, hp_ofs_cal, HPOFS_CAL, 9, 15, IIO_RESISTANCE),263	MTK_PMIC_IIO_CHAN(MT6359, dcxo_temp, DCXO_TEMP, 10, 15, IIO_TEMP),264	MTK_PMIC_IIO_CHAN(MT6359, bif_v, VBIF, 11, 12, IIO_VOLTAGE),265	MTK_PMIC_IIO_CHAN(MT6359, vcore_temp, VCORE_TEMP, 30, 12, IIO_TEMP),266	MTK_PMIC_IIO_CHAN(MT6359, vproc_temp, VPROC_TEMP, 31, 12, IIO_TEMP),267	MTK_PMIC_IIO_CHAN(MT6359, vgpu_temp, VGPU_TEMP, 32, 12, IIO_TEMP),268 269	/* Battery impedance channels */270	MTK_PMIC_IIO_CHAN(MT6359, batt_v, VBAT, 0, 15, IIO_VOLTAGE),271	MTK_PMIC_IIO_CHAN(MT6359, batt_i, IBAT, 0, 15, IIO_CURRENT),272};273 274static const struct mtk_pmic_auxadc_chan mt6359_auxadc_ch_desc[] = {275	MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, 128, 7, 2),276	MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, 8, 5, 2),277	MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, 8, 1, 1),278	MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, 8, 1, 1),279	MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, 8, 3, 2),280	MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, 128, 1, 1),281	MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, 256, 1, 1),282	MTK_PMIC_ADC_CHAN(DCXO_TEMP, PMIC_AUXADC_RQST0, 10, 16, 1, 1),283	MTK_PMIC_ADC_CHAN(VBIF, PMIC_AUXADC_RQST0, 11, 8, 5, 2),284	MTK_PMIC_ADC_CHAN(VCORE_TEMP, PMIC_AUXADC_RQST1, 8, 8, 1, 1),285	MTK_PMIC_ADC_CHAN(VPROC_TEMP, PMIC_AUXADC_RQST1, 9, 8, 1, 1),286	MTK_PMIC_ADC_CHAN(VGPU_TEMP, PMIC_AUXADC_RQST1, 10, 8, 1, 1),287 288	/* Battery impedance channels */289	MTK_PMIC_ADC_CHAN(VBAT, 0, 0, 128, 7, 2),290	MTK_PMIC_ADC_CHAN(IBAT, 0, 0, 128, 7, 2),291};292 293static const u16 mt6359_auxadc_regs[] = {294	[PMIC_FGADC_R_CON0]	= 0x0d88,295	[PMIC_HK_TOP_WKEY]	= 0x0fb4,296	[PMIC_HK_TOP_RST_CON0]	= 0x0f90,297	[PMIC_AUXADC_RQST0]	= 0x1108,298	[PMIC_AUXADC_RQST1]	= 0x110a,299	[PMIC_AUXADC_ADC0]	= 0x1088,300	[PMIC_AUXADC_IMP0]	= 0x1208,301	[PMIC_AUXADC_IMP1]	= 0x120a,302	[PMIC_AUXADC_IMP3]	= 0x120e,303};304 305static void mt6358_stop_imp_conv(struct mt6359_auxadc *adc_dev)306{307	const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;308	struct regmap *regmap = adc_dev->regmap;309 310	regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6358_IMP0_CLEAR);311	regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6358_IMP0_CLEAR);312	regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP1], MT6358_IMP1_AUTOREPEAT_EN);313	regmap_clear_bits(regmap, cinfo->regs[PMIC_AUXADC_DCM_CON], MT6358_DCM_CK_SW_EN);314}315 316static int mt6358_start_imp_conv(struct mt6359_auxadc *adc_dev)317{318	const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;319	struct regmap *regmap = adc_dev->regmap;320	u32 val;321	int ret;322 323	regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_DCM_CON], MT6358_DCM_CK_SW_EN);324	regmap_set_bits(regmap, cinfo->regs[PMIC_AUXADC_IMP1], MT6358_IMP1_AUTOREPEAT_EN);325 326	ret = regmap_read_poll_timeout(adc_dev->regmap, cinfo->regs[PMIC_AUXADC_IMP0],327				       val, val & MT6358_IMP0_IRQ_RDY,328				       IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US);329	if (ret) {330		mt6358_stop_imp_conv(adc_dev);331		return ret;332	}333 334	return 0;335}336 337static int mt6358_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat)338{339	const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;340	struct regmap *regmap = adc_dev->regmap;341	u16 reg_adc0 = cinfo->regs[PMIC_AUXADC_ADC0];342	u32 val_v;343	int ret;344 345	ret = mt6358_start_imp_conv(adc_dev);346	if (ret)347		return ret;348 349	/* Read the params before stopping */350	regmap_read(regmap, reg_adc0 + (cinfo->imp_adc_num << 1), &val_v);351 352	mt6358_stop_imp_conv(adc_dev);353 354	if (vbat)355		*vbat = val_v;356	if (ibat)357		*ibat = 0;358 359	return 0;360}361 362static int mt6359_read_imp(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat)363{364	const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;365	struct regmap *regmap = adc_dev->regmap;366	u32 val, val_v, val_i;367	int ret;368 369	/* Start conversion */370	regmap_write(regmap, cinfo->regs[PMIC_AUXADC_IMP0], MT6359_IMP0_CONV_EN);371	ret = regmap_read_poll_timeout(regmap, cinfo->regs[PMIC_AUXADC_IMP1],372				       val, val & MT6359_IMP1_IRQ_RDY,373				       IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US);374 375	/* Stop conversion regardless of the result */376	regmap_write(regmap, cinfo->regs[PMIC_AUXADC_IMP0], 0);377	if (ret)378		return ret;379 380	/* If it succeeded, wait for the registers to be populated */381	fsleep(IMP_STOP_DELAY_US);382 383	ret = regmap_read(regmap, cinfo->regs[PMIC_AUXADC_IMP3], &val_v);384	if (ret)385		return ret;386 387	ret = regmap_read(regmap, cinfo->regs[PMIC_FGADC_R_CON0], &val_i);388	if (ret)389		return ret;390 391	if (vbat)392		*vbat = val_v;393	if (ibat)394		*ibat = val_i;395 396	return 0;397}398 399static const struct mtk_pmic_auxadc_info mt6357_chip_info = {400	.model_name = "MT6357",401	.channels = mt6357_auxadc_channels,402	.num_channels = ARRAY_SIZE(mt6357_auxadc_channels),403	.desc = mt6357_auxadc_ch_desc,404	.regs = mt6357_auxadc_regs,405	.imp_adc_num = MT6357_IMP_ADC_NUM,406	.read_imp = mt6358_read_imp,407};408 409static const struct mtk_pmic_auxadc_info mt6358_chip_info = {410	.model_name = "MT6358",411	.channels = mt6358_auxadc_channels,412	.num_channels = ARRAY_SIZE(mt6358_auxadc_channels),413	.desc = mt6358_auxadc_ch_desc,414	.regs = mt6358_auxadc_regs,415	.imp_adc_num = MT6358_IMP_ADC_NUM,416	.read_imp = mt6358_read_imp,417};418 419static const struct mtk_pmic_auxadc_info mt6359_chip_info = {420	.model_name = "MT6359",421	.channels = mt6359_auxadc_channels,422	.num_channels = ARRAY_SIZE(mt6359_auxadc_channels),423	.desc = mt6359_auxadc_ch_desc,424	.regs = mt6359_auxadc_regs,425	.sec_unlock_key = 0x6359,426	.read_imp = mt6359_read_imp,427};428 429static void mt6359_auxadc_reset(struct mt6359_auxadc *adc_dev)430{431	const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;432	struct regmap *regmap = adc_dev->regmap;433 434	/* Unlock HK_TOP writes */435	if (cinfo->sec_unlock_key)436		regmap_write(regmap, cinfo->regs[PMIC_HK_TOP_WKEY], cinfo->sec_unlock_key);437 438	/* Assert ADC reset */439	regmap_set_bits(regmap, cinfo->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL);440 441	/* De-assert ADC reset. No wait required, as pwrap takes care of that for us. */442	regmap_clear_bits(regmap, cinfo->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL);443 444	/* Lock HK_TOP writes again */445	if (cinfo->sec_unlock_key)446		regmap_write(regmap, cinfo->regs[PMIC_HK_TOP_WKEY], 0);447}448 449static int mt6359_auxadc_read_adc(struct mt6359_auxadc *adc_dev,450				  const struct iio_chan_spec *chan, int *out)451{452	const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;453	const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index];454	struct regmap *regmap = adc_dev->regmap;455	u32 val;456	int ret;457 458	/* Request to start sampling for ADC channel */459	ret = regmap_write(regmap, cinfo->regs[desc->req_idx], desc->req_mask);460	if (ret)461		return ret;462 463	/* Wait until all samples are averaged */464	fsleep(desc->num_samples * AUXADC_AVG_TIME_US);465 466	ret = regmap_read_poll_timeout(regmap,467				       cinfo->regs[PMIC_AUXADC_ADC0] + (chan->address << 1),468				       val, val & PMIC_AUXADC_RDY_BIT,469				       AUXADC_POLL_DELAY_US, AUXADC_TIMEOUT_US);470	if (ret)471		return ret;472 473	/* Stop sampling */474	regmap_write(regmap, cinfo->regs[desc->req_idx], 0);475 476	*out = val & GENMASK(chan->scan_type.realbits - 1, 0);477	return 0;478}479 480static int mt6359_auxadc_read_label(struct iio_dev *indio_dev,481				    const struct iio_chan_spec *chan, char *label)482{483	return sysfs_emit(label, "%s\n", chan->datasheet_name);484}485 486static int mt6359_auxadc_read_raw(struct iio_dev *indio_dev,487				  const struct iio_chan_spec *chan,488				  int *val, int *val2, long mask)489{490	struct mt6359_auxadc *adc_dev = iio_priv(indio_dev);491	const struct mtk_pmic_auxadc_info *cinfo = adc_dev->chip_info;492	const struct mtk_pmic_auxadc_chan *desc = &cinfo->desc[chan->scan_index];493	int ret;494 495	if (mask == IIO_CHAN_INFO_SCALE) {496		*val = desc->r_ratio.numerator * AUXADC_VOLT_FULL;497 498		if (desc->r_ratio.denominator > 1) {499			*val2 = desc->r_ratio.denominator;500			return IIO_VAL_FRACTIONAL;501		}502 503		return IIO_VAL_INT;504	}505 506	scoped_guard(mutex, &adc_dev->lock) {507		switch (chan->scan_index) {508		case PMIC_AUXADC_CHAN_IBAT:509			ret = adc_dev->chip_info->read_imp(adc_dev, NULL, val);510			break;511		case PMIC_AUXADC_CHAN_VBAT:512			ret = adc_dev->chip_info->read_imp(adc_dev, val, NULL);513			break;514		default:515			ret = mt6359_auxadc_read_adc(adc_dev, chan, val);516			break;517		}518	}519 520	if (ret) {521		/*522		 * If we get more than one timeout, it's possible that the523		 * AUXADC is stuck: perform a full reset to recover it.524		 */525		if (ret == -ETIMEDOUT) {526			if (adc_dev->timed_out) {527				dev_warn(adc_dev->dev, "Resetting stuck ADC!\r\n");528				mt6359_auxadc_reset(adc_dev);529			}530			adc_dev->timed_out = true;531		}532		return ret;533	}534	adc_dev->timed_out = false;535 536	return IIO_VAL_INT;537}538 539static const struct iio_info mt6359_auxadc_iio_info = {540	.read_label = mt6359_auxadc_read_label,541	.read_raw = mt6359_auxadc_read_raw,542};543 544static int mt6359_auxadc_probe(struct platform_device *pdev)545{546	struct device *dev = &pdev->dev;547	struct device *mt6397_mfd_dev = dev->parent;548	struct mt6359_auxadc *adc_dev;549	struct iio_dev *indio_dev;550	struct regmap *regmap;551	int ret;552 553	/* Regmap is from SoC PMIC Wrapper, parent of the mt6397 MFD */554	regmap = dev_get_regmap(mt6397_mfd_dev->parent, NULL);555	if (!regmap)556		return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n");557 558	indio_dev = devm_iio_device_alloc(dev, sizeof(*adc_dev));559	if (!indio_dev)560		return -ENOMEM;561 562	adc_dev = iio_priv(indio_dev);563	adc_dev->regmap = regmap;564	adc_dev->dev = dev;565 566	adc_dev->chip_info = device_get_match_data(dev);567	if (!adc_dev->chip_info)568		return -EINVAL;569 570	mutex_init(&adc_dev->lock);571 572	mt6359_auxadc_reset(adc_dev);573 574	indio_dev->name = adc_dev->chip_info->model_name;575	indio_dev->info = &mt6359_auxadc_iio_info;576	indio_dev->modes = INDIO_DIRECT_MODE;577	indio_dev->channels = adc_dev->chip_info->channels;578	indio_dev->num_channels = adc_dev->chip_info->num_channels;579 580	ret = devm_iio_device_register(dev, indio_dev);581	if (ret)582		return dev_err_probe(dev, ret, "failed to register iio device\n");583 584	return 0;585}586 587static const struct of_device_id mt6359_auxadc_of_match[] = {588	{ .compatible = "mediatek,mt6357-auxadc", .data = &mt6357_chip_info },589	{ .compatible = "mediatek,mt6358-auxadc", .data = &mt6358_chip_info },590	{ .compatible = "mediatek,mt6359-auxadc", .data = &mt6359_chip_info },591	{ /* sentinel */ }592};593MODULE_DEVICE_TABLE(of, mt6359_auxadc_of_match);594 595static struct platform_driver mt6359_auxadc_driver = {596	.driver = {597		.name = "mt6359-auxadc",598		.of_match_table = mt6359_auxadc_of_match,599	},600	.probe	= mt6359_auxadc_probe,601};602module_platform_driver(mt6359_auxadc_driver);603 604MODULE_LICENSE("GPL");605MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");606MODULE_DESCRIPTION("MediaTek MT6359 PMIC AUXADC Driver");607