1 /*
2  * Copyright 2024 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT pixart_pmw3610
8 
9 #include <stdint.h>
10 #include <stdlib.h>
11 
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/spi.h>
15 #include <zephyr/input/input.h>
16 #include <zephyr/input/input_pmw3610.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/logging/log.h>
19 #include <zephyr/pm/device.h>
20 #include <zephyr/pm/device_runtime.h>
21 #include <zephyr/sys/byteorder.h>
22 #include <zephyr/sys/util.h>
23 
24 LOG_MODULE_REGISTER(input_pmw3610, CONFIG_INPUT_LOG_LEVEL);
25 
26 /* Page 0 */
27 #define PMW3610_PROD_ID		0x00
28 #define PMW3610_REV_ID		0x01
29 #define PMW3610_MOTION		0x02
30 #define PMW3610_DELTA_X_L	0x03
31 #define PMW3610_DELTA_Y_L	0x04
32 #define PMW3610_DELTA_XY_H	0x05
33 #define PMW3610_PERFORMANCE	0x11
34 #define PMW3610_BURST_READ	0x12
35 #define PMW3610_RUN_DOWNSHIFT	0x1b
36 #define PMW3610_REST1_RATE	0x1c
37 #define PMW3610_REST1_DOWNSHIFT	0x1d
38 #define PMW3610_OBSERVATION1	0x2d
39 #define PMW3610_SMART_MODE	0x32
40 #define PMW3610_POWER_UP_RESET	0x3a
41 #define PMW3610_SHUTDOWN	0x3b
42 #define PMW3610_SPI_CLK_ON_REQ	0x41
43 #define PWM3610_SPI_PAGE0	0x7f
44 
45 /* Page 1 */
46 #define PMW3610_RES_STEP	0x05
47 #define PWM3610_SPI_PAGE1	0x7f
48 
49 /* Burst register offsets */
50 #define BURST_MOTION		0
51 #define BURST_DELTA_X_L		1
52 #define BURST_DELTA_Y_L		2
53 #define BURST_DELTA_XY_H	3
54 #define BURST_SQUAL		4
55 #define BURST_SHUTTER_HI	5
56 #define BURST_SHUTTER_LO	6
57 
58 #define BURST_DATA_LEN_NORMAL	(BURST_DELTA_XY_H + 1)
59 #define BURST_DATA_LEN_SMART	(BURST_SHUTTER_LO + 1)
60 #define BURST_DATA_LEN_MAX	MAX(BURST_DATA_LEN_NORMAL, BURST_DATA_LEN_SMART)
61 
62 /* Init sequence values */
63 #define OBSERVATION1_INIT_MASK 0x0f
64 #define PERFORMANCE_INIT 0x0d
65 #define RUN_DOWNSHIFT_INIT 0x04
66 #define REST1_RATE_INIT 0x04
67 #define REST1_DOWNSHIFT_INIT 0x0f
68 
69 #define PRODUCT_ID_PMW3610 0x3e
70 #define SPI_WRITE BIT(7)
71 #define MOTION_STATUS_MOTION BIT(7)
72 #define SPI_CLOCK_ON_REQ_ON 0xba
73 #define SPI_CLOCK_ON_REQ_OFF 0xb5
74 #define RES_STEP_INV_X_BIT 6
75 #define RES_STEP_INV_Y_BIT 5
76 #define RES_STEP_RES_MASK 0x1f
77 #define PERFORMANCE_FMODE_MASK (0x0f << 4)
78 #define PERFORMANCE_FMODE_NORMAL (0x00 << 4)
79 #define PERFORMANCE_FMODE_FORCE_AWAKE (0x0f << 4)
80 #define POWER_UP_RESET 0x5a
81 #define POWER_UP_WAKEUP 0x96
82 #define SHUTDOWN_ENABLE 0xe7
83 #define SPI_PAGE0_1 0xff
84 #define SPI_PAGE1_0 0x00
85 #define SHUTTER_SMART_THRESHOLD 45
86 #define SMART_MODE_ENABLE 0x00
87 #define SMART_MODE_DISABLE 0x80
88 
89 #define PMW3610_DATA_SIZE_BITS 12
90 
91 #define RESET_DELAY_MS 10
92 #define INIT_OBSERVATION_DELAY_MS 10
93 #define CLOCK_ON_DELAY_US 300
94 
95 #define RES_STEP 200
96 #define RES_MIN 200
97 #define RES_MAX 3200
98 
99 struct pmw3610_config {
100 	struct spi_dt_spec spi;
101 	struct gpio_dt_spec motion_gpio;
102 	struct gpio_dt_spec reset_gpio;
103 	uint16_t axis_x;
104 	uint16_t axis_y;
105 	int16_t res_cpi;
106 	bool invert_x;
107 	bool invert_y;
108 	bool force_awake;
109 	bool smart_mode;
110 };
111 
112 struct pmw3610_data {
113 	const struct device *dev;
114 	struct k_work motion_work;
115 	struct gpio_callback motion_cb;
116 	bool smart_flag;
117 };
118 
pmw3610_read(const struct device * dev,uint8_t addr,uint8_t * value,uint8_t len)119 static int pmw3610_read(const struct device *dev,
120 			uint8_t addr, uint8_t *value, uint8_t len)
121 {
122 	const struct pmw3610_config *cfg = dev->config;
123 
124 	const struct spi_buf tx_buf = {
125 		.buf = &addr,
126 		.len = sizeof(addr),
127 	};
128 	const struct spi_buf_set tx = {
129 		.buffers = &tx_buf,
130 		.count = 1,
131 	};
132 
133 	struct spi_buf rx_buf[] = {
134 		{
135 			.buf = NULL,
136 			.len = sizeof(addr),
137 		},
138 		{
139 			.buf = value,
140 			.len = len,
141 		},
142 	};
143 	const struct spi_buf_set rx = {
144 		.buffers = rx_buf,
145 		.count = ARRAY_SIZE(rx_buf),
146 	};
147 
148 	return spi_transceive_dt(&cfg->spi, &tx, &rx);
149 }
150 
pmw3610_read_reg(const struct device * dev,uint8_t addr,uint8_t * value)151 static int pmw3610_read_reg(const struct device *dev, uint8_t addr, uint8_t *value)
152 {
153 	return pmw3610_read(dev, addr, value, 1);
154 }
155 
pmw3610_write_reg(const struct device * dev,uint8_t addr,uint8_t value)156 static int pmw3610_write_reg(const struct device *dev, uint8_t addr, uint8_t value)
157 {
158 	const struct pmw3610_config *cfg = dev->config;
159 
160 	uint8_t write_buf[] = {addr | SPI_WRITE, value};
161 	const struct spi_buf tx_buf = {
162 		.buf = write_buf,
163 		.len = sizeof(write_buf),
164 	};
165 	const struct spi_buf_set tx = {
166 		.buffers = &tx_buf,
167 		.count = 1,
168 	};
169 
170 	return spi_write_dt(&cfg->spi, &tx);
171 }
172 
pmw3610_spi_clk_on(const struct device * dev)173 static int pmw3610_spi_clk_on(const struct device *dev)
174 {
175 	int ret;
176 
177 	ret = pmw3610_write_reg(dev, PMW3610_SPI_CLK_ON_REQ, SPI_CLOCK_ON_REQ_ON);
178 
179 	k_sleep(K_USEC(CLOCK_ON_DELAY_US));
180 
181 	return ret;
182 }
183 
pmw3610_spi_clk_off(const struct device * dev)184 static int pmw3610_spi_clk_off(const struct device *dev)
185 {
186 	return pmw3610_write_reg(dev, PMW3610_SPI_CLK_ON_REQ, SPI_CLOCK_ON_REQ_OFF);
187 }
188 
pmw3610_motion_work_handler(struct k_work * work)189 static void pmw3610_motion_work_handler(struct k_work *work)
190 {
191 	struct pmw3610_data *data = CONTAINER_OF(
192 			work, struct pmw3610_data, motion_work);
193 	const struct device *dev = data->dev;
194 	const struct pmw3610_config *cfg = dev->config;
195 	uint8_t burst_data[BURST_DATA_LEN_MAX];
196 	uint8_t burst_data_len;
197 	int32_t x, y;
198 	int ret;
199 
200 	if (cfg->smart_mode) {
201 		burst_data_len = BURST_DATA_LEN_SMART;
202 	} else {
203 		burst_data_len = BURST_DATA_LEN_NORMAL;
204 	}
205 
206 	ret = pmw3610_read(dev, PMW3610_BURST_READ, burst_data, burst_data_len);
207 	if (ret < 0) {
208 		return;
209 	}
210 
211 	if ((burst_data[BURST_MOTION] & MOTION_STATUS_MOTION) == 0x00) {
212 		return;
213 	}
214 
215 	x = ((burst_data[BURST_DELTA_XY_H] << 4) & 0xf00) | burst_data[BURST_DELTA_X_L];
216 	y = ((burst_data[BURST_DELTA_XY_H] << 8) & 0xf00) | burst_data[BURST_DELTA_Y_L];
217 
218 	x = sign_extend(x, PMW3610_DATA_SIZE_BITS - 1);
219 	y = sign_extend(y, PMW3610_DATA_SIZE_BITS - 1);
220 
221 	input_report_rel(data->dev, cfg->axis_x, x, false, K_FOREVER);
222 	input_report_rel(data->dev, cfg->axis_y, y, true, K_FOREVER);
223 
224 	if (cfg->smart_mode) {
225 		uint16_t shutter_val = sys_get_be16(&burst_data[BURST_SHUTTER_HI]);
226 
227 		if (data->smart_flag && shutter_val < SHUTTER_SMART_THRESHOLD) {
228 			pmw3610_spi_clk_on(dev);
229 
230 			ret = pmw3610_write_reg(dev, PMW3610_SMART_MODE, SMART_MODE_ENABLE);
231 			if (ret < 0) {
232 				return;
233 			}
234 
235 			pmw3610_spi_clk_off(dev);
236 
237 			data->smart_flag = false;
238 		} else if (!data->smart_flag && shutter_val > SHUTTER_SMART_THRESHOLD) {
239 			pmw3610_spi_clk_on(dev);
240 
241 			ret = pmw3610_write_reg(dev, PMW3610_SMART_MODE, SMART_MODE_DISABLE);
242 			if (ret < 0) {
243 				return;
244 			}
245 
246 			pmw3610_spi_clk_off(dev);
247 
248 			data->smart_flag = true;
249 		}
250 	}
251 }
252 
pmw3610_motion_handler(const struct device * gpio_dev,struct gpio_callback * cb,uint32_t pins)253 static void pmw3610_motion_handler(const struct device *gpio_dev,
254 				   struct gpio_callback *cb,
255 				   uint32_t pins)
256 {
257 	struct pmw3610_data *data = CONTAINER_OF(
258 			cb, struct pmw3610_data, motion_cb);
259 
260 	k_work_submit(&data->motion_work);
261 }
262 
pmw3610_set_resolution(const struct device * dev,uint16_t res_cpi)263 int pmw3610_set_resolution(const struct device *dev, uint16_t res_cpi)
264 {
265 	uint8_t val;
266 	int ret;
267 
268 	if (!IN_RANGE(res_cpi, RES_MIN, RES_MAX)) {
269 		LOG_ERR("res_cpi out of range: %d", res_cpi);
270 		return -EINVAL;
271 	}
272 
273 	ret = pmw3610_spi_clk_on(dev);
274 	if (ret < 0) {
275 		return ret;
276 	}
277 
278 	ret = pmw3610_write_reg(dev, PWM3610_SPI_PAGE0, SPI_PAGE0_1);
279 	if (ret < 0) {
280 		return ret;
281 	}
282 
283 	ret = pmw3610_read_reg(dev, PMW3610_RES_STEP, &val);
284 	if (ret < 0) {
285 		return ret;
286 	}
287 
288 	val &= ~RES_STEP_RES_MASK;
289 	val |= res_cpi / RES_STEP;
290 
291 	ret = pmw3610_write_reg(dev, PMW3610_RES_STEP, val);
292 	if (ret < 0) {
293 		return ret;
294 	}
295 
296 	ret = pmw3610_write_reg(dev, PWM3610_SPI_PAGE1, SPI_PAGE1_0);
297 	if (ret < 0) {
298 		return ret;
299 	}
300 
301 	ret = pmw3610_spi_clk_off(dev);
302 	if (ret < 0) {
303 		return ret;
304 	}
305 
306 	return 0;
307 }
308 
pmw3610_force_awake(const struct device * dev,bool enable)309 int pmw3610_force_awake(const struct device *dev, bool enable)
310 {
311 	uint8_t val;
312 	int ret;
313 
314 	ret = pmw3610_read_reg(dev, PMW3610_PERFORMANCE, &val);
315 	if (ret < 0) {
316 		return ret;
317 	}
318 
319 	val &= ~PERFORMANCE_FMODE_MASK;
320 	if (enable) {
321 		val |= PERFORMANCE_FMODE_FORCE_AWAKE;
322 	} else {
323 		val |= PERFORMANCE_FMODE_NORMAL;
324 	}
325 
326 	ret = pmw3610_spi_clk_on(dev);
327 	if (ret < 0) {
328 		return ret;
329 	}
330 
331 	ret = pmw3610_write_reg(dev, PMW3610_PERFORMANCE, val);
332 	if (ret < 0) {
333 		return ret;
334 	}
335 
336 	ret = pmw3610_spi_clk_off(dev);
337 	if (ret < 0) {
338 		return ret;
339 	}
340 
341 	return 0;
342 }
343 
pmw3610_configure(const struct device * dev)344 static int pmw3610_configure(const struct device *dev)
345 {
346 	const struct pmw3610_config *cfg = dev->config;
347 	uint8_t val;
348 	int ret;
349 
350 	if (cfg->reset_gpio.port != NULL) {
351 		if (!gpio_is_ready_dt(&cfg->reset_gpio)) {
352 			LOG_ERR("%s is not ready", cfg->reset_gpio.port->name);
353 			return -ENODEV;
354 		}
355 
356 		ret = gpio_pin_configure_dt(&cfg->reset_gpio, GPIO_OUTPUT_ACTIVE);
357 		if (ret != 0) {
358 			LOG_ERR("Reset pin configuration failed: %d", ret);
359 			return ret;
360 		}
361 
362 		k_sleep(K_MSEC(RESET_DELAY_MS));
363 
364 		gpio_pin_set_dt(&cfg->reset_gpio, 0);
365 
366 		k_sleep(K_MSEC(RESET_DELAY_MS));
367 	} else {
368 		ret = pmw3610_write_reg(dev, PMW3610_POWER_UP_RESET, POWER_UP_RESET);
369 		if (ret < 0) {
370 			return ret;
371 		}
372 
373 		k_sleep(K_MSEC(RESET_DELAY_MS));
374 	}
375 
376 	ret = pmw3610_read_reg(dev, PMW3610_PROD_ID, &val);
377 	if (ret < 0) {
378 		return ret;
379 	}
380 
381 	if (val != PRODUCT_ID_PMW3610) {
382 		LOG_ERR("Invalid product id: %02x", val);
383 		return -ENOTSUP;
384 	}
385 
386 	/* Power-up init sequence */
387 	ret = pmw3610_spi_clk_on(dev);
388 	if (ret < 0) {
389 		return ret;
390 	}
391 
392 	ret = pmw3610_write_reg(dev, PMW3610_OBSERVATION1, 0);
393 	if (ret < 0) {
394 		return ret;
395 	}
396 
397 	k_sleep(K_MSEC(INIT_OBSERVATION_DELAY_MS));
398 
399 	ret = pmw3610_read_reg(dev, PMW3610_OBSERVATION1, &val);
400 	if (ret < 0) {
401 		return ret;
402 	}
403 
404 	if ((val & OBSERVATION1_INIT_MASK) != OBSERVATION1_INIT_MASK) {
405 		LOG_ERR("Unexpected OBSERVATION1 value: %02x", val);
406 		return -EINVAL;
407 	}
408 
409 	for (uint8_t reg = PMW3610_MOTION; reg <= PMW3610_DELTA_XY_H; reg++) {
410 		ret = pmw3610_read_reg(dev, reg, &val);
411 		if (ret < 0) {
412 			return ret;
413 		}
414 	}
415 
416 	ret = pmw3610_write_reg(dev, PMW3610_PERFORMANCE, PERFORMANCE_INIT);
417 	if (ret < 0) {
418 		return ret;
419 	}
420 
421 	ret = pmw3610_write_reg(dev, PMW3610_RUN_DOWNSHIFT, RUN_DOWNSHIFT_INIT);
422 	if (ret < 0) {
423 		return ret;
424 	}
425 
426 	ret = pmw3610_write_reg(dev, PMW3610_REST1_RATE, REST1_RATE_INIT);
427 	if (ret < 0) {
428 		return ret;
429 	}
430 
431 	ret = pmw3610_write_reg(dev, PMW3610_REST1_DOWNSHIFT, REST1_DOWNSHIFT_INIT);
432 	if (ret < 0) {
433 		return ret;
434 	}
435 
436 	/* Configuration */
437 
438 	if (cfg->invert_x || cfg->invert_y) {
439 		ret = pmw3610_write_reg(dev, PWM3610_SPI_PAGE0, SPI_PAGE0_1);
440 		if (ret < 0) {
441 			return ret;
442 		}
443 
444 		ret = pmw3610_read_reg(dev, PMW3610_RES_STEP, &val);
445 		if (ret < 0) {
446 			return ret;
447 		}
448 
449 		WRITE_BIT(val, RES_STEP_INV_X_BIT, cfg->invert_x);
450 		WRITE_BIT(val, RES_STEP_INV_Y_BIT, cfg->invert_y);
451 
452 		ret = pmw3610_write_reg(dev, PMW3610_RES_STEP, val);
453 		if (ret < 0) {
454 			return ret;
455 		}
456 
457 		ret = pmw3610_write_reg(dev, PWM3610_SPI_PAGE1, SPI_PAGE1_0);
458 		if (ret < 0) {
459 			return ret;
460 		}
461 
462 	}
463 
464 	ret = pmw3610_spi_clk_off(dev);
465 	if (ret < 0) {
466 		return ret;
467 	}
468 
469 	/* The remaining functions call spi_clk_on/off independently. */
470 
471 	if (cfg->res_cpi > 0) {
472 		pmw3610_set_resolution(dev, cfg->res_cpi);
473 	}
474 
475 	pmw3610_force_awake(dev, cfg->force_awake);
476 
477 	return 0;
478 }
479 
pmw3610_init(const struct device * dev)480 static int pmw3610_init(const struct device *dev)
481 {
482 	const struct pmw3610_config *cfg = dev->config;
483 	struct pmw3610_data *data = dev->data;
484 	int ret;
485 
486 	if (!spi_is_ready_dt(&cfg->spi)) {
487 		LOG_ERR("%s is not ready", cfg->spi.bus->name);
488 		return -ENODEV;
489 	}
490 
491 	data->dev = dev;
492 
493 	k_work_init(&data->motion_work, pmw3610_motion_work_handler);
494 
495 	if (!gpio_is_ready_dt(&cfg->motion_gpio)) {
496 		LOG_ERR("%s is not ready", cfg->motion_gpio.port->name);
497 		return -ENODEV;
498 	}
499 
500 	ret = gpio_pin_configure_dt(&cfg->motion_gpio, GPIO_INPUT);
501 	if (ret != 0) {
502 		LOG_ERR("Motion pin configuration failed: %d", ret);
503 		return ret;
504 	}
505 
506 	gpio_init_callback(&data->motion_cb, pmw3610_motion_handler,
507 			   BIT(cfg->motion_gpio.pin));
508 
509 	ret = gpio_add_callback_dt(&cfg->motion_gpio, &data->motion_cb);
510 	if (ret < 0) {
511 		LOG_ERR("Could not set motion callback: %d", ret);
512 		return ret;
513 	}
514 
515 	ret = pmw3610_configure(dev);
516 	if (ret != 0) {
517 		LOG_ERR("Device configuration failed: %d", ret);
518 		return ret;
519 	}
520 
521 	ret = gpio_pin_interrupt_configure_dt(&cfg->motion_gpio,
522 					      GPIO_INT_EDGE_TO_ACTIVE);
523 	if (ret != 0) {
524 		LOG_ERR("Motion interrupt configuration failed: %d", ret);
525 		return ret;
526 	}
527 
528 	ret = pm_device_runtime_enable(dev);
529 	if (ret < 0) {
530 		LOG_ERR("Failed to enable runtime power management: %d", ret);
531 		return ret;
532 	}
533 
534 	return 0;
535 }
536 
537 #ifdef CONFIG_PM_DEVICE
pmw3610_pm_action(const struct device * dev,enum pm_device_action action)538 static int pmw3610_pm_action(const struct device *dev,
539 			     enum pm_device_action action)
540 {
541 	int ret;
542 
543 	switch (action) {
544 	case PM_DEVICE_ACTION_SUSPEND:
545 		ret = pmw3610_write_reg(dev, PMW3610_SHUTDOWN, SHUTDOWN_ENABLE);
546 		if (ret < 0) {
547 			return ret;
548 		}
549 		break;
550 	case PM_DEVICE_ACTION_RESUME:
551 		ret = pmw3610_write_reg(dev, PMW3610_POWER_UP_RESET, POWER_UP_WAKEUP);
552 		if (ret < 0) {
553 			return ret;
554 		}
555 		break;
556 	default:
557 		return -ENOTSUP;
558 	}
559 
560 	return 0;
561 }
562 #endif
563 
564 #define PMW3610_SPI_MODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \
565 			  SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_TRANSFER_MSB)
566 
567 #define PMW3610_INIT(n)								\
568 	BUILD_ASSERT(IN_RANGE(DT_INST_PROP_OR(n, res_cpi, RES_MIN),		\
569 			      RES_MIN, RES_MAX), "invalid res-cpi");		\
570 										\
571 	static const struct pmw3610_config pmw3610_cfg_##n = {			\
572 		.spi = SPI_DT_SPEC_INST_GET(n, PMW3610_SPI_MODE, 0),		\
573 		.motion_gpio = GPIO_DT_SPEC_INST_GET(n, motion_gpios),		\
574 		.reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {}),	\
575 		.axis_x = DT_INST_PROP(n, zephyr_axis_x),			\
576 		.axis_y = DT_INST_PROP(n, zephyr_axis_y),			\
577 		.res_cpi = DT_INST_PROP_OR(n, res_cpi, -1),			\
578 		.invert_x = DT_INST_PROP(n, invert_x),				\
579 		.invert_y = DT_INST_PROP(n, invert_y),				\
580 		.force_awake = DT_INST_PROP(n, force_awake),			\
581 		.smart_mode = DT_INST_PROP(n, smart_mode),			\
582 	};									\
583 										\
584 	static struct pmw3610_data pmw3610_data_##n;				\
585 										\
586 	PM_DEVICE_DT_INST_DEFINE(n, pmw3610_pm_action);				\
587 										\
588 	DEVICE_DT_INST_DEFINE(n, pmw3610_init, PM_DEVICE_DT_INST_GET(n),	\
589 			      &pmw3610_data_##n, &pmw3610_cfg_##n,		\
590 			      POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY,		\
591 			      NULL);
592 
593 DT_INST_FOREACH_STATUS_OKAY(PMW3610_INIT)
594