From af972c2c4781869435bbd27d6b83d5a58b7397b1 Mon Sep 17 00:00:00 2001 From: Piotr Mienkowski Date: Tue, 22 Jan 2019 10:13:02 +0100 Subject: [PATCH] api: gpio: Align GPIO dt-bindings flags with Linux DTS This commit makes following changes to GPIO dt-bindings flags: - Added GPIO_ACTIVE_LOW, GPIO_ACTIVE_HIGH to indicate pin active state. - Added GPIO_OPEN_DRAIN, GPIO_OPEN_SOURCE to configure single ended pin driving mode. - Added GPIO_PULL_UP, GPIO_PULL_DOWN flags. - GPIO_INPUT, GPIO_OUTPUT to configure pin as input or output. - Added GPIO_OUTPUT_LOW, GPIO_OUTPUT_HIGH flags to initialize output in low or high state. - reworked GPIO_INT_* flags to configure pin interrupts. - following flags were deprecated: GPIO_DIR_*, GPIO_DS_DISCONNECT_*, GPIO_PUD_*, GPIO_INT_ACTIVE_*, GPIO_INT_DOUBLE_EDGE, GPIO_POL_*. To be aligned with Linux DTS standard any GPIO flags that should not be used in DTS files are moved from include/dt-bindings/gpio/gpio.h file to include/drivers/gpio.h with an exception of several old flags which removal would cause DTS compilation errors. Those remaining old flags will be removed from include/dt-bindings/gpio/gpio.h at a later stage. Signed-off-by: Piotr Mienkowski --- include/drivers/gpio.h | 349 +++++++++++++++++++++++++++++++- include/dt-bindings/gpio/gpio.h | 189 +++++------------ 2 files changed, 398 insertions(+), 140 deletions(-) diff --git a/include/drivers/gpio.h b/include/drivers/gpio.h index 4d87956969b..0cf0072c60c 100644 --- a/include/drivers/gpio.h +++ b/include/drivers/gpio.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2019 Piotr Mienkowski * Copyright (c) 2017 ARM Ltd * Copyright (c) 2015-2016 Intel Corporation. * @@ -32,6 +33,334 @@ extern "C" { * @{ */ +/** + * @name GPIO input/output configuration flags + * @{ + */ + +/** Enables pin as input. */ +#define GPIO_INPUT (1U << 8) + +/** Enables pin as output, no change to the output state. */ +#define GPIO_OUTPUT (1U << 9) + +/** @cond INTERNAL_HIDDEN */ + +/* Initializes output to a low state. */ +#define GPIO_OUTPUT_INIT_LOW (1U << 10) + +/* Initializes output to a high state. */ +#define GPIO_OUTPUT_INIT_HIGH (1U << 11) + +/** @endcond */ + +/** Configures GPIO pin as output and initializes it to a low state. */ +#define GPIO_OUTPUT_LOW (GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW) +/** Configures GPIO pin as output and initializes it to a high state. */ +#define GPIO_OUTPUT_HIGH (GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH) + +/** @} */ + +/** + * @name GPIO interrupt configuration flags + * The `GPIO_INT_*` flags are used to specify how input GPIO pins will trigger + * interrupts. The interrupts can be sensitive to pin physical or logical level. + * Interrupts sensitive to pin logical level take into account GPIO_ACTIVE_LOW + * flag. If a pin was configured as Active Low, physical level low will be + * considered as logical level 1 (an active state), physical level high will + * be considered as logical level 0 (an inactive state). + * @{ + */ + +/** Disables GPIO pin interrupt. */ +#define GPIO_INT_DISABLE (0U << 12) + +/** @cond INTERNAL_HIDDEN */ + +/* Enables GPIO pin interrupt. */ +#define GPIO_INT_ENABLE (1U << 12) + +/* GPIO interrupt is sensitive to logical levels. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_LEVELS_LOGICAL (1U << 13) + +/* GPIO interrupt is edge sensitive. + * + * Note: by default interrupts are level sensitive. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_EDGE (1U << 14) + +/* Trigger detection when input state is (or transitions to) physical low or + * logical 0 level. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_LOW_0 (1U << 15) + +/* Trigger detection on input state is (or transitions to) physical high or + * logical 1 level. + * + * This is a component flag that should be combined with other + * `GPIO_INT_*` flags to produce a meaningful configuration. + */ +#define GPIO_INT_HIGH_1 (1U << 16) + +/** @endcond */ + +/** Configures GPIO interrupt to be triggered on pin rising edge and enables it. + */ +#define GPIO_INT_EDGE_RISING (GPIO_INT_ENABLE | \ + GPIO_INT_EDGE | \ + GPIO_INT_HIGH_1) + +/** Configures GPIO interrupt to be triggered on pin falling edge and enables + * it. + */ +#define GPIO_INT_EDGE_FALLING (GPIO_INT_ENABLE | \ + GPIO_INT_EDGE | \ + GPIO_INT_LOW_0) + +/** Configures GPIO interrupt to be triggered on pin rising or falling edge and + * enables it. + */ +#define GPIO_INT_EDGE_BOTH (GPIO_INT_ENABLE | \ + GPIO_INT_EDGE | \ + GPIO_INT_LOW_0 | \ + GPIO_INT_HIGH_1) + +/** Configures GPIO interrupt to be triggered on pin physical level low and + * enables it. + */ +#define GPIO_INT_LEVEL_LOW (GPIO_INT_ENABLE | \ + GPIO_INT_LOW_0) + +/** Configures GPIO interrupt to be triggered on pin physical level high and + * enables it. + */ +#define GPIO_INT_LEVEL_HIGH (GPIO_INT_ENABLE | \ + GPIO_INT_HIGH_1) + +/** Configures GPIO interrupt to be triggered on pin state change to logical + * level 0 and enables it. + */ +#define GPIO_INT_EDGE_TO_INACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_EDGE | \ + GPIO_INT_LOW_0) + +/** Configures GPIO interrupt to be triggered on pin state change to logical + * level 1 and enables it. + */ +#define GPIO_INT_EDGE_TO_ACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_EDGE | \ + GPIO_INT_HIGH_1) + +/** Configures GPIO interrupt to be triggered on pin logical level 0 and enables + * it. + */ +#define GPIO_INT_LEVEL_INACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_LOW_0) + +/** Configures GPIO interrupt to be triggered on pin logical level 1 and enables + * it. + */ +#define GPIO_INT_LEVEL_ACTIVE (GPIO_INT_ENABLE | \ + GPIO_INT_LEVELS_LOGICAL | \ + GPIO_INT_HIGH_1) + +/** @} */ + +/** Enable GPIO pin debounce. */ +#define GPIO_INT_DEBOUNCE (1U << 17) + +/** + * @name GPIO drive strength flags + * The `GPIO_DS_*` flags are used with `gpio_pin_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 + * when output is low. + + * The `GPIO_DS_*_HIGH` enumerations define the drive strength of a pin + * when output is high. + * + * 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 + * + * On hardware that supports only one standard drive strength, both + * `DFLT` and `ALT` have the same behavior. + * @{ + */ +/** @cond INTERNAL_HIDDEN */ +#define GPIO_DS_LOW_POS 18 +#define GPIO_DS_LOW_MASK (0x3U << GPIO_DS_LOW_POS) +/** @endcond */ + +/** Default drive strength standard when GPIO pin output is low. + */ +#define GPIO_DS_DFLT_LOW (0x0U << GPIO_DS_LOW_POS) + +/** 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 (0x1U << GPIO_DS_LOW_POS) + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_DS_HIGH_POS 20 +#define GPIO_DS_HIGH_MASK (0x3U << GPIO_DS_HIGH_POS) +/** @endcond */ + +/** Default drive strength when GPIO pin output is high. + */ +#define GPIO_DS_DFLT_HIGH (0x0U << GPIO_DS_HIGH_POS) + +/** 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 (0x1U << GPIO_DS_HIGH_POS) +/** @} */ + +/** @name Deprecated Flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_DIR_SHIFT 8 +#define GPIO_DIR_MASK (0x3U << GPIO_DIR_SHIFT) +/** @endcond */ + +/** Legacy flag indicating pin is configured as input only. + * + * @deprecated Replace with `GPIO_INPUT`. + */ +#define GPIO_DIR_IN GPIO_INPUT + +/** Legacy flag indicating pin is configured as output. + * + * @deprecated Replace with `GPIO_OUTPUT`. + */ +#undef GPIO_DIR_OUT +#define GPIO_DIR_OUT GPIO_OUTPUT + +/** Legacy flag indicating pin is disconnected when GPIO pin output is low. + * + * @deprecated Replace with `GPIO_OPEN_SOURCE`. + */ +#define GPIO_DS_DISCONNECT_LOW GPIO_OPEN_SOURCE + +/** Legacy flag indicating pin is disconnected when GPIO pin output is high. + * + * @deprecated Replace with `GPIO_OPEN_DRAIN`. + */ +#define GPIO_DS_DISCONNECT_HIGH GPIO_OPEN_DRAIN + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_PUD_SHIFT 4 +#define GPIO_PUD_MASK (0x3U << GPIO_PUD_SHIFT) +/** @endcond */ + +/** Pin is neither pull-up nor pull-down. + * + * @deprecated Not used any more + */ +#define GPIO_PUD_NORMAL 0U + +/** Enable GPIO pin pull-up. + * + * @deprecated Replace with `GPIO_PULL_UP`. + */ +#undef GPIO_PUD_PULL_UP +#define GPIO_PUD_PULL_UP GPIO_PULL_UP + +/** Enable GPIO pin pull-down. + * + * @deprecated Replace with `GPIO_PULL_DOWN`. + */ +#undef GPIO_PUD_PULL_DOWN +#define GPIO_PUD_PULL_DOWN GPIO_PULL_DOWN + +/** Legacy flag indicating that interrupt is enabled. + * + * @deprecated Replace with `GPIO_INT_ENABLE`. + */ +#define GPIO_INT GPIO_INT_ENABLE + +/** Legacy flag indicating that interrupt is level sensitive. + * + * @deprecated Replace with `GPIO_INT_LEVEL_LOW`, `GPIO_INT_LEVEL_HIGH`. + */ +#define GPIO_INT_LEVEL (0U << 14) + +/** 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 + * interpretations 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_0` + * depending on intent. + */ +#undef GPIO_INT_ACTIVE_LOW +#define GPIO_INT_ACTIVE_LOW GPIO_INT_LOW_0 + +/** 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 + * interpretations 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_1` + * depending on intent. + */ +#undef GPIO_INT_ACTIVE_HIGH +#define GPIO_INT_ACTIVE_HIGH GPIO_INT_HIGH_1 + +/** Legacy flag indicating interrupt triggers on both rising and falling edge. + * + * @deprecated Replace with `GPIO_INT_EDGE_BOTH`. + */ +#define GPIO_INT_DOUBLE_EDGE GPIO_INT_EDGE_BOTH + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_POL_SHIFT 0 +#define GPIO_POL_MASK (1U << GPIO_POL_SHIFT) +/** @endcond */ + +/** Legacy flag indicating that GPIO pin polarity is normal. + * + * @deprecated Replace with `GPIO_ACTIVE_HIGH`. + */ +#define GPIO_POL_NORMAL GPIO_ACTIVE_HIGH + +/** Legacy flag indicating that GPIO pin polarity is inverted. + * + * @deprecated Replace with `GPIO_ACTIVE_LOW`. + */ +#define GPIO_POL_INV GPIO_ACTIVE_LOW + +/** @} */ + /** @cond INTERNAL_HIDDEN */ #define GPIO_ACCESS_BY_PIN 0 #define GPIO_ACCESS_BY_PORT 1 @@ -177,14 +506,28 @@ static inline int z_impl_gpio_disable_callback(struct device *port, /** * @brief Configure a single pin. + * * @param port Pointer to device structure for the driver instance. * @param pin Pin number to configure. - * @param flags Flags for pin configuration. IN/OUT, interrupt ... - * @return 0 if successful, negative errno code on failure. + * @param flags Flags for pin configuration: 'GPIO input/output configuration + * flags', 'GPIO drive strength flags', 'GPIO pin drive flags', 'GPIO pin + * bias flags', GPIO_INT_DEBOUNCE. + * + * @retval 0 If successful. + * @retval -ENOTSUP if any of the configuration options is not supported. + * @retval -EINVAL Invalid argument. */ static inline int gpio_pin_configure(struct device *port, u32_t pin, - int flags) + unsigned int flags) { + __ASSERT((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != + (GPIO_PULL_UP | GPIO_PULL_DOWN), + "Pull Up and Pull Down should not be enabled simultaneously"); + + __ASSERT((flags & (GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH)) == 0 + || (flags & GPIO_OUTPUT) != 0, + "Output needs to be enabled to be initialized low or high"); + return gpio_config(port, GPIO_ACCESS_BY_PIN, pin, flags); } diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index c365d449e34..adc0d8d2d5f 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2019 Piotr Mienkowski * Copyright (c) 2018 Linaro Limited * * SPDX-License-Identifier: Apache-2.0 @@ -6,175 +7,89 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ - /** - * @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. + * @brief GPIO Driver APIs + * @defgroup gpio_interface GPIO Driver APIs + * @ingroup io_interfaces * @{ */ -/** GPIO pin to be input. */ -#define GPIO_DIR_IN (0 << 0) -/** GPIO pin to be output. */ -#define GPIO_DIR_OUT (1 << 0) +/** + * @name GPIO pin active level flags + * @{ + */ + +/** GPIO pin is active (has logical value '1') in low state. */ +#define GPIO_ACTIVE_LOW (1 << 0) +/** GPIO pin is active (has logical value '1') in high state. */ +#define GPIO_ACTIVE_HIGH (0 << 0) -/** @cond INTERNAL_HIDDEN */ -#define GPIO_DIR_MASK 0x1 -/** @endcond */ /** @} */ - /** - * @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 pin drive flags * @{ */ -/** GPIO pin to trigger interrupt. */ -#define GPIO_INT (1 << 1) -/** GPIO pin trigger on level low or falling edge. */ -#define GPIO_INT_ACTIVE_LOW (0 << 2) +/** @cond INTERNAL_HIDDEN */ -/** GPIO pin trigger on level high or rising edge. */ -#define GPIO_INT_ACTIVE_HIGH (1 << 2) +/* Configures GPIO output in single-ended mode (open drain or open source). */ +#define GPIO_SINGLE_ENDED (1 << 1) +/* Configures GPIO output in push-pull mode */ +#define GPIO_PUSH_PULL (0 << 1) -/** Enable GPIO pin debounce. */ -#define GPIO_INT_DEBOUNCE (1 << 4) +/* Indicates single ended open drain mode (wired AND). */ +#define GPIO_LINE_OPEN_DRAIN (1 << 2) +/* Indicates single ended open source mode (wired OR). */ +#define GPIO_LINE_OPEN_SOURCE (0 << 2) -/** Do Level trigger. */ -#define GPIO_INT_LEVEL (0 << 5) +/** @endcond */ -/** Do Edge trigger. */ -#define GPIO_INT_EDGE (1 << 5) - -/** Interrupt triggers on both rising and falling edge. - * Must be combined with GPIO_INT_EDGE. +/** Configures GPIO output in open drain mode (wired AND). + * + * @note 'Open Drain' mode also known as 'Open Collector' is an output + * configuration which behaves like a switch that is either connected to ground + * or disconnected. */ -#define GPIO_INT_DOUBLE_EDGE (1 << 6) +#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN) +/** Configures GPIO output in open source mode (wired OR). + * + * @note 'Open Source' is a term used by software engineers to describe output + * mode opposite to 'Open Drain'. It behaves like a switch that is either + * connected to power supply or disconnected. There exist no corresponding + * hardware schematic and the term is generally unknown to hardware engineers. + */ +#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE) + /** @} */ - /** - * @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 pin bias flags * @{ */ -/** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_POS 7 -/** @endcond */ -/** GPIO pin polarity is normal. */ -#define GPIO_POL_NORMAL (0 << GPIO_POL_POS) - -/** GPIO pin polarity is inverted. */ -#define GPIO_POL_INV (1 << GPIO_POL_POS) - -/** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_MASK (1 << GPIO_POL_POS) -/** @endcond */ -/** @} */ - - -/** - * @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_POS 8 -/** @endcond */ - -/** Pin is neither pull-up nor pull-down. */ -#define GPIO_PUD_NORMAL (0 << GPIO_PUD_POS) - -/** Enable GPIO pin pull-up. */ -#define GPIO_PUD_PULL_UP (1 << GPIO_PUD_POS) +/** Enables GPIO pin pull-up. */ +#define GPIO_PULL_UP (1 << 4) /** Enable GPIO pin pull-down. */ -#define GPIO_PUD_PULL_DOWN (2 << GPIO_PUD_POS) +#define GPIO_PULL_DOWN (1 << 5) -/** @cond INTERNAL_HIDDEN */ -#define GPIO_PUD_MASK (3 << GPIO_PUD_POS) -/** @endcond */ /** @} */ - /** - * @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. + * @cond INTERNAL_HIDDEN * - * 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 - * when output is low. - - * The `GPIO_DS_*_HIGH` enumerations 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. - * - * 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 - * - * On hardware that supports only one standard drive strength, both - * `DFLT` and `ALT` have the same behavior. - * - * On hardware that does not support a disconnect mode, `DISCONNECT` - * will behave the same as `DFLT`. - * @{ + * Following defines are deprecated and shouldn't be used in DTS files. */ -/** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_LOW_POS 12 -#define GPIO_DS_LOW_MASK (0x3 << GPIO_DS_LOW_POS) +#define GPIO_DIR_OUT (1 << 9) /* GPIO_OUTPUT */ +#define GPIO_PUD_PULL_UP GPIO_PULL_UP +#define GPIO_PUD_PULL_DOWN GPIO_PULL_DOWN +#define GPIO_INT_ACTIVE_LOW (1 << 15) /* GPIO_INT_LOW_0 */ +#define GPIO_INT_ACTIVE_HIGH (1 << 16) /* GPIO_INT_HIGH_1 */ /** @endcond */ -/** Default drive strength standard when GPIO pin output is low. +/** + * @} */ -#define GPIO_DS_DFLT_LOW (0x0 << GPIO_DS_LOW_POS) - -/** 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) - -/** 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) - -/** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_HIGH_POS 14 -#define GPIO_DS_HIGH_MASK (0x3 << GPIO_DS_HIGH_POS) -/** @endcond */ - -/** Default drive strength when GPIO pin output is high. - */ -#define GPIO_DS_DFLT_HIGH (0x0 << GPIO_DS_HIGH_POS) - -/** 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) - -/** Disconnect pin when GPIO pin output is high. - * For hardware that does not support disconnect use the default - * drive strength. - */ -#define GPIO_DS_DISCONNECT_HIGH (0x3 << GPIO_DS_HIGH_POS) -/** @} */ - - #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_GPIO_H_ */