Lines Matching +full:16 +full:- +full:pin
5 * SPDX-License-Identifier: Apache-2.0
9 * @file Driver for MPC23xxx I2C/SPI-based GPIO driver.
42 const struct mcp23xxx_config *config = dev->config; in read_port_regs()
44 if (config->ngpios == 16U) { in read_port_regs()
48 return config->read_fn(dev, reg, buf); in read_port_regs()
65 const struct mcp23xxx_config *config = dev->config; in write_port_regs()
67 if (config->ngpios == 16U) { in write_port_regs()
71 return config->write_fn(dev, reg, value); in write_port_regs()
77 * IOCON is the only register that is not 16 bits wide on 16-pin devices; instead, it is mirrored in
78 * two adjacent memory locations. Because the underlying `write_fn` always does a 16-bit write for
79 * 16-pin devices, make sure we write the same value to both IOCON locations.
88 struct mcp23xxx_drv_data *drv_data = dev->data; in write_iocon()
94 drv_data->reg_cache.iocon = extended_value; in write_iocon()
101 * @brief Setup the pin direction.
104 * @param pin The pin number.
105 * @param flags Flags of pin or port.
108 static int setup_pin_dir(const struct device *dev, uint32_t pin, int flags) in setup_pin_dir() argument
110 struct mcp23xxx_drv_data *drv_data = dev->data; in setup_pin_dir()
111 uint16_t dir = drv_data->reg_cache.iodir; in setup_pin_dir()
112 uint16_t output = drv_data->reg_cache.gpio; in setup_pin_dir()
117 output |= BIT(pin); in setup_pin_dir()
119 output &= ~BIT(pin); in setup_pin_dir()
121 dir &= ~BIT(pin); in setup_pin_dir()
123 dir |= BIT(pin); in setup_pin_dir()
131 drv_data->reg_cache.gpio = output; in setup_pin_dir()
135 drv_data->reg_cache.iodir = dir; in setup_pin_dir()
142 * @brief Setup pin pull up/pull down.
145 * @param pin The pin number.
146 * @param flags Flags of pin or port.
149 static int setup_pin_pull(const struct device *dev, uint32_t pin, int flags) in setup_pin_pull() argument
151 struct mcp23xxx_drv_data *drv_data = dev->data; in setup_pin_pull()
155 port = drv_data->reg_cache.gppu; in setup_pin_pull()
158 return -ENOTSUP; in setup_pin_pull()
161 WRITE_BIT(port, pin, (flags & GPIO_PULL_UP) != 0); in setup_pin_pull()
165 drv_data->reg_cache.gppu = port; in setup_pin_pull()
171 static int mcp23xxx_pin_cfg(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) in mcp23xxx_pin_cfg() argument
173 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_pin_cfg()
174 const struct mcp23xxx_config *config = dev->config; in mcp23xxx_pin_cfg()
178 return -EWOULDBLOCK; in mcp23xxx_pin_cfg()
181 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_pin_cfg()
183 if ((bool)(flags & GPIO_SINGLE_ENDED) != config->is_open_drain || in mcp23xxx_pin_cfg()
184 (bool)(flags & GPIO_LINE_OPEN_DRAIN) != config->is_open_drain) { in mcp23xxx_pin_cfg()
185 ret = -ENOTSUP; in mcp23xxx_pin_cfg()
189 ret = setup_pin_dir(dev, pin, flags); in mcp23xxx_pin_cfg()
191 LOG_ERR("Error setting pin direction (%d)", ret); in mcp23xxx_pin_cfg()
195 ret = setup_pin_pull(dev, pin, flags); in mcp23xxx_pin_cfg()
197 LOG_ERR("Error setting pin pull up/pull down (%d)", ret); in mcp23xxx_pin_cfg()
202 k_sem_give(&drv_data->lock); in mcp23xxx_pin_cfg()
208 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_port_get_raw()
213 return -EWOULDBLOCK; in mcp23xxx_port_get_raw()
216 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_port_get_raw()
223 k_sem_give(&drv_data->lock); in mcp23xxx_port_get_raw()
229 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_port_set_masked_raw()
234 return -EWOULDBLOCK; in mcp23xxx_port_set_masked_raw()
237 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_port_set_masked_raw()
239 buf = drv_data->reg_cache.gpio; in mcp23xxx_port_set_masked_raw()
244 drv_data->reg_cache.gpio = buf; in mcp23xxx_port_set_masked_raw()
247 k_sem_give(&drv_data->lock); in mcp23xxx_port_set_masked_raw()
263 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_port_toggle_bits()
268 return -EWOULDBLOCK; in mcp23xxx_port_toggle_bits()
271 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_port_toggle_bits()
273 buf = drv_data->reg_cache.gpio; in mcp23xxx_port_toggle_bits()
278 drv_data->reg_cache.gpio = buf; in mcp23xxx_port_toggle_bits()
281 k_sem_give(&drv_data->lock); in mcp23xxx_port_toggle_bits()
286 static int mcp23xxx_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, in mcp23xxx_pin_interrupt_configure() argument
289 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_pin_interrupt_configure()
290 const struct mcp23xxx_config *config = dev->config; in mcp23xxx_pin_interrupt_configure()
292 if (!config->gpio_int.port) { in mcp23xxx_pin_interrupt_configure()
293 return -ENOTSUP; in mcp23xxx_pin_interrupt_configure()
297 return -EWOULDBLOCK; in mcp23xxx_pin_interrupt_configure()
300 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_pin_interrupt_configure()
302 uint16_t gpinten = drv_data->reg_cache.gpinten; in mcp23xxx_pin_interrupt_configure()
303 uint16_t defval = drv_data->reg_cache.defval; in mcp23xxx_pin_interrupt_configure()
304 uint16_t intcon = drv_data->reg_cache.intcon; in mcp23xxx_pin_interrupt_configure()
310 gpinten &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
314 gpinten |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
315 intcon |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
319 defval |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
322 defval &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
326 ret = -ENOTSUP; in mcp23xxx_pin_interrupt_configure()
329 ret = -EINVAL; in mcp23xxx_pin_interrupt_configure()
335 gpinten |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
336 intcon &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
340 drv_data->rising_edge_ints &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
341 drv_data->falling_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
344 drv_data->rising_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
345 drv_data->falling_edge_ints &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
348 drv_data->rising_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
349 drv_data->falling_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
352 ret = -EINVAL; in mcp23xxx_pin_interrupt_configure()
362 drv_data->reg_cache.gpinten = gpinten; in mcp23xxx_pin_interrupt_configure()
368 drv_data->reg_cache.defval = defval; in mcp23xxx_pin_interrupt_configure()
374 drv_data->reg_cache.intcon = intcon; in mcp23xxx_pin_interrupt_configure()
377 k_sem_give(&drv_data->lock); in mcp23xxx_pin_interrupt_configure()
385 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_manage_callback()
386 const struct mcp23xxx_config *config = dev->config; in mcp23xxx_manage_callback()
388 if (!config->gpio_int.port) { in mcp23xxx_manage_callback()
389 return -ENOTSUP; in mcp23xxx_manage_callback()
393 return -EWOULDBLOCK; in mcp23xxx_manage_callback()
396 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_manage_callback()
398 int ret = gpio_manage_callback(&drv_data->callbacks, callback, set); in mcp23xxx_manage_callback()
400 k_sem_give(&drv_data->lock); in mcp23xxx_manage_callback()
408 const struct device *dev = drv_data->dev; in mcp23xxx_work_handler()
412 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_work_handler()
424 * - REG_GPIO was read from somewhere else before the interrupt handler had a chance in mcp23xxx_work_handler()
426 * - Even though the datasheet says differently, reading INTCAP while a level in mcp23xxx_work_handler()
444 /* mcp23xxx does not support single-edge interrupts in hardware, filter them out manually */ in mcp23xxx_work_handler()
445 uint16_t level_ints = drv_data->reg_cache.gpinten & drv_data->reg_cache.intcon; in mcp23xxx_work_handler()
447 intf &= level_ints | (intcap & drv_data->rising_edge_ints) | in mcp23xxx_work_handler()
448 (~intcap & drv_data->falling_edge_ints); in mcp23xxx_work_handler()
450 k_sem_give(&drv_data->lock); in mcp23xxx_work_handler()
451 gpio_fire_callbacks(&drv_data->callbacks, dev, intf); in mcp23xxx_work_handler()
455 k_sem_give(&drv_data->lock); in mcp23xxx_work_handler()
464 k_work_submit(&drv_data->work); in mcp23xxx_int_gpio_handler()
486 const struct mcp23xxx_config *config = dev->config; in gpio_mcp23xxx_init()
487 struct mcp23xxx_drv_data *drv_data = dev->data; in gpio_mcp23xxx_init()
490 if (config->ngpios != 8U && config->ngpios != 16U) { in gpio_mcp23xxx_init()
491 LOG_ERR("Invalid value ngpios=%u. Expected 8 or 16!", config->ngpios); in gpio_mcp23xxx_init()
492 return -EINVAL; in gpio_mcp23xxx_init()
495 err = config->bus_fn(dev); in gpio_mcp23xxx_init()
500 k_sem_init(&drv_data->lock, 0, 1); in gpio_mcp23xxx_init()
503 if (config->gpio_reset.port) { in gpio_mcp23xxx_init()
504 err = gpio_pin_configure_dt(&config->gpio_reset, GPIO_OUTPUT_ACTIVE); in gpio_mcp23xxx_init()
507 return -EIO; in gpio_mcp23xxx_init()
512 err = gpio_pin_set_dt(&config->gpio_reset, 0); in gpio_mcp23xxx_init()
515 return -EIO; in gpio_mcp23xxx_init()
520 if (config->gpio_int.port) { in gpio_mcp23xxx_init()
521 if (config->ngpios == 16) { in gpio_mcp23xxx_init()
522 /* send both ports' interrupts through one IRQ pin */ in gpio_mcp23xxx_init()
527 return -EIO; in gpio_mcp23xxx_init()
531 if (!gpio_is_ready_dt(&config->gpio_int)) { in gpio_mcp23xxx_init()
533 return -ENODEV; in gpio_mcp23xxx_init()
536 drv_data->dev = dev; in gpio_mcp23xxx_init()
537 k_work_init(&drv_data->work, mcp23xxx_work_handler); in gpio_mcp23xxx_init()
539 err = gpio_pin_configure_dt(&config->gpio_int, GPIO_INPUT); in gpio_mcp23xxx_init()
542 return -EIO; in gpio_mcp23xxx_init()
545 gpio_init_callback(&drv_data->int_gpio_cb, mcp23xxx_int_gpio_handler, in gpio_mcp23xxx_init()
546 BIT(config->gpio_int.pin)); in gpio_mcp23xxx_init()
547 err = gpio_add_callback(config->gpio_int.port, &drv_data->int_gpio_cb); in gpio_mcp23xxx_init()
550 return -EIO; in gpio_mcp23xxx_init()
553 err = gpio_pin_interrupt_configure_dt(&config->gpio_int, GPIO_INT_EDGE_TO_ACTIVE); in gpio_mcp23xxx_init()
556 return -EIO; in gpio_mcp23xxx_init()
560 k_sem_give(&drv_data->lock); in gpio_mcp23xxx_init()