19374e8f5SOleksij Rempel // SPDX-License-Identifier: GPL-2.0 29374e8f5SOleksij Rempel /* 39374e8f5SOleksij Rempel * Texas Instruments TSC2046 SPI ADC driver 49374e8f5SOleksij Rempel * 59374e8f5SOleksij Rempel * Copyright (c) 2021 Oleksij Rempel <kernel@pengutronix.de>, Pengutronix 69374e8f5SOleksij Rempel */ 79374e8f5SOleksij Rempel 89374e8f5SOleksij Rempel #include <linux/bitfield.h> 99374e8f5SOleksij Rempel #include <linux/delay.h> 109374e8f5SOleksij Rempel #include <linux/module.h> 119374e8f5SOleksij Rempel #include <linux/spi/spi.h> 129374e8f5SOleksij Rempel 139374e8f5SOleksij Rempel #include <asm/unaligned.h> 149374e8f5SOleksij Rempel 159374e8f5SOleksij Rempel #include <linux/iio/buffer.h> 169374e8f5SOleksij Rempel #include <linux/iio/trigger_consumer.h> 179374e8f5SOleksij Rempel #include <linux/iio/triggered_buffer.h> 189374e8f5SOleksij Rempel #include <linux/iio/trigger.h> 199374e8f5SOleksij Rempel 209374e8f5SOleksij Rempel /* 219374e8f5SOleksij Rempel * The PENIRQ of TSC2046 controller is implemented as level shifter attached to 229374e8f5SOleksij Rempel * the X+ line. If voltage of the X+ line reaches a specific level the IRQ will 239374e8f5SOleksij Rempel * be activated or deactivated. 249374e8f5SOleksij Rempel * To make this kind of IRQ reusable as trigger following additions were 259374e8f5SOleksij Rempel * implemented: 269374e8f5SOleksij Rempel * - rate limiting: 279374e8f5SOleksij Rempel * For typical touchscreen use case, we need to trigger about each 10ms. 289374e8f5SOleksij Rempel * - hrtimer: 299374e8f5SOleksij Rempel * Continue triggering at least once after the IRQ was deactivated. Then 309374e8f5SOleksij Rempel * deactivate this trigger to stop sampling in order to reduce power 319374e8f5SOleksij Rempel * consumption. 329374e8f5SOleksij Rempel */ 339374e8f5SOleksij Rempel 349374e8f5SOleksij Rempel #define TI_TSC2046_NAME "tsc2046" 359374e8f5SOleksij Rempel 369374e8f5SOleksij Rempel /* This driver doesn't aim at the peak continuous sample rate */ 379374e8f5SOleksij Rempel #define TI_TSC2046_MAX_SAMPLE_RATE 125000 389374e8f5SOleksij Rempel #define TI_TSC2046_SAMPLE_BITS \ 399374e8f5SOleksij Rempel BITS_PER_TYPE(struct tsc2046_adc_atom) 409374e8f5SOleksij Rempel #define TI_TSC2046_MAX_CLK_FREQ \ 419374e8f5SOleksij Rempel (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS) 429374e8f5SOleksij Rempel 439374e8f5SOleksij Rempel #define TI_TSC2046_SAMPLE_INTERVAL_US 10000 449374e8f5SOleksij Rempel 459374e8f5SOleksij Rempel #define TI_TSC2046_START BIT(7) 469374e8f5SOleksij Rempel #define TI_TSC2046_ADDR GENMASK(6, 4) 479374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_TEMP1 7 489374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_AUX 6 499374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_X 5 509374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_Z2 4 519374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_Z1 3 529374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_VBAT 2 539374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_Y 1 549374e8f5SOleksij Rempel #define TI_TSC2046_ADDR_TEMP0 0 559374e8f5SOleksij Rempel 569374e8f5SOleksij Rempel /* 579374e8f5SOleksij Rempel * The mode bit sets the resolution of the ADC. With this bit low, the next 589374e8f5SOleksij Rempel * conversion has 12-bit resolution, whereas with this bit high, the next 599374e8f5SOleksij Rempel * conversion has 8-bit resolution. This driver is optimized for 12-bit mode. 609374e8f5SOleksij Rempel * So, for this driver, this bit should stay zero. 619374e8f5SOleksij Rempel */ 629374e8f5SOleksij Rempel #define TI_TSC2046_8BIT_MODE BIT(3) 639374e8f5SOleksij Rempel 649374e8f5SOleksij Rempel /* 659374e8f5SOleksij Rempel * SER/DFR - The SER/DFR bit controls the reference mode, either single-ended 669374e8f5SOleksij Rempel * (high) or differential (low). 679374e8f5SOleksij Rempel */ 689374e8f5SOleksij Rempel #define TI_TSC2046_SER BIT(2) 699374e8f5SOleksij Rempel 709374e8f5SOleksij Rempel /* 719374e8f5SOleksij Rempel * If VREF_ON and ADC_ON are both zero, then the chip operates in 729374e8f5SOleksij Rempel * auto-wake/suspend mode. In most case this bits should stay zero. 739374e8f5SOleksij Rempel */ 749374e8f5SOleksij Rempel #define TI_TSC2046_PD1_VREF_ON BIT(1) 759374e8f5SOleksij Rempel #define TI_TSC2046_PD0_ADC_ON BIT(0) 769374e8f5SOleksij Rempel 779374e8f5SOleksij Rempel /* 789374e8f5SOleksij Rempel * All supported devices can do 8 or 12bit resolution. This driver 799374e8f5SOleksij Rempel * supports only 12bit mode, here we have a 16bit data transfer, where 809374e8f5SOleksij Rempel * the MSB and the 3 LSB are 0. 819374e8f5SOleksij Rempel */ 829374e8f5SOleksij Rempel #define TI_TSC2046_DATA_12BIT GENMASK(14, 3) 839374e8f5SOleksij Rempel 849374e8f5SOleksij Rempel #define TI_TSC2046_MAX_CHAN 8 8584e5d889SOleksij Rempel #define TI_TSC2046_MIN_POLL_CNT 3 8684e5d889SOleksij Rempel #define TI_TSC2046_EXT_POLL_CNT 3 8784e5d889SOleksij Rempel #define TI_TSC2046_POLL_CNT \ 8884e5d889SOleksij Rempel (TI_TSC2046_MIN_POLL_CNT + TI_TSC2046_EXT_POLL_CNT) 89b617693aSOleksij Rempel #define TI_TSC2046_INT_VREF 2500 909374e8f5SOleksij Rempel 919374e8f5SOleksij Rempel /* Represents a HW sample */ 929374e8f5SOleksij Rempel struct tsc2046_adc_atom { 939374e8f5SOleksij Rempel /* 949374e8f5SOleksij Rempel * Command transmitted to the controller. This field is empty on the RX 959374e8f5SOleksij Rempel * buffer. 969374e8f5SOleksij Rempel */ 979374e8f5SOleksij Rempel u8 cmd; 989374e8f5SOleksij Rempel /* 999374e8f5SOleksij Rempel * Data received from the controller. This field is empty for the TX 1009374e8f5SOleksij Rempel * buffer 1019374e8f5SOleksij Rempel */ 1029374e8f5SOleksij Rempel __be16 data; 1039374e8f5SOleksij Rempel } __packed; 1049374e8f5SOleksij Rempel 1059374e8f5SOleksij Rempel /* Layout of atomic buffers within big buffer */ 1069374e8f5SOleksij Rempel struct tsc2046_adc_group_layout { 1079374e8f5SOleksij Rempel /* Group offset within the SPI RX buffer */ 1089374e8f5SOleksij Rempel unsigned int offset; 1099374e8f5SOleksij Rempel /* 1109374e8f5SOleksij Rempel * Amount of tsc2046_adc_atom structs within the same command gathered 1119374e8f5SOleksij Rempel * within same group. 1129374e8f5SOleksij Rempel */ 1139374e8f5SOleksij Rempel unsigned int count; 1149374e8f5SOleksij Rempel /* 1159374e8f5SOleksij Rempel * Settling samples (tsc2046_adc_atom structs) which should be skipped 1169374e8f5SOleksij Rempel * before good samples will start. 1179374e8f5SOleksij Rempel */ 1189374e8f5SOleksij Rempel unsigned int skip; 1199374e8f5SOleksij Rempel }; 1209374e8f5SOleksij Rempel 1219374e8f5SOleksij Rempel struct tsc2046_adc_dcfg { 1229374e8f5SOleksij Rempel const struct iio_chan_spec *channels; 1239374e8f5SOleksij Rempel unsigned int num_channels; 1249374e8f5SOleksij Rempel }; 1259374e8f5SOleksij Rempel 1269374e8f5SOleksij Rempel struct tsc2046_adc_ch_cfg { 1279374e8f5SOleksij Rempel unsigned int settling_time_us; 1289374e8f5SOleksij Rempel unsigned int oversampling_ratio; 1299374e8f5SOleksij Rempel }; 1309374e8f5SOleksij Rempel 13184e5d889SOleksij Rempel enum tsc2046_state { 13284e5d889SOleksij Rempel TSC2046_STATE_SHUTDOWN, 13384e5d889SOleksij Rempel TSC2046_STATE_STANDBY, 13484e5d889SOleksij Rempel TSC2046_STATE_POLL, 13584e5d889SOleksij Rempel TSC2046_STATE_POLL_IRQ_DISABLE, 13684e5d889SOleksij Rempel TSC2046_STATE_ENABLE_IRQ, 13784e5d889SOleksij Rempel }; 13884e5d889SOleksij Rempel 1399374e8f5SOleksij Rempel struct tsc2046_adc_priv { 1409374e8f5SOleksij Rempel struct spi_device *spi; 1419374e8f5SOleksij Rempel const struct tsc2046_adc_dcfg *dcfg; 1429374e8f5SOleksij Rempel 1439374e8f5SOleksij Rempel struct iio_trigger *trig; 1449374e8f5SOleksij Rempel struct hrtimer trig_timer; 14584e5d889SOleksij Rempel enum tsc2046_state state; 14684e5d889SOleksij Rempel int poll_cnt; 14784e5d889SOleksij Rempel spinlock_t state_lock; 1489374e8f5SOleksij Rempel 1499374e8f5SOleksij Rempel struct spi_transfer xfer; 1509374e8f5SOleksij Rempel struct spi_message msg; 1519374e8f5SOleksij Rempel 1529374e8f5SOleksij Rempel struct { 1539374e8f5SOleksij Rempel /* Scan data for each channel */ 1549374e8f5SOleksij Rempel u16 data[TI_TSC2046_MAX_CHAN]; 1559374e8f5SOleksij Rempel /* Timestamp */ 1569374e8f5SOleksij Rempel s64 ts __aligned(8); 1579374e8f5SOleksij Rempel } scan_buf; 1589374e8f5SOleksij Rempel 1599374e8f5SOleksij Rempel /* 1609374e8f5SOleksij Rempel * Lock to protect the layout and the SPI transfer buffer. 1619374e8f5SOleksij Rempel * tsc2046_adc_group_layout can be changed within update_scan_mode(), 1629374e8f5SOleksij Rempel * in this case the l[] and tx/rx buffer will be out of sync to each 1639374e8f5SOleksij Rempel * other. 1649374e8f5SOleksij Rempel */ 1659374e8f5SOleksij Rempel struct mutex slock; 1669374e8f5SOleksij Rempel struct tsc2046_adc_group_layout l[TI_TSC2046_MAX_CHAN]; 1679374e8f5SOleksij Rempel struct tsc2046_adc_atom *rx; 1689374e8f5SOleksij Rempel struct tsc2046_adc_atom *tx; 1699374e8f5SOleksij Rempel 1709374e8f5SOleksij Rempel unsigned int count; 1719374e8f5SOleksij Rempel unsigned int groups; 1729374e8f5SOleksij Rempel u32 effective_speed_hz; 1739374e8f5SOleksij Rempel u32 scan_interval_us; 1749374e8f5SOleksij Rempel u32 time_per_scan_us; 1759374e8f5SOleksij Rempel u32 time_per_bit_ns; 1769374e8f5SOleksij Rempel 1779374e8f5SOleksij Rempel struct tsc2046_adc_ch_cfg ch_cfg[TI_TSC2046_MAX_CHAN]; 1789374e8f5SOleksij Rempel }; 1799374e8f5SOleksij Rempel 1809374e8f5SOleksij Rempel #define TI_TSC2046_V_CHAN(index, bits, name) \ 1819374e8f5SOleksij Rempel { \ 1829374e8f5SOleksij Rempel .type = IIO_VOLTAGE, \ 1839374e8f5SOleksij Rempel .indexed = 1, \ 1849374e8f5SOleksij Rempel .channel = index, \ 185b617693aSOleksij Rempel .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 186b617693aSOleksij Rempel .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 1879374e8f5SOleksij Rempel .datasheet_name = "#name", \ 1889374e8f5SOleksij Rempel .scan_index = index, \ 1899374e8f5SOleksij Rempel .scan_type = { \ 1909374e8f5SOleksij Rempel .sign = 'u', \ 1919374e8f5SOleksij Rempel .realbits = bits, \ 1929374e8f5SOleksij Rempel .storagebits = 16, \ 1939374e8f5SOleksij Rempel .endianness = IIO_CPU, \ 1949374e8f5SOleksij Rempel }, \ 1959374e8f5SOleksij Rempel } 1969374e8f5SOleksij Rempel 1979374e8f5SOleksij Rempel #define DECLARE_TI_TSC2046_8_CHANNELS(name, bits) \ 1989374e8f5SOleksij Rempel const struct iio_chan_spec name ## _channels[] = { \ 1999374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(0, bits, TEMP0), \ 2009374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(1, bits, Y), \ 2019374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(2, bits, VBAT), \ 2029374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(3, bits, Z1), \ 2039374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(4, bits, Z2), \ 2049374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(5, bits, X), \ 2059374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(6, bits, AUX), \ 2069374e8f5SOleksij Rempel TI_TSC2046_V_CHAN(7, bits, TEMP1), \ 2079374e8f5SOleksij Rempel IIO_CHAN_SOFT_TIMESTAMP(8), \ 2089374e8f5SOleksij Rempel } 2099374e8f5SOleksij Rempel 2109374e8f5SOleksij Rempel static DECLARE_TI_TSC2046_8_CHANNELS(tsc2046_adc, 12); 2119374e8f5SOleksij Rempel 2129374e8f5SOleksij Rempel static const struct tsc2046_adc_dcfg tsc2046_adc_dcfg_tsc2046e = { 2139374e8f5SOleksij Rempel .channels = tsc2046_adc_channels, 2149374e8f5SOleksij Rempel .num_channels = ARRAY_SIZE(tsc2046_adc_channels), 2159374e8f5SOleksij Rempel }; 2169374e8f5SOleksij Rempel 2179374e8f5SOleksij Rempel /* 2189374e8f5SOleksij Rempel * Convert time to a number of samples which can be transferred within this 2199374e8f5SOleksij Rempel * time. 2209374e8f5SOleksij Rempel */ 2219374e8f5SOleksij Rempel static unsigned int tsc2046_adc_time_to_count(struct tsc2046_adc_priv *priv, 2229374e8f5SOleksij Rempel unsigned long time) 2239374e8f5SOleksij Rempel { 2249374e8f5SOleksij Rempel unsigned int bit_count, sample_count; 2259374e8f5SOleksij Rempel 2269374e8f5SOleksij Rempel bit_count = DIV_ROUND_UP(time * NSEC_PER_USEC, priv->time_per_bit_ns); 2279374e8f5SOleksij Rempel sample_count = DIV_ROUND_UP(bit_count, TI_TSC2046_SAMPLE_BITS); 2289374e8f5SOleksij Rempel 2299374e8f5SOleksij Rempel dev_dbg(&priv->spi->dev, "Effective speed %u, time per bit: %u, count bits: %u, count samples: %u\n", 2309374e8f5SOleksij Rempel priv->effective_speed_hz, priv->time_per_bit_ns, 2319374e8f5SOleksij Rempel bit_count, sample_count); 2329374e8f5SOleksij Rempel 2339374e8f5SOleksij Rempel return sample_count; 2349374e8f5SOleksij Rempel } 2359374e8f5SOleksij Rempel 2369374e8f5SOleksij Rempel static u8 tsc2046_adc_get_cmd(struct tsc2046_adc_priv *priv, int ch_idx, 2379374e8f5SOleksij Rempel bool keep_power) 2389374e8f5SOleksij Rempel { 2399374e8f5SOleksij Rempel u32 pd; 2409374e8f5SOleksij Rempel 2419374e8f5SOleksij Rempel /* 2429374e8f5SOleksij Rempel * if PD bits are 0, controller will automatically disable ADC, VREF and 2439374e8f5SOleksij Rempel * enable IRQ. 2449374e8f5SOleksij Rempel */ 2459374e8f5SOleksij Rempel if (keep_power) 2469374e8f5SOleksij Rempel pd = TI_TSC2046_PD0_ADC_ON; 2479374e8f5SOleksij Rempel else 2489374e8f5SOleksij Rempel pd = 0; 2499374e8f5SOleksij Rempel 250b617693aSOleksij Rempel switch (ch_idx) { 251b617693aSOleksij Rempel case TI_TSC2046_ADDR_TEMP1: 252b617693aSOleksij Rempel case TI_TSC2046_ADDR_AUX: 253b617693aSOleksij Rempel case TI_TSC2046_ADDR_VBAT: 254b617693aSOleksij Rempel case TI_TSC2046_ADDR_TEMP0: 255b617693aSOleksij Rempel pd |= TI_TSC2046_SER | TI_TSC2046_PD1_VREF_ON; 256b617693aSOleksij Rempel } 257b617693aSOleksij Rempel 2589374e8f5SOleksij Rempel return TI_TSC2046_START | FIELD_PREP(TI_TSC2046_ADDR, ch_idx) | pd; 2599374e8f5SOleksij Rempel } 2609374e8f5SOleksij Rempel 2619374e8f5SOleksij Rempel static u16 tsc2046_adc_get_value(struct tsc2046_adc_atom *buf) 2629374e8f5SOleksij Rempel { 2639374e8f5SOleksij Rempel return FIELD_GET(TI_TSC2046_DATA_12BIT, get_unaligned_be16(&buf->data)); 2649374e8f5SOleksij Rempel } 2659374e8f5SOleksij Rempel 2669374e8f5SOleksij Rempel static int tsc2046_adc_read_one(struct tsc2046_adc_priv *priv, int ch_idx, 2679374e8f5SOleksij Rempel u32 *effective_speed_hz) 2689374e8f5SOleksij Rempel { 269b617693aSOleksij Rempel struct tsc2046_adc_ch_cfg *ch = &priv->ch_cfg[ch_idx]; 270b617693aSOleksij Rempel struct tsc2046_adc_atom *rx_buf, *tx_buf; 271b617693aSOleksij Rempel unsigned int val, val_normalized = 0; 272b617693aSOleksij Rempel int ret, i, count_skip = 0, max_count; 2739374e8f5SOleksij Rempel struct spi_transfer xfer; 2749374e8f5SOleksij Rempel struct spi_message msg; 275b617693aSOleksij Rempel u8 cmd; 276b617693aSOleksij Rempel 277b617693aSOleksij Rempel if (!effective_speed_hz) { 278b617693aSOleksij Rempel count_skip = tsc2046_adc_time_to_count(priv, ch->settling_time_us); 279b617693aSOleksij Rempel max_count = count_skip + ch->oversampling_ratio; 280b617693aSOleksij Rempel } else { 281b617693aSOleksij Rempel max_count = 1; 282b617693aSOleksij Rempel } 283b617693aSOleksij Rempel 284b617693aSOleksij Rempel if (sizeof(*tx_buf) * max_count > PAGE_SIZE) 285b617693aSOleksij Rempel return -ENOSPC; 286b617693aSOleksij Rempel 287b617693aSOleksij Rempel tx_buf = kcalloc(max_count, sizeof(*tx_buf), GFP_KERNEL); 288b617693aSOleksij Rempel if (!tx_buf) 289b617693aSOleksij Rempel return -ENOMEM; 290b617693aSOleksij Rempel 291b617693aSOleksij Rempel rx_buf = kcalloc(max_count, sizeof(*rx_buf), GFP_KERNEL); 292b617693aSOleksij Rempel if (!rx_buf) { 293b617693aSOleksij Rempel ret = -ENOMEM; 294b617693aSOleksij Rempel goto free_tx; 295b617693aSOleksij Rempel } 296b617693aSOleksij Rempel 297b617693aSOleksij Rempel /* 298b617693aSOleksij Rempel * Do not enable automatic power down on working samples. Otherwise the 299b617693aSOleksij Rempel * plates will never be completely charged. 300b617693aSOleksij Rempel */ 301b617693aSOleksij Rempel cmd = tsc2046_adc_get_cmd(priv, ch_idx, true); 302b617693aSOleksij Rempel 303b617693aSOleksij Rempel for (i = 0; i < max_count - 1; i++) 304b617693aSOleksij Rempel tx_buf[i].cmd = cmd; 305b617693aSOleksij Rempel 306b617693aSOleksij Rempel /* automatically power down on last sample */ 307b617693aSOleksij Rempel tx_buf[i].cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); 3089374e8f5SOleksij Rempel 3099374e8f5SOleksij Rempel memset(&xfer, 0, sizeof(xfer)); 310b617693aSOleksij Rempel xfer.tx_buf = tx_buf; 311b617693aSOleksij Rempel xfer.rx_buf = rx_buf; 312b617693aSOleksij Rempel xfer.len = sizeof(*tx_buf) * max_count; 3139374e8f5SOleksij Rempel spi_message_init_with_transfers(&msg, &xfer, 1); 3149374e8f5SOleksij Rempel 3159374e8f5SOleksij Rempel /* 3169374e8f5SOleksij Rempel * We aren't using spi_write_then_read() because we need to be able 3179374e8f5SOleksij Rempel * to get hold of the effective_speed_hz from the xfer 3189374e8f5SOleksij Rempel */ 3199374e8f5SOleksij Rempel ret = spi_sync(priv->spi, &msg); 3209374e8f5SOleksij Rempel if (ret) { 3219374e8f5SOleksij Rempel dev_err_ratelimited(&priv->spi->dev, "SPI transfer failed %pe\n", 3229374e8f5SOleksij Rempel ERR_PTR(ret)); 323b617693aSOleksij Rempel goto free_bufs; 3249374e8f5SOleksij Rempel } 3259374e8f5SOleksij Rempel 3269374e8f5SOleksij Rempel if (effective_speed_hz) 3279374e8f5SOleksij Rempel *effective_speed_hz = xfer.effective_speed_hz; 3289374e8f5SOleksij Rempel 329b617693aSOleksij Rempel for (i = 0; i < max_count - count_skip; i++) { 330b617693aSOleksij Rempel val = tsc2046_adc_get_value(&rx_buf[count_skip + i]); 331b617693aSOleksij Rempel val_normalized += val; 332b617693aSOleksij Rempel } 333b617693aSOleksij Rempel 334b617693aSOleksij Rempel ret = DIV_ROUND_UP(val_normalized, max_count - count_skip); 335b617693aSOleksij Rempel 336b617693aSOleksij Rempel free_bufs: 337b617693aSOleksij Rempel kfree(rx_buf); 338b617693aSOleksij Rempel free_tx: 339b617693aSOleksij Rempel kfree(tx_buf); 340b617693aSOleksij Rempel 341b617693aSOleksij Rempel return ret; 3429374e8f5SOleksij Rempel } 3439374e8f5SOleksij Rempel 3449374e8f5SOleksij Rempel static size_t tsc2046_adc_group_set_layout(struct tsc2046_adc_priv *priv, 3459374e8f5SOleksij Rempel unsigned int group, 3469374e8f5SOleksij Rempel unsigned int ch_idx) 3479374e8f5SOleksij Rempel { 3489374e8f5SOleksij Rempel struct tsc2046_adc_ch_cfg *ch = &priv->ch_cfg[ch_idx]; 3499374e8f5SOleksij Rempel struct tsc2046_adc_group_layout *cur; 3509374e8f5SOleksij Rempel unsigned int max_count, count_skip; 3519374e8f5SOleksij Rempel unsigned int offset = 0; 3529374e8f5SOleksij Rempel 3539374e8f5SOleksij Rempel if (group) 3549374e8f5SOleksij Rempel offset = priv->l[group - 1].offset + priv->l[group - 1].count; 3559374e8f5SOleksij Rempel 3569374e8f5SOleksij Rempel count_skip = tsc2046_adc_time_to_count(priv, ch->settling_time_us); 3579374e8f5SOleksij Rempel max_count = count_skip + ch->oversampling_ratio; 3589374e8f5SOleksij Rempel 3599374e8f5SOleksij Rempel cur = &priv->l[group]; 3609374e8f5SOleksij Rempel cur->offset = offset; 3619374e8f5SOleksij Rempel cur->count = max_count; 3629374e8f5SOleksij Rempel cur->skip = count_skip; 3639374e8f5SOleksij Rempel 3649374e8f5SOleksij Rempel return sizeof(*priv->tx) * max_count; 3659374e8f5SOleksij Rempel } 3669374e8f5SOleksij Rempel 3679374e8f5SOleksij Rempel static void tsc2046_adc_group_set_cmd(struct tsc2046_adc_priv *priv, 3689374e8f5SOleksij Rempel unsigned int group, int ch_idx) 3699374e8f5SOleksij Rempel { 3709374e8f5SOleksij Rempel struct tsc2046_adc_group_layout *l = &priv->l[group]; 3719374e8f5SOleksij Rempel unsigned int i; 3729374e8f5SOleksij Rempel u8 cmd; 3739374e8f5SOleksij Rempel 3749374e8f5SOleksij Rempel /* 3759374e8f5SOleksij Rempel * Do not enable automatic power down on working samples. Otherwise the 3769374e8f5SOleksij Rempel * plates will never be completely charged. 3779374e8f5SOleksij Rempel */ 3789374e8f5SOleksij Rempel cmd = tsc2046_adc_get_cmd(priv, ch_idx, true); 3799374e8f5SOleksij Rempel 3809374e8f5SOleksij Rempel for (i = 0; i < l->count - 1; i++) 3819374e8f5SOleksij Rempel priv->tx[l->offset + i].cmd = cmd; 3829374e8f5SOleksij Rempel 3839374e8f5SOleksij Rempel /* automatically power down on last sample */ 3849374e8f5SOleksij Rempel priv->tx[l->offset + i].cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); 3859374e8f5SOleksij Rempel } 3869374e8f5SOleksij Rempel 3879374e8f5SOleksij Rempel static u16 tsc2046_adc_get_val(struct tsc2046_adc_priv *priv, int group) 3889374e8f5SOleksij Rempel { 3899374e8f5SOleksij Rempel struct tsc2046_adc_group_layout *l; 3909374e8f5SOleksij Rempel unsigned int val, val_normalized = 0; 3919374e8f5SOleksij Rempel int valid_count, i; 3929374e8f5SOleksij Rempel 3939374e8f5SOleksij Rempel l = &priv->l[group]; 3949374e8f5SOleksij Rempel valid_count = l->count - l->skip; 3959374e8f5SOleksij Rempel 3969374e8f5SOleksij Rempel for (i = 0; i < valid_count; i++) { 3979374e8f5SOleksij Rempel val = tsc2046_adc_get_value(&priv->rx[l->offset + l->skip + i]); 3989374e8f5SOleksij Rempel val_normalized += val; 3999374e8f5SOleksij Rempel } 4009374e8f5SOleksij Rempel 4019374e8f5SOleksij Rempel return DIV_ROUND_UP(val_normalized, valid_count); 4029374e8f5SOleksij Rempel } 4039374e8f5SOleksij Rempel 4049374e8f5SOleksij Rempel static int tsc2046_adc_scan(struct iio_dev *indio_dev) 4059374e8f5SOleksij Rempel { 4069374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 4079374e8f5SOleksij Rempel struct device *dev = &priv->spi->dev; 4089374e8f5SOleksij Rempel int group; 4099374e8f5SOleksij Rempel int ret; 4109374e8f5SOleksij Rempel 4119374e8f5SOleksij Rempel ret = spi_sync(priv->spi, &priv->msg); 4129374e8f5SOleksij Rempel if (ret < 0) { 4139374e8f5SOleksij Rempel dev_err_ratelimited(dev, "SPI transfer failed: %pe\n", ERR_PTR(ret)); 4149374e8f5SOleksij Rempel return ret; 4159374e8f5SOleksij Rempel } 4169374e8f5SOleksij Rempel 4179374e8f5SOleksij Rempel for (group = 0; group < priv->groups; group++) 4189374e8f5SOleksij Rempel priv->scan_buf.data[group] = tsc2046_adc_get_val(priv, group); 4199374e8f5SOleksij Rempel 4209374e8f5SOleksij Rempel ret = iio_push_to_buffers_with_timestamp(indio_dev, &priv->scan_buf, 4219374e8f5SOleksij Rempel iio_get_time_ns(indio_dev)); 4229374e8f5SOleksij Rempel /* If the consumer is kfifo, we may get a EBUSY here - ignore it. */ 4239374e8f5SOleksij Rempel if (ret < 0 && ret != -EBUSY) { 4249374e8f5SOleksij Rempel dev_err_ratelimited(dev, "Failed to push scan buffer %pe\n", 4259374e8f5SOleksij Rempel ERR_PTR(ret)); 4269374e8f5SOleksij Rempel 4279374e8f5SOleksij Rempel return ret; 4289374e8f5SOleksij Rempel } 4299374e8f5SOleksij Rempel 4309374e8f5SOleksij Rempel return 0; 4319374e8f5SOleksij Rempel } 4329374e8f5SOleksij Rempel 4339374e8f5SOleksij Rempel static irqreturn_t tsc2046_adc_trigger_handler(int irq, void *p) 4349374e8f5SOleksij Rempel { 4359374e8f5SOleksij Rempel struct iio_poll_func *pf = p; 4369374e8f5SOleksij Rempel struct iio_dev *indio_dev = pf->indio_dev; 4379374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 4389374e8f5SOleksij Rempel 4399374e8f5SOleksij Rempel mutex_lock(&priv->slock); 4409374e8f5SOleksij Rempel tsc2046_adc_scan(indio_dev); 4419374e8f5SOleksij Rempel mutex_unlock(&priv->slock); 4429374e8f5SOleksij Rempel 4439374e8f5SOleksij Rempel iio_trigger_notify_done(indio_dev->trig); 4449374e8f5SOleksij Rempel 4459374e8f5SOleksij Rempel return IRQ_HANDLED; 4469374e8f5SOleksij Rempel } 4479374e8f5SOleksij Rempel 448b617693aSOleksij Rempel static int tsc2046_adc_read_raw(struct iio_dev *indio_dev, 449b617693aSOleksij Rempel struct iio_chan_spec const *chan, 450b617693aSOleksij Rempel int *val, int *val2, long m) 451b617693aSOleksij Rempel { 452b617693aSOleksij Rempel struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 453b617693aSOleksij Rempel int ret; 454b617693aSOleksij Rempel 455b617693aSOleksij Rempel switch (m) { 456b617693aSOleksij Rempel case IIO_CHAN_INFO_RAW: 457b617693aSOleksij Rempel ret = tsc2046_adc_read_one(priv, chan->channel, NULL); 458b617693aSOleksij Rempel if (ret < 0) 459b617693aSOleksij Rempel return ret; 460b617693aSOleksij Rempel 461b617693aSOleksij Rempel *val = ret; 462b617693aSOleksij Rempel 463b617693aSOleksij Rempel return IIO_VAL_INT; 464b617693aSOleksij Rempel case IIO_CHAN_INFO_SCALE: 465b617693aSOleksij Rempel /* 466b617693aSOleksij Rempel * Note: the TSC2046 has internal voltage divider on the VBAT 467b617693aSOleksij Rempel * line. This divider can be influenced by external divider. 468b617693aSOleksij Rempel * So, it is better to use external voltage-divider driver 469b617693aSOleksij Rempel * instead, which is calculating complete chain. 470b617693aSOleksij Rempel */ 471b617693aSOleksij Rempel *val = TI_TSC2046_INT_VREF; 472b617693aSOleksij Rempel *val2 = chan->scan_type.realbits; 473b617693aSOleksij Rempel return IIO_VAL_FRACTIONAL_LOG2; 474b617693aSOleksij Rempel } 475b617693aSOleksij Rempel 476b617693aSOleksij Rempel return -EINVAL; 477b617693aSOleksij Rempel } 478b617693aSOleksij Rempel 4799374e8f5SOleksij Rempel static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, 4809374e8f5SOleksij Rempel const unsigned long *active_scan_mask) 4819374e8f5SOleksij Rempel { 4829374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 4839374e8f5SOleksij Rempel unsigned int ch_idx, group = 0; 4849374e8f5SOleksij Rempel size_t size; 4859374e8f5SOleksij Rempel 4869374e8f5SOleksij Rempel mutex_lock(&priv->slock); 4879374e8f5SOleksij Rempel 4889374e8f5SOleksij Rempel size = 0; 4899374e8f5SOleksij Rempel for_each_set_bit(ch_idx, active_scan_mask, indio_dev->num_channels) { 4909374e8f5SOleksij Rempel size += tsc2046_adc_group_set_layout(priv, group, ch_idx); 4919374e8f5SOleksij Rempel tsc2046_adc_group_set_cmd(priv, group, ch_idx); 4929374e8f5SOleksij Rempel group++; 4939374e8f5SOleksij Rempel } 4949374e8f5SOleksij Rempel 4959374e8f5SOleksij Rempel priv->groups = group; 4969374e8f5SOleksij Rempel priv->xfer.len = size; 4979374e8f5SOleksij Rempel priv->time_per_scan_us = size * 8 * priv->time_per_bit_ns / NSEC_PER_USEC; 4989374e8f5SOleksij Rempel 49969b31fd7SOleksij Rempel if (priv->scan_interval_us < priv->time_per_scan_us) 5009374e8f5SOleksij Rempel dev_warn(&priv->spi->dev, "The scan interval (%d) is less then calculated scan time (%d)\n", 5019374e8f5SOleksij Rempel priv->scan_interval_us, priv->time_per_scan_us); 5029374e8f5SOleksij Rempel 5039374e8f5SOleksij Rempel mutex_unlock(&priv->slock); 5049374e8f5SOleksij Rempel 5059374e8f5SOleksij Rempel return 0; 5069374e8f5SOleksij Rempel } 5079374e8f5SOleksij Rempel 5089374e8f5SOleksij Rempel static const struct iio_info tsc2046_adc_info = { 509b617693aSOleksij Rempel .read_raw = tsc2046_adc_read_raw, 5109374e8f5SOleksij Rempel .update_scan_mode = tsc2046_adc_update_scan_mode, 5119374e8f5SOleksij Rempel }; 5129374e8f5SOleksij Rempel 51384e5d889SOleksij Rempel static enum hrtimer_restart tsc2046_adc_timer(struct hrtimer *hrtimer) 5149374e8f5SOleksij Rempel { 5159374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv = container_of(hrtimer, 5169374e8f5SOleksij Rempel struct tsc2046_adc_priv, 5179374e8f5SOleksij Rempel trig_timer); 5189374e8f5SOleksij Rempel unsigned long flags; 5199374e8f5SOleksij Rempel 52084e5d889SOleksij Rempel /* 52184e5d889SOleksij Rempel * This state machine should address following challenges : 52284e5d889SOleksij Rempel * - the interrupt source is based on level shifter attached to the X 52384e5d889SOleksij Rempel * channel of ADC. It will change the state every time we switch 52484e5d889SOleksij Rempel * between channels. So, we need to disable IRQ if we do 52584e5d889SOleksij Rempel * iio_trigger_poll(). 52684e5d889SOleksij Rempel * - we should do iio_trigger_poll() at some reduced sample rate 52784e5d889SOleksij Rempel * - we should still trigger for some amount of time after last 52884e5d889SOleksij Rempel * interrupt with enabled IRQ was processed. 52984e5d889SOleksij Rempel */ 5309374e8f5SOleksij Rempel 53184e5d889SOleksij Rempel spin_lock_irqsave(&priv->state_lock, flags); 53284e5d889SOleksij Rempel switch (priv->state) { 53384e5d889SOleksij Rempel case TSC2046_STATE_ENABLE_IRQ: 53484e5d889SOleksij Rempel if (priv->poll_cnt < TI_TSC2046_POLL_CNT) { 53584e5d889SOleksij Rempel priv->poll_cnt++; 53684e5d889SOleksij Rempel hrtimer_start(&priv->trig_timer, 53784e5d889SOleksij Rempel ns_to_ktime(priv->scan_interval_us * 53884e5d889SOleksij Rempel NSEC_PER_USEC), 53984e5d889SOleksij Rempel HRTIMER_MODE_REL_SOFT); 54084e5d889SOleksij Rempel 54184e5d889SOleksij Rempel if (priv->poll_cnt >= TI_TSC2046_MIN_POLL_CNT) { 54284e5d889SOleksij Rempel priv->state = TSC2046_STATE_POLL_IRQ_DISABLE; 54384e5d889SOleksij Rempel enable_irq(priv->spi->irq); 54484e5d889SOleksij Rempel } else { 54584e5d889SOleksij Rempel priv->state = TSC2046_STATE_POLL; 54684e5d889SOleksij Rempel } 54784e5d889SOleksij Rempel } else { 54884e5d889SOleksij Rempel priv->state = TSC2046_STATE_STANDBY; 54984e5d889SOleksij Rempel enable_irq(priv->spi->irq); 55084e5d889SOleksij Rempel } 55184e5d889SOleksij Rempel break; 55284e5d889SOleksij Rempel case TSC2046_STATE_POLL_IRQ_DISABLE: 5539374e8f5SOleksij Rempel disable_irq_nosync(priv->spi->irq); 55484e5d889SOleksij Rempel fallthrough; 55584e5d889SOleksij Rempel case TSC2046_STATE_POLL: 55684e5d889SOleksij Rempel priv->state = TSC2046_STATE_ENABLE_IRQ; 55784e5d889SOleksij Rempel /* iio_trigger_poll() starts hrtimer */ 5589374e8f5SOleksij Rempel iio_trigger_poll(priv->trig); 55984e5d889SOleksij Rempel break; 56084e5d889SOleksij Rempel case TSC2046_STATE_SHUTDOWN: 56184e5d889SOleksij Rempel break; 56284e5d889SOleksij Rempel case TSC2046_STATE_STANDBY: 56384e5d889SOleksij Rempel fallthrough; 56484e5d889SOleksij Rempel default: 56584e5d889SOleksij Rempel dev_warn(&priv->spi->dev, "Got unexpected state: %i\n", 56684e5d889SOleksij Rempel priv->state); 56784e5d889SOleksij Rempel break; 56884e5d889SOleksij Rempel } 56984e5d889SOleksij Rempel spin_unlock_irqrestore(&priv->state_lock, flags); 5709374e8f5SOleksij Rempel 5719374e8f5SOleksij Rempel return HRTIMER_NORESTART; 5729374e8f5SOleksij Rempel } 5739374e8f5SOleksij Rempel 5749374e8f5SOleksij Rempel static irqreturn_t tsc2046_adc_irq(int irq, void *dev_id) 5759374e8f5SOleksij Rempel { 5769374e8f5SOleksij Rempel struct iio_dev *indio_dev = dev_id; 5779374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 57884e5d889SOleksij Rempel unsigned long flags; 5799374e8f5SOleksij Rempel 5809374e8f5SOleksij Rempel hrtimer_try_to_cancel(&priv->trig_timer); 5819374e8f5SOleksij Rempel 58284e5d889SOleksij Rempel spin_lock_irqsave(&priv->state_lock, flags); 58384e5d889SOleksij Rempel if (priv->state != TSC2046_STATE_SHUTDOWN) { 58484e5d889SOleksij Rempel priv->state = TSC2046_STATE_ENABLE_IRQ; 58584e5d889SOleksij Rempel priv->poll_cnt = 0; 58684e5d889SOleksij Rempel 58784e5d889SOleksij Rempel /* iio_trigger_poll() starts hrtimer */ 5889374e8f5SOleksij Rempel disable_irq_nosync(priv->spi->irq); 5899374e8f5SOleksij Rempel iio_trigger_poll(priv->trig); 59084e5d889SOleksij Rempel } 59184e5d889SOleksij Rempel spin_unlock_irqrestore(&priv->state_lock, flags); 5929374e8f5SOleksij Rempel 5939374e8f5SOleksij Rempel return IRQ_HANDLED; 5949374e8f5SOleksij Rempel } 5959374e8f5SOleksij Rempel 5969374e8f5SOleksij Rempel static void tsc2046_adc_reenable_trigger(struct iio_trigger *trig) 5979374e8f5SOleksij Rempel { 5989374e8f5SOleksij Rempel struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 5999374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 60084e5d889SOleksij Rempel ktime_t tim; 6019374e8f5SOleksij Rempel 6029374e8f5SOleksij Rempel /* 6039374e8f5SOleksij Rempel * We can sample it as fast as we can, but usually we do not need so 6049374e8f5SOleksij Rempel * many samples. Reduce the sample rate for default (touchscreen) use 6059374e8f5SOleksij Rempel * case. 6069374e8f5SOleksij Rempel */ 60784e5d889SOleksij Rempel tim = ns_to_ktime((priv->scan_interval_us - priv->time_per_scan_us) * 60884e5d889SOleksij Rempel NSEC_PER_USEC); 60984e5d889SOleksij Rempel hrtimer_start(&priv->trig_timer, tim, HRTIMER_MODE_REL_SOFT); 6109374e8f5SOleksij Rempel } 6119374e8f5SOleksij Rempel 6129374e8f5SOleksij Rempel static int tsc2046_adc_set_trigger_state(struct iio_trigger *trig, bool enable) 6139374e8f5SOleksij Rempel { 6149374e8f5SOleksij Rempel struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); 6159374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv = iio_priv(indio_dev); 61684e5d889SOleksij Rempel unsigned long flags; 6179374e8f5SOleksij Rempel 6189374e8f5SOleksij Rempel if (enable) { 61984e5d889SOleksij Rempel spin_lock_irqsave(&priv->state_lock, flags); 62084e5d889SOleksij Rempel if (priv->state == TSC2046_STATE_SHUTDOWN) { 62184e5d889SOleksij Rempel priv->state = TSC2046_STATE_STANDBY; 6229374e8f5SOleksij Rempel enable_irq(priv->spi->irq); 62384e5d889SOleksij Rempel } 62484e5d889SOleksij Rempel spin_unlock_irqrestore(&priv->state_lock, flags); 6259374e8f5SOleksij Rempel } else { 62684e5d889SOleksij Rempel spin_lock_irqsave(&priv->state_lock, flags); 62784e5d889SOleksij Rempel 62884e5d889SOleksij Rempel if (priv->state == TSC2046_STATE_STANDBY || 62984e5d889SOleksij Rempel priv->state == TSC2046_STATE_POLL_IRQ_DISABLE) 63084e5d889SOleksij Rempel disable_irq_nosync(priv->spi->irq); 63184e5d889SOleksij Rempel 63284e5d889SOleksij Rempel priv->state = TSC2046_STATE_SHUTDOWN; 63384e5d889SOleksij Rempel spin_unlock_irqrestore(&priv->state_lock, flags); 63484e5d889SOleksij Rempel 63584e5d889SOleksij Rempel hrtimer_cancel(&priv->trig_timer); 6369374e8f5SOleksij Rempel } 6379374e8f5SOleksij Rempel 6389374e8f5SOleksij Rempel return 0; 6399374e8f5SOleksij Rempel } 6409374e8f5SOleksij Rempel 6419374e8f5SOleksij Rempel static const struct iio_trigger_ops tsc2046_adc_trigger_ops = { 6429374e8f5SOleksij Rempel .set_trigger_state = tsc2046_adc_set_trigger_state, 6439374e8f5SOleksij Rempel .reenable = tsc2046_adc_reenable_trigger, 6449374e8f5SOleksij Rempel }; 6459374e8f5SOleksij Rempel 6469374e8f5SOleksij Rempel static int tsc2046_adc_setup_spi_msg(struct tsc2046_adc_priv *priv) 6479374e8f5SOleksij Rempel { 6489374e8f5SOleksij Rempel unsigned int ch_idx; 6499374e8f5SOleksij Rempel size_t size; 6509374e8f5SOleksij Rempel int ret; 6519374e8f5SOleksij Rempel 6529374e8f5SOleksij Rempel /* 6539374e8f5SOleksij Rempel * Make dummy read to set initial power state and get real SPI clock 6549374e8f5SOleksij Rempel * freq. It seems to be not important which channel is used for this 6559374e8f5SOleksij Rempel * case. 6569374e8f5SOleksij Rempel */ 6579374e8f5SOleksij Rempel ret = tsc2046_adc_read_one(priv, TI_TSC2046_ADDR_TEMP0, 6589374e8f5SOleksij Rempel &priv->effective_speed_hz); 6599374e8f5SOleksij Rempel if (ret < 0) 6609374e8f5SOleksij Rempel return ret; 6619374e8f5SOleksij Rempel 6629374e8f5SOleksij Rempel /* 6639374e8f5SOleksij Rempel * In case SPI controller do not report effective_speed_hz, use 6649374e8f5SOleksij Rempel * configure value and hope it will match. 6659374e8f5SOleksij Rempel */ 6669374e8f5SOleksij Rempel if (!priv->effective_speed_hz) 6679374e8f5SOleksij Rempel priv->effective_speed_hz = priv->spi->max_speed_hz; 6689374e8f5SOleksij Rempel 6699374e8f5SOleksij Rempel 6709374e8f5SOleksij Rempel priv->scan_interval_us = TI_TSC2046_SAMPLE_INTERVAL_US; 6719374e8f5SOleksij Rempel priv->time_per_bit_ns = DIV_ROUND_UP(NSEC_PER_SEC, 6729374e8f5SOleksij Rempel priv->effective_speed_hz); 6739374e8f5SOleksij Rempel 6749374e8f5SOleksij Rempel /* 6759374e8f5SOleksij Rempel * Calculate and allocate maximal size buffer if all channels are 6769374e8f5SOleksij Rempel * enabled. 6779374e8f5SOleksij Rempel */ 6789374e8f5SOleksij Rempel size = 0; 6799374e8f5SOleksij Rempel for (ch_idx = 0; ch_idx < priv->dcfg->num_channels; ch_idx++) 6809374e8f5SOleksij Rempel size += tsc2046_adc_group_set_layout(priv, ch_idx, ch_idx); 6819374e8f5SOleksij Rempel 682*576434fdSOleksij Rempel if (size > PAGE_SIZE) { 683*576434fdSOleksij Rempel dev_err(&priv->spi->dev, 684*576434fdSOleksij Rempel "Calculated scan buffer is too big. Try to reduce spi-max-frequency, settling-time-us or oversampling-ratio\n"); 685*576434fdSOleksij Rempel return -ENOSPC; 686*576434fdSOleksij Rempel } 687*576434fdSOleksij Rempel 6889374e8f5SOleksij Rempel priv->tx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); 6899374e8f5SOleksij Rempel if (!priv->tx) 6909374e8f5SOleksij Rempel return -ENOMEM; 6919374e8f5SOleksij Rempel 6929374e8f5SOleksij Rempel priv->rx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); 6939374e8f5SOleksij Rempel if (!priv->rx) 6949374e8f5SOleksij Rempel return -ENOMEM; 6959374e8f5SOleksij Rempel 6969374e8f5SOleksij Rempel priv->xfer.tx_buf = priv->tx; 6979374e8f5SOleksij Rempel priv->xfer.rx_buf = priv->rx; 6989374e8f5SOleksij Rempel priv->xfer.len = size; 6999374e8f5SOleksij Rempel spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); 7009374e8f5SOleksij Rempel 7019374e8f5SOleksij Rempel return 0; 7029374e8f5SOleksij Rempel } 7039374e8f5SOleksij Rempel 7049374e8f5SOleksij Rempel static void tsc2046_adc_parse_fwnode(struct tsc2046_adc_priv *priv) 7059374e8f5SOleksij Rempel { 7069374e8f5SOleksij Rempel struct fwnode_handle *child; 7079374e8f5SOleksij Rempel struct device *dev = &priv->spi->dev; 7089374e8f5SOleksij Rempel unsigned int i; 7099374e8f5SOleksij Rempel 7109374e8f5SOleksij Rempel for (i = 0; i < ARRAY_SIZE(priv->ch_cfg); i++) { 7119374e8f5SOleksij Rempel priv->ch_cfg[i].settling_time_us = 1; 7129374e8f5SOleksij Rempel priv->ch_cfg[i].oversampling_ratio = 1; 7139374e8f5SOleksij Rempel } 7149374e8f5SOleksij Rempel 7159374e8f5SOleksij Rempel device_for_each_child_node(dev, child) { 7169374e8f5SOleksij Rempel u32 stl, overs, reg; 7179374e8f5SOleksij Rempel int ret; 7189374e8f5SOleksij Rempel 7199374e8f5SOleksij Rempel ret = fwnode_property_read_u32(child, "reg", ®); 7209374e8f5SOleksij Rempel if (ret) { 7219374e8f5SOleksij Rempel dev_err(dev, "invalid reg on %pfw, err: %pe\n", child, 7229374e8f5SOleksij Rempel ERR_PTR(ret)); 7239374e8f5SOleksij Rempel continue; 7249374e8f5SOleksij Rempel } 7259374e8f5SOleksij Rempel 7269374e8f5SOleksij Rempel if (reg >= ARRAY_SIZE(priv->ch_cfg)) { 7279374e8f5SOleksij Rempel dev_err(dev, "%pfw: Unsupported reg value: %i, max supported is: %zu.\n", 7289374e8f5SOleksij Rempel child, reg, ARRAY_SIZE(priv->ch_cfg)); 7299374e8f5SOleksij Rempel continue; 7309374e8f5SOleksij Rempel } 7319374e8f5SOleksij Rempel 7329374e8f5SOleksij Rempel ret = fwnode_property_read_u32(child, "settling-time-us", &stl); 7339374e8f5SOleksij Rempel if (!ret) 7349374e8f5SOleksij Rempel priv->ch_cfg[reg].settling_time_us = stl; 7359374e8f5SOleksij Rempel 7369374e8f5SOleksij Rempel ret = fwnode_property_read_u32(child, "oversampling-ratio", 7379374e8f5SOleksij Rempel &overs); 7389374e8f5SOleksij Rempel if (!ret) 7399374e8f5SOleksij Rempel priv->ch_cfg[reg].oversampling_ratio = overs; 7409374e8f5SOleksij Rempel } 7419374e8f5SOleksij Rempel } 7429374e8f5SOleksij Rempel 7439374e8f5SOleksij Rempel static int tsc2046_adc_probe(struct spi_device *spi) 7449374e8f5SOleksij Rempel { 7459374e8f5SOleksij Rempel const struct tsc2046_adc_dcfg *dcfg; 7469374e8f5SOleksij Rempel struct device *dev = &spi->dev; 7479374e8f5SOleksij Rempel struct tsc2046_adc_priv *priv; 7489374e8f5SOleksij Rempel struct iio_dev *indio_dev; 7499374e8f5SOleksij Rempel struct iio_trigger *trig; 7509374e8f5SOleksij Rempel int ret; 7519374e8f5SOleksij Rempel 7529374e8f5SOleksij Rempel if (spi->max_speed_hz > TI_TSC2046_MAX_CLK_FREQ) { 7539374e8f5SOleksij Rempel dev_err(dev, "SPI max_speed_hz is too high: %d Hz. Max supported freq is %zu Hz\n", 7549374e8f5SOleksij Rempel spi->max_speed_hz, TI_TSC2046_MAX_CLK_FREQ); 7559374e8f5SOleksij Rempel return -EINVAL; 7569374e8f5SOleksij Rempel } 7579374e8f5SOleksij Rempel 7589374e8f5SOleksij Rempel dcfg = device_get_match_data(dev); 7599374e8f5SOleksij Rempel if (!dcfg) 7609374e8f5SOleksij Rempel return -EINVAL; 7619374e8f5SOleksij Rempel 7629374e8f5SOleksij Rempel spi->bits_per_word = 8; 7639374e8f5SOleksij Rempel spi->mode &= ~SPI_MODE_X_MASK; 7649374e8f5SOleksij Rempel spi->mode |= SPI_MODE_0; 7659374e8f5SOleksij Rempel ret = spi_setup(spi); 7669374e8f5SOleksij Rempel if (ret < 0) 7679374e8f5SOleksij Rempel return dev_err_probe(dev, ret, "Error in SPI setup\n"); 7689374e8f5SOleksij Rempel 7699374e8f5SOleksij Rempel indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); 7709374e8f5SOleksij Rempel if (!indio_dev) 7719374e8f5SOleksij Rempel return -ENOMEM; 7729374e8f5SOleksij Rempel 7739374e8f5SOleksij Rempel priv = iio_priv(indio_dev); 7749374e8f5SOleksij Rempel priv->dcfg = dcfg; 7759374e8f5SOleksij Rempel 7769374e8f5SOleksij Rempel priv->spi = spi; 7779374e8f5SOleksij Rempel 7789374e8f5SOleksij Rempel indio_dev->name = TI_TSC2046_NAME; 7799374e8f5SOleksij Rempel indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED; 7809374e8f5SOleksij Rempel indio_dev->channels = dcfg->channels; 7819374e8f5SOleksij Rempel indio_dev->num_channels = dcfg->num_channels; 7829374e8f5SOleksij Rempel indio_dev->info = &tsc2046_adc_info; 7839374e8f5SOleksij Rempel 7849374e8f5SOleksij Rempel tsc2046_adc_parse_fwnode(priv); 7859374e8f5SOleksij Rempel 7869374e8f5SOleksij Rempel ret = tsc2046_adc_setup_spi_msg(priv); 7879374e8f5SOleksij Rempel if (ret) 7889374e8f5SOleksij Rempel return ret; 7899374e8f5SOleksij Rempel 7909374e8f5SOleksij Rempel mutex_init(&priv->slock); 7919374e8f5SOleksij Rempel 7929374e8f5SOleksij Rempel ret = devm_request_irq(dev, spi->irq, &tsc2046_adc_irq, 7939374e8f5SOleksij Rempel IRQF_NO_AUTOEN, indio_dev->name, indio_dev); 7949374e8f5SOleksij Rempel if (ret) 7959374e8f5SOleksij Rempel return ret; 7969374e8f5SOleksij Rempel 7979374e8f5SOleksij Rempel trig = devm_iio_trigger_alloc(dev, "touchscreen-%s", indio_dev->name); 7989374e8f5SOleksij Rempel if (!trig) 7999374e8f5SOleksij Rempel return -ENOMEM; 8009374e8f5SOleksij Rempel 8019374e8f5SOleksij Rempel priv->trig = trig; 8029374e8f5SOleksij Rempel iio_trigger_set_drvdata(trig, indio_dev); 8039374e8f5SOleksij Rempel trig->ops = &tsc2046_adc_trigger_ops; 8049374e8f5SOleksij Rempel 80584e5d889SOleksij Rempel spin_lock_init(&priv->state_lock); 80684e5d889SOleksij Rempel priv->state = TSC2046_STATE_SHUTDOWN; 8079374e8f5SOleksij Rempel hrtimer_init(&priv->trig_timer, CLOCK_MONOTONIC, 8089374e8f5SOleksij Rempel HRTIMER_MODE_REL_SOFT); 80984e5d889SOleksij Rempel priv->trig_timer.function = tsc2046_adc_timer; 8109374e8f5SOleksij Rempel 8119374e8f5SOleksij Rempel ret = devm_iio_trigger_register(dev, trig); 8129374e8f5SOleksij Rempel if (ret) { 8139374e8f5SOleksij Rempel dev_err(dev, "failed to register trigger\n"); 8149374e8f5SOleksij Rempel return ret; 8159374e8f5SOleksij Rempel } 8169374e8f5SOleksij Rempel 8179374e8f5SOleksij Rempel ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, 8189374e8f5SOleksij Rempel &tsc2046_adc_trigger_handler, NULL); 8199374e8f5SOleksij Rempel if (ret) { 8209374e8f5SOleksij Rempel dev_err(dev, "Failed to setup triggered buffer\n"); 8219374e8f5SOleksij Rempel return ret; 8229374e8f5SOleksij Rempel } 8239374e8f5SOleksij Rempel 8249374e8f5SOleksij Rempel /* set default trigger */ 8259374e8f5SOleksij Rempel indio_dev->trig = iio_trigger_get(priv->trig); 8269374e8f5SOleksij Rempel 8279374e8f5SOleksij Rempel return devm_iio_device_register(dev, indio_dev); 8289374e8f5SOleksij Rempel } 8299374e8f5SOleksij Rempel 8309374e8f5SOleksij Rempel static const struct of_device_id ads7950_of_table[] = { 8319374e8f5SOleksij Rempel { .compatible = "ti,tsc2046e-adc", .data = &tsc2046_adc_dcfg_tsc2046e }, 8329374e8f5SOleksij Rempel { } 8339374e8f5SOleksij Rempel }; 8349374e8f5SOleksij Rempel MODULE_DEVICE_TABLE(of, ads7950_of_table); 8359374e8f5SOleksij Rempel 8369374e8f5SOleksij Rempel static struct spi_driver tsc2046_adc_driver = { 8379374e8f5SOleksij Rempel .driver = { 8389374e8f5SOleksij Rempel .name = "tsc2046", 8399374e8f5SOleksij Rempel .of_match_table = ads7950_of_table, 8409374e8f5SOleksij Rempel }, 8419374e8f5SOleksij Rempel .probe = tsc2046_adc_probe, 8429374e8f5SOleksij Rempel }; 8439374e8f5SOleksij Rempel module_spi_driver(tsc2046_adc_driver); 8449374e8f5SOleksij Rempel 8459374e8f5SOleksij Rempel MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>"); 8469374e8f5SOleksij Rempel MODULE_DESCRIPTION("TI TSC2046 ADC"); 8479374e8f5SOleksij Rempel MODULE_LICENSE("GPL v2"); 848