|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2020 NXP |
| 2 | + * Copyright (c) 2020, 2025 NXP |
3 | 3 | * Copyright (c) 2020 Mark Olsson <mark@markolsson.se>
|
4 | 4 | * Copyright (c) 2020 Teslabs Engineering S.L.
|
5 | 5 | *
|
|
12 | 12 | #include <zephyr/drivers/i2c.h>
|
13 | 13 | #include <zephyr/input/input.h>
|
14 | 14 | #include <zephyr/sys/byteorder.h>
|
| 15 | +#include <zephyr/pm/pm.h> |
15 | 16 |
|
16 | 17 | #include <zephyr/logging/log.h>
|
17 | 18 | LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL);
|
@@ -64,6 +65,9 @@ struct gt911_data {
|
64 | 65 | /** Timer (polling mode). */
|
65 | 66 | struct k_timer timer;
|
66 | 67 | #endif
|
| 68 | +#ifdef CONFIG_PM |
| 69 | + struct pm_notifier pm_notifier_handle; |
| 70 | +#endif |
67 | 71 | };
|
68 | 72 |
|
69 | 73 | /** gt911 point reg */
|
@@ -237,6 +241,37 @@ static bool gt911_verify_firmware(const uint8_t *firmware)
|
237 | 241 | (gt911_get_firmware_checksum(firmware) == firmware[REG_CONFIG_SIZE - 2U]));
|
238 | 242 | }
|
239 | 243 |
|
| 244 | +#if CONFIG_PM |
| 245 | +static void gt911_pm_state_exit(const struct device *dev, enum pm_state state) |
| 246 | +{ |
| 247 | + switch (state) { |
| 248 | + case PM_STATE_STANDBY: |
| 249 | + /* Reconfigure the GPIO interrupt pin on exit from |
| 250 | + * certain low power states as we might lose the GPIO state. |
| 251 | + */ |
| 252 | + const struct gt911_config *config = dev->config; |
| 253 | + int r; |
| 254 | + |
| 255 | + r = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); |
| 256 | + if (r < 0) { |
| 257 | + LOG_ERR("Could not configure interrupt GPIO pin"); |
| 258 | + return; |
| 259 | + } |
| 260 | + |
| 261 | +#ifdef CONFIG_INPUT_GT911_INTERRUPT |
| 262 | + r = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); |
| 263 | + if (r < 0) { |
| 264 | + LOG_ERR("Could not configure interrupt GPIO interrupt."); |
| 265 | + return; |
| 266 | + } |
| 267 | +#endif /* CONFIG_INPUT_GT911_INTERRUPT */ |
| 268 | + break; |
| 269 | + default: |
| 270 | + break; |
| 271 | + } |
| 272 | +} |
| 273 | +#endif /* CONFIG_PM */ |
| 274 | + |
240 | 275 | static int gt911_init(const struct device *dev)
|
241 | 276 | {
|
242 | 277 | const struct gt911_config *config = dev->config;
|
@@ -390,17 +425,42 @@ static int gt911_init(const struct device *dev)
|
390 | 425 | K_MSEC(CONFIG_INPUT_GT911_PERIOD_MS));
|
391 | 426 | #endif
|
392 | 427 |
|
| 428 | +#if CONFIG_PM |
| 429 | + /* We need to reconfigure the interrupt GPIO when waking up from |
| 430 | + * certain low power modes. |
| 431 | + */ |
| 432 | + pm_notifier_register(&data->pm_notifier_handle); |
| 433 | +#endif |
393 | 434 | return 0;
|
394 | 435 | }
|
395 | 436 |
|
| 437 | +#if CONFIG_PM |
| 438 | +#define GT911_PM_NOTIFIER_FUNCS(n) \ |
| 439 | +static void gt911_##n##_pm_state_exit(enum pm_state state) \ |
| 440 | +{ \ |
| 441 | + gt911_pm_state_exit(DEVICE_DT_INST_GET(n), state); \ |
| 442 | +} |
| 443 | + |
| 444 | +#define GT911_PM_NOTIFIER(n) \ |
| 445 | + .pm_notifier_handle = { \ |
| 446 | + .state_exit = gt911_##n##_pm_state_exit, \ |
| 447 | + }, |
| 448 | +#else |
| 449 | +#define GT911_PM_NOTIFIER_FUNCS(n) |
| 450 | +#define GT911_PM_NOTIFIER(n) |
| 451 | +#endif /* CONFIG_PM */ |
| 452 | + |
396 | 453 | #define GT911_INIT(index) \
|
397 | 454 | static const struct gt911_config gt911_config_##index = { \
|
398 | 455 | .bus = I2C_DT_SPEC_INST_GET(index), \
|
399 | 456 | .rst_gpio = GPIO_DT_SPEC_INST_GET_OR(index, reset_gpios, {0}), \
|
400 | 457 | .int_gpio = GPIO_DT_SPEC_INST_GET(index, irq_gpios), \
|
401 | 458 | .alt_addr = DT_INST_PROP_OR(index, alt_addr, 0), \
|
402 | 459 | }; \
|
403 |
| - static struct gt911_data gt911_data_##index; \ |
| 460 | + GT911_PM_NOTIFIER_FUNCS(index) \ |
| 461 | + static struct gt911_data gt911_data_##index = { \ |
| 462 | + GT911_PM_NOTIFIER(index) \ |
| 463 | + }; \ |
404 | 464 | DEVICE_DT_INST_DEFINE(index, gt911_init, NULL, >911_data_##index, >911_config_##index, \
|
405 | 465 | POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL);
|
406 | 466 |
|
|
0 commit comments