1 /*
2 * Copyright (c) 2015 Intel Corporation.
3 * Copyright (c) 2020 Norbit ODM AS
4 * Copyright 2022 NXP
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define DT_DRV_COMPAT nxp_pca95xx
10
11 /**
12 * @file Driver for PCA95XX and PCAL95XX I2C-based GPIO driver.
13 */
14
15 #include <errno.h>
16
17 #include <zephyr/kernel.h>
18 #include <zephyr/device.h>
19 #include <zephyr/init.h>
20 #include <zephyr/sys/byteorder.h>
21 #include <zephyr/sys/util.h>
22 #include <zephyr/drivers/gpio.h>
23 #include <zephyr/drivers/i2c.h>
24
25 #include <zephyr/drivers/gpio/gpio_utils.h>
26
27 #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
28 #include <zephyr/logging/log.h>
29 LOG_MODULE_REGISTER(gpio_pca95xx);
30
31 #if CONFIG_LITTLE_ENDIAN
32 #define LOW_BYTE_LE16_IDX 0
33 #define HIGH_BYTE_LE16_IDX 1
34 #else
35 #define LOW_BYTE_LE16_IDX 1
36 #define HIGH_BYTE_LE16_IDX 0
37 #endif
38
39 /* Register definitions */
40 #define REG_INPUT_PORT0 0x00
41 #define REG_INPUT_PORT1 0x01
42 #define REG_OUTPUT_PORT0 0x02
43 #define REG_OUTPUT_PORT1 0x03
44 #define REG_POL_INV_PORT0 0x04
45 #define REG_POL_INV_PORT1 0x05
46 #define REG_CONF_PORT0 0x06
47 #define REG_CONF_PORT1 0x07
48 #define REG_OUT_DRV_STRENGTH_PORT0_L 0x40
49 #define REG_OUT_DRV_STRENGTH_PORT0_H 0x41
50 #define REG_OUT_DRV_STRENGTH_PORT1_L 0x42
51 #define REG_OUT_DRV_STRENGTH_PORT1_H 0x43
52 #define REG_INPUT_LATCH_PORT0 0x44
53 #define REG_INPUT_LATCH_PORT1 0x45
54 #define REG_PUD_EN_PORT0 0x46
55 #define REG_PUD_EN_PORT1 0x47
56 #define REG_PUD_SEL_PORT0 0x48
57 #define REG_PUD_SEL_PORT1 0x49
58 #define REG_INT_MASK_PORT0 0x4A
59 #define REG_INT_MASK_PORT1 0x4B
60 #define REG_INT_STATUS_PORT0 0x4C
61 #define REG_INT_STATUS_PORT1 0x4D
62 #define REG_OUTPUT_PORT_CONF 0x4F
63
64 /* Driver flags */
65 #define PCA_HAS_PUD BIT(0)
66 #define PCA_HAS_INTERRUPT BIT(1)
67 #define PCA_HAS_INTERRUPT_MASK_REG BIT(2)
68
69 /** Configuration data */
70 struct gpio_pca95xx_config {
71 /* gpio_driver_config needs to be first */
72 struct gpio_driver_config common;
73 struct i2c_dt_spec bus;
74 uint8_t capabilities;
75 #ifdef CONFIG_GPIO_PCA95XX_INTERRUPT
76 struct gpio_dt_spec int_gpio;
77 #endif
78 };
79
80 /** Runtime driver data */
81 struct gpio_pca95xx_drv_data {
82 /* gpio_driver_data needs to be first */
83 struct gpio_driver_data common;
84
85 struct {
86 uint16_t input;
87 uint16_t output;
88 uint16_t dir;
89 uint16_t pud_en;
90 uint16_t pud_sel;
91 uint16_t int_mask;
92 uint16_t input_latch;
93 } reg_cache;
94
95 struct k_sem lock;
96
97 #ifdef CONFIG_GPIO_PCA95XX_INTERRUPT
98 /* Self-reference to the driver instance */
99 const struct device *instance;
100
101 /* port ISR callback routine address */
102 sys_slist_t callbacks;
103
104 /* interrupt triggering pin masks */
105 struct {
106 uint16_t edge_rising;
107 uint16_t edge_falling;
108 uint16_t level_high;
109 uint16_t level_low;
110 } interrupts;
111
112 struct gpio_callback gpio_callback;
113
114 struct k_work interrupt_worker;
115
116 bool interrupt_active;
117 #endif
118 };
119
read_port_reg(const struct device * dev,uint8_t reg,uint8_t pin,uint16_t * cache,uint16_t * buf)120 static int read_port_reg(const struct device *dev, uint8_t reg, uint8_t pin,
121 uint16_t *cache, uint16_t *buf)
122 {
123 const struct gpio_pca95xx_config * const config = dev->config;
124 uint8_t b_buf;
125 int ret;
126
127 if (pin >= 8)
128 reg++;
129
130 ret = i2c_reg_read_byte_dt(&config->bus, reg, &b_buf);
131 if (ret != 0) {
132 LOG_ERR("PCA95XX[0x%X]: error reading register 0x%X (%d)",
133 config->bus.addr, reg, ret);
134 return ret;
135 }
136
137 if (pin < 8) {
138 ((uint8_t *)cache)[LOW_BYTE_LE16_IDX] = b_buf;
139 } else {
140 ((uint8_t *)cache)[HIGH_BYTE_LE16_IDX] = b_buf;
141 }
142
143 *buf = *cache;
144
145 LOG_DBG("PCA95XX[0x%X]: Read: REG[0x%X] = 0x%X",
146 config->bus.addr, reg, b_buf);
147
148 return 0;
149 }
150
151 /**
152 * @brief Read both port 0 and port 1 registers of certain register function.
153 *
154 * Given the register in reg, read the pair of port 0 and port 1.
155 *
156 * @param dev Device struct of the PCA95XX.
157 * @param reg Register to read (the PORT0 of the pair of registers).
158 * @param cache Pointer to the cache to be updated after successful read.
159 * @param buf Buffer to read data into.
160 *
161 * @return 0 if successful, failed otherwise.
162 */
read_port_regs(const struct device * dev,uint8_t reg,uint16_t * cache,uint16_t * buf)163 static int read_port_regs(const struct device *dev, uint8_t reg,
164 uint16_t *cache, uint16_t *buf)
165 {
166 const struct gpio_pca95xx_config * const config = dev->config;
167 uint16_t port_data, value;
168 int ret;
169
170 ret = i2c_burst_read_dt(&config->bus, reg, (uint8_t *)&port_data,
171 sizeof(port_data));
172 if (ret != 0) {
173 LOG_ERR("PCA95XX[0x%X]: error reading register 0x%X (%d)",
174 config->bus.addr, reg, ret);
175 return ret;
176 }
177
178 value = sys_le16_to_cpu(port_data);
179 *cache = value;
180 *buf = value;
181
182 LOG_DBG("PCA95XX[0x%X]: Read: REG[0x%X] = 0x%X, REG[0x%X] = 0x%X",
183 config->bus.addr, reg, (*buf & 0xFF), (reg + 1), (*buf >> 8));
184
185 return 0;
186 }
187
188
write_port_reg(const struct device * dev,uint8_t reg,uint8_t pin,uint16_t * cache,uint16_t value)189 static int write_port_reg(const struct device *dev, uint8_t reg, uint8_t pin,
190 uint16_t *cache, uint16_t value)
191 {
192 const struct gpio_pca95xx_config * const config = dev->config;
193 uint8_t buf[2];
194 int ret;
195
196 if (pin < 8) {
197 buf[1] = value;
198 } else {
199 buf[1] = value >> 8;
200 reg++;
201 }
202 buf[0] = reg;
203
204 LOG_DBG("PCA95XX[0x%X]: Write: REG[0x%X] = 0x%X", config->bus.addr,
205 reg, buf[1]);
206
207 ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
208 if (ret == 0) {
209 *cache = value;
210 } else {
211 LOG_ERR("PCA95XX[0x%X]: error writing to register 0x%X "
212 "(%d)", config->bus.addr, reg, ret);
213 }
214
215 return ret;
216 }
217
218 /**
219 * @brief Write both port 0 and port 1 registers of certain register function.
220 *
221 * Given the register in reg, write the pair of port 0 and port 1.
222 *
223 * @param dev Device struct of the PCA95XX.
224 * @param reg Register to write into (the PORT0 of the pair of registers).
225 * @param cache Pointer to the cache to be updated after successful write.
226 * @param value New value to set.
227 *
228 * @return 0 if successful, failed otherwise.
229 */
write_port_regs(const struct device * dev,uint8_t reg,uint16_t * cache,uint16_t value)230 static int write_port_regs(const struct device *dev, uint8_t reg,
231 uint16_t *cache, uint16_t value)
232 {
233 const struct gpio_pca95xx_config * const config = dev->config;
234 uint8_t buf[3];
235 int ret;
236
237 LOG_DBG("PCA95XX[0x%X]: Write: REG[0x%X] = 0x%X, REG[0x%X] = "
238 "0x%X", config->bus.addr, reg, (value & 0xFF),
239 (reg + 1), (value >> 8));
240
241 buf[0] = reg;
242 sys_put_le16(value, &buf[1]);
243
244 ret = i2c_write_dt(&config->bus, buf, sizeof(buf));
245 if (ret == 0) {
246 *cache = value;
247 } else {
248 LOG_ERR("PCA95XX[0x%X]: error writing to register 0x%X "
249 "(%d)", config->bus.addr, reg, ret);
250 }
251
252 return ret;
253 }
254
update_input_reg(const struct device * dev,uint8_t pin,uint16_t * buf)255 static inline int update_input_reg(const struct device *dev, uint8_t pin,
256 uint16_t *buf)
257 {
258 struct gpio_pca95xx_drv_data * const drv_data =
259 (struct gpio_pca95xx_drv_data * const)dev->data;
260
261 return read_port_reg(dev, REG_INPUT_PORT0, pin,
262 &drv_data->reg_cache.input, buf);
263 }
264
update_input_regs(const struct device * dev,uint16_t * buf)265 static inline int update_input_regs(const struct device *dev, uint16_t *buf)
266 {
267 struct gpio_pca95xx_drv_data * const drv_data =
268 (struct gpio_pca95xx_drv_data * const)dev->data;
269
270 return read_port_regs(dev, REG_INPUT_PORT0,
271 &drv_data->reg_cache.input, buf);
272 }
273
update_output_reg(const struct device * dev,uint8_t pin,uint16_t value)274 static inline int update_output_reg(const struct device *dev, uint8_t pin,
275 uint16_t value)
276 {
277 struct gpio_pca95xx_drv_data * const drv_data =
278 (struct gpio_pca95xx_drv_data * const)dev->data;
279
280 return write_port_reg(dev, REG_OUTPUT_PORT0, pin,
281 &drv_data->reg_cache.output, value);
282 }
283
update_output_regs(const struct device * dev,uint16_t value)284 static inline int update_output_regs(const struct device *dev, uint16_t value)
285 {
286 struct gpio_pca95xx_drv_data * const drv_data =
287 (struct gpio_pca95xx_drv_data * const)dev->data;
288
289 return write_port_regs(dev, REG_OUTPUT_PORT0,
290 &drv_data->reg_cache.output, value);
291 }
292
update_direction_reg(const struct device * dev,uint8_t pin,uint16_t value)293 static inline int update_direction_reg(const struct device *dev, uint8_t pin,
294 uint16_t value)
295 {
296 struct gpio_pca95xx_drv_data * const drv_data =
297 (struct gpio_pca95xx_drv_data * const)dev->data;
298
299 return write_port_reg(dev, REG_CONF_PORT0, pin,
300 &drv_data->reg_cache.dir, value);
301 }
302
update_pul_sel_reg(const struct device * dev,uint8_t pin,uint16_t value)303 static inline int update_pul_sel_reg(const struct device *dev, uint8_t pin,
304 uint16_t value)
305 {
306 struct gpio_pca95xx_drv_data * const drv_data =
307 (struct gpio_pca95xx_drv_data * const)dev->data;
308
309 return write_port_reg(dev, REG_PUD_SEL_PORT0, pin,
310 &drv_data->reg_cache.pud_sel, value);
311 }
312
update_pul_en_reg(const struct device * dev,uint8_t pin,uint8_t value)313 static inline int update_pul_en_reg(const struct device *dev, uint8_t pin,
314 uint8_t value)
315 {
316 struct gpio_pca95xx_drv_data * const drv_data =
317 (struct gpio_pca95xx_drv_data * const)dev->data;
318
319 return write_port_reg(dev, REG_PUD_EN_PORT0, pin,
320 &drv_data->reg_cache.pud_en, value);
321 }
322
323 #ifdef CONFIG_GPIO_PCA95XX_INTERRUPT
update_int_mask_reg(const struct device * dev,uint8_t pin,uint16_t value)324 static inline int update_int_mask_reg(const struct device *dev, uint8_t pin,
325 uint16_t value)
326 {
327 struct gpio_pca95xx_drv_data * const drv_data =
328 (struct gpio_pca95xx_drv_data * const)dev->data;
329
330 /* If the interrupt mask is present, so is the input latch */
331 write_port_reg(dev, REG_INPUT_LATCH_PORT0, pin, &drv_data->reg_cache.input_latch, ~value);
332
333 return write_port_reg(dev, REG_INT_MASK_PORT0, pin,
334 &drv_data->reg_cache.int_mask, value);
335 }
336 #endif /* CONFIG_GPIO_PCA95XX_INTERRUPT */
337
338 /**
339 * @brief Setup the pin direction (input or output)
340 *
341 * @param dev Device struct of the PCA95XX
342 * @param pin The pin number
343 * @param flags Flags of pin or port
344 *
345 * @return 0 if successful, failed otherwise
346 */
setup_pin_dir(const struct device * dev,uint32_t pin,int flags)347 static int setup_pin_dir(const struct device *dev, uint32_t pin, int flags)
348 {
349 struct gpio_pca95xx_drv_data * const drv_data =
350 (struct gpio_pca95xx_drv_data * const)dev->data;
351 uint16_t reg_dir = drv_data->reg_cache.dir;
352 uint16_t reg_out = drv_data->reg_cache.output;
353 int ret;
354
355 /* For each pin, 0 == output, 1 == input */
356 if ((flags & GPIO_OUTPUT) != 0U) {
357 if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
358 reg_out |= BIT(pin);
359 } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
360 reg_out &= ~BIT(pin);
361 }
362 ret = update_output_reg(dev, pin, reg_out);
363 if (ret != 0) {
364 return ret;
365 }
366 reg_dir &= ~BIT(pin);
367 } else {
368 reg_dir |= BIT(pin);
369 }
370
371 ret = update_direction_reg(dev, pin, reg_dir);
372
373 return ret;
374 }
375
376 /**
377 * @brief Setup the pin pull up/pull down status
378 *
379 * @param dev Device struct of the PCA95XX
380 * @param pin The pin number
381 * @param flags Flags of pin or port
382 *
383 * @return 0 if successful, failed otherwise
384 */
setup_pin_pullupdown(const struct device * dev,uint32_t pin,int flags)385 static int setup_pin_pullupdown(const struct device *dev, uint32_t pin,
386 int flags)
387 {
388 const struct gpio_pca95xx_config * const config = dev->config;
389 struct gpio_pca95xx_drv_data * const drv_data =
390 (struct gpio_pca95xx_drv_data * const)dev->data;
391 uint16_t reg_pud;
392 int ret;
393
394 if ((config->capabilities & PCA_HAS_PUD) == 0) {
395 /* Chip does not support pull up/pull down */
396 if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0U) {
397 return -ENOTSUP;
398 }
399
400 /* If both GPIO_PULL_UP and GPIO_PULL_DOWN are not set,
401 * we should disable them in hardware. But need to skip
402 * if the chip does not support pull up/pull down.
403 */
404 return 0;
405 }
406
407 /* If disabling pull up/down, there is no need to set the selection
408 * register. Just go straight to disabling.
409 */
410 if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0U) {
411 /* Setup pin pull up or pull down */
412 reg_pud = drv_data->reg_cache.pud_sel;
413
414 /* pull down == 0, pull up == 1 */
415 WRITE_BIT(reg_pud, pin, (flags & GPIO_PULL_UP) != 0U);
416
417 ret = update_pul_sel_reg(dev, pin, reg_pud);
418 if (ret) {
419 return ret;
420 }
421 }
422
423 /* enable/disable pull up/down */
424 reg_pud = drv_data->reg_cache.pud_en;
425
426 WRITE_BIT(reg_pud, pin,
427 (flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0U);
428
429 ret = update_pul_en_reg(dev, pin, reg_pud);
430
431 return ret;
432 }
433
434 /**
435 * @brief Configure pin or port
436 *
437 * @param dev Device struct of the PCA95XX
438 * @param pin The pin number
439 * @param flags Flags of pin or port
440 *
441 * @return 0 if successful, failed otherwise
442 */
gpio_pca95xx_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)443 static int gpio_pca95xx_config(const struct device *dev,
444 gpio_pin_t pin, gpio_flags_t flags)
445 {
446 int ret;
447 struct gpio_pca95xx_drv_data * const drv_data =
448 (struct gpio_pca95xx_drv_data * const)dev->data;
449
450 #if (CONFIG_GPIO_LOG_LEVEL >= LOG_LEVEL_DEBUG)
451 const struct gpio_pca95xx_config * const config = dev->config;
452 #endif
453
454 /* Does not support disconnected pin */
455 if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) {
456 return -ENOTSUP;
457 }
458
459 /* Open-drain support is per port, not per pin.
460 * So can't really support the API as-is.
461 */
462 if ((flags & GPIO_SINGLE_ENDED) != 0U) {
463 return -ENOTSUP;
464 }
465
466 /* Can't do I2C bus operations from an ISR */
467 if (k_is_in_isr()) {
468 return -EWOULDBLOCK;
469 }
470
471 k_sem_take(&drv_data->lock, K_FOREVER);
472
473 ret = setup_pin_dir(dev, pin, flags);
474 if (ret) {
475 LOG_ERR("PCA95XX[0x%X]: error setting pin direction (%d)",
476 config->bus.addr, ret);
477 goto done;
478 }
479
480 ret = setup_pin_pullupdown(dev, pin, flags);
481 if (ret) {
482 LOG_ERR("PCA95XX[0x%X]: error setting pin pull up/down "
483 "(%d)", config->bus.addr, ret);
484 goto done;
485 }
486
487 done:
488 k_sem_give(&drv_data->lock);
489 return ret;
490 }
491
gpio_pca95xx_port_get_raw(const struct device * dev,uint32_t * value)492 static int gpio_pca95xx_port_get_raw(const struct device *dev, uint32_t *value)
493 {
494 struct gpio_pca95xx_drv_data * const drv_data =
495 (struct gpio_pca95xx_drv_data * const)dev->data;
496 uint16_t buf;
497 int ret;
498
499 /* Can't do I2C bus operations from an ISR */
500 if (k_is_in_isr()) {
501 return -EWOULDBLOCK;
502 }
503
504 k_sem_take(&drv_data->lock, K_FOREVER);
505
506 ret = update_input_regs(dev, &buf);
507 if (ret != 0) {
508 goto done;
509 }
510
511 *value = buf;
512
513 done:
514 k_sem_give(&drv_data->lock);
515 return ret;
516 }
517
gpio_pca95xx_port_set_masked_raw(const struct device * dev,uint32_t mask,uint32_t value)518 static int gpio_pca95xx_port_set_masked_raw(const struct device *dev,
519 uint32_t mask, uint32_t value)
520 {
521 struct gpio_pca95xx_drv_data * const drv_data =
522 (struct gpio_pca95xx_drv_data * const)dev->data;
523 uint16_t reg_out;
524 int ret;
525
526 /* Can't do I2C bus operations from an ISR */
527 if (k_is_in_isr()) {
528 return -EWOULDBLOCK;
529 }
530
531 k_sem_take(&drv_data->lock, K_FOREVER);
532
533 reg_out = drv_data->reg_cache.output;
534 reg_out = (reg_out & ~mask) | (mask & value);
535
536 ret = update_output_regs(dev, reg_out);
537
538 k_sem_give(&drv_data->lock);
539
540 return ret;
541 }
542
gpio_pca95xx_port_set_bits_raw(const struct device * dev,uint32_t mask)543 static int gpio_pca95xx_port_set_bits_raw(const struct device *dev,
544 uint32_t mask)
545 {
546 return gpio_pca95xx_port_set_masked_raw(dev, mask, mask);
547 }
548
gpio_pca95xx_port_clear_bits_raw(const struct device * dev,uint32_t mask)549 static int gpio_pca95xx_port_clear_bits_raw(const struct device *dev,
550 uint32_t mask)
551 {
552 return gpio_pca95xx_port_set_masked_raw(dev, mask, 0);
553 }
554
gpio_pca95xx_port_toggle_bits(const struct device * dev,uint32_t mask)555 static int gpio_pca95xx_port_toggle_bits(const struct device *dev,
556 uint32_t mask)
557 {
558 struct gpio_pca95xx_drv_data * const drv_data =
559 (struct gpio_pca95xx_drv_data * const)dev->data;
560 uint16_t reg_out;
561 int ret;
562
563 /* Can't do I2C bus operations from an ISR */
564 if (k_is_in_isr()) {
565 return -EWOULDBLOCK;
566 }
567
568 k_sem_take(&drv_data->lock, K_FOREVER);
569
570 reg_out = drv_data->reg_cache.output;
571 reg_out ^= mask;
572
573 ret = update_output_regs(dev, reg_out);
574
575 k_sem_give(&drv_data->lock);
576
577 return ret;
578 }
579
580 #ifdef CONFIG_GPIO_PCA95XX_INTERRUPT
get_triggered_it(struct gpio_pca95xx_drv_data * drv_data,uint16_t * trig_edge,uint16_t * trig_level)581 static void get_triggered_it(struct gpio_pca95xx_drv_data *drv_data,
582 uint16_t *trig_edge, uint16_t *trig_level)
583 {
584 uint16_t input_cache, changed_pins, input_new;
585 int ret;
586
587 input_cache = drv_data->reg_cache.input;
588 ret = update_input_regs(drv_data->instance, &input_new);
589 if (ret == 0) {
590 changed_pins = (input_cache ^ input_new);
591
592 *trig_edge |= (changed_pins & input_new &
593 drv_data->interrupts.edge_rising);
594 *trig_edge |= (changed_pins & input_cache &
595 drv_data->interrupts.edge_falling);
596 *trig_level |= (input_new & drv_data->interrupts.level_high);
597 *trig_level |= (~input_new & drv_data->interrupts.level_low);
598 }
599 }
600
gpio_pca95xx_interrupt_worker(struct k_work * work)601 static void gpio_pca95xx_interrupt_worker(struct k_work *work)
602 {
603 struct gpio_pca95xx_drv_data * const drv_data = CONTAINER_OF(
604 work, struct gpio_pca95xx_drv_data, interrupt_worker);
605 const struct gpio_pca95xx_config * const config = drv_data->instance->config;
606 uint16_t trig_edge = 0, trig_level = 0;
607 uint32_t triggered_int = 0;
608
609 k_sem_take(&drv_data->lock, K_FOREVER);
610
611 /* Note: PCA Interrupt status is cleared by reading inputs */
612 if (config->capabilities & PCA_HAS_INTERRUPT_MASK_REG) {
613 /* gpio latched read values, to be compared to cached ones */
614 get_triggered_it(drv_data, &trig_edge, &trig_level);
615 }
616 /* gpio unlatched read values, in case signal has flipped again */
617 get_triggered_it(drv_data, &trig_edge, &trig_level);
618
619 triggered_int = (trig_edge | trig_level);
620
621 k_sem_give(&drv_data->lock);
622
623 if (triggered_int != 0) {
624 gpio_fire_callbacks(&drv_data->callbacks, drv_data->instance,
625 triggered_int);
626 }
627
628 /* Emulate level triggering */
629 if (trig_level != 0) {
630 /* Reschedule worker */
631 k_work_submit(&drv_data->interrupt_worker);
632 }
633 }
634
gpio_pca95xx_interrupt_callback(const struct device * dev,struct gpio_callback * cb,gpio_port_pins_t pins)635 static void gpio_pca95xx_interrupt_callback(const struct device *dev,
636 struct gpio_callback *cb,
637 gpio_port_pins_t pins)
638 {
639 struct gpio_pca95xx_drv_data * const drv_data =
640 CONTAINER_OF(cb, struct gpio_pca95xx_drv_data, gpio_callback);
641
642 ARG_UNUSED(pins);
643
644 /* Cannot read PCA95xx registers from ISR context, queue worker */
645 k_work_submit(&drv_data->interrupt_worker);
646 }
647
gpio_pca95xx_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)648 static int gpio_pca95xx_pin_interrupt_configure(const struct device *dev,
649 gpio_pin_t pin,
650 enum gpio_int_mode mode,
651 enum gpio_int_trig trig)
652 {
653 int ret = 0;
654 const struct gpio_pca95xx_config * const config = dev->config;
655 struct gpio_pca95xx_drv_data * const drv_data =
656 (struct gpio_pca95xx_drv_data * const)dev->data;
657 uint16_t reg;
658 bool enabled, edge, level, active;
659
660 /* Check if GPIO port supports interrupts */
661 if ((config->capabilities & PCA_HAS_INTERRUPT) == 0U) {
662 return -ENOTSUP;
663 }
664
665 /* Check for an invalid pin number */
666 if (BIT(pin) > config->common.port_pin_mask) {
667 return -EINVAL;
668 }
669
670 /* Check configured pin direction */
671 if ((mode != GPIO_INT_MODE_DISABLED) &&
672 (BIT(pin) & drv_data->reg_cache.dir) != BIT(pin)) {
673 LOG_ERR("PCA95XX[0x%X]: output pin cannot trigger interrupt",
674 config->bus.addr);
675 return -ENOTSUP;
676 }
677
678 k_sem_take(&drv_data->lock, K_FOREVER);
679
680 /* Check if GPIO port has an interrupt mask register */
681 if (config->capabilities & PCA_HAS_INTERRUPT_MASK_REG) {
682 uint16_t reg_out;
683
684 reg_out = drv_data->reg_cache.int_mask;
685 WRITE_BIT(reg_out, pin, (mode == GPIO_INT_MODE_DISABLED));
686
687 ret = update_int_mask_reg(dev, pin, reg_out);
688 if (ret != 0) {
689 LOG_ERR("PCA95XX[0x%X]: failed to update int mask (%d)",
690 config->bus.addr, ret);
691 goto err;
692 }
693 }
694
695 /* Update interrupt masks */
696 enabled = ((mode & GPIO_INT_MODE_DISABLED) == 0U);
697 edge = (mode == GPIO_INT_MODE_EDGE);
698 level = (mode == GPIO_INT_MODE_LEVEL);
699 WRITE_BIT(drv_data->interrupts.edge_rising, pin, (enabled &&
700 edge && ((trig & GPIO_INT_TRIG_HIGH) == GPIO_INT_TRIG_HIGH)));
701 WRITE_BIT(drv_data->interrupts.edge_falling, pin, (enabled &&
702 edge && ((trig & GPIO_INT_TRIG_LOW) == GPIO_INT_TRIG_LOW)));
703 WRITE_BIT(drv_data->interrupts.level_high, pin, (enabled &&
704 level && ((trig & GPIO_INT_TRIG_HIGH) == GPIO_INT_TRIG_HIGH)));
705 WRITE_BIT(drv_data->interrupts.level_low, pin, (enabled &&
706 level && ((trig & GPIO_INT_TRIG_LOW) == GPIO_INT_TRIG_LOW)));
707
708 active = ((drv_data->interrupts.edge_rising ||
709 drv_data->interrupts.edge_falling ||
710 drv_data->interrupts.level_high ||
711 drv_data->interrupts.level_low) > 0);
712
713 /* Enable / disable interrupt as needed */
714 if (active != drv_data->interrupt_active) {
715 ret = gpio_pin_interrupt_configure_dt(
716 &config->int_gpio, active ?
717 GPIO_INT_EDGE_TO_ACTIVE :
718 GPIO_INT_MODE_DISABLED);
719 if (ret != 0) {
720 LOG_ERR("PCA95XX[0x%X]: failed to configure interrupt "
721 "on pin %d (%d)", config->bus.addr,
722 config->int_gpio.pin, ret);
723 goto err;
724 }
725 drv_data->interrupt_active = active;
726
727 if (active) {
728 /* Read current status to reset any
729 * active signal on INT line
730 */
731 update_input_regs(dev, ®);
732 }
733 }
734
735 err:
736 k_sem_give(&drv_data->lock);
737 return ret;
738 }
739
gpio_pca95xx_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)740 static int gpio_pca95xx_manage_callback(const struct device *dev,
741 struct gpio_callback *callback,
742 bool set)
743 {
744 const struct gpio_pca95xx_config * const config = dev->config;
745 struct gpio_pca95xx_drv_data * const drv_data =
746 (struct gpio_pca95xx_drv_data * const)dev->data;
747
748 if ((config->capabilities & PCA_HAS_INTERRUPT) == 0U) {
749 return -ENOTSUP;
750 }
751
752 k_sem_take(&drv_data->lock, K_FOREVER);
753
754 gpio_manage_callback(&drv_data->callbacks, callback, set);
755
756 k_sem_give(&drv_data->lock);
757 return 0;
758 }
759 #endif /* CONFIG_GPIO_PCA95XX_INTERRUPT */
760
761 static const struct gpio_driver_api gpio_pca95xx_drv_api_funcs = {
762 .pin_configure = gpio_pca95xx_config,
763 .port_get_raw = gpio_pca95xx_port_get_raw,
764 .port_set_masked_raw = gpio_pca95xx_port_set_masked_raw,
765 .port_set_bits_raw = gpio_pca95xx_port_set_bits_raw,
766 .port_clear_bits_raw = gpio_pca95xx_port_clear_bits_raw,
767 .port_toggle_bits = gpio_pca95xx_port_toggle_bits,
768 #ifdef CONFIG_GPIO_PCA95XX_INTERRUPT
769 .pin_interrupt_configure = gpio_pca95xx_pin_interrupt_configure,
770 .manage_callback = gpio_pca95xx_manage_callback,
771 #endif
772 };
773
774 /**
775 * @brief Initialization function of PCA95XX
776 *
777 * @param dev Device struct
778 * @return 0 if successful, failed otherwise.
779 */
gpio_pca95xx_init(const struct device * dev)780 static int gpio_pca95xx_init(const struct device *dev)
781 {
782 const struct gpio_pca95xx_config * const config = dev->config;
783 struct gpio_pca95xx_drv_data * const drv_data =
784 (struct gpio_pca95xx_drv_data * const)dev->data;
785
786 if (!device_is_ready(config->bus.bus)) {
787 return -ENODEV;
788 }
789
790 k_sem_init(&drv_data->lock, 1, 1);
791
792 #ifdef CONFIG_GPIO_PCA95XX_INTERRUPT
793 /* Check if GPIO port supports interrupts */
794 if ((config->capabilities & PCA_HAS_INTERRUPT) != 0) {
795 int ret;
796
797 /* Store self-reference for interrupt handling */
798 drv_data->instance = dev;
799
800 /* Prepare interrupt worker */
801 k_work_init(&drv_data->interrupt_worker,
802 gpio_pca95xx_interrupt_worker);
803
804 /* Configure GPIO interrupt pin */
805 if (!gpio_is_ready_dt(&config->int_gpio)) {
806 LOG_ERR("PCA95XX[0x%X]: interrupt GPIO not ready",
807 config->bus.addr);
808 return -ENODEV;
809 }
810
811 ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
812 if (ret != 0) {
813 LOG_ERR("PCA95XX[0x%X]: failed to configure interrupt"
814 " pin %d (%d)", config->bus.addr,
815 config->int_gpio.pin, ret);
816 return ret;
817 }
818
819 /* Prepare GPIO callback for interrupt pin */
820 gpio_init_callback(&drv_data->gpio_callback,
821 gpio_pca95xx_interrupt_callback,
822 BIT(config->int_gpio.pin));
823 ret = gpio_add_callback(config->int_gpio.port, &drv_data->gpio_callback);
824 if (ret != 0) {
825 LOG_ERR("PCA95XX[0x%X]: failed to add interrupt callback for"
826 " pin %d (%d)", config->bus.addr,
827 config->int_gpio.pin, ret);
828 return ret;
829 }
830 }
831 #endif
832
833 return 0;
834 }
835
836 #define GPIO_PCA95XX_DEVICE_INSTANCE(inst) \
837 static const struct gpio_pca95xx_config gpio_pca95xx_##inst##_cfg = { \
838 .common = { \
839 .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \
840 }, \
841 .bus = I2C_DT_SPEC_INST_GET(inst), \
842 .capabilities = \
843 (DT_INST_PROP(inst, has_pud) ? PCA_HAS_PUD : 0) | \
844 IF_ENABLED(CONFIG_GPIO_PCA95XX_INTERRUPT, ( \
845 (DT_INST_NODE_HAS_PROP(inst, interrupt_gpios) ? \
846 PCA_HAS_INTERRUPT : 0) | \
847 (DT_INST_PROP(inst, has_interrupt_mask_reg) ? \
848 PCA_HAS_INTERRUPT_MASK_REG : 0) | \
849 )) \
850 0, \
851 IF_ENABLED(CONFIG_GPIO_PCA95XX_INTERRUPT, \
852 (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, interrupt_gpios, {}),)) \
853 }; \
854 \
855 static struct gpio_pca95xx_drv_data gpio_pca95xx_##inst##_drvdata = { \
856 .reg_cache.input = 0x0, \
857 .reg_cache.output = 0xFFFF, \
858 .reg_cache.dir = 0xFFFF, \
859 .reg_cache.pud_en = 0x0, \
860 .reg_cache.pud_sel = 0xFFFF, \
861 .reg_cache.int_mask = 0xFFFF, \
862 .reg_cache.input_latch = 0x0, \
863 IF_ENABLED(CONFIG_GPIO_PCA95XX_INTERRUPT, ( \
864 .interrupt_active = false, \
865 )) \
866 }; \
867 \
868 DEVICE_DT_INST_DEFINE(inst, \
869 gpio_pca95xx_init, \
870 NULL, \
871 &gpio_pca95xx_##inst##_drvdata, \
872 &gpio_pca95xx_##inst##_cfg, \
873 POST_KERNEL, CONFIG_GPIO_PCA95XX_INIT_PRIORITY, \
874 &gpio_pca95xx_drv_api_funcs);
875
876 DT_INST_FOREACH_STATUS_OKAY(GPIO_PCA95XX_DEVICE_INSTANCE)
877