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