162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Analog Devices LTC2983 Multi-Sensor Digital Temperature Measurement System
462306a36Sopenharmony_ci * driver
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright 2019 Analog Devices Inc.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/bitfield.h>
962306a36Sopenharmony_ci#include <linux/completion.h>
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/iio/iio.h>
1362306a36Sopenharmony_ci#include <linux/interrupt.h>
1462306a36Sopenharmony_ci#include <linux/list.h>
1562306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/property.h>
1862306a36Sopenharmony_ci#include <linux/regmap.h>
1962306a36Sopenharmony_ci#include <linux/spi/spi.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <asm/byteorder.h>
2262306a36Sopenharmony_ci#include <asm/unaligned.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* register map */
2562306a36Sopenharmony_ci#define LTC2983_STATUS_REG			0x0000
2662306a36Sopenharmony_ci#define LTC2983_TEMP_RES_START_REG		0x0010
2762306a36Sopenharmony_ci#define LTC2983_TEMP_RES_END_REG		0x005F
2862306a36Sopenharmony_ci#define LTC2983_EEPROM_KEY_REG			0x00B0
2962306a36Sopenharmony_ci#define LTC2983_EEPROM_READ_STATUS_REG		0x00D0
3062306a36Sopenharmony_ci#define LTC2983_GLOBAL_CONFIG_REG		0x00F0
3162306a36Sopenharmony_ci#define LTC2983_MULT_CHANNEL_START_REG		0x00F4
3262306a36Sopenharmony_ci#define LTC2983_MULT_CHANNEL_END_REG		0x00F7
3362306a36Sopenharmony_ci#define LTC2986_EEPROM_STATUS_REG		0x00F9
3462306a36Sopenharmony_ci#define LTC2983_MUX_CONFIG_REG			0x00FF
3562306a36Sopenharmony_ci#define LTC2983_CHAN_ASSIGN_START_REG		0x0200
3662306a36Sopenharmony_ci#define LTC2983_CHAN_ASSIGN_END_REG		0x024F
3762306a36Sopenharmony_ci#define LTC2983_CUST_SENS_TBL_START_REG		0x0250
3862306a36Sopenharmony_ci#define LTC2983_CUST_SENS_TBL_END_REG		0x03CF
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define LTC2983_DIFFERENTIAL_CHAN_MIN		2
4162306a36Sopenharmony_ci#define LTC2983_MIN_CHANNELS_NR			1
4262306a36Sopenharmony_ci#define LTC2983_SLEEP				0x97
4362306a36Sopenharmony_ci#define LTC2983_CUSTOM_STEINHART_SIZE		24
4462306a36Sopenharmony_ci#define LTC2983_CUSTOM_SENSOR_ENTRY_SZ		6
4562306a36Sopenharmony_ci#define LTC2983_CUSTOM_STEINHART_ENTRY_SZ	4
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define LTC2983_EEPROM_KEY			0xA53C0F5A
4862306a36Sopenharmony_ci#define LTC2983_EEPROM_WRITE_CMD		0x15
4962306a36Sopenharmony_ci#define LTC2983_EEPROM_READ_CMD			0x16
5062306a36Sopenharmony_ci#define LTC2983_EEPROM_STATUS_FAILURE_MASK	GENMASK(3, 1)
5162306a36Sopenharmony_ci#define LTC2983_EEPROM_READ_FAILURE_MASK	GENMASK(7, 0)
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define LTC2983_EEPROM_WRITE_TIME_MS		2600
5462306a36Sopenharmony_ci#define LTC2983_EEPROM_READ_TIME_MS		20
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#define LTC2983_CHAN_START_ADDR(chan) \
5762306a36Sopenharmony_ci			(((chan - 1) * 4) + LTC2983_CHAN_ASSIGN_START_REG)
5862306a36Sopenharmony_ci#define LTC2983_CHAN_RES_ADDR(chan) \
5962306a36Sopenharmony_ci			(((chan - 1) * 4) + LTC2983_TEMP_RES_START_REG)
6062306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_DIFF_MASK		BIT(3)
6162306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_SGL(x) \
6262306a36Sopenharmony_ci				FIELD_PREP(LTC2983_THERMOCOUPLE_DIFF_MASK, x)
6362306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_OC_CURR_MASK	GENMASK(1, 0)
6462306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_OC_CURR(x) \
6562306a36Sopenharmony_ci				FIELD_PREP(LTC2983_THERMOCOUPLE_OC_CURR_MASK, x)
6662306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_OC_CHECK_MASK	BIT(2)
6762306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_OC_CHECK(x) \
6862306a36Sopenharmony_ci			FIELD_PREP(LTC2983_THERMOCOUPLE_OC_CHECK_MASK, x)
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define LTC2983_THERMISTOR_DIFF_MASK		BIT(2)
7162306a36Sopenharmony_ci#define LTC2983_THERMISTOR_SGL(x) \
7262306a36Sopenharmony_ci				FIELD_PREP(LTC2983_THERMISTOR_DIFF_MASK, x)
7362306a36Sopenharmony_ci#define LTC2983_THERMISTOR_R_SHARE_MASK		BIT(1)
7462306a36Sopenharmony_ci#define LTC2983_THERMISTOR_R_SHARE(x) \
7562306a36Sopenharmony_ci				FIELD_PREP(LTC2983_THERMISTOR_R_SHARE_MASK, x)
7662306a36Sopenharmony_ci#define LTC2983_THERMISTOR_C_ROTATE_MASK	BIT(0)
7762306a36Sopenharmony_ci#define LTC2983_THERMISTOR_C_ROTATE(x) \
7862306a36Sopenharmony_ci				FIELD_PREP(LTC2983_THERMISTOR_C_ROTATE_MASK, x)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define LTC2983_DIODE_DIFF_MASK			BIT(2)
8162306a36Sopenharmony_ci#define LTC2983_DIODE_SGL(x) \
8262306a36Sopenharmony_ci			FIELD_PREP(LTC2983_DIODE_DIFF_MASK, x)
8362306a36Sopenharmony_ci#define LTC2983_DIODE_3_CONV_CYCLE_MASK		BIT(1)
8462306a36Sopenharmony_ci#define LTC2983_DIODE_3_CONV_CYCLE(x) \
8562306a36Sopenharmony_ci				FIELD_PREP(LTC2983_DIODE_3_CONV_CYCLE_MASK, x)
8662306a36Sopenharmony_ci#define LTC2983_DIODE_AVERAGE_ON_MASK		BIT(0)
8762306a36Sopenharmony_ci#define LTC2983_DIODE_AVERAGE_ON(x) \
8862306a36Sopenharmony_ci				FIELD_PREP(LTC2983_DIODE_AVERAGE_ON_MASK, x)
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define LTC2983_RTD_4_WIRE_MASK			BIT(3)
9162306a36Sopenharmony_ci#define LTC2983_RTD_ROTATION_MASK		BIT(1)
9262306a36Sopenharmony_ci#define LTC2983_RTD_C_ROTATE(x) \
9362306a36Sopenharmony_ci			FIELD_PREP(LTC2983_RTD_ROTATION_MASK, x)
9462306a36Sopenharmony_ci#define LTC2983_RTD_KELVIN_R_SENSE_MASK		GENMASK(3, 2)
9562306a36Sopenharmony_ci#define LTC2983_RTD_N_WIRES_MASK		GENMASK(3, 2)
9662306a36Sopenharmony_ci#define LTC2983_RTD_N_WIRES(x) \
9762306a36Sopenharmony_ci			FIELD_PREP(LTC2983_RTD_N_WIRES_MASK, x)
9862306a36Sopenharmony_ci#define LTC2983_RTD_R_SHARE_MASK		BIT(0)
9962306a36Sopenharmony_ci#define LTC2983_RTD_R_SHARE(x) \
10062306a36Sopenharmony_ci			FIELD_PREP(LTC2983_RTD_R_SHARE_MASK, 1)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci#define LTC2983_COMMON_HARD_FAULT_MASK	GENMASK(31, 30)
10362306a36Sopenharmony_ci#define LTC2983_COMMON_SOFT_FAULT_MASK	GENMASK(27, 25)
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci#define	LTC2983_STATUS_START_MASK	BIT(7)
10662306a36Sopenharmony_ci#define	LTC2983_STATUS_START(x)		FIELD_PREP(LTC2983_STATUS_START_MASK, x)
10762306a36Sopenharmony_ci#define	LTC2983_STATUS_UP_MASK		GENMASK(7, 6)
10862306a36Sopenharmony_ci#define	LTC2983_STATUS_UP(reg)		FIELD_GET(LTC2983_STATUS_UP_MASK, reg)
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#define	LTC2983_STATUS_CHAN_SEL_MASK	GENMASK(4, 0)
11162306a36Sopenharmony_ci#define	LTC2983_STATUS_CHAN_SEL(x) \
11262306a36Sopenharmony_ci				FIELD_PREP(LTC2983_STATUS_CHAN_SEL_MASK, x)
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#define LTC2983_TEMP_UNITS_MASK		BIT(2)
11562306a36Sopenharmony_ci#define LTC2983_TEMP_UNITS(x)		FIELD_PREP(LTC2983_TEMP_UNITS_MASK, x)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci#define LTC2983_NOTCH_FREQ_MASK		GENMASK(1, 0)
11862306a36Sopenharmony_ci#define LTC2983_NOTCH_FREQ(x)		FIELD_PREP(LTC2983_NOTCH_FREQ_MASK, x)
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#define LTC2983_RES_VALID_MASK		BIT(24)
12162306a36Sopenharmony_ci#define LTC2983_DATA_MASK		GENMASK(23, 0)
12262306a36Sopenharmony_ci#define LTC2983_DATA_SIGN_BIT		23
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#define LTC2983_CHAN_TYPE_MASK		GENMASK(31, 27)
12562306a36Sopenharmony_ci#define LTC2983_CHAN_TYPE(x)		FIELD_PREP(LTC2983_CHAN_TYPE_MASK, x)
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/* cold junction for thermocouples and rsense for rtd's and thermistor's */
12862306a36Sopenharmony_ci#define LTC2983_CHAN_ASSIGN_MASK	GENMASK(26, 22)
12962306a36Sopenharmony_ci#define LTC2983_CHAN_ASSIGN(x)		FIELD_PREP(LTC2983_CHAN_ASSIGN_MASK, x)
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#define LTC2983_CUSTOM_LEN_MASK		GENMASK(5, 0)
13262306a36Sopenharmony_ci#define LTC2983_CUSTOM_LEN(x)		FIELD_PREP(LTC2983_CUSTOM_LEN_MASK, x)
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#define LTC2983_CUSTOM_ADDR_MASK	GENMASK(11, 6)
13562306a36Sopenharmony_ci#define LTC2983_CUSTOM_ADDR(x)		FIELD_PREP(LTC2983_CUSTOM_ADDR_MASK, x)
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_CFG_MASK	GENMASK(21, 18)
13862306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_CFG(x) \
13962306a36Sopenharmony_ci				FIELD_PREP(LTC2983_THERMOCOUPLE_CFG_MASK, x)
14062306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_HARD_FAULT_MASK	GENMASK(31, 29)
14162306a36Sopenharmony_ci#define LTC2983_THERMOCOUPLE_SOFT_FAULT_MASK	GENMASK(28, 25)
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci#define LTC2983_RTD_CFG_MASK		GENMASK(21, 18)
14462306a36Sopenharmony_ci#define LTC2983_RTD_CFG(x)		FIELD_PREP(LTC2983_RTD_CFG_MASK, x)
14562306a36Sopenharmony_ci#define LTC2983_RTD_EXC_CURRENT_MASK	GENMASK(17, 14)
14662306a36Sopenharmony_ci#define LTC2983_RTD_EXC_CURRENT(x) \
14762306a36Sopenharmony_ci				FIELD_PREP(LTC2983_RTD_EXC_CURRENT_MASK, x)
14862306a36Sopenharmony_ci#define LTC2983_RTD_CURVE_MASK		GENMASK(13, 12)
14962306a36Sopenharmony_ci#define LTC2983_RTD_CURVE(x)		FIELD_PREP(LTC2983_RTD_CURVE_MASK, x)
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci#define LTC2983_THERMISTOR_CFG_MASK	GENMASK(21, 19)
15262306a36Sopenharmony_ci#define LTC2983_THERMISTOR_CFG(x) \
15362306a36Sopenharmony_ci				FIELD_PREP(LTC2983_THERMISTOR_CFG_MASK, x)
15462306a36Sopenharmony_ci#define LTC2983_THERMISTOR_EXC_CURRENT_MASK	GENMASK(18, 15)
15562306a36Sopenharmony_ci#define LTC2983_THERMISTOR_EXC_CURRENT(x) \
15662306a36Sopenharmony_ci			FIELD_PREP(LTC2983_THERMISTOR_EXC_CURRENT_MASK, x)
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci#define LTC2983_DIODE_CFG_MASK		GENMASK(26, 24)
15962306a36Sopenharmony_ci#define LTC2983_DIODE_CFG(x)		FIELD_PREP(LTC2983_DIODE_CFG_MASK, x)
16062306a36Sopenharmony_ci#define LTC2983_DIODE_EXC_CURRENT_MASK	GENMASK(23, 22)
16162306a36Sopenharmony_ci#define LTC2983_DIODE_EXC_CURRENT(x) \
16262306a36Sopenharmony_ci				FIELD_PREP(LTC2983_DIODE_EXC_CURRENT_MASK, x)
16362306a36Sopenharmony_ci#define LTC2983_DIODE_IDEAL_FACTOR_MASK	GENMASK(21, 0)
16462306a36Sopenharmony_ci#define LTC2983_DIODE_IDEAL_FACTOR(x) \
16562306a36Sopenharmony_ci				FIELD_PREP(LTC2983_DIODE_IDEAL_FACTOR_MASK, x)
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci#define LTC2983_R_SENSE_VAL_MASK	GENMASK(26, 0)
16862306a36Sopenharmony_ci#define LTC2983_R_SENSE_VAL(x)		FIELD_PREP(LTC2983_R_SENSE_VAL_MASK, x)
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci#define LTC2983_ADC_SINGLE_ENDED_MASK	BIT(26)
17162306a36Sopenharmony_ci#define LTC2983_ADC_SINGLE_ENDED(x) \
17262306a36Sopenharmony_ci				FIELD_PREP(LTC2983_ADC_SINGLE_ENDED_MASK, x)
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cienum {
17562306a36Sopenharmony_ci	LTC2983_SENSOR_THERMOCOUPLE = 1,
17662306a36Sopenharmony_ci	LTC2983_SENSOR_THERMOCOUPLE_CUSTOM = 9,
17762306a36Sopenharmony_ci	LTC2983_SENSOR_RTD = 10,
17862306a36Sopenharmony_ci	LTC2983_SENSOR_RTD_CUSTOM = 18,
17962306a36Sopenharmony_ci	LTC2983_SENSOR_THERMISTOR = 19,
18062306a36Sopenharmony_ci	LTC2983_SENSOR_THERMISTOR_STEINHART = 26,
18162306a36Sopenharmony_ci	LTC2983_SENSOR_THERMISTOR_CUSTOM = 27,
18262306a36Sopenharmony_ci	LTC2983_SENSOR_DIODE = 28,
18362306a36Sopenharmony_ci	LTC2983_SENSOR_SENSE_RESISTOR = 29,
18462306a36Sopenharmony_ci	LTC2983_SENSOR_DIRECT_ADC = 30,
18562306a36Sopenharmony_ci	LTC2983_SENSOR_ACTIVE_TEMP = 31,
18662306a36Sopenharmony_ci};
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci#define to_thermocouple(_sensor) \
18962306a36Sopenharmony_ci		container_of(_sensor, struct ltc2983_thermocouple, sensor)
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci#define to_rtd(_sensor) \
19262306a36Sopenharmony_ci		container_of(_sensor, struct ltc2983_rtd, sensor)
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci#define to_thermistor(_sensor) \
19562306a36Sopenharmony_ci		container_of(_sensor, struct ltc2983_thermistor, sensor)
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci#define to_diode(_sensor) \
19862306a36Sopenharmony_ci		container_of(_sensor, struct ltc2983_diode, sensor)
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci#define to_rsense(_sensor) \
20162306a36Sopenharmony_ci		container_of(_sensor, struct ltc2983_rsense, sensor)
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci#define to_adc(_sensor) \
20462306a36Sopenharmony_ci		container_of(_sensor, struct ltc2983_adc, sensor)
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci#define to_temp(_sensor) \
20762306a36Sopenharmony_ci		container_of(_sensor, struct ltc2983_temp, sensor)
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistruct ltc2983_chip_info {
21062306a36Sopenharmony_ci	unsigned int max_channels_nr;
21162306a36Sopenharmony_ci	bool has_temp;
21262306a36Sopenharmony_ci	bool has_eeprom;
21362306a36Sopenharmony_ci};
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistruct ltc2983_data {
21662306a36Sopenharmony_ci	const struct ltc2983_chip_info *info;
21762306a36Sopenharmony_ci	struct regmap *regmap;
21862306a36Sopenharmony_ci	struct spi_device *spi;
21962306a36Sopenharmony_ci	struct mutex lock;
22062306a36Sopenharmony_ci	struct completion completion;
22162306a36Sopenharmony_ci	struct iio_chan_spec *iio_chan;
22262306a36Sopenharmony_ci	struct ltc2983_sensor **sensors;
22362306a36Sopenharmony_ci	u32 mux_delay_config;
22462306a36Sopenharmony_ci	u32 filter_notch_freq;
22562306a36Sopenharmony_ci	u16 custom_table_size;
22662306a36Sopenharmony_ci	u8 num_channels;
22762306a36Sopenharmony_ci	u8 iio_channels;
22862306a36Sopenharmony_ci	/*
22962306a36Sopenharmony_ci	 * DMA (thus cache coherency maintenance) may require the
23062306a36Sopenharmony_ci	 * transfer buffers to live in their own cache lines.
23162306a36Sopenharmony_ci	 * Holds the converted temperature
23262306a36Sopenharmony_ci	 */
23362306a36Sopenharmony_ci	__be32 temp __aligned(IIO_DMA_MINALIGN);
23462306a36Sopenharmony_ci	__be32 chan_val;
23562306a36Sopenharmony_ci	__be32 eeprom_key;
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistruct ltc2983_sensor {
23962306a36Sopenharmony_ci	int (*fault_handler)(const struct ltc2983_data *st, const u32 result);
24062306a36Sopenharmony_ci	int (*assign_chan)(struct ltc2983_data *st,
24162306a36Sopenharmony_ci			   const struct ltc2983_sensor *sensor);
24262306a36Sopenharmony_ci	/* specifies the sensor channel */
24362306a36Sopenharmony_ci	u32 chan;
24462306a36Sopenharmony_ci	/* sensor type */
24562306a36Sopenharmony_ci	u32 type;
24662306a36Sopenharmony_ci};
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistruct ltc2983_custom_sensor {
24962306a36Sopenharmony_ci	/* raw table sensor data */
25062306a36Sopenharmony_ci	void *table;
25162306a36Sopenharmony_ci	size_t size;
25262306a36Sopenharmony_ci	/* address offset */
25362306a36Sopenharmony_ci	s8 offset;
25462306a36Sopenharmony_ci	bool is_steinhart;
25562306a36Sopenharmony_ci};
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistruct ltc2983_thermocouple {
25862306a36Sopenharmony_ci	struct ltc2983_sensor sensor;
25962306a36Sopenharmony_ci	struct ltc2983_custom_sensor *custom;
26062306a36Sopenharmony_ci	u32 sensor_config;
26162306a36Sopenharmony_ci	u32 cold_junction_chan;
26262306a36Sopenharmony_ci};
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistruct ltc2983_rtd {
26562306a36Sopenharmony_ci	struct ltc2983_sensor sensor;
26662306a36Sopenharmony_ci	struct ltc2983_custom_sensor *custom;
26762306a36Sopenharmony_ci	u32 sensor_config;
26862306a36Sopenharmony_ci	u32 r_sense_chan;
26962306a36Sopenharmony_ci	u32 excitation_current;
27062306a36Sopenharmony_ci	u32 rtd_curve;
27162306a36Sopenharmony_ci};
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistruct ltc2983_thermistor {
27462306a36Sopenharmony_ci	struct ltc2983_sensor sensor;
27562306a36Sopenharmony_ci	struct ltc2983_custom_sensor *custom;
27662306a36Sopenharmony_ci	u32 sensor_config;
27762306a36Sopenharmony_ci	u32 r_sense_chan;
27862306a36Sopenharmony_ci	u32 excitation_current;
27962306a36Sopenharmony_ci};
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistruct ltc2983_diode {
28262306a36Sopenharmony_ci	struct ltc2983_sensor sensor;
28362306a36Sopenharmony_ci	u32 sensor_config;
28462306a36Sopenharmony_ci	u32 excitation_current;
28562306a36Sopenharmony_ci	u32 ideal_factor_value;
28662306a36Sopenharmony_ci};
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistruct ltc2983_rsense {
28962306a36Sopenharmony_ci	struct ltc2983_sensor sensor;
29062306a36Sopenharmony_ci	u32 r_sense_val;
29162306a36Sopenharmony_ci};
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cistruct ltc2983_adc {
29462306a36Sopenharmony_ci	struct ltc2983_sensor sensor;
29562306a36Sopenharmony_ci	bool single_ended;
29662306a36Sopenharmony_ci};
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cistruct ltc2983_temp {
29962306a36Sopenharmony_ci	struct ltc2983_sensor sensor;
30062306a36Sopenharmony_ci	struct ltc2983_custom_sensor *custom;
30162306a36Sopenharmony_ci	bool single_ended;
30262306a36Sopenharmony_ci};
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci/*
30562306a36Sopenharmony_ci * Convert to Q format numbers. These number's are integers where
30662306a36Sopenharmony_ci * the number of integer and fractional bits are specified. The resolution
30762306a36Sopenharmony_ci * is given by 1/@resolution and tell us the number of fractional bits. For
30862306a36Sopenharmony_ci * instance a resolution of 2^-10 means we have 10 fractional bits.
30962306a36Sopenharmony_ci */
31062306a36Sopenharmony_cistatic u32 __convert_to_raw(const u64 val, const u32 resolution)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	u64 __res = val * resolution;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	/* all values are multiplied by 1000000 to remove the fraction */
31562306a36Sopenharmony_ci	do_div(__res, 1000000);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	return __res;
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic u32 __convert_to_raw_sign(const u64 val, const u32 resolution)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	s64 __res = -(s32)val;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	__res = __convert_to_raw(__res, resolution);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	return (u32)-__res;
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic int __ltc2983_fault_handler(const struct ltc2983_data *st,
33062306a36Sopenharmony_ci				   const u32 result, const u32 hard_mask,
33162306a36Sopenharmony_ci				   const u32 soft_mask)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	const struct device *dev = &st->spi->dev;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	if (result & hard_mask) {
33662306a36Sopenharmony_ci		dev_err(dev, "Invalid conversion: Sensor HARD fault\n");
33762306a36Sopenharmony_ci		return -EIO;
33862306a36Sopenharmony_ci	} else if (result & soft_mask) {
33962306a36Sopenharmony_ci		/* just print a warning */
34062306a36Sopenharmony_ci		dev_warn(dev, "Suspicious conversion: Sensor SOFT fault\n");
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	return 0;
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic int __ltc2983_chan_assign_common(struct ltc2983_data *st,
34762306a36Sopenharmony_ci					const struct ltc2983_sensor *sensor,
34862306a36Sopenharmony_ci					u32 chan_val)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	u32 reg = LTC2983_CHAN_START_ADDR(sensor->chan);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	chan_val |= LTC2983_CHAN_TYPE(sensor->type);
35362306a36Sopenharmony_ci	dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg,
35462306a36Sopenharmony_ci		chan_val);
35562306a36Sopenharmony_ci	st->chan_val = cpu_to_be32(chan_val);
35662306a36Sopenharmony_ci	return regmap_bulk_write(st->regmap, reg, &st->chan_val,
35762306a36Sopenharmony_ci				 sizeof(st->chan_val));
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_cistatic int __ltc2983_chan_custom_sensor_assign(struct ltc2983_data *st,
36162306a36Sopenharmony_ci					  struct ltc2983_custom_sensor *custom,
36262306a36Sopenharmony_ci					  u32 *chan_val)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	u32 reg;
36562306a36Sopenharmony_ci	u8 mult = custom->is_steinhart ? LTC2983_CUSTOM_STEINHART_ENTRY_SZ :
36662306a36Sopenharmony_ci		LTC2983_CUSTOM_SENSOR_ENTRY_SZ;
36762306a36Sopenharmony_ci	const struct device *dev = &st->spi->dev;
36862306a36Sopenharmony_ci	/*
36962306a36Sopenharmony_ci	 * custom->size holds the raw size of the table. However, when
37062306a36Sopenharmony_ci	 * configuring the sensor channel, we must write the number of
37162306a36Sopenharmony_ci	 * entries of the table minus 1. For steinhart sensors 0 is written
37262306a36Sopenharmony_ci	 * since the size is constant!
37362306a36Sopenharmony_ci	 */
37462306a36Sopenharmony_ci	const u8 len = custom->is_steinhart ? 0 :
37562306a36Sopenharmony_ci		(custom->size / LTC2983_CUSTOM_SENSOR_ENTRY_SZ) - 1;
37662306a36Sopenharmony_ci	/*
37762306a36Sopenharmony_ci	 * Check if the offset was assigned already. It should be for steinhart
37862306a36Sopenharmony_ci	 * sensors. When coming from sleep, it should be assigned for all.
37962306a36Sopenharmony_ci	 */
38062306a36Sopenharmony_ci	if (custom->offset < 0) {
38162306a36Sopenharmony_ci		/*
38262306a36Sopenharmony_ci		 * This needs to be done again here because, from the moment
38362306a36Sopenharmony_ci		 * when this test was done (successfully) for this custom
38462306a36Sopenharmony_ci		 * sensor, a steinhart sensor might have been added changing
38562306a36Sopenharmony_ci		 * custom_table_size...
38662306a36Sopenharmony_ci		 */
38762306a36Sopenharmony_ci		if (st->custom_table_size + custom->size >
38862306a36Sopenharmony_ci		    (LTC2983_CUST_SENS_TBL_END_REG -
38962306a36Sopenharmony_ci		     LTC2983_CUST_SENS_TBL_START_REG) + 1) {
39062306a36Sopenharmony_ci			dev_err(dev,
39162306a36Sopenharmony_ci				"Not space left(%d) for new custom sensor(%zu)",
39262306a36Sopenharmony_ci				st->custom_table_size,
39362306a36Sopenharmony_ci				custom->size);
39462306a36Sopenharmony_ci			return -EINVAL;
39562306a36Sopenharmony_ci		}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci		custom->offset = st->custom_table_size /
39862306a36Sopenharmony_ci					LTC2983_CUSTOM_SENSOR_ENTRY_SZ;
39962306a36Sopenharmony_ci		st->custom_table_size += custom->size;
40062306a36Sopenharmony_ci	}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	reg = (custom->offset * mult) + LTC2983_CUST_SENS_TBL_START_REG;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	*chan_val |= LTC2983_CUSTOM_LEN(len);
40562306a36Sopenharmony_ci	*chan_val |= LTC2983_CUSTOM_ADDR(custom->offset);
40662306a36Sopenharmony_ci	dev_dbg(dev, "Assign custom sensor, reg:0x%04X, off:%d, sz:%zu",
40762306a36Sopenharmony_ci		reg, custom->offset,
40862306a36Sopenharmony_ci		custom->size);
40962306a36Sopenharmony_ci	/* write custom sensor table */
41062306a36Sopenharmony_ci	return regmap_bulk_write(st->regmap, reg, custom->table, custom->size);
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic struct ltc2983_custom_sensor *
41462306a36Sopenharmony_ci__ltc2983_custom_sensor_new(struct ltc2983_data *st, const struct fwnode_handle *fn,
41562306a36Sopenharmony_ci			    const char *propname, const bool is_steinhart,
41662306a36Sopenharmony_ci			    const u32 resolution, const bool has_signed)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	struct ltc2983_custom_sensor *new_custom;
41962306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
42062306a36Sopenharmony_ci	/*
42162306a36Sopenharmony_ci	 * For custom steinhart, the full u32 is taken. For all the others
42262306a36Sopenharmony_ci	 * the MSB is discarded.
42362306a36Sopenharmony_ci	 */
42462306a36Sopenharmony_ci	const u8 n_size = is_steinhart ? 4 : 3;
42562306a36Sopenharmony_ci	u8 index, n_entries;
42662306a36Sopenharmony_ci	int ret;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	if (is_steinhart)
42962306a36Sopenharmony_ci		n_entries = fwnode_property_count_u32(fn, propname);
43062306a36Sopenharmony_ci	else
43162306a36Sopenharmony_ci		n_entries = fwnode_property_count_u64(fn, propname);
43262306a36Sopenharmony_ci	/* n_entries must be an even number */
43362306a36Sopenharmony_ci	if (!n_entries || (n_entries % 2) != 0) {
43462306a36Sopenharmony_ci		dev_err(dev, "Number of entries either 0 or not even\n");
43562306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	new_custom = devm_kzalloc(dev, sizeof(*new_custom), GFP_KERNEL);
43962306a36Sopenharmony_ci	if (!new_custom)
44062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	new_custom->size = n_entries * n_size;
44362306a36Sopenharmony_ci	/* check Steinhart size */
44462306a36Sopenharmony_ci	if (is_steinhart && new_custom->size != LTC2983_CUSTOM_STEINHART_SIZE) {
44562306a36Sopenharmony_ci		dev_err(dev, "Steinhart sensors size(%zu) must be %u\n", new_custom->size,
44662306a36Sopenharmony_ci			LTC2983_CUSTOM_STEINHART_SIZE);
44762306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
44862306a36Sopenharmony_ci	}
44962306a36Sopenharmony_ci	/* Check space on the table. */
45062306a36Sopenharmony_ci	if (st->custom_table_size + new_custom->size >
45162306a36Sopenharmony_ci	    (LTC2983_CUST_SENS_TBL_END_REG -
45262306a36Sopenharmony_ci	     LTC2983_CUST_SENS_TBL_START_REG) + 1) {
45362306a36Sopenharmony_ci		dev_err(dev, "No space left(%d) for new custom sensor(%zu)",
45462306a36Sopenharmony_ci				st->custom_table_size, new_custom->size);
45562306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	/* allocate the table */
45962306a36Sopenharmony_ci	if (is_steinhart)
46062306a36Sopenharmony_ci		new_custom->table = devm_kcalloc(dev, n_entries, sizeof(u32), GFP_KERNEL);
46162306a36Sopenharmony_ci	else
46262306a36Sopenharmony_ci		new_custom->table = devm_kcalloc(dev, n_entries, sizeof(u64), GFP_KERNEL);
46362306a36Sopenharmony_ci	if (!new_custom->table)
46462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	/*
46762306a36Sopenharmony_ci	 * Steinhart sensors are configured with raw values in the firmware
46862306a36Sopenharmony_ci	 * node. For the other sensors we must convert the value to raw.
46962306a36Sopenharmony_ci	 * The odd index's correspond to temperatures and always have 1/1024
47062306a36Sopenharmony_ci	 * of resolution. Temperatures also come in Kelvin, so signed values
47162306a36Sopenharmony_ci	 * are not possible.
47262306a36Sopenharmony_ci	 */
47362306a36Sopenharmony_ci	if (is_steinhart) {
47462306a36Sopenharmony_ci		ret = fwnode_property_read_u32_array(fn, propname, new_custom->table, n_entries);
47562306a36Sopenharmony_ci		if (ret < 0)
47662306a36Sopenharmony_ci			return ERR_PTR(ret);
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci		cpu_to_be32_array(new_custom->table, new_custom->table, n_entries);
47962306a36Sopenharmony_ci	} else {
48062306a36Sopenharmony_ci		ret = fwnode_property_read_u64_array(fn, propname, new_custom->table, n_entries);
48162306a36Sopenharmony_ci		if (ret < 0)
48262306a36Sopenharmony_ci			return ERR_PTR(ret);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci		for (index = 0; index < n_entries; index++) {
48562306a36Sopenharmony_ci			u64 temp = ((u64 *)new_custom->table)[index];
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci			if ((index % 2) != 0)
48862306a36Sopenharmony_ci				temp = __convert_to_raw(temp, 1024);
48962306a36Sopenharmony_ci			else if (has_signed && (s64)temp < 0)
49062306a36Sopenharmony_ci				temp = __convert_to_raw_sign(temp, resolution);
49162306a36Sopenharmony_ci			else
49262306a36Sopenharmony_ci				temp = __convert_to_raw(temp, resolution);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci			put_unaligned_be24(temp, new_custom->table + index * 3);
49562306a36Sopenharmony_ci		}
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	new_custom->is_steinhart = is_steinhart;
49962306a36Sopenharmony_ci	/*
50062306a36Sopenharmony_ci	 * This is done to first add all the steinhart sensors to the table,
50162306a36Sopenharmony_ci	 * in order to maximize the table usage. If we mix adding steinhart
50262306a36Sopenharmony_ci	 * with the other sensors, we might have to do some roundup to make
50362306a36Sopenharmony_ci	 * sure that sensor_addr - 0x250(start address) is a multiple of 4
50462306a36Sopenharmony_ci	 * (for steinhart), and a multiple of 6 for all the other sensors.
50562306a36Sopenharmony_ci	 * Since we have const 24 bytes for steinhart sensors and 24 is
50662306a36Sopenharmony_ci	 * also a multiple of 6, we guarantee that the first non-steinhart
50762306a36Sopenharmony_ci	 * sensor will sit in a correct address without the need of filling
50862306a36Sopenharmony_ci	 * addresses.
50962306a36Sopenharmony_ci	 */
51062306a36Sopenharmony_ci	if (is_steinhart) {
51162306a36Sopenharmony_ci		new_custom->offset = st->custom_table_size /
51262306a36Sopenharmony_ci					LTC2983_CUSTOM_STEINHART_ENTRY_SZ;
51362306a36Sopenharmony_ci		st->custom_table_size += new_custom->size;
51462306a36Sopenharmony_ci	} else {
51562306a36Sopenharmony_ci		/* mark as unset. This is checked later on the assign phase */
51662306a36Sopenharmony_ci		new_custom->offset = -1;
51762306a36Sopenharmony_ci	}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	return new_custom;
52062306a36Sopenharmony_ci}
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_cistatic int ltc2983_thermocouple_fault_handler(const struct ltc2983_data *st,
52362306a36Sopenharmony_ci					      const u32 result)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	return __ltc2983_fault_handler(st, result,
52662306a36Sopenharmony_ci				       LTC2983_THERMOCOUPLE_HARD_FAULT_MASK,
52762306a36Sopenharmony_ci				       LTC2983_THERMOCOUPLE_SOFT_FAULT_MASK);
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_cistatic int ltc2983_common_fault_handler(const struct ltc2983_data *st,
53162306a36Sopenharmony_ci					const u32 result)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	return __ltc2983_fault_handler(st, result,
53462306a36Sopenharmony_ci				       LTC2983_COMMON_HARD_FAULT_MASK,
53562306a36Sopenharmony_ci				       LTC2983_COMMON_SOFT_FAULT_MASK);
53662306a36Sopenharmony_ci}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_cistatic int ltc2983_thermocouple_assign_chan(struct ltc2983_data *st,
53962306a36Sopenharmony_ci				const struct ltc2983_sensor *sensor)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	struct ltc2983_thermocouple *thermo = to_thermocouple(sensor);
54262306a36Sopenharmony_ci	u32 chan_val;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	chan_val = LTC2983_CHAN_ASSIGN(thermo->cold_junction_chan);
54562306a36Sopenharmony_ci	chan_val |= LTC2983_THERMOCOUPLE_CFG(thermo->sensor_config);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	if (thermo->custom) {
54862306a36Sopenharmony_ci		int ret;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci		ret = __ltc2983_chan_custom_sensor_assign(st, thermo->custom,
55162306a36Sopenharmony_ci							  &chan_val);
55262306a36Sopenharmony_ci		if (ret)
55362306a36Sopenharmony_ci			return ret;
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci	return __ltc2983_chan_assign_common(st, sensor, chan_val);
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_cistatic int ltc2983_rtd_assign_chan(struct ltc2983_data *st,
55962306a36Sopenharmony_ci				   const struct ltc2983_sensor *sensor)
56062306a36Sopenharmony_ci{
56162306a36Sopenharmony_ci	struct ltc2983_rtd *rtd = to_rtd(sensor);
56262306a36Sopenharmony_ci	u32 chan_val;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	chan_val = LTC2983_CHAN_ASSIGN(rtd->r_sense_chan);
56562306a36Sopenharmony_ci	chan_val |= LTC2983_RTD_CFG(rtd->sensor_config);
56662306a36Sopenharmony_ci	chan_val |= LTC2983_RTD_EXC_CURRENT(rtd->excitation_current);
56762306a36Sopenharmony_ci	chan_val |= LTC2983_RTD_CURVE(rtd->rtd_curve);
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	if (rtd->custom) {
57062306a36Sopenharmony_ci		int ret;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci		ret = __ltc2983_chan_custom_sensor_assign(st, rtd->custom,
57362306a36Sopenharmony_ci							  &chan_val);
57462306a36Sopenharmony_ci		if (ret)
57562306a36Sopenharmony_ci			return ret;
57662306a36Sopenharmony_ci	}
57762306a36Sopenharmony_ci	return __ltc2983_chan_assign_common(st, sensor, chan_val);
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cistatic int ltc2983_thermistor_assign_chan(struct ltc2983_data *st,
58162306a36Sopenharmony_ci					  const struct ltc2983_sensor *sensor)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct ltc2983_thermistor *thermistor = to_thermistor(sensor);
58462306a36Sopenharmony_ci	u32 chan_val;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	chan_val = LTC2983_CHAN_ASSIGN(thermistor->r_sense_chan);
58762306a36Sopenharmony_ci	chan_val |= LTC2983_THERMISTOR_CFG(thermistor->sensor_config);
58862306a36Sopenharmony_ci	chan_val |=
58962306a36Sopenharmony_ci		LTC2983_THERMISTOR_EXC_CURRENT(thermistor->excitation_current);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if (thermistor->custom) {
59262306a36Sopenharmony_ci		int ret;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci		ret = __ltc2983_chan_custom_sensor_assign(st,
59562306a36Sopenharmony_ci							  thermistor->custom,
59662306a36Sopenharmony_ci							  &chan_val);
59762306a36Sopenharmony_ci		if (ret)
59862306a36Sopenharmony_ci			return ret;
59962306a36Sopenharmony_ci	}
60062306a36Sopenharmony_ci	return __ltc2983_chan_assign_common(st, sensor, chan_val);
60162306a36Sopenharmony_ci}
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_cistatic int ltc2983_diode_assign_chan(struct ltc2983_data *st,
60462306a36Sopenharmony_ci				     const struct ltc2983_sensor *sensor)
60562306a36Sopenharmony_ci{
60662306a36Sopenharmony_ci	struct ltc2983_diode *diode = to_diode(sensor);
60762306a36Sopenharmony_ci	u32 chan_val;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	chan_val = LTC2983_DIODE_CFG(diode->sensor_config);
61062306a36Sopenharmony_ci	chan_val |= LTC2983_DIODE_EXC_CURRENT(diode->excitation_current);
61162306a36Sopenharmony_ci	chan_val |= LTC2983_DIODE_IDEAL_FACTOR(diode->ideal_factor_value);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	return __ltc2983_chan_assign_common(st, sensor, chan_val);
61462306a36Sopenharmony_ci}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_cistatic int ltc2983_r_sense_assign_chan(struct ltc2983_data *st,
61762306a36Sopenharmony_ci				       const struct ltc2983_sensor *sensor)
61862306a36Sopenharmony_ci{
61962306a36Sopenharmony_ci	struct ltc2983_rsense *rsense = to_rsense(sensor);
62062306a36Sopenharmony_ci	u32 chan_val;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	chan_val = LTC2983_R_SENSE_VAL(rsense->r_sense_val);
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	return __ltc2983_chan_assign_common(st, sensor, chan_val);
62562306a36Sopenharmony_ci}
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_cistatic int ltc2983_adc_assign_chan(struct ltc2983_data *st,
62862306a36Sopenharmony_ci				   const struct ltc2983_sensor *sensor)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	struct ltc2983_adc *adc = to_adc(sensor);
63162306a36Sopenharmony_ci	u32 chan_val;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	chan_val = LTC2983_ADC_SINGLE_ENDED(adc->single_ended);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	return __ltc2983_chan_assign_common(st, sensor, chan_val);
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistatic int ltc2983_temp_assign_chan(struct ltc2983_data *st,
63962306a36Sopenharmony_ci				    const struct ltc2983_sensor *sensor)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	struct ltc2983_temp *temp = to_temp(sensor);
64262306a36Sopenharmony_ci	u32 chan_val;
64362306a36Sopenharmony_ci	int ret;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	chan_val = LTC2983_ADC_SINGLE_ENDED(temp->single_ended);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	ret = __ltc2983_chan_custom_sensor_assign(st, temp->custom, &chan_val);
64862306a36Sopenharmony_ci	if (ret)
64962306a36Sopenharmony_ci		return ret;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	return __ltc2983_chan_assign_common(st, sensor, chan_val);
65262306a36Sopenharmony_ci}
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_cistatic struct ltc2983_sensor *
65562306a36Sopenharmony_ciltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data *st,
65662306a36Sopenharmony_ci			 const struct ltc2983_sensor *sensor)
65762306a36Sopenharmony_ci{
65862306a36Sopenharmony_ci	struct ltc2983_thermocouple *thermo;
65962306a36Sopenharmony_ci	struct fwnode_handle *ref;
66062306a36Sopenharmony_ci	u32 oc_current;
66162306a36Sopenharmony_ci	int ret;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	thermo = devm_kzalloc(&st->spi->dev, sizeof(*thermo), GFP_KERNEL);
66462306a36Sopenharmony_ci	if (!thermo)
66562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,single-ended"))
66862306a36Sopenharmony_ci		thermo->sensor_config = LTC2983_THERMOCOUPLE_SGL(1);
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	ret = fwnode_property_read_u32(child, "adi,sensor-oc-current-microamp", &oc_current);
67162306a36Sopenharmony_ci	if (!ret) {
67262306a36Sopenharmony_ci		switch (oc_current) {
67362306a36Sopenharmony_ci		case 10:
67462306a36Sopenharmony_ci			thermo->sensor_config |=
67562306a36Sopenharmony_ci					LTC2983_THERMOCOUPLE_OC_CURR(0);
67662306a36Sopenharmony_ci			break;
67762306a36Sopenharmony_ci		case 100:
67862306a36Sopenharmony_ci			thermo->sensor_config |=
67962306a36Sopenharmony_ci					LTC2983_THERMOCOUPLE_OC_CURR(1);
68062306a36Sopenharmony_ci			break;
68162306a36Sopenharmony_ci		case 500:
68262306a36Sopenharmony_ci			thermo->sensor_config |=
68362306a36Sopenharmony_ci					LTC2983_THERMOCOUPLE_OC_CURR(2);
68462306a36Sopenharmony_ci			break;
68562306a36Sopenharmony_ci		case 1000:
68662306a36Sopenharmony_ci			thermo->sensor_config |=
68762306a36Sopenharmony_ci					LTC2983_THERMOCOUPLE_OC_CURR(3);
68862306a36Sopenharmony_ci			break;
68962306a36Sopenharmony_ci		default:
69062306a36Sopenharmony_ci			dev_err(&st->spi->dev,
69162306a36Sopenharmony_ci				"Invalid open circuit current:%u", oc_current);
69262306a36Sopenharmony_ci			return ERR_PTR(-EINVAL);
69362306a36Sopenharmony_ci		}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci		thermo->sensor_config |= LTC2983_THERMOCOUPLE_OC_CHECK(1);
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci	/* validate channel index */
69862306a36Sopenharmony_ci	if (!(thermo->sensor_config & LTC2983_THERMOCOUPLE_DIFF_MASK) &&
69962306a36Sopenharmony_ci	    sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
70062306a36Sopenharmony_ci		dev_err(&st->spi->dev,
70162306a36Sopenharmony_ci			"Invalid chann:%d for differential thermocouple",
70262306a36Sopenharmony_ci			sensor->chan);
70362306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	ref = fwnode_find_reference(child, "adi,cold-junction-handle", 0);
70762306a36Sopenharmony_ci	if (IS_ERR(ref)) {
70862306a36Sopenharmony_ci		ref = NULL;
70962306a36Sopenharmony_ci	} else {
71062306a36Sopenharmony_ci		ret = fwnode_property_read_u32(ref, "reg", &thermo->cold_junction_chan);
71162306a36Sopenharmony_ci		if (ret) {
71262306a36Sopenharmony_ci			/*
71362306a36Sopenharmony_ci			 * This would be catched later but we can just return
71462306a36Sopenharmony_ci			 * the error right away.
71562306a36Sopenharmony_ci			 */
71662306a36Sopenharmony_ci			dev_err(&st->spi->dev, "Property reg must be given\n");
71762306a36Sopenharmony_ci			goto fail;
71862306a36Sopenharmony_ci		}
71962306a36Sopenharmony_ci	}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	/* check custom sensor */
72262306a36Sopenharmony_ci	if (sensor->type == LTC2983_SENSOR_THERMOCOUPLE_CUSTOM) {
72362306a36Sopenharmony_ci		const char *propname = "adi,custom-thermocouple";
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci		thermo->custom = __ltc2983_custom_sensor_new(st, child,
72662306a36Sopenharmony_ci							     propname, false,
72762306a36Sopenharmony_ci							     16384, true);
72862306a36Sopenharmony_ci		if (IS_ERR(thermo->custom)) {
72962306a36Sopenharmony_ci			ret = PTR_ERR(thermo->custom);
73062306a36Sopenharmony_ci			goto fail;
73162306a36Sopenharmony_ci		}
73262306a36Sopenharmony_ci	}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	/* set common parameters */
73562306a36Sopenharmony_ci	thermo->sensor.fault_handler = ltc2983_thermocouple_fault_handler;
73662306a36Sopenharmony_ci	thermo->sensor.assign_chan = ltc2983_thermocouple_assign_chan;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	fwnode_handle_put(ref);
73962306a36Sopenharmony_ci	return &thermo->sensor;
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cifail:
74262306a36Sopenharmony_ci	fwnode_handle_put(ref);
74362306a36Sopenharmony_ci	return ERR_PTR(ret);
74462306a36Sopenharmony_ci}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_cistatic struct ltc2983_sensor *
74762306a36Sopenharmony_ciltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
74862306a36Sopenharmony_ci		const struct ltc2983_sensor *sensor)
74962306a36Sopenharmony_ci{
75062306a36Sopenharmony_ci	struct ltc2983_rtd *rtd;
75162306a36Sopenharmony_ci	int ret = 0;
75262306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
75362306a36Sopenharmony_ci	struct fwnode_handle *ref;
75462306a36Sopenharmony_ci	u32 excitation_current = 0, n_wires = 0;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	rtd = devm_kzalloc(dev, sizeof(*rtd), GFP_KERNEL);
75762306a36Sopenharmony_ci	if (!rtd)
75862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	ref = fwnode_find_reference(child, "adi,rsense-handle", 0);
76162306a36Sopenharmony_ci	if (IS_ERR(ref)) {
76262306a36Sopenharmony_ci		dev_err(dev, "Property adi,rsense-handle missing or invalid");
76362306a36Sopenharmony_ci		return ERR_CAST(ref);
76462306a36Sopenharmony_ci	}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	ret = fwnode_property_read_u32(ref, "reg", &rtd->r_sense_chan);
76762306a36Sopenharmony_ci	if (ret) {
76862306a36Sopenharmony_ci		dev_err(dev, "Property reg must be given\n");
76962306a36Sopenharmony_ci		goto fail;
77062306a36Sopenharmony_ci	}
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	ret = fwnode_property_read_u32(child, "adi,number-of-wires", &n_wires);
77362306a36Sopenharmony_ci	if (!ret) {
77462306a36Sopenharmony_ci		switch (n_wires) {
77562306a36Sopenharmony_ci		case 2:
77662306a36Sopenharmony_ci			rtd->sensor_config = LTC2983_RTD_N_WIRES(0);
77762306a36Sopenharmony_ci			break;
77862306a36Sopenharmony_ci		case 3:
77962306a36Sopenharmony_ci			rtd->sensor_config = LTC2983_RTD_N_WIRES(1);
78062306a36Sopenharmony_ci			break;
78162306a36Sopenharmony_ci		case 4:
78262306a36Sopenharmony_ci			rtd->sensor_config = LTC2983_RTD_N_WIRES(2);
78362306a36Sopenharmony_ci			break;
78462306a36Sopenharmony_ci		case 5:
78562306a36Sopenharmony_ci			/* 4 wires, Kelvin Rsense */
78662306a36Sopenharmony_ci			rtd->sensor_config = LTC2983_RTD_N_WIRES(3);
78762306a36Sopenharmony_ci			break;
78862306a36Sopenharmony_ci		default:
78962306a36Sopenharmony_ci			dev_err(dev, "Invalid number of wires:%u\n", n_wires);
79062306a36Sopenharmony_ci			ret = -EINVAL;
79162306a36Sopenharmony_ci			goto fail;
79262306a36Sopenharmony_ci		}
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,rsense-share")) {
79662306a36Sopenharmony_ci		/* Current rotation is only available with rsense sharing */
79762306a36Sopenharmony_ci		if (fwnode_property_read_bool(child, "adi,current-rotate")) {
79862306a36Sopenharmony_ci			if (n_wires == 2 || n_wires == 3) {
79962306a36Sopenharmony_ci				dev_err(dev,
80062306a36Sopenharmony_ci					"Rotation not allowed for 2/3 Wire RTDs");
80162306a36Sopenharmony_ci				ret = -EINVAL;
80262306a36Sopenharmony_ci				goto fail;
80362306a36Sopenharmony_ci			}
80462306a36Sopenharmony_ci			rtd->sensor_config |= LTC2983_RTD_C_ROTATE(1);
80562306a36Sopenharmony_ci		} else {
80662306a36Sopenharmony_ci			rtd->sensor_config |= LTC2983_RTD_R_SHARE(1);
80762306a36Sopenharmony_ci		}
80862306a36Sopenharmony_ci	}
80962306a36Sopenharmony_ci	/*
81062306a36Sopenharmony_ci	 * rtd channel indexes are a bit more complicated to validate.
81162306a36Sopenharmony_ci	 * For 4wire RTD with rotation, the channel selection cannot be
81262306a36Sopenharmony_ci	 * >=19 since the chann + 1 is used in this configuration.
81362306a36Sopenharmony_ci	 * For 4wire RTDs with kelvin rsense, the rsense channel cannot be
81462306a36Sopenharmony_ci	 * <=1 since chanel - 1 and channel - 2 are used.
81562306a36Sopenharmony_ci	 */
81662306a36Sopenharmony_ci	if (rtd->sensor_config & LTC2983_RTD_4_WIRE_MASK) {
81762306a36Sopenharmony_ci		/* 4-wire */
81862306a36Sopenharmony_ci		u8 min = LTC2983_DIFFERENTIAL_CHAN_MIN,
81962306a36Sopenharmony_ci			max = st->info->max_channels_nr;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci		if (rtd->sensor_config & LTC2983_RTD_ROTATION_MASK)
82262306a36Sopenharmony_ci			max = st->info->max_channels_nr - 1;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci		if (((rtd->sensor_config & LTC2983_RTD_KELVIN_R_SENSE_MASK)
82562306a36Sopenharmony_ci		     == LTC2983_RTD_KELVIN_R_SENSE_MASK) &&
82662306a36Sopenharmony_ci		    (rtd->r_sense_chan <=  min)) {
82762306a36Sopenharmony_ci			/* kelvin rsense*/
82862306a36Sopenharmony_ci			dev_err(dev,
82962306a36Sopenharmony_ci				"Invalid rsense chann:%d to use in kelvin rsense",
83062306a36Sopenharmony_ci				rtd->r_sense_chan);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci			ret = -EINVAL;
83362306a36Sopenharmony_ci			goto fail;
83462306a36Sopenharmony_ci		}
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci		if (sensor->chan < min || sensor->chan > max) {
83762306a36Sopenharmony_ci			dev_err(dev, "Invalid chann:%d for the rtd config",
83862306a36Sopenharmony_ci				sensor->chan);
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci			ret = -EINVAL;
84162306a36Sopenharmony_ci			goto fail;
84262306a36Sopenharmony_ci		}
84362306a36Sopenharmony_ci	} else {
84462306a36Sopenharmony_ci		/* same as differential case */
84562306a36Sopenharmony_ci		if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
84662306a36Sopenharmony_ci			dev_err(&st->spi->dev,
84762306a36Sopenharmony_ci				"Invalid chann:%d for RTD", sensor->chan);
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci			ret = -EINVAL;
85062306a36Sopenharmony_ci			goto fail;
85162306a36Sopenharmony_ci		}
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	/* check custom sensor */
85562306a36Sopenharmony_ci	if (sensor->type == LTC2983_SENSOR_RTD_CUSTOM) {
85662306a36Sopenharmony_ci		rtd->custom = __ltc2983_custom_sensor_new(st, child,
85762306a36Sopenharmony_ci							  "adi,custom-rtd",
85862306a36Sopenharmony_ci							  false, 2048, false);
85962306a36Sopenharmony_ci		if (IS_ERR(rtd->custom)) {
86062306a36Sopenharmony_ci			ret = PTR_ERR(rtd->custom);
86162306a36Sopenharmony_ci			goto fail;
86262306a36Sopenharmony_ci		}
86362306a36Sopenharmony_ci	}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	/* set common parameters */
86662306a36Sopenharmony_ci	rtd->sensor.fault_handler = ltc2983_common_fault_handler;
86762306a36Sopenharmony_ci	rtd->sensor.assign_chan = ltc2983_rtd_assign_chan;
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp",
87062306a36Sopenharmony_ci				       &excitation_current);
87162306a36Sopenharmony_ci	if (ret) {
87262306a36Sopenharmony_ci		/* default to 5uA */
87362306a36Sopenharmony_ci		rtd->excitation_current = 1;
87462306a36Sopenharmony_ci	} else {
87562306a36Sopenharmony_ci		switch (excitation_current) {
87662306a36Sopenharmony_ci		case 5:
87762306a36Sopenharmony_ci			rtd->excitation_current = 0x01;
87862306a36Sopenharmony_ci			break;
87962306a36Sopenharmony_ci		case 10:
88062306a36Sopenharmony_ci			rtd->excitation_current = 0x02;
88162306a36Sopenharmony_ci			break;
88262306a36Sopenharmony_ci		case 25:
88362306a36Sopenharmony_ci			rtd->excitation_current = 0x03;
88462306a36Sopenharmony_ci			break;
88562306a36Sopenharmony_ci		case 50:
88662306a36Sopenharmony_ci			rtd->excitation_current = 0x04;
88762306a36Sopenharmony_ci			break;
88862306a36Sopenharmony_ci		case 100:
88962306a36Sopenharmony_ci			rtd->excitation_current = 0x05;
89062306a36Sopenharmony_ci			break;
89162306a36Sopenharmony_ci		case 250:
89262306a36Sopenharmony_ci			rtd->excitation_current = 0x06;
89362306a36Sopenharmony_ci			break;
89462306a36Sopenharmony_ci		case 500:
89562306a36Sopenharmony_ci			rtd->excitation_current = 0x07;
89662306a36Sopenharmony_ci			break;
89762306a36Sopenharmony_ci		case 1000:
89862306a36Sopenharmony_ci			rtd->excitation_current = 0x08;
89962306a36Sopenharmony_ci			break;
90062306a36Sopenharmony_ci		default:
90162306a36Sopenharmony_ci			dev_err(&st->spi->dev,
90262306a36Sopenharmony_ci				"Invalid value for excitation current(%u)",
90362306a36Sopenharmony_ci				excitation_current);
90462306a36Sopenharmony_ci			ret = -EINVAL;
90562306a36Sopenharmony_ci			goto fail;
90662306a36Sopenharmony_ci		}
90762306a36Sopenharmony_ci	}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,rtd-curve", &rtd->rtd_curve);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	fwnode_handle_put(ref);
91262306a36Sopenharmony_ci	return &rtd->sensor;
91362306a36Sopenharmony_cifail:
91462306a36Sopenharmony_ci	fwnode_handle_put(ref);
91562306a36Sopenharmony_ci	return ERR_PTR(ret);
91662306a36Sopenharmony_ci}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_cistatic struct ltc2983_sensor *
91962306a36Sopenharmony_ciltc2983_thermistor_new(const struct fwnode_handle *child, struct ltc2983_data *st,
92062306a36Sopenharmony_ci		       const struct ltc2983_sensor *sensor)
92162306a36Sopenharmony_ci{
92262306a36Sopenharmony_ci	struct ltc2983_thermistor *thermistor;
92362306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
92462306a36Sopenharmony_ci	struct fwnode_handle *ref;
92562306a36Sopenharmony_ci	u32 excitation_current = 0;
92662306a36Sopenharmony_ci	int ret = 0;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	thermistor = devm_kzalloc(dev, sizeof(*thermistor), GFP_KERNEL);
92962306a36Sopenharmony_ci	if (!thermistor)
93062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	ref = fwnode_find_reference(child, "adi,rsense-handle", 0);
93362306a36Sopenharmony_ci	if (IS_ERR(ref)) {
93462306a36Sopenharmony_ci		dev_err(dev, "Property adi,rsense-handle missing or invalid");
93562306a36Sopenharmony_ci		return ERR_CAST(ref);
93662306a36Sopenharmony_ci	}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	ret = fwnode_property_read_u32(ref, "reg", &thermistor->r_sense_chan);
93962306a36Sopenharmony_ci	if (ret) {
94062306a36Sopenharmony_ci		dev_err(dev, "rsense channel must be configured...\n");
94162306a36Sopenharmony_ci		goto fail;
94262306a36Sopenharmony_ci	}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,single-ended")) {
94562306a36Sopenharmony_ci		thermistor->sensor_config = LTC2983_THERMISTOR_SGL(1);
94662306a36Sopenharmony_ci	} else if (fwnode_property_read_bool(child, "adi,rsense-share")) {
94762306a36Sopenharmony_ci		/* rotation is only possible if sharing rsense */
94862306a36Sopenharmony_ci		if (fwnode_property_read_bool(child, "adi,current-rotate"))
94962306a36Sopenharmony_ci			thermistor->sensor_config =
95062306a36Sopenharmony_ci						LTC2983_THERMISTOR_C_ROTATE(1);
95162306a36Sopenharmony_ci		else
95262306a36Sopenharmony_ci			thermistor->sensor_config =
95362306a36Sopenharmony_ci						LTC2983_THERMISTOR_R_SHARE(1);
95462306a36Sopenharmony_ci	}
95562306a36Sopenharmony_ci	/* validate channel index */
95662306a36Sopenharmony_ci	if (!(thermistor->sensor_config & LTC2983_THERMISTOR_DIFF_MASK) &&
95762306a36Sopenharmony_ci	    sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
95862306a36Sopenharmony_ci		dev_err(&st->spi->dev,
95962306a36Sopenharmony_ci			"Invalid chann:%d for differential thermistor",
96062306a36Sopenharmony_ci			sensor->chan);
96162306a36Sopenharmony_ci		ret = -EINVAL;
96262306a36Sopenharmony_ci		goto fail;
96362306a36Sopenharmony_ci	}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	/* check custom sensor */
96662306a36Sopenharmony_ci	if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART) {
96762306a36Sopenharmony_ci		bool steinhart = false;
96862306a36Sopenharmony_ci		const char *propname;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci		if (sensor->type == LTC2983_SENSOR_THERMISTOR_STEINHART) {
97162306a36Sopenharmony_ci			steinhart = true;
97262306a36Sopenharmony_ci			propname = "adi,custom-steinhart";
97362306a36Sopenharmony_ci		} else {
97462306a36Sopenharmony_ci			propname = "adi,custom-thermistor";
97562306a36Sopenharmony_ci		}
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci		thermistor->custom = __ltc2983_custom_sensor_new(st, child,
97862306a36Sopenharmony_ci								 propname,
97962306a36Sopenharmony_ci								 steinhart,
98062306a36Sopenharmony_ci								 64, false);
98162306a36Sopenharmony_ci		if (IS_ERR(thermistor->custom)) {
98262306a36Sopenharmony_ci			ret = PTR_ERR(thermistor->custom);
98362306a36Sopenharmony_ci			goto fail;
98462306a36Sopenharmony_ci		}
98562306a36Sopenharmony_ci	}
98662306a36Sopenharmony_ci	/* set common parameters */
98762306a36Sopenharmony_ci	thermistor->sensor.fault_handler = ltc2983_common_fault_handler;
98862306a36Sopenharmony_ci	thermistor->sensor.assign_chan = ltc2983_thermistor_assign_chan;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	ret = fwnode_property_read_u32(child, "adi,excitation-current-nanoamp",
99162306a36Sopenharmony_ci				       &excitation_current);
99262306a36Sopenharmony_ci	if (ret) {
99362306a36Sopenharmony_ci		/* Auto range is not allowed for custom sensors */
99462306a36Sopenharmony_ci		if (sensor->type >= LTC2983_SENSOR_THERMISTOR_STEINHART)
99562306a36Sopenharmony_ci			/* default to 1uA */
99662306a36Sopenharmony_ci			thermistor->excitation_current = 0x03;
99762306a36Sopenharmony_ci		else
99862306a36Sopenharmony_ci			/* default to auto-range */
99962306a36Sopenharmony_ci			thermistor->excitation_current = 0x0c;
100062306a36Sopenharmony_ci	} else {
100162306a36Sopenharmony_ci		switch (excitation_current) {
100262306a36Sopenharmony_ci		case 0:
100362306a36Sopenharmony_ci			/* auto range */
100462306a36Sopenharmony_ci			if (sensor->type >=
100562306a36Sopenharmony_ci			    LTC2983_SENSOR_THERMISTOR_STEINHART) {
100662306a36Sopenharmony_ci				dev_err(&st->spi->dev,
100762306a36Sopenharmony_ci					"Auto Range not allowed for custom sensors\n");
100862306a36Sopenharmony_ci				ret = -EINVAL;
100962306a36Sopenharmony_ci				goto fail;
101062306a36Sopenharmony_ci			}
101162306a36Sopenharmony_ci			thermistor->excitation_current = 0x0c;
101262306a36Sopenharmony_ci			break;
101362306a36Sopenharmony_ci		case 250:
101462306a36Sopenharmony_ci			thermistor->excitation_current = 0x01;
101562306a36Sopenharmony_ci			break;
101662306a36Sopenharmony_ci		case 500:
101762306a36Sopenharmony_ci			thermistor->excitation_current = 0x02;
101862306a36Sopenharmony_ci			break;
101962306a36Sopenharmony_ci		case 1000:
102062306a36Sopenharmony_ci			thermistor->excitation_current = 0x03;
102162306a36Sopenharmony_ci			break;
102262306a36Sopenharmony_ci		case 5000:
102362306a36Sopenharmony_ci			thermistor->excitation_current = 0x04;
102462306a36Sopenharmony_ci			break;
102562306a36Sopenharmony_ci		case 10000:
102662306a36Sopenharmony_ci			thermistor->excitation_current = 0x05;
102762306a36Sopenharmony_ci			break;
102862306a36Sopenharmony_ci		case 25000:
102962306a36Sopenharmony_ci			thermistor->excitation_current = 0x06;
103062306a36Sopenharmony_ci			break;
103162306a36Sopenharmony_ci		case 50000:
103262306a36Sopenharmony_ci			thermistor->excitation_current = 0x07;
103362306a36Sopenharmony_ci			break;
103462306a36Sopenharmony_ci		case 100000:
103562306a36Sopenharmony_ci			thermistor->excitation_current = 0x08;
103662306a36Sopenharmony_ci			break;
103762306a36Sopenharmony_ci		case 250000:
103862306a36Sopenharmony_ci			thermistor->excitation_current = 0x09;
103962306a36Sopenharmony_ci			break;
104062306a36Sopenharmony_ci		case 500000:
104162306a36Sopenharmony_ci			thermistor->excitation_current = 0x0a;
104262306a36Sopenharmony_ci			break;
104362306a36Sopenharmony_ci		case 1000000:
104462306a36Sopenharmony_ci			thermistor->excitation_current = 0x0b;
104562306a36Sopenharmony_ci			break;
104662306a36Sopenharmony_ci		default:
104762306a36Sopenharmony_ci			dev_err(&st->spi->dev,
104862306a36Sopenharmony_ci				"Invalid value for excitation current(%u)",
104962306a36Sopenharmony_ci				excitation_current);
105062306a36Sopenharmony_ci			ret = -EINVAL;
105162306a36Sopenharmony_ci			goto fail;
105262306a36Sopenharmony_ci		}
105362306a36Sopenharmony_ci	}
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	fwnode_handle_put(ref);
105662306a36Sopenharmony_ci	return &thermistor->sensor;
105762306a36Sopenharmony_cifail:
105862306a36Sopenharmony_ci	fwnode_handle_put(ref);
105962306a36Sopenharmony_ci	return ERR_PTR(ret);
106062306a36Sopenharmony_ci}
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_cistatic struct ltc2983_sensor *
106362306a36Sopenharmony_ciltc2983_diode_new(const struct fwnode_handle *child, const struct ltc2983_data *st,
106462306a36Sopenharmony_ci		  const struct ltc2983_sensor *sensor)
106562306a36Sopenharmony_ci{
106662306a36Sopenharmony_ci	struct ltc2983_diode *diode;
106762306a36Sopenharmony_ci	u32 temp = 0, excitation_current = 0;
106862306a36Sopenharmony_ci	int ret;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	diode = devm_kzalloc(&st->spi->dev, sizeof(*diode), GFP_KERNEL);
107162306a36Sopenharmony_ci	if (!diode)
107262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,single-ended"))
107562306a36Sopenharmony_ci		diode->sensor_config = LTC2983_DIODE_SGL(1);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,three-conversion-cycles"))
107862306a36Sopenharmony_ci		diode->sensor_config |= LTC2983_DIODE_3_CONV_CYCLE(1);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,average-on"))
108162306a36Sopenharmony_ci		diode->sensor_config |= LTC2983_DIODE_AVERAGE_ON(1);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	/* validate channel index */
108462306a36Sopenharmony_ci	if (!(diode->sensor_config & LTC2983_DIODE_DIFF_MASK) &&
108562306a36Sopenharmony_ci	    sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
108662306a36Sopenharmony_ci		dev_err(&st->spi->dev,
108762306a36Sopenharmony_ci			"Invalid chann:%d for differential thermistor",
108862306a36Sopenharmony_ci			sensor->chan);
108962306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
109062306a36Sopenharmony_ci	}
109162306a36Sopenharmony_ci	/* set common parameters */
109262306a36Sopenharmony_ci	diode->sensor.fault_handler = ltc2983_common_fault_handler;
109362306a36Sopenharmony_ci	diode->sensor.assign_chan = ltc2983_diode_assign_chan;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	ret = fwnode_property_read_u32(child, "adi,excitation-current-microamp",
109662306a36Sopenharmony_ci				       &excitation_current);
109762306a36Sopenharmony_ci	if (!ret) {
109862306a36Sopenharmony_ci		switch (excitation_current) {
109962306a36Sopenharmony_ci		case 10:
110062306a36Sopenharmony_ci			diode->excitation_current = 0x00;
110162306a36Sopenharmony_ci			break;
110262306a36Sopenharmony_ci		case 20:
110362306a36Sopenharmony_ci			diode->excitation_current = 0x01;
110462306a36Sopenharmony_ci			break;
110562306a36Sopenharmony_ci		case 40:
110662306a36Sopenharmony_ci			diode->excitation_current = 0x02;
110762306a36Sopenharmony_ci			break;
110862306a36Sopenharmony_ci		case 80:
110962306a36Sopenharmony_ci			diode->excitation_current = 0x03;
111062306a36Sopenharmony_ci			break;
111162306a36Sopenharmony_ci		default:
111262306a36Sopenharmony_ci			dev_err(&st->spi->dev,
111362306a36Sopenharmony_ci				"Invalid value for excitation current(%u)",
111462306a36Sopenharmony_ci				excitation_current);
111562306a36Sopenharmony_ci			return ERR_PTR(-EINVAL);
111662306a36Sopenharmony_ci		}
111762306a36Sopenharmony_ci	}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,ideal-factor-value", &temp);
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	/* 2^20 resolution */
112262306a36Sopenharmony_ci	diode->ideal_factor_value = __convert_to_raw(temp, 1048576);
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	return &diode->sensor;
112562306a36Sopenharmony_ci}
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_cistatic struct ltc2983_sensor *ltc2983_r_sense_new(struct fwnode_handle *child,
112862306a36Sopenharmony_ci					struct ltc2983_data *st,
112962306a36Sopenharmony_ci					const struct ltc2983_sensor *sensor)
113062306a36Sopenharmony_ci{
113162306a36Sopenharmony_ci	struct ltc2983_rsense *rsense;
113262306a36Sopenharmony_ci	int ret;
113362306a36Sopenharmony_ci	u32 temp;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	rsense = devm_kzalloc(&st->spi->dev, sizeof(*rsense), GFP_KERNEL);
113662306a36Sopenharmony_ci	if (!rsense)
113762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	/* validate channel index */
114062306a36Sopenharmony_ci	if (sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
114162306a36Sopenharmony_ci		dev_err(&st->spi->dev, "Invalid chann:%d for r_sense",
114262306a36Sopenharmony_ci			sensor->chan);
114362306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
114462306a36Sopenharmony_ci	}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	ret = fwnode_property_read_u32(child, "adi,rsense-val-milli-ohms", &temp);
114762306a36Sopenharmony_ci	if (ret) {
114862306a36Sopenharmony_ci		dev_err(&st->spi->dev, "Property adi,rsense-val-milli-ohms missing\n");
114962306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
115062306a36Sopenharmony_ci	}
115162306a36Sopenharmony_ci	/*
115262306a36Sopenharmony_ci	 * Times 1000 because we have milli-ohms and __convert_to_raw
115362306a36Sopenharmony_ci	 * expects scales of 1000000 which are used for all other
115462306a36Sopenharmony_ci	 * properties.
115562306a36Sopenharmony_ci	 * 2^10 resolution
115662306a36Sopenharmony_ci	 */
115762306a36Sopenharmony_ci	rsense->r_sense_val = __convert_to_raw((u64)temp * 1000, 1024);
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	/* set common parameters */
116062306a36Sopenharmony_ci	rsense->sensor.assign_chan = ltc2983_r_sense_assign_chan;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	return &rsense->sensor;
116362306a36Sopenharmony_ci}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_cistatic struct ltc2983_sensor *ltc2983_adc_new(struct fwnode_handle *child,
116662306a36Sopenharmony_ci					 struct ltc2983_data *st,
116762306a36Sopenharmony_ci					 const struct ltc2983_sensor *sensor)
116862306a36Sopenharmony_ci{
116962306a36Sopenharmony_ci	struct ltc2983_adc *adc;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	adc = devm_kzalloc(&st->spi->dev, sizeof(*adc), GFP_KERNEL);
117262306a36Sopenharmony_ci	if (!adc)
117362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,single-ended"))
117662306a36Sopenharmony_ci		adc->single_ended = true;
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	if (!adc->single_ended &&
117962306a36Sopenharmony_ci	    sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
118062306a36Sopenharmony_ci		dev_err(&st->spi->dev, "Invalid chan:%d for differential adc\n",
118162306a36Sopenharmony_ci			sensor->chan);
118262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
118362306a36Sopenharmony_ci	}
118462306a36Sopenharmony_ci	/* set common parameters */
118562306a36Sopenharmony_ci	adc->sensor.assign_chan = ltc2983_adc_assign_chan;
118662306a36Sopenharmony_ci	adc->sensor.fault_handler = ltc2983_common_fault_handler;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	return &adc->sensor;
118962306a36Sopenharmony_ci}
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_cistatic struct ltc2983_sensor *ltc2983_temp_new(struct fwnode_handle *child,
119262306a36Sopenharmony_ci					       struct ltc2983_data *st,
119362306a36Sopenharmony_ci					       const struct ltc2983_sensor *sensor)
119462306a36Sopenharmony_ci{
119562306a36Sopenharmony_ci	struct ltc2983_temp *temp;
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	temp = devm_kzalloc(&st->spi->dev, sizeof(*temp), GFP_KERNEL);
119862306a36Sopenharmony_ci	if (!temp)
119962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	if (fwnode_property_read_bool(child, "adi,single-ended"))
120262306a36Sopenharmony_ci		temp->single_ended = true;
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (!temp->single_ended &&
120562306a36Sopenharmony_ci	    sensor->chan < LTC2983_DIFFERENTIAL_CHAN_MIN) {
120662306a36Sopenharmony_ci		dev_err(&st->spi->dev, "Invalid chan:%d for differential temp\n",
120762306a36Sopenharmony_ci			sensor->chan);
120862306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
120962306a36Sopenharmony_ci	}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	temp->custom = __ltc2983_custom_sensor_new(st, child, "adi,custom-temp",
121262306a36Sopenharmony_ci						   false, 4096, true);
121362306a36Sopenharmony_ci	if (IS_ERR(temp->custom))
121462306a36Sopenharmony_ci		return ERR_CAST(temp->custom);
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	/* set common parameters */
121762306a36Sopenharmony_ci	temp->sensor.assign_chan = ltc2983_temp_assign_chan;
121862306a36Sopenharmony_ci	temp->sensor.fault_handler = ltc2983_common_fault_handler;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	return &temp->sensor;
122162306a36Sopenharmony_ci}
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_cistatic int ltc2983_chan_read(struct ltc2983_data *st,
122462306a36Sopenharmony_ci			const struct ltc2983_sensor *sensor, int *val)
122562306a36Sopenharmony_ci{
122662306a36Sopenharmony_ci	u32 start_conversion = 0;
122762306a36Sopenharmony_ci	int ret;
122862306a36Sopenharmony_ci	unsigned long time;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	start_conversion = LTC2983_STATUS_START(true);
123162306a36Sopenharmony_ci	start_conversion |= LTC2983_STATUS_CHAN_SEL(sensor->chan);
123262306a36Sopenharmony_ci	dev_dbg(&st->spi->dev, "Start conversion on chan:%d, status:%02X\n",
123362306a36Sopenharmony_ci		sensor->chan, start_conversion);
123462306a36Sopenharmony_ci	/* start conversion */
123562306a36Sopenharmony_ci	ret = regmap_write(st->regmap, LTC2983_STATUS_REG, start_conversion);
123662306a36Sopenharmony_ci	if (ret)
123762306a36Sopenharmony_ci		return ret;
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	reinit_completion(&st->completion);
124062306a36Sopenharmony_ci	/*
124162306a36Sopenharmony_ci	 * wait for conversion to complete.
124262306a36Sopenharmony_ci	 * 300 ms should be more than enough to complete the conversion.
124362306a36Sopenharmony_ci	 * Depending on the sensor configuration, there are 2/3 conversions
124462306a36Sopenharmony_ci	 * cycles of 82ms.
124562306a36Sopenharmony_ci	 */
124662306a36Sopenharmony_ci	time = wait_for_completion_timeout(&st->completion,
124762306a36Sopenharmony_ci					   msecs_to_jiffies(300));
124862306a36Sopenharmony_ci	if (!time) {
124962306a36Sopenharmony_ci		dev_warn(&st->spi->dev, "Conversion timed out\n");
125062306a36Sopenharmony_ci		return -ETIMEDOUT;
125162306a36Sopenharmony_ci	}
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	/* read the converted data */
125462306a36Sopenharmony_ci	ret = regmap_bulk_read(st->regmap, LTC2983_CHAN_RES_ADDR(sensor->chan),
125562306a36Sopenharmony_ci			       &st->temp, sizeof(st->temp));
125662306a36Sopenharmony_ci	if (ret)
125762306a36Sopenharmony_ci		return ret;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	*val = __be32_to_cpu(st->temp);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	if (!(LTC2983_RES_VALID_MASK & *val)) {
126262306a36Sopenharmony_ci		dev_err(&st->spi->dev, "Invalid conversion detected\n");
126362306a36Sopenharmony_ci		return -EIO;
126462306a36Sopenharmony_ci	}
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	ret = sensor->fault_handler(st, *val);
126762306a36Sopenharmony_ci	if (ret)
126862306a36Sopenharmony_ci		return ret;
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	*val = sign_extend32((*val) & LTC2983_DATA_MASK, LTC2983_DATA_SIGN_BIT);
127162306a36Sopenharmony_ci	return 0;
127262306a36Sopenharmony_ci}
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_cistatic int ltc2983_read_raw(struct iio_dev *indio_dev,
127562306a36Sopenharmony_ci			    struct iio_chan_spec const *chan,
127662306a36Sopenharmony_ci			    int *val, int *val2, long mask)
127762306a36Sopenharmony_ci{
127862306a36Sopenharmony_ci	struct ltc2983_data *st = iio_priv(indio_dev);
127962306a36Sopenharmony_ci	int ret;
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	/* sanity check */
128262306a36Sopenharmony_ci	if (chan->address >= st->num_channels) {
128362306a36Sopenharmony_ci		dev_err(&st->spi->dev, "Invalid chan address:%ld",
128462306a36Sopenharmony_ci			chan->address);
128562306a36Sopenharmony_ci		return -EINVAL;
128662306a36Sopenharmony_ci	}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	switch (mask) {
128962306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
129062306a36Sopenharmony_ci		mutex_lock(&st->lock);
129162306a36Sopenharmony_ci		ret = ltc2983_chan_read(st, st->sensors[chan->address], val);
129262306a36Sopenharmony_ci		mutex_unlock(&st->lock);
129362306a36Sopenharmony_ci		return ret ?: IIO_VAL_INT;
129462306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
129562306a36Sopenharmony_ci		switch (chan->type) {
129662306a36Sopenharmony_ci		case IIO_TEMP:
129762306a36Sopenharmony_ci			/* value in milli degrees */
129862306a36Sopenharmony_ci			*val = 1000;
129962306a36Sopenharmony_ci			/* 2^10 */
130062306a36Sopenharmony_ci			*val2 = 1024;
130162306a36Sopenharmony_ci			return IIO_VAL_FRACTIONAL;
130262306a36Sopenharmony_ci		case IIO_VOLTAGE:
130362306a36Sopenharmony_ci			/* value in millivolt */
130462306a36Sopenharmony_ci			*val = 1000;
130562306a36Sopenharmony_ci			/* 2^21 */
130662306a36Sopenharmony_ci			*val2 = 2097152;
130762306a36Sopenharmony_ci			return IIO_VAL_FRACTIONAL;
130862306a36Sopenharmony_ci		default:
130962306a36Sopenharmony_ci			return -EINVAL;
131062306a36Sopenharmony_ci		}
131162306a36Sopenharmony_ci	}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci	return -EINVAL;
131462306a36Sopenharmony_ci}
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_cistatic int ltc2983_reg_access(struct iio_dev *indio_dev,
131762306a36Sopenharmony_ci			      unsigned int reg,
131862306a36Sopenharmony_ci			      unsigned int writeval,
131962306a36Sopenharmony_ci			      unsigned int *readval)
132062306a36Sopenharmony_ci{
132162306a36Sopenharmony_ci	struct ltc2983_data *st = iio_priv(indio_dev);
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	if (readval)
132462306a36Sopenharmony_ci		return regmap_read(st->regmap, reg, readval);
132562306a36Sopenharmony_ci	else
132662306a36Sopenharmony_ci		return regmap_write(st->regmap, reg, writeval);
132762306a36Sopenharmony_ci}
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_cistatic irqreturn_t ltc2983_irq_handler(int irq, void *data)
133062306a36Sopenharmony_ci{
133162306a36Sopenharmony_ci	struct ltc2983_data *st = data;
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	complete(&st->completion);
133462306a36Sopenharmony_ci	return IRQ_HANDLED;
133562306a36Sopenharmony_ci}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci#define LTC2983_CHAN(__type, index, __address) ({ \
133862306a36Sopenharmony_ci	struct iio_chan_spec __chan = { \
133962306a36Sopenharmony_ci		.type = __type, \
134062306a36Sopenharmony_ci		.indexed = 1, \
134162306a36Sopenharmony_ci		.channel = index, \
134262306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
134362306a36Sopenharmony_ci		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
134462306a36Sopenharmony_ci		.address = __address, \
134562306a36Sopenharmony_ci	}; \
134662306a36Sopenharmony_ci	__chan; \
134762306a36Sopenharmony_ci})
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_cistatic int ltc2983_parse_dt(struct ltc2983_data *st)
135062306a36Sopenharmony_ci{
135162306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
135262306a36Sopenharmony_ci	struct fwnode_handle *child;
135362306a36Sopenharmony_ci	int ret = 0, chan = 0, channel_avail_mask = 0;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	device_property_read_u32(dev, "adi,mux-delay-config-us", &st->mux_delay_config);
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	device_property_read_u32(dev, "adi,filter-notch-freq", &st->filter_notch_freq);
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	st->num_channels = device_get_child_node_count(dev);
136062306a36Sopenharmony_ci	if (!st->num_channels) {
136162306a36Sopenharmony_ci		dev_err(&st->spi->dev, "At least one channel must be given!");
136262306a36Sopenharmony_ci		return -EINVAL;
136362306a36Sopenharmony_ci	}
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	st->sensors = devm_kcalloc(dev, st->num_channels, sizeof(*st->sensors),
136662306a36Sopenharmony_ci				   GFP_KERNEL);
136762306a36Sopenharmony_ci	if (!st->sensors)
136862306a36Sopenharmony_ci		return -ENOMEM;
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	st->iio_channels = st->num_channels;
137162306a36Sopenharmony_ci	device_for_each_child_node(dev, child) {
137262306a36Sopenharmony_ci		struct ltc2983_sensor sensor;
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci		ret = fwnode_property_read_u32(child, "reg", &sensor.chan);
137562306a36Sopenharmony_ci		if (ret) {
137662306a36Sopenharmony_ci			dev_err(dev, "reg property must given for child nodes\n");
137762306a36Sopenharmony_ci			goto put_child;
137862306a36Sopenharmony_ci		}
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci		/* check if we have a valid channel */
138162306a36Sopenharmony_ci		if (sensor.chan < LTC2983_MIN_CHANNELS_NR ||
138262306a36Sopenharmony_ci		    sensor.chan > st->info->max_channels_nr) {
138362306a36Sopenharmony_ci			ret = -EINVAL;
138462306a36Sopenharmony_ci			dev_err(dev, "chan:%d must be from %u to %u\n", sensor.chan,
138562306a36Sopenharmony_ci				LTC2983_MIN_CHANNELS_NR, st->info->max_channels_nr);
138662306a36Sopenharmony_ci			goto put_child;
138762306a36Sopenharmony_ci		} else if (channel_avail_mask & BIT(sensor.chan)) {
138862306a36Sopenharmony_ci			ret = -EINVAL;
138962306a36Sopenharmony_ci			dev_err(dev, "chan:%d already in use\n", sensor.chan);
139062306a36Sopenharmony_ci			goto put_child;
139162306a36Sopenharmony_ci		}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci		ret = fwnode_property_read_u32(child, "adi,sensor-type", &sensor.type);
139462306a36Sopenharmony_ci		if (ret) {
139562306a36Sopenharmony_ci			dev_err(dev,
139662306a36Sopenharmony_ci				"adi,sensor-type property must given for child nodes\n");
139762306a36Sopenharmony_ci			goto put_child;
139862306a36Sopenharmony_ci		}
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci		dev_dbg(dev, "Create new sensor, type %u, chann %u",
140162306a36Sopenharmony_ci								sensor.type,
140262306a36Sopenharmony_ci								sensor.chan);
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci		if (sensor.type >= LTC2983_SENSOR_THERMOCOUPLE &&
140562306a36Sopenharmony_ci		    sensor.type <= LTC2983_SENSOR_THERMOCOUPLE_CUSTOM) {
140662306a36Sopenharmony_ci			st->sensors[chan] = ltc2983_thermocouple_new(child, st,
140762306a36Sopenharmony_ci								     &sensor);
140862306a36Sopenharmony_ci		} else if (sensor.type >= LTC2983_SENSOR_RTD &&
140962306a36Sopenharmony_ci			   sensor.type <= LTC2983_SENSOR_RTD_CUSTOM) {
141062306a36Sopenharmony_ci			st->sensors[chan] = ltc2983_rtd_new(child, st, &sensor);
141162306a36Sopenharmony_ci		} else if (sensor.type >= LTC2983_SENSOR_THERMISTOR &&
141262306a36Sopenharmony_ci			   sensor.type <= LTC2983_SENSOR_THERMISTOR_CUSTOM) {
141362306a36Sopenharmony_ci			st->sensors[chan] = ltc2983_thermistor_new(child, st,
141462306a36Sopenharmony_ci								   &sensor);
141562306a36Sopenharmony_ci		} else if (sensor.type == LTC2983_SENSOR_DIODE) {
141662306a36Sopenharmony_ci			st->sensors[chan] = ltc2983_diode_new(child, st,
141762306a36Sopenharmony_ci							      &sensor);
141862306a36Sopenharmony_ci		} else if (sensor.type == LTC2983_SENSOR_SENSE_RESISTOR) {
141962306a36Sopenharmony_ci			st->sensors[chan] = ltc2983_r_sense_new(child, st,
142062306a36Sopenharmony_ci								&sensor);
142162306a36Sopenharmony_ci			/* don't add rsense to iio */
142262306a36Sopenharmony_ci			st->iio_channels--;
142362306a36Sopenharmony_ci		} else if (sensor.type == LTC2983_SENSOR_DIRECT_ADC) {
142462306a36Sopenharmony_ci			st->sensors[chan] = ltc2983_adc_new(child, st, &sensor);
142562306a36Sopenharmony_ci		} else if (st->info->has_temp &&
142662306a36Sopenharmony_ci			   sensor.type == LTC2983_SENSOR_ACTIVE_TEMP) {
142762306a36Sopenharmony_ci			st->sensors[chan] = ltc2983_temp_new(child, st, &sensor);
142862306a36Sopenharmony_ci		} else {
142962306a36Sopenharmony_ci			dev_err(dev, "Unknown sensor type %d\n", sensor.type);
143062306a36Sopenharmony_ci			ret = -EINVAL;
143162306a36Sopenharmony_ci			goto put_child;
143262306a36Sopenharmony_ci		}
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_ci		if (IS_ERR(st->sensors[chan])) {
143562306a36Sopenharmony_ci			dev_err(dev, "Failed to create sensor %ld",
143662306a36Sopenharmony_ci				PTR_ERR(st->sensors[chan]));
143762306a36Sopenharmony_ci			ret = PTR_ERR(st->sensors[chan]);
143862306a36Sopenharmony_ci			goto put_child;
143962306a36Sopenharmony_ci		}
144062306a36Sopenharmony_ci		/* set generic sensor parameters */
144162306a36Sopenharmony_ci		st->sensors[chan]->chan = sensor.chan;
144262306a36Sopenharmony_ci		st->sensors[chan]->type = sensor.type;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci		channel_avail_mask |= BIT(sensor.chan);
144562306a36Sopenharmony_ci		chan++;
144662306a36Sopenharmony_ci	}
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	return 0;
144962306a36Sopenharmony_ciput_child:
145062306a36Sopenharmony_ci	fwnode_handle_put(child);
145162306a36Sopenharmony_ci	return ret;
145262306a36Sopenharmony_ci}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_cistatic int ltc2983_eeprom_cmd(struct ltc2983_data *st, unsigned int cmd,
145562306a36Sopenharmony_ci			      unsigned int wait_time, unsigned int status_reg,
145662306a36Sopenharmony_ci			      unsigned long status_fail_mask)
145762306a36Sopenharmony_ci{
145862306a36Sopenharmony_ci	unsigned long time;
145962306a36Sopenharmony_ci	unsigned int val;
146062306a36Sopenharmony_ci	int ret;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	ret = regmap_bulk_write(st->regmap, LTC2983_EEPROM_KEY_REG,
146362306a36Sopenharmony_ci				&st->eeprom_key, sizeof(st->eeprom_key));
146462306a36Sopenharmony_ci	if (ret)
146562306a36Sopenharmony_ci		return ret;
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	reinit_completion(&st->completion);
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	ret = regmap_write(st->regmap, LTC2983_STATUS_REG,
147062306a36Sopenharmony_ci			   LTC2983_STATUS_START(true) | cmd);
147162306a36Sopenharmony_ci	if (ret)
147262306a36Sopenharmony_ci		return ret;
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	time = wait_for_completion_timeout(&st->completion,
147562306a36Sopenharmony_ci					   msecs_to_jiffies(wait_time));
147662306a36Sopenharmony_ci	if (!time) {
147762306a36Sopenharmony_ci		dev_err(&st->spi->dev, "EEPROM command timed out\n");
147862306a36Sopenharmony_ci		return -ETIMEDOUT;
147962306a36Sopenharmony_ci	}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	ret = regmap_read(st->regmap, status_reg, &val);
148262306a36Sopenharmony_ci	if (ret)
148362306a36Sopenharmony_ci		return ret;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	if (val & status_fail_mask) {
148662306a36Sopenharmony_ci		dev_err(&st->spi->dev, "EEPROM command failed: 0x%02X\n", val);
148762306a36Sopenharmony_ci		return -EINVAL;
148862306a36Sopenharmony_ci	}
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	return 0;
149162306a36Sopenharmony_ci}
149262306a36Sopenharmony_ci
149362306a36Sopenharmony_cistatic int ltc2983_setup(struct ltc2983_data *st, bool assign_iio)
149462306a36Sopenharmony_ci{
149562306a36Sopenharmony_ci	u32 iio_chan_t = 0, iio_chan_v = 0, chan, iio_idx = 0, status;
149662306a36Sopenharmony_ci	int ret;
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	/* make sure the device is up: start bit (7) is 0 and done bit (6) is 1 */
149962306a36Sopenharmony_ci	ret = regmap_read_poll_timeout(st->regmap, LTC2983_STATUS_REG, status,
150062306a36Sopenharmony_ci				       LTC2983_STATUS_UP(status) == 1, 25000,
150162306a36Sopenharmony_ci				       25000 * 10);
150262306a36Sopenharmony_ci	if (ret) {
150362306a36Sopenharmony_ci		dev_err(&st->spi->dev, "Device startup timed out\n");
150462306a36Sopenharmony_ci		return ret;
150562306a36Sopenharmony_ci	}
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG,
150862306a36Sopenharmony_ci				 LTC2983_NOTCH_FREQ_MASK,
150962306a36Sopenharmony_ci				 LTC2983_NOTCH_FREQ(st->filter_notch_freq));
151062306a36Sopenharmony_ci	if (ret)
151162306a36Sopenharmony_ci		return ret;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	ret = regmap_write(st->regmap, LTC2983_MUX_CONFIG_REG,
151462306a36Sopenharmony_ci			   st->mux_delay_config);
151562306a36Sopenharmony_ci	if (ret)
151662306a36Sopenharmony_ci		return ret;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci	if (st->info->has_eeprom && !assign_iio) {
151962306a36Sopenharmony_ci		ret = ltc2983_eeprom_cmd(st, LTC2983_EEPROM_READ_CMD,
152062306a36Sopenharmony_ci					 LTC2983_EEPROM_READ_TIME_MS,
152162306a36Sopenharmony_ci					 LTC2983_EEPROM_READ_STATUS_REG,
152262306a36Sopenharmony_ci					 LTC2983_EEPROM_READ_FAILURE_MASK);
152362306a36Sopenharmony_ci		if (!ret)
152462306a36Sopenharmony_ci			return 0;
152562306a36Sopenharmony_ci	}
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	for (chan = 0; chan < st->num_channels; chan++) {
152862306a36Sopenharmony_ci		u32 chan_type = 0, *iio_chan;
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci		ret = st->sensors[chan]->assign_chan(st, st->sensors[chan]);
153162306a36Sopenharmony_ci		if (ret)
153262306a36Sopenharmony_ci			return ret;
153362306a36Sopenharmony_ci		/*
153462306a36Sopenharmony_ci		 * The assign_iio flag is necessary for when the device is
153562306a36Sopenharmony_ci		 * coming out of sleep. In that case, we just need to
153662306a36Sopenharmony_ci		 * re-configure the device channels.
153762306a36Sopenharmony_ci		 * We also don't assign iio channels for rsense.
153862306a36Sopenharmony_ci		 */
153962306a36Sopenharmony_ci		if (st->sensors[chan]->type == LTC2983_SENSOR_SENSE_RESISTOR ||
154062306a36Sopenharmony_ci		    !assign_iio)
154162306a36Sopenharmony_ci			continue;
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci		/* assign iio channel */
154462306a36Sopenharmony_ci		if (st->sensors[chan]->type != LTC2983_SENSOR_DIRECT_ADC) {
154562306a36Sopenharmony_ci			chan_type = IIO_TEMP;
154662306a36Sopenharmony_ci			iio_chan = &iio_chan_t;
154762306a36Sopenharmony_ci		} else {
154862306a36Sopenharmony_ci			chan_type = IIO_VOLTAGE;
154962306a36Sopenharmony_ci			iio_chan = &iio_chan_v;
155062306a36Sopenharmony_ci		}
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci		/*
155362306a36Sopenharmony_ci		 * add chan as the iio .address so that, we can directly
155462306a36Sopenharmony_ci		 * reference the sensor given the iio_chan_spec
155562306a36Sopenharmony_ci		 */
155662306a36Sopenharmony_ci		st->iio_chan[iio_idx++] = LTC2983_CHAN(chan_type, (*iio_chan)++,
155762306a36Sopenharmony_ci						       chan);
155862306a36Sopenharmony_ci	}
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	return 0;
156162306a36Sopenharmony_ci}
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_cistatic const struct regmap_range ltc2983_reg_ranges[] = {
156462306a36Sopenharmony_ci	regmap_reg_range(LTC2983_STATUS_REG, LTC2983_STATUS_REG),
156562306a36Sopenharmony_ci	regmap_reg_range(LTC2983_TEMP_RES_START_REG, LTC2983_TEMP_RES_END_REG),
156662306a36Sopenharmony_ci	regmap_reg_range(LTC2983_EEPROM_KEY_REG, LTC2983_EEPROM_KEY_REG),
156762306a36Sopenharmony_ci	regmap_reg_range(LTC2983_EEPROM_READ_STATUS_REG,
156862306a36Sopenharmony_ci			 LTC2983_EEPROM_READ_STATUS_REG),
156962306a36Sopenharmony_ci	regmap_reg_range(LTC2983_GLOBAL_CONFIG_REG, LTC2983_GLOBAL_CONFIG_REG),
157062306a36Sopenharmony_ci	regmap_reg_range(LTC2983_MULT_CHANNEL_START_REG,
157162306a36Sopenharmony_ci			 LTC2983_MULT_CHANNEL_END_REG),
157262306a36Sopenharmony_ci	regmap_reg_range(LTC2986_EEPROM_STATUS_REG, LTC2986_EEPROM_STATUS_REG),
157362306a36Sopenharmony_ci	regmap_reg_range(LTC2983_MUX_CONFIG_REG, LTC2983_MUX_CONFIG_REG),
157462306a36Sopenharmony_ci	regmap_reg_range(LTC2983_CHAN_ASSIGN_START_REG,
157562306a36Sopenharmony_ci			 LTC2983_CHAN_ASSIGN_END_REG),
157662306a36Sopenharmony_ci	regmap_reg_range(LTC2983_CUST_SENS_TBL_START_REG,
157762306a36Sopenharmony_ci			 LTC2983_CUST_SENS_TBL_END_REG),
157862306a36Sopenharmony_ci};
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_cistatic const struct regmap_access_table ltc2983_reg_table = {
158162306a36Sopenharmony_ci	.yes_ranges = ltc2983_reg_ranges,
158262306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(ltc2983_reg_ranges),
158362306a36Sopenharmony_ci};
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ci/*
158662306a36Sopenharmony_ci *  The reg_bits are actually 12 but the device needs the first *complete*
158762306a36Sopenharmony_ci *  byte for the command (R/W).
158862306a36Sopenharmony_ci */
158962306a36Sopenharmony_cistatic const struct regmap_config ltc2983_regmap_config = {
159062306a36Sopenharmony_ci	.reg_bits = 24,
159162306a36Sopenharmony_ci	.val_bits = 8,
159262306a36Sopenharmony_ci	.wr_table = &ltc2983_reg_table,
159362306a36Sopenharmony_ci	.rd_table = &ltc2983_reg_table,
159462306a36Sopenharmony_ci	.read_flag_mask = GENMASK(1, 0),
159562306a36Sopenharmony_ci	.write_flag_mask = BIT(1),
159662306a36Sopenharmony_ci};
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_cistatic const struct  iio_info ltc2983_iio_info = {
159962306a36Sopenharmony_ci	.read_raw = ltc2983_read_raw,
160062306a36Sopenharmony_ci	.debugfs_reg_access = ltc2983_reg_access,
160162306a36Sopenharmony_ci};
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_cistatic int ltc2983_probe(struct spi_device *spi)
160462306a36Sopenharmony_ci{
160562306a36Sopenharmony_ci	struct ltc2983_data *st;
160662306a36Sopenharmony_ci	struct iio_dev *indio_dev;
160762306a36Sopenharmony_ci	struct gpio_desc *gpio;
160862306a36Sopenharmony_ci	const char *name = spi_get_device_id(spi)->name;
160962306a36Sopenharmony_ci	int ret;
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
161262306a36Sopenharmony_ci	if (!indio_dev)
161362306a36Sopenharmony_ci		return -ENOMEM;
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	st = iio_priv(indio_dev);
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	st->info = device_get_match_data(&spi->dev);
161862306a36Sopenharmony_ci	if (!st->info)
161962306a36Sopenharmony_ci		st->info = (void *)spi_get_device_id(spi)->driver_data;
162062306a36Sopenharmony_ci	if (!st->info)
162162306a36Sopenharmony_ci		return -ENODEV;
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	st->regmap = devm_regmap_init_spi(spi, &ltc2983_regmap_config);
162462306a36Sopenharmony_ci	if (IS_ERR(st->regmap)) {
162562306a36Sopenharmony_ci		dev_err(&spi->dev, "Failed to initialize regmap\n");
162662306a36Sopenharmony_ci		return PTR_ERR(st->regmap);
162762306a36Sopenharmony_ci	}
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	mutex_init(&st->lock);
163062306a36Sopenharmony_ci	init_completion(&st->completion);
163162306a36Sopenharmony_ci	st->spi = spi;
163262306a36Sopenharmony_ci	st->eeprom_key = cpu_to_be32(LTC2983_EEPROM_KEY);
163362306a36Sopenharmony_ci	spi_set_drvdata(spi, st);
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	ret = ltc2983_parse_dt(st);
163662306a36Sopenharmony_ci	if (ret)
163762306a36Sopenharmony_ci		return ret;
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci	gpio = devm_gpiod_get_optional(&st->spi->dev, "reset", GPIOD_OUT_HIGH);
164062306a36Sopenharmony_ci	if (IS_ERR(gpio))
164162306a36Sopenharmony_ci		return PTR_ERR(gpio);
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	if (gpio) {
164462306a36Sopenharmony_ci		/* bring the device out of reset */
164562306a36Sopenharmony_ci		usleep_range(1000, 1200);
164662306a36Sopenharmony_ci		gpiod_set_value_cansleep(gpio, 0);
164762306a36Sopenharmony_ci	}
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	st->iio_chan = devm_kzalloc(&spi->dev,
165062306a36Sopenharmony_ci				    st->iio_channels * sizeof(*st->iio_chan),
165162306a36Sopenharmony_ci				    GFP_KERNEL);
165262306a36Sopenharmony_ci	if (!st->iio_chan)
165362306a36Sopenharmony_ci		return -ENOMEM;
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	ret = ltc2983_setup(st, true);
165662306a36Sopenharmony_ci	if (ret)
165762306a36Sopenharmony_ci		return ret;
165862306a36Sopenharmony_ci
165962306a36Sopenharmony_ci	ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler,
166062306a36Sopenharmony_ci			       IRQF_TRIGGER_RISING, name, st);
166162306a36Sopenharmony_ci	if (ret) {
166262306a36Sopenharmony_ci		dev_err(&spi->dev, "failed to request an irq, %d", ret);
166362306a36Sopenharmony_ci		return ret;
166462306a36Sopenharmony_ci	}
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ci	if (st->info->has_eeprom) {
166762306a36Sopenharmony_ci		ret = ltc2983_eeprom_cmd(st, LTC2983_EEPROM_WRITE_CMD,
166862306a36Sopenharmony_ci					 LTC2983_EEPROM_WRITE_TIME_MS,
166962306a36Sopenharmony_ci					 LTC2986_EEPROM_STATUS_REG,
167062306a36Sopenharmony_ci					 LTC2983_EEPROM_STATUS_FAILURE_MASK);
167162306a36Sopenharmony_ci		if (ret)
167262306a36Sopenharmony_ci			return ret;
167362306a36Sopenharmony_ci	}
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	indio_dev->name = name;
167662306a36Sopenharmony_ci	indio_dev->num_channels = st->iio_channels;
167762306a36Sopenharmony_ci	indio_dev->channels = st->iio_chan;
167862306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
167962306a36Sopenharmony_ci	indio_dev->info = &ltc2983_iio_info;
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci	return devm_iio_device_register(&spi->dev, indio_dev);
168262306a36Sopenharmony_ci}
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_cistatic int ltc2983_resume(struct device *dev)
168562306a36Sopenharmony_ci{
168662306a36Sopenharmony_ci	struct ltc2983_data *st = spi_get_drvdata(to_spi_device(dev));
168762306a36Sopenharmony_ci	int dummy;
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	/* dummy read to bring the device out of sleep */
169062306a36Sopenharmony_ci	regmap_read(st->regmap, LTC2983_STATUS_REG, &dummy);
169162306a36Sopenharmony_ci	/* we need to re-assign the channels */
169262306a36Sopenharmony_ci	return ltc2983_setup(st, false);
169362306a36Sopenharmony_ci}
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_cistatic int ltc2983_suspend(struct device *dev)
169662306a36Sopenharmony_ci{
169762306a36Sopenharmony_ci	struct ltc2983_data *st = spi_get_drvdata(to_spi_device(dev));
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	return regmap_write(st->regmap, LTC2983_STATUS_REG, LTC2983_SLEEP);
170062306a36Sopenharmony_ci}
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(ltc2983_pm_ops, ltc2983_suspend,
170362306a36Sopenharmony_ci				ltc2983_resume);
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_cistatic const struct ltc2983_chip_info ltc2983_chip_info_data = {
170662306a36Sopenharmony_ci	.max_channels_nr = 20,
170762306a36Sopenharmony_ci};
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_cistatic const struct ltc2983_chip_info ltc2984_chip_info_data = {
171062306a36Sopenharmony_ci	.max_channels_nr = 20,
171162306a36Sopenharmony_ci	.has_eeprom = true,
171262306a36Sopenharmony_ci};
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_cistatic const struct ltc2983_chip_info ltc2986_chip_info_data = {
171562306a36Sopenharmony_ci	.max_channels_nr = 10,
171662306a36Sopenharmony_ci	.has_temp = true,
171762306a36Sopenharmony_ci	.has_eeprom = true,
171862306a36Sopenharmony_ci};
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_cistatic const struct spi_device_id ltc2983_id_table[] = {
172162306a36Sopenharmony_ci	{ "ltc2983", (kernel_ulong_t)&ltc2983_chip_info_data },
172262306a36Sopenharmony_ci	{ "ltc2984", (kernel_ulong_t)&ltc2984_chip_info_data },
172362306a36Sopenharmony_ci	{ "ltc2986", (kernel_ulong_t)&ltc2986_chip_info_data },
172462306a36Sopenharmony_ci	{ "ltm2985", (kernel_ulong_t)&ltc2986_chip_info_data },
172562306a36Sopenharmony_ci	{},
172662306a36Sopenharmony_ci};
172762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ltc2983_id_table);
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_cistatic const struct of_device_id ltc2983_of_match[] = {
173062306a36Sopenharmony_ci	{ .compatible = "adi,ltc2983", .data = &ltc2983_chip_info_data },
173162306a36Sopenharmony_ci	{ .compatible = "adi,ltc2984", .data = &ltc2984_chip_info_data },
173262306a36Sopenharmony_ci	{ .compatible = "adi,ltc2986", .data = &ltc2986_chip_info_data },
173362306a36Sopenharmony_ci	{ .compatible = "adi,ltm2985", .data = &ltc2986_chip_info_data },
173462306a36Sopenharmony_ci	{},
173562306a36Sopenharmony_ci};
173662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ltc2983_of_match);
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_cistatic struct spi_driver ltc2983_driver = {
173962306a36Sopenharmony_ci	.driver = {
174062306a36Sopenharmony_ci		.name = "ltc2983",
174162306a36Sopenharmony_ci		.of_match_table = ltc2983_of_match,
174262306a36Sopenharmony_ci		.pm = pm_sleep_ptr(&ltc2983_pm_ops),
174362306a36Sopenharmony_ci	},
174462306a36Sopenharmony_ci	.probe = ltc2983_probe,
174562306a36Sopenharmony_ci	.id_table = ltc2983_id_table,
174662306a36Sopenharmony_ci};
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_cimodule_spi_driver(ltc2983_driver);
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ciMODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
175162306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices LTC2983 SPI Temperature sensors");
175262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1753