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