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()
177 return -EWOULDBLOCK; in mcp23xxx_pin_cfg()
180 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_pin_cfg()
183 ret = -ENOTSUP; in mcp23xxx_pin_cfg()
187 ret = setup_pin_dir(dev, pin, flags); in mcp23xxx_pin_cfg()
189 LOG_ERR("Error setting pin direction (%d)", ret); in mcp23xxx_pin_cfg()
193 ret = setup_pin_pull(dev, pin, flags); in mcp23xxx_pin_cfg()
195 LOG_ERR("Error setting pin pull up/pull down (%d)", ret); in mcp23xxx_pin_cfg()
200 k_sem_give(&drv_data->lock); in mcp23xxx_pin_cfg()
206 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_port_get_raw()
211 return -EWOULDBLOCK; in mcp23xxx_port_get_raw()
214 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_port_get_raw()
221 k_sem_give(&drv_data->lock); in mcp23xxx_port_get_raw()
227 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_port_set_masked_raw()
232 return -EWOULDBLOCK; in mcp23xxx_port_set_masked_raw()
235 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_port_set_masked_raw()
237 buf = drv_data->reg_cache.gpio; in mcp23xxx_port_set_masked_raw()
242 drv_data->reg_cache.gpio = buf; in mcp23xxx_port_set_masked_raw()
245 k_sem_give(&drv_data->lock); in mcp23xxx_port_set_masked_raw()
261 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_port_toggle_bits()
266 return -EWOULDBLOCK; in mcp23xxx_port_toggle_bits()
269 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_port_toggle_bits()
271 buf = drv_data->reg_cache.gpio; in mcp23xxx_port_toggle_bits()
276 drv_data->reg_cache.gpio = buf; in mcp23xxx_port_toggle_bits()
279 k_sem_give(&drv_data->lock); in mcp23xxx_port_toggle_bits()
284 static int mcp23xxx_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, in mcp23xxx_pin_interrupt_configure() argument
287 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_pin_interrupt_configure()
288 const struct mcp23xxx_config *config = dev->config; in mcp23xxx_pin_interrupt_configure()
290 if (!config->gpio_int.port) { in mcp23xxx_pin_interrupt_configure()
291 return -ENOTSUP; in mcp23xxx_pin_interrupt_configure()
295 return -EWOULDBLOCK; in mcp23xxx_pin_interrupt_configure()
298 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_pin_interrupt_configure()
300 uint16_t gpinten = drv_data->reg_cache.gpinten; in mcp23xxx_pin_interrupt_configure()
301 uint16_t defval = drv_data->reg_cache.defval; in mcp23xxx_pin_interrupt_configure()
302 uint16_t intcon = drv_data->reg_cache.intcon; in mcp23xxx_pin_interrupt_configure()
308 gpinten &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
312 gpinten |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
313 intcon |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
317 defval |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
320 defval &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
324 ret = -ENOTSUP; in mcp23xxx_pin_interrupt_configure()
330 gpinten |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
331 intcon &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
335 drv_data->rising_edge_ints &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
336 drv_data->falling_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
339 drv_data->rising_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
340 drv_data->falling_edge_ints &= ~BIT(pin); in mcp23xxx_pin_interrupt_configure()
343 drv_data->rising_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
344 drv_data->falling_edge_ints |= BIT(pin); in mcp23xxx_pin_interrupt_configure()
354 drv_data->reg_cache.gpinten = gpinten; in mcp23xxx_pin_interrupt_configure()
360 drv_data->reg_cache.defval = defval; in mcp23xxx_pin_interrupt_configure()
366 drv_data->reg_cache.intcon = intcon; in mcp23xxx_pin_interrupt_configure()
369 k_sem_give(&drv_data->lock); in mcp23xxx_pin_interrupt_configure()
377 struct mcp23xxx_drv_data *drv_data = dev->data; in mcp23xxx_manage_callback()
378 const struct mcp23xxx_config *config = dev->config; in mcp23xxx_manage_callback()
380 if (!config->gpio_int.port) { in mcp23xxx_manage_callback()
381 return -ENOTSUP; in mcp23xxx_manage_callback()
385 return -EWOULDBLOCK; in mcp23xxx_manage_callback()
388 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_manage_callback()
390 int ret = gpio_manage_callback(&drv_data->callbacks, callback, set); in mcp23xxx_manage_callback()
392 k_sem_give(&drv_data->lock); in mcp23xxx_manage_callback()
400 const struct device *dev = drv_data->dev; in mcp23xxx_work_handler()
404 k_sem_take(&drv_data->lock, K_FOREVER); in mcp23xxx_work_handler()
431 /* mcp23xxx does not support single-edge interrupts in hardware, filter them out manually */ in mcp23xxx_work_handler()
432 uint16_t level_ints = drv_data->reg_cache.gpinten & drv_data->reg_cache.intcon; in mcp23xxx_work_handler()
434 intf &= level_ints | (intcap & drv_data->rising_edge_ints) | in mcp23xxx_work_handler()
435 (~intcap & drv_data->falling_edge_ints); in mcp23xxx_work_handler()
437 k_sem_give(&drv_data->lock); in mcp23xxx_work_handler()
438 gpio_fire_callbacks(&drv_data->callbacks, dev, intf); in mcp23xxx_work_handler()
442 k_sem_give(&drv_data->lock); in mcp23xxx_work_handler()
451 k_work_submit(&drv_data->work); in mcp23xxx_int_gpio_handler()
473 const struct mcp23xxx_config *config = dev->config; in gpio_mcp23xxx_init()
474 struct mcp23xxx_drv_data *drv_data = dev->data; in gpio_mcp23xxx_init()
477 if (config->ngpios != 8U && config->ngpios != 16U) { in gpio_mcp23xxx_init()
478 LOG_ERR("Invalid value ngpios=%u. Expected 8 or 16!", config->ngpios); in gpio_mcp23xxx_init()
479 return -EINVAL; in gpio_mcp23xxx_init()
482 err = config->bus_fn(dev); in gpio_mcp23xxx_init()
487 k_sem_init(&drv_data->lock, 0, 1); in gpio_mcp23xxx_init()
490 if (config->gpio_reset.port) { in gpio_mcp23xxx_init()
491 err = gpio_pin_configure_dt(&config->gpio_reset, GPIO_OUTPUT_ACTIVE); in gpio_mcp23xxx_init()
494 return -EIO; in gpio_mcp23xxx_init()
499 err = gpio_pin_set_dt(&config->gpio_reset, 0); in gpio_mcp23xxx_init()
502 return -EIO; in gpio_mcp23xxx_init()
507 if (config->gpio_int.port) { in gpio_mcp23xxx_init()
508 if (config->ngpios == 16) { in gpio_mcp23xxx_init()
509 /* send both ports' interrupts through one IRQ pin */ in gpio_mcp23xxx_init()
514 return -EIO; in gpio_mcp23xxx_init()
518 if (!gpio_is_ready_dt(&config->gpio_int)) { in gpio_mcp23xxx_init()
520 return -ENODEV; in gpio_mcp23xxx_init()
523 drv_data->dev = dev; in gpio_mcp23xxx_init()
524 k_work_init(&drv_data->work, mcp23xxx_work_handler); in gpio_mcp23xxx_init()
526 err = gpio_pin_configure_dt(&config->gpio_int, GPIO_INPUT); in gpio_mcp23xxx_init()
529 return -EIO; in gpio_mcp23xxx_init()
532 gpio_init_callback(&drv_data->int_gpio_cb, mcp23xxx_int_gpio_handler, in gpio_mcp23xxx_init()
533 BIT(config->gpio_int.pin)); in gpio_mcp23xxx_init()
534 err = gpio_add_callback(config->gpio_int.port, &drv_data->int_gpio_cb); in gpio_mcp23xxx_init()
537 return -EIO; in gpio_mcp23xxx_init()
540 err = gpio_pin_interrupt_configure_dt(&config->gpio_int, GPIO_INT_EDGE_TO_ACTIVE); in gpio_mcp23xxx_init()
543 return -EIO; in gpio_mcp23xxx_init()
547 k_sem_give(&drv_data->lock); in gpio_mcp23xxx_init()