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 = <c2983_reg_table, 159362306a36Sopenharmony_ci .rd_table = <c2983_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, <c2983_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 = <c2983_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)<c2983_chip_info_data }, 172262306a36Sopenharmony_ci { "ltc2984", (kernel_ulong_t)<c2984_chip_info_data }, 172362306a36Sopenharmony_ci { "ltc2986", (kernel_ulong_t)<c2986_chip_info_data }, 172462306a36Sopenharmony_ci { "ltm2985", (kernel_ulong_t)<c2986_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 = <c2983_chip_info_data }, 173162306a36Sopenharmony_ci { .compatible = "adi,ltc2984", .data = <c2984_chip_info_data }, 173262306a36Sopenharmony_ci { .compatible = "adi,ltc2986", .data = <c2986_chip_info_data }, 173362306a36Sopenharmony_ci { .compatible = "adi,ltm2985", .data = <c2986_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(<c2983_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