162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) ST-Ericsson SA 2010
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Arun R Murthy <arun.murthy@stericsson.com>
662306a36Sopenharmony_ci * Author: Daniel Willerud <daniel.willerud@stericsson.com>
762306a36Sopenharmony_ci * Author: Johan Palsson <johan.palsson@stericsson.com>
862306a36Sopenharmony_ci * Author: M'boumba Cedric Madianga
962306a36Sopenharmony_ci * Author: Linus Walleij <linus.walleij@linaro.org>
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * AB8500 General Purpose ADC driver. The AB8500 uses reference voltages:
1262306a36Sopenharmony_ci * VinVADC, and VADC relative to GND to do its job. It monitors main and backup
1362306a36Sopenharmony_ci * battery voltages, AC (mains) voltage, USB cable voltage, as well as voltages
1462306a36Sopenharmony_ci * representing the temperature of the chip die and battery, accessory
1562306a36Sopenharmony_ci * detection by resistance measurements using relative voltages and GSM burst
1662306a36Sopenharmony_ci * information.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * Some of the voltages are measured on external pins on the IC, such as
1962306a36Sopenharmony_ci * battery temperature or "ADC aux" 1 and 2. Other voltages are internal rails
2062306a36Sopenharmony_ci * from other parts of the ASIC such as main charger voltage, main and battery
2162306a36Sopenharmony_ci * backup voltage or USB VBUS voltage. For this reason drivers for other
2262306a36Sopenharmony_ci * parts of the system are required to obtain handles to the ADC to do work
2362306a36Sopenharmony_ci * for them and the IIO driver provides arbitration among these consumers.
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci#include <linux/init.h>
2662306a36Sopenharmony_ci#include <linux/bits.h>
2762306a36Sopenharmony_ci#include <linux/iio/iio.h>
2862306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
2962306a36Sopenharmony_ci#include <linux/device.h>
3062306a36Sopenharmony_ci#include <linux/interrupt.h>
3162306a36Sopenharmony_ci#include <linux/spinlock.h>
3262306a36Sopenharmony_ci#include <linux/delay.h>
3362306a36Sopenharmony_ci#include <linux/pm_runtime.h>
3462306a36Sopenharmony_ci#include <linux/platform_device.h>
3562306a36Sopenharmony_ci#include <linux/completion.h>
3662306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
3762306a36Sopenharmony_ci#include <linux/random.h>
3862306a36Sopenharmony_ci#include <linux/err.h>
3962306a36Sopenharmony_ci#include <linux/slab.h>
4062306a36Sopenharmony_ci#include <linux/mfd/abx500.h>
4162306a36Sopenharmony_ci#include <linux/mfd/abx500/ab8500.h>
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* GPADC register offsets and bit definitions */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_REG		0x00
4662306a36Sopenharmony_ci/* GPADC control register 1 bits */
4762306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_DISABLE		0x00
4862306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_ENABLE		BIT(0)
4962306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_TRIG_ENA		BIT(1)
5062306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_START_SW_CONV	BIT(2)
5162306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_BTEMP_PULL_UP	BIT(3)
5262306a36Sopenharmony_ci/* 0 = use rising edge, 1 = use falling edge */
5362306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_TRIG_EDGE		BIT(4)
5462306a36Sopenharmony_ci/* 0 = use VTVOUT, 1 = use VRTC as pull-up supply for battery temp NTC */
5562306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_PUPSUPSEL		BIT(5)
5662306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_BUF_ENA		BIT(6)
5762306a36Sopenharmony_ci#define AB8500_GPADC_CTRL1_ICHAR_ENA		BIT(7)
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#define AB8500_GPADC_CTRL2_REG		0x01
6062306a36Sopenharmony_ci#define AB8500_GPADC_CTRL3_REG		0x02
6162306a36Sopenharmony_ci/*
6262306a36Sopenharmony_ci * GPADC control register 2 and 3 bits
6362306a36Sopenharmony_ci * the bit layout is the same for SW and HW conversion set-up
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_ci#define AB8500_GPADC_CTRL2_AVG_1		0x00
6662306a36Sopenharmony_ci#define AB8500_GPADC_CTRL2_AVG_4		BIT(5)
6762306a36Sopenharmony_ci#define AB8500_GPADC_CTRL2_AVG_8		BIT(6)
6862306a36Sopenharmony_ci#define AB8500_GPADC_CTRL2_AVG_16		(BIT(5) | BIT(6))
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cienum ab8500_gpadc_channel {
7162306a36Sopenharmony_ci	AB8500_GPADC_CHAN_UNUSED = 0x00,
7262306a36Sopenharmony_ci	AB8500_GPADC_CHAN_BAT_CTRL = 0x01,
7362306a36Sopenharmony_ci	AB8500_GPADC_CHAN_BAT_TEMP = 0x02,
7462306a36Sopenharmony_ci	/* This is not used on AB8505 */
7562306a36Sopenharmony_ci	AB8500_GPADC_CHAN_MAIN_CHARGER = 0x03,
7662306a36Sopenharmony_ci	AB8500_GPADC_CHAN_ACC_DET_1 = 0x04,
7762306a36Sopenharmony_ci	AB8500_GPADC_CHAN_ACC_DET_2 = 0x05,
7862306a36Sopenharmony_ci	AB8500_GPADC_CHAN_ADC_AUX_1 = 0x06,
7962306a36Sopenharmony_ci	AB8500_GPADC_CHAN_ADC_AUX_2 = 0x07,
8062306a36Sopenharmony_ci	AB8500_GPADC_CHAN_VBAT_A = 0x08,
8162306a36Sopenharmony_ci	AB8500_GPADC_CHAN_VBUS = 0x09,
8262306a36Sopenharmony_ci	AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT = 0x0a,
8362306a36Sopenharmony_ci	AB8500_GPADC_CHAN_USB_CHARGER_CURRENT = 0x0b,
8462306a36Sopenharmony_ci	AB8500_GPADC_CHAN_BACKUP_BAT = 0x0c,
8562306a36Sopenharmony_ci	/* Only on AB8505 */
8662306a36Sopenharmony_ci	AB8505_GPADC_CHAN_DIE_TEMP = 0x0d,
8762306a36Sopenharmony_ci	AB8500_GPADC_CHAN_ID = 0x0e,
8862306a36Sopenharmony_ci	AB8500_GPADC_CHAN_INTERNAL_TEST_1 = 0x0f,
8962306a36Sopenharmony_ci	AB8500_GPADC_CHAN_INTERNAL_TEST_2 = 0x10,
9062306a36Sopenharmony_ci	AB8500_GPADC_CHAN_INTERNAL_TEST_3 = 0x11,
9162306a36Sopenharmony_ci	/* FIXME: Applicable to all ASIC variants? */
9262306a36Sopenharmony_ci	AB8500_GPADC_CHAN_XTAL_TEMP = 0x12,
9362306a36Sopenharmony_ci	AB8500_GPADC_CHAN_VBAT_TRUE_MEAS = 0x13,
9462306a36Sopenharmony_ci	/* FIXME: Doesn't seem to work with pure AB8500 */
9562306a36Sopenharmony_ci	AB8500_GPADC_CHAN_BAT_CTRL_AND_IBAT = 0x1c,
9662306a36Sopenharmony_ci	AB8500_GPADC_CHAN_VBAT_MEAS_AND_IBAT = 0x1d,
9762306a36Sopenharmony_ci	AB8500_GPADC_CHAN_VBAT_TRUE_MEAS_AND_IBAT = 0x1e,
9862306a36Sopenharmony_ci	AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT = 0x1f,
9962306a36Sopenharmony_ci	/*
10062306a36Sopenharmony_ci	 * Virtual channel used only for ibat conversion to ampere.
10162306a36Sopenharmony_ci	 * Battery current conversion (ibat) cannot be requested as a
10262306a36Sopenharmony_ci	 * single conversion but it is always requested in combination
10362306a36Sopenharmony_ci	 * with other input requests.
10462306a36Sopenharmony_ci	 */
10562306a36Sopenharmony_ci	AB8500_GPADC_CHAN_IBAT_VIRTUAL = 0xFF,
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#define AB8500_GPADC_AUTO_TIMER_REG	0x03
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#define AB8500_GPADC_STAT_REG		0x04
11162306a36Sopenharmony_ci#define AB8500_GPADC_STAT_BUSY		BIT(0)
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#define AB8500_GPADC_MANDATAL_REG	0x05
11462306a36Sopenharmony_ci#define AB8500_GPADC_MANDATAH_REG	0x06
11562306a36Sopenharmony_ci#define AB8500_GPADC_AUTODATAL_REG	0x07
11662306a36Sopenharmony_ci#define AB8500_GPADC_AUTODATAH_REG	0x08
11762306a36Sopenharmony_ci#define AB8500_GPADC_MUX_CTRL_REG	0x09
11862306a36Sopenharmony_ci#define AB8540_GPADC_MANDATA2L_REG	0x09
11962306a36Sopenharmony_ci#define AB8540_GPADC_MANDATA2H_REG	0x0A
12062306a36Sopenharmony_ci#define AB8540_GPADC_APEAAX_REG		0x10
12162306a36Sopenharmony_ci#define AB8540_GPADC_APEAAT_REG		0x11
12262306a36Sopenharmony_ci#define AB8540_GPADC_APEAAM_REG		0x12
12362306a36Sopenharmony_ci#define AB8540_GPADC_APEAAH_REG		0x13
12462306a36Sopenharmony_ci#define AB8540_GPADC_APEAAL_REG		0x14
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/*
12762306a36Sopenharmony_ci * OTP register offsets
12862306a36Sopenharmony_ci * Bank : 0x15
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_ci#define AB8500_GPADC_CAL_1	0x0F
13162306a36Sopenharmony_ci#define AB8500_GPADC_CAL_2	0x10
13262306a36Sopenharmony_ci#define AB8500_GPADC_CAL_3	0x11
13362306a36Sopenharmony_ci#define AB8500_GPADC_CAL_4	0x12
13462306a36Sopenharmony_ci#define AB8500_GPADC_CAL_5	0x13
13562306a36Sopenharmony_ci#define AB8500_GPADC_CAL_6	0x14
13662306a36Sopenharmony_ci#define AB8500_GPADC_CAL_7	0x15
13762306a36Sopenharmony_ci/* New calibration for 8540 */
13862306a36Sopenharmony_ci#define AB8540_GPADC_OTP4_REG_7	0x38
13962306a36Sopenharmony_ci#define AB8540_GPADC_OTP4_REG_6	0x39
14062306a36Sopenharmony_ci#define AB8540_GPADC_OTP4_REG_5	0x3A
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#define AB8540_GPADC_DIS_ZERO	0x00
14362306a36Sopenharmony_ci#define AB8540_GPADC_EN_VBIAS_XTAL_TEMP	0x02
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/* GPADC constants from AB8500 spec, UM0836 */
14662306a36Sopenharmony_ci#define AB8500_ADC_RESOLUTION		1024
14762306a36Sopenharmony_ci#define AB8500_ADC_CH_BTEMP_MIN		0
14862306a36Sopenharmony_ci#define AB8500_ADC_CH_BTEMP_MAX		1350
14962306a36Sopenharmony_ci#define AB8500_ADC_CH_DIETEMP_MIN	0
15062306a36Sopenharmony_ci#define AB8500_ADC_CH_DIETEMP_MAX	1350
15162306a36Sopenharmony_ci#define AB8500_ADC_CH_CHG_V_MIN		0
15262306a36Sopenharmony_ci#define AB8500_ADC_CH_CHG_V_MAX		20030
15362306a36Sopenharmony_ci#define AB8500_ADC_CH_ACCDET2_MIN	0
15462306a36Sopenharmony_ci#define AB8500_ADC_CH_ACCDET2_MAX	2500
15562306a36Sopenharmony_ci#define AB8500_ADC_CH_VBAT_MIN		2300
15662306a36Sopenharmony_ci#define AB8500_ADC_CH_VBAT_MAX		4800
15762306a36Sopenharmony_ci#define AB8500_ADC_CH_CHG_I_MIN		0
15862306a36Sopenharmony_ci#define AB8500_ADC_CH_CHG_I_MAX		1500
15962306a36Sopenharmony_ci#define AB8500_ADC_CH_BKBAT_MIN		0
16062306a36Sopenharmony_ci#define AB8500_ADC_CH_BKBAT_MAX		3200
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/* GPADC constants from AB8540 spec */
16362306a36Sopenharmony_ci#define AB8500_ADC_CH_IBAT_MIN		(-6000) /* mA range measured by ADC for ibat */
16462306a36Sopenharmony_ci#define AB8500_ADC_CH_IBAT_MAX		6000
16562306a36Sopenharmony_ci#define AB8500_ADC_CH_IBAT_MIN_V	(-60)	/* mV range measured by ADC for ibat */
16662306a36Sopenharmony_ci#define AB8500_ADC_CH_IBAT_MAX_V	60
16762306a36Sopenharmony_ci#define AB8500_GPADC_IBAT_VDROP_L	(-56)  /* mV */
16862306a36Sopenharmony_ci#define AB8500_GPADC_IBAT_VDROP_H	56
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci/* This is used to not lose precision when dividing to get gain and offset */
17162306a36Sopenharmony_ci#define AB8500_GPADC_CALIB_SCALE	1000
17262306a36Sopenharmony_ci/*
17362306a36Sopenharmony_ci * Number of bits shift used to not lose precision
17462306a36Sopenharmony_ci * when dividing to get ibat gain.
17562306a36Sopenharmony_ci */
17662306a36Sopenharmony_ci#define AB8500_GPADC_CALIB_SHIFT_IBAT	20
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci/* Time in ms before disabling regulator */
17962306a36Sopenharmony_ci#define AB8500_GPADC_AUTOSUSPEND_DELAY	1
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci#define AB8500_GPADC_CONVERSION_TIME	500 /* ms */
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cienum ab8500_cal_channels {
18462306a36Sopenharmony_ci	AB8500_CAL_VMAIN = 0,
18562306a36Sopenharmony_ci	AB8500_CAL_BTEMP,
18662306a36Sopenharmony_ci	AB8500_CAL_VBAT,
18762306a36Sopenharmony_ci	AB8500_CAL_IBAT,
18862306a36Sopenharmony_ci	AB8500_CAL_NR,
18962306a36Sopenharmony_ci};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/**
19262306a36Sopenharmony_ci * struct ab8500_adc_cal_data - Table for storing gain and offset for the
19362306a36Sopenharmony_ci * calibrated ADC channels
19462306a36Sopenharmony_ci * @gain: Gain of the ADC channel
19562306a36Sopenharmony_ci * @offset: Offset of the ADC channel
19662306a36Sopenharmony_ci * @otp_calib_hi: Calibration from OTP
19762306a36Sopenharmony_ci * @otp_calib_lo: Calibration from OTP
19862306a36Sopenharmony_ci */
19962306a36Sopenharmony_cistruct ab8500_adc_cal_data {
20062306a36Sopenharmony_ci	s64 gain;
20162306a36Sopenharmony_ci	s64 offset;
20262306a36Sopenharmony_ci	u16 otp_calib_hi;
20362306a36Sopenharmony_ci	u16 otp_calib_lo;
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/**
20762306a36Sopenharmony_ci * struct ab8500_gpadc_chan_info - per-channel GPADC info
20862306a36Sopenharmony_ci * @name: name of the channel
20962306a36Sopenharmony_ci * @id: the internal AB8500 ID number for the channel
21062306a36Sopenharmony_ci * @hardware_control: indicate that we want to use hardware ADC control
21162306a36Sopenharmony_ci * on this channel, the default is software ADC control. Hardware control
21262306a36Sopenharmony_ci * is normally only used to test the battery voltage during GSM bursts
21362306a36Sopenharmony_ci * and needs a hardware trigger on the GPADCTrig pin of the ASIC.
21462306a36Sopenharmony_ci * @falling_edge: indicate that we want to trigger on falling edge
21562306a36Sopenharmony_ci * rather than rising edge, rising edge is the default
21662306a36Sopenharmony_ci * @avg_sample: how many samples to average: must be 1, 4, 8 or 16.
21762306a36Sopenharmony_ci * @trig_timer: how long to wait for the trigger, in 32kHz periods:
21862306a36Sopenharmony_ci * 0 .. 255 periods
21962306a36Sopenharmony_ci */
22062306a36Sopenharmony_cistruct ab8500_gpadc_chan_info {
22162306a36Sopenharmony_ci	const char *name;
22262306a36Sopenharmony_ci	u8 id;
22362306a36Sopenharmony_ci	bool hardware_control;
22462306a36Sopenharmony_ci	bool falling_edge;
22562306a36Sopenharmony_ci	u8 avg_sample;
22662306a36Sopenharmony_ci	u8 trig_timer;
22762306a36Sopenharmony_ci};
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci/**
23062306a36Sopenharmony_ci * struct ab8500_gpadc - AB8500 GPADC device information
23162306a36Sopenharmony_ci * @dev: pointer to the containing device
23262306a36Sopenharmony_ci * @ab8500: pointer to the parent AB8500 device
23362306a36Sopenharmony_ci * @chans: internal per-channel information container
23462306a36Sopenharmony_ci * @nchans: number of channels
23562306a36Sopenharmony_ci * @complete: pointer to the completion that indicates
23662306a36Sopenharmony_ci * the completion of an gpadc conversion cycle
23762306a36Sopenharmony_ci * @vddadc: pointer to the regulator supplying VDDADC
23862306a36Sopenharmony_ci * @irq_sw: interrupt number that is used by gpadc for software ADC conversion
23962306a36Sopenharmony_ci * @irq_hw: interrupt number that is used by gpadc for hardware ADC conversion
24062306a36Sopenharmony_ci * @cal_data: array of ADC calibration data structs
24162306a36Sopenharmony_ci */
24262306a36Sopenharmony_cistruct ab8500_gpadc {
24362306a36Sopenharmony_ci	struct device *dev;
24462306a36Sopenharmony_ci	struct ab8500 *ab8500;
24562306a36Sopenharmony_ci	struct ab8500_gpadc_chan_info *chans;
24662306a36Sopenharmony_ci	unsigned int nchans;
24762306a36Sopenharmony_ci	struct completion complete;
24862306a36Sopenharmony_ci	struct regulator *vddadc;
24962306a36Sopenharmony_ci	int irq_sw;
25062306a36Sopenharmony_ci	int irq_hw;
25162306a36Sopenharmony_ci	struct ab8500_adc_cal_data cal_data[AB8500_CAL_NR];
25262306a36Sopenharmony_ci};
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic struct ab8500_gpadc_chan_info *
25562306a36Sopenharmony_ciab8500_gpadc_get_channel(struct ab8500_gpadc *gpadc, u8 chan)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	struct ab8500_gpadc_chan_info *ch;
25862306a36Sopenharmony_ci	int i;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	for (i = 0; i < gpadc->nchans; i++) {
26162306a36Sopenharmony_ci		ch = &gpadc->chans[i];
26262306a36Sopenharmony_ci		if (ch->id == chan)
26362306a36Sopenharmony_ci			break;
26462306a36Sopenharmony_ci	}
26562306a36Sopenharmony_ci	if (i == gpadc->nchans)
26662306a36Sopenharmony_ci		return NULL;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	return ch;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/**
27262306a36Sopenharmony_ci * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage
27362306a36Sopenharmony_ci * @gpadc: GPADC instance
27462306a36Sopenharmony_ci * @ch: the sampled channel this raw value is coming from
27562306a36Sopenharmony_ci * @ad_value: the raw value
27662306a36Sopenharmony_ci */
27762306a36Sopenharmony_cistatic int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc,
27862306a36Sopenharmony_ci				      enum ab8500_gpadc_channel ch,
27962306a36Sopenharmony_ci				      int ad_value)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	int res;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	switch (ch) {
28462306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_MAIN_CHARGER:
28562306a36Sopenharmony_ci		/* No calibration data available: just interpolate */
28662306a36Sopenharmony_ci		if (!gpadc->cal_data[AB8500_CAL_VMAIN].gain) {
28762306a36Sopenharmony_ci			res = AB8500_ADC_CH_CHG_V_MIN + (AB8500_ADC_CH_CHG_V_MAX -
28862306a36Sopenharmony_ci				AB8500_ADC_CH_CHG_V_MIN) * ad_value /
28962306a36Sopenharmony_ci				AB8500_ADC_RESOLUTION;
29062306a36Sopenharmony_ci			break;
29162306a36Sopenharmony_ci		}
29262306a36Sopenharmony_ci		/* Here we can use calibration */
29362306a36Sopenharmony_ci		res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_VMAIN].gain +
29462306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].offset) / AB8500_GPADC_CALIB_SCALE;
29562306a36Sopenharmony_ci		break;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_BAT_CTRL:
29862306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_BAT_TEMP:
29962306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_ACC_DET_1:
30062306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_ADC_AUX_1:
30162306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_ADC_AUX_2:
30262306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_XTAL_TEMP:
30362306a36Sopenharmony_ci		/* No calibration data available: just interpolate */
30462306a36Sopenharmony_ci		if (!gpadc->cal_data[AB8500_CAL_BTEMP].gain) {
30562306a36Sopenharmony_ci			res = AB8500_ADC_CH_BTEMP_MIN + (AB8500_ADC_CH_BTEMP_MAX -
30662306a36Sopenharmony_ci				AB8500_ADC_CH_BTEMP_MIN) * ad_value /
30762306a36Sopenharmony_ci				AB8500_ADC_RESOLUTION;
30862306a36Sopenharmony_ci			break;
30962306a36Sopenharmony_ci		}
31062306a36Sopenharmony_ci		/* Here we can use calibration */
31162306a36Sopenharmony_ci		res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_BTEMP].gain +
31262306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_BTEMP].offset) / AB8500_GPADC_CALIB_SCALE;
31362306a36Sopenharmony_ci		break;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_VBAT_A:
31662306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_VBAT_TRUE_MEAS:
31762306a36Sopenharmony_ci		/* No calibration data available: just interpolate */
31862306a36Sopenharmony_ci		if (!gpadc->cal_data[AB8500_CAL_VBAT].gain) {
31962306a36Sopenharmony_ci			res = AB8500_ADC_CH_VBAT_MIN + (AB8500_ADC_CH_VBAT_MAX -
32062306a36Sopenharmony_ci				AB8500_ADC_CH_VBAT_MIN) * ad_value /
32162306a36Sopenharmony_ci				AB8500_ADC_RESOLUTION;
32262306a36Sopenharmony_ci			break;
32362306a36Sopenharmony_ci		}
32462306a36Sopenharmony_ci		/* Here we can use calibration */
32562306a36Sopenharmony_ci		res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_VBAT].gain +
32662306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VBAT].offset) / AB8500_GPADC_CALIB_SCALE;
32762306a36Sopenharmony_ci		break;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	case AB8505_GPADC_CHAN_DIE_TEMP:
33062306a36Sopenharmony_ci		res = AB8500_ADC_CH_DIETEMP_MIN +
33162306a36Sopenharmony_ci			(AB8500_ADC_CH_DIETEMP_MAX - AB8500_ADC_CH_DIETEMP_MIN) * ad_value /
33262306a36Sopenharmony_ci			AB8500_ADC_RESOLUTION;
33362306a36Sopenharmony_ci		break;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_ACC_DET_2:
33662306a36Sopenharmony_ci		res = AB8500_ADC_CH_ACCDET2_MIN +
33762306a36Sopenharmony_ci			(AB8500_ADC_CH_ACCDET2_MAX - AB8500_ADC_CH_ACCDET2_MIN) * ad_value /
33862306a36Sopenharmony_ci			AB8500_ADC_RESOLUTION;
33962306a36Sopenharmony_ci		break;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_VBUS:
34262306a36Sopenharmony_ci		res = AB8500_ADC_CH_CHG_V_MIN +
34362306a36Sopenharmony_ci			(AB8500_ADC_CH_CHG_V_MAX - AB8500_ADC_CH_CHG_V_MIN) * ad_value /
34462306a36Sopenharmony_ci			AB8500_ADC_RESOLUTION;
34562306a36Sopenharmony_ci		break;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT:
34862306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_USB_CHARGER_CURRENT:
34962306a36Sopenharmony_ci		res = AB8500_ADC_CH_CHG_I_MIN +
35062306a36Sopenharmony_ci			(AB8500_ADC_CH_CHG_I_MAX - AB8500_ADC_CH_CHG_I_MIN) * ad_value /
35162306a36Sopenharmony_ci			AB8500_ADC_RESOLUTION;
35262306a36Sopenharmony_ci		break;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_BACKUP_BAT:
35562306a36Sopenharmony_ci		res = AB8500_ADC_CH_BKBAT_MIN +
35662306a36Sopenharmony_ci			(AB8500_ADC_CH_BKBAT_MAX - AB8500_ADC_CH_BKBAT_MIN) * ad_value /
35762306a36Sopenharmony_ci			AB8500_ADC_RESOLUTION;
35862306a36Sopenharmony_ci		break;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_IBAT_VIRTUAL:
36162306a36Sopenharmony_ci		/* No calibration data available: just interpolate */
36262306a36Sopenharmony_ci		if (!gpadc->cal_data[AB8500_CAL_IBAT].gain) {
36362306a36Sopenharmony_ci			res = AB8500_ADC_CH_IBAT_MIN + (AB8500_ADC_CH_IBAT_MAX -
36462306a36Sopenharmony_ci				AB8500_ADC_CH_IBAT_MIN) * ad_value /
36562306a36Sopenharmony_ci				AB8500_ADC_RESOLUTION;
36662306a36Sopenharmony_ci			break;
36762306a36Sopenharmony_ci		}
36862306a36Sopenharmony_ci		/* Here we can use calibration */
36962306a36Sopenharmony_ci		res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_IBAT].gain +
37062306a36Sopenharmony_ci				gpadc->cal_data[AB8500_CAL_IBAT].offset)
37162306a36Sopenharmony_ci				>> AB8500_GPADC_CALIB_SHIFT_IBAT;
37262306a36Sopenharmony_ci		break;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	default:
37562306a36Sopenharmony_ci		dev_err(gpadc->dev,
37662306a36Sopenharmony_ci			"unknown channel ID: %d, not possible to convert\n",
37762306a36Sopenharmony_ci			ch);
37862306a36Sopenharmony_ci		res = -EINVAL;
37962306a36Sopenharmony_ci		break;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	return res;
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic int ab8500_gpadc_read(struct ab8500_gpadc *gpadc,
38762306a36Sopenharmony_ci			     const struct ab8500_gpadc_chan_info *ch,
38862306a36Sopenharmony_ci			     int *ibat)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	int ret;
39162306a36Sopenharmony_ci	int looplimit = 0;
39262306a36Sopenharmony_ci	unsigned long completion_timeout;
39362306a36Sopenharmony_ci	u8 val;
39462306a36Sopenharmony_ci	u8 low_data, high_data, low_data2, high_data2;
39562306a36Sopenharmony_ci	u8 ctrl1;
39662306a36Sopenharmony_ci	u8 ctrl23;
39762306a36Sopenharmony_ci	unsigned int delay_min = 0;
39862306a36Sopenharmony_ci	unsigned int delay_max = 0;
39962306a36Sopenharmony_ci	u8 data_low_addr, data_high_addr;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	if (!gpadc)
40262306a36Sopenharmony_ci		return -ENODEV;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/* check if conversion is supported */
40562306a36Sopenharmony_ci	if ((gpadc->irq_sw <= 0) && !ch->hardware_control)
40662306a36Sopenharmony_ci		return -ENOTSUPP;
40762306a36Sopenharmony_ci	if ((gpadc->irq_hw <= 0) && ch->hardware_control)
40862306a36Sopenharmony_ci		return -ENOTSUPP;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	/* Enable vddadc by grabbing PM runtime */
41162306a36Sopenharmony_ci	pm_runtime_get_sync(gpadc->dev);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	/* Check if ADC is not busy, lock and proceed */
41462306a36Sopenharmony_ci	do {
41562306a36Sopenharmony_ci		ret = abx500_get_register_interruptible(gpadc->dev,
41662306a36Sopenharmony_ci			AB8500_GPADC, AB8500_GPADC_STAT_REG, &val);
41762306a36Sopenharmony_ci		if (ret < 0)
41862306a36Sopenharmony_ci			goto out;
41962306a36Sopenharmony_ci		if (!(val & AB8500_GPADC_STAT_BUSY))
42062306a36Sopenharmony_ci			break;
42162306a36Sopenharmony_ci		msleep(20);
42262306a36Sopenharmony_ci	} while (++looplimit < 10);
42362306a36Sopenharmony_ci	if (looplimit >= 10 && (val & AB8500_GPADC_STAT_BUSY)) {
42462306a36Sopenharmony_ci		dev_err(gpadc->dev, "gpadc_conversion: GPADC busy");
42562306a36Sopenharmony_ci		ret = -EINVAL;
42662306a36Sopenharmony_ci		goto out;
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/* Enable GPADC */
43062306a36Sopenharmony_ci	ctrl1 = AB8500_GPADC_CTRL1_ENABLE;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	/* Select the channel source and set average samples */
43362306a36Sopenharmony_ci	switch (ch->avg_sample) {
43462306a36Sopenharmony_ci	case 1:
43562306a36Sopenharmony_ci		ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_1;
43662306a36Sopenharmony_ci		break;
43762306a36Sopenharmony_ci	case 4:
43862306a36Sopenharmony_ci		ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_4;
43962306a36Sopenharmony_ci		break;
44062306a36Sopenharmony_ci	case 8:
44162306a36Sopenharmony_ci		ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_8;
44262306a36Sopenharmony_ci		break;
44362306a36Sopenharmony_ci	default:
44462306a36Sopenharmony_ci		ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_16;
44562306a36Sopenharmony_ci		break;
44662306a36Sopenharmony_ci	}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	if (ch->hardware_control) {
44962306a36Sopenharmony_ci		ret = abx500_set_register_interruptible(gpadc->dev,
45062306a36Sopenharmony_ci				AB8500_GPADC, AB8500_GPADC_CTRL3_REG, ctrl23);
45162306a36Sopenharmony_ci		ctrl1 |= AB8500_GPADC_CTRL1_TRIG_ENA;
45262306a36Sopenharmony_ci		if (ch->falling_edge)
45362306a36Sopenharmony_ci			ctrl1 |= AB8500_GPADC_CTRL1_TRIG_EDGE;
45462306a36Sopenharmony_ci	} else {
45562306a36Sopenharmony_ci		ret = abx500_set_register_interruptible(gpadc->dev,
45662306a36Sopenharmony_ci				AB8500_GPADC, AB8500_GPADC_CTRL2_REG, ctrl23);
45762306a36Sopenharmony_ci	}
45862306a36Sopenharmony_ci	if (ret < 0) {
45962306a36Sopenharmony_ci		dev_err(gpadc->dev,
46062306a36Sopenharmony_ci			"gpadc_conversion: set avg samples failed\n");
46162306a36Sopenharmony_ci		goto out;
46262306a36Sopenharmony_ci	}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/*
46562306a36Sopenharmony_ci	 * Enable ADC, buffering, select rising edge and enable ADC path
46662306a36Sopenharmony_ci	 * charging current sense if it needed, ABB 3.0 needs some special
46762306a36Sopenharmony_ci	 * treatment too.
46862306a36Sopenharmony_ci	 */
46962306a36Sopenharmony_ci	switch (ch->id) {
47062306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT:
47162306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_USB_CHARGER_CURRENT:
47262306a36Sopenharmony_ci		ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA |
47362306a36Sopenharmony_ci			AB8500_GPADC_CTRL1_ICHAR_ENA;
47462306a36Sopenharmony_ci		break;
47562306a36Sopenharmony_ci	case AB8500_GPADC_CHAN_BAT_TEMP:
47662306a36Sopenharmony_ci		if (!is_ab8500_2p0_or_earlier(gpadc->ab8500)) {
47762306a36Sopenharmony_ci			ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA |
47862306a36Sopenharmony_ci				AB8500_GPADC_CTRL1_BTEMP_PULL_UP;
47962306a36Sopenharmony_ci			/*
48062306a36Sopenharmony_ci			 * Delay might be needed for ABB8500 cut 3.0, if not,
48162306a36Sopenharmony_ci			 * remove when hardware will be available
48262306a36Sopenharmony_ci			 */
48362306a36Sopenharmony_ci			delay_min = 1000; /* Delay in micro seconds */
48462306a36Sopenharmony_ci			delay_max = 10000; /* large range optimises sleepmode */
48562306a36Sopenharmony_ci			break;
48662306a36Sopenharmony_ci		}
48762306a36Sopenharmony_ci		fallthrough;
48862306a36Sopenharmony_ci	default:
48962306a36Sopenharmony_ci		ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA;
49062306a36Sopenharmony_ci		break;
49162306a36Sopenharmony_ci	}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	/* Write configuration to control register 1 */
49462306a36Sopenharmony_ci	ret = abx500_set_register_interruptible(gpadc->dev,
49562306a36Sopenharmony_ci		AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ctrl1);
49662306a36Sopenharmony_ci	if (ret < 0) {
49762306a36Sopenharmony_ci		dev_err(gpadc->dev,
49862306a36Sopenharmony_ci			"gpadc_conversion: set Control register failed\n");
49962306a36Sopenharmony_ci		goto out;
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	if (delay_min != 0)
50362306a36Sopenharmony_ci		usleep_range(delay_min, delay_max);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	if (ch->hardware_control) {
50662306a36Sopenharmony_ci		/* Set trigger delay timer */
50762306a36Sopenharmony_ci		ret = abx500_set_register_interruptible(gpadc->dev,
50862306a36Sopenharmony_ci			AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG,
50962306a36Sopenharmony_ci			ch->trig_timer);
51062306a36Sopenharmony_ci		if (ret < 0) {
51162306a36Sopenharmony_ci			dev_err(gpadc->dev,
51262306a36Sopenharmony_ci				"gpadc_conversion: trig timer failed\n");
51362306a36Sopenharmony_ci			goto out;
51462306a36Sopenharmony_ci		}
51562306a36Sopenharmony_ci		completion_timeout = 2 * HZ;
51662306a36Sopenharmony_ci		data_low_addr = AB8500_GPADC_AUTODATAL_REG;
51762306a36Sopenharmony_ci		data_high_addr = AB8500_GPADC_AUTODATAH_REG;
51862306a36Sopenharmony_ci	} else {
51962306a36Sopenharmony_ci		/* Start SW conversion */
52062306a36Sopenharmony_ci		ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
52162306a36Sopenharmony_ci			AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
52262306a36Sopenharmony_ci			AB8500_GPADC_CTRL1_START_SW_CONV,
52362306a36Sopenharmony_ci			AB8500_GPADC_CTRL1_START_SW_CONV);
52462306a36Sopenharmony_ci		if (ret < 0) {
52562306a36Sopenharmony_ci			dev_err(gpadc->dev,
52662306a36Sopenharmony_ci				"gpadc_conversion: start s/w conv failed\n");
52762306a36Sopenharmony_ci			goto out;
52862306a36Sopenharmony_ci		}
52962306a36Sopenharmony_ci		completion_timeout = msecs_to_jiffies(AB8500_GPADC_CONVERSION_TIME);
53062306a36Sopenharmony_ci		data_low_addr = AB8500_GPADC_MANDATAL_REG;
53162306a36Sopenharmony_ci		data_high_addr = AB8500_GPADC_MANDATAH_REG;
53262306a36Sopenharmony_ci	}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	/* Wait for completion of conversion */
53562306a36Sopenharmony_ci	if (!wait_for_completion_timeout(&gpadc->complete,
53662306a36Sopenharmony_ci			completion_timeout)) {
53762306a36Sopenharmony_ci		dev_err(gpadc->dev,
53862306a36Sopenharmony_ci			"timeout didn't receive GPADC conv interrupt\n");
53962306a36Sopenharmony_ci		ret = -EINVAL;
54062306a36Sopenharmony_ci		goto out;
54162306a36Sopenharmony_ci	}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	/* Read the converted RAW data */
54462306a36Sopenharmony_ci	ret = abx500_get_register_interruptible(gpadc->dev,
54562306a36Sopenharmony_ci			AB8500_GPADC, data_low_addr, &low_data);
54662306a36Sopenharmony_ci	if (ret < 0) {
54762306a36Sopenharmony_ci		dev_err(gpadc->dev,
54862306a36Sopenharmony_ci			"gpadc_conversion: read low data failed\n");
54962306a36Sopenharmony_ci		goto out;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	ret = abx500_get_register_interruptible(gpadc->dev,
55362306a36Sopenharmony_ci		AB8500_GPADC, data_high_addr, &high_data);
55462306a36Sopenharmony_ci	if (ret < 0) {
55562306a36Sopenharmony_ci		dev_err(gpadc->dev,
55662306a36Sopenharmony_ci			"gpadc_conversion: read high data failed\n");
55762306a36Sopenharmony_ci		goto out;
55862306a36Sopenharmony_ci	}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	/* Check if double conversion is required */
56162306a36Sopenharmony_ci	if ((ch->id == AB8500_GPADC_CHAN_BAT_CTRL_AND_IBAT) ||
56262306a36Sopenharmony_ci	    (ch->id == AB8500_GPADC_CHAN_VBAT_MEAS_AND_IBAT) ||
56362306a36Sopenharmony_ci	    (ch->id == AB8500_GPADC_CHAN_VBAT_TRUE_MEAS_AND_IBAT) ||
56462306a36Sopenharmony_ci	    (ch->id == AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT)) {
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci		if (ch->hardware_control) {
56762306a36Sopenharmony_ci			/* not supported */
56862306a36Sopenharmony_ci			ret = -ENOTSUPP;
56962306a36Sopenharmony_ci			dev_err(gpadc->dev,
57062306a36Sopenharmony_ci				"gpadc_conversion: only SW double conversion supported\n");
57162306a36Sopenharmony_ci			goto out;
57262306a36Sopenharmony_ci		} else {
57362306a36Sopenharmony_ci			/* Read the converted RAW data 2 */
57462306a36Sopenharmony_ci			ret = abx500_get_register_interruptible(gpadc->dev,
57562306a36Sopenharmony_ci				AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG,
57662306a36Sopenharmony_ci				&low_data2);
57762306a36Sopenharmony_ci			if (ret < 0) {
57862306a36Sopenharmony_ci				dev_err(gpadc->dev,
57962306a36Sopenharmony_ci					"gpadc_conversion: read sw low data 2 failed\n");
58062306a36Sopenharmony_ci				goto out;
58162306a36Sopenharmony_ci			}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci			ret = abx500_get_register_interruptible(gpadc->dev,
58462306a36Sopenharmony_ci				AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG,
58562306a36Sopenharmony_ci				&high_data2);
58662306a36Sopenharmony_ci			if (ret < 0) {
58762306a36Sopenharmony_ci				dev_err(gpadc->dev,
58862306a36Sopenharmony_ci					"gpadc_conversion: read sw high data 2 failed\n");
58962306a36Sopenharmony_ci				goto out;
59062306a36Sopenharmony_ci			}
59162306a36Sopenharmony_ci			if (ibat != NULL) {
59262306a36Sopenharmony_ci				*ibat = (high_data2 << 8) | low_data2;
59362306a36Sopenharmony_ci			} else {
59462306a36Sopenharmony_ci				dev_warn(gpadc->dev,
59562306a36Sopenharmony_ci					"gpadc_conversion: ibat not stored\n");
59662306a36Sopenharmony_ci			}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci		}
59962306a36Sopenharmony_ci	}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	/* Disable GPADC */
60262306a36Sopenharmony_ci	ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
60362306a36Sopenharmony_ci		AB8500_GPADC_CTRL1_REG, AB8500_GPADC_CTRL1_DISABLE);
60462306a36Sopenharmony_ci	if (ret < 0) {
60562306a36Sopenharmony_ci		dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n");
60662306a36Sopenharmony_ci		goto out;
60762306a36Sopenharmony_ci	}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	/* This eventually drops the regulator */
61062306a36Sopenharmony_ci	pm_runtime_mark_last_busy(gpadc->dev);
61162306a36Sopenharmony_ci	pm_runtime_put_autosuspend(gpadc->dev);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	return (high_data << 8) | low_data;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ciout:
61662306a36Sopenharmony_ci	/*
61762306a36Sopenharmony_ci	 * It has shown to be needed to turn off the GPADC if an error occurs,
61862306a36Sopenharmony_ci	 * otherwise we might have problem when waiting for the busy bit in the
61962306a36Sopenharmony_ci	 * GPADC status register to go low. In V1.1 there wait_for_completion
62062306a36Sopenharmony_ci	 * seems to timeout when waiting for an interrupt.. Not seen in V2.0
62162306a36Sopenharmony_ci	 */
62262306a36Sopenharmony_ci	(void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
62362306a36Sopenharmony_ci		AB8500_GPADC_CTRL1_REG, AB8500_GPADC_CTRL1_DISABLE);
62462306a36Sopenharmony_ci	pm_runtime_put(gpadc->dev);
62562306a36Sopenharmony_ci	dev_err(gpadc->dev,
62662306a36Sopenharmony_ci		"gpadc_conversion: Failed to AD convert channel %d\n", ch->id);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	return ret;
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci/**
63262306a36Sopenharmony_ci * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion
63362306a36Sopenharmony_ci * @irq: irq number
63462306a36Sopenharmony_ci * @data: pointer to the data passed during request irq
63562306a36Sopenharmony_ci *
63662306a36Sopenharmony_ci * This is a interrupt service routine for gpadc conversion completion.
63762306a36Sopenharmony_ci * Notifies the gpadc completion is completed and the converted raw value
63862306a36Sopenharmony_ci * can be read from the registers.
63962306a36Sopenharmony_ci * Returns IRQ status(IRQ_HANDLED)
64062306a36Sopenharmony_ci */
64162306a36Sopenharmony_cistatic irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *data)
64262306a36Sopenharmony_ci{
64362306a36Sopenharmony_ci	struct ab8500_gpadc *gpadc = data;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	complete(&gpadc->complete);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	return IRQ_HANDLED;
64862306a36Sopenharmony_ci}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_cistatic int otp_cal_regs[] = {
65162306a36Sopenharmony_ci	AB8500_GPADC_CAL_1,
65262306a36Sopenharmony_ci	AB8500_GPADC_CAL_2,
65362306a36Sopenharmony_ci	AB8500_GPADC_CAL_3,
65462306a36Sopenharmony_ci	AB8500_GPADC_CAL_4,
65562306a36Sopenharmony_ci	AB8500_GPADC_CAL_5,
65662306a36Sopenharmony_ci	AB8500_GPADC_CAL_6,
65762306a36Sopenharmony_ci	AB8500_GPADC_CAL_7,
65862306a36Sopenharmony_ci};
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_cistatic int otp4_cal_regs[] = {
66162306a36Sopenharmony_ci	AB8540_GPADC_OTP4_REG_7,
66262306a36Sopenharmony_ci	AB8540_GPADC_OTP4_REG_6,
66362306a36Sopenharmony_ci	AB8540_GPADC_OTP4_REG_5,
66462306a36Sopenharmony_ci};
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_cistatic void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
66762306a36Sopenharmony_ci{
66862306a36Sopenharmony_ci	int i;
66962306a36Sopenharmony_ci	int ret[ARRAY_SIZE(otp_cal_regs)];
67062306a36Sopenharmony_ci	u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)];
67162306a36Sopenharmony_ci	int ret_otp4[ARRAY_SIZE(otp4_cal_regs)];
67262306a36Sopenharmony_ci	u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)];
67362306a36Sopenharmony_ci	int vmain_high, vmain_low;
67462306a36Sopenharmony_ci	int btemp_high, btemp_low;
67562306a36Sopenharmony_ci	int vbat_high, vbat_low;
67662306a36Sopenharmony_ci	int ibat_high, ibat_low;
67762306a36Sopenharmony_ci	s64 V_gain, V_offset, V2A_gain, V2A_offset;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	/* First we read all OTP registers and store the error code */
68062306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) {
68162306a36Sopenharmony_ci		ret[i] = abx500_get_register_interruptible(gpadc->dev,
68262306a36Sopenharmony_ci			AB8500_OTP_EMUL, otp_cal_regs[i],  &gpadc_cal[i]);
68362306a36Sopenharmony_ci		if (ret[i] < 0) {
68462306a36Sopenharmony_ci			/* Continue anyway: maybe the other registers are OK */
68562306a36Sopenharmony_ci			dev_err(gpadc->dev, "%s: read otp reg 0x%02x failed\n",
68662306a36Sopenharmony_ci				__func__, otp_cal_regs[i]);
68762306a36Sopenharmony_ci		} else {
68862306a36Sopenharmony_ci			/* Put this in the entropy pool as device-unique */
68962306a36Sopenharmony_ci			add_device_randomness(&ret[i], sizeof(ret[i]));
69062306a36Sopenharmony_ci		}
69162306a36Sopenharmony_ci	}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	/*
69462306a36Sopenharmony_ci	 * The ADC calibration data is stored in OTP registers.
69562306a36Sopenharmony_ci	 * The layout of the calibration data is outlined below and a more
69662306a36Sopenharmony_ci	 * detailed description can be found in UM0836
69762306a36Sopenharmony_ci	 *
69862306a36Sopenharmony_ci	 * vm_h/l = vmain_high/low
69962306a36Sopenharmony_ci	 * bt_h/l = btemp_high/low
70062306a36Sopenharmony_ci	 * vb_h/l = vbat_high/low
70162306a36Sopenharmony_ci	 *
70262306a36Sopenharmony_ci	 * Data bits 8500/9540:
70362306a36Sopenharmony_ci	 * | 7	   | 6	   | 5	   | 4	   | 3	   | 2	   | 1	   | 0
70462306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
70562306a36Sopenharmony_ci	 * |						   | vm_h9 | vm_h8
70662306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
70762306a36Sopenharmony_ci	 * |		   | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
70862306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
70962306a36Sopenharmony_ci	 * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
71062306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
71162306a36Sopenharmony_ci	 * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
71262306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
71362306a36Sopenharmony_ci	 * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
71462306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
71562306a36Sopenharmony_ci	 * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
71662306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
71762306a36Sopenharmony_ci	 * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
71862306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
71962306a36Sopenharmony_ci	 *
72062306a36Sopenharmony_ci	 * Data bits 8540:
72162306a36Sopenharmony_ci	 * OTP2
72262306a36Sopenharmony_ci	 * | 7	   | 6	   | 5	   | 4	   | 3	   | 2	   | 1	   | 0
72362306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
72462306a36Sopenharmony_ci	 * |
72562306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
72662306a36Sopenharmony_ci	 * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
72762306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
72862306a36Sopenharmony_ci	 * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
72962306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
73062306a36Sopenharmony_ci	 * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
73162306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
73262306a36Sopenharmony_ci	 * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
73362306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
73462306a36Sopenharmony_ci	 * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
73562306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
73662306a36Sopenharmony_ci	 * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
73762306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
73862306a36Sopenharmony_ci	 *
73962306a36Sopenharmony_ci	 * Data bits 8540:
74062306a36Sopenharmony_ci	 * OTP4
74162306a36Sopenharmony_ci	 * | 7	   | 6	   | 5	   | 4	   | 3	   | 2	   | 1	   | 0
74262306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
74362306a36Sopenharmony_ci	 * |					   | ib_h9 | ib_h8 | ib_h7
74462306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
74562306a36Sopenharmony_ci	 * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5
74662306a36Sopenharmony_ci	 * |.......|.......|.......|.......|.......|.......|.......|.......
74762306a36Sopenharmony_ci	 * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 |
74862306a36Sopenharmony_ci	 *
74962306a36Sopenharmony_ci	 *
75062306a36Sopenharmony_ci	 * Ideal output ADC codes corresponding to injected input voltages
75162306a36Sopenharmony_ci	 * during manufacturing is:
75262306a36Sopenharmony_ci	 *
75362306a36Sopenharmony_ci	 * vmain_high: Vin = 19500mV / ADC ideal code = 997
75462306a36Sopenharmony_ci	 * vmain_low:  Vin = 315mV   / ADC ideal code = 16
75562306a36Sopenharmony_ci	 * btemp_high: Vin = 1300mV  / ADC ideal code = 985
75662306a36Sopenharmony_ci	 * btemp_low:  Vin = 21mV    / ADC ideal code = 16
75762306a36Sopenharmony_ci	 * vbat_high:  Vin = 4700mV  / ADC ideal code = 982
75862306a36Sopenharmony_ci	 * vbat_low:   Vin = 2380mV  / ADC ideal code = 33
75962306a36Sopenharmony_ci	 */
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	if (is_ab8540(gpadc->ab8500)) {
76262306a36Sopenharmony_ci		/* Calculate gain and offset for VMAIN if all reads succeeded*/
76362306a36Sopenharmony_ci		if (!(ret[1] < 0 || ret[2] < 0)) {
76462306a36Sopenharmony_ci			vmain_high = (((gpadc_cal[1] & 0xFF) << 2) |
76562306a36Sopenharmony_ci				((gpadc_cal[2] & 0xC0) >> 6));
76662306a36Sopenharmony_ci			vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_hi =
76962306a36Sopenharmony_ci				(u16)vmain_high;
77062306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_lo =
77162306a36Sopenharmony_ci				(u16)vmain_low;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].gain = AB8500_GPADC_CALIB_SCALE *
77462306a36Sopenharmony_ci				(19500 - 315) / (vmain_high - vmain_low);
77562306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].offset = AB8500_GPADC_CALIB_SCALE *
77662306a36Sopenharmony_ci				19500 - (AB8500_GPADC_CALIB_SCALE * (19500 - 315) /
77762306a36Sopenharmony_ci				(vmain_high - vmain_low)) * vmain_high;
77862306a36Sopenharmony_ci		} else {
77962306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].gain = 0;
78062306a36Sopenharmony_ci		}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci		/* Read IBAT calibration Data */
78362306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) {
78462306a36Sopenharmony_ci			ret_otp4[i] = abx500_get_register_interruptible(
78562306a36Sopenharmony_ci					gpadc->dev, AB8500_OTP_EMUL,
78662306a36Sopenharmony_ci					otp4_cal_regs[i],  &gpadc_otp4[i]);
78762306a36Sopenharmony_ci			if (ret_otp4[i] < 0)
78862306a36Sopenharmony_ci				dev_err(gpadc->dev,
78962306a36Sopenharmony_ci					"%s: read otp4 reg 0x%02x failed\n",
79062306a36Sopenharmony_ci					__func__, otp4_cal_regs[i]);
79162306a36Sopenharmony_ci		}
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci		/* Calculate gain and offset for IBAT if all reads succeeded */
79462306a36Sopenharmony_ci		if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) {
79562306a36Sopenharmony_ci			ibat_high = (((gpadc_otp4[0] & 0x07) << 7) |
79662306a36Sopenharmony_ci				((gpadc_otp4[1] & 0xFE) >> 1));
79762306a36Sopenharmony_ci			ibat_low = (((gpadc_otp4[1] & 0x01) << 5) |
79862306a36Sopenharmony_ci				((gpadc_otp4[2] & 0xF8) >> 3));
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_IBAT].otp_calib_hi =
80162306a36Sopenharmony_ci				(u16)ibat_high;
80262306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_IBAT].otp_calib_lo =
80362306a36Sopenharmony_ci				(u16)ibat_low;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci			V_gain = ((AB8500_GPADC_IBAT_VDROP_H - AB8500_GPADC_IBAT_VDROP_L)
80662306a36Sopenharmony_ci				<< AB8500_GPADC_CALIB_SHIFT_IBAT) / (ibat_high - ibat_low);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci			V_offset = (AB8500_GPADC_IBAT_VDROP_H << AB8500_GPADC_CALIB_SHIFT_IBAT) -
80962306a36Sopenharmony_ci				(((AB8500_GPADC_IBAT_VDROP_H - AB8500_GPADC_IBAT_VDROP_L) <<
81062306a36Sopenharmony_ci				AB8500_GPADC_CALIB_SHIFT_IBAT) / (ibat_high - ibat_low))
81162306a36Sopenharmony_ci				* ibat_high;
81262306a36Sopenharmony_ci			/*
81362306a36Sopenharmony_ci			 * Result obtained is in mV (at a scale factor),
81462306a36Sopenharmony_ci			 * we need to calculate gain and offset to get mA
81562306a36Sopenharmony_ci			 */
81662306a36Sopenharmony_ci			V2A_gain = (AB8500_ADC_CH_IBAT_MAX - AB8500_ADC_CH_IBAT_MIN)/
81762306a36Sopenharmony_ci				(AB8500_ADC_CH_IBAT_MAX_V - AB8500_ADC_CH_IBAT_MIN_V);
81862306a36Sopenharmony_ci			V2A_offset = ((AB8500_ADC_CH_IBAT_MAX_V * AB8500_ADC_CH_IBAT_MIN -
81962306a36Sopenharmony_ci				AB8500_ADC_CH_IBAT_MAX * AB8500_ADC_CH_IBAT_MIN_V)
82062306a36Sopenharmony_ci				<< AB8500_GPADC_CALIB_SHIFT_IBAT)
82162306a36Sopenharmony_ci				/ (AB8500_ADC_CH_IBAT_MAX_V - AB8500_ADC_CH_IBAT_MIN_V);
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_IBAT].gain =
82462306a36Sopenharmony_ci				V_gain * V2A_gain;
82562306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_IBAT].offset =
82662306a36Sopenharmony_ci				V_offset * V2A_gain + V2A_offset;
82762306a36Sopenharmony_ci		} else {
82862306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_IBAT].gain = 0;
82962306a36Sopenharmony_ci		}
83062306a36Sopenharmony_ci	} else {
83162306a36Sopenharmony_ci		/* Calculate gain and offset for VMAIN if all reads succeeded */
83262306a36Sopenharmony_ci		if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) {
83362306a36Sopenharmony_ci			vmain_high = (((gpadc_cal[0] & 0x03) << 8) |
83462306a36Sopenharmony_ci				((gpadc_cal[1] & 0x3F) << 2) |
83562306a36Sopenharmony_ci				((gpadc_cal[2] & 0xC0) >> 6));
83662306a36Sopenharmony_ci			vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_hi =
83962306a36Sopenharmony_ci				(u16)vmain_high;
84062306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_lo =
84162306a36Sopenharmony_ci				(u16)vmain_low;
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].gain = AB8500_GPADC_CALIB_SCALE *
84462306a36Sopenharmony_ci				(19500 - 315) / (vmain_high - vmain_low);
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].offset = AB8500_GPADC_CALIB_SCALE *
84762306a36Sopenharmony_ci				19500 - (AB8500_GPADC_CALIB_SCALE * (19500 - 315) /
84862306a36Sopenharmony_ci				(vmain_high - vmain_low)) * vmain_high;
84962306a36Sopenharmony_ci		} else {
85062306a36Sopenharmony_ci			gpadc->cal_data[AB8500_CAL_VMAIN].gain = 0;
85162306a36Sopenharmony_ci		}
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	/* Calculate gain and offset for BTEMP if all reads succeeded */
85562306a36Sopenharmony_ci	if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) {
85662306a36Sopenharmony_ci		btemp_high = (((gpadc_cal[2] & 0x01) << 9) |
85762306a36Sopenharmony_ci			(gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7));
85862306a36Sopenharmony_ci		btemp_low = ((gpadc_cal[4] & 0x7C) >> 2);
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_BTEMP].otp_calib_hi = (u16)btemp_high;
86162306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_BTEMP].otp_calib_lo = (u16)btemp_low;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_BTEMP].gain =
86462306a36Sopenharmony_ci			AB8500_GPADC_CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low);
86562306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_BTEMP].offset = AB8500_GPADC_CALIB_SCALE * 1300 -
86662306a36Sopenharmony_ci			(AB8500_GPADC_CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low))
86762306a36Sopenharmony_ci			* btemp_high;
86862306a36Sopenharmony_ci	} else {
86962306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_BTEMP].gain = 0;
87062306a36Sopenharmony_ci	}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	/* Calculate gain and offset for VBAT if all reads succeeded */
87362306a36Sopenharmony_ci	if (!(ret[4] < 0 || ret[5] < 0 || ret[6] < 0)) {
87462306a36Sopenharmony_ci		vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]);
87562306a36Sopenharmony_ci		vbat_low = ((gpadc_cal[6] & 0xFC) >> 2);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_VBAT].otp_calib_hi = (u16)vbat_high;
87862306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_VBAT].otp_calib_lo = (u16)vbat_low;
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_VBAT].gain = AB8500_GPADC_CALIB_SCALE *
88162306a36Sopenharmony_ci			(4700 - 2380) /	(vbat_high - vbat_low);
88262306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_VBAT].offset = AB8500_GPADC_CALIB_SCALE * 4700 -
88362306a36Sopenharmony_ci			(AB8500_GPADC_CALIB_SCALE * (4700 - 2380) /
88462306a36Sopenharmony_ci			(vbat_high - vbat_low)) * vbat_high;
88562306a36Sopenharmony_ci	} else {
88662306a36Sopenharmony_ci		gpadc->cal_data[AB8500_CAL_VBAT].gain = 0;
88762306a36Sopenharmony_ci	}
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_cistatic int ab8500_gpadc_read_raw(struct iio_dev *indio_dev,
89162306a36Sopenharmony_ci				 struct iio_chan_spec const *chan,
89262306a36Sopenharmony_ci				 int *val, int *val2, long mask)
89362306a36Sopenharmony_ci{
89462306a36Sopenharmony_ci	struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
89562306a36Sopenharmony_ci	const struct ab8500_gpadc_chan_info *ch;
89662306a36Sopenharmony_ci	int raw_val;
89762306a36Sopenharmony_ci	int processed;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	ch = ab8500_gpadc_get_channel(gpadc, chan->address);
90062306a36Sopenharmony_ci	if (!ch) {
90162306a36Sopenharmony_ci		dev_err(gpadc->dev, "no such channel %lu\n",
90262306a36Sopenharmony_ci			chan->address);
90362306a36Sopenharmony_ci		return -EINVAL;
90462306a36Sopenharmony_ci	}
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	raw_val = ab8500_gpadc_read(gpadc, ch, NULL);
90762306a36Sopenharmony_ci	if (raw_val < 0)
90862306a36Sopenharmony_ci		return raw_val;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	if (mask == IIO_CHAN_INFO_RAW) {
91162306a36Sopenharmony_ci		*val = raw_val;
91262306a36Sopenharmony_ci		return IIO_VAL_INT;
91362306a36Sopenharmony_ci	}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	if (mask == IIO_CHAN_INFO_PROCESSED) {
91662306a36Sopenharmony_ci		processed = ab8500_gpadc_ad_to_voltage(gpadc, ch->id, raw_val);
91762306a36Sopenharmony_ci		if (processed < 0)
91862306a36Sopenharmony_ci			return processed;
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci		/* Return millivolt or milliamps or millicentigrades */
92162306a36Sopenharmony_ci		*val = processed;
92262306a36Sopenharmony_ci		return IIO_VAL_INT;
92362306a36Sopenharmony_ci	}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	return -EINVAL;
92662306a36Sopenharmony_ci}
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_cistatic int ab8500_gpadc_fwnode_xlate(struct iio_dev *indio_dev,
92962306a36Sopenharmony_ci				     const struct fwnode_reference_args *iiospec)
93062306a36Sopenharmony_ci{
93162306a36Sopenharmony_ci	int i;
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	for (i = 0; i < indio_dev->num_channels; i++)
93462306a36Sopenharmony_ci		if (indio_dev->channels[i].channel == iiospec->args[0])
93562306a36Sopenharmony_ci			return i;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	return -EINVAL;
93862306a36Sopenharmony_ci}
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_cistatic const struct iio_info ab8500_gpadc_info = {
94162306a36Sopenharmony_ci	.fwnode_xlate = ab8500_gpadc_fwnode_xlate,
94262306a36Sopenharmony_ci	.read_raw = ab8500_gpadc_read_raw,
94362306a36Sopenharmony_ci};
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_cistatic int ab8500_gpadc_runtime_suspend(struct device *dev)
94662306a36Sopenharmony_ci{
94762306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
94862306a36Sopenharmony_ci	struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	regulator_disable(gpadc->vddadc);
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	return 0;
95362306a36Sopenharmony_ci}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_cistatic int ab8500_gpadc_runtime_resume(struct device *dev)
95662306a36Sopenharmony_ci{
95762306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
95862306a36Sopenharmony_ci	struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
95962306a36Sopenharmony_ci	int ret;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	ret = regulator_enable(gpadc->vddadc);
96262306a36Sopenharmony_ci	if (ret)
96362306a36Sopenharmony_ci		dev_err(dev, "Failed to enable vddadc: %d\n", ret);
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	return ret;
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci/**
96962306a36Sopenharmony_ci * ab8500_gpadc_parse_channel() - process devicetree channel configuration
97062306a36Sopenharmony_ci * @dev: pointer to containing device
97162306a36Sopenharmony_ci * @fwnode: fw node for the channel to configure
97262306a36Sopenharmony_ci * @ch: channel info to fill in
97362306a36Sopenharmony_ci * @iio_chan: IIO channel specification to fill in
97462306a36Sopenharmony_ci *
97562306a36Sopenharmony_ci * The devicetree will set up the channel for use with the specific device,
97662306a36Sopenharmony_ci * and define usage for things like AUX GPADC inputs more precisely.
97762306a36Sopenharmony_ci */
97862306a36Sopenharmony_cistatic int ab8500_gpadc_parse_channel(struct device *dev,
97962306a36Sopenharmony_ci				      struct fwnode_handle *fwnode,
98062306a36Sopenharmony_ci				      struct ab8500_gpadc_chan_info *ch,
98162306a36Sopenharmony_ci				      struct iio_chan_spec *iio_chan)
98262306a36Sopenharmony_ci{
98362306a36Sopenharmony_ci	const char *name = fwnode_get_name(fwnode);
98462306a36Sopenharmony_ci	u32 chan;
98562306a36Sopenharmony_ci	int ret;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	ret = fwnode_property_read_u32(fwnode, "reg", &chan);
98862306a36Sopenharmony_ci	if (ret) {
98962306a36Sopenharmony_ci		dev_err(dev, "invalid channel number %s\n", name);
99062306a36Sopenharmony_ci		return ret;
99162306a36Sopenharmony_ci	}
99262306a36Sopenharmony_ci	if (chan > AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT) {
99362306a36Sopenharmony_ci		dev_err(dev, "%s channel number out of range %d\n", name, chan);
99462306a36Sopenharmony_ci		return -EINVAL;
99562306a36Sopenharmony_ci	}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	iio_chan->channel = chan;
99862306a36Sopenharmony_ci	iio_chan->datasheet_name = name;
99962306a36Sopenharmony_ci	iio_chan->indexed = 1;
100062306a36Sopenharmony_ci	iio_chan->address = chan;
100162306a36Sopenharmony_ci	iio_chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
100262306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_PROCESSED);
100362306a36Sopenharmony_ci	/* Most are voltages (also temperatures), some are currents */
100462306a36Sopenharmony_ci	if ((chan == AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT) ||
100562306a36Sopenharmony_ci	    (chan == AB8500_GPADC_CHAN_USB_CHARGER_CURRENT))
100662306a36Sopenharmony_ci		iio_chan->type = IIO_CURRENT;
100762306a36Sopenharmony_ci	else
100862306a36Sopenharmony_ci		iio_chan->type = IIO_VOLTAGE;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	ch->id = chan;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	/* Sensible defaults */
101362306a36Sopenharmony_ci	ch->avg_sample = 16;
101462306a36Sopenharmony_ci	ch->hardware_control = false;
101562306a36Sopenharmony_ci	ch->falling_edge = false;
101662306a36Sopenharmony_ci	ch->trig_timer = 0;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	return 0;
101962306a36Sopenharmony_ci}
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci/**
102262306a36Sopenharmony_ci * ab8500_gpadc_parse_channels() - Parse the GPADC channels from DT
102362306a36Sopenharmony_ci * @gpadc: the GPADC to configure the channels for
102462306a36Sopenharmony_ci * @chans: the IIO channels we parsed
102562306a36Sopenharmony_ci * @nchans: the number of IIO channels we parsed
102662306a36Sopenharmony_ci */
102762306a36Sopenharmony_cistatic int ab8500_gpadc_parse_channels(struct ab8500_gpadc *gpadc,
102862306a36Sopenharmony_ci				       struct iio_chan_spec **chans_parsed,
102962306a36Sopenharmony_ci				       unsigned int *nchans_parsed)
103062306a36Sopenharmony_ci{
103162306a36Sopenharmony_ci	struct fwnode_handle *child;
103262306a36Sopenharmony_ci	struct ab8500_gpadc_chan_info *ch;
103362306a36Sopenharmony_ci	struct iio_chan_spec *iio_chans;
103462306a36Sopenharmony_ci	unsigned int nchans;
103562306a36Sopenharmony_ci	int i;
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	nchans = device_get_child_node_count(gpadc->dev);
103862306a36Sopenharmony_ci	if (!nchans) {
103962306a36Sopenharmony_ci		dev_err(gpadc->dev, "no channel children\n");
104062306a36Sopenharmony_ci		return -ENODEV;
104162306a36Sopenharmony_ci	}
104262306a36Sopenharmony_ci	dev_info(gpadc->dev, "found %d ADC channels\n", nchans);
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	iio_chans = devm_kcalloc(gpadc->dev, nchans,
104562306a36Sopenharmony_ci				 sizeof(*iio_chans), GFP_KERNEL);
104662306a36Sopenharmony_ci	if (!iio_chans)
104762306a36Sopenharmony_ci		return -ENOMEM;
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci	gpadc->chans = devm_kcalloc(gpadc->dev, nchans,
105062306a36Sopenharmony_ci				    sizeof(*gpadc->chans), GFP_KERNEL);
105162306a36Sopenharmony_ci	if (!gpadc->chans)
105262306a36Sopenharmony_ci		return -ENOMEM;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	i = 0;
105562306a36Sopenharmony_ci	device_for_each_child_node(gpadc->dev, child) {
105662306a36Sopenharmony_ci		struct iio_chan_spec *iio_chan;
105762306a36Sopenharmony_ci		int ret;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci		ch = &gpadc->chans[i];
106062306a36Sopenharmony_ci		iio_chan = &iio_chans[i];
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci		ret = ab8500_gpadc_parse_channel(gpadc->dev, child, ch,
106362306a36Sopenharmony_ci						 iio_chan);
106462306a36Sopenharmony_ci		if (ret) {
106562306a36Sopenharmony_ci			fwnode_handle_put(child);
106662306a36Sopenharmony_ci			return ret;
106762306a36Sopenharmony_ci		}
106862306a36Sopenharmony_ci		i++;
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci	gpadc->nchans = nchans;
107162306a36Sopenharmony_ci	*chans_parsed = iio_chans;
107262306a36Sopenharmony_ci	*nchans_parsed = nchans;
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	return 0;
107562306a36Sopenharmony_ci}
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_cistatic int ab8500_gpadc_probe(struct platform_device *pdev)
107862306a36Sopenharmony_ci{
107962306a36Sopenharmony_ci	struct ab8500_gpadc *gpadc;
108062306a36Sopenharmony_ci	struct iio_dev *indio_dev;
108162306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
108262306a36Sopenharmony_ci	struct iio_chan_spec *iio_chans;
108362306a36Sopenharmony_ci	unsigned int n_iio_chans;
108462306a36Sopenharmony_ci	int ret;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
108762306a36Sopenharmony_ci	if (!indio_dev)
108862306a36Sopenharmony_ci		return -ENOMEM;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	platform_set_drvdata(pdev, indio_dev);
109162306a36Sopenharmony_ci	gpadc = iio_priv(indio_dev);
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	gpadc->dev = dev;
109462306a36Sopenharmony_ci	gpadc->ab8500 = dev_get_drvdata(dev->parent);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	ret = ab8500_gpadc_parse_channels(gpadc, &iio_chans, &n_iio_chans);
109762306a36Sopenharmony_ci	if (ret)
109862306a36Sopenharmony_ci		return ret;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END");
110162306a36Sopenharmony_ci	if (gpadc->irq_sw < 0)
110262306a36Sopenharmony_ci		return gpadc->irq_sw;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	if (is_ab8500(gpadc->ab8500)) {
110562306a36Sopenharmony_ci		gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END");
110662306a36Sopenharmony_ci		if (gpadc->irq_hw < 0)
110762306a36Sopenharmony_ci			return gpadc->irq_hw;
110862306a36Sopenharmony_ci	} else {
110962306a36Sopenharmony_ci		gpadc->irq_hw = 0;
111062306a36Sopenharmony_ci	}
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	/* Initialize completion used to notify completion of conversion */
111362306a36Sopenharmony_ci	init_completion(&gpadc->complete);
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	/* Request interrupts */
111662306a36Sopenharmony_ci	ret = devm_request_threaded_irq(dev, gpadc->irq_sw, NULL,
111762306a36Sopenharmony_ci		ab8500_bm_gpadcconvend_handler,	IRQF_NO_SUSPEND | IRQF_ONESHOT,
111862306a36Sopenharmony_ci		"ab8500-gpadc-sw", gpadc);
111962306a36Sopenharmony_ci	if (ret < 0) {
112062306a36Sopenharmony_ci		dev_err(dev,
112162306a36Sopenharmony_ci			"failed to request sw conversion irq %d\n",
112262306a36Sopenharmony_ci			gpadc->irq_sw);
112362306a36Sopenharmony_ci		return ret;
112462306a36Sopenharmony_ci	}
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	if (gpadc->irq_hw) {
112762306a36Sopenharmony_ci		ret = devm_request_threaded_irq(dev, gpadc->irq_hw, NULL,
112862306a36Sopenharmony_ci			ab8500_bm_gpadcconvend_handler,	IRQF_NO_SUSPEND | IRQF_ONESHOT,
112962306a36Sopenharmony_ci			"ab8500-gpadc-hw", gpadc);
113062306a36Sopenharmony_ci		if (ret < 0) {
113162306a36Sopenharmony_ci			dev_err(dev,
113262306a36Sopenharmony_ci				"Failed to request hw conversion irq: %d\n",
113362306a36Sopenharmony_ci				gpadc->irq_hw);
113462306a36Sopenharmony_ci			return ret;
113562306a36Sopenharmony_ci		}
113662306a36Sopenharmony_ci	}
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	/* The VTVout LDO used to power the AB8500 GPADC */
113962306a36Sopenharmony_ci	gpadc->vddadc = devm_regulator_get(dev, "vddadc");
114062306a36Sopenharmony_ci	if (IS_ERR(gpadc->vddadc))
114162306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(gpadc->vddadc),
114262306a36Sopenharmony_ci				     "failed to get vddadc\n");
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	ret = regulator_enable(gpadc->vddadc);
114562306a36Sopenharmony_ci	if (ret) {
114662306a36Sopenharmony_ci		dev_err(dev, "failed to enable vddadc: %d\n", ret);
114762306a36Sopenharmony_ci		return ret;
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	/* Enable runtime PM */
115162306a36Sopenharmony_ci	pm_runtime_get_noresume(dev);
115262306a36Sopenharmony_ci	pm_runtime_set_active(dev);
115362306a36Sopenharmony_ci	pm_runtime_enable(dev);
115462306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(dev, AB8500_GPADC_AUTOSUSPEND_DELAY);
115562306a36Sopenharmony_ci	pm_runtime_use_autosuspend(dev);
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	ab8500_gpadc_read_calibration_data(gpadc);
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	pm_runtime_put(dev);
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	indio_dev->name = "ab8500-gpadc";
116262306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
116362306a36Sopenharmony_ci	indio_dev->info = &ab8500_gpadc_info;
116462306a36Sopenharmony_ci	indio_dev->channels = iio_chans;
116562306a36Sopenharmony_ci	indio_dev->num_channels = n_iio_chans;
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	ret = devm_iio_device_register(dev, indio_dev);
116862306a36Sopenharmony_ci	if (ret)
116962306a36Sopenharmony_ci		goto out_dis_pm;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	return 0;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ciout_dis_pm:
117462306a36Sopenharmony_ci	pm_runtime_get_sync(dev);
117562306a36Sopenharmony_ci	pm_runtime_put_noidle(dev);
117662306a36Sopenharmony_ci	pm_runtime_disable(dev);
117762306a36Sopenharmony_ci	regulator_disable(gpadc->vddadc);
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	return ret;
118062306a36Sopenharmony_ci}
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_cistatic int ab8500_gpadc_remove(struct platform_device *pdev)
118362306a36Sopenharmony_ci{
118462306a36Sopenharmony_ci	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
118562306a36Sopenharmony_ci	struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	pm_runtime_get_sync(gpadc->dev);
118862306a36Sopenharmony_ci	pm_runtime_put_noidle(gpadc->dev);
118962306a36Sopenharmony_ci	pm_runtime_disable(gpadc->dev);
119062306a36Sopenharmony_ci	regulator_disable(gpadc->vddadc);
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	return 0;
119362306a36Sopenharmony_ci}
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_cistatic DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
119662306a36Sopenharmony_ci				 ab8500_gpadc_runtime_suspend,
119762306a36Sopenharmony_ci				 ab8500_gpadc_runtime_resume, NULL);
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_cistatic struct platform_driver ab8500_gpadc_driver = {
120062306a36Sopenharmony_ci	.probe = ab8500_gpadc_probe,
120162306a36Sopenharmony_ci	.remove = ab8500_gpadc_remove,
120262306a36Sopenharmony_ci	.driver = {
120362306a36Sopenharmony_ci		.name = "ab8500-gpadc",
120462306a36Sopenharmony_ci		.pm = pm_ptr(&ab8500_gpadc_pm_ops),
120562306a36Sopenharmony_ci	},
120662306a36Sopenharmony_ci};
120762306a36Sopenharmony_cibuiltin_platform_driver(ab8500_gpadc_driver);
1208