162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2022 Analog Devices, Inc. 462306a36Sopenharmony_ci * Author: Cosmin Tanislav <cosmin.tanislav@analog.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/bitfield.h> 862306a36Sopenharmony_ci#include <linux/bitops.h> 962306a36Sopenharmony_ci#include <linux/crc8.h> 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1262306a36Sopenharmony_ci#include <linux/interrupt.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/regmap.h> 1562306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1662306a36Sopenharmony_ci#include <linux/spi/spi.h> 1762306a36Sopenharmony_ci#include <linux/units.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <asm/unaligned.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/iio/buffer.h> 2262306a36Sopenharmony_ci#include <linux/iio/iio.h> 2362306a36Sopenharmony_ci#include <linux/iio/trigger.h> 2462306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 2562306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define AD74115_NAME "ad74115" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define AD74115_CH_FUNC_SETUP_REG 0x01 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_REG 0x02 3262306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV2_RATE_MASK GENMASK(15, 13) 3362306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV1_RATE_MASK GENMASK(12, 10) 3462306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV2_RANGE_MASK GENMASK(9, 7) 3562306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV1_RANGE_MASK GENMASK(6, 4) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define AD74115_PWR_OPTIM_CONFIG_REG 0x03 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define AD74115_DIN_CONFIG1_REG 0x04 4062306a36Sopenharmony_ci#define AD74115_DIN_COMPARATOR_EN_MASK BIT(13) 4162306a36Sopenharmony_ci#define AD74115_DIN_SINK_MASK GENMASK(11, 7) 4262306a36Sopenharmony_ci#define AD74115_DIN_DEBOUNCE_MASK GENMASK(4, 0) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define AD74115_DIN_CONFIG2_REG 0x05 4562306a36Sopenharmony_ci#define AD74115_COMP_THRESH_MASK GENMASK(6, 0) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define AD74115_OUTPUT_CONFIG_REG 0x06 4862306a36Sopenharmony_ci#define AD74115_OUTPUT_SLEW_EN_MASK GENMASK(6, 5) 4962306a36Sopenharmony_ci#define AD74115_OUTPUT_SLEW_LIN_STEP_MASK GENMASK(4, 3) 5062306a36Sopenharmony_ci#define AD74115_OUTPUT_SLEW_LIN_RATE_MASK GENMASK(2, 1) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define AD74115_RTD3W4W_CONFIG_REG 0x07 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define AD74115_BURNOUT_CONFIG_REG 0x0a 5562306a36Sopenharmony_ci#define AD74115_BURNOUT_EXT2_EN_MASK BIT(10) 5662306a36Sopenharmony_ci#define AD74115_BURNOUT_EXT1_EN_MASK BIT(5) 5762306a36Sopenharmony_ci#define AD74115_BURNOUT_VIOUT_EN_MASK BIT(0) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define AD74115_DAC_CODE_REG 0x0b 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define AD74115_DAC_ACTIVE_REG 0x0d 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_X_REG(x) (0x35 + (x)) 6462306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_GPI_DATA BIT(5) 6562306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_GPO_DATA BIT(4) 6662306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_SELECT_MASK GENMASK(2, 0) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#define AD74115_CHARGE_PUMP_REG 0x3a 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define AD74115_ADC_CONV_CTRL_REG 0x3b 7162306a36Sopenharmony_ci#define AD74115_ADC_CONV_SEQ_MASK GENMASK(13, 12) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define AD74115_DIN_COMP_OUT_REG 0x40 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define AD74115_LIVE_STATUS_REG 0x42 7662306a36Sopenharmony_ci#define AD74115_ADC_DATA_RDY_MASK BIT(3) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define AD74115_READ_SELECT_REG 0x64 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define AD74115_CMD_KEY_REG 0x78 8162306a36Sopenharmony_ci#define AD74115_CMD_KEY_RESET1 0x15fa 8262306a36Sopenharmony_ci#define AD74115_CMD_KEY_RESET2 0xaf51 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#define AD74115_CRC_POLYNOMIAL 0x7 8562306a36Sopenharmony_ciDECLARE_CRC8_TABLE(ad74115_crc8_table); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define AD74115_ADC_CODE_MAX ((int)GENMASK(15, 0)) 8862306a36Sopenharmony_ci#define AD74115_ADC_CODE_HALF (AD74115_ADC_CODE_MAX / 2) 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci#define AD74115_DAC_VOLTAGE_MAX 12000 9162306a36Sopenharmony_ci#define AD74115_DAC_CURRENT_MAX 25 9262306a36Sopenharmony_ci#define AD74115_DAC_CODE_MAX ((int)GENMASK(13, 0)) 9362306a36Sopenharmony_ci#define AD74115_DAC_CODE_HALF (AD74115_DAC_CODE_MAX / 2) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#define AD74115_COMP_THRESH_MAX 98 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define AD74115_SENSE_RESISTOR_OHMS 100 9862306a36Sopenharmony_ci#define AD74115_REF_RESISTOR_OHMS 2100 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define AD74115_DIN_SINK_LOW_STEP 120 10162306a36Sopenharmony_ci#define AD74115_DIN_SINK_HIGH_STEP 240 10262306a36Sopenharmony_ci#define AD74115_DIN_SINK_MAX 31 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define AD74115_FRAME_SIZE 4 10562306a36Sopenharmony_ci#define AD74115_GPIO_NUM 4 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#define AD74115_CONV_TIME_US 1000000 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cienum ad74115_dac_ch { 11062306a36Sopenharmony_ci AD74115_DAC_CH_MAIN, 11162306a36Sopenharmony_ci AD74115_DAC_CH_COMPARATOR, 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cienum ad74115_adc_ch { 11562306a36Sopenharmony_ci AD74115_ADC_CH_CONV1, 11662306a36Sopenharmony_ci AD74115_ADC_CH_CONV2, 11762306a36Sopenharmony_ci AD74115_ADC_CH_NUM 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cienum ad74115_ch_func { 12162306a36Sopenharmony_ci AD74115_CH_FUNC_HIGH_IMPEDANCE, 12262306a36Sopenharmony_ci AD74115_CH_FUNC_VOLTAGE_OUTPUT, 12362306a36Sopenharmony_ci AD74115_CH_FUNC_CURRENT_OUTPUT, 12462306a36Sopenharmony_ci AD74115_CH_FUNC_VOLTAGE_INPUT, 12562306a36Sopenharmony_ci AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER, 12662306a36Sopenharmony_ci AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER, 12762306a36Sopenharmony_ci AD74115_CH_FUNC_2_WIRE_RESISTANCE_INPUT, 12862306a36Sopenharmony_ci AD74115_CH_FUNC_3_4_WIRE_RESISTANCE_INPUT, 12962306a36Sopenharmony_ci AD74115_CH_FUNC_DIGITAL_INPUT_LOGIC, 13062306a36Sopenharmony_ci AD74115_CH_FUNC_DIGITAL_INPUT_LOOP_POWER, 13162306a36Sopenharmony_ci AD74115_CH_FUNC_CURRENT_OUTPUT_HART, 13262306a36Sopenharmony_ci AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER_HART, 13362306a36Sopenharmony_ci AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART, 13462306a36Sopenharmony_ci AD74115_CH_FUNC_MAX = AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART, 13562306a36Sopenharmony_ci AD74115_CH_FUNC_NUM 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cienum ad74115_adc_range { 13962306a36Sopenharmony_ci AD74115_ADC_RANGE_12V, 14062306a36Sopenharmony_ci AD74115_ADC_RANGE_12V_BIPOLAR, 14162306a36Sopenharmony_ci AD74115_ADC_RANGE_2_5V_BIPOLAR, 14262306a36Sopenharmony_ci AD74115_ADC_RANGE_2_5V_NEG, 14362306a36Sopenharmony_ci AD74115_ADC_RANGE_2_5V, 14462306a36Sopenharmony_ci AD74115_ADC_RANGE_0_625V, 14562306a36Sopenharmony_ci AD74115_ADC_RANGE_104MV_BIPOLAR, 14662306a36Sopenharmony_ci AD74115_ADC_RANGE_12V_OTHER, 14762306a36Sopenharmony_ci AD74115_ADC_RANGE_MAX = AD74115_ADC_RANGE_12V_OTHER, 14862306a36Sopenharmony_ci AD74115_ADC_RANGE_NUM 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cienum ad74115_adc_conv_seq { 15262306a36Sopenharmony_ci AD74115_ADC_CONV_SEQ_STANDBY = 0b00, 15362306a36Sopenharmony_ci AD74115_ADC_CONV_SEQ_SINGLE = 0b01, 15462306a36Sopenharmony_ci AD74115_ADC_CONV_SEQ_CONTINUOUS = 0b10, 15562306a36Sopenharmony_ci}; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cienum ad74115_din_threshold_mode { 15862306a36Sopenharmony_ci AD74115_DIN_THRESHOLD_MODE_AVDD, 15962306a36Sopenharmony_ci AD74115_DIN_THRESHOLD_MODE_FIXED, 16062306a36Sopenharmony_ci AD74115_DIN_THRESHOLD_MODE_MAX = AD74115_DIN_THRESHOLD_MODE_FIXED, 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cienum ad74115_slew_mode { 16462306a36Sopenharmony_ci AD74115_SLEW_MODE_DISABLED, 16562306a36Sopenharmony_ci AD74115_SLEW_MODE_LINEAR, 16662306a36Sopenharmony_ci AD74115_SLEW_MODE_HART, 16762306a36Sopenharmony_ci}; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cienum ad74115_slew_step { 17062306a36Sopenharmony_ci AD74115_SLEW_STEP_0_8_PERCENT, 17162306a36Sopenharmony_ci AD74115_SLEW_STEP_1_5_PERCENT, 17262306a36Sopenharmony_ci AD74115_SLEW_STEP_6_1_PERCENT, 17362306a36Sopenharmony_ci AD74115_SLEW_STEP_22_2_PERCENT, 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cienum ad74115_slew_rate { 17762306a36Sopenharmony_ci AD74115_SLEW_RATE_4KHZ, 17862306a36Sopenharmony_ci AD74115_SLEW_RATE_64KHZ, 17962306a36Sopenharmony_ci AD74115_SLEW_RATE_150KHZ, 18062306a36Sopenharmony_ci AD74115_SLEW_RATE_240KHZ, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cienum ad74115_gpio_config { 18462306a36Sopenharmony_ci AD74115_GPIO_CONFIG_OUTPUT_BUFFERED = 0b010, 18562306a36Sopenharmony_ci AD74115_GPIO_CONFIG_INPUT = 0b011, 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cienum ad74115_gpio_mode { 18962306a36Sopenharmony_ci AD74115_GPIO_MODE_LOGIC = 1, 19062306a36Sopenharmony_ci AD74115_GPIO_MODE_SPECIAL = 2, 19162306a36Sopenharmony_ci}; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistruct ad74115_channels { 19462306a36Sopenharmony_ci struct iio_chan_spec *channels; 19562306a36Sopenharmony_ci unsigned int num_channels; 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistruct ad74115_state { 19962306a36Sopenharmony_ci struct spi_device *spi; 20062306a36Sopenharmony_ci struct regmap *regmap; 20162306a36Sopenharmony_ci struct iio_trigger *trig; 20262306a36Sopenharmony_ci struct regulator *avdd; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* 20562306a36Sopenharmony_ci * Synchronize consecutive operations when doing a one-shot 20662306a36Sopenharmony_ci * conversion and when updating the ADC samples SPI message. 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_ci struct mutex lock; 20962306a36Sopenharmony_ci struct gpio_chip gc; 21062306a36Sopenharmony_ci struct gpio_chip comp_gc; 21162306a36Sopenharmony_ci int irq; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci unsigned int avdd_mv; 21462306a36Sopenharmony_ci unsigned long gpio_valid_mask; 21562306a36Sopenharmony_ci bool dac_bipolar; 21662306a36Sopenharmony_ci bool dac_hart_slew; 21762306a36Sopenharmony_ci bool rtd_mode_4_wire; 21862306a36Sopenharmony_ci enum ad74115_ch_func ch_func; 21962306a36Sopenharmony_ci enum ad74115_din_threshold_mode din_threshold_mode; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci struct completion adc_data_completion; 22262306a36Sopenharmony_ci struct spi_message adc_samples_msg; 22362306a36Sopenharmony_ci struct spi_transfer adc_samples_xfer[AD74115_ADC_CH_NUM + 1]; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* 22662306a36Sopenharmony_ci * DMA (thus cache coherency maintenance) requires the 22762306a36Sopenharmony_ci * transfer buffers to live in their own cache lines. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ci u8 reg_tx_buf[AD74115_FRAME_SIZE] __aligned(IIO_DMA_MINALIGN); 23062306a36Sopenharmony_ci u8 reg_rx_buf[AD74115_FRAME_SIZE]; 23162306a36Sopenharmony_ci u8 adc_samples_tx_buf[AD74115_FRAME_SIZE * AD74115_ADC_CH_NUM]; 23262306a36Sopenharmony_ci u8 adc_samples_rx_buf[AD74115_FRAME_SIZE * AD74115_ADC_CH_NUM]; 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistruct ad74115_fw_prop { 23662306a36Sopenharmony_ci const char *name; 23762306a36Sopenharmony_ci bool is_boolean; 23862306a36Sopenharmony_ci bool negate; 23962306a36Sopenharmony_ci unsigned int max; 24062306a36Sopenharmony_ci unsigned int reg; 24162306a36Sopenharmony_ci unsigned int mask; 24262306a36Sopenharmony_ci const unsigned int *lookup_tbl; 24362306a36Sopenharmony_ci unsigned int lookup_tbl_len; 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define AD74115_FW_PROP(_name, _max, _reg, _mask) \ 24762306a36Sopenharmony_ci{ \ 24862306a36Sopenharmony_ci .name = (_name), \ 24962306a36Sopenharmony_ci .max = (_max), \ 25062306a36Sopenharmony_ci .reg = (_reg), \ 25162306a36Sopenharmony_ci .mask = (_mask), \ 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci#define AD74115_FW_PROP_TBL(_name, _tbl, _reg, _mask) \ 25562306a36Sopenharmony_ci{ \ 25662306a36Sopenharmony_ci .name = (_name), \ 25762306a36Sopenharmony_ci .reg = (_reg), \ 25862306a36Sopenharmony_ci .mask = (_mask), \ 25962306a36Sopenharmony_ci .lookup_tbl = (_tbl), \ 26062306a36Sopenharmony_ci .lookup_tbl_len = ARRAY_SIZE(_tbl), \ 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci#define AD74115_FW_PROP_BOOL(_name, _reg, _mask) \ 26462306a36Sopenharmony_ci{ \ 26562306a36Sopenharmony_ci .name = (_name), \ 26662306a36Sopenharmony_ci .is_boolean = true, \ 26762306a36Sopenharmony_ci .reg = (_reg), \ 26862306a36Sopenharmony_ci .mask = (_mask), \ 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci#define AD74115_FW_PROP_BOOL_NEG(_name, _reg, _mask) \ 27262306a36Sopenharmony_ci{ \ 27362306a36Sopenharmony_ci .name = (_name), \ 27462306a36Sopenharmony_ci .is_boolean = true, \ 27562306a36Sopenharmony_ci .negate = true, \ 27662306a36Sopenharmony_ci .reg = (_reg), \ 27762306a36Sopenharmony_ci .mask = (_mask), \ 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic const int ad74115_dac_rate_tbl[] = { 28162306a36Sopenharmony_ci 0, 28262306a36Sopenharmony_ci 4 * 8, 28362306a36Sopenharmony_ci 4 * 15, 28462306a36Sopenharmony_ci 4 * 61, 28562306a36Sopenharmony_ci 4 * 222, 28662306a36Sopenharmony_ci 64 * 8, 28762306a36Sopenharmony_ci 64 * 15, 28862306a36Sopenharmony_ci 64 * 61, 28962306a36Sopenharmony_ci 64 * 222, 29062306a36Sopenharmony_ci 150 * 8, 29162306a36Sopenharmony_ci 150 * 15, 29262306a36Sopenharmony_ci 150 * 61, 29362306a36Sopenharmony_ci 150 * 222, 29462306a36Sopenharmony_ci 240 * 8, 29562306a36Sopenharmony_ci 240 * 15, 29662306a36Sopenharmony_ci 240 * 61, 29762306a36Sopenharmony_ci 240 * 222, 29862306a36Sopenharmony_ci}; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic const unsigned int ad74115_dac_rate_step_tbl[][3] = { 30162306a36Sopenharmony_ci { AD74115_SLEW_MODE_DISABLED }, 30262306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_4KHZ }, 30362306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_4KHZ }, 30462306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_4KHZ }, 30562306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_4KHZ }, 30662306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_64KHZ }, 30762306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_64KHZ }, 30862306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_64KHZ }, 30962306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_64KHZ }, 31062306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_150KHZ }, 31162306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_150KHZ }, 31262306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_150KHZ }, 31362306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_150KHZ }, 31462306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_240KHZ }, 31562306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_240KHZ }, 31662306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_240KHZ }, 31762306a36Sopenharmony_ci { AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_240KHZ }, 31862306a36Sopenharmony_ci}; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cistatic const unsigned int ad74115_rtd_excitation_current_ua_tbl[] = { 32162306a36Sopenharmony_ci 250, 500, 750, 1000 32262306a36Sopenharmony_ci}; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic const unsigned int ad74115_burnout_current_na_tbl[] = { 32562306a36Sopenharmony_ci 0, 50, 0, 500, 1000, 0, 10000, 0 32662306a36Sopenharmony_ci}; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistatic const unsigned int ad74115_viout_burnout_current_na_tbl[] = { 32962306a36Sopenharmony_ci 0, 0, 0, 0, 1000, 0, 10000, 0 33062306a36Sopenharmony_ci}; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic const unsigned int ad74115_gpio_mode_tbl[] = { 33362306a36Sopenharmony_ci 0, 0, 0, 1, 2, 3, 4, 5 33462306a36Sopenharmony_ci}; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic const unsigned int ad74115_adc_conv_rate_tbl[] = { 33762306a36Sopenharmony_ci 10, 20, 1200, 4800, 9600 33862306a36Sopenharmony_ci}; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic const unsigned int ad74115_debounce_tbl[] = { 34162306a36Sopenharmony_ci 0, 13, 18, 24, 32, 42, 56, 75, 34262306a36Sopenharmony_ci 100, 130, 180, 240, 320, 420, 560, 750, 34362306a36Sopenharmony_ci 1000, 1300, 1800, 2400, 3200, 4200, 5600, 7500, 34462306a36Sopenharmony_ci 10000, 13000, 18000, 24000, 32000, 42000, 56000, 75000, 34562306a36Sopenharmony_ci}; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic const unsigned int ad74115_adc_ch_data_regs_tbl[] = { 34862306a36Sopenharmony_ci [AD74115_ADC_CH_CONV1] = 0x44, 34962306a36Sopenharmony_ci [AD74115_ADC_CH_CONV2] = 0x46, 35062306a36Sopenharmony_ci}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic const unsigned int ad74115_adc_ch_en_bit_tbl[] = { 35362306a36Sopenharmony_ci [AD74115_ADC_CH_CONV1] = BIT(0), 35462306a36Sopenharmony_ci [AD74115_ADC_CH_CONV2] = BIT(1), 35562306a36Sopenharmony_ci}; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic const bool ad74115_adc_bipolar_tbl[AD74115_ADC_RANGE_NUM] = { 35862306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V_BIPOLAR] = true, 35962306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V_BIPOLAR] = true, 36062306a36Sopenharmony_ci [AD74115_ADC_RANGE_104MV_BIPOLAR] = true, 36162306a36Sopenharmony_ci}; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic const unsigned int ad74115_adc_conv_mul_tbl[AD74115_ADC_RANGE_NUM] = { 36462306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V] = 12000, 36562306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V_BIPOLAR] = 24000, 36662306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V_BIPOLAR] = 5000, 36762306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V_NEG] = 2500, 36862306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V] = 2500, 36962306a36Sopenharmony_ci [AD74115_ADC_RANGE_0_625V] = 625, 37062306a36Sopenharmony_ci [AD74115_ADC_RANGE_104MV_BIPOLAR] = 208, 37162306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V_OTHER] = 12000, 37262306a36Sopenharmony_ci}; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic const unsigned int ad74115_adc_gain_tbl[AD74115_ADC_RANGE_NUM][2] = { 37562306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V] = { 5, 24 }, 37662306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V_BIPOLAR] = { 5, 24 }, 37762306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V_BIPOLAR] = { 1, 1 }, 37862306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V_NEG] = { 1, 1 }, 37962306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V] = { 1, 1 }, 38062306a36Sopenharmony_ci [AD74115_ADC_RANGE_0_625V] = { 4, 1 }, 38162306a36Sopenharmony_ci [AD74115_ADC_RANGE_104MV_BIPOLAR] = { 24, 1 }, 38262306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V_OTHER] = { 5, 24 }, 38362306a36Sopenharmony_ci}; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic const int ad74115_adc_range_tbl[AD74115_ADC_RANGE_NUM][2] = { 38662306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V] = { 0, 12000000 }, 38762306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V_BIPOLAR] = { -12000000, 12000000 }, 38862306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V_BIPOLAR] = { -2500000, 2500000 }, 38962306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V_NEG] = { -2500000, 0 }, 39062306a36Sopenharmony_ci [AD74115_ADC_RANGE_2_5V] = { 0, 2500000 }, 39162306a36Sopenharmony_ci [AD74115_ADC_RANGE_0_625V] = { 0, 625000 }, 39262306a36Sopenharmony_ci [AD74115_ADC_RANGE_104MV_BIPOLAR] = { -104000, 104000 }, 39362306a36Sopenharmony_ci [AD74115_ADC_RANGE_12V_OTHER] = { 0, 12000000 }, 39462306a36Sopenharmony_ci}; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic int _ad74115_find_tbl_index(const unsigned int *tbl, unsigned int tbl_len, 39762306a36Sopenharmony_ci unsigned int val, unsigned int *index) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci unsigned int i; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci for (i = 0; i < tbl_len; i++) 40262306a36Sopenharmony_ci if (val == tbl[i]) { 40362306a36Sopenharmony_ci *index = i; 40462306a36Sopenharmony_ci return 0; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci return -EINVAL; 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci#define ad74115_find_tbl_index(tbl, val, index) \ 41162306a36Sopenharmony_ci _ad74115_find_tbl_index(tbl, ARRAY_SIZE(tbl), val, index) 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic int ad74115_crc(u8 *buf) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci return crc8(ad74115_crc8_table, buf, 3, 0); 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic void ad74115_format_reg_write(u8 reg, u16 val, u8 *buf) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci buf[0] = reg; 42162306a36Sopenharmony_ci put_unaligned_be16(val, &buf[1]); 42262306a36Sopenharmony_ci buf[3] = ad74115_crc(buf); 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic int ad74115_reg_write(void *context, unsigned int reg, unsigned int val) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci struct ad74115_state *st = context; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci ad74115_format_reg_write(reg, val, st->reg_tx_buf); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci return spi_write(st->spi, st->reg_tx_buf, AD74115_FRAME_SIZE); 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic int ad74115_crc_check(struct ad74115_state *st, u8 *buf) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 43762306a36Sopenharmony_ci u8 expected_crc = ad74115_crc(buf); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (buf[3] != expected_crc) { 44062306a36Sopenharmony_ci dev_err(dev, "Bad CRC %02x for %02x%02x%02x, expected %02x\n", 44162306a36Sopenharmony_ci buf[3], buf[0], buf[1], buf[2], expected_crc); 44262306a36Sopenharmony_ci return -EINVAL; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci return 0; 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic int ad74115_reg_read(void *context, unsigned int reg, unsigned int *val) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci struct ad74115_state *st = context; 45162306a36Sopenharmony_ci struct spi_transfer reg_read_xfer[] = { 45262306a36Sopenharmony_ci { 45362306a36Sopenharmony_ci .tx_buf = st->reg_tx_buf, 45462306a36Sopenharmony_ci .len = sizeof(st->reg_tx_buf), 45562306a36Sopenharmony_ci .cs_change = 1, 45662306a36Sopenharmony_ci }, 45762306a36Sopenharmony_ci { 45862306a36Sopenharmony_ci .rx_buf = st->reg_rx_buf, 45962306a36Sopenharmony_ci .len = sizeof(st->reg_rx_buf), 46062306a36Sopenharmony_ci }, 46162306a36Sopenharmony_ci }; 46262306a36Sopenharmony_ci int ret; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci ad74115_format_reg_write(AD74115_READ_SELECT_REG, reg, st->reg_tx_buf); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci ret = spi_sync_transfer(st->spi, reg_read_xfer, ARRAY_SIZE(reg_read_xfer)); 46762306a36Sopenharmony_ci if (ret) 46862306a36Sopenharmony_ci return ret; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci ret = ad74115_crc_check(st, st->reg_rx_buf); 47162306a36Sopenharmony_ci if (ret) 47262306a36Sopenharmony_ci return ret; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci *val = get_unaligned_be16(&st->reg_rx_buf[1]); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci return 0; 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic const struct regmap_config ad74115_regmap_config = { 48062306a36Sopenharmony_ci .reg_bits = 8, 48162306a36Sopenharmony_ci .val_bits = 16, 48262306a36Sopenharmony_ci .reg_read = ad74115_reg_read, 48362306a36Sopenharmony_ci .reg_write = ad74115_reg_write, 48462306a36Sopenharmony_ci}; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic int ad74115_gpio_config_set(struct ad74115_state *st, unsigned int offset, 48762306a36Sopenharmony_ci enum ad74115_gpio_config cfg) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), 49062306a36Sopenharmony_ci AD74115_GPIO_CONFIG_SELECT_MASK, 49162306a36Sopenharmony_ci FIELD_PREP(AD74115_GPIO_CONFIG_SELECT_MASK, cfg)); 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_cistatic int ad74115_gpio_init_valid_mask(struct gpio_chip *gc, 49562306a36Sopenharmony_ci unsigned long *valid_mask, 49662306a36Sopenharmony_ci unsigned int ngpios) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(gc); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci *valid_mask = st->gpio_valid_mask; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci return 0; 50362306a36Sopenharmony_ci} 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic int ad74115_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(gc); 50862306a36Sopenharmony_ci unsigned int val; 50962306a36Sopenharmony_ci int ret; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), &val); 51262306a36Sopenharmony_ci if (ret) 51362306a36Sopenharmony_ci return ret; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci return FIELD_GET(AD74115_GPIO_CONFIG_SELECT_MASK, val) == AD74115_GPIO_CONFIG_INPUT; 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic int ad74115_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(gc); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci return ad74115_gpio_config_set(st, offset, AD74115_GPIO_CONFIG_INPUT); 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cistatic int ad74115_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, 52662306a36Sopenharmony_ci int value) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(gc); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci return ad74115_gpio_config_set(st, offset, AD74115_GPIO_CONFIG_OUTPUT_BUFFERED); 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic int ad74115_gpio_get(struct gpio_chip *gc, unsigned int offset) 53462306a36Sopenharmony_ci{ 53562306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(gc); 53662306a36Sopenharmony_ci unsigned int val; 53762306a36Sopenharmony_ci int ret; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), &val); 54062306a36Sopenharmony_ci if (ret) 54162306a36Sopenharmony_ci return ret; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci return FIELD_GET(AD74115_GPIO_CONFIG_GPI_DATA, val); 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic void ad74115_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(gc); 54962306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 55062306a36Sopenharmony_ci int ret; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), 55362306a36Sopenharmony_ci AD74115_GPIO_CONFIG_GPO_DATA, 55462306a36Sopenharmony_ci FIELD_PREP(AD74115_GPIO_CONFIG_GPO_DATA, value)); 55562306a36Sopenharmony_ci if (ret) 55662306a36Sopenharmony_ci dev_err(dev, "Failed to set GPIO %u output value, err: %d\n", 55762306a36Sopenharmony_ci offset, ret); 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_cistatic int ad74115_set_comp_debounce(struct ad74115_state *st, unsigned int val) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci unsigned int len = ARRAY_SIZE(ad74115_debounce_tbl); 56362306a36Sopenharmony_ci unsigned int i; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci for (i = 0; i < len; i++) 56662306a36Sopenharmony_ci if (val <= ad74115_debounce_tbl[i]) 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci if (i == len) 57062306a36Sopenharmony_ci i = len - 1; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_DIN_CONFIG1_REG, 57362306a36Sopenharmony_ci AD74115_DIN_DEBOUNCE_MASK, 57462306a36Sopenharmony_ci FIELD_PREP(AD74115_DIN_DEBOUNCE_MASK, val)); 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic int ad74115_comp_gpio_get_direction(struct gpio_chip *chip, 57862306a36Sopenharmony_ci unsigned int offset) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci return GPIO_LINE_DIRECTION_IN; 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic int ad74115_comp_gpio_set_config(struct gpio_chip *chip, 58462306a36Sopenharmony_ci unsigned int offset, 58562306a36Sopenharmony_ci unsigned long config) 58662306a36Sopenharmony_ci{ 58762306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(chip); 58862306a36Sopenharmony_ci u32 param = pinconf_to_config_param(config); 58962306a36Sopenharmony_ci u32 arg = pinconf_to_config_argument(config); 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci switch (param) { 59262306a36Sopenharmony_ci case PIN_CONFIG_INPUT_DEBOUNCE: 59362306a36Sopenharmony_ci return ad74115_set_comp_debounce(st, arg); 59462306a36Sopenharmony_ci default: 59562306a36Sopenharmony_ci return -ENOTSUPP; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic int ad74115_comp_gpio_get(struct gpio_chip *chip, unsigned int offset) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci struct ad74115_state *st = gpiochip_get_data(chip); 60262306a36Sopenharmony_ci unsigned int val; 60362306a36Sopenharmony_ci int ret; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_DIN_COMP_OUT_REG, &val); 60662306a36Sopenharmony_ci if (ret) 60762306a36Sopenharmony_ci return ret; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci return !!val; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_cistatic irqreturn_t ad74115_trigger_handler(int irq, void *p) 61362306a36Sopenharmony_ci{ 61462306a36Sopenharmony_ci struct iio_poll_func *pf = p; 61562306a36Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 61662306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 61762306a36Sopenharmony_ci int ret; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci ret = spi_sync(st->spi, &st->adc_samples_msg); 62062306a36Sopenharmony_ci if (ret) 62162306a36Sopenharmony_ci goto out; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci iio_push_to_buffers(indio_dev, st->adc_samples_rx_buf); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ciout: 62662306a36Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci return IRQ_HANDLED; 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_cistatic irqreturn_t ad74115_adc_data_interrupt(int irq, void *data) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci struct iio_dev *indio_dev = data; 63462306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (iio_buffer_enabled(indio_dev)) 63762306a36Sopenharmony_ci iio_trigger_poll(st->trig); 63862306a36Sopenharmony_ci else 63962306a36Sopenharmony_ci complete(&st->adc_data_completion); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci return IRQ_HANDLED; 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_cistatic int ad74115_set_adc_ch_en(struct ad74115_state *st, 64562306a36Sopenharmony_ci enum ad74115_adc_ch channel, bool status) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci unsigned int mask = ad74115_adc_ch_en_bit_tbl[channel]; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_ADC_CONV_CTRL_REG, mask, 65062306a36Sopenharmony_ci status ? mask : 0); 65162306a36Sopenharmony_ci} 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_cistatic int ad74115_set_adc_conv_seq(struct ad74115_state *st, 65462306a36Sopenharmony_ci enum ad74115_adc_conv_seq conv_seq) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_ADC_CONV_CTRL_REG, 65762306a36Sopenharmony_ci AD74115_ADC_CONV_SEQ_MASK, 65862306a36Sopenharmony_ci FIELD_PREP(AD74115_ADC_CONV_SEQ_MASK, conv_seq)); 65962306a36Sopenharmony_ci} 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_cistatic int ad74115_update_scan_mode(struct iio_dev *indio_dev, 66262306a36Sopenharmony_ci const unsigned long *active_scan_mask) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 66562306a36Sopenharmony_ci struct spi_transfer *xfer = st->adc_samples_xfer; 66662306a36Sopenharmony_ci u8 *rx_buf = st->adc_samples_rx_buf; 66762306a36Sopenharmony_ci u8 *tx_buf = st->adc_samples_tx_buf; 66862306a36Sopenharmony_ci unsigned int i; 66962306a36Sopenharmony_ci int ret = 0; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci mutex_lock(&st->lock); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci spi_message_init(&st->adc_samples_msg); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci for_each_clear_bit(i, active_scan_mask, AD74115_ADC_CH_NUM) { 67662306a36Sopenharmony_ci ret = ad74115_set_adc_ch_en(st, i, false); 67762306a36Sopenharmony_ci if (ret) 67862306a36Sopenharmony_ci goto out; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* 68262306a36Sopenharmony_ci * The read select register is used to select which register's value 68362306a36Sopenharmony_ci * will be sent by the slave on the next SPI frame. 68462306a36Sopenharmony_ci * 68562306a36Sopenharmony_ci * Create an SPI message that, on each step, writes to the read select 68662306a36Sopenharmony_ci * register to select the ADC result of the next enabled channel, and 68762306a36Sopenharmony_ci * reads the ADC result of the previous enabled channel. 68862306a36Sopenharmony_ci * 68962306a36Sopenharmony_ci * Example: 69062306a36Sopenharmony_ci * W: [WCH1] [WCH2] [WCH2] [WCH3] [ ] 69162306a36Sopenharmony_ci * R: [ ] [RCH1] [RCH2] [RCH3] [RCH4] 69262306a36Sopenharmony_ci */ 69362306a36Sopenharmony_ci for_each_set_bit(i, active_scan_mask, AD74115_ADC_CH_NUM) { 69462306a36Sopenharmony_ci ret = ad74115_set_adc_ch_en(st, i, true); 69562306a36Sopenharmony_ci if (ret) 69662306a36Sopenharmony_ci goto out; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci if (xfer == st->adc_samples_xfer) 69962306a36Sopenharmony_ci xfer->rx_buf = NULL; 70062306a36Sopenharmony_ci else 70162306a36Sopenharmony_ci xfer->rx_buf = rx_buf; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci xfer->tx_buf = tx_buf; 70462306a36Sopenharmony_ci xfer->len = AD74115_FRAME_SIZE; 70562306a36Sopenharmony_ci xfer->cs_change = 1; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci ad74115_format_reg_write(AD74115_READ_SELECT_REG, 70862306a36Sopenharmony_ci ad74115_adc_ch_data_regs_tbl[i], tx_buf); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci spi_message_add_tail(xfer, &st->adc_samples_msg); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci tx_buf += AD74115_FRAME_SIZE; 71362306a36Sopenharmony_ci if (xfer != st->adc_samples_xfer) 71462306a36Sopenharmony_ci rx_buf += AD74115_FRAME_SIZE; 71562306a36Sopenharmony_ci xfer++; 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci xfer->rx_buf = rx_buf; 71962306a36Sopenharmony_ci xfer->tx_buf = NULL; 72062306a36Sopenharmony_ci xfer->len = AD74115_FRAME_SIZE; 72162306a36Sopenharmony_ci xfer->cs_change = 0; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci spi_message_add_tail(xfer, &st->adc_samples_msg); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ciout: 72662306a36Sopenharmony_ci mutex_unlock(&st->lock); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci return ret; 72962306a36Sopenharmony_ci} 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_cistatic int ad74115_buffer_postenable(struct iio_dev *indio_dev) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci return ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_CONTINUOUS); 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic int ad74115_buffer_predisable(struct iio_dev *indio_dev) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 74162306a36Sopenharmony_ci unsigned int i; 74262306a36Sopenharmony_ci int ret; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci mutex_lock(&st->lock); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_STANDBY); 74762306a36Sopenharmony_ci if (ret) 74862306a36Sopenharmony_ci goto out; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci /* 75162306a36Sopenharmony_ci * update_scan_mode() is not called in the disable path, disable all 75262306a36Sopenharmony_ci * channels here. 75362306a36Sopenharmony_ci */ 75462306a36Sopenharmony_ci for (i = 0; i < AD74115_ADC_CH_NUM; i++) { 75562306a36Sopenharmony_ci ret = ad74115_set_adc_ch_en(st, i, false); 75662306a36Sopenharmony_ci if (ret) 75762306a36Sopenharmony_ci goto out; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ciout: 76162306a36Sopenharmony_ci mutex_unlock(&st->lock); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci return ret; 76462306a36Sopenharmony_ci} 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops ad74115_buffer_ops = { 76762306a36Sopenharmony_ci .postenable = &ad74115_buffer_postenable, 76862306a36Sopenharmony_ci .predisable = &ad74115_buffer_predisable, 76962306a36Sopenharmony_ci}; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistatic const struct iio_trigger_ops ad74115_trigger_ops = { 77262306a36Sopenharmony_ci .validate_device = iio_trigger_validate_own_device, 77362306a36Sopenharmony_ci}; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_cistatic int ad74115_get_adc_rate(struct ad74115_state *st, 77662306a36Sopenharmony_ci enum ad74115_adc_ch channel, int *val) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci unsigned int i; 77962306a36Sopenharmony_ci int ret; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_ADC_CONFIG_REG, &i); 78262306a36Sopenharmony_ci if (ret) 78362306a36Sopenharmony_ci return ret; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci if (channel == AD74115_ADC_CH_CONV1) 78662306a36Sopenharmony_ci i = FIELD_GET(AD74115_ADC_CONFIG_CONV1_RATE_MASK, i); 78762306a36Sopenharmony_ci else 78862306a36Sopenharmony_ci i = FIELD_GET(AD74115_ADC_CONFIG_CONV2_RATE_MASK, i); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci *val = ad74115_adc_conv_rate_tbl[i]; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci return IIO_VAL_INT; 79362306a36Sopenharmony_ci} 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_cistatic int _ad74115_get_adc_code(struct ad74115_state *st, 79662306a36Sopenharmony_ci enum ad74115_adc_ch channel, int *val) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci unsigned int uval; 79962306a36Sopenharmony_ci int ret; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci reinit_completion(&st->adc_data_completion); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci ret = ad74115_set_adc_ch_en(st, channel, true); 80462306a36Sopenharmony_ci if (ret) 80562306a36Sopenharmony_ci return ret; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_SINGLE); 80862306a36Sopenharmony_ci if (ret) 80962306a36Sopenharmony_ci return ret; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci if (st->irq) { 81262306a36Sopenharmony_ci ret = wait_for_completion_timeout(&st->adc_data_completion, 81362306a36Sopenharmony_ci msecs_to_jiffies(1000)); 81462306a36Sopenharmony_ci if (!ret) 81562306a36Sopenharmony_ci return -ETIMEDOUT; 81662306a36Sopenharmony_ci } else { 81762306a36Sopenharmony_ci unsigned int regval, wait_time; 81862306a36Sopenharmony_ci int rate; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci ret = ad74115_get_adc_rate(st, channel, &rate); 82162306a36Sopenharmony_ci if (ret < 0) 82262306a36Sopenharmony_ci return ret; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci wait_time = DIV_ROUND_CLOSEST(AD74115_CONV_TIME_US, rate); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci ret = regmap_read_poll_timeout(st->regmap, AD74115_LIVE_STATUS_REG, 82762306a36Sopenharmony_ci regval, regval & AD74115_ADC_DATA_RDY_MASK, 82862306a36Sopenharmony_ci wait_time, 5 * wait_time); 82962306a36Sopenharmony_ci if (ret) 83062306a36Sopenharmony_ci return ret; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci /* 83362306a36Sopenharmony_ci * The ADC_DATA_RDY bit is W1C. 83462306a36Sopenharmony_ci * See datasheet page 98, Table 62. Bit Descriptions for 83562306a36Sopenharmony_ci * LIVE_STATUS. 83662306a36Sopenharmony_ci * Although the datasheet mentions that the bit will auto-clear 83762306a36Sopenharmony_ci * when writing to the ADC_CONV_CTRL register, this does not 83862306a36Sopenharmony_ci * seem to happen. 83962306a36Sopenharmony_ci */ 84062306a36Sopenharmony_ci ret = regmap_write_bits(st->regmap, AD74115_LIVE_STATUS_REG, 84162306a36Sopenharmony_ci AD74115_ADC_DATA_RDY_MASK, 84262306a36Sopenharmony_ci FIELD_PREP(AD74115_ADC_DATA_RDY_MASK, 1)); 84362306a36Sopenharmony_ci if (ret) 84462306a36Sopenharmony_ci return ret; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci ret = regmap_read(st->regmap, ad74115_adc_ch_data_regs_tbl[channel], &uval); 84862306a36Sopenharmony_ci if (ret) 84962306a36Sopenharmony_ci return ret; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_STANDBY); 85262306a36Sopenharmony_ci if (ret) 85362306a36Sopenharmony_ci return ret; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci ret = ad74115_set_adc_ch_en(st, channel, false); 85662306a36Sopenharmony_ci if (ret) 85762306a36Sopenharmony_ci return ret; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci *val = uval; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci return IIO_VAL_INT; 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cistatic int ad74115_get_adc_code(struct iio_dev *indio_dev, 86562306a36Sopenharmony_ci enum ad74115_adc_ch channel, int *val) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 86862306a36Sopenharmony_ci int ret; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 87162306a36Sopenharmony_ci if (ret) 87262306a36Sopenharmony_ci return ret; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci mutex_lock(&st->lock); 87562306a36Sopenharmony_ci ret = _ad74115_get_adc_code(st, channel, val); 87662306a36Sopenharmony_ci mutex_unlock(&st->lock); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci return ret; 88162306a36Sopenharmony_ci} 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cistatic int ad74115_adc_code_to_resistance(int code, int *val, int *val2) 88462306a36Sopenharmony_ci{ 88562306a36Sopenharmony_ci if (code == AD74115_ADC_CODE_MAX) 88662306a36Sopenharmony_ci code--; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci *val = code * AD74115_REF_RESISTOR_OHMS; 88962306a36Sopenharmony_ci *val2 = AD74115_ADC_CODE_MAX - code; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 89262306a36Sopenharmony_ci} 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_cistatic int ad74115_set_dac_code(struct ad74115_state *st, 89562306a36Sopenharmony_ci enum ad74115_dac_ch channel, int val) 89662306a36Sopenharmony_ci{ 89762306a36Sopenharmony_ci if (val < 0) 89862306a36Sopenharmony_ci return -EINVAL; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci if (channel == AD74115_DAC_CH_COMPARATOR) { 90162306a36Sopenharmony_ci if (val > AD74115_COMP_THRESH_MAX) 90262306a36Sopenharmony_ci return -EINVAL; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_DIN_CONFIG2_REG, 90562306a36Sopenharmony_ci AD74115_COMP_THRESH_MASK, 90662306a36Sopenharmony_ci FIELD_PREP(AD74115_COMP_THRESH_MASK, val)); 90762306a36Sopenharmony_ci } 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (val > AD74115_DAC_CODE_MAX) 91062306a36Sopenharmony_ci return -EINVAL; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci return regmap_write(st->regmap, AD74115_DAC_CODE_REG, val); 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_cistatic int ad74115_get_dac_code(struct ad74115_state *st, 91662306a36Sopenharmony_ci enum ad74115_dac_ch channel, int *val) 91762306a36Sopenharmony_ci{ 91862306a36Sopenharmony_ci unsigned int uval; 91962306a36Sopenharmony_ci int ret; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci if (channel == AD74115_DAC_CH_COMPARATOR) 92262306a36Sopenharmony_ci return -EINVAL; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_DAC_ACTIVE_REG, &uval); 92562306a36Sopenharmony_ci if (ret) 92662306a36Sopenharmony_ci return ret; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci *val = uval; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci return IIO_VAL_INT; 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_cistatic int ad74115_set_adc_rate(struct ad74115_state *st, 93462306a36Sopenharmony_ci enum ad74115_adc_ch channel, int val) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci unsigned int i; 93762306a36Sopenharmony_ci int ret; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci ret = ad74115_find_tbl_index(ad74115_adc_conv_rate_tbl, val, &i); 94062306a36Sopenharmony_ci if (ret) 94162306a36Sopenharmony_ci return ret; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci if (channel == AD74115_ADC_CH_CONV1) 94462306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG, 94562306a36Sopenharmony_ci AD74115_ADC_CONFIG_CONV1_RATE_MASK, 94662306a36Sopenharmony_ci FIELD_PREP(AD74115_ADC_CONFIG_CONV1_RATE_MASK, i)); 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG, 94962306a36Sopenharmony_ci AD74115_ADC_CONFIG_CONV2_RATE_MASK, 95062306a36Sopenharmony_ci FIELD_PREP(AD74115_ADC_CONFIG_CONV2_RATE_MASK, i)); 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_cistatic int ad74115_get_dac_rate(struct ad74115_state *st, int *val) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci unsigned int i, en_val, step_val, rate_val, tmp; 95662306a36Sopenharmony_ci int ret; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_OUTPUT_CONFIG_REG, &tmp); 95962306a36Sopenharmony_ci if (ret) 96062306a36Sopenharmony_ci return ret; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci en_val = FIELD_GET(AD74115_OUTPUT_SLEW_EN_MASK, tmp); 96362306a36Sopenharmony_ci step_val = FIELD_GET(AD74115_OUTPUT_SLEW_LIN_STEP_MASK, tmp); 96462306a36Sopenharmony_ci rate_val = FIELD_GET(AD74115_OUTPUT_SLEW_LIN_RATE_MASK, tmp); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad74115_dac_rate_step_tbl); i++) 96762306a36Sopenharmony_ci if (en_val == ad74115_dac_rate_step_tbl[i][0] && 96862306a36Sopenharmony_ci step_val == ad74115_dac_rate_step_tbl[i][1] && 96962306a36Sopenharmony_ci rate_val == ad74115_dac_rate_step_tbl[i][2]) 97062306a36Sopenharmony_ci break; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci if (i == ARRAY_SIZE(ad74115_dac_rate_step_tbl)) 97362306a36Sopenharmony_ci return -EINVAL; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci *val = ad74115_dac_rate_tbl[i]; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci return IIO_VAL_INT; 97862306a36Sopenharmony_ci} 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_cistatic int ad74115_set_dac_rate(struct ad74115_state *st, int val) 98162306a36Sopenharmony_ci{ 98262306a36Sopenharmony_ci unsigned int i, en_val, step_val, rate_val, mask, tmp; 98362306a36Sopenharmony_ci int ret; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci ret = ad74115_find_tbl_index(ad74115_dac_rate_tbl, val, &i); 98662306a36Sopenharmony_ci if (ret) 98762306a36Sopenharmony_ci return ret; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci en_val = ad74115_dac_rate_step_tbl[i][0]; 99062306a36Sopenharmony_ci step_val = ad74115_dac_rate_step_tbl[i][1]; 99162306a36Sopenharmony_ci rate_val = ad74115_dac_rate_step_tbl[i][2]; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci mask = AD74115_OUTPUT_SLEW_EN_MASK; 99462306a36Sopenharmony_ci mask |= AD74115_OUTPUT_SLEW_LIN_STEP_MASK; 99562306a36Sopenharmony_ci mask |= AD74115_OUTPUT_SLEW_LIN_RATE_MASK; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci tmp = FIELD_PREP(AD74115_OUTPUT_SLEW_EN_MASK, en_val); 99862306a36Sopenharmony_ci tmp |= FIELD_PREP(AD74115_OUTPUT_SLEW_LIN_STEP_MASK, step_val); 99962306a36Sopenharmony_ci tmp |= FIELD_PREP(AD74115_OUTPUT_SLEW_LIN_RATE_MASK, rate_val); 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_OUTPUT_CONFIG_REG, mask, tmp); 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_cistatic int ad74115_get_dac_scale(struct ad74115_state *st, 100562306a36Sopenharmony_ci struct iio_chan_spec const *chan, 100662306a36Sopenharmony_ci int *val, int *val2) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci if (chan->channel == AD74115_DAC_CH_MAIN) { 100962306a36Sopenharmony_ci if (chan->type == IIO_VOLTAGE) { 101062306a36Sopenharmony_ci *val = AD74115_DAC_VOLTAGE_MAX; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci if (st->dac_bipolar) 101362306a36Sopenharmony_ci *val *= 2; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci } else { 101662306a36Sopenharmony_ci *val = AD74115_DAC_CURRENT_MAX; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci *val2 = AD74115_DAC_CODE_MAX; 102062306a36Sopenharmony_ci } else { 102162306a36Sopenharmony_ci if (st->din_threshold_mode == AD74115_DIN_THRESHOLD_MODE_AVDD) { 102262306a36Sopenharmony_ci *val = 196 * st->avdd_mv; 102362306a36Sopenharmony_ci *val2 = 10 * AD74115_COMP_THRESH_MAX; 102462306a36Sopenharmony_ci } else { 102562306a36Sopenharmony_ci *val = 49000; 102662306a36Sopenharmony_ci *val2 = AD74115_COMP_THRESH_MAX; 102762306a36Sopenharmony_ci } 102862306a36Sopenharmony_ci } 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 103162306a36Sopenharmony_ci} 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_cistatic int ad74115_get_dac_offset(struct ad74115_state *st, 103462306a36Sopenharmony_ci struct iio_chan_spec const *chan, int *val) 103562306a36Sopenharmony_ci{ 103662306a36Sopenharmony_ci if (chan->channel == AD74115_DAC_CH_MAIN) { 103762306a36Sopenharmony_ci if (chan->type == IIO_VOLTAGE && st->dac_bipolar) 103862306a36Sopenharmony_ci *val = -AD74115_DAC_CODE_HALF; 103962306a36Sopenharmony_ci else 104062306a36Sopenharmony_ci *val = 0; 104162306a36Sopenharmony_ci } else { 104262306a36Sopenharmony_ci if (st->din_threshold_mode == AD74115_DIN_THRESHOLD_MODE_AVDD) 104362306a36Sopenharmony_ci *val = -48; 104462306a36Sopenharmony_ci else 104562306a36Sopenharmony_ci *val = -38; 104662306a36Sopenharmony_ci } 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci return IIO_VAL_INT; 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_cistatic int ad74115_get_adc_range(struct ad74115_state *st, 105262306a36Sopenharmony_ci enum ad74115_adc_ch channel, unsigned int *val) 105362306a36Sopenharmony_ci{ 105462306a36Sopenharmony_ci int ret; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_ADC_CONFIG_REG, val); 105762306a36Sopenharmony_ci if (ret) 105862306a36Sopenharmony_ci return ret; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci if (channel == AD74115_ADC_CH_CONV1) 106162306a36Sopenharmony_ci *val = FIELD_GET(AD74115_ADC_CONFIG_CONV1_RANGE_MASK, *val); 106262306a36Sopenharmony_ci else 106362306a36Sopenharmony_ci *val = FIELD_GET(AD74115_ADC_CONFIG_CONV2_RANGE_MASK, *val); 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci return 0; 106662306a36Sopenharmony_ci} 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_cistatic int ad74115_get_adc_resistance_scale(struct ad74115_state *st, 106962306a36Sopenharmony_ci unsigned int range, 107062306a36Sopenharmony_ci int *val, int *val2) 107162306a36Sopenharmony_ci{ 107262306a36Sopenharmony_ci *val = ad74115_adc_gain_tbl[range][1] * AD74115_REF_RESISTOR_OHMS; 107362306a36Sopenharmony_ci *val2 = ad74115_adc_gain_tbl[range][0]; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci if (ad74115_adc_bipolar_tbl[range]) 107662306a36Sopenharmony_ci *val2 *= AD74115_ADC_CODE_HALF; 107762306a36Sopenharmony_ci else 107862306a36Sopenharmony_ci *val2 *= AD74115_ADC_CODE_MAX; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 108162306a36Sopenharmony_ci} 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_cistatic int ad74115_get_adc_scale(struct ad74115_state *st, 108462306a36Sopenharmony_ci struct iio_chan_spec const *chan, 108562306a36Sopenharmony_ci int *val, int *val2) 108662306a36Sopenharmony_ci{ 108762306a36Sopenharmony_ci unsigned int range; 108862306a36Sopenharmony_ci int ret; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci ret = ad74115_get_adc_range(st, chan->channel, &range); 109162306a36Sopenharmony_ci if (ret) 109262306a36Sopenharmony_ci return ret; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci if (chan->type == IIO_RESISTANCE) 109562306a36Sopenharmony_ci return ad74115_get_adc_resistance_scale(st, range, val, val2); 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci *val = ad74115_adc_conv_mul_tbl[range]; 109862306a36Sopenharmony_ci *val2 = AD74115_ADC_CODE_MAX; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci if (chan->type == IIO_CURRENT) 110162306a36Sopenharmony_ci *val2 *= AD74115_SENSE_RESISTOR_OHMS; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic int ad74115_get_adc_resistance_offset(struct ad74115_state *st, 110762306a36Sopenharmony_ci unsigned int range, 110862306a36Sopenharmony_ci int *val, int *val2) 110962306a36Sopenharmony_ci{ 111062306a36Sopenharmony_ci unsigned int d = 10 * AD74115_REF_RESISTOR_OHMS 111162306a36Sopenharmony_ci * ad74115_adc_gain_tbl[range][1]; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci *val = 5; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci if (ad74115_adc_bipolar_tbl[range]) 111662306a36Sopenharmony_ci *val -= AD74115_ADC_CODE_HALF; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci *val *= d; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (!st->rtd_mode_4_wire) { 112162306a36Sopenharmony_ci /* Add 0.2 Ohm to the final result for 3-wire RTD. */ 112262306a36Sopenharmony_ci unsigned int v = 2 * ad74115_adc_gain_tbl[range][0]; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci if (ad74115_adc_bipolar_tbl[range]) 112562306a36Sopenharmony_ci v *= AD74115_ADC_CODE_HALF; 112662306a36Sopenharmony_ci else 112762306a36Sopenharmony_ci v *= AD74115_ADC_CODE_MAX; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci *val += v; 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci *val2 = d; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 113562306a36Sopenharmony_ci} 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_cistatic int ad74115_get_adc_offset(struct ad74115_state *st, 113862306a36Sopenharmony_ci struct iio_chan_spec const *chan, 113962306a36Sopenharmony_ci int *val, int *val2) 114062306a36Sopenharmony_ci{ 114162306a36Sopenharmony_ci unsigned int range; 114262306a36Sopenharmony_ci int ret; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci ret = ad74115_get_adc_range(st, chan->channel, &range); 114562306a36Sopenharmony_ci if (ret) 114662306a36Sopenharmony_ci return ret; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci if (chan->type == IIO_RESISTANCE) 114962306a36Sopenharmony_ci return ad74115_get_adc_resistance_offset(st, range, val, val2); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci if (ad74115_adc_bipolar_tbl[range]) 115262306a36Sopenharmony_ci *val = -AD74115_ADC_CODE_HALF; 115362306a36Sopenharmony_ci else if (range == AD74115_ADC_RANGE_2_5V_NEG) 115462306a36Sopenharmony_ci *val = -AD74115_ADC_CODE_MAX; 115562306a36Sopenharmony_ci else 115662306a36Sopenharmony_ci *val = 0; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci return IIO_VAL_INT; 115962306a36Sopenharmony_ci} 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_cistatic int ad74115_read_raw(struct iio_dev *indio_dev, 116262306a36Sopenharmony_ci struct iio_chan_spec const *chan, 116362306a36Sopenharmony_ci int *val, int *val2, long info) 116462306a36Sopenharmony_ci{ 116562306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 116662306a36Sopenharmony_ci int ret; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci switch (info) { 116962306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 117062306a36Sopenharmony_ci if (chan->output) 117162306a36Sopenharmony_ci return ad74115_get_dac_code(st, chan->channel, val); 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci return ad74115_get_adc_code(indio_dev, chan->channel, val); 117462306a36Sopenharmony_ci case IIO_CHAN_INFO_PROCESSED: 117562306a36Sopenharmony_ci ret = ad74115_get_adc_code(indio_dev, chan->channel, val); 117662306a36Sopenharmony_ci if (ret) 117762306a36Sopenharmony_ci return ret; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci return ad74115_adc_code_to_resistance(*val, val, val2); 118062306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 118162306a36Sopenharmony_ci if (chan->output) 118262306a36Sopenharmony_ci return ad74115_get_dac_scale(st, chan, val, val2); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci return ad74115_get_adc_scale(st, chan, val, val2); 118562306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 118662306a36Sopenharmony_ci if (chan->output) 118762306a36Sopenharmony_ci return ad74115_get_dac_offset(st, chan, val); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci return ad74115_get_adc_offset(st, chan, val, val2); 119062306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 119162306a36Sopenharmony_ci if (chan->output) 119262306a36Sopenharmony_ci return ad74115_get_dac_rate(st, val); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci return ad74115_get_adc_rate(st, chan->channel, val); 119562306a36Sopenharmony_ci default: 119662306a36Sopenharmony_ci return -EINVAL; 119762306a36Sopenharmony_ci } 119862306a36Sopenharmony_ci} 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_cistatic int ad74115_write_raw(struct iio_dev *indio_dev, 120162306a36Sopenharmony_ci struct iio_chan_spec const *chan, int val, int val2, 120262306a36Sopenharmony_ci long info) 120362306a36Sopenharmony_ci{ 120462306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci switch (info) { 120762306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 120862306a36Sopenharmony_ci if (!chan->output) 120962306a36Sopenharmony_ci return -EINVAL; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci return ad74115_set_dac_code(st, chan->channel, val); 121262306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 121362306a36Sopenharmony_ci if (chan->output) 121462306a36Sopenharmony_ci return ad74115_set_dac_rate(st, val); 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci return ad74115_set_adc_rate(st, chan->channel, val); 121762306a36Sopenharmony_ci default: 121862306a36Sopenharmony_ci return -EINVAL; 121962306a36Sopenharmony_ci } 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic int ad74115_read_avail(struct iio_dev *indio_dev, 122362306a36Sopenharmony_ci struct iio_chan_spec const *chan, 122462306a36Sopenharmony_ci const int **vals, int *type, int *length, long info) 122562306a36Sopenharmony_ci{ 122662306a36Sopenharmony_ci switch (info) { 122762306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 122862306a36Sopenharmony_ci if (chan->output) { 122962306a36Sopenharmony_ci *vals = ad74115_dac_rate_tbl; 123062306a36Sopenharmony_ci *length = ARRAY_SIZE(ad74115_dac_rate_tbl); 123162306a36Sopenharmony_ci } else { 123262306a36Sopenharmony_ci *vals = ad74115_adc_conv_rate_tbl; 123362306a36Sopenharmony_ci *length = ARRAY_SIZE(ad74115_adc_conv_rate_tbl); 123462306a36Sopenharmony_ci } 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci *type = IIO_VAL_INT; 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci return IIO_AVAIL_LIST; 123962306a36Sopenharmony_ci default: 124062306a36Sopenharmony_ci return -EINVAL; 124162306a36Sopenharmony_ci } 124262306a36Sopenharmony_ci} 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_cistatic int ad74115_reg_access(struct iio_dev *indio_dev, unsigned int reg, 124562306a36Sopenharmony_ci unsigned int writeval, unsigned int *readval) 124662306a36Sopenharmony_ci{ 124762306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci if (readval) 125062306a36Sopenharmony_ci return regmap_read(st->regmap, reg, readval); 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci return regmap_write(st->regmap, reg, writeval); 125362306a36Sopenharmony_ci} 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_cistatic const struct iio_info ad74115_info = { 125662306a36Sopenharmony_ci .read_raw = ad74115_read_raw, 125762306a36Sopenharmony_ci .write_raw = ad74115_write_raw, 125862306a36Sopenharmony_ci .read_avail = ad74115_read_avail, 125962306a36Sopenharmony_ci .update_scan_mode = ad74115_update_scan_mode, 126062306a36Sopenharmony_ci .debugfs_reg_access = ad74115_reg_access, 126162306a36Sopenharmony_ci}; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci#define AD74115_DAC_CHANNEL(_type, index) \ 126462306a36Sopenharmony_ci { \ 126562306a36Sopenharmony_ci .type = (_type), \ 126662306a36Sopenharmony_ci .channel = (index), \ 126762306a36Sopenharmony_ci .indexed = 1, \ 126862306a36Sopenharmony_ci .output = 1, \ 126962306a36Sopenharmony_ci .scan_index = -1, \ 127062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ 127162306a36Sopenharmony_ci | BIT(IIO_CHAN_INFO_SCALE) \ 127262306a36Sopenharmony_ci | BIT(IIO_CHAN_INFO_OFFSET), \ 127362306a36Sopenharmony_ci } 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci#define _AD74115_ADC_CHANNEL(_type, index, extra_mask_separate) \ 127662306a36Sopenharmony_ci { \ 127762306a36Sopenharmony_ci .type = (_type), \ 127862306a36Sopenharmony_ci .channel = (index), \ 127962306a36Sopenharmony_ci .indexed = 1, \ 128062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ 128162306a36Sopenharmony_ci | BIT(IIO_CHAN_INFO_SAMP_FREQ) \ 128262306a36Sopenharmony_ci | (extra_mask_separate), \ 128362306a36Sopenharmony_ci .info_mask_separate_available = \ 128462306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 128562306a36Sopenharmony_ci .scan_index = index, \ 128662306a36Sopenharmony_ci .scan_type = { \ 128762306a36Sopenharmony_ci .sign = 'u', \ 128862306a36Sopenharmony_ci .realbits = 16, \ 128962306a36Sopenharmony_ci .storagebits = 32, \ 129062306a36Sopenharmony_ci .shift = 8, \ 129162306a36Sopenharmony_ci .endianness = IIO_BE, \ 129262306a36Sopenharmony_ci }, \ 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci#define AD74115_ADC_CHANNEL(_type, index) \ 129662306a36Sopenharmony_ci _AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE) \ 129762306a36Sopenharmony_ci | BIT(IIO_CHAN_INFO_OFFSET)) 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_voltage_input_channels[] = { 130062306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), 130162306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 130262306a36Sopenharmony_ci}; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_voltage_output_channels[] = { 130562306a36Sopenharmony_ci AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN), 130662306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1), 130762306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 130862306a36Sopenharmony_ci}; 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_current_input_channels[] = { 131162306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1), 131262306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 131362306a36Sopenharmony_ci}; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_current_output_channels[] = { 131662306a36Sopenharmony_ci AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN), 131762306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), 131862306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 131962306a36Sopenharmony_ci}; 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = { 132262306a36Sopenharmony_ci _AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1, 132362306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_PROCESSED)), 132462306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 132562306a36Sopenharmony_ci}; 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = { 132862306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1), 132962306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 133062306a36Sopenharmony_ci}; 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_digital_input_logic_channels[] = { 133362306a36Sopenharmony_ci AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR), 133462306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), 133562306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 133662306a36Sopenharmony_ci}; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_digital_input_loop_channels[] = { 133962306a36Sopenharmony_ci AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN), 134062306a36Sopenharmony_ci AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR), 134162306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), 134262306a36Sopenharmony_ci AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), 134362306a36Sopenharmony_ci}; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci#define _AD74115_CHANNELS(_channels) \ 134662306a36Sopenharmony_ci { \ 134762306a36Sopenharmony_ci .channels = _channels, \ 134862306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(_channels), \ 134962306a36Sopenharmony_ci } 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci#define AD74115_CHANNELS(name) \ 135262306a36Sopenharmony_ci _AD74115_CHANNELS(ad74115_ ## name ## _channels) 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_cistatic const struct ad74115_channels ad74115_channels_map[AD74115_CH_FUNC_NUM] = { 135562306a36Sopenharmony_ci [AD74115_CH_FUNC_HIGH_IMPEDANCE] = AD74115_CHANNELS(voltage_input), 135662306a36Sopenharmony_ci [AD74115_CH_FUNC_VOLTAGE_INPUT] = AD74115_CHANNELS(voltage_input), 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci [AD74115_CH_FUNC_VOLTAGE_OUTPUT] = AD74115_CHANNELS(voltage_output), 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci [AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER] = AD74115_CHANNELS(current_input), 136162306a36Sopenharmony_ci [AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER] = AD74115_CHANNELS(current_input), 136262306a36Sopenharmony_ci [AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER_HART] = AD74115_CHANNELS(current_input), 136362306a36Sopenharmony_ci [AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART] = AD74115_CHANNELS(current_input), 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci [AD74115_CH_FUNC_CURRENT_OUTPUT] = AD74115_CHANNELS(current_output), 136662306a36Sopenharmony_ci [AD74115_CH_FUNC_CURRENT_OUTPUT_HART] = AD74115_CHANNELS(current_output), 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci [AD74115_CH_FUNC_2_WIRE_RESISTANCE_INPUT] = AD74115_CHANNELS(2_wire_resistance_input), 136962306a36Sopenharmony_ci [AD74115_CH_FUNC_3_4_WIRE_RESISTANCE_INPUT] = AD74115_CHANNELS(3_4_wire_resistance_input), 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci [AD74115_CH_FUNC_DIGITAL_INPUT_LOGIC] = AD74115_CHANNELS(digital_input_logic), 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci [AD74115_CH_FUNC_DIGITAL_INPUT_LOOP_POWER] = AD74115_CHANNELS(digital_input_loop), 137462306a36Sopenharmony_ci}; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci#define AD74115_GPIO_MODE_FW_PROP(i) \ 137762306a36Sopenharmony_ci{ \ 137862306a36Sopenharmony_ci .name = "adi,gpio" __stringify(i) "-mode", \ 137962306a36Sopenharmony_ci .reg = AD74115_GPIO_CONFIG_X_REG(i), \ 138062306a36Sopenharmony_ci .mask = AD74115_GPIO_CONFIG_SELECT_MASK, \ 138162306a36Sopenharmony_ci .lookup_tbl = ad74115_gpio_mode_tbl, \ 138262306a36Sopenharmony_ci .lookup_tbl_len = ARRAY_SIZE(ad74115_gpio_mode_tbl), \ 138362306a36Sopenharmony_ci} 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_gpio_mode_fw_props[] = { 138662306a36Sopenharmony_ci AD74115_GPIO_MODE_FW_PROP(0), 138762306a36Sopenharmony_ci AD74115_GPIO_MODE_FW_PROP(1), 138862306a36Sopenharmony_ci AD74115_GPIO_MODE_FW_PROP(2), 138962306a36Sopenharmony_ci AD74115_GPIO_MODE_FW_PROP(3), 139062306a36Sopenharmony_ci}; 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_din_threshold_mode_fw_prop = 139362306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,digital-input-threshold-mode-fixed", 139462306a36Sopenharmony_ci AD74115_DIN_CONFIG2_REG, BIT(7)); 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_dac_bipolar_fw_prop = 139762306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,dac-bipolar", AD74115_OUTPUT_CONFIG_REG, BIT(7)); 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_ch_func_fw_prop = 140062306a36Sopenharmony_ci AD74115_FW_PROP("adi,ch-func", AD74115_CH_FUNC_MAX, 140162306a36Sopenharmony_ci AD74115_CH_FUNC_SETUP_REG, GENMASK(3, 0)); 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_rtd_mode_fw_prop = 140462306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,4-wire-rtd", AD74115_RTD3W4W_CONFIG_REG, BIT(3)); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_din_range_fw_prop = 140762306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,digital-input-sink-range-high", 140862306a36Sopenharmony_ci AD74115_DIN_CONFIG1_REG, BIT(12)); 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_ext2_burnout_current_fw_prop = 141162306a36Sopenharmony_ci AD74115_FW_PROP_TBL("adi,ext2-burnout-current-nanoamp", 141262306a36Sopenharmony_ci ad74115_burnout_current_na_tbl, 141362306a36Sopenharmony_ci AD74115_BURNOUT_CONFIG_REG, GENMASK(14, 12)); 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_ext1_burnout_current_fw_prop = 141662306a36Sopenharmony_ci AD74115_FW_PROP_TBL("adi,ext1-burnout-current-nanoamp", 141762306a36Sopenharmony_ci ad74115_burnout_current_na_tbl, 141862306a36Sopenharmony_ci AD74115_BURNOUT_CONFIG_REG, GENMASK(9, 7)); 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_viout_burnout_current_fw_prop = 142162306a36Sopenharmony_ci AD74115_FW_PROP_TBL("adi,viout-burnout-current-nanoamp", 142262306a36Sopenharmony_ci ad74115_viout_burnout_current_na_tbl, 142362306a36Sopenharmony_ci AD74115_BURNOUT_CONFIG_REG, GENMASK(4, 2)); 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_fw_props[] = { 142662306a36Sopenharmony_ci AD74115_FW_PROP("adi,conv2-mux", 3, 142762306a36Sopenharmony_ci AD74115_ADC_CONFIG_REG, GENMASK(3, 2)), 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci AD74115_FW_PROP_BOOL_NEG("adi,sense-agnd-buffer-low-power", 143062306a36Sopenharmony_ci AD74115_PWR_OPTIM_CONFIG_REG, BIT(4)), 143162306a36Sopenharmony_ci AD74115_FW_PROP_BOOL_NEG("adi,lf-buffer-low-power", 143262306a36Sopenharmony_ci AD74115_PWR_OPTIM_CONFIG_REG, BIT(3)), 143362306a36Sopenharmony_ci AD74115_FW_PROP_BOOL_NEG("adi,hf-buffer-low-power", 143462306a36Sopenharmony_ci AD74115_PWR_OPTIM_CONFIG_REG, BIT(2)), 143562306a36Sopenharmony_ci AD74115_FW_PROP_BOOL_NEG("adi,ext2-buffer-low-power", 143662306a36Sopenharmony_ci AD74115_PWR_OPTIM_CONFIG_REG, BIT(1)), 143762306a36Sopenharmony_ci AD74115_FW_PROP_BOOL_NEG("adi,ext1-buffer-low-power", 143862306a36Sopenharmony_ci AD74115_PWR_OPTIM_CONFIG_REG, BIT(0)), 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,comparator-invert", 144162306a36Sopenharmony_ci AD74115_DIN_CONFIG1_REG, BIT(14)), 144262306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,digital-input-debounce-mode-counter-reset", 144362306a36Sopenharmony_ci AD74115_DIN_CONFIG1_REG, BIT(6)), 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,digital-input-unbuffered", 144662306a36Sopenharmony_ci AD74115_DIN_CONFIG2_REG, BIT(10)), 144762306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,digital-input-short-circuit-detection", 144862306a36Sopenharmony_ci AD74115_DIN_CONFIG2_REG, BIT(9)), 144962306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,digital-input-open-circuit-detection", 145062306a36Sopenharmony_ci AD74115_DIN_CONFIG2_REG, BIT(8)), 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,dac-current-limit-low", 145362306a36Sopenharmony_ci AD74115_OUTPUT_CONFIG_REG, BIT(0)), 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,3-wire-rtd-excitation-swap", 145662306a36Sopenharmony_ci AD74115_RTD3W4W_CONFIG_REG, BIT(2)), 145762306a36Sopenharmony_ci AD74115_FW_PROP_TBL("adi,rtd-excitation-current-microamp", 145862306a36Sopenharmony_ci ad74115_rtd_excitation_current_ua_tbl, 145962306a36Sopenharmony_ci AD74115_RTD3W4W_CONFIG_REG, GENMASK(1, 0)), 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,ext2-burnout-current-polarity-sourcing", 146262306a36Sopenharmony_ci AD74115_BURNOUT_CONFIG_REG, BIT(11)), 146362306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,ext1-burnout-current-polarity-sourcing", 146462306a36Sopenharmony_ci AD74115_BURNOUT_CONFIG_REG, BIT(6)), 146562306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,viout-burnout-current-polarity-sourcing", 146662306a36Sopenharmony_ci AD74115_BURNOUT_CONFIG_REG, BIT(1)), 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci AD74115_FW_PROP_BOOL("adi,charge-pump", 146962306a36Sopenharmony_ci AD74115_CHARGE_PUMP_REG, BIT(0)), 147062306a36Sopenharmony_ci}; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_cistatic int ad74115_apply_fw_prop(struct ad74115_state *st, 147362306a36Sopenharmony_ci const struct ad74115_fw_prop *prop, u32 *retval) 147462306a36Sopenharmony_ci{ 147562306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 147662306a36Sopenharmony_ci u32 val = 0; 147762306a36Sopenharmony_ci int ret; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci if (prop->is_boolean) { 148062306a36Sopenharmony_ci val = device_property_read_bool(dev, prop->name); 148162306a36Sopenharmony_ci } else { 148262306a36Sopenharmony_ci ret = device_property_read_u32(dev, prop->name, &val); 148362306a36Sopenharmony_ci if (ret && prop->lookup_tbl) 148462306a36Sopenharmony_ci val = prop->lookup_tbl[0]; 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci *retval = val; 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci if (prop->negate) 149062306a36Sopenharmony_ci val = !val; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci if (prop->lookup_tbl) 149362306a36Sopenharmony_ci ret = _ad74115_find_tbl_index(prop->lookup_tbl, 149462306a36Sopenharmony_ci prop->lookup_tbl_len, val, &val); 149562306a36Sopenharmony_ci else if (prop->max && val > prop->max) 149662306a36Sopenharmony_ci ret = -EINVAL; 149762306a36Sopenharmony_ci else 149862306a36Sopenharmony_ci ret = 0; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci if (ret) 150162306a36Sopenharmony_ci return dev_err_probe(dev, -EINVAL, 150262306a36Sopenharmony_ci "Invalid value %u for prop %s\n", 150362306a36Sopenharmony_ci val, prop->name); 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci WARN(!prop->mask, "Prop %s mask is empty\n", prop->name); 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci val = (val << __ffs(prop->mask)) & prop->mask; 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci return regmap_update_bits(st->regmap, prop->reg, prop->mask, val); 151062306a36Sopenharmony_ci} 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_cistatic int ad74115_setup_adc_conv2_range(struct ad74115_state *st) 151362306a36Sopenharmony_ci{ 151462306a36Sopenharmony_ci unsigned int tbl_len = ARRAY_SIZE(ad74115_adc_range_tbl); 151562306a36Sopenharmony_ci const char *prop_name = "adi,conv2-range-microvolt"; 151662306a36Sopenharmony_ci s32 vals[2] = { 151762306a36Sopenharmony_ci ad74115_adc_range_tbl[0][0], 151862306a36Sopenharmony_ci ad74115_adc_range_tbl[0][1], 151962306a36Sopenharmony_ci }; 152062306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 152162306a36Sopenharmony_ci unsigned int i; 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci device_property_read_u32_array(dev, prop_name, vals, 2); 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci for (i = 0; i < tbl_len; i++) 152662306a36Sopenharmony_ci if (vals[0] == ad74115_adc_range_tbl[i][0] && 152762306a36Sopenharmony_ci vals[1] == ad74115_adc_range_tbl[i][1]) 152862306a36Sopenharmony_ci break; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci if (i == tbl_len) 153162306a36Sopenharmony_ci return dev_err_probe(dev, -EINVAL, 153262306a36Sopenharmony_ci "Invalid value %d, %d for prop %s\n", 153362306a36Sopenharmony_ci vals[0], vals[1], prop_name); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG, 153662306a36Sopenharmony_ci AD74115_ADC_CONFIG_CONV2_RANGE_MASK, 153762306a36Sopenharmony_ci FIELD_PREP(AD74115_ADC_CONFIG_CONV2_RANGE_MASK, i)); 153862306a36Sopenharmony_ci} 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_cistatic int ad74115_setup_iio_channels(struct iio_dev *indio_dev) 154162306a36Sopenharmony_ci{ 154262306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 154362306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 154462306a36Sopenharmony_ci struct iio_chan_spec *channels; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci channels = devm_kcalloc(dev, sizeof(*channels), 154762306a36Sopenharmony_ci indio_dev->num_channels, GFP_KERNEL); 154862306a36Sopenharmony_ci if (!channels) 154962306a36Sopenharmony_ci return -ENOMEM; 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci indio_dev->channels = channels; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci memcpy(channels, ad74115_channels_map[st->ch_func].channels, 155462306a36Sopenharmony_ci sizeof(*channels) * ad74115_channels_map[st->ch_func].num_channels); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci if (channels[0].output && channels[0].channel == AD74115_DAC_CH_MAIN && 155762306a36Sopenharmony_ci channels[0].type == IIO_VOLTAGE && !st->dac_hart_slew) { 155862306a36Sopenharmony_ci channels[0].info_mask_separate |= BIT(IIO_CHAN_INFO_SAMP_FREQ); 155962306a36Sopenharmony_ci channels[0].info_mask_separate_available |= BIT(IIO_CHAN_INFO_SAMP_FREQ); 156062306a36Sopenharmony_ci } 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci return 0; 156362306a36Sopenharmony_ci} 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_cistatic int ad74115_setup_gpio_chip(struct ad74115_state *st) 156662306a36Sopenharmony_ci{ 156762306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci if (!st->gpio_valid_mask) 157062306a36Sopenharmony_ci return 0; 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci st->gc = (struct gpio_chip) { 157362306a36Sopenharmony_ci .owner = THIS_MODULE, 157462306a36Sopenharmony_ci .label = AD74115_NAME, 157562306a36Sopenharmony_ci .base = -1, 157662306a36Sopenharmony_ci .ngpio = AD74115_GPIO_NUM, 157762306a36Sopenharmony_ci .parent = dev, 157862306a36Sopenharmony_ci .can_sleep = true, 157962306a36Sopenharmony_ci .init_valid_mask = ad74115_gpio_init_valid_mask, 158062306a36Sopenharmony_ci .get_direction = ad74115_gpio_get_direction, 158162306a36Sopenharmony_ci .direction_input = ad74115_gpio_direction_input, 158262306a36Sopenharmony_ci .direction_output = ad74115_gpio_direction_output, 158362306a36Sopenharmony_ci .get = ad74115_gpio_get, 158462306a36Sopenharmony_ci .set = ad74115_gpio_set, 158562306a36Sopenharmony_ci }; 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci return devm_gpiochip_add_data(dev, &st->gc, st); 158862306a36Sopenharmony_ci} 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_cistatic int ad74115_setup_comp_gpio_chip(struct ad74115_state *st) 159162306a36Sopenharmony_ci{ 159262306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 159362306a36Sopenharmony_ci u32 val; 159462306a36Sopenharmony_ci int ret; 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci ret = regmap_read(st->regmap, AD74115_DIN_CONFIG1_REG, &val); 159762306a36Sopenharmony_ci if (ret) 159862306a36Sopenharmony_ci return ret; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci if (!(val & AD74115_DIN_COMPARATOR_EN_MASK)) 160162306a36Sopenharmony_ci return 0; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci st->comp_gc = (struct gpio_chip) { 160462306a36Sopenharmony_ci .owner = THIS_MODULE, 160562306a36Sopenharmony_ci .label = AD74115_NAME, 160662306a36Sopenharmony_ci .base = -1, 160762306a36Sopenharmony_ci .ngpio = 1, 160862306a36Sopenharmony_ci .parent = dev, 160962306a36Sopenharmony_ci .can_sleep = true, 161062306a36Sopenharmony_ci .get_direction = ad74115_comp_gpio_get_direction, 161162306a36Sopenharmony_ci .get = ad74115_comp_gpio_get, 161262306a36Sopenharmony_ci .set_config = ad74115_comp_gpio_set_config, 161362306a36Sopenharmony_ci }; 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci return devm_gpiochip_add_data(dev, &st->comp_gc, st); 161662306a36Sopenharmony_ci} 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_cistatic int ad74115_setup(struct iio_dev *indio_dev) 161962306a36Sopenharmony_ci{ 162062306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 162162306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 162262306a36Sopenharmony_ci u32 val, din_range_high; 162362306a36Sopenharmony_ci unsigned int i; 162462306a36Sopenharmony_ci int ret; 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_ch_func_fw_prop, &val); 162762306a36Sopenharmony_ci if (ret) 162862306a36Sopenharmony_ci return ret; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci indio_dev->num_channels += ad74115_channels_map[val].num_channels; 163162306a36Sopenharmony_ci st->ch_func = val; 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci ret = ad74115_setup_adc_conv2_range(st); 163462306a36Sopenharmony_ci if (ret) 163562306a36Sopenharmony_ci return ret; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci val = device_property_read_bool(dev, "adi,dac-hart-slew"); 163862306a36Sopenharmony_ci if (val) { 163962306a36Sopenharmony_ci st->dac_hart_slew = val; 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, AD74115_OUTPUT_CONFIG_REG, 164262306a36Sopenharmony_ci AD74115_OUTPUT_SLEW_EN_MASK, 164362306a36Sopenharmony_ci FIELD_PREP(AD74115_OUTPUT_SLEW_EN_MASK, 164462306a36Sopenharmony_ci AD74115_SLEW_MODE_HART)); 164562306a36Sopenharmony_ci if (ret) 164662306a36Sopenharmony_ci return ret; 164762306a36Sopenharmony_ci } 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_din_range_fw_prop, 165062306a36Sopenharmony_ci &din_range_high); 165162306a36Sopenharmony_ci if (ret) 165262306a36Sopenharmony_ci return ret; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci ret = device_property_read_u32(dev, "adi,digital-input-sink-microamp", &val); 165562306a36Sopenharmony_ci if (!ret) { 165662306a36Sopenharmony_ci if (din_range_high) 165762306a36Sopenharmony_ci val = DIV_ROUND_CLOSEST(val, AD74115_DIN_SINK_LOW_STEP); 165862306a36Sopenharmony_ci else 165962306a36Sopenharmony_ci val = DIV_ROUND_CLOSEST(val, AD74115_DIN_SINK_HIGH_STEP); 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci if (val > AD74115_DIN_SINK_MAX) 166262306a36Sopenharmony_ci val = AD74115_DIN_SINK_MAX; 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, AD74115_DIN_CONFIG1_REG, 166562306a36Sopenharmony_ci AD74115_DIN_SINK_MASK, 166662306a36Sopenharmony_ci FIELD_PREP(AD74115_DIN_SINK_MASK, val)); 166762306a36Sopenharmony_ci if (ret) 166862306a36Sopenharmony_ci return ret; 166962306a36Sopenharmony_ci } 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_din_threshold_mode_fw_prop, &val); 167262306a36Sopenharmony_ci if (ret) 167362306a36Sopenharmony_ci return ret; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci if (val == AD74115_DIN_THRESHOLD_MODE_AVDD) { 167662306a36Sopenharmony_ci ret = regulator_get_voltage(st->avdd); 167762306a36Sopenharmony_ci if (ret < 0) 167862306a36Sopenharmony_ci return ret; 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci st->avdd_mv = ret / 1000; 168162306a36Sopenharmony_ci } 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci st->din_threshold_mode = val; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_dac_bipolar_fw_prop, &val); 168662306a36Sopenharmony_ci if (ret) 168762306a36Sopenharmony_ci return ret; 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci st->dac_bipolar = val; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_rtd_mode_fw_prop, &val); 169262306a36Sopenharmony_ci if (ret) 169362306a36Sopenharmony_ci return ret; 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci st->rtd_mode_4_wire = val; 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_ext2_burnout_current_fw_prop, &val); 169862306a36Sopenharmony_ci if (ret) 169962306a36Sopenharmony_ci return ret; 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci if (val) { 170262306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG, 170362306a36Sopenharmony_ci AD74115_BURNOUT_EXT2_EN_MASK, 170462306a36Sopenharmony_ci FIELD_PREP(AD74115_BURNOUT_EXT2_EN_MASK, 1)); 170562306a36Sopenharmony_ci if (ret) 170662306a36Sopenharmony_ci return ret; 170762306a36Sopenharmony_ci } 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_ext1_burnout_current_fw_prop, &val); 171062306a36Sopenharmony_ci if (ret) 171162306a36Sopenharmony_ci return ret; 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci if (val) { 171462306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG, 171562306a36Sopenharmony_ci AD74115_BURNOUT_EXT1_EN_MASK, 171662306a36Sopenharmony_ci FIELD_PREP(AD74115_BURNOUT_EXT1_EN_MASK, 1)); 171762306a36Sopenharmony_ci if (ret) 171862306a36Sopenharmony_ci return ret; 171962306a36Sopenharmony_ci } 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_viout_burnout_current_fw_prop, &val); 172262306a36Sopenharmony_ci if (ret) 172362306a36Sopenharmony_ci return ret; 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci if (val) { 172662306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG, 172762306a36Sopenharmony_ci AD74115_BURNOUT_VIOUT_EN_MASK, 172862306a36Sopenharmony_ci FIELD_PREP(AD74115_BURNOUT_VIOUT_EN_MASK, 1)); 172962306a36Sopenharmony_ci if (ret) 173062306a36Sopenharmony_ci return ret; 173162306a36Sopenharmony_ci } 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ci for (i = 0; i < AD74115_GPIO_NUM; i++) { 173462306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_gpio_mode_fw_props[i], &val); 173562306a36Sopenharmony_ci if (ret) 173662306a36Sopenharmony_ci return ret; 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci if (val == AD74115_GPIO_MODE_LOGIC) 173962306a36Sopenharmony_ci st->gpio_valid_mask |= BIT(i); 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ad74115_fw_props); i++) { 174362306a36Sopenharmony_ci ret = ad74115_apply_fw_prop(st, &ad74115_fw_props[i], &val); 174462306a36Sopenharmony_ci if (ret) 174562306a36Sopenharmony_ci return ret; 174662306a36Sopenharmony_ci } 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci ret = ad74115_setup_gpio_chip(st); 174962306a36Sopenharmony_ci if (ret) 175062306a36Sopenharmony_ci return ret; 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci ret = ad74115_setup_comp_gpio_chip(st); 175362306a36Sopenharmony_ci if (ret) 175462306a36Sopenharmony_ci return ret; 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci return ad74115_setup_iio_channels(indio_dev); 175762306a36Sopenharmony_ci} 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_cistatic int ad74115_reset(struct ad74115_state *st) 176062306a36Sopenharmony_ci{ 176162306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 176262306a36Sopenharmony_ci struct gpio_desc *reset_gpio; 176362306a36Sopenharmony_ci int ret; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 176662306a36Sopenharmony_ci if (IS_ERR(reset_gpio)) 176762306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(reset_gpio), 176862306a36Sopenharmony_ci "Failed to find reset GPIO\n"); 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci if (reset_gpio) { 177162306a36Sopenharmony_ci fsleep(100); 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci gpiod_set_value_cansleep(reset_gpio, 0); 177462306a36Sopenharmony_ci } else { 177562306a36Sopenharmony_ci ret = regmap_write(st->regmap, AD74115_CMD_KEY_REG, 177662306a36Sopenharmony_ci AD74115_CMD_KEY_RESET1); 177762306a36Sopenharmony_ci if (ret) 177862306a36Sopenharmony_ci return ret; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci ret = regmap_write(st->regmap, AD74115_CMD_KEY_REG, 178162306a36Sopenharmony_ci AD74115_CMD_KEY_RESET2); 178262306a36Sopenharmony_ci if (ret) 178362306a36Sopenharmony_ci return ret; 178462306a36Sopenharmony_ci } 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci fsleep(1000); 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci return 0; 178962306a36Sopenharmony_ci} 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_cistatic void ad74115_regulator_disable(void *data) 179262306a36Sopenharmony_ci{ 179362306a36Sopenharmony_ci regulator_disable(data); 179462306a36Sopenharmony_ci} 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_cistatic int ad74115_setup_trigger(struct iio_dev *indio_dev) 179762306a36Sopenharmony_ci{ 179862306a36Sopenharmony_ci struct ad74115_state *st = iio_priv(indio_dev); 179962306a36Sopenharmony_ci struct device *dev = &st->spi->dev; 180062306a36Sopenharmony_ci int ret; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci st->irq = fwnode_irq_get_byname(dev_fwnode(dev), "adc_rdy"); 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci if (st->irq == -EPROBE_DEFER) 180562306a36Sopenharmony_ci return -EPROBE_DEFER; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci if (st->irq < 0) { 180862306a36Sopenharmony_ci st->irq = 0; 180962306a36Sopenharmony_ci return 0; 181062306a36Sopenharmony_ci } 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci ret = devm_request_irq(dev, st->irq, ad74115_adc_data_interrupt, 181362306a36Sopenharmony_ci 0, AD74115_NAME, indio_dev); 181462306a36Sopenharmony_ci if (ret) 181562306a36Sopenharmony_ci return ret; 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", AD74115_NAME, 181862306a36Sopenharmony_ci iio_device_id(indio_dev)); 181962306a36Sopenharmony_ci if (!st->trig) 182062306a36Sopenharmony_ci return -ENOMEM; 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci st->trig->ops = &ad74115_trigger_ops; 182362306a36Sopenharmony_ci iio_trigger_set_drvdata(st->trig, st); 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci ret = devm_iio_trigger_register(dev, st->trig); 182662306a36Sopenharmony_ci if (ret) 182762306a36Sopenharmony_ci return ret; 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci indio_dev->trig = iio_trigger_get(st->trig); 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci return 0; 183262306a36Sopenharmony_ci} 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_cistatic int ad74115_probe(struct spi_device *spi) 183562306a36Sopenharmony_ci{ 183662306a36Sopenharmony_ci static const char * const regulator_names[] = { 183762306a36Sopenharmony_ci "avcc", "dvcc", "dovdd", "refin", 183862306a36Sopenharmony_ci }; 183962306a36Sopenharmony_ci struct device *dev = &spi->dev; 184062306a36Sopenharmony_ci struct ad74115_state *st; 184162306a36Sopenharmony_ci struct iio_dev *indio_dev; 184262306a36Sopenharmony_ci int ret; 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); 184562306a36Sopenharmony_ci if (!indio_dev) 184662306a36Sopenharmony_ci return -ENOMEM; 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci st = iio_priv(indio_dev); 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ci st->spi = spi; 185162306a36Sopenharmony_ci mutex_init(&st->lock); 185262306a36Sopenharmony_ci init_completion(&st->adc_data_completion); 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci indio_dev->name = AD74115_NAME; 185562306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 185662306a36Sopenharmony_ci indio_dev->info = &ad74115_info; 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci st->avdd = devm_regulator_get(dev, "avdd"); 185962306a36Sopenharmony_ci if (IS_ERR(st->avdd)) 186062306a36Sopenharmony_ci return PTR_ERR(st->avdd); 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci ret = regulator_enable(st->avdd); 186362306a36Sopenharmony_ci if (ret) { 186462306a36Sopenharmony_ci dev_err(dev, "Failed to enable avdd regulator\n"); 186562306a36Sopenharmony_ci return ret; 186662306a36Sopenharmony_ci } 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci ret = devm_add_action_or_reset(dev, ad74115_regulator_disable, st->avdd); 186962306a36Sopenharmony_ci if (ret) 187062306a36Sopenharmony_ci return ret; 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names), 187362306a36Sopenharmony_ci regulator_names); 187462306a36Sopenharmony_ci if (ret) 187562306a36Sopenharmony_ci return ret; 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_ci st->regmap = devm_regmap_init(dev, NULL, st, &ad74115_regmap_config); 187862306a36Sopenharmony_ci if (IS_ERR(st->regmap)) 187962306a36Sopenharmony_ci return PTR_ERR(st->regmap); 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci ret = ad74115_reset(st); 188262306a36Sopenharmony_ci if (ret) 188362306a36Sopenharmony_ci return ret; 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci ret = ad74115_setup(indio_dev); 188662306a36Sopenharmony_ci if (ret) 188762306a36Sopenharmony_ci return ret; 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci ret = ad74115_setup_trigger(indio_dev); 189062306a36Sopenharmony_ci if (ret) 189162306a36Sopenharmony_ci return ret; 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, 189462306a36Sopenharmony_ci ad74115_trigger_handler, 189562306a36Sopenharmony_ci &ad74115_buffer_ops); 189662306a36Sopenharmony_ci if (ret) 189762306a36Sopenharmony_ci return ret; 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci return devm_iio_device_register(dev, indio_dev); 190062306a36Sopenharmony_ci} 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_cistatic int ad74115_unregister_driver(struct spi_driver *spi) 190362306a36Sopenharmony_ci{ 190462306a36Sopenharmony_ci spi_unregister_driver(spi); 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci return 0; 190762306a36Sopenharmony_ci} 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_cistatic int __init ad74115_register_driver(struct spi_driver *spi) 191062306a36Sopenharmony_ci{ 191162306a36Sopenharmony_ci crc8_populate_msb(ad74115_crc8_table, AD74115_CRC_POLYNOMIAL); 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci return spi_register_driver(spi); 191462306a36Sopenharmony_ci} 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_cistatic const struct spi_device_id ad74115_spi_id[] = { 191762306a36Sopenharmony_ci { "ad74115h" }, 191862306a36Sopenharmony_ci { } 191962306a36Sopenharmony_ci}; 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad74115_spi_id); 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_cistatic const struct of_device_id ad74115_dt_id[] = { 192462306a36Sopenharmony_ci { .compatible = "adi,ad74115h" }, 192562306a36Sopenharmony_ci { } 192662306a36Sopenharmony_ci}; 192762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad74115_dt_id); 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_cistatic struct spi_driver ad74115_driver = { 193062306a36Sopenharmony_ci .driver = { 193162306a36Sopenharmony_ci .name = "ad74115", 193262306a36Sopenharmony_ci .of_match_table = ad74115_dt_id, 193362306a36Sopenharmony_ci }, 193462306a36Sopenharmony_ci .probe = ad74115_probe, 193562306a36Sopenharmony_ci .id_table = ad74115_spi_id, 193662306a36Sopenharmony_ci}; 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_cimodule_driver(ad74115_driver, 193962306a36Sopenharmony_ci ad74115_register_driver, ad74115_unregister_driver); 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ciMODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>"); 194262306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD74115 ADDAC"); 194362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1944