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, &reg);
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