diff --git a/drivers/gpio/gpio_cc2650.c b/drivers/gpio/gpio_cc2650.c index 7fa676897a84f..44d466a77d0e1 100644 --- a/drivers/gpio/gpio_cc2650.c +++ b/drivers/gpio/gpio_cc2650.c @@ -164,7 +164,7 @@ static int gpio_cc2650_config_pin(int pin, int flags) if (flags & GPIO_DS_DISCONNECT_LOW) { disconnect(pin, &gpio_doe31_0_config, &iocfg_config); } - if (flags & GPIO_DS_ALT_LOW) { + if ((flags & GPIO_DS_LOW_MASK) == GPIO_DS_HI_LOW) { iocfg_config |= CC2650_IOC_MAX_DRIVE_STRENGTH; } else { iocfg_config |= CC2650_IOC_MIN_DRIVE_STRENGTH; diff --git a/drivers/gpio/gpio_dw.c b/drivers/gpio/gpio_dw.c index 2706b399d72ee..5cb33818d44ef 100644 --- a/drivers/gpio/gpio_dw.c +++ b/drivers/gpio/gpio_dw.c @@ -154,7 +154,7 @@ static inline void dw_interrupt_config(struct device *port, int access_op, struct gpio_dw_runtime *context = port->driver_data; const struct gpio_dw_config *config = port->config->config_info; u32_t base_addr = dw_base_to_block_base(context->base_addr); - u8_t flag_is_set; + bool flag_is_set; ARG_UNUSED(access_op); diff --git a/drivers/gpio/gpio_esp32.c b/drivers/gpio/gpio_esp32.c index a4a0ead673608..20841cc6dc1cf 100644 --- a/drivers/gpio/gpio_esp32.c +++ b/drivers/gpio/gpio_esp32.c @@ -52,7 +52,7 @@ static int convert_int_type(int flags) return 0; /* Disables interrupt for a pin. */ } - if ((flags & GPIO_INT_EDGE) == GPIO_INT_EDGE) { + if ((flags & GPIO_INT_TRIGGER_MASK) == GPIO_INT_EDGE) { if ((flags & GPIO_INT_ACTIVE_HIGH) == GPIO_INT_ACTIVE_HIGH) { return 1; } @@ -64,7 +64,7 @@ static int convert_int_type(int flags) return 2; /* Defaults to falling edge. */ } - if ((flags & GPIO_INT_LEVEL) == GPIO_INT_LEVEL) { + if ((flags & GPIO_INT_TRIGGER_MASK) == GPIO_INT_LEVEL) { if ((flags & GPIO_INT_ACTIVE_HIGH) == GPIO_INT_ACTIVE_HIGH) { return 5; } diff --git a/drivers/gpio/gpio_nrfx.c b/drivers/gpio/gpio_nrfx.c index 3460ac27844da..5047809081a10 100644 --- a/drivers/gpio/gpio_nrfx.c +++ b/drivers/gpio/gpio_nrfx.c @@ -134,31 +134,39 @@ static int gpio_nrfx_config(struct device *port, int access_op, u8_t from_pin; u8_t to_pin; + /* Map default selections to Nordic standard (low) */ + if ((flags & GPIO_DS_LOW_MASK) == GPIO_DS_DFLT_LOW) { + flags |= GPIO_DS_LO_LOW; + } + if ((flags & GPIO_DS_HIGH_MASK) == GPIO_DS_DFLT_HIGH) { + flags |= GPIO_DS_LO_HIGH; + } + switch (flags & (GPIO_DS_LOW_MASK | GPIO_DS_HIGH_MASK)) { - case GPIO_DS_DFLT_LOW | GPIO_DS_DFLT_HIGH: + case GPIO_DS_LO_LOW | GPIO_DS_LO_HIGH: drive = NRF_GPIO_PIN_S0S1; break; - case GPIO_DS_DFLT_LOW | GPIO_DS_ALT_HIGH: + case GPIO_DS_LO_LOW | GPIO_DS_HI_HIGH: drive = NRF_GPIO_PIN_S0H1; break; - case GPIO_DS_DFLT_LOW | GPIO_DS_DISCONNECT_HIGH: + case GPIO_DS_LO_LOW | GPIO_DS_DISCONNECT_HIGH: drive = NRF_GPIO_PIN_S0D1; break; - case GPIO_DS_ALT_LOW | GPIO_DS_DFLT_HIGH: + case GPIO_DS_HI_LOW | GPIO_DS_LO_HIGH: drive = NRF_GPIO_PIN_H0S1; break; - case GPIO_DS_ALT_LOW | GPIO_DS_ALT_HIGH: + case GPIO_DS_HI_LOW | GPIO_DS_HI_HIGH: drive = NRF_GPIO_PIN_H0H1; break; - case GPIO_DS_ALT_LOW | GPIO_DS_DISCONNECT_HIGH: + case GPIO_DS_HI_LOW | GPIO_DS_DISCONNECT_HIGH: drive = NRF_GPIO_PIN_H0D1; break; - case GPIO_DS_DISCONNECT_LOW | GPIO_DS_DFLT_HIGH: + case GPIO_DS_DISCONNECT_LOW | GPIO_DS_LO_HIGH: drive = NRF_GPIO_PIN_D0S1; break; - case GPIO_DS_DISCONNECT_LOW | GPIO_DS_ALT_HIGH: + case GPIO_DS_DISCONNECT_LOW | GPIO_DS_HI_HIGH: drive = NRF_GPIO_PIN_D0H1; break; diff --git a/drivers/gpio/gpio_qmsi.c b/drivers/gpio/gpio_qmsi.c index 1db10b9ad498f..f8213d890ff01 100644 --- a/drivers/gpio/gpio_qmsi.c +++ b/drivers/gpio/gpio_qmsi.c @@ -171,7 +171,7 @@ static void gpio_qmsi_callback(void *data, u32_t status) } } -static void qmsi_write_bit(u32_t *target, u8_t bit, u8_t value) +static void qmsi_write_bit(u32_t *target, u8_t bit, bool value) { if (value) { sys_set_bit((uintptr_t) target, bit); diff --git a/drivers/gpio/gpio_qmsi_ss.c b/drivers/gpio/gpio_qmsi_ss.c index f17588603756e..61d81d81a833b 100644 --- a/drivers/gpio/gpio_qmsi_ss.c +++ b/drivers/gpio/gpio_qmsi_ss.c @@ -143,7 +143,7 @@ static void ss_gpio_qmsi_callback(void *data, uint32_t status) } } -static void ss_qmsi_write_bit(u32_t *target, u8_t bit, u8_t value) +static void ss_qmsi_write_bit(u32_t *target, u8_t bit, bool value) { if (value) { sys_set_bit((uintptr_t) target, bit); diff --git a/drivers/gpio/gpio_sx1509b.c b/drivers/gpio/gpio_sx1509b.c index fb0270364df5b..22b7dbdd9bbcd 100644 --- a/drivers/gpio/gpio_sx1509b.c +++ b/drivers/gpio/gpio_sx1509b.c @@ -14,15 +14,17 @@ #include #include -/** Cache of the output configuration and data of the pins */ +/** Cache of the output configuration and data of the pins. */ struct gpio_sx1509b_pin_state { - u16_t input_disable; - u16_t pull_up; - u16_t pull_down; - u16_t open_drain; - u16_t polarity; - u16_t dir; - u16_t data; + u16_t input_disable; /* 0x00 */ + u16_t long_slew; /* 0x02 */ + u16_t low_drive; /* 0x04 */ + u16_t pull_up; /* 0x06 */ + u16_t pull_down; /* 0x08 */ + u16_t open_drain; /* 0x0A */ + u16_t polarity; /* 0x0C */ + u16_t dir; /* 0x0E */ + u16_t data; /* 0x10 */ }; /** Runtime driver data */ @@ -89,12 +91,12 @@ static inline int i2c_reg_write_word_be(struct device *dev, u16_t dev_addr, } /** - * @brief Configure pin or port + * @brief Configure pin (port not supported) * * @param dev Device struct of the SX1509B - * @param access_op Access operation (pin or port) + * @param access_op Access operation (pin only, port not supported) * @param pin The pin number - * @param flags Flags of pin or port + * @param flags Flags of pin * * @return 0 if successful, failed otherwise */ @@ -104,112 +106,108 @@ static int gpio_sx1509b_config(struct device *dev, int access_op, u32_t pin, const struct gpio_sx1509b_config *cfg = dev->config->config_info; struct gpio_sx1509b_drv_data *drv_data = dev->driver_data; struct gpio_sx1509b_pin_state *pins = &drv_data->pin_state; + struct { + u8_t reg; + struct gpio_sx1509b_pin_state pins; + } __packed outbuf; int ret = 0; + u16_t bit = BIT(pin); + bool data_first = false; + + if (access_op != GPIO_ACCESS_BY_PIN) { + return -ENOTSUP; + } - if (flags & GPIO_INT) { + if (flags & GPIO_INT_ENABLE) { return -ENOTSUP; } k_sem_take(&drv_data->lock, K_FOREVER); - switch (access_op) { - case GPIO_ACCESS_BY_PIN: - if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) { - pins->dir |= BIT(pin); - pins->input_disable &= ~BIT(pin); - } else { - pins->dir &= ~BIT(pin); - pins->input_disable |= BIT(pin); - } - if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) { - pins->pull_up |= BIT(pin); - } else { - pins->pull_up &= ~BIT(pin); - } - if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_DOWN) { - pins->pull_down |= BIT(pin); - } else { - pins->pull_down &= ~BIT(pin); - } - if ((flags & GPIO_PUD_MASK) == GPIO_PUD_NORMAL) { - pins->pull_up &= ~BIT(pin); - pins->pull_down &= ~BIT(pin); - } - if (flags & GPIO_DS_DISCONNECT_HIGH) { - pins->open_drain |= BIT(pin); - } else { - pins->open_drain &= ~BIT(pin); - } - if (flags & GPIO_POL_INV) { - pins->polarity |= BIT(pin); - } else { - pins->polarity &= ~BIT(pin); - } - break; - case GPIO_ACCESS_BY_PORT: - if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) { - pins->dir = 0xffff; - pins->input_disable = 0x0000; - } else { - pins->dir = 0x0000; - pins->input_disable = 0xffff; - } - if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) { - pins->pull_up = 0xffff; - } else { - pins->pull_up = 0x0000; - } - if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_DOWN) { - pins->pull_down = 0xffff; - } else { - pins->pull_down = 0x0000; - } - if ((flags & GPIO_PUD_MASK) == GPIO_PUD_NORMAL) { - pins->pull_up = 0x0000; - pins->pull_down = 0x0000; - } - if (flags & GPIO_DS_DISCONNECT_HIGH) { - pins->open_drain = 0xffff; - } else { - pins->open_drain = 0x0000; - } - if (flags & GPIO_POL_INV) { - pins->polarity = 0xffff; - } else { - pins->polarity = 0x0000; - } - break; + if ((flags & GPIO_OPEN_MASK) == GPIO_OPEN_DRAIN) { + pins->open_drain |= bit; + } else { + pins->open_drain &= ~bit; + } + + switch (flags & GPIO_PUD_MASK) { default: - ret = -ENOTSUP; + ret = -EINVAL; goto out; + case GPIO_PUD_NORMAL: + pins->pull_up &= ~bit; + pins->pull_down &= ~bit; + break; + case GPIO_PUD_PULL_UP: + pins->pull_up |= bit; + pins->pull_down &= ~bit; + break; + case GPIO_PUD_PULL_DOWN: + pins->pull_up &= ~bit; + pins->pull_down |= bit; + break; } - ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr, - SX1509B_REG_DIR, pins->dir); - if (ret) - goto out; + if (flags & GPIO_IO_IN_ENABLED) { + pins->input_disable &= ~bit; + } else { + pins->input_disable |= bit; + } - ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr, - SX1509B_REG_INPUT_DISABLE, - pins->input_disable); - if (ret) - goto out; + if (flags & GPIO_IO_OUT_ENABLED) { + pins->dir &= ~bit; + } else { + pins->dir |= bit; + } - ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr, - SX1509B_REG_PULL_UP, - pins->pull_up); - if (ret) - goto out; + if (flags & GPIO_IO_INIT_ENABLED) { + data_first = true; + if ((flags & GPIO_IO_INIT_MASK) == GPIO_IO_INIT_HIGH) { + pins->data |= bit; + } else { + pins->data &= ~bit; + } + } - ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr, - SX1509B_REG_PULL_DOWN, - pins->pull_down); - if (ret) - goto out; + if (flags & GPIO_POL_INV) { + pins->polarity |= bit; + } else { + pins->polarity &= ~bit; + } - ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr, - SX1509B_REG_OPEN_DRAIN, - pins->open_drain); + if (flags & GPIO_DS_LO_LOW) { + pins->low_drive |= bit; + } else { + pins->low_drive &= ~bit; + } + + outbuf.reg = SX1509B_REG_INPUT_DISABLE; + outbuf.pins.input_disable = sys_cpu_to_be16(pins->input_disable); + outbuf.pins.long_slew = sys_cpu_to_be16(pins->long_slew); + outbuf.pins.low_drive = sys_cpu_to_be16(pins->low_drive); + outbuf.pins.pull_up = sys_cpu_to_be16(pins->pull_up); + outbuf.pins.pull_down = sys_cpu_to_be16(pins->pull_down); + outbuf.pins.open_drain = sys_cpu_to_be16(pins->open_drain); + outbuf.pins.polarity = sys_cpu_to_be16(pins->polarity); + outbuf.pins.dir = sys_cpu_to_be16(pins->dir); + outbuf.pins.data = sys_cpu_to_be16(pins->data); + + if (data_first) { + ret = i2c_reg_write_word_be(drv_data->i2c_master, + cfg->i2c_slave_addr, + SX1509B_REG_DATA, pins->data); + if (ret == 0) { + ret = i2c_write(drv_data->i2c_master, + &outbuf.reg, + sizeof(outbuf) - sizeof(pins->data), + cfg->i2c_slave_addr); + } + } else { + ret = i2c_write(drv_data->i2c_master, + &outbuf.reg, + sizeof(outbuf), + cfg->i2c_slave_addr); + } out: k_sem_give(&drv_data->lock); @@ -323,12 +321,8 @@ static int gpio_sx1509b_init(struct device *dev) /* Reset state */ drv_data->pin_state = (struct gpio_sx1509b_pin_state) { - .input_disable = 0x0000, - .pull_up = 0x0000, - .pull_down = 0x0000, - .open_drain = 0x0000, - .dir = 0xffff, - .data = 0xffff, + .dir = -1, + .data = -1, }; ret = i2c_reg_write_byte(drv_data->i2c_master, cfg->i2c_slave_addr, diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index c365d449e347b..9ac4c4bc1e079 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h @@ -1,180 +1,487 @@ /* * Copyright (c) 2018 Linaro Limited + * Copyright (c) 2018 Peter Bigot Consulting, LLC * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ +/* + * Assigned Bit Positions + * + * @note: This table is intended as a convenience to summarize the bit + * assignments used in the fields defined below. The GPIO_foo_SHIFT + * macros are the canonical definition. + * + * Bit Prefix Variations + * ===== ============== ======================================================= + * 0 GPIO_ACTIVE high or low + * 1 GPIO_SIGNALING single-ended or push-pull + * 2 GPIO_LINE source or drain + * 3-4 GPIO_PUD pull normal/up/down + * 5-8 GPIO_IO in, out, initialize, initial value + * 9-13 GPIO_INT enable, level/edge, low, high, double-edge + * 14 GPIO_POL polarity normal/invert + * 15 GPIO_DEBOUNCE disable/enable + * 16-17 GPIO_DS_LOW drive strength for output low: default/low/high/discon + * 18-19 GPIO_DS_HIGH drive strength for output high: default/low/high/discon + */ /** - * @name GPIO direction flags - * The `GPIO_DIR_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify whether a GPIO pin will be used for input or output. + * @name GPIO active level indicator. + * + * The `GPIO_ACTIVE_*` flags indicate the level at which a + * corresponding gpio is considered active, e.g. whether an LED is lit + * with a low or high output, or a button is pressed with a low or + * high input. + * * @{ */ -/** GPIO pin to be input. */ -#define GPIO_DIR_IN (0 << 0) +/** @cond INTERNAL_HIDDEN */ +#define GPIO_ACTIVE_SHIFT 0 +#define GPIO_ACTIVE_MASK (1 << GPIO_ACTIVE_SHIFT) +/** @endcond */ -/** GPIO pin to be output. */ -#define GPIO_DIR_OUT (1 << 0) +/** GPIO pin indicates active in high state. */ +#define GPIO_ACTIVE_HIGH (0 << GPIO_ACTIVE_SHIFT) +/** GPIO pin indicates active in low state. */ +#define GPIO_ACTIVE_LOW (1 << GPIO_ACTIVE_SHIFT) + +/** + * @name GPIO signaling method and line role. + * + * These flags are components used to distinguish `GPIO_OPEN_DRAIN`, + * `GPIO_OPEN_SOURCE`, and `GPIO_PUSH_PULL`. + * + * @{ + */ /** @cond INTERNAL_HIDDEN */ -#define GPIO_DIR_MASK 0x1 +#define GPIO_OPEN_SHIFT 1 +#define GPIO_SIGNALING_SHIFT GPIO_OPEN_SHIFT +#define GPIO_SIGNALING_MASK (1 << GPIO_SIGNALING_SHIFT) +#define GPIO_LINE_SHIFT (GPIO_OPEN_SHIFT + 1) +#define GPIO_LINE_MASK (1 << GPIO_LINE_SHIFT) +#define GPIO_OPEN_MASK (GPIO_SIGNALING_MASK | GPIO_LINE_MASK) /** @endcond */ + +/** GPIO uses differential signaling. */ +#define GPIO_PUSH_PULL (0 << GPIO_SIGNALING_SHIFT) + +/** GPIO uses single-ended signaling. */ +#define GPIO_SINGLE_ENDED (1 << GPIO_SIGNALING_SHIFT) + +/** GPIO is source for signal. */ +#define GPIO_LINE_SOURCE (0 << GPIO_LINE_SHIFT) + +/** GPIO is drain for signal. */ +#define GPIO_LINE_DRAIN (1 << GPIO_LINE_SHIFT) + +/** GPIO is an open-source/emitter. */ +#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_SOURCE) + +/** GPIO is an open-drain/collector. */ +#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_DRAIN) + /** @} */ +/** + * @name GPIO pull flags + * The `GPIO_PUD_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify the pull-up or pull-down + * electrical configuration of a GPIO pin. + * + * @{ + */ +/** @cond INTERNAL_HIDDEN */ +#define GPIO_PUD_SHIFT 3 +#define GPIO_PUD_MASK (3 << GPIO_PUD_SHIFT) +/** @endcond */ + +/** Pin is neither pull-up nor pull-down. */ +#define GPIO_PUD_NORMAL (0 << GPIO_PUD_SHIFT) + +/** Enable GPIO pin pull-up. */ +#define GPIO_PUD_PULL_UP (1 << GPIO_PUD_SHIFT) + +/** Enable GPIO pin pull-down. */ +#define GPIO_PUD_PULL_DOWN (2 << GPIO_PUD_SHIFT) + +/** @} */ /** - * @name GPIO interrupt flags - * The `GPIO_INT_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify how input GPIO pins will trigger interrupts. + * @name GPIO input/output configuration. + * The `GPIO_IO_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify whether a GPIO pin will be used + * for input and/or output and the initial state for output. + * + * The `GPIO_DIR_*` values derived from these flags may be more + * convenient. + * * @{ */ -/** GPIO pin to trigger interrupt. */ -#define GPIO_INT (1 << 1) +/** @cond INTERNAL_HIDDEN */ +#define GPIO_IO_SHIFT 5 +#define GPIO_IO_MASK (0x0F << GPIO_IO_SHIFT) +/** @endcond */ -/** GPIO pin trigger on level low or falling edge. */ -#define GPIO_INT_ACTIVE_LOW (0 << 2) +/** + * Mask to isolate the `GPIO_IO_IN_ENABLED` and `GPIO_IO_OUT_ENABLED` + * flags. + */ +#define GPIO_DIR_MASK (0x03 << GPIO_IO_SHIFT) -/** GPIO pin trigger on level high or rising edge. */ -#define GPIO_INT_ACTIVE_HIGH (1 << 2) +/** + * Mask to isolate the `GPIO_IO_INIT_LOW` and `GPIO_IO_INIT_HIGH` + * flags. + */ +#define GPIO_IO_INIT_MASK (1 << (GPIO_IO_SHIFT + 3)) -/** Enable GPIO pin debounce. */ -#define GPIO_INT_DEBOUNCE (1 << 4) +/** GPIO pin input is connected (i.e. read should work). */ +#define GPIO_IO_IN_ENABLED (1 << GPIO_IO_SHIFT) -/** Do Level trigger. */ -#define GPIO_INT_LEVEL (0 << 5) +/** GPIO pin output is enabled (i.e. write should work). */ +#define GPIO_IO_OUT_ENABLED (1 << (GPIO_IO_SHIFT + 1)) -/** Do Edge trigger. */ -#define GPIO_INT_EDGE (1 << 5) +/** + * GPIO pin output is to be initialized simultaneous with + * configuration. + */ +#define GPIO_IO_INIT_ENABLED (1 << (GPIO_IO_SHIFT + 2)) -/** Interrupt triggers on both rising and falling edge. - * Must be combined with GPIO_INT_EDGE. +/** + * GPIO pin output is driven low at configuration. + * + * Flag is applied only if `GPIO_IO_INIT_ENABLED` is set. */ -#define GPIO_INT_DOUBLE_EDGE (1 << 6) +#define GPIO_IO_INIT_LOW (0 << (GPIO_IO_SHIFT + 3)) + +/** + * GPIO pin output is driven high at configuration. + * + * Flag is applied only if `GPIO_IO_INIT_ENABLED` is set. + */ +#define GPIO_IO_INIT_HIGH (1 << (GPIO_IO_SHIFT + 3)) + +/** GPIO pin configured as input only. */ +#define GPIO_DIR_IN GPIO_IO_IN_ENABLED + +/** GPIO pin configured as output with no change to output state. */ +#define GPIO_DIR_OUT GPIO_IO_OUT_ENABLED + +/** GPIO pin configured as output low. + * + * Where configuration is not atomic the output value should be set + * before the pin is configured to drive the output. + */ +#define GPIO_DIR_OUT_LOW (GPIO_IO_OUT_ENABLED \ + | GPIO_IO_INIT_ENABLED \ + | GPIO_IO_INIT_LOW) + +/** GPIO pin configured as output high. + * + * Where configuration is not atomic the output value should be set + * before the pin is configured to drive the output. + */ +#define GPIO_DIR_OUT_HIGH (GPIO_IO_OUT_ENABLED \ + | GPIO_IO_INIT_ENABLED \ + | GPIO_IO_INIT_HIGH) /** @} */ /** - * @name GPIO polarity flags - * The `GPIO_POL_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the polarity of a GPIO pin. + * @name GPIO interrupt flags + * + * The `GPIO_INT_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify how input GPIO pins will trigger + * interrupts. + * * @{ */ /** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_POS 7 +#define GPIO_INT_SHIFT 9 +#define GPIO_INT_MASK (0x1F << GPIO_INT_SHIFT) /** @endcond */ -/** GPIO pin polarity is normal. */ -#define GPIO_POL_NORMAL (0 << GPIO_POL_POS) +/** Mask to isolate the `GPIO_INT_LEVEL` and `GPIO_INT_EDGE` flags. */ +#define GPIO_INT_TRIGGER_MASK (0x01 << (GPIO_INT_SHIFT + 1)) -/** GPIO pin polarity is inverted. */ -#define GPIO_POL_INV (1 << GPIO_POL_POS) +/** Mask to isolate the `GPIO_INT_LOW` and `GPIO_INT_HIGH` flags. */ +#define GPIO_INT_DIR_MASK (0x03 << (GPIO_INT_SHIFT + 2)) -/** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_MASK (1 << GPIO_POL_POS) -/** @endcond */ -/** @} */ +/** GPIO pin causes interrupt. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_ENABLE (1 << GPIO_INT_SHIFT) +/** Trigger detection when signal is observed to be at a particular + * level. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. Isolate + * using `GPIO_INT_TRIGGER_MASK`. + */ +#define GPIO_INT_LEVEL (0 << (GPIO_INT_SHIFT + 1)) + +/** Trigger detection when a signal is observed to change level. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. Isolate + * using `GPIO_INT_TRIGGER_MASK`. + */ +#define GPIO_INT_EDGE (1 << (GPIO_INT_SHIFT + 1)) + +/** Trigger detection when input state is (or transitions to) low. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. Isolate + * using `GPIO_INT_DIR_MASK`. + * + * This bit may be combined `GPIO_INT_HIGH` to sense both states + * (generally with `GPIO_INT_EDGE`). + */ +#define GPIO_INT_LOW (1 << (GPIO_INT_SHIFT + 2)) + +/** Trigger detection on input state is (or transitions to) high. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. Isolate + * using `GPIO_INT_DIR_MASK`. + * + * This bit may be combined `GPIO_INT_LOW` to sense both states + * (generally with `GPIO_INT_EDGE`). + */ +#define GPIO_INT_HIGH (1 << (GPIO_INT_SHIFT + 3)) + +/** Interrupt triggers on both rising and falling edge. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + * + * For compatibility with old code this should be combined with + * `GPIO_INT_EDGE`. + * + * For compatibility with new code this should be combined with both + * `GPIO_INT_LOW` and `GPIO_INT_HIGH`. Updated driver code should + * prefer to check the individual flags. + * + * @deprecated Replace tests with a check that flags masked by + * `GPIO_INT_DIR_MASK` is equal to `GPIO_INT_LOW | GPIO_INT_HIGH`. + */ +#define GPIO_INT_DOUBLE_EDGE (1 << (GPIO_INT_SHIFT + 4)) + +/** GPIO pin trigger on rising edge. */ +#define GPIO_INT_EDGE_RISING (GPIO_INT_ENABLE \ + | GPIO_INT_EDGE \ + | GPIO_INT_HIGH) + +/** GPIO pin trigger on rising edge. */ +#define GPIO_INT_EDGE_FALLING (GPIO_INT_ENABLE \ + | GPIO_INT_EDGE \ + | GPIO_INT_LOW) + +/** GPIO pin trigger on rising or falling edge. */ +#define GPIO_INT_EDGE_BOTH (GPIO_INT_ENABLE \ + | GPIO_INT_EDGE \ + | GPIO_INT_LOW \ + | GPIO_INT_HIGH \ + | GPIO_INT_DOUBLE_EDGE) + +/** GPIO pin trigger on level low. */ +#define GPIO_INT_LEVEL_LOW (GPIO_INT_ENABLE \ + | GPIO_INT_LEVEL \ + | GPIO_INT_LOW) + +/** GPIO pin trigger on level high. */ +#define GPIO_INT_LEVEL_HIGH (GPIO_INT_ENABLE \ + | GPIO_INT_LEVEL \ + | GPIO_INT_HIGH) + +/** @} */ /** - * @name GPIO pull flags - * The `GPIO_PUD_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the pull-up or pull-down electrical configuration of a GPIO pin. + * @name GPIO polarity flags + * + * The `GPIO_POL_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify the polarity of a GPIO pin. + * + * Note that not all GPIO drivers may support configuring pin + * polarity, and the effect of such configuration may also be + * driver-specific. + * * @{ */ /** @cond INTERNAL_HIDDEN */ -#define GPIO_PUD_POS 8 +#define GPIO_POL_SHIFT 14 +#define GPIO_POL_MASK (1 << GPIO_POL_SHIFT) /** @endcond */ -/** Pin is neither pull-up nor pull-down. */ -#define GPIO_PUD_NORMAL (0 << GPIO_PUD_POS) +/** GPIO pin polarity is normal. */ +#define GPIO_POL_NORMAL (0 << GPIO_POL_SHIFT) -/** Enable GPIO pin pull-up. */ -#define GPIO_PUD_PULL_UP (1 << GPIO_PUD_POS) +/** GPIO pin polarity is inverted. */ +#define GPIO_POL_INV (1 << GPIO_POL_SHIFT) -/** Enable GPIO pin pull-down. */ -#define GPIO_PUD_PULL_DOWN (2 << GPIO_PUD_POS) +/** @} */ /** @cond INTERNAL_HIDDEN */ -#define GPIO_PUD_MASK (3 << GPIO_PUD_POS) +#define GPIO_DEBOUNCE_SHIFT 15 +#define GPIO_DEBOUNCE_MASK (1 << GPIO_DEBOUNCE_SHIFT) /** @endcond */ -/** @} */ +/** Enable GPIO pin debounce. */ +#define GPIO_DEBOUNCE (1 << GPIO_DEBOUNCE_SHIFT) /** * @name GPIO drive strength flags - * The `GPIO_DS_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the drive strength configuration of a GPIO pin. + * + * The `GPIO_DS_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify the drive strength configuration + * of a GPIO pin. * * The drive strength of individual pins can be configured * independently for when the pin output is low and high. * - * The `GPIO_DS_*_LOW` enumerations define the drive strength of a pin + * The `GPIO_DS_*_LOW` bits define the drive strength of a pin * when output is low. - - * The `GPIO_DS_*_HIGH` enumerations define the drive strength of a pin + * + * The `GPIO_DS_*_HIGH` bits define the drive strength of a pin * when output is high. * - * The `DISCONNECT` drive strength indicates that the pin is placed in a - * high impedance state and not driven, this option is used to - * configure hardware that supports a open collector drive mode. + * If the device does not distinguish drive strength by signal level, + * the drive strength configuration from `GPIO_DS_*_LOW` shall be + * used. + * + * The interface supports several drive strengths: + * `LO` - The lowest drive strength supported by the HW + * `HI` - The highest drive strength supported by the HW + * `DISCONNECT` - The pin is placed in a high impedance state and not + * driven (open drain mode) * - * The interface supports two different drive strengths: - * `DFLT` - The lowest drive strength supported by the HW - * `ALT` - The highest drive strength supported by the HW + * In addition `DFLT` represents the default drive strength for a + * particular driver, and may be either `LO` or `HI`. * - * On hardware that supports only one standard drive strength, both - * `DFLT` and `ALT` have the same behavior. + * On hardware that supports only one standard drive strength `LO` and + * `HI` have the same behavior. * * On hardware that does not support a disconnect mode, `DISCONNECT` * will behave the same as `DFLT`. + * * @{ */ /** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_LOW_POS 12 -#define GPIO_DS_LOW_MASK (0x3 << GPIO_DS_LOW_POS) +#define GPIO_DS_LOW_SHIFT 16 +#define GPIO_DS_LOW_MASK (3 << GPIO_DS_LOW_SHIFT) /** @endcond */ -/** Default drive strength standard when GPIO pin output is low. - */ -#define GPIO_DS_DFLT_LOW (0x0 << GPIO_DS_LOW_POS) +/** Use default drive strength when GPIO pin output is low. */ +#define GPIO_DS_DFLT_LOW (0 << GPIO_DS_LOW_SHIFT) -/** Alternative drive strength when GPIO pin output is low. - * For hardware that does not support configurable drive strength - * use the default drive strength. - */ -#define GPIO_DS_ALT_LOW (0x1 << GPIO_DS_LOW_POS) +/** Use low/reduced drive strength when GPIO pin output is low. */ +#define GPIO_DS_LO_LOW (1 << GPIO_DS_LOW_SHIFT) + +/** Use high/increased drive strength when GPIO pin output is low. */ +#define GPIO_DS_HI_LOW (2 << GPIO_DS_LOW_SHIFT) /** Disconnect pin when GPIO pin output is low. * For hardware that does not support disconnect use the default * drive strength. */ -#define GPIO_DS_DISCONNECT_LOW (0x3 << GPIO_DS_LOW_POS) +#define GPIO_DS_DISCONNECT_LOW (3 << GPIO_DS_LOW_SHIFT) /** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_HIGH_POS 14 -#define GPIO_DS_HIGH_MASK (0x3 << GPIO_DS_HIGH_POS) +#define GPIO_DS_HIGH_SHIFT 18 +#define GPIO_DS_HIGH_MASK (3 << GPIO_DS_HIGH_SHIFT) /** @endcond */ -/** Default drive strength when GPIO pin output is high. - */ -#define GPIO_DS_DFLT_HIGH (0x0 << GPIO_DS_HIGH_POS) +/** Use default drive strength when GPIO pin output is low. */ +#define GPIO_DS_DFLT_HIGH (0 << GPIO_DS_HIGH_SHIFT) -/** Alternative drive strength when GPIO pin output is high. - * For hardware that does not support configurable drive strengths - * use the default drive strength. - */ -#define GPIO_DS_ALT_HIGH (0x1 << GPIO_DS_HIGH_POS) +/** Use low/reduced drive strength when GPIO pin output is low. */ +#define GPIO_DS_LO_HIGH (1 << GPIO_DS_HIGH_SHIFT) -/** Disconnect pin when GPIO pin output is high. +/** Use high/increased drive strength when GPIO pin output is low. */ +#define GPIO_DS_HI_HIGH (2 << GPIO_DS_HIGH_SHIFT) + +/** Disconnect pin when GPIO pin output is low. * For hardware that does not support disconnect use the default * drive strength. */ -#define GPIO_DS_DISCONNECT_HIGH (0x3 << GPIO_DS_HIGH_POS) +#define GPIO_DS_DISCONNECT_HIGH (3 << GPIO_DS_HIGH_SHIFT) + /** @} */ +/** @name Deprecated Flags + * + * These flags were defined at a time when the characteristic they + * identified was assumed to be relevant only for interrupts. The + * features are also useful for non-interrupt inputs and in some cases + * for outputs. + * + * @{ + */ + +/** Legacy flag setting indicating signal or interrupt active level. + * + * This flag was used both to indicate a signal's active level, and to + * indicate the level associated with an interrupt on a signal. As + * active level is also relevant to output signals the two + * intepretations have been separated. The legacy value supports + * testing for interrupt level as this is the most common use in + * existing code. + * + * @deprecated Replace with `GPIO_ACTIVE_LOW` or `GPIO_INT_LOW` + * depending on intent. + */ +#define GPIO_INT_ACTIVE_LOW GPIO_INT_LOW +/** Legacy flag setting indicating signal or interrupt active level. + * + * This flag was used both to indicate a signal's active level, and to + * indicate the level associated with an interrupt on a signal. As + * active level is also relevant to output signals the two + * intepretations have been separated. The legacy value supports + * testing for interrupt level as this is the most common use in + * existing code. + * + * @deprecated Replace with `GPIO_ACTIVE_HIGH` or `GPIO_INT_HIGH` + * depending on intent. + */ +#define GPIO_INT_ACTIVE_HIGH GPIO_INT_HIGH + +/** Legacy flag indicating a desire to debounce the signal. + * + * Although debouncing is useful for interrupts it is not specific to + * interrupts. + * + * @deprecated Replace with `GPIO_DEBOUNCE` + */ +#define GPIO_INT_DEBOUNCE GPIO_DEBOUNCE + +/** Legacy alias indicating that interrupts should be enabled on the + * GPIO. + * + * @deprecated Replace with `GPIO_INT_ENABLE` + */ +#define GPIO_INT GPIO_INT_ENABLE + +/** Legacy alias identifying high drive strength when GPIO output is + * low. + * + * @deprecated Replace with `GPIO_DS_HI_LOW` + */ +#define GPIO_DS_ALT_LOW GPIO_DS_HI_LOW + +/** Legacy alias identifying high drive strength when GPIO output is + * high. + * + * @deprecated Replace with `GPIO_DS_HI_HIGH` + */ +#define GPIO_DS_ALT_HIGH GPIO_DS_HI_HIGH + +/** @} */ #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ */ diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c b/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c index 70908bae230cf..d775ebd9cdd9b 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c @@ -93,7 +93,7 @@ static int test_callback(int mode) goto pass_exit; } - if ((mode & GPIO_INT_LEVEL) == GPIO_INT_LEVEL) { + if ((mode & GPIO_INT_TRIGGER_MASK) == GPIO_INT_LEVEL) { if (cb_cnt != MAX_INT_CNT) { TC_ERROR("not trigger callback correctly\n"); goto err_exit;