Lines Matching +full:int +full:- +full:pin

6  * SPDX-License-Identifier: Apache-2.0
12 * @file Driver for PCA95XX and PCAL95XX I2C-based GPIO driver.
98 /* Self-reference to the driver instance */
104 /* interrupt triggering pin masks */
120 static int read_port_reg(const struct device *dev, uint8_t reg, uint8_t pin, in read_port_reg() argument
123 const struct gpio_pca95xx_config * const config = dev->config; in read_port_reg()
125 int ret; in read_port_reg()
127 if (pin >= 8) { in read_port_reg()
131 ret = i2c_reg_read_byte_dt(&config->bus, reg, &b_buf); in read_port_reg()
134 config->bus.addr, reg, ret); in read_port_reg()
138 if (pin < 8) { in read_port_reg()
147 config->bus.addr, reg, b_buf); in read_port_reg()
164 static int read_port_regs(const struct device *dev, uint8_t reg, in read_port_regs()
167 const struct gpio_pca95xx_config * const config = dev->config; in read_port_regs()
169 int ret; in read_port_regs()
171 ret = i2c_burst_read_dt(&config->bus, reg, (uint8_t *)&port_data, in read_port_regs()
175 config->bus.addr, reg, ret); in read_port_regs()
184 config->bus.addr, reg, (*buf & 0xFF), (reg + 1), (*buf >> 8)); in read_port_regs()
190 static int write_port_reg(const struct device *dev, uint8_t reg, uint8_t pin, in write_port_reg() argument
193 const struct gpio_pca95xx_config * const config = dev->config; in write_port_reg()
195 int ret; in write_port_reg()
197 if (pin < 8) { in write_port_reg()
205 LOG_DBG("PCA95XX[0x%X]: Write: REG[0x%X] = 0x%X", config->bus.addr, in write_port_reg()
208 ret = i2c_write_dt(&config->bus, buf, sizeof(buf)); in write_port_reg()
213 "(%d)", config->bus.addr, reg, ret); in write_port_reg()
231 static int write_port_regs(const struct device *dev, uint8_t reg, in write_port_regs()
234 const struct gpio_pca95xx_config * const config = dev->config; in write_port_regs()
236 int ret; in write_port_regs()
239 "0x%X", config->bus.addr, reg, (value & 0xFF), in write_port_regs()
245 ret = i2c_write_dt(&config->bus, buf, sizeof(buf)); in write_port_regs()
250 "(%d)", config->bus.addr, reg, ret); in write_port_regs()
256 static inline int update_input_reg(const struct device *dev, uint8_t pin, in update_input_reg() argument
260 (struct gpio_pca95xx_drv_data * const)dev->data; in update_input_reg()
262 return read_port_reg(dev, REG_INPUT_PORT0, pin, in update_input_reg()
263 &drv_data->reg_cache.input, buf); in update_input_reg()
266 static inline int update_input_regs(const struct device *dev, uint16_t *buf) in update_input_regs()
269 (struct gpio_pca95xx_drv_data * const)dev->data; in update_input_regs()
272 &drv_data->reg_cache.input, buf); in update_input_regs()
275 static inline int update_output_reg(const struct device *dev, uint8_t pin, in update_output_reg() argument
279 (struct gpio_pca95xx_drv_data * const)dev->data; in update_output_reg()
281 return write_port_reg(dev, REG_OUTPUT_PORT0, pin, in update_output_reg()
282 &drv_data->reg_cache.output, value); in update_output_reg()
285 static inline int update_output_regs(const struct device *dev, uint16_t value) in update_output_regs()
288 (struct gpio_pca95xx_drv_data * const)dev->data; in update_output_regs()
291 &drv_data->reg_cache.output, value); in update_output_regs()
294 static inline int update_direction_reg(const struct device *dev, uint8_t pin, in update_direction_reg() argument
298 (struct gpio_pca95xx_drv_data * const)dev->data; in update_direction_reg()
300 return write_port_reg(dev, REG_CONF_PORT0, pin, in update_direction_reg()
301 &drv_data->reg_cache.dir, value); in update_direction_reg()
304 static inline int update_direction_regs(const struct device *dev, uint16_t value) in update_direction_regs()
307 (struct gpio_pca95xx_drv_data * const)dev->data; in update_direction_regs()
310 &drv_data->reg_cache.dir, value); in update_direction_regs()
313 static inline int update_pul_sel_reg(const struct device *dev, uint8_t pin, in update_pul_sel_reg() argument
317 (struct gpio_pca95xx_drv_data * const)dev->data; in update_pul_sel_reg()
319 return write_port_reg(dev, REG_PUD_SEL_PORT0, pin, in update_pul_sel_reg()
320 &drv_data->reg_cache.pud_sel, value); in update_pul_sel_reg()
323 static inline int update_pul_en_reg(const struct device *dev, uint8_t pin, in update_pul_en_reg() argument
327 (struct gpio_pca95xx_drv_data * const)dev->data; in update_pul_en_reg()
329 return write_port_reg(dev, REG_PUD_EN_PORT0, pin, in update_pul_en_reg()
330 &drv_data->reg_cache.pud_en, value); in update_pul_en_reg()
334 static inline int update_int_mask_reg(const struct device *dev, uint8_t pin, in update_int_mask_reg() argument
338 (struct gpio_pca95xx_drv_data * const)dev->data; in update_int_mask_reg()
341 write_port_reg(dev, REG_INPUT_LATCH_PORT0, pin, &drv_data->reg_cache.input_latch, ~value); in update_int_mask_reg()
343 return write_port_reg(dev, REG_INT_MASK_PORT0, pin, in update_int_mask_reg()
344 &drv_data->reg_cache.int_mask, value); in update_int_mask_reg()
349 * @brief Setup the pin direction (input or output)
352 * @param pin The pin number
353 * @param flags Flags of pin or port
357 static int setup_pin_dir(const struct device *dev, uint32_t pin, int flags) in setup_pin_dir() argument
360 (struct gpio_pca95xx_drv_data * const)dev->data; in setup_pin_dir()
361 uint16_t reg_dir = drv_data->reg_cache.dir; in setup_pin_dir()
362 uint16_t reg_out = drv_data->reg_cache.output; in setup_pin_dir()
363 int ret; in setup_pin_dir()
365 /* For each pin, 0 == output, 1 == input */ in setup_pin_dir()
368 reg_out |= BIT(pin); in setup_pin_dir()
370 reg_out &= ~BIT(pin); in setup_pin_dir()
372 ret = update_output_reg(dev, pin, reg_out); in setup_pin_dir()
376 reg_dir &= ~BIT(pin); in setup_pin_dir()
378 reg_dir |= BIT(pin); in setup_pin_dir()
381 ret = update_direction_reg(dev, pin, reg_dir); in setup_pin_dir()
393 static int init_pins(const struct device *dev) in init_pins()
399 * @brief Setup the pin pull up/pull down status
402 * @param pin The pin number
403 * @param flags Flags of pin or port
407 static int setup_pin_pullupdown(const struct device *dev, uint32_t pin, in setup_pin_pullupdown() argument
408 int flags) in setup_pin_pullupdown()
410 const struct gpio_pca95xx_config * const config = dev->config; in setup_pin_pullupdown()
412 (struct gpio_pca95xx_drv_data * const)dev->data; in setup_pin_pullupdown()
414 int ret; in setup_pin_pullupdown()
416 if ((config->capabilities & PCA_HAS_PUD) == 0) { in setup_pin_pullupdown()
419 return -ENOTSUP; in setup_pin_pullupdown()
433 /* Setup pin pull up or pull down */ in setup_pin_pullupdown()
434 reg_pud = drv_data->reg_cache.pud_sel; in setup_pin_pullupdown()
437 WRITE_BIT(reg_pud, pin, (flags & GPIO_PULL_UP) != 0U); in setup_pin_pullupdown()
439 ret = update_pul_sel_reg(dev, pin, reg_pud); in setup_pin_pullupdown()
446 reg_pud = drv_data->reg_cache.pud_en; in setup_pin_pullupdown()
448 WRITE_BIT(reg_pud, pin, in setup_pin_pullupdown()
451 ret = update_pul_en_reg(dev, pin, reg_pud); in setup_pin_pullupdown()
457 * @brief Configure pin or port
460 * @param pin The pin number
461 * @param flags Flags of pin or port
465 static int gpio_pca95xx_config(const struct device *dev, in gpio_pca95xx_config()
466 gpio_pin_t pin, gpio_flags_t flags) in gpio_pca95xx_config() argument
468 int ret; in gpio_pca95xx_config()
470 (struct gpio_pca95xx_drv_data * const)dev->data; in gpio_pca95xx_config()
473 const struct gpio_pca95xx_config * const config = dev->config; in gpio_pca95xx_config()
476 /* Does not support disconnected pin */ in gpio_pca95xx_config()
478 return -ENOTSUP; in gpio_pca95xx_config()
481 /* Open-drain support is per port, not per pin. in gpio_pca95xx_config()
482 * So can't really support the API as-is. in gpio_pca95xx_config()
485 return -ENOTSUP; in gpio_pca95xx_config()
490 return -EWOULDBLOCK; in gpio_pca95xx_config()
493 k_sem_take(&drv_data->lock, K_FOREVER); in gpio_pca95xx_config()
495 ret = setup_pin_dir(dev, pin, flags); in gpio_pca95xx_config()
497 LOG_ERR("PCA95XX[0x%X]: error setting pin direction (%d)", in gpio_pca95xx_config()
498 config->bus.addr, ret); in gpio_pca95xx_config()
502 ret = setup_pin_pullupdown(dev, pin, flags); in gpio_pca95xx_config()
504 LOG_ERR("PCA95XX[0x%X]: error setting pin pull up/down " in gpio_pca95xx_config()
505 "(%d)", config->bus.addr, ret); in gpio_pca95xx_config()
510 k_sem_give(&drv_data->lock); in gpio_pca95xx_config()
514 static int gpio_pca95xx_port_get_raw(const struct device *dev, uint32_t *value) in gpio_pca95xx_port_get_raw()
517 (struct gpio_pca95xx_drv_data * const)dev->data; in gpio_pca95xx_port_get_raw()
519 int ret; in gpio_pca95xx_port_get_raw()
523 return -EWOULDBLOCK; in gpio_pca95xx_port_get_raw()
526 k_sem_take(&drv_data->lock, K_FOREVER); in gpio_pca95xx_port_get_raw()
536 k_sem_give(&drv_data->lock); in gpio_pca95xx_port_get_raw()
540 static int gpio_pca95xx_port_set_masked_raw(const struct device *dev, in gpio_pca95xx_port_set_masked_raw()
544 (struct gpio_pca95xx_drv_data * const)dev->data; in gpio_pca95xx_port_set_masked_raw()
546 int ret; in gpio_pca95xx_port_set_masked_raw()
550 return -EWOULDBLOCK; in gpio_pca95xx_port_set_masked_raw()
553 k_sem_take(&drv_data->lock, K_FOREVER); in gpio_pca95xx_port_set_masked_raw()
555 reg_out = drv_data->reg_cache.output; in gpio_pca95xx_port_set_masked_raw()
560 k_sem_give(&drv_data->lock); in gpio_pca95xx_port_set_masked_raw()
565 static int gpio_pca95xx_port_set_bits_raw(const struct device *dev, in gpio_pca95xx_port_set_bits_raw()
571 static int gpio_pca95xx_port_clear_bits_raw(const struct device *dev, in gpio_pca95xx_port_clear_bits_raw()
577 static int gpio_pca95xx_port_toggle_bits(const struct device *dev, in gpio_pca95xx_port_toggle_bits()
581 (struct gpio_pca95xx_drv_data * const)dev->data; in gpio_pca95xx_port_toggle_bits()
583 int ret; in gpio_pca95xx_port_toggle_bits()
587 return -EWOULDBLOCK; in gpio_pca95xx_port_toggle_bits()
590 k_sem_take(&drv_data->lock, K_FOREVER); in gpio_pca95xx_port_toggle_bits()
592 reg_out = drv_data->reg_cache.output; in gpio_pca95xx_port_toggle_bits()
597 k_sem_give(&drv_data->lock); in gpio_pca95xx_port_toggle_bits()
607 int ret; in get_triggered_it()
609 input_cache = drv_data->reg_cache.input; in get_triggered_it()
610 ret = update_input_regs(drv_data->instance, &input_new); in get_triggered_it()
615 drv_data->interrupts.edge_rising); in get_triggered_it()
617 drv_data->interrupts.edge_falling); in get_triggered_it()
618 *trig_level |= (input_new & drv_data->interrupts.level_high); in get_triggered_it()
619 *trig_level |= (~input_new & drv_data->interrupts.level_low); in get_triggered_it()
627 const struct gpio_pca95xx_config * const config = drv_data->instance->config; in gpio_pca95xx_interrupt_worker()
631 k_sem_take(&drv_data->lock, K_FOREVER); in gpio_pca95xx_interrupt_worker()
634 if (config->capabilities & PCA_HAS_INTERRUPT_MASK_REG) { in gpio_pca95xx_interrupt_worker()
643 k_sem_give(&drv_data->lock); in gpio_pca95xx_interrupt_worker()
646 gpio_fire_callbacks(&drv_data->callbacks, drv_data->instance, in gpio_pca95xx_interrupt_worker()
653 k_work_submit(&drv_data->interrupt_worker); in gpio_pca95xx_interrupt_worker()
667 k_work_submit(&drv_data->interrupt_worker); in gpio_pca95xx_interrupt_callback()
670 static int gpio_pca95xx_pin_interrupt_configure(const struct device *dev, in gpio_pca95xx_pin_interrupt_configure()
671 gpio_pin_t pin, in gpio_pca95xx_pin_interrupt_configure() argument
675 int ret = 0; in gpio_pca95xx_pin_interrupt_configure()
676 const struct gpio_pca95xx_config * const config = dev->config; in gpio_pca95xx_pin_interrupt_configure()
678 (struct gpio_pca95xx_drv_data * const)dev->data; in gpio_pca95xx_pin_interrupt_configure()
683 if ((config->capabilities & PCA_HAS_INTERRUPT) == 0U) { in gpio_pca95xx_pin_interrupt_configure()
684 return -ENOTSUP; in gpio_pca95xx_pin_interrupt_configure()
687 /* Check for an invalid pin number */ in gpio_pca95xx_pin_interrupt_configure()
688 if (BIT(pin) > config->common.port_pin_mask) { in gpio_pca95xx_pin_interrupt_configure()
689 return -EINVAL; in gpio_pca95xx_pin_interrupt_configure()
692 /* Check configured pin direction */ in gpio_pca95xx_pin_interrupt_configure()
694 (BIT(pin) & drv_data->reg_cache.dir) != BIT(pin)) { in gpio_pca95xx_pin_interrupt_configure()
695 LOG_ERR("PCA95XX[0x%X]: output pin cannot trigger interrupt", in gpio_pca95xx_pin_interrupt_configure()
696 config->bus.addr); in gpio_pca95xx_pin_interrupt_configure()
697 return -ENOTSUP; in gpio_pca95xx_pin_interrupt_configure()
700 k_sem_take(&drv_data->lock, K_FOREVER); in gpio_pca95xx_pin_interrupt_configure()
703 if (config->capabilities & PCA_HAS_INTERRUPT_MASK_REG) { in gpio_pca95xx_pin_interrupt_configure()
706 reg_out = drv_data->reg_cache.int_mask; in gpio_pca95xx_pin_interrupt_configure()
707 WRITE_BIT(reg_out, pin, (mode == GPIO_INT_MODE_DISABLED)); in gpio_pca95xx_pin_interrupt_configure()
709 ret = update_int_mask_reg(dev, pin, reg_out); in gpio_pca95xx_pin_interrupt_configure()
711 LOG_ERR("PCA95XX[0x%X]: failed to update int mask (%d)", in gpio_pca95xx_pin_interrupt_configure()
712 config->bus.addr, ret); in gpio_pca95xx_pin_interrupt_configure()
721 WRITE_BIT(drv_data->interrupts.edge_rising, pin, (enabled && in gpio_pca95xx_pin_interrupt_configure()
723 WRITE_BIT(drv_data->interrupts.edge_falling, pin, (enabled && in gpio_pca95xx_pin_interrupt_configure()
725 WRITE_BIT(drv_data->interrupts.level_high, pin, (enabled && in gpio_pca95xx_pin_interrupt_configure()
727 WRITE_BIT(drv_data->interrupts.level_low, pin, (enabled && in gpio_pca95xx_pin_interrupt_configure()
730 active = ((drv_data->interrupts.edge_rising || in gpio_pca95xx_pin_interrupt_configure()
731 drv_data->interrupts.edge_falling || in gpio_pca95xx_pin_interrupt_configure()
732 drv_data->interrupts.level_high || in gpio_pca95xx_pin_interrupt_configure()
733 drv_data->interrupts.level_low) > 0); in gpio_pca95xx_pin_interrupt_configure()
736 if (active != drv_data->interrupt_active) { in gpio_pca95xx_pin_interrupt_configure()
738 &config->int_gpio, active ? in gpio_pca95xx_pin_interrupt_configure()
743 "on pin %d (%d)", config->bus.addr, in gpio_pca95xx_pin_interrupt_configure()
744 config->int_gpio.pin, ret); in gpio_pca95xx_pin_interrupt_configure()
747 drv_data->interrupt_active = active; in gpio_pca95xx_pin_interrupt_configure()
751 * active signal on INT line in gpio_pca95xx_pin_interrupt_configure()
758 k_sem_give(&drv_data->lock); in gpio_pca95xx_pin_interrupt_configure()
762 static int gpio_pca95xx_manage_callback(const struct device *dev, in gpio_pca95xx_manage_callback()
766 const struct gpio_pca95xx_config * const config = dev->config; in gpio_pca95xx_manage_callback()
768 (struct gpio_pca95xx_drv_data * const)dev->data; in gpio_pca95xx_manage_callback()
770 if ((config->capabilities & PCA_HAS_INTERRUPT) == 0U) { in gpio_pca95xx_manage_callback()
771 return -ENOTSUP; in gpio_pca95xx_manage_callback()
774 k_sem_take(&drv_data->lock, K_FOREVER); in gpio_pca95xx_manage_callback()
776 gpio_manage_callback(&drv_data->callbacks, callback, set); in gpio_pca95xx_manage_callback()
778 k_sem_give(&drv_data->lock); in gpio_pca95xx_manage_callback()
802 static int gpio_pca95xx_init(const struct device *dev) in gpio_pca95xx_init()
804 const struct gpio_pca95xx_config * const config = dev->config; in gpio_pca95xx_init()
806 (struct gpio_pca95xx_drv_data * const)dev->data; in gpio_pca95xx_init()
807 int ret; in gpio_pca95xx_init()
809 if (!device_is_ready(config->bus.bus)) { in gpio_pca95xx_init()
810 return -ENODEV; in gpio_pca95xx_init()
813 k_sem_init(&drv_data->lock, 1, 1); in gpio_pca95xx_init()
822 if ((config->capabilities & PCA_HAS_INTERRUPT) != 0) { in gpio_pca95xx_init()
823 /* Store self-reference for interrupt handling */ in gpio_pca95xx_init()
824 drv_data->instance = dev; in gpio_pca95xx_init()
827 k_work_init(&drv_data->interrupt_worker, in gpio_pca95xx_init()
830 /* Configure GPIO interrupt pin */ in gpio_pca95xx_init()
831 if (!gpio_is_ready_dt(&config->int_gpio)) { in gpio_pca95xx_init()
833 config->bus.addr); in gpio_pca95xx_init()
834 return -ENODEV; in gpio_pca95xx_init()
837 ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); in gpio_pca95xx_init()
840 " pin %d (%d)", config->bus.addr, in gpio_pca95xx_init()
841 config->int_gpio.pin, ret); in gpio_pca95xx_init()
845 /* Prepare GPIO callback for interrupt pin */ in gpio_pca95xx_init()
846 gpio_init_callback(&drv_data->gpio_callback, in gpio_pca95xx_init()
848 BIT(config->int_gpio.pin)); in gpio_pca95xx_init()
849 ret = gpio_add_callback(config->int_gpio.port, &drv_data->gpio_callback); in gpio_pca95xx_init()
852 " pin %d (%d)", config->bus.addr, in gpio_pca95xx_init()
853 config->int_gpio.pin, ret); in gpio_pca95xx_init()