1 /**
2  * Copyright (c) 2023 Antmicro <www.antmicro.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #define DT_DRV_COMPAT st_stmpe811
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/gpio.h>
9 #include <zephyr/drivers/i2c.h>
10 #include <zephyr/input/input.h>
11 #include <zephyr/input/input_touch.h>
12 #include <zephyr/sys/byteorder.h>
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(stmpe811, CONFIG_INPUT_LOG_LEVEL);
16 
17 #define CHIP_ID 0x0811U
18 
19 /* Touch Screen Pins definition */
20 #define STMPE811_GPIO_PIN_4 BIT(4)
21 #define STMPE811_GPIO_PIN_5 BIT(5)
22 #define STMPE811_GPIO_PIN_6 BIT(6)
23 #define STMPE811_GPIO_PIN_7 BIT(7)
24 
25 #define STMPE811_TOUCH_YD STMPE811_GPIO_PIN_7
26 #define STMPE811_TOUCH_XD STMPE811_GPIO_PIN_6
27 #define STMPE811_TOUCH_YU STMPE811_GPIO_PIN_5
28 #define STMPE811_TOUCH_XU STMPE811_GPIO_PIN_4
29 #define STMPE811_TOUCH_IO_ALL                                                                      \
30 	(STMPE811_TOUCH_YD | STMPE811_TOUCH_XD | STMPE811_TOUCH_YU | STMPE811_TOUCH_XU)
31 
32 /* Registers */
33 #define STMPE811_CHP_ID_LSB_REG       0x00U
34 #define STMPE811_ADC_CTRL1_REG        0x20U
35 #define STMPE811_ADC_CTRL2_REG        0x21U
36 #define STMPE811_SYS_CTRL1_REG        0x03U
37 #define STMPE811_SYS_CTRL2_REG        0x04U
38 #define STMPE811_TSC_CFG_REG          0x41U
39 #define STMPE811_IO_AF_REG            0x17U
40 #define STMPE811_FIFO_TH_REG          0x4AU
41 #define STMPE811_FIFO_STA_REG         0x4BU
42 #define STMPE811_FIFO_SIZE_REG        0x4CU
43 #define STMPE811_TSC_FRACT_XYZ_REG    0x56U
44 #define STMPE811_TSC_I_DRIVE_REG      0x58U
45 #define STMPE811_TSC_CTRL_REG         0x40U
46 #define STMPE811_INT_STA_REG          0x0BU
47 #define STMPE811_TSC_DATA_NON_INC_REG 0xD7U
48 #define STMPE811_INT_CTRL_REG         0x09U
49 #define STMPE811_INT_EN_REG           0x0AU
50 
51 /* Touch detected bit */
52 #define STMPE811_TSC_CTRL_BIT_TOUCH_DET BIT(7)
53 
54 /* Global interrupt enable bit */
55 #define STMPE811_INT_CTRL_BIT_GLOBAL_INT BIT(0)
56 
57 /* IO expander functionalities */
58 #define STMPE811_SYS_CTRL2_BIT_ADC_FCT BIT(0)
59 #define STMPE811_SYS_CTRL2_BIT_TS_FCT  BIT(1)
60 #define STMPE811_SYS_CTRL2_BIT_IO_FCT  BIT(2)
61 
62 /* Global Interrupts definitions */
63 #define STMPE811_INT_BIT_FIFO_THRESHOLD  BIT(1)       /* FIFO above threshold interrupt       */
64 #define STMPE811_INT_BIT_TOUCH           BIT(0)       /* Touch/release is detected interrupt  */
65 #define STMPE811_INT_ALL		 BIT_MASK(8)  /* All interrupts */
66 
67 /* Reset control */
68 #define STMPE811_SYS_CTRL1_RESET_ON   0
69 #define STMPE811_SYS_CTRL1_RESET_SOFT BIT(1) /* Soft reset */
70 
71 /* Delays to ensure registers erasing */
72 #define STMPE811_RESET_DELAY_MS 10
73 #define STMPE811_WAIT_DELAY_MS  2
74 
75 /* Configuration */
76 #define STMPE811_FIFO_TH_SINGLE_POINT 1
77 #define STMPE811_FIFO_STA_CLEAR       1
78 #define STMPE811_FIFO_STA_OPERATIONAL 0
79 #define STMPE811_TSC_I_DRIVE_LIMIT    1
80 
81 /**
82  * Touch Screen Control
83  *
84  * - bits [1-3]   X, Y only acquisition mode
85  */
86 #define STMPE811_TSC_CTRL_CONF 3U
87 
88 /**
89  * Analog-to-digital Converter
90  *
91  * - bit  [3]   selects 12 bit ADC
92  * - bits [4-6] select ADC conversion time = 80
93  */
94 #define STMPE811_ADC_CTRL1_CONF 0x48U
95 
96 /**
97  * ADC clock speed: 3.25 MHz
98  *
99  * - 00 : 1.625 MHz
100  * - 01 : 3.25  MHz
101  * - 10 : 6.5   MHz
102  * - 11 : 6.5   MHz
103  */
104 #define STMPE811_ADC_CLOCK_SPEED 1
105 
106 /**
107  * Range and accuracy of the pressure measurement (Z)
108  *
109  * - Fractional part : 7
110  * - Whole part      : 1
111  */
112 #define STMPE811_TSC_FRACT_XYZ_CONF 1
113 
114 struct stmpe811_config {
115 	struct input_touchscreen_common_config common;
116 	struct i2c_dt_spec bus;
117 	struct gpio_dt_spec int_gpio;
118 	uint8_t panel_driver_settling_time_us;
119 	uint8_t touch_detect_delay_us;
120 	uint8_t touch_average_control;
121 	uint8_t tracking_index;
122 	int raw_x_min;
123 	int raw_y_min;
124 	uint16_t raw_x_max;
125 	uint16_t raw_y_max;
126 };
127 
128 struct stmpe811_data {
129 	const struct device *dev;
130 	struct k_work processing_work;
131 	struct gpio_callback int_gpio_cb;
132 	uint32_t touch_x;
133 	uint32_t touch_y;
134 };
135 
136 INPUT_TOUCH_STRUCT_CHECK(struct stmpe811_config);
137 
stmpe811_reset(const struct device * dev)138 static int stmpe811_reset(const struct device *dev)
139 {
140 	const struct stmpe811_config *config = dev->config;
141 
142 	/* Power down the stmpe811 */
143 	int ret = i2c_reg_write_byte_dt(&config->bus, STMPE811_SYS_CTRL1_REG,
144 					STMPE811_SYS_CTRL1_RESET_SOFT);
145 
146 	if (ret < 0) {
147 		return ret;
148 	}
149 	k_msleep(STMPE811_RESET_DELAY_MS);
150 
151 	/* Power on the stmpe811 after the power off => all registers are reinitialized */
152 	ret = i2c_reg_write_byte_dt(&config->bus, STMPE811_SYS_CTRL1_REG,
153 				    STMPE811_SYS_CTRL1_RESET_ON);
154 	if (ret < 0) {
155 		return ret;
156 	}
157 	k_msleep(STMPE811_WAIT_DELAY_MS);
158 
159 	return 0;
160 }
161 
stmpe811_io_enable_af(const struct device * dev,uint32_t io_pin)162 static int stmpe811_io_enable_af(const struct device *dev, uint32_t io_pin)
163 {
164 	const struct stmpe811_config *config = dev->config;
165 
166 	/* Apply ~io_pin as a mask to the current register value */
167 	return i2c_reg_update_byte_dt(&config->bus, STMPE811_IO_AF_REG, io_pin, 0);
168 }
169 
stmpe811_tsc_config_bits(const struct device * dev)170 static uint8_t stmpe811_tsc_config_bits(const struct device *dev)
171 {
172 	const struct stmpe811_config *config = dev->config;
173 
174 	/**
175 	 * Configuration:
176 	 * - bits [0-2] : panel driver settling time
177 	 * - bits [3-5] : touch detect delay
178 	 * - bits [6-7] : touch average control
179 	 */
180 
181 	return config->panel_driver_settling_time_us | config->touch_detect_delay_us << 3 |
182 	       config->touch_average_control << 6;
183 }
184 
stmpe811_tsc_control_bits(const struct device * dev)185 static uint8_t stmpe811_tsc_control_bits(const struct device *dev)
186 {
187 	const struct stmpe811_config *config = dev->config;
188 
189 	/**
190 	 * Touch Screen Control
191 	 *
192 	 * - bit  [0]     enables TSC
193 	 * - bits [1-3]   X, Y only acquisition mode
194 	 * - bits [4-6]   window tracking index (set from config)
195 	 * - bit  [7]     TSC status (writing has no effect)
196 	 */
197 
198 	return STMPE811_TSC_CTRL_CONF | config->tracking_index << 4;
199 }
200 
stmpe811_ts_init(const struct device * dev)201 static int stmpe811_ts_init(const struct device *dev)
202 {
203 	const struct stmpe811_config *config = dev->config;
204 	int err;
205 
206 	err = stmpe811_reset(dev);
207 	if (err < 0) {
208 		return err;
209 	}
210 
211 	/* Select TSC pins in TSC alternate mode */
212 	err = stmpe811_io_enable_af(dev, STMPE811_TOUCH_IO_ALL);
213 	if (err < 0) {
214 		return err;
215 	}
216 
217 	/**
218 	 * Set the functionalities to be enabled
219 	 * Bits [0-3] disable functionalities if set to 1 (reset value: 0x0f)
220 	 *
221 	 * Apply inverted sum of chosen FCT bits as a mask to the currect register value
222 	 */
223 	err = i2c_reg_update_byte_dt(&config->bus, STMPE811_SYS_CTRL2_REG,
224 				     STMPE811_SYS_CTRL2_BIT_IO_FCT | STMPE811_SYS_CTRL2_BIT_TS_FCT |
225 				     STMPE811_SYS_CTRL2_BIT_ADC_FCT, 0);
226 	if (err < 0) {
227 		return err;
228 	}
229 
230 	/* Select sample time, bit number and ADC reference */
231 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_ADC_CTRL1_REG, STMPE811_ADC_CTRL1_CONF);
232 	if (err < 0) {
233 		return err;
234 	}
235 
236 	/* Select the ADC clock speed */
237 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_ADC_CTRL2_REG, STMPE811_ADC_CLOCK_SPEED);
238 	if (err < 0) {
239 		return err;
240 	}
241 
242 	/* Touch screen configuration */
243 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_CFG_REG,
244 				    stmpe811_tsc_config_bits(dev));
245 	if (err < 0) {
246 		return err;
247 	}
248 
249 	/* Configure the touch FIFO threshold */
250 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_FIFO_TH_REG,
251 				    STMPE811_FIFO_TH_SINGLE_POINT);
252 	if (err < 0) {
253 		return err;
254 	}
255 
256 	/* Clear the FIFO memory content */
257 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_FIFO_STA_REG, STMPE811_FIFO_STA_CLEAR);
258 	if (err < 0) {
259 		return err;
260 	}
261 
262 	/* Set the range and accuracy of the pressure measurement (Z) */
263 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_FRACT_XYZ_REG,
264 				    STMPE811_TSC_FRACT_XYZ_CONF);
265 	if (err < 0) {
266 		return err;
267 	}
268 
269 	/* Set the driving capability (limit) of the device for TSC pins */
270 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_I_DRIVE_REG,
271 				    STMPE811_TSC_I_DRIVE_LIMIT);
272 	if (err < 0) {
273 		return err;
274 	}
275 
276 	/* Touch screen control configuration */
277 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_TSC_CTRL_REG,
278 				    stmpe811_tsc_control_bits(dev));
279 	if (err < 0) {
280 		return err;
281 	}
282 
283 	/**
284 	 * Clear all the status pending bits if any.
285 	 * Writing '1' to this register clears the corresponding bits.
286 	 * This is an 8-bit register, so writing 0xFF clears all.
287 	 */
288 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_STA_REG, STMPE811_INT_ALL);
289 	if (err < 0) {
290 		return err;
291 	}
292 
293 	/* Put the FIFO back into operation mode */
294 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_FIFO_STA_REG,
295 				    STMPE811_FIFO_STA_OPERATIONAL);
296 	if (err < 0) {
297 		return err;
298 	}
299 
300 	/* Enable FIFO and touch interrupts */
301 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_EN_REG,
302 				    STMPE811_INT_BIT_TOUCH | STMPE811_INT_BIT_FIFO_THRESHOLD);
303 	if (err < 0) {
304 		LOG_ERR("Could not enable interrupt types (%d)", err);
305 		return err;
306 	}
307 
308 	return 0;
309 }
310 
stmpe811_ts_get_data(const struct device * dev)311 static int stmpe811_ts_get_data(const struct device *dev)
312 {
313 	const struct stmpe811_config *config = dev->config;
314 	struct stmpe811_data *data = dev->data;
315 
316 	uint8_t data_xy[3];
317 	uint32_t uldata_xy;
318 
319 	int ret = i2c_burst_read_dt(&config->bus, STMPE811_TSC_DATA_NON_INC_REG, data_xy,
320 				    sizeof(data_xy));
321 	if (ret < 0) {
322 		return ret;
323 	}
324 
325 	/* Calculate positions values */
326 	uldata_xy = (data_xy[0] << 16) | (data_xy[1] << 8) | data_xy[2];
327 	data->touch_x = (uldata_xy >> 12U) & BIT_MASK(12);
328 	data->touch_y = uldata_xy & BIT_MASK(12);
329 
330 	return 0;
331 }
332 
stmpe811_report_touch(const struct device * dev)333 static void stmpe811_report_touch(const struct device *dev)
334 {
335 	const struct stmpe811_config *config = dev->config;
336 	const struct input_touchscreen_common_config *common = &config->common;
337 	struct stmpe811_data *data = dev->data;
338 	int x = data->touch_x;
339 	int y = data->touch_y;
340 
341 	if (common->screen_width > 0 && common->screen_height > 0) {
342 		x = (((int)data->touch_x - config->raw_x_min) * common->screen_width) /
343 			(config->raw_x_max - config->raw_x_min);
344 		y = (((int)data->touch_y - config->raw_y_min) * common->screen_height) /
345 			(config->raw_y_max - config->raw_y_min);
346 
347 		x = CLAMP(x, 0, common->screen_width);
348 		y = CLAMP(y, 0, common->screen_height);
349 	}
350 
351 	input_touchscreen_report_pos(dev, x, y, K_FOREVER);
352 	input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER);
353 }
354 
stmpe811_process(const struct device * dev)355 static int stmpe811_process(const struct device *dev)
356 {
357 	const struct stmpe811_config *config = dev->config;
358 
359 	int err;
360 	uint8_t int_sta, fifo_size, tsc_ctrl;
361 
362 	err = i2c_reg_read_byte_dt(&config->bus, STMPE811_INT_STA_REG, &int_sta);
363 	if (err < 0) {
364 		return err;
365 	}
366 
367 	/* Clear processed interrupts */
368 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_STA_REG, int_sta);
369 	if (err < 0) {
370 		return err;
371 	}
372 
373 	if (int_sta & STMPE811_INT_BIT_FIFO_THRESHOLD) {
374 		/**
375 		 * Report every element in FIFO
376 		 *
377 		 * This requires a while loop to avoid a race condition
378 		 * in which an element is added after reading FIFO_SIZE.
379 		 *
380 		 * Exiting ISR without handling every element in FIFO
381 		 * would prevent FIFO_THRESHOLD interrupt from being triggered again.
382 		 */
383 		while (true) {
384 			err = i2c_reg_read_byte_dt(&config->bus, STMPE811_FIFO_SIZE_REG,
385 						   &fifo_size);
386 			if (err < 0) {
387 				return err;
388 			}
389 
390 			if (fifo_size == 0) {
391 				break;
392 			}
393 
394 			for (int i = 0; i < fifo_size; i++) {
395 				err = stmpe811_ts_get_data(dev);
396 				if (err < 0) {
397 					return err;
398 				}
399 
400 				stmpe811_report_touch(dev);
401 			}
402 		}
403 	}
404 
405 	/* TOUCH interrupt also gets triggered at release */
406 	if (int_sta & STMPE811_INT_BIT_TOUCH) {
407 		err = i2c_reg_read_byte_dt(&config->bus, STMPE811_TSC_CTRL_REG, &tsc_ctrl);
408 		if (err < 0) {
409 			return err;
410 		}
411 
412 		/* TOUCH interrupt + no touch detected in TSC_CTRL reg <=> release */
413 		if (!(tsc_ctrl & STMPE811_TSC_CTRL_BIT_TOUCH_DET)) {
414 			input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER);
415 		}
416 	}
417 
418 	return 0;
419 }
420 
stmpe811_work_handler(struct k_work * work)421 static void stmpe811_work_handler(struct k_work *work)
422 {
423 	struct stmpe811_data *data = CONTAINER_OF(work, struct stmpe811_data, processing_work);
424 	const struct stmpe811_config *config = data->dev->config;
425 
426 	stmpe811_process(data->dev);
427 	/**
428 	 * Reschedule ISR if there was an interrupt triggered during handling (race condition).
429 	 * IRQ is edge-triggered, so otherwise it would never be triggered again.
430 	 */
431 	if (gpio_pin_get_dt(&config->int_gpio)) {
432 		k_work_submit(&data->processing_work);
433 	}
434 }
435 
stmpe811_interrupt_handler(const struct device * dev,struct gpio_callback * cb,uint32_t pins)436 static void stmpe811_interrupt_handler(const struct device *dev, struct gpio_callback *cb,
437 				       uint32_t pins)
438 {
439 	struct stmpe811_data *data = CONTAINER_OF(cb, struct stmpe811_data, int_gpio_cb);
440 
441 	k_work_submit(&data->processing_work);
442 }
443 
stmpe811_verify_chip_id(const struct device * dev)444 static int stmpe811_verify_chip_id(const struct device *dev)
445 {
446 	const struct stmpe811_config *config = dev->config;
447 	uint8_t buf[2];
448 
449 	i2c_burst_read_dt(&config->bus, STMPE811_CHP_ID_LSB_REG, buf, 2);
450 
451 	if (sys_get_be16(buf) != CHIP_ID) {
452 		return -EINVAL;
453 	}
454 
455 	return 0;
456 }
457 
stmpe811_init(const struct device * dev)458 static int stmpe811_init(const struct device *dev)
459 {
460 	const struct stmpe811_config *config = dev->config;
461 	struct stmpe811_data *data = dev->data;
462 	int err;
463 
464 	if (!i2c_is_ready_dt(&config->bus)) {
465 		LOG_ERR("I2C controller device not ready");
466 		return -ENODEV;
467 	}
468 
469 	data->dev = dev;
470 
471 	k_work_init(&data->processing_work, stmpe811_work_handler);
472 
473 	/* Verify CHIP_ID */
474 	err = stmpe811_verify_chip_id(dev);
475 	if (err) {
476 		LOG_ERR("CHIP ID verification failed (%d)", err);
477 		return err;
478 	}
479 
480 	/* Initialize */
481 	err = stmpe811_ts_init(dev);
482 	if (err) {
483 		LOG_ERR("Touch screen controller initialization failed (%d)", err);
484 		return err;
485 	}
486 
487 	/* Initialize GPIO interrupt */
488 	if (!gpio_is_ready_dt(&config->int_gpio)) {
489 		LOG_ERR("Interrupt GPIO controller device not ready");
490 		return -ENODEV;
491 	}
492 
493 	err = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
494 	if (err < 0) {
495 		LOG_ERR("Could not configure interrupt GPIO pin (%d)", err);
496 		return err;
497 	}
498 
499 	err = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
500 	if (err < 0) {
501 		LOG_ERR("Could not configure GPIO interrupt (%d)", err);
502 		return err;
503 	}
504 
505 	gpio_init_callback(&data->int_gpio_cb, stmpe811_interrupt_handler,
506 			   BIT(config->int_gpio.pin));
507 	err = gpio_add_callback_dt(&config->int_gpio, &data->int_gpio_cb);
508 	if (err < 0) {
509 		LOG_ERR("Could not set GPIO callback (%d)", err);
510 		return err;
511 	}
512 
513 	/* Enable global interrupts */
514 	err = i2c_reg_write_byte_dt(&config->bus, STMPE811_INT_CTRL_REG,
515 				    STMPE811_INT_CTRL_BIT_GLOBAL_INT);
516 	if (err < 0) {
517 		LOG_ERR("Could not enable global interrupts (%d)", err);
518 		return err;
519 	}
520 
521 	return 0;
522 }
523 
524 #define STMPE811_DEFINE(index)                                                                     \
525 	BUILD_ASSERT(DT_INST_PROP_OR(index, raw_x_max, 4096) >                                     \
526 		     DT_INST_PROP_OR(index, raw_x_min, 0),                                         \
527 		     "raw-x-max should be larger than raw-x-min");                                 \
528 	BUILD_ASSERT(DT_INST_PROP_OR(index, raw_y_max, 4096) >                                     \
529 		     DT_INST_PROP_OR(index, raw_y_min, 0),                                         \
530 		     "raw-y-max should be larger than raw-y-min");                                 \
531 	static const struct stmpe811_config stmpe811_config_##index = {                            \
532 		.common = INPUT_TOUCH_DT_INST_COMMON_CONFIG_INIT(index),                           \
533 		.bus = I2C_DT_SPEC_INST_GET(index),                                                \
534 		.int_gpio = GPIO_DT_SPEC_INST_GET(index, int_gpios),                               \
535 		.panel_driver_settling_time_us =                                                   \
536 			DT_INST_ENUM_IDX(index, panel_driver_settling_time_us),                    \
537 		.raw_x_min = DT_INST_PROP_OR(index, raw_x_min, 0),                                 \
538 		.raw_y_min = DT_INST_PROP_OR(index, raw_y_min, 0),                                 \
539 		.raw_x_max = DT_INST_PROP_OR(index, raw_x_max, 4096),                              \
540 		.raw_y_max = DT_INST_PROP_OR(index, raw_y_max, 4096),                              \
541 		.touch_detect_delay_us = DT_INST_ENUM_IDX(index, touch_detect_delay_us),           \
542 		.touch_average_control = DT_INST_ENUM_IDX(index, touch_average_control),           \
543 		.tracking_index = DT_INST_ENUM_IDX(index, tracking_index)};                        \
544 	static struct stmpe811_data stmpe811_data_##index;                                         \
545 	DEVICE_DT_INST_DEFINE(index, stmpe811_init, NULL, &stmpe811_data_##index,                  \
546 			      &stmpe811_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY,   \
547 			      NULL);
548 
549 DT_INST_FOREACH_STATUS_OKAY(STMPE811_DEFINE)
550