162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Texas Instruments TSC2046 SPI ADC driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2021 Oleksij Rempel <kernel@pengutronix.de>, Pengutronix 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bitfield.h> 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1262306a36Sopenharmony_ci#include <linux/spi/spi.h> 1362306a36Sopenharmony_ci#include <linux/units.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <asm/unaligned.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/iio/buffer.h> 1862306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 1962306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 2062306a36Sopenharmony_ci#include <linux/iio/trigger.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * The PENIRQ of TSC2046 controller is implemented as level shifter attached to 2462306a36Sopenharmony_ci * the X+ line. If voltage of the X+ line reaches a specific level the IRQ will 2562306a36Sopenharmony_ci * be activated or deactivated. 2662306a36Sopenharmony_ci * To make this kind of IRQ reusable as trigger following additions were 2762306a36Sopenharmony_ci * implemented: 2862306a36Sopenharmony_ci * - rate limiting: 2962306a36Sopenharmony_ci * For typical touchscreen use case, we need to trigger about each 10ms. 3062306a36Sopenharmony_ci * - hrtimer: 3162306a36Sopenharmony_ci * Continue triggering at least once after the IRQ was deactivated. Then 3262306a36Sopenharmony_ci * deactivate this trigger to stop sampling in order to reduce power 3362306a36Sopenharmony_ci * consumption. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define TI_TSC2046_NAME "tsc2046" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* This driver doesn't aim at the peak continuous sample rate */ 3962306a36Sopenharmony_ci#define TI_TSC2046_MAX_SAMPLE_RATE 125000 4062306a36Sopenharmony_ci#define TI_TSC2046_SAMPLE_BITS \ 4162306a36Sopenharmony_ci BITS_PER_TYPE(struct tsc2046_adc_atom) 4262306a36Sopenharmony_ci#define TI_TSC2046_MAX_CLK_FREQ \ 4362306a36Sopenharmony_ci (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define TI_TSC2046_SAMPLE_INTERVAL_US 10000 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define TI_TSC2046_START BIT(7) 4862306a36Sopenharmony_ci#define TI_TSC2046_ADDR GENMASK(6, 4) 4962306a36Sopenharmony_ci#define TI_TSC2046_ADDR_TEMP1 7 5062306a36Sopenharmony_ci#define TI_TSC2046_ADDR_AUX 6 5162306a36Sopenharmony_ci#define TI_TSC2046_ADDR_X 5 5262306a36Sopenharmony_ci#define TI_TSC2046_ADDR_Z2 4 5362306a36Sopenharmony_ci#define TI_TSC2046_ADDR_Z1 3 5462306a36Sopenharmony_ci#define TI_TSC2046_ADDR_VBAT 2 5562306a36Sopenharmony_ci#define TI_TSC2046_ADDR_Y 1 5662306a36Sopenharmony_ci#define TI_TSC2046_ADDR_TEMP0 0 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* 5962306a36Sopenharmony_ci * The mode bit sets the resolution of the ADC. With this bit low, the next 6062306a36Sopenharmony_ci * conversion has 12-bit resolution, whereas with this bit high, the next 6162306a36Sopenharmony_ci * conversion has 8-bit resolution. This driver is optimized for 12-bit mode. 6262306a36Sopenharmony_ci * So, for this driver, this bit should stay zero. 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci#define TI_TSC2046_8BIT_MODE BIT(3) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* 6762306a36Sopenharmony_ci * SER/DFR - The SER/DFR bit controls the reference mode, either single-ended 6862306a36Sopenharmony_ci * (high) or differential (low). 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ci#define TI_TSC2046_SER BIT(2) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* 7362306a36Sopenharmony_ci * If VREF_ON and ADC_ON are both zero, then the chip operates in 7462306a36Sopenharmony_ci * auto-wake/suspend mode. In most case this bits should stay zero. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci#define TI_TSC2046_PD1_VREF_ON BIT(1) 7762306a36Sopenharmony_ci#define TI_TSC2046_PD0_ADC_ON BIT(0) 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * All supported devices can do 8 or 12bit resolution. This driver 8162306a36Sopenharmony_ci * supports only 12bit mode, here we have a 16bit data transfer, where 8262306a36Sopenharmony_ci * the MSB and the 3 LSB are 0. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci#define TI_TSC2046_DATA_12BIT GENMASK(14, 3) 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define TI_TSC2046_MAX_CHAN 8 8762306a36Sopenharmony_ci#define TI_TSC2046_MIN_POLL_CNT 3 8862306a36Sopenharmony_ci#define TI_TSC2046_EXT_POLL_CNT 3 8962306a36Sopenharmony_ci#define TI_TSC2046_POLL_CNT \ 9062306a36Sopenharmony_ci (TI_TSC2046_MIN_POLL_CNT + TI_TSC2046_EXT_POLL_CNT) 9162306a36Sopenharmony_ci#define TI_TSC2046_INT_VREF 2500 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* Represents a HW sample */ 9462306a36Sopenharmony_cistruct tsc2046_adc_atom { 9562306a36Sopenharmony_ci /* 9662306a36Sopenharmony_ci * Command transmitted to the controller. This field is empty on the RX 9762306a36Sopenharmony_ci * buffer. 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci u8 cmd; 10062306a36Sopenharmony_ci /* 10162306a36Sopenharmony_ci * Data received from the controller. This field is empty for the TX 10262306a36Sopenharmony_ci * buffer 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_ci __be16 data; 10562306a36Sopenharmony_ci} __packed; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/* Layout of atomic buffers within big buffer */ 10862306a36Sopenharmony_cistruct tsc2046_adc_group_layout { 10962306a36Sopenharmony_ci /* Group offset within the SPI RX buffer */ 11062306a36Sopenharmony_ci unsigned int offset; 11162306a36Sopenharmony_ci /* 11262306a36Sopenharmony_ci * Amount of tsc2046_adc_atom structs within the same command gathered 11362306a36Sopenharmony_ci * within same group. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci unsigned int count; 11662306a36Sopenharmony_ci /* 11762306a36Sopenharmony_ci * Settling samples (tsc2046_adc_atom structs) which should be skipped 11862306a36Sopenharmony_ci * before good samples will start. 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ci unsigned int skip; 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistruct tsc2046_adc_dcfg { 12462306a36Sopenharmony_ci const struct iio_chan_spec *channels; 12562306a36Sopenharmony_ci unsigned int num_channels; 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistruct tsc2046_adc_ch_cfg { 12962306a36Sopenharmony_ci unsigned int settling_time_us; 13062306a36Sopenharmony_ci unsigned int oversampling_ratio; 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cienum tsc2046_state { 13462306a36Sopenharmony_ci TSC2046_STATE_SHUTDOWN, 13562306a36Sopenharmony_ci TSC2046_STATE_STANDBY, 13662306a36Sopenharmony_ci TSC2046_STATE_POLL, 13762306a36Sopenharmony_ci TSC2046_STATE_POLL_IRQ_DISABLE, 13862306a36Sopenharmony_ci TSC2046_STATE_ENABLE_IRQ, 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistruct tsc2046_adc_priv { 14262306a36Sopenharmony_ci struct spi_device *spi; 14362306a36Sopenharmony_ci const struct tsc2046_adc_dcfg *dcfg; 14462306a36Sopenharmony_ci struct regulator *vref_reg; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci struct iio_trigger *trig; 14762306a36Sopenharmony_ci struct hrtimer trig_timer; 14862306a36Sopenharmony_ci enum tsc2046_state state; 14962306a36Sopenharmony_ci int poll_cnt; 15062306a36Sopenharmony_ci spinlock_t state_lock; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci struct spi_transfer xfer; 15362306a36Sopenharmony_ci struct spi_message msg; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci struct { 15662306a36Sopenharmony_ci /* Scan data for each channel */ 15762306a36Sopenharmony_ci u16 data[TI_TSC2046_MAX_CHAN]; 15862306a36Sopenharmony_ci /* Timestamp */ 15962306a36Sopenharmony_ci s64 ts __aligned(8); 16062306a36Sopenharmony_ci } scan_buf; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* 16362306a36Sopenharmony_ci * Lock to protect the layout and the SPI transfer buffer. 16462306a36Sopenharmony_ci * tsc2046_adc_group_layout can be changed within update_scan_mode(), 16562306a36Sopenharmony_ci * in this case the l[] and tx/rx buffer will be out of sync to each 16662306a36Sopenharmony_ci * other. 16762306a36Sopenharmony_ci */ 16862306a36Sopenharmony_ci struct mutex slock; 16962306a36Sopenharmony_ci struct tsc2046_adc_group_layout l[TI_TSC2046_MAX_CHAN]; 17062306a36Sopenharmony_ci struct tsc2046_adc_atom *rx; 17162306a36Sopenharmony_ci struct tsc2046_adc_atom *tx; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci unsigned int count; 17462306a36Sopenharmony_ci unsigned int groups; 17562306a36Sopenharmony_ci u32 effective_speed_hz; 17662306a36Sopenharmony_ci u32 scan_interval_us; 17762306a36Sopenharmony_ci u32 time_per_scan_us; 17862306a36Sopenharmony_ci u32 time_per_bit_ns; 17962306a36Sopenharmony_ci unsigned int vref_mv; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci struct tsc2046_adc_ch_cfg ch_cfg[TI_TSC2046_MAX_CHAN]; 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define TI_TSC2046_V_CHAN(index, bits, name) \ 18562306a36Sopenharmony_ci{ \ 18662306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 18762306a36Sopenharmony_ci .indexed = 1, \ 18862306a36Sopenharmony_ci .channel = index, \ 18962306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 19062306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 19162306a36Sopenharmony_ci .datasheet_name = "#name", \ 19262306a36Sopenharmony_ci .scan_index = index, \ 19362306a36Sopenharmony_ci .scan_type = { \ 19462306a36Sopenharmony_ci .sign = 'u', \ 19562306a36Sopenharmony_ci .realbits = bits, \ 19662306a36Sopenharmony_ci .storagebits = 16, \ 19762306a36Sopenharmony_ci .endianness = IIO_CPU, \ 19862306a36Sopenharmony_ci }, \ 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#define DECLARE_TI_TSC2046_8_CHANNELS(name, bits) \ 20262306a36Sopenharmony_ciconst struct iio_chan_spec name ## _channels[] = { \ 20362306a36Sopenharmony_ci TI_TSC2046_V_CHAN(0, bits, TEMP0), \ 20462306a36Sopenharmony_ci TI_TSC2046_V_CHAN(1, bits, Y), \ 20562306a36Sopenharmony_ci TI_TSC2046_V_CHAN(2, bits, VBAT), \ 20662306a36Sopenharmony_ci TI_TSC2046_V_CHAN(3, bits, Z1), \ 20762306a36Sopenharmony_ci TI_TSC2046_V_CHAN(4, bits, Z2), \ 20862306a36Sopenharmony_ci TI_TSC2046_V_CHAN(5, bits, X), \ 20962306a36Sopenharmony_ci TI_TSC2046_V_CHAN(6, bits, AUX), \ 21062306a36Sopenharmony_ci TI_TSC2046_V_CHAN(7, bits, TEMP1), \ 21162306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(8), \ 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic DECLARE_TI_TSC2046_8_CHANNELS(tsc2046_adc, 12); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic const struct tsc2046_adc_dcfg tsc2046_adc_dcfg_tsc2046e = { 21762306a36Sopenharmony_ci .channels = tsc2046_adc_channels, 21862306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(tsc2046_adc_channels), 21962306a36Sopenharmony_ci}; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci/* 22262306a36Sopenharmony_ci * Convert time to a number of samples which can be transferred within this 22362306a36Sopenharmony_ci * time. 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_cistatic unsigned int tsc2046_adc_time_to_count(struct tsc2046_adc_priv *priv, 22662306a36Sopenharmony_ci unsigned long time) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci unsigned int bit_count, sample_count; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci bit_count = DIV_ROUND_UP(time * NSEC_PER_USEC, priv->time_per_bit_ns); 23162306a36Sopenharmony_ci sample_count = DIV_ROUND_UP(bit_count, TI_TSC2046_SAMPLE_BITS); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci dev_dbg(&priv->spi->dev, "Effective speed %u, time per bit: %u, count bits: %u, count samples: %u\n", 23462306a36Sopenharmony_ci priv->effective_speed_hz, priv->time_per_bit_ns, 23562306a36Sopenharmony_ci bit_count, sample_count); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci return sample_count; 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic u8 tsc2046_adc_get_cmd(struct tsc2046_adc_priv *priv, int ch_idx, 24162306a36Sopenharmony_ci bool keep_power) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci u32 pd; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* 24662306a36Sopenharmony_ci * if PD bits are 0, controller will automatically disable ADC, VREF and 24762306a36Sopenharmony_ci * enable IRQ. 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ci if (keep_power) 25062306a36Sopenharmony_ci pd = TI_TSC2046_PD0_ADC_ON; 25162306a36Sopenharmony_ci else 25262306a36Sopenharmony_ci pd = 0; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci switch (ch_idx) { 25562306a36Sopenharmony_ci case TI_TSC2046_ADDR_TEMP1: 25662306a36Sopenharmony_ci case TI_TSC2046_ADDR_AUX: 25762306a36Sopenharmony_ci case TI_TSC2046_ADDR_VBAT: 25862306a36Sopenharmony_ci case TI_TSC2046_ADDR_TEMP0: 25962306a36Sopenharmony_ci pd |= TI_TSC2046_SER; 26062306a36Sopenharmony_ci if (!priv->vref_reg) 26162306a36Sopenharmony_ci pd |= TI_TSC2046_PD1_VREF_ON; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci return TI_TSC2046_START | FIELD_PREP(TI_TSC2046_ADDR, ch_idx) | pd; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic u16 tsc2046_adc_get_value(struct tsc2046_adc_atom *buf) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci return FIELD_GET(TI_TSC2046_DATA_12BIT, get_unaligned_be16(&buf->data)); 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic int tsc2046_adc_read_one(struct tsc2046_adc_priv *priv, int ch_idx, 27362306a36Sopenharmony_ci u32 *effective_speed_hz) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci struct tsc2046_adc_ch_cfg *ch = &priv->ch_cfg[ch_idx]; 27662306a36Sopenharmony_ci struct tsc2046_adc_atom *rx_buf, *tx_buf; 27762306a36Sopenharmony_ci unsigned int val, val_normalized = 0; 27862306a36Sopenharmony_ci int ret, i, count_skip = 0, max_count; 27962306a36Sopenharmony_ci struct spi_transfer xfer; 28062306a36Sopenharmony_ci struct spi_message msg; 28162306a36Sopenharmony_ci u8 cmd; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (!effective_speed_hz) { 28462306a36Sopenharmony_ci count_skip = tsc2046_adc_time_to_count(priv, ch->settling_time_us); 28562306a36Sopenharmony_ci max_count = count_skip + ch->oversampling_ratio; 28662306a36Sopenharmony_ci } else { 28762306a36Sopenharmony_ci max_count = 1; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (sizeof(*tx_buf) * max_count > PAGE_SIZE) 29162306a36Sopenharmony_ci return -ENOSPC; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci tx_buf = kcalloc(max_count, sizeof(*tx_buf), GFP_KERNEL); 29462306a36Sopenharmony_ci if (!tx_buf) 29562306a36Sopenharmony_ci return -ENOMEM; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci rx_buf = kcalloc(max_count, sizeof(*rx_buf), GFP_KERNEL); 29862306a36Sopenharmony_ci if (!rx_buf) { 29962306a36Sopenharmony_ci ret = -ENOMEM; 30062306a36Sopenharmony_ci goto free_tx; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * Do not enable automatic power down on working samples. Otherwise the 30562306a36Sopenharmony_ci * plates will never be completely charged. 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_ci cmd = tsc2046_adc_get_cmd(priv, ch_idx, true); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci for (i = 0; i < max_count - 1; i++) 31062306a36Sopenharmony_ci tx_buf[i].cmd = cmd; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci /* automatically power down on last sample */ 31362306a36Sopenharmony_ci tx_buf[i].cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci memset(&xfer, 0, sizeof(xfer)); 31662306a36Sopenharmony_ci xfer.tx_buf = tx_buf; 31762306a36Sopenharmony_ci xfer.rx_buf = rx_buf; 31862306a36Sopenharmony_ci xfer.len = sizeof(*tx_buf) * max_count; 31962306a36Sopenharmony_ci spi_message_init_with_transfers(&msg, &xfer, 1); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* 32262306a36Sopenharmony_ci * We aren't using spi_write_then_read() because we need to be able 32362306a36Sopenharmony_ci * to get hold of the effective_speed_hz from the xfer 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_ci ret = spi_sync(priv->spi, &msg); 32662306a36Sopenharmony_ci if (ret) { 32762306a36Sopenharmony_ci dev_err_ratelimited(&priv->spi->dev, "SPI transfer failed %pe\n", 32862306a36Sopenharmony_ci ERR_PTR(ret)); 32962306a36Sopenharmony_ci goto free_bufs; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci if (effective_speed_hz) 33362306a36Sopenharmony_ci *effective_speed_hz = xfer.effective_speed_hz; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci for (i = 0; i < max_count - count_skip; i++) { 33662306a36Sopenharmony_ci val = tsc2046_adc_get_value(&rx_buf[count_skip + i]); 33762306a36Sopenharmony_ci val_normalized += val; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci ret = DIV_ROUND_UP(val_normalized, max_count - count_skip); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cifree_bufs: 34362306a36Sopenharmony_ci kfree(rx_buf); 34462306a36Sopenharmony_cifree_tx: 34562306a36Sopenharmony_ci kfree(tx_buf); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return ret; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic size_t tsc2046_adc_group_set_layout(struct tsc2046_adc_priv *priv, 35162306a36Sopenharmony_ci unsigned int group, 35262306a36Sopenharmony_ci unsigned int ch_idx) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct tsc2046_adc_ch_cfg *ch = &priv->ch_cfg[ch_idx]; 35562306a36Sopenharmony_ci struct tsc2046_adc_group_layout *cur; 35662306a36Sopenharmony_ci unsigned int max_count, count_skip; 35762306a36Sopenharmony_ci unsigned int offset = 0; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if (group) 36062306a36Sopenharmony_ci offset = priv->l[group - 1].offset + priv->l[group - 1].count; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci count_skip = tsc2046_adc_time_to_count(priv, ch->settling_time_us); 36362306a36Sopenharmony_ci max_count = count_skip + ch->oversampling_ratio; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci cur = &priv->l[group]; 36662306a36Sopenharmony_ci cur->offset = offset; 36762306a36Sopenharmony_ci cur->count = max_count; 36862306a36Sopenharmony_ci cur->skip = count_skip; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci return sizeof(*priv->tx) * max_count; 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic void tsc2046_adc_group_set_cmd(struct tsc2046_adc_priv *priv, 37462306a36Sopenharmony_ci unsigned int group, int ch_idx) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci struct tsc2046_adc_group_layout *l = &priv->l[group]; 37762306a36Sopenharmony_ci unsigned int i; 37862306a36Sopenharmony_ci u8 cmd; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* 38162306a36Sopenharmony_ci * Do not enable automatic power down on working samples. Otherwise the 38262306a36Sopenharmony_ci * plates will never be completely charged. 38362306a36Sopenharmony_ci */ 38462306a36Sopenharmony_ci cmd = tsc2046_adc_get_cmd(priv, ch_idx, true); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci for (i = 0; i < l->count - 1; i++) 38762306a36Sopenharmony_ci priv->tx[l->offset + i].cmd = cmd; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /* automatically power down on last sample */ 39062306a36Sopenharmony_ci priv->tx[l->offset + i].cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic u16 tsc2046_adc_get_val(struct tsc2046_adc_priv *priv, int group) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci struct tsc2046_adc_group_layout *l; 39662306a36Sopenharmony_ci unsigned int val, val_normalized = 0; 39762306a36Sopenharmony_ci int valid_count, i; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci l = &priv->l[group]; 40062306a36Sopenharmony_ci valid_count = l->count - l->skip; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci for (i = 0; i < valid_count; i++) { 40362306a36Sopenharmony_ci val = tsc2046_adc_get_value(&priv->rx[l->offset + l->skip + i]); 40462306a36Sopenharmony_ci val_normalized += val; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci return DIV_ROUND_UP(val_normalized, valid_count); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic int tsc2046_adc_scan(struct iio_dev *indio_dev) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 41362306a36Sopenharmony_ci struct device *dev = &priv->spi->dev; 41462306a36Sopenharmony_ci int group; 41562306a36Sopenharmony_ci int ret; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci ret = spi_sync(priv->spi, &priv->msg); 41862306a36Sopenharmony_ci if (ret < 0) { 41962306a36Sopenharmony_ci dev_err_ratelimited(dev, "SPI transfer failed: %pe\n", ERR_PTR(ret)); 42062306a36Sopenharmony_ci return ret; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci for (group = 0; group < priv->groups; group++) 42462306a36Sopenharmony_ci priv->scan_buf.data[group] = tsc2046_adc_get_val(priv, group); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci ret = iio_push_to_buffers_with_timestamp(indio_dev, &priv->scan_buf, 42762306a36Sopenharmony_ci iio_get_time_ns(indio_dev)); 42862306a36Sopenharmony_ci /* If the consumer is kfifo, we may get a EBUSY here - ignore it. */ 42962306a36Sopenharmony_ci if (ret < 0 && ret != -EBUSY) { 43062306a36Sopenharmony_ci dev_err_ratelimited(dev, "Failed to push scan buffer %pe\n", 43162306a36Sopenharmony_ci ERR_PTR(ret)); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci return ret; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci return 0; 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic irqreturn_t tsc2046_adc_trigger_handler(int irq, void *p) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci struct iio_poll_func *pf = p; 44262306a36Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 44362306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci mutex_lock(&priv->slock); 44662306a36Sopenharmony_ci tsc2046_adc_scan(indio_dev); 44762306a36Sopenharmony_ci mutex_unlock(&priv->slock); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci return IRQ_HANDLED; 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic int tsc2046_adc_read_raw(struct iio_dev *indio_dev, 45562306a36Sopenharmony_ci struct iio_chan_spec const *chan, 45662306a36Sopenharmony_ci int *val, int *val2, long m) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 45962306a36Sopenharmony_ci int ret; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci switch (m) { 46262306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 46362306a36Sopenharmony_ci ret = tsc2046_adc_read_one(priv, chan->channel, NULL); 46462306a36Sopenharmony_ci if (ret < 0) 46562306a36Sopenharmony_ci return ret; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci *val = ret; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci return IIO_VAL_INT; 47062306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 47162306a36Sopenharmony_ci /* 47262306a36Sopenharmony_ci * Note: the TSC2046 has internal voltage divider on the VBAT 47362306a36Sopenharmony_ci * line. This divider can be influenced by external divider. 47462306a36Sopenharmony_ci * So, it is better to use external voltage-divider driver 47562306a36Sopenharmony_ci * instead, which is calculating complete chain. 47662306a36Sopenharmony_ci */ 47762306a36Sopenharmony_ci *val = priv->vref_mv; 47862306a36Sopenharmony_ci *val2 = chan->scan_type.realbits; 47962306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci return -EINVAL; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, 48662306a36Sopenharmony_ci const unsigned long *active_scan_mask) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 48962306a36Sopenharmony_ci unsigned int ch_idx, group = 0; 49062306a36Sopenharmony_ci size_t size; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci mutex_lock(&priv->slock); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci size = 0; 49562306a36Sopenharmony_ci for_each_set_bit(ch_idx, active_scan_mask, ARRAY_SIZE(priv->l)) { 49662306a36Sopenharmony_ci size += tsc2046_adc_group_set_layout(priv, group, ch_idx); 49762306a36Sopenharmony_ci tsc2046_adc_group_set_cmd(priv, group, ch_idx); 49862306a36Sopenharmony_ci group++; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci priv->groups = group; 50262306a36Sopenharmony_ci priv->xfer.len = size; 50362306a36Sopenharmony_ci priv->time_per_scan_us = size * 8 * priv->time_per_bit_ns / NSEC_PER_USEC; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci if (priv->scan_interval_us < priv->time_per_scan_us) 50662306a36Sopenharmony_ci dev_warn(&priv->spi->dev, "The scan interval (%d) is less then calculated scan time (%d)\n", 50762306a36Sopenharmony_ci priv->scan_interval_us, priv->time_per_scan_us); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci mutex_unlock(&priv->slock); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci return 0; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic const struct iio_info tsc2046_adc_info = { 51562306a36Sopenharmony_ci .read_raw = tsc2046_adc_read_raw, 51662306a36Sopenharmony_ci .update_scan_mode = tsc2046_adc_update_scan_mode, 51762306a36Sopenharmony_ci}; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistatic enum hrtimer_restart tsc2046_adc_timer(struct hrtimer *hrtimer) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = container_of(hrtimer, 52262306a36Sopenharmony_ci struct tsc2046_adc_priv, 52362306a36Sopenharmony_ci trig_timer); 52462306a36Sopenharmony_ci unsigned long flags; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* 52762306a36Sopenharmony_ci * This state machine should address following challenges : 52862306a36Sopenharmony_ci * - the interrupt source is based on level shifter attached to the X 52962306a36Sopenharmony_ci * channel of ADC. It will change the state every time we switch 53062306a36Sopenharmony_ci * between channels. So, we need to disable IRQ if we do 53162306a36Sopenharmony_ci * iio_trigger_poll(). 53262306a36Sopenharmony_ci * - we should do iio_trigger_poll() at some reduced sample rate 53362306a36Sopenharmony_ci * - we should still trigger for some amount of time after last 53462306a36Sopenharmony_ci * interrupt with enabled IRQ was processed. 53562306a36Sopenharmony_ci */ 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci spin_lock_irqsave(&priv->state_lock, flags); 53862306a36Sopenharmony_ci switch (priv->state) { 53962306a36Sopenharmony_ci case TSC2046_STATE_ENABLE_IRQ: 54062306a36Sopenharmony_ci if (priv->poll_cnt < TI_TSC2046_POLL_CNT) { 54162306a36Sopenharmony_ci priv->poll_cnt++; 54262306a36Sopenharmony_ci hrtimer_start(&priv->trig_timer, 54362306a36Sopenharmony_ci ns_to_ktime(priv->scan_interval_us * 54462306a36Sopenharmony_ci NSEC_PER_USEC), 54562306a36Sopenharmony_ci HRTIMER_MODE_REL_SOFT); 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci if (priv->poll_cnt >= TI_TSC2046_MIN_POLL_CNT) { 54862306a36Sopenharmony_ci priv->state = TSC2046_STATE_POLL_IRQ_DISABLE; 54962306a36Sopenharmony_ci enable_irq(priv->spi->irq); 55062306a36Sopenharmony_ci } else { 55162306a36Sopenharmony_ci priv->state = TSC2046_STATE_POLL; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci } else { 55462306a36Sopenharmony_ci priv->state = TSC2046_STATE_STANDBY; 55562306a36Sopenharmony_ci enable_irq(priv->spi->irq); 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci break; 55862306a36Sopenharmony_ci case TSC2046_STATE_POLL_IRQ_DISABLE: 55962306a36Sopenharmony_ci disable_irq_nosync(priv->spi->irq); 56062306a36Sopenharmony_ci fallthrough; 56162306a36Sopenharmony_ci case TSC2046_STATE_POLL: 56262306a36Sopenharmony_ci priv->state = TSC2046_STATE_ENABLE_IRQ; 56362306a36Sopenharmony_ci /* iio_trigger_poll() starts hrtimer */ 56462306a36Sopenharmony_ci iio_trigger_poll(priv->trig); 56562306a36Sopenharmony_ci break; 56662306a36Sopenharmony_ci case TSC2046_STATE_SHUTDOWN: 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci case TSC2046_STATE_STANDBY: 56962306a36Sopenharmony_ci fallthrough; 57062306a36Sopenharmony_ci default: 57162306a36Sopenharmony_ci dev_warn(&priv->spi->dev, "Got unexpected state: %i\n", 57262306a36Sopenharmony_ci priv->state); 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->state_lock, flags); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci return HRTIMER_NORESTART; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic irqreturn_t tsc2046_adc_irq(int irq, void *dev_id) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_id; 58362306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 58462306a36Sopenharmony_ci unsigned long flags; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci hrtimer_try_to_cancel(&priv->trig_timer); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci spin_lock_irqsave(&priv->state_lock, flags); 58962306a36Sopenharmony_ci if (priv->state != TSC2046_STATE_SHUTDOWN) { 59062306a36Sopenharmony_ci priv->state = TSC2046_STATE_ENABLE_IRQ; 59162306a36Sopenharmony_ci priv->poll_cnt = 0; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci /* iio_trigger_poll() starts hrtimer */ 59462306a36Sopenharmony_ci disable_irq_nosync(priv->spi->irq); 59562306a36Sopenharmony_ci iio_trigger_poll(priv->trig); 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->state_lock, flags); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci return IRQ_HANDLED; 60062306a36Sopenharmony_ci} 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_cistatic void tsc2046_adc_reenable_trigger(struct iio_trigger *trig) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 60562306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 60662306a36Sopenharmony_ci ktime_t tim; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* 60962306a36Sopenharmony_ci * We can sample it as fast as we can, but usually we do not need so 61062306a36Sopenharmony_ci * many samples. Reduce the sample rate for default (touchscreen) use 61162306a36Sopenharmony_ci * case. 61262306a36Sopenharmony_ci */ 61362306a36Sopenharmony_ci tim = ns_to_ktime((priv->scan_interval_us - priv->time_per_scan_us) * 61462306a36Sopenharmony_ci NSEC_PER_USEC); 61562306a36Sopenharmony_ci hrtimer_start(&priv->trig_timer, tim, HRTIMER_MODE_REL_SOFT); 61662306a36Sopenharmony_ci} 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_cistatic int tsc2046_adc_set_trigger_state(struct iio_trigger *trig, bool enable) 61962306a36Sopenharmony_ci{ 62062306a36Sopenharmony_ci struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 62162306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 62262306a36Sopenharmony_ci unsigned long flags; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci if (enable) { 62562306a36Sopenharmony_ci spin_lock_irqsave(&priv->state_lock, flags); 62662306a36Sopenharmony_ci if (priv->state == TSC2046_STATE_SHUTDOWN) { 62762306a36Sopenharmony_ci priv->state = TSC2046_STATE_STANDBY; 62862306a36Sopenharmony_ci enable_irq(priv->spi->irq); 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->state_lock, flags); 63162306a36Sopenharmony_ci } else { 63262306a36Sopenharmony_ci spin_lock_irqsave(&priv->state_lock, flags); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci if (priv->state == TSC2046_STATE_STANDBY || 63562306a36Sopenharmony_ci priv->state == TSC2046_STATE_POLL_IRQ_DISABLE) 63662306a36Sopenharmony_ci disable_irq_nosync(priv->spi->irq); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci priv->state = TSC2046_STATE_SHUTDOWN; 63962306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->state_lock, flags); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci hrtimer_cancel(&priv->trig_timer); 64262306a36Sopenharmony_ci } 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci return 0; 64562306a36Sopenharmony_ci} 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_cistatic const struct iio_trigger_ops tsc2046_adc_trigger_ops = { 64862306a36Sopenharmony_ci .set_trigger_state = tsc2046_adc_set_trigger_state, 64962306a36Sopenharmony_ci .reenable = tsc2046_adc_reenable_trigger, 65062306a36Sopenharmony_ci}; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic int tsc2046_adc_setup_spi_msg(struct tsc2046_adc_priv *priv) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci unsigned int ch_idx; 65562306a36Sopenharmony_ci size_t size; 65662306a36Sopenharmony_ci int ret; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci /* 65962306a36Sopenharmony_ci * Make dummy read to set initial power state and get real SPI clock 66062306a36Sopenharmony_ci * freq. It seems to be not important which channel is used for this 66162306a36Sopenharmony_ci * case. 66262306a36Sopenharmony_ci */ 66362306a36Sopenharmony_ci ret = tsc2046_adc_read_one(priv, TI_TSC2046_ADDR_TEMP0, 66462306a36Sopenharmony_ci &priv->effective_speed_hz); 66562306a36Sopenharmony_ci if (ret < 0) 66662306a36Sopenharmony_ci return ret; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci /* 66962306a36Sopenharmony_ci * In case SPI controller do not report effective_speed_hz, use 67062306a36Sopenharmony_ci * configure value and hope it will match. 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci if (!priv->effective_speed_hz) 67362306a36Sopenharmony_ci priv->effective_speed_hz = priv->spi->max_speed_hz; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci priv->scan_interval_us = TI_TSC2046_SAMPLE_INTERVAL_US; 67762306a36Sopenharmony_ci priv->time_per_bit_ns = DIV_ROUND_UP(NSEC_PER_SEC, 67862306a36Sopenharmony_ci priv->effective_speed_hz); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* 68162306a36Sopenharmony_ci * Calculate and allocate maximal size buffer if all channels are 68262306a36Sopenharmony_ci * enabled. 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_ci size = 0; 68562306a36Sopenharmony_ci for (ch_idx = 0; ch_idx < ARRAY_SIZE(priv->l); ch_idx++) 68662306a36Sopenharmony_ci size += tsc2046_adc_group_set_layout(priv, ch_idx, ch_idx); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci if (size > PAGE_SIZE) { 68962306a36Sopenharmony_ci dev_err(&priv->spi->dev, 69062306a36Sopenharmony_ci "Calculated scan buffer is too big. Try to reduce spi-max-frequency, settling-time-us or oversampling-ratio\n"); 69162306a36Sopenharmony_ci return -ENOSPC; 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci priv->tx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); 69562306a36Sopenharmony_ci if (!priv->tx) 69662306a36Sopenharmony_ci return -ENOMEM; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci priv->rx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); 69962306a36Sopenharmony_ci if (!priv->rx) 70062306a36Sopenharmony_ci return -ENOMEM; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci priv->xfer.tx_buf = priv->tx; 70362306a36Sopenharmony_ci priv->xfer.rx_buf = priv->rx; 70462306a36Sopenharmony_ci priv->xfer.len = size; 70562306a36Sopenharmony_ci spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci return 0; 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic void tsc2046_adc_parse_fwnode(struct tsc2046_adc_priv *priv) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci struct fwnode_handle *child; 71362306a36Sopenharmony_ci struct device *dev = &priv->spi->dev; 71462306a36Sopenharmony_ci unsigned int i; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(priv->ch_cfg); i++) { 71762306a36Sopenharmony_ci priv->ch_cfg[i].settling_time_us = 1; 71862306a36Sopenharmony_ci priv->ch_cfg[i].oversampling_ratio = 1; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci device_for_each_child_node(dev, child) { 72262306a36Sopenharmony_ci u32 stl, overs, reg; 72362306a36Sopenharmony_ci int ret; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci ret = fwnode_property_read_u32(child, "reg", ®); 72662306a36Sopenharmony_ci if (ret) { 72762306a36Sopenharmony_ci dev_err(dev, "invalid reg on %pfw, err: %pe\n", child, 72862306a36Sopenharmony_ci ERR_PTR(ret)); 72962306a36Sopenharmony_ci continue; 73062306a36Sopenharmony_ci } 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci if (reg >= ARRAY_SIZE(priv->ch_cfg)) { 73362306a36Sopenharmony_ci dev_err(dev, "%pfw: Unsupported reg value: %i, max supported is: %zu.\n", 73462306a36Sopenharmony_ci child, reg, ARRAY_SIZE(priv->ch_cfg)); 73562306a36Sopenharmony_ci continue; 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci ret = fwnode_property_read_u32(child, "settling-time-us", &stl); 73962306a36Sopenharmony_ci if (!ret) 74062306a36Sopenharmony_ci priv->ch_cfg[reg].settling_time_us = stl; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci ret = fwnode_property_read_u32(child, "oversampling-ratio", 74362306a36Sopenharmony_ci &overs); 74462306a36Sopenharmony_ci if (!ret) 74562306a36Sopenharmony_ci priv->ch_cfg[reg].oversampling_ratio = overs; 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci} 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_cistatic void tsc2046_adc_regulator_disable(void *data) 75062306a36Sopenharmony_ci{ 75162306a36Sopenharmony_ci struct tsc2046_adc_priv *priv = data; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci regulator_disable(priv->vref_reg); 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_cistatic int tsc2046_adc_configure_regulator(struct tsc2046_adc_priv *priv) 75762306a36Sopenharmony_ci{ 75862306a36Sopenharmony_ci struct device *dev = &priv->spi->dev; 75962306a36Sopenharmony_ci int ret; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci priv->vref_reg = devm_regulator_get_optional(dev, "vref"); 76262306a36Sopenharmony_ci if (IS_ERR(priv->vref_reg)) { 76362306a36Sopenharmony_ci /* If regulator exists but can't be get, return an error */ 76462306a36Sopenharmony_ci if (PTR_ERR(priv->vref_reg) != -ENODEV) 76562306a36Sopenharmony_ci return PTR_ERR(priv->vref_reg); 76662306a36Sopenharmony_ci priv->vref_reg = NULL; 76762306a36Sopenharmony_ci } 76862306a36Sopenharmony_ci if (!priv->vref_reg) { 76962306a36Sopenharmony_ci /* Use internal reference */ 77062306a36Sopenharmony_ci priv->vref_mv = TI_TSC2046_INT_VREF; 77162306a36Sopenharmony_ci return 0; 77262306a36Sopenharmony_ci } 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci ret = regulator_enable(priv->vref_reg); 77562306a36Sopenharmony_ci if (ret) 77662306a36Sopenharmony_ci return ret; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci ret = devm_add_action_or_reset(dev, tsc2046_adc_regulator_disable, 77962306a36Sopenharmony_ci priv); 78062306a36Sopenharmony_ci if (ret) 78162306a36Sopenharmony_ci return ret; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci ret = regulator_get_voltage(priv->vref_reg); 78462306a36Sopenharmony_ci if (ret < 0) 78562306a36Sopenharmony_ci return ret; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci priv->vref_mv = ret / MILLI; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci return 0; 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic int tsc2046_adc_probe(struct spi_device *spi) 79362306a36Sopenharmony_ci{ 79462306a36Sopenharmony_ci const struct tsc2046_adc_dcfg *dcfg; 79562306a36Sopenharmony_ci struct device *dev = &spi->dev; 79662306a36Sopenharmony_ci struct tsc2046_adc_priv *priv; 79762306a36Sopenharmony_ci struct iio_dev *indio_dev; 79862306a36Sopenharmony_ci struct iio_trigger *trig; 79962306a36Sopenharmony_ci int ret; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (spi->max_speed_hz > TI_TSC2046_MAX_CLK_FREQ) { 80262306a36Sopenharmony_ci dev_err(dev, "SPI max_speed_hz is too high: %d Hz. Max supported freq is %zu Hz\n", 80362306a36Sopenharmony_ci spi->max_speed_hz, TI_TSC2046_MAX_CLK_FREQ); 80462306a36Sopenharmony_ci return -EINVAL; 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci dcfg = device_get_match_data(dev); 80862306a36Sopenharmony_ci if (!dcfg) { 80962306a36Sopenharmony_ci const struct spi_device_id *id = spi_get_device_id(spi); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci dcfg = (const struct tsc2046_adc_dcfg *)id->driver_data; 81262306a36Sopenharmony_ci } 81362306a36Sopenharmony_ci if (!dcfg) 81462306a36Sopenharmony_ci return -EINVAL; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci spi->bits_per_word = 8; 81762306a36Sopenharmony_ci spi->mode &= ~SPI_MODE_X_MASK; 81862306a36Sopenharmony_ci spi->mode |= SPI_MODE_0; 81962306a36Sopenharmony_ci ret = spi_setup(spi); 82062306a36Sopenharmony_ci if (ret < 0) 82162306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Error in SPI setup\n"); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); 82462306a36Sopenharmony_ci if (!indio_dev) 82562306a36Sopenharmony_ci return -ENOMEM; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci priv = iio_priv(indio_dev); 82862306a36Sopenharmony_ci priv->dcfg = dcfg; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci priv->spi = spi; 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci indio_dev->name = TI_TSC2046_NAME; 83362306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 83462306a36Sopenharmony_ci indio_dev->channels = dcfg->channels; 83562306a36Sopenharmony_ci indio_dev->num_channels = dcfg->num_channels; 83662306a36Sopenharmony_ci indio_dev->info = &tsc2046_adc_info; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci ret = tsc2046_adc_configure_regulator(priv); 83962306a36Sopenharmony_ci if (ret) 84062306a36Sopenharmony_ci return ret; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci tsc2046_adc_parse_fwnode(priv); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci ret = tsc2046_adc_setup_spi_msg(priv); 84562306a36Sopenharmony_ci if (ret) 84662306a36Sopenharmony_ci return ret; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci mutex_init(&priv->slock); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci ret = devm_request_irq(dev, spi->irq, &tsc2046_adc_irq, 85162306a36Sopenharmony_ci IRQF_NO_AUTOEN, indio_dev->name, indio_dev); 85262306a36Sopenharmony_ci if (ret) 85362306a36Sopenharmony_ci return ret; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci trig = devm_iio_trigger_alloc(dev, "touchscreen-%s", indio_dev->name); 85662306a36Sopenharmony_ci if (!trig) 85762306a36Sopenharmony_ci return -ENOMEM; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci priv->trig = trig; 86062306a36Sopenharmony_ci iio_trigger_set_drvdata(trig, indio_dev); 86162306a36Sopenharmony_ci trig->ops = &tsc2046_adc_trigger_ops; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci spin_lock_init(&priv->state_lock); 86462306a36Sopenharmony_ci priv->state = TSC2046_STATE_SHUTDOWN; 86562306a36Sopenharmony_ci hrtimer_init(&priv->trig_timer, CLOCK_MONOTONIC, 86662306a36Sopenharmony_ci HRTIMER_MODE_REL_SOFT); 86762306a36Sopenharmony_ci priv->trig_timer.function = tsc2046_adc_timer; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci ret = devm_iio_trigger_register(dev, trig); 87062306a36Sopenharmony_ci if (ret) { 87162306a36Sopenharmony_ci dev_err(dev, "failed to register trigger\n"); 87262306a36Sopenharmony_ci return ret; 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, 87662306a36Sopenharmony_ci &tsc2046_adc_trigger_handler, NULL); 87762306a36Sopenharmony_ci if (ret) { 87862306a36Sopenharmony_ci dev_err(dev, "Failed to setup triggered buffer\n"); 87962306a36Sopenharmony_ci return ret; 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci /* set default trigger */ 88362306a36Sopenharmony_ci indio_dev->trig = iio_trigger_get(priv->trig); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci return devm_iio_device_register(dev, indio_dev); 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic const struct of_device_id ads7950_of_table[] = { 88962306a36Sopenharmony_ci { .compatible = "ti,tsc2046e-adc", .data = &tsc2046_adc_dcfg_tsc2046e }, 89062306a36Sopenharmony_ci { } 89162306a36Sopenharmony_ci}; 89262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ads7950_of_table); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_cistatic const struct spi_device_id tsc2046_adc_spi_ids[] = { 89562306a36Sopenharmony_ci { "tsc2046e-adc", (unsigned long)&tsc2046_adc_dcfg_tsc2046e }, 89662306a36Sopenharmony_ci { } 89762306a36Sopenharmony_ci}; 89862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, tsc2046_adc_spi_ids); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic struct spi_driver tsc2046_adc_driver = { 90162306a36Sopenharmony_ci .driver = { 90262306a36Sopenharmony_ci .name = "tsc2046", 90362306a36Sopenharmony_ci .of_match_table = ads7950_of_table, 90462306a36Sopenharmony_ci }, 90562306a36Sopenharmony_ci .id_table = tsc2046_adc_spi_ids, 90662306a36Sopenharmony_ci .probe = tsc2046_adc_probe, 90762306a36Sopenharmony_ci}; 90862306a36Sopenharmony_cimodule_spi_driver(tsc2046_adc_driver); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ciMODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>"); 91162306a36Sopenharmony_ciMODULE_DESCRIPTION("TI TSC2046 ADC"); 91262306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 913