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