drivers: mcp23xxx: add support for open-drain chip variants

Pin definitions should correctly reflect the actual drive mode of the GPIO
controller, either push-pull or open drain.

Signed-off-by: Armin Brauns <armin.brauns@embedded-solutions.at>
This commit is contained in:
Armin Brauns 2023-11-27 08:39:01 +00:00 committed by Carles Cufí
commit ede19a4337
5 changed files with 20 additions and 13 deletions

View file

@ -49,7 +49,9 @@ Device Drivers and Devicetree
``microchip,mcp230xx`` and ``microchip,mcp23sxx`` should change their devicetree ``compatible``
values to the specific chip variant, e.g. :dtcompatible:`microchip,mcp23017`.
The ``ngpios`` devicetree property has been removed, since it is implied by the model name.
(:github:`65797`)
Chip variants with open-drain outputs (``mcp23x09``, ``mcp23x18``) now correctly reflect this in
their driver API, users of these devices should ensure they pass appropriate values to
:c:func:`gpio_pin_set`. (:github:`65797`)
Controller Area Network (CAN)
=============================

View file

@ -75,7 +75,7 @@ static int mcp230xx_bus_is_ready(const struct device *dev)
return 0;
}
#define GPIO_MCP230XX_DEVICE(inst, num_gpios) \
#define GPIO_MCP230XX_DEVICE(inst, num_gpios, open_drain) \
static struct mcp23xxx_drv_data mcp230xx_##inst##_drvdata = { \
/* Default for registers according to datasheet */ \
.reg_cache.iodir = 0xFFFF, .reg_cache.ipol = 0x0, .reg_cache.gpinten = 0x0, \
@ -93,6 +93,7 @@ static int mcp230xx_bus_is_ready(const struct device *dev)
.gpio_int = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \
.gpio_reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \
.ngpios = num_gpios, \
.is_open_drain = open_drain, \
.read_fn = mcp230xx_read_port_regs, \
.write_fn = mcp230xx_write_port_regs, \
.bus_fn = mcp230xx_bus_is_ready, \
@ -102,17 +103,17 @@ static int mcp230xx_bus_is_ready(const struct device *dev)
CONFIG_GPIO_MCP230XX_INIT_PRIORITY, &gpio_mcp23xxx_api_table);
#define DT_DRV_COMPAT microchip_mcp23008
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 8)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 8, false)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT microchip_mcp23009
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 8)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 8, true)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT microchip_mcp23016
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 16)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 16, false)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT microchip_mcp23017
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 16)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 16, false)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT microchip_mcp23018
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 16)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP230XX_DEVICE, 16, true)
#undef DT_DRV_COMPAT

View file

@ -113,7 +113,7 @@ static int mcp23sxx_bus_is_ready(const struct device *dev)
return 0;
}
#define GPIO_MCP23SXX_DEVICE(inst, num_gpios) \
#define GPIO_MCP23SXX_DEVICE(inst, num_gpios, open_drain) \
static struct mcp23xxx_drv_data mcp23sxx_##inst##_drvdata = { \
/* Default for registers according to datasheet */ \
.reg_cache.iodir = 0xFFFF, .reg_cache.ipol = 0x0, .reg_cache.gpinten = 0x0, \
@ -133,6 +133,7 @@ static int mcp23sxx_bus_is_ready(const struct device *dev)
.gpio_int = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \
.gpio_reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \
.ngpios = num_gpios, \
.is_open_drain = open_drain, \
.read_fn = mcp23sxx_read_port_regs, \
.write_fn = mcp23sxx_write_port_regs, \
.bus_fn = mcp23sxx_bus_is_ready \
@ -143,14 +144,14 @@ static int mcp23sxx_bus_is_ready(const struct device *dev)
#define DT_DRV_COMPAT microchip_mcp23s08
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 8)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 8, false)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT microchip_mcp23s09
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 8)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 8, true)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT microchip_mcp23s17
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 16)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 16, false)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT microchip_mcp23s18
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 16)
DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MCP23SXX_DEVICE, 16, true)
#undef DT_DRV_COMPAT

View file

@ -171,6 +171,7 @@ static int setup_pin_pull(const struct device *dev, uint32_t pin, int flags)
static int mcp23xxx_pin_cfg(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
{
struct mcp23xxx_drv_data *drv_data = dev->data;
const struct mcp23xxx_config *config = dev->config;
int ret;
if (k_is_in_isr()) {
@ -179,7 +180,8 @@ static int mcp23xxx_pin_cfg(const struct device *dev, gpio_pin_t pin, gpio_flags
k_sem_take(&drv_data->lock, K_FOREVER);
if ((flags & GPIO_SINGLE_ENDED) != 0U) {
if ((bool)(flags & GPIO_SINGLE_ENDED) != config->is_open_drain ||
(bool)(flags & GPIO_LINE_OPEN_DRAIN) != config->is_open_drain) {
ret = -ENOTSUP;
goto done;
}

View file

@ -61,6 +61,7 @@ struct mcp23xxx_config {
struct gpio_dt_spec gpio_reset;
uint8_t ngpios;
bool is_open_drain;
mcp23xxx_read_port_regs read_fn;
mcp23xxx_write_port_regs write_fn;
mcp23xxx_bus_is_ready bus_fn;