162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2016-2017, 2019, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2022 Linaro Limited. 562306a36Sopenharmony_ci * Author: Caleb Connolly <caleb.connolly@linaro.org> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This driver is for the Round Robin ADC found in the pmi8998 and pm660 PMICs. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/bitfield.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/math64.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <linux/property.h> 1862306a36Sopenharmony_ci#include <linux/regmap.h> 1962306a36Sopenharmony_ci#include <linux/spmi.h> 2062306a36Sopenharmony_ci#include <linux/types.h> 2162306a36Sopenharmony_ci#include <linux/units.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <asm/unaligned.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <linux/iio/iio.h> 2662306a36Sopenharmony_ci#include <linux/iio/types.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <soc/qcom/qcom-spmi-pmic.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define DRIVER_NAME "qcom-spmi-rradc" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define RR_ADC_EN_CTL 0x46 3362306a36Sopenharmony_ci#define RR_ADC_SKIN_TEMP_LSB 0x50 3462306a36Sopenharmony_ci#define RR_ADC_SKIN_TEMP_MSB 0x51 3562306a36Sopenharmony_ci#define RR_ADC_CTL 0x52 3662306a36Sopenharmony_ci#define RR_ADC_CTL_CONTINUOUS_SEL BIT(3) 3762306a36Sopenharmony_ci#define RR_ADC_LOG 0x53 3862306a36Sopenharmony_ci#define RR_ADC_LOG_CLR_CTRL BIT(0) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define RR_ADC_FAKE_BATT_LOW_LSB 0x58 4162306a36Sopenharmony_ci#define RR_ADC_FAKE_BATT_LOW_MSB 0x59 4262306a36Sopenharmony_ci#define RR_ADC_FAKE_BATT_HIGH_LSB 0x5A 4362306a36Sopenharmony_ci#define RR_ADC_FAKE_BATT_HIGH_MSB 0x5B 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define RR_ADC_BATT_ID_CTRL 0x60 4662306a36Sopenharmony_ci#define RR_ADC_BATT_ID_CTRL_CHANNEL_CONV BIT(0) 4762306a36Sopenharmony_ci#define RR_ADC_BATT_ID_TRIGGER 0x61 4862306a36Sopenharmony_ci#define RR_ADC_BATT_ID_STS 0x62 4962306a36Sopenharmony_ci#define RR_ADC_BATT_ID_CFG 0x63 5062306a36Sopenharmony_ci#define BATT_ID_SETTLE_MASK GENMASK(7, 5) 5162306a36Sopenharmony_ci#define RR_ADC_BATT_ID_5_LSB 0x66 5262306a36Sopenharmony_ci#define RR_ADC_BATT_ID_5_MSB 0x67 5362306a36Sopenharmony_ci#define RR_ADC_BATT_ID_15_LSB 0x68 5462306a36Sopenharmony_ci#define RR_ADC_BATT_ID_15_MSB 0x69 5562306a36Sopenharmony_ci#define RR_ADC_BATT_ID_150_LSB 0x6A 5662306a36Sopenharmony_ci#define RR_ADC_BATT_ID_150_MSB 0x6B 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_CTRL 0x70 5962306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_TRIGGER 0x71 6062306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_STS 0x72 6162306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_CFG 0x73 6262306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_LSB 0x74 6362306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_MSB 0x75 6462306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_FREQ 0x76 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_CTRL 0x80 6762306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_TRIGGER 0x81 6862306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_STS 0x82 6962306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_CFG 0x83 7062306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_LSB 0x84 7162306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_MSB 0x85 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define RR_ADC_SKIN_HOT 0x86 7462306a36Sopenharmony_ci#define RR_ADC_SKIN_TOO_HOT 0x87 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_C1 0x88 7762306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_C2 0x89 7862306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_C3 0x8A 7962306a36Sopenharmony_ci#define RR_ADC_AUX_THERM_HALF_RANGE 0x8B 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define RR_ADC_USB_IN_V_CTRL 0x90 8262306a36Sopenharmony_ci#define RR_ADC_USB_IN_V_TRIGGER 0x91 8362306a36Sopenharmony_ci#define RR_ADC_USB_IN_V_STS 0x92 8462306a36Sopenharmony_ci#define RR_ADC_USB_IN_V_LSB 0x94 8562306a36Sopenharmony_ci#define RR_ADC_USB_IN_V_MSB 0x95 8662306a36Sopenharmony_ci#define RR_ADC_USB_IN_I_CTRL 0x98 8762306a36Sopenharmony_ci#define RR_ADC_USB_IN_I_TRIGGER 0x99 8862306a36Sopenharmony_ci#define RR_ADC_USB_IN_I_STS 0x9A 8962306a36Sopenharmony_ci#define RR_ADC_USB_IN_I_LSB 0x9C 9062306a36Sopenharmony_ci#define RR_ADC_USB_IN_I_MSB 0x9D 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define RR_ADC_DC_IN_V_CTRL 0xA0 9362306a36Sopenharmony_ci#define RR_ADC_DC_IN_V_TRIGGER 0xA1 9462306a36Sopenharmony_ci#define RR_ADC_DC_IN_V_STS 0xA2 9562306a36Sopenharmony_ci#define RR_ADC_DC_IN_V_LSB 0xA4 9662306a36Sopenharmony_ci#define RR_ADC_DC_IN_V_MSB 0xA5 9762306a36Sopenharmony_ci#define RR_ADC_DC_IN_I_CTRL 0xA8 9862306a36Sopenharmony_ci#define RR_ADC_DC_IN_I_TRIGGER 0xA9 9962306a36Sopenharmony_ci#define RR_ADC_DC_IN_I_STS 0xAA 10062306a36Sopenharmony_ci#define RR_ADC_DC_IN_I_LSB 0xAC 10162306a36Sopenharmony_ci#define RR_ADC_DC_IN_I_MSB 0xAD 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#define RR_ADC_PMI_DIE_TEMP_CTRL 0xB0 10462306a36Sopenharmony_ci#define RR_ADC_PMI_DIE_TEMP_TRIGGER 0xB1 10562306a36Sopenharmony_ci#define RR_ADC_PMI_DIE_TEMP_STS 0xB2 10662306a36Sopenharmony_ci#define RR_ADC_PMI_DIE_TEMP_CFG 0xB3 10762306a36Sopenharmony_ci#define RR_ADC_PMI_DIE_TEMP_LSB 0xB4 10862306a36Sopenharmony_ci#define RR_ADC_PMI_DIE_TEMP_MSB 0xB5 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#define RR_ADC_CHARGER_TEMP_CTRL 0xB8 11162306a36Sopenharmony_ci#define RR_ADC_CHARGER_TEMP_TRIGGER 0xB9 11262306a36Sopenharmony_ci#define RR_ADC_CHARGER_TEMP_STS 0xBA 11362306a36Sopenharmony_ci#define RR_ADC_CHARGER_TEMP_CFG 0xBB 11462306a36Sopenharmony_ci#define RR_ADC_CHARGER_TEMP_LSB 0xBC 11562306a36Sopenharmony_ci#define RR_ADC_CHARGER_TEMP_MSB 0xBD 11662306a36Sopenharmony_ci#define RR_ADC_CHARGER_HOT 0xBE 11762306a36Sopenharmony_ci#define RR_ADC_CHARGER_TOO_HOT 0xBF 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci#define RR_ADC_GPIO_CTRL 0xC0 12062306a36Sopenharmony_ci#define RR_ADC_GPIO_TRIGGER 0xC1 12162306a36Sopenharmony_ci#define RR_ADC_GPIO_STS 0xC2 12262306a36Sopenharmony_ci#define RR_ADC_GPIO_LSB 0xC4 12362306a36Sopenharmony_ci#define RR_ADC_GPIO_MSB 0xC5 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#define RR_ADC_ATEST_CTRL 0xC8 12662306a36Sopenharmony_ci#define RR_ADC_ATEST_TRIGGER 0xC9 12762306a36Sopenharmony_ci#define RR_ADC_ATEST_STS 0xCA 12862306a36Sopenharmony_ci#define RR_ADC_ATEST_LSB 0xCC 12962306a36Sopenharmony_ci#define RR_ADC_ATEST_MSB 0xCD 13062306a36Sopenharmony_ci#define RR_ADC_SEC_ACCESS 0xD0 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#define RR_ADC_PERPH_RESET_CTL2 0xD9 13362306a36Sopenharmony_ci#define RR_ADC_PERPH_RESET_CTL3 0xDA 13462306a36Sopenharmony_ci#define RR_ADC_PERPH_RESET_CTL4 0xDB 13562306a36Sopenharmony_ci#define RR_ADC_INT_TEST1 0xE0 13662306a36Sopenharmony_ci#define RR_ADC_INT_TEST_VAL 0xE1 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci#define RR_ADC_TM_TRIGGER_CTRLS 0xE2 13962306a36Sopenharmony_ci#define RR_ADC_TM_ADC_CTRLS 0xE3 14062306a36Sopenharmony_ci#define RR_ADC_TM_CNL_CTRL 0xE4 14162306a36Sopenharmony_ci#define RR_ADC_TM_BATT_ID_CTRL 0xE5 14262306a36Sopenharmony_ci#define RR_ADC_TM_THERM_CTRL 0xE6 14362306a36Sopenharmony_ci#define RR_ADC_TM_CONV_STS 0xE7 14462306a36Sopenharmony_ci#define RR_ADC_TM_ADC_READ_LSB 0xE8 14562306a36Sopenharmony_ci#define RR_ADC_TM_ADC_READ_MSB 0xE9 14662306a36Sopenharmony_ci#define RR_ADC_TM_ATEST_MUX_1 0xEA 14762306a36Sopenharmony_ci#define RR_ADC_TM_ATEST_MUX_2 0xEB 14862306a36Sopenharmony_ci#define RR_ADC_TM_REFERENCES 0xED 14962306a36Sopenharmony_ci#define RR_ADC_TM_MISC_CTL 0xEE 15062306a36Sopenharmony_ci#define RR_ADC_TM_RR_CTRL 0xEF 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#define RR_ADC_TRIGGER_EVERY_CYCLE BIT(7) 15362306a36Sopenharmony_ci#define RR_ADC_TRIGGER_CTL BIT(0) 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#define RR_ADC_BATT_ID_RANGE 820 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci#define RR_ADC_BITS 10 15862306a36Sopenharmony_ci#define RR_ADC_CHAN_MSB (1 << RR_ADC_BITS) 15962306a36Sopenharmony_ci#define RR_ADC_FS_VOLTAGE_MV 2500 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* BATT_THERM 0.25K/LSB */ 16262306a36Sopenharmony_ci#define RR_ADC_BATT_THERM_LSB_K 4 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#define RR_ADC_TEMP_FS_VOLTAGE_NUM 5000000 16562306a36Sopenharmony_ci#define RR_ADC_TEMP_FS_VOLTAGE_DEN 3 16662306a36Sopenharmony_ci#define RR_ADC_DIE_TEMP_OFFSET 601400 16762306a36Sopenharmony_ci#define RR_ADC_DIE_TEMP_SLOPE 2 16862306a36Sopenharmony_ci#define RR_ADC_DIE_TEMP_OFFSET_MILLI_DEGC 25000 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_GF_OFFSET_UV 1303168 17162306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_GF_SLOPE_UV_PER_C 3784 17262306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_SMIC_OFFSET_UV 1338433 17362306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_SMIC_SLOPE_UV_PER_C 3655 17462306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_660_GF_OFFSET_UV 1309001 17562306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_660_GF_SLOPE_UV_PER_C 3403 17662306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_660_SMIC_OFFSET_UV 1295898 17762306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C 3596 17862306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_660_MGNA_OFFSET_UV 1314779 17962306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_660_MGNA_SLOPE_UV_PER_C 3496 18062306a36Sopenharmony_ci#define RR_ADC_CHG_TEMP_OFFSET_MILLI_DEGC 25000 18162306a36Sopenharmony_ci#define RR_ADC_CHG_THRESHOLD_SCALE 4 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#define RR_ADC_VOLT_INPUT_FACTOR 8 18462306a36Sopenharmony_ci#define RR_ADC_CURR_INPUT_FACTOR 2000 18562306a36Sopenharmony_ci#define RR_ADC_CURR_USBIN_INPUT_FACTOR_MIL 1886 18662306a36Sopenharmony_ci#define RR_ADC_CURR_USBIN_660_FACTOR_MIL 9 18762306a36Sopenharmony_ci#define RR_ADC_CURR_USBIN_660_UV_VAL 579500 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#define RR_ADC_GPIO_FS_RANGE 5000 19062306a36Sopenharmony_ci#define RR_ADC_COHERENT_CHECK_RETRY 5 19162306a36Sopenharmony_ci#define RR_ADC_CHAN_MAX_CONTINUOUS_BUFFER_LEN 16 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci#define RR_ADC_STS_CHANNEL_READING_MASK GENMASK(1, 0) 19462306a36Sopenharmony_ci#define RR_ADC_STS_CHANNEL_STS BIT(1) 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci#define RR_ADC_TP_REV_VERSION1 21 19762306a36Sopenharmony_ci#define RR_ADC_TP_REV_VERSION2 29 19862306a36Sopenharmony_ci#define RR_ADC_TP_REV_VERSION3 32 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#define RRADC_BATT_ID_DELAY_MAX 8 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cienum rradc_channel_id { 20362306a36Sopenharmony_ci RR_ADC_BATT_ID = 0, 20462306a36Sopenharmony_ci RR_ADC_BATT_THERM, 20562306a36Sopenharmony_ci RR_ADC_SKIN_TEMP, 20662306a36Sopenharmony_ci RR_ADC_USBIN_I, 20762306a36Sopenharmony_ci RR_ADC_USBIN_V, 20862306a36Sopenharmony_ci RR_ADC_DCIN_I, 20962306a36Sopenharmony_ci RR_ADC_DCIN_V, 21062306a36Sopenharmony_ci RR_ADC_DIE_TEMP, 21162306a36Sopenharmony_ci RR_ADC_CHG_TEMP, 21262306a36Sopenharmony_ci RR_ADC_GPIO, 21362306a36Sopenharmony_ci RR_ADC_CHAN_MAX 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistruct rradc_chip; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/** 21962306a36Sopenharmony_ci * struct rradc_channel - rradc channel data 22062306a36Sopenharmony_ci * @label: channel label 22162306a36Sopenharmony_ci * @lsb: Channel least significant byte 22262306a36Sopenharmony_ci * @status: Channel status address 22362306a36Sopenharmony_ci * @size: number of bytes to read 22462306a36Sopenharmony_ci * @trigger_addr: Trigger address, trigger is only used on some channels 22562306a36Sopenharmony_ci * @trigger_mask: Trigger mask 22662306a36Sopenharmony_ci * @scale_fn: Post process callback for channels which can't be exposed 22762306a36Sopenharmony_ci * as offset + scale. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_cistruct rradc_channel { 23062306a36Sopenharmony_ci const char *label; 23162306a36Sopenharmony_ci u8 lsb; 23262306a36Sopenharmony_ci u8 status; 23362306a36Sopenharmony_ci int size; 23462306a36Sopenharmony_ci int trigger_addr; 23562306a36Sopenharmony_ci int trigger_mask; 23662306a36Sopenharmony_ci int (*scale_fn)(struct rradc_chip *chip, u16 adc_code, int *result); 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistruct rradc_chip { 24062306a36Sopenharmony_ci struct device *dev; 24162306a36Sopenharmony_ci const struct qcom_spmi_pmic *pmic; 24262306a36Sopenharmony_ci /* 24362306a36Sopenharmony_ci * Lock held while doing channel conversion 24462306a36Sopenharmony_ci * involving multiple register read/writes 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_ci struct mutex conversion_lock; 24762306a36Sopenharmony_ci struct regmap *regmap; 24862306a36Sopenharmony_ci u32 base; 24962306a36Sopenharmony_ci int batt_id_delay; 25062306a36Sopenharmony_ci u16 batt_id_data; 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic const int batt_id_delays[] = { 0, 1, 4, 12, 20, 40, 60, 80 }; 25462306a36Sopenharmony_cistatic const struct rradc_channel rradc_chans[RR_ADC_CHAN_MAX]; 25562306a36Sopenharmony_cistatic const struct iio_chan_spec rradc_iio_chans[RR_ADC_CHAN_MAX]; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic int rradc_read(struct rradc_chip *chip, u16 addr, __le16 *buf, int len) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci int ret, retry_cnt = 0; 26062306a36Sopenharmony_ci __le16 data_check[RR_ADC_CHAN_MAX_CONTINUOUS_BUFFER_LEN / 2]; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci if (len > RR_ADC_CHAN_MAX_CONTINUOUS_BUFFER_LEN) { 26362306a36Sopenharmony_ci dev_err(chip->dev, 26462306a36Sopenharmony_ci "Can't read more than %d bytes, but asked to read %d bytes.\n", 26562306a36Sopenharmony_ci RR_ADC_CHAN_MAX_CONTINUOUS_BUFFER_LEN, len); 26662306a36Sopenharmony_ci return -EINVAL; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci while (retry_cnt < RR_ADC_COHERENT_CHECK_RETRY) { 27062306a36Sopenharmony_ci ret = regmap_bulk_read(chip->regmap, chip->base + addr, buf, 27162306a36Sopenharmony_ci len); 27262306a36Sopenharmony_ci if (ret < 0) { 27362306a36Sopenharmony_ci dev_err(chip->dev, "rr_adc reg 0x%x failed :%d\n", addr, 27462306a36Sopenharmony_ci ret); 27562306a36Sopenharmony_ci return ret; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci ret = regmap_bulk_read(chip->regmap, chip->base + addr, 27962306a36Sopenharmony_ci data_check, len); 28062306a36Sopenharmony_ci if (ret < 0) { 28162306a36Sopenharmony_ci dev_err(chip->dev, "rr_adc reg 0x%x failed :%d\n", addr, 28262306a36Sopenharmony_ci ret); 28362306a36Sopenharmony_ci return ret; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (memcmp(buf, data_check, len) != 0) { 28762306a36Sopenharmony_ci retry_cnt++; 28862306a36Sopenharmony_ci dev_dbg(chip->dev, 28962306a36Sopenharmony_ci "coherent read error, retry_cnt:%d\n", 29062306a36Sopenharmony_ci retry_cnt); 29162306a36Sopenharmony_ci continue; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci break; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (retry_cnt == RR_ADC_COHERENT_CHECK_RETRY) 29862306a36Sopenharmony_ci dev_err(chip->dev, "Retry exceeded for coherency check\n"); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci return ret; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic int rradc_get_fab_coeff(struct rradc_chip *chip, int64_t *offset, 30462306a36Sopenharmony_ci int64_t *slope) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci if (chip->pmic->subtype == PM660_SUBTYPE) { 30762306a36Sopenharmony_ci switch (chip->pmic->fab_id) { 30862306a36Sopenharmony_ci case PM660_FAB_ID_GF: 30962306a36Sopenharmony_ci *offset = RR_ADC_CHG_TEMP_660_GF_OFFSET_UV; 31062306a36Sopenharmony_ci *slope = RR_ADC_CHG_TEMP_660_GF_SLOPE_UV_PER_C; 31162306a36Sopenharmony_ci return 0; 31262306a36Sopenharmony_ci case PM660_FAB_ID_TSMC: 31362306a36Sopenharmony_ci *offset = RR_ADC_CHG_TEMP_660_SMIC_OFFSET_UV; 31462306a36Sopenharmony_ci *slope = RR_ADC_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C; 31562306a36Sopenharmony_ci return 0; 31662306a36Sopenharmony_ci default: 31762306a36Sopenharmony_ci *offset = RR_ADC_CHG_TEMP_660_MGNA_OFFSET_UV; 31862306a36Sopenharmony_ci *slope = RR_ADC_CHG_TEMP_660_MGNA_SLOPE_UV_PER_C; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci } else if (chip->pmic->subtype == PMI8998_SUBTYPE) { 32162306a36Sopenharmony_ci switch (chip->pmic->fab_id) { 32262306a36Sopenharmony_ci case PMI8998_FAB_ID_GF: 32362306a36Sopenharmony_ci *offset = RR_ADC_CHG_TEMP_GF_OFFSET_UV; 32462306a36Sopenharmony_ci *slope = RR_ADC_CHG_TEMP_GF_SLOPE_UV_PER_C; 32562306a36Sopenharmony_ci return 0; 32662306a36Sopenharmony_ci case PMI8998_FAB_ID_SMIC: 32762306a36Sopenharmony_ci *offset = RR_ADC_CHG_TEMP_SMIC_OFFSET_UV; 32862306a36Sopenharmony_ci *slope = RR_ADC_CHG_TEMP_SMIC_SLOPE_UV_PER_C; 32962306a36Sopenharmony_ci return 0; 33062306a36Sopenharmony_ci default: 33162306a36Sopenharmony_ci return -EINVAL; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return -EINVAL; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci/* 33962306a36Sopenharmony_ci * These functions explicitly cast int64_t to int. 34062306a36Sopenharmony_ci * They will never overflow, as the values are small enough. 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_cistatic int rradc_post_process_batt_id(struct rradc_chip *chip, u16 adc_code, 34362306a36Sopenharmony_ci int *result_ohms) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci uint32_t current_value; 34662306a36Sopenharmony_ci int64_t r_id; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci current_value = chip->batt_id_data; 34962306a36Sopenharmony_ci r_id = ((int64_t)adc_code * RR_ADC_FS_VOLTAGE_MV); 35062306a36Sopenharmony_ci r_id = div64_s64(r_id, (RR_ADC_CHAN_MSB * current_value)); 35162306a36Sopenharmony_ci *result_ohms = (int)(r_id * MILLI); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci return 0; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic int rradc_enable_continuous_mode(struct rradc_chip *chip) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci int ret; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci /* Clear channel log */ 36162306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_LOG, 36262306a36Sopenharmony_ci RR_ADC_LOG_CLR_CTRL, RR_ADC_LOG_CLR_CTRL); 36362306a36Sopenharmony_ci if (ret < 0) { 36462306a36Sopenharmony_ci dev_err(chip->dev, "log ctrl update to clear failed:%d\n", ret); 36562306a36Sopenharmony_ci return ret; 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_LOG, 36962306a36Sopenharmony_ci RR_ADC_LOG_CLR_CTRL, 0); 37062306a36Sopenharmony_ci if (ret < 0) { 37162306a36Sopenharmony_ci dev_err(chip->dev, "log ctrl update to not clear failed:%d\n", 37262306a36Sopenharmony_ci ret); 37362306a36Sopenharmony_ci return ret; 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci /* Switch to continuous mode */ 37762306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_CTL, 37862306a36Sopenharmony_ci RR_ADC_CTL_CONTINUOUS_SEL, 37962306a36Sopenharmony_ci RR_ADC_CTL_CONTINUOUS_SEL); 38062306a36Sopenharmony_ci if (ret < 0) 38162306a36Sopenharmony_ci dev_err(chip->dev, "Update to continuous mode failed:%d\n", 38262306a36Sopenharmony_ci ret); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci return ret; 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic int rradc_disable_continuous_mode(struct rradc_chip *chip) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci int ret; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* Switch to non continuous mode */ 39262306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_CTL, 39362306a36Sopenharmony_ci RR_ADC_CTL_CONTINUOUS_SEL, 0); 39462306a36Sopenharmony_ci if (ret < 0) 39562306a36Sopenharmony_ci dev_err(chip->dev, "Update to non-continuous mode failed:%d\n", 39662306a36Sopenharmony_ci ret); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return ret; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic bool rradc_is_ready(struct rradc_chip *chip, 40262306a36Sopenharmony_ci enum rradc_channel_id chan_address) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci const struct rradc_channel *chan = &rradc_chans[chan_address]; 40562306a36Sopenharmony_ci int ret; 40662306a36Sopenharmony_ci unsigned int status, mask; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* BATT_ID STS bit does not get set initially */ 40962306a36Sopenharmony_ci switch (chan_address) { 41062306a36Sopenharmony_ci case RR_ADC_BATT_ID: 41162306a36Sopenharmony_ci mask = RR_ADC_STS_CHANNEL_STS; 41262306a36Sopenharmony_ci break; 41362306a36Sopenharmony_ci default: 41462306a36Sopenharmony_ci mask = RR_ADC_STS_CHANNEL_READING_MASK; 41562306a36Sopenharmony_ci break; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci ret = regmap_read(chip->regmap, chip->base + chan->status, &status); 41962306a36Sopenharmony_ci if (ret < 0 || !(status & mask)) 42062306a36Sopenharmony_ci return false; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci return true; 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic int rradc_read_status_in_cont_mode(struct rradc_chip *chip, 42662306a36Sopenharmony_ci enum rradc_channel_id chan_address) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci const struct rradc_channel *chan = &rradc_chans[chan_address]; 42962306a36Sopenharmony_ci const struct iio_chan_spec *iio_chan = &rradc_iio_chans[chan_address]; 43062306a36Sopenharmony_ci int ret, i; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (chan->trigger_mask == 0) { 43362306a36Sopenharmony_ci dev_err(chip->dev, "Channel doesn't have a trigger mask\n"); 43462306a36Sopenharmony_ci return -EINVAL; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, chip->base + chan->trigger_addr, 43862306a36Sopenharmony_ci chan->trigger_mask, chan->trigger_mask); 43962306a36Sopenharmony_ci if (ret < 0) { 44062306a36Sopenharmony_ci dev_err(chip->dev, 44162306a36Sopenharmony_ci "Failed to apply trigger for channel '%s' ret=%d\n", 44262306a36Sopenharmony_ci iio_chan->extend_name, ret); 44362306a36Sopenharmony_ci return ret; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci ret = rradc_enable_continuous_mode(chip); 44762306a36Sopenharmony_ci if (ret < 0) { 44862306a36Sopenharmony_ci dev_err(chip->dev, "Failed to switch to continuous mode\n"); 44962306a36Sopenharmony_ci goto disable_trigger; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* 45362306a36Sopenharmony_ci * The wait/sleep values were found through trial and error, 45462306a36Sopenharmony_ci * this is mostly for the battery ID channel which takes some 45562306a36Sopenharmony_ci * time to settle. 45662306a36Sopenharmony_ci */ 45762306a36Sopenharmony_ci for (i = 0; i < 5; i++) { 45862306a36Sopenharmony_ci if (rradc_is_ready(chip, chan_address)) 45962306a36Sopenharmony_ci break; 46062306a36Sopenharmony_ci usleep_range(50000, 50000 + 500); 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (i == 5) { 46462306a36Sopenharmony_ci dev_err(chip->dev, "Channel '%s' is not ready\n", 46562306a36Sopenharmony_ci iio_chan->extend_name); 46662306a36Sopenharmony_ci ret = -ETIMEDOUT; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci rradc_disable_continuous_mode(chip); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cidisable_trigger: 47262306a36Sopenharmony_ci regmap_update_bits(chip->regmap, chip->base + chan->trigger_addr, 47362306a36Sopenharmony_ci chan->trigger_mask, 0); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci return ret; 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic int rradc_prepare_batt_id_conversion(struct rradc_chip *chip, 47962306a36Sopenharmony_ci enum rradc_channel_id chan_address, 48062306a36Sopenharmony_ci u16 *data) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci int ret; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_CTRL, 48562306a36Sopenharmony_ci RR_ADC_BATT_ID_CTRL_CHANNEL_CONV, 48662306a36Sopenharmony_ci RR_ADC_BATT_ID_CTRL_CHANNEL_CONV); 48762306a36Sopenharmony_ci if (ret < 0) { 48862306a36Sopenharmony_ci dev_err(chip->dev, "Enabling BATT ID channel failed:%d\n", ret); 48962306a36Sopenharmony_ci return ret; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, 49362306a36Sopenharmony_ci chip->base + RR_ADC_BATT_ID_TRIGGER, 49462306a36Sopenharmony_ci RR_ADC_TRIGGER_CTL, RR_ADC_TRIGGER_CTL); 49562306a36Sopenharmony_ci if (ret < 0) { 49662306a36Sopenharmony_ci dev_err(chip->dev, "BATT_ID trigger set failed:%d\n", ret); 49762306a36Sopenharmony_ci goto out_disable_batt_id; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci ret = rradc_read_status_in_cont_mode(chip, chan_address); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* Reset registers back to default values */ 50362306a36Sopenharmony_ci regmap_update_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_TRIGGER, 50462306a36Sopenharmony_ci RR_ADC_TRIGGER_CTL, 0); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ciout_disable_batt_id: 50762306a36Sopenharmony_ci regmap_update_bits(chip->regmap, chip->base + RR_ADC_BATT_ID_CTRL, 50862306a36Sopenharmony_ci RR_ADC_BATT_ID_CTRL_CHANNEL_CONV, 0); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci return ret; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic int rradc_do_conversion(struct rradc_chip *chip, 51462306a36Sopenharmony_ci enum rradc_channel_id chan_address, u16 *data) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci const struct rradc_channel *chan = &rradc_chans[chan_address]; 51762306a36Sopenharmony_ci const struct iio_chan_spec *iio_chan = &rradc_iio_chans[chan_address]; 51862306a36Sopenharmony_ci int ret; 51962306a36Sopenharmony_ci __le16 buf[3]; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci mutex_lock(&chip->conversion_lock); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci switch (chan_address) { 52462306a36Sopenharmony_ci case RR_ADC_BATT_ID: 52562306a36Sopenharmony_ci ret = rradc_prepare_batt_id_conversion(chip, chan_address, data); 52662306a36Sopenharmony_ci if (ret < 0) { 52762306a36Sopenharmony_ci dev_err(chip->dev, "Battery ID conversion failed:%d\n", 52862306a36Sopenharmony_ci ret); 52962306a36Sopenharmony_ci goto unlock_out; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci break; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci case RR_ADC_USBIN_V: 53462306a36Sopenharmony_ci case RR_ADC_DIE_TEMP: 53562306a36Sopenharmony_ci ret = rradc_read_status_in_cont_mode(chip, chan_address); 53662306a36Sopenharmony_ci if (ret < 0) { 53762306a36Sopenharmony_ci dev_err(chip->dev, 53862306a36Sopenharmony_ci "Error reading in continuous mode:%d\n", ret); 53962306a36Sopenharmony_ci goto unlock_out; 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci break; 54262306a36Sopenharmony_ci default: 54362306a36Sopenharmony_ci if (!rradc_is_ready(chip, chan_address)) { 54462306a36Sopenharmony_ci /* 54562306a36Sopenharmony_ci * Usually this means the channel isn't attached, for example 54662306a36Sopenharmony_ci * the in_voltage_usbin_v_input channel will not be ready if 54762306a36Sopenharmony_ci * no USB cable is attached 54862306a36Sopenharmony_ci */ 54962306a36Sopenharmony_ci dev_dbg(chip->dev, "channel '%s' is not ready\n", 55062306a36Sopenharmony_ci iio_chan->extend_name); 55162306a36Sopenharmony_ci ret = -ENODATA; 55262306a36Sopenharmony_ci goto unlock_out; 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci break; 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci ret = rradc_read(chip, chan->lsb, buf, chan->size); 55862306a36Sopenharmony_ci if (ret) { 55962306a36Sopenharmony_ci dev_err(chip->dev, "read data failed\n"); 56062306a36Sopenharmony_ci goto unlock_out; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* 56462306a36Sopenharmony_ci * For the battery ID we read the register for every ID ADC and then 56562306a36Sopenharmony_ci * see which one is actually connected. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci if (chan_address == RR_ADC_BATT_ID) { 56862306a36Sopenharmony_ci u16 batt_id_150 = le16_to_cpu(buf[2]); 56962306a36Sopenharmony_ci u16 batt_id_15 = le16_to_cpu(buf[1]); 57062306a36Sopenharmony_ci u16 batt_id_5 = le16_to_cpu(buf[0]); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (!batt_id_150 && !batt_id_15 && !batt_id_5) { 57362306a36Sopenharmony_ci dev_err(chip->dev, 57462306a36Sopenharmony_ci "Invalid batt_id values with all zeros\n"); 57562306a36Sopenharmony_ci ret = -EINVAL; 57662306a36Sopenharmony_ci goto unlock_out; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (batt_id_150 <= RR_ADC_BATT_ID_RANGE) { 58062306a36Sopenharmony_ci *data = batt_id_150; 58162306a36Sopenharmony_ci chip->batt_id_data = 150; 58262306a36Sopenharmony_ci } else if (batt_id_15 <= RR_ADC_BATT_ID_RANGE) { 58362306a36Sopenharmony_ci *data = batt_id_15; 58462306a36Sopenharmony_ci chip->batt_id_data = 15; 58562306a36Sopenharmony_ci } else { 58662306a36Sopenharmony_ci *data = batt_id_5; 58762306a36Sopenharmony_ci chip->batt_id_data = 5; 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci } else { 59062306a36Sopenharmony_ci /* 59162306a36Sopenharmony_ci * All of the other channels are either 1 or 2 bytes. 59262306a36Sopenharmony_ci * We can rely on the second byte being 0 for 1-byte channels. 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_ci *data = le16_to_cpu(buf[0]); 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ciunlock_out: 59862306a36Sopenharmony_ci mutex_unlock(&chip->conversion_lock); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci return ret; 60162306a36Sopenharmony_ci} 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_cistatic int rradc_read_scale(struct rradc_chip *chip, int chan_address, int *val, 60462306a36Sopenharmony_ci int *val2) 60562306a36Sopenharmony_ci{ 60662306a36Sopenharmony_ci int64_t fab_offset, fab_slope; 60762306a36Sopenharmony_ci int ret; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci ret = rradc_get_fab_coeff(chip, &fab_offset, &fab_slope); 61062306a36Sopenharmony_ci if (ret < 0) { 61162306a36Sopenharmony_ci dev_err(chip->dev, "Unable to get fab id coefficients\n"); 61262306a36Sopenharmony_ci return -EINVAL; 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci switch (chan_address) { 61662306a36Sopenharmony_ci case RR_ADC_SKIN_TEMP: 61762306a36Sopenharmony_ci *val = MILLI; 61862306a36Sopenharmony_ci *val2 = RR_ADC_BATT_THERM_LSB_K; 61962306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 62062306a36Sopenharmony_ci case RR_ADC_USBIN_I: 62162306a36Sopenharmony_ci *val = RR_ADC_CURR_USBIN_INPUT_FACTOR_MIL * 62262306a36Sopenharmony_ci RR_ADC_FS_VOLTAGE_MV; 62362306a36Sopenharmony_ci *val2 = RR_ADC_CHAN_MSB; 62462306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 62562306a36Sopenharmony_ci case RR_ADC_DCIN_I: 62662306a36Sopenharmony_ci *val = RR_ADC_CURR_INPUT_FACTOR * RR_ADC_FS_VOLTAGE_MV; 62762306a36Sopenharmony_ci *val2 = RR_ADC_CHAN_MSB; 62862306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 62962306a36Sopenharmony_ci case RR_ADC_USBIN_V: 63062306a36Sopenharmony_ci case RR_ADC_DCIN_V: 63162306a36Sopenharmony_ci *val = RR_ADC_VOLT_INPUT_FACTOR * RR_ADC_FS_VOLTAGE_MV * MILLI; 63262306a36Sopenharmony_ci *val2 = RR_ADC_CHAN_MSB; 63362306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 63462306a36Sopenharmony_ci case RR_ADC_GPIO: 63562306a36Sopenharmony_ci *val = RR_ADC_GPIO_FS_RANGE; 63662306a36Sopenharmony_ci *val2 = RR_ADC_CHAN_MSB; 63762306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 63862306a36Sopenharmony_ci case RR_ADC_CHG_TEMP: 63962306a36Sopenharmony_ci /* 64062306a36Sopenharmony_ci * We divide val2 by MILLI instead of multiplying val 64162306a36Sopenharmony_ci * to avoid an integer overflow. 64262306a36Sopenharmony_ci */ 64362306a36Sopenharmony_ci *val = -RR_ADC_TEMP_FS_VOLTAGE_NUM; 64462306a36Sopenharmony_ci *val2 = div64_s64(RR_ADC_TEMP_FS_VOLTAGE_DEN * RR_ADC_CHAN_MSB * 64562306a36Sopenharmony_ci fab_slope, 64662306a36Sopenharmony_ci MILLI); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 64962306a36Sopenharmony_ci case RR_ADC_DIE_TEMP: 65062306a36Sopenharmony_ci *val = RR_ADC_TEMP_FS_VOLTAGE_NUM; 65162306a36Sopenharmony_ci *val2 = RR_ADC_TEMP_FS_VOLTAGE_DEN * RR_ADC_CHAN_MSB * 65262306a36Sopenharmony_ci RR_ADC_DIE_TEMP_SLOPE; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 65562306a36Sopenharmony_ci default: 65662306a36Sopenharmony_ci return -EINVAL; 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_cistatic int rradc_read_offset(struct rradc_chip *chip, int chan_address, int *val) 66162306a36Sopenharmony_ci{ 66262306a36Sopenharmony_ci int64_t fab_offset, fab_slope; 66362306a36Sopenharmony_ci int64_t offset1, offset2; 66462306a36Sopenharmony_ci int ret; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci switch (chan_address) { 66762306a36Sopenharmony_ci case RR_ADC_SKIN_TEMP: 66862306a36Sopenharmony_ci /* 66962306a36Sopenharmony_ci * Offset from kelvin to degC, divided by the 67062306a36Sopenharmony_ci * scale factor (250). We lose some precision here. 67162306a36Sopenharmony_ci * 273150 / 250 = 1092.6 67262306a36Sopenharmony_ci */ 67362306a36Sopenharmony_ci *val = div64_s64(ABSOLUTE_ZERO_MILLICELSIUS, 67462306a36Sopenharmony_ci (MILLI / RR_ADC_BATT_THERM_LSB_K)); 67562306a36Sopenharmony_ci return IIO_VAL_INT; 67662306a36Sopenharmony_ci case RR_ADC_CHG_TEMP: 67762306a36Sopenharmony_ci ret = rradc_get_fab_coeff(chip, &fab_offset, &fab_slope); 67862306a36Sopenharmony_ci if (ret < 0) { 67962306a36Sopenharmony_ci dev_err(chip->dev, 68062306a36Sopenharmony_ci "Unable to get fab id coefficients\n"); 68162306a36Sopenharmony_ci return -EINVAL; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci offset1 = -(fab_offset * RR_ADC_TEMP_FS_VOLTAGE_DEN * 68462306a36Sopenharmony_ci RR_ADC_CHAN_MSB); 68562306a36Sopenharmony_ci offset1 += (int64_t)RR_ADC_TEMP_FS_VOLTAGE_NUM / 2ULL; 68662306a36Sopenharmony_ci offset1 = div64_s64(offset1, 68762306a36Sopenharmony_ci (int64_t)(RR_ADC_TEMP_FS_VOLTAGE_NUM)); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci offset2 = (int64_t)RR_ADC_CHG_TEMP_OFFSET_MILLI_DEGC * 69062306a36Sopenharmony_ci RR_ADC_TEMP_FS_VOLTAGE_DEN * RR_ADC_CHAN_MSB * 69162306a36Sopenharmony_ci (int64_t)fab_slope; 69262306a36Sopenharmony_ci offset2 += ((int64_t)MILLI * RR_ADC_TEMP_FS_VOLTAGE_NUM) / 2; 69362306a36Sopenharmony_ci offset2 = div64_s64( 69462306a36Sopenharmony_ci offset2, ((int64_t)MILLI * RR_ADC_TEMP_FS_VOLTAGE_NUM)); 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci /* 69762306a36Sopenharmony_ci * The -1 is to compensate for lost precision. 69862306a36Sopenharmony_ci * It should actually be -0.7906976744186046. 69962306a36Sopenharmony_ci * This works out to every value being off 70062306a36Sopenharmony_ci * by about +0.091 degrees C after applying offset and scale. 70162306a36Sopenharmony_ci */ 70262306a36Sopenharmony_ci *val = (int)(offset1 - offset2 - 1); 70362306a36Sopenharmony_ci return IIO_VAL_INT; 70462306a36Sopenharmony_ci case RR_ADC_DIE_TEMP: 70562306a36Sopenharmony_ci offset1 = -RR_ADC_DIE_TEMP_OFFSET * 70662306a36Sopenharmony_ci (int64_t)RR_ADC_TEMP_FS_VOLTAGE_DEN * 70762306a36Sopenharmony_ci (int64_t)RR_ADC_CHAN_MSB; 70862306a36Sopenharmony_ci offset1 = div64_s64(offset1, RR_ADC_TEMP_FS_VOLTAGE_NUM); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci offset2 = -(int64_t)RR_ADC_CHG_TEMP_OFFSET_MILLI_DEGC * 71162306a36Sopenharmony_ci RR_ADC_TEMP_FS_VOLTAGE_DEN * RR_ADC_CHAN_MSB * 71262306a36Sopenharmony_ci RR_ADC_DIE_TEMP_SLOPE; 71362306a36Sopenharmony_ci offset2 = div64_s64(offset2, 71462306a36Sopenharmony_ci ((int64_t)RR_ADC_TEMP_FS_VOLTAGE_NUM)); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /* 71762306a36Sopenharmony_ci * The result is -339, it should be -338.69789, this results 71862306a36Sopenharmony_ci * in the calculated die temp being off by 71962306a36Sopenharmony_ci * -0.004 - -0.0175 degrees C 72062306a36Sopenharmony_ci */ 72162306a36Sopenharmony_ci *val = (int)(offset1 - offset2); 72262306a36Sopenharmony_ci return IIO_VAL_INT; 72362306a36Sopenharmony_ci default: 72462306a36Sopenharmony_ci break; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci return -EINVAL; 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_cistatic int rradc_read_raw(struct iio_dev *indio_dev, 73062306a36Sopenharmony_ci struct iio_chan_spec const *chan_spec, int *val, 73162306a36Sopenharmony_ci int *val2, long mask) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci struct rradc_chip *chip = iio_priv(indio_dev); 73462306a36Sopenharmony_ci const struct rradc_channel *chan; 73562306a36Sopenharmony_ci int ret; 73662306a36Sopenharmony_ci u16 adc_code; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci if (chan_spec->address >= RR_ADC_CHAN_MAX) { 73962306a36Sopenharmony_ci dev_err(chip->dev, "Invalid channel index:%lu\n", 74062306a36Sopenharmony_ci chan_spec->address); 74162306a36Sopenharmony_ci return -EINVAL; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci switch (mask) { 74562306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 74662306a36Sopenharmony_ci return rradc_read_scale(chip, chan_spec->address, val, val2); 74762306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 74862306a36Sopenharmony_ci return rradc_read_offset(chip, chan_spec->address, val); 74962306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 75062306a36Sopenharmony_ci ret = rradc_do_conversion(chip, chan_spec->address, &adc_code); 75162306a36Sopenharmony_ci if (ret < 0) 75262306a36Sopenharmony_ci return ret; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci *val = adc_code; 75562306a36Sopenharmony_ci return IIO_VAL_INT; 75662306a36Sopenharmony_ci case IIO_CHAN_INFO_PROCESSED: 75762306a36Sopenharmony_ci chan = &rradc_chans[chan_spec->address]; 75862306a36Sopenharmony_ci if (!chan->scale_fn) 75962306a36Sopenharmony_ci return -EINVAL; 76062306a36Sopenharmony_ci ret = rradc_do_conversion(chip, chan_spec->address, &adc_code); 76162306a36Sopenharmony_ci if (ret < 0) 76262306a36Sopenharmony_ci return ret; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci *val = chan->scale_fn(chip, adc_code, val); 76562306a36Sopenharmony_ci return IIO_VAL_INT; 76662306a36Sopenharmony_ci default: 76762306a36Sopenharmony_ci return -EINVAL; 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic int rradc_read_label(struct iio_dev *indio_dev, 77262306a36Sopenharmony_ci struct iio_chan_spec const *chan, char *label) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci return snprintf(label, PAGE_SIZE, "%s\n", 77562306a36Sopenharmony_ci rradc_chans[chan->address].label); 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic const struct iio_info rradc_info = { 77962306a36Sopenharmony_ci .read_raw = rradc_read_raw, 78062306a36Sopenharmony_ci .read_label = rradc_read_label, 78162306a36Sopenharmony_ci}; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic const struct rradc_channel rradc_chans[RR_ADC_CHAN_MAX] = { 78462306a36Sopenharmony_ci { 78562306a36Sopenharmony_ci .label = "batt_id", 78662306a36Sopenharmony_ci .scale_fn = rradc_post_process_batt_id, 78762306a36Sopenharmony_ci .lsb = RR_ADC_BATT_ID_5_LSB, 78862306a36Sopenharmony_ci .status = RR_ADC_BATT_ID_STS, 78962306a36Sopenharmony_ci .size = 6, 79062306a36Sopenharmony_ci .trigger_addr = RR_ADC_BATT_ID_TRIGGER, 79162306a36Sopenharmony_ci .trigger_mask = BIT(0), 79262306a36Sopenharmony_ci }, { 79362306a36Sopenharmony_ci .label = "batt", 79462306a36Sopenharmony_ci .lsb = RR_ADC_BATT_THERM_LSB, 79562306a36Sopenharmony_ci .status = RR_ADC_BATT_THERM_STS, 79662306a36Sopenharmony_ci .size = 2, 79762306a36Sopenharmony_ci .trigger_addr = RR_ADC_BATT_THERM_TRIGGER, 79862306a36Sopenharmony_ci }, { 79962306a36Sopenharmony_ci .label = "pmi8998_skin", 80062306a36Sopenharmony_ci .lsb = RR_ADC_SKIN_TEMP_LSB, 80162306a36Sopenharmony_ci .status = RR_ADC_AUX_THERM_STS, 80262306a36Sopenharmony_ci .size = 2, 80362306a36Sopenharmony_ci .trigger_addr = RR_ADC_AUX_THERM_TRIGGER, 80462306a36Sopenharmony_ci }, { 80562306a36Sopenharmony_ci .label = "usbin_i", 80662306a36Sopenharmony_ci .lsb = RR_ADC_USB_IN_I_LSB, 80762306a36Sopenharmony_ci .status = RR_ADC_USB_IN_I_STS, 80862306a36Sopenharmony_ci .size = 2, 80962306a36Sopenharmony_ci .trigger_addr = RR_ADC_USB_IN_I_TRIGGER, 81062306a36Sopenharmony_ci }, { 81162306a36Sopenharmony_ci .label = "usbin_v", 81262306a36Sopenharmony_ci .lsb = RR_ADC_USB_IN_V_LSB, 81362306a36Sopenharmony_ci .status = RR_ADC_USB_IN_V_STS, 81462306a36Sopenharmony_ci .size = 2, 81562306a36Sopenharmony_ci .trigger_addr = RR_ADC_USB_IN_V_TRIGGER, 81662306a36Sopenharmony_ci .trigger_mask = BIT(7), 81762306a36Sopenharmony_ci }, { 81862306a36Sopenharmony_ci .label = "dcin_i", 81962306a36Sopenharmony_ci .lsb = RR_ADC_DC_IN_I_LSB, 82062306a36Sopenharmony_ci .status = RR_ADC_DC_IN_I_STS, 82162306a36Sopenharmony_ci .size = 2, 82262306a36Sopenharmony_ci .trigger_addr = RR_ADC_DC_IN_I_TRIGGER, 82362306a36Sopenharmony_ci }, { 82462306a36Sopenharmony_ci .label = "dcin_v", 82562306a36Sopenharmony_ci .lsb = RR_ADC_DC_IN_V_LSB, 82662306a36Sopenharmony_ci .status = RR_ADC_DC_IN_V_STS, 82762306a36Sopenharmony_ci .size = 2, 82862306a36Sopenharmony_ci .trigger_addr = RR_ADC_DC_IN_V_TRIGGER, 82962306a36Sopenharmony_ci }, { 83062306a36Sopenharmony_ci .label = "pmi8998_die", 83162306a36Sopenharmony_ci .lsb = RR_ADC_PMI_DIE_TEMP_LSB, 83262306a36Sopenharmony_ci .status = RR_ADC_PMI_DIE_TEMP_STS, 83362306a36Sopenharmony_ci .size = 2, 83462306a36Sopenharmony_ci .trigger_addr = RR_ADC_PMI_DIE_TEMP_TRIGGER, 83562306a36Sopenharmony_ci .trigger_mask = RR_ADC_TRIGGER_EVERY_CYCLE, 83662306a36Sopenharmony_ci }, { 83762306a36Sopenharmony_ci .label = "chg", 83862306a36Sopenharmony_ci .lsb = RR_ADC_CHARGER_TEMP_LSB, 83962306a36Sopenharmony_ci .status = RR_ADC_CHARGER_TEMP_STS, 84062306a36Sopenharmony_ci .size = 2, 84162306a36Sopenharmony_ci .trigger_addr = RR_ADC_CHARGER_TEMP_TRIGGER, 84262306a36Sopenharmony_ci }, { 84362306a36Sopenharmony_ci .label = "gpio", 84462306a36Sopenharmony_ci .lsb = RR_ADC_GPIO_LSB, 84562306a36Sopenharmony_ci .status = RR_ADC_GPIO_STS, 84662306a36Sopenharmony_ci .size = 2, 84762306a36Sopenharmony_ci .trigger_addr = RR_ADC_GPIO_TRIGGER, 84862306a36Sopenharmony_ci }, 84962306a36Sopenharmony_ci}; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_cistatic const struct iio_chan_spec rradc_iio_chans[RR_ADC_CHAN_MAX] = { 85262306a36Sopenharmony_ci { 85362306a36Sopenharmony_ci .type = IIO_RESISTANCE, 85462306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 85562306a36Sopenharmony_ci .address = RR_ADC_BATT_ID, 85662306a36Sopenharmony_ci .channel = 0, 85762306a36Sopenharmony_ci .indexed = 1, 85862306a36Sopenharmony_ci }, { 85962306a36Sopenharmony_ci .type = IIO_TEMP, 86062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 86162306a36Sopenharmony_ci .address = RR_ADC_BATT_THERM, 86262306a36Sopenharmony_ci .channel = 0, 86362306a36Sopenharmony_ci .indexed = 1, 86462306a36Sopenharmony_ci }, { 86562306a36Sopenharmony_ci .type = IIO_TEMP, 86662306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 86762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | 86862306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET), 86962306a36Sopenharmony_ci .address = RR_ADC_SKIN_TEMP, 87062306a36Sopenharmony_ci .channel = 1, 87162306a36Sopenharmony_ci .indexed = 1, 87262306a36Sopenharmony_ci }, { 87362306a36Sopenharmony_ci .type = IIO_CURRENT, 87462306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 87562306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 87662306a36Sopenharmony_ci .address = RR_ADC_USBIN_I, 87762306a36Sopenharmony_ci .channel = 0, 87862306a36Sopenharmony_ci .indexed = 1, 87962306a36Sopenharmony_ci }, { 88062306a36Sopenharmony_ci .type = IIO_VOLTAGE, 88162306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 88262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 88362306a36Sopenharmony_ci .address = RR_ADC_USBIN_V, 88462306a36Sopenharmony_ci .channel = 0, 88562306a36Sopenharmony_ci .indexed = 1, 88662306a36Sopenharmony_ci }, { 88762306a36Sopenharmony_ci .type = IIO_CURRENT, 88862306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 88962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 89062306a36Sopenharmony_ci .address = RR_ADC_DCIN_I, 89162306a36Sopenharmony_ci .channel = 1, 89262306a36Sopenharmony_ci .indexed = 1, 89362306a36Sopenharmony_ci }, { 89462306a36Sopenharmony_ci .type = IIO_VOLTAGE, 89562306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 89662306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 89762306a36Sopenharmony_ci .address = RR_ADC_DCIN_V, 89862306a36Sopenharmony_ci .channel = 1, 89962306a36Sopenharmony_ci .indexed = 1, 90062306a36Sopenharmony_ci }, { 90162306a36Sopenharmony_ci .type = IIO_TEMP, 90262306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 90362306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | 90462306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET), 90562306a36Sopenharmony_ci .address = RR_ADC_DIE_TEMP, 90662306a36Sopenharmony_ci .channel = 2, 90762306a36Sopenharmony_ci .indexed = 1, 90862306a36Sopenharmony_ci }, { 90962306a36Sopenharmony_ci .type = IIO_TEMP, 91062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 91162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET) | 91262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 91362306a36Sopenharmony_ci .address = RR_ADC_CHG_TEMP, 91462306a36Sopenharmony_ci .channel = 3, 91562306a36Sopenharmony_ci .indexed = 1, 91662306a36Sopenharmony_ci }, { 91762306a36Sopenharmony_ci .type = IIO_VOLTAGE, 91862306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | 91962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 92062306a36Sopenharmony_ci .address = RR_ADC_GPIO, 92162306a36Sopenharmony_ci .channel = 2, 92262306a36Sopenharmony_ci .indexed = 1, 92362306a36Sopenharmony_ci }, 92462306a36Sopenharmony_ci}; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_cistatic int rradc_probe(struct platform_device *pdev) 92762306a36Sopenharmony_ci{ 92862306a36Sopenharmony_ci struct device *dev = &pdev->dev; 92962306a36Sopenharmony_ci struct iio_dev *indio_dev; 93062306a36Sopenharmony_ci struct rradc_chip *chip; 93162306a36Sopenharmony_ci int ret, i, batt_id_delay; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(dev, sizeof(*chip)); 93462306a36Sopenharmony_ci if (!indio_dev) 93562306a36Sopenharmony_ci return -ENOMEM; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci chip = iio_priv(indio_dev); 93862306a36Sopenharmony_ci chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); 93962306a36Sopenharmony_ci if (!chip->regmap) { 94062306a36Sopenharmony_ci dev_err(dev, "Couldn't get parent's regmap\n"); 94162306a36Sopenharmony_ci return -EINVAL; 94262306a36Sopenharmony_ci } 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci chip->dev = dev; 94562306a36Sopenharmony_ci mutex_init(&chip->conversion_lock); 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci ret = device_property_read_u32(dev, "reg", &chip->base); 94862306a36Sopenharmony_ci if (ret < 0) { 94962306a36Sopenharmony_ci dev_err(chip->dev, "Couldn't find reg address, ret = %d\n", 95062306a36Sopenharmony_ci ret); 95162306a36Sopenharmony_ci return ret; 95262306a36Sopenharmony_ci } 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci batt_id_delay = -1; 95562306a36Sopenharmony_ci ret = device_property_read_u32(dev, "qcom,batt-id-delay-ms", 95662306a36Sopenharmony_ci &batt_id_delay); 95762306a36Sopenharmony_ci if (!ret) { 95862306a36Sopenharmony_ci for (i = 0; i < RRADC_BATT_ID_DELAY_MAX; i++) { 95962306a36Sopenharmony_ci if (batt_id_delay == batt_id_delays[i]) 96062306a36Sopenharmony_ci break; 96162306a36Sopenharmony_ci } 96262306a36Sopenharmony_ci if (i == RRADC_BATT_ID_DELAY_MAX) 96362306a36Sopenharmony_ci batt_id_delay = -1; 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci if (batt_id_delay >= 0) { 96762306a36Sopenharmony_ci batt_id_delay = FIELD_PREP(BATT_ID_SETTLE_MASK, batt_id_delay); 96862306a36Sopenharmony_ci ret = regmap_update_bits(chip->regmap, 96962306a36Sopenharmony_ci chip->base + RR_ADC_BATT_ID_CFG, 97062306a36Sopenharmony_ci batt_id_delay, batt_id_delay); 97162306a36Sopenharmony_ci if (ret < 0) { 97262306a36Sopenharmony_ci dev_err(chip->dev, 97362306a36Sopenharmony_ci "BATT_ID settling time config failed:%d\n", 97462306a36Sopenharmony_ci ret); 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci /* Get the PMIC revision, we need it to handle some varying coefficients */ 97962306a36Sopenharmony_ci chip->pmic = qcom_pmic_get(chip->dev); 98062306a36Sopenharmony_ci if (IS_ERR(chip->pmic)) { 98162306a36Sopenharmony_ci dev_err(chip->dev, "Unable to get reference to PMIC device\n"); 98262306a36Sopenharmony_ci return PTR_ERR(chip->pmic); 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci switch (chip->pmic->subtype) { 98662306a36Sopenharmony_ci case PMI8998_SUBTYPE: 98762306a36Sopenharmony_ci indio_dev->name = "pmi8998-rradc"; 98862306a36Sopenharmony_ci break; 98962306a36Sopenharmony_ci case PM660_SUBTYPE: 99062306a36Sopenharmony_ci indio_dev->name = "pm660-rradc"; 99162306a36Sopenharmony_ci break; 99262306a36Sopenharmony_ci default: 99362306a36Sopenharmony_ci indio_dev->name = DRIVER_NAME; 99462306a36Sopenharmony_ci break; 99562306a36Sopenharmony_ci } 99662306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 99762306a36Sopenharmony_ci indio_dev->info = &rradc_info; 99862306a36Sopenharmony_ci indio_dev->channels = rradc_iio_chans; 99962306a36Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(rradc_iio_chans); 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci return devm_iio_device_register(dev, indio_dev); 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_cistatic const struct of_device_id rradc_match_table[] = { 100562306a36Sopenharmony_ci { .compatible = "qcom,pm660-rradc" }, 100662306a36Sopenharmony_ci { .compatible = "qcom,pmi8998-rradc" }, 100762306a36Sopenharmony_ci {} 100862306a36Sopenharmony_ci}; 100962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rradc_match_table); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_cistatic struct platform_driver rradc_driver = { 101262306a36Sopenharmony_ci .driver = { 101362306a36Sopenharmony_ci .name = DRIVER_NAME, 101462306a36Sopenharmony_ci .of_match_table = rradc_match_table, 101562306a36Sopenharmony_ci }, 101662306a36Sopenharmony_ci .probe = rradc_probe, 101762306a36Sopenharmony_ci}; 101862306a36Sopenharmony_cimodule_platform_driver(rradc_driver); 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ciMODULE_DESCRIPTION("QCOM SPMI PMIC RR ADC driver"); 102162306a36Sopenharmony_ciMODULE_AUTHOR("Caleb Connolly <caleb.connolly@linaro.org>"); 102262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1023