gpio: Handle logical conversion in gpio api layer
Move handling of logical flag support into gpio_pin_configure and gpio_pin_interrupt_configure. This way drivers don't need to know anything about logical levels. Signed-off-by: Kumar Gala <kumar.gala@linaro.org> Signed-off-by: Piotr Mienkowski <piotr.mienkowski@gmail.com>
This commit is contained in:
parent
84b27a1525
commit
b535881f0c
1 changed files with 63 additions and 3 deletions
|
@ -394,6 +394,10 @@ typedef u32_t gpio_port_value_t;
|
|||
*/
|
||||
#define GPIO_MAX_PINS_PER_PORT (sizeof(gpio_port_pins_t) * __CHAR_BIT__)
|
||||
|
||||
/**
|
||||
* This structure is common to all GPIO drivers and is expected to be the first
|
||||
* element in the driver's struct driver_data decleration.
|
||||
*/
|
||||
struct gpio_driver_data {
|
||||
gpio_port_pins_t invert;
|
||||
};
|
||||
|
@ -450,6 +454,28 @@ struct gpio_callback {
|
|||
*
|
||||
* For internal use only, skip these in public documentation.
|
||||
*/
|
||||
|
||||
/* Used by driver api function pin_interrupt_configure, these are defined
|
||||
* in terms of the public int flags so we can just mask and pass them
|
||||
* through to the driver api
|
||||
*/
|
||||
enum gpio_int_mode {
|
||||
GPIO_INT_MODE_DISABLED = GPIO_INT_DISABLE,
|
||||
GPIO_INT_MODE_LEVEL = GPIO_INT_ENABLE,
|
||||
GPIO_INT_MODE_EDGE = GPIO_INT_ENABLE | GPIO_INT_EDGE,
|
||||
};
|
||||
|
||||
enum gpio_int_trig {
|
||||
/* Trigger detection when input state is (or transitions to)
|
||||
* physical low. (Edge Failing or Active Low) */
|
||||
GPIO_INT_TRIG_LOW = GPIO_INT_LOW_0,
|
||||
/* Trigger detection when input state is (or transitions to)
|
||||
* physical high. (Edge Rising or Active High) */
|
||||
GPIO_INT_TRIG_HIGH = GPIO_INT_HIGH_1,
|
||||
/* Trigger detection on pin rising or falling edge. */
|
||||
GPIO_INT_TRIG_BOTH = GPIO_INT_LOW_0 | GPIO_INT_HIGH_1,
|
||||
};
|
||||
|
||||
struct gpio_driver_api {
|
||||
int (*config)(struct device *port, int access_op, u32_t pin, int flags);
|
||||
int (*write)(struct device *port, int access_op, u32_t pin,
|
||||
|
@ -463,7 +489,7 @@ struct gpio_driver_api {
|
|||
int (*port_clear_bits_raw)(struct device *port, gpio_port_pins_t pins);
|
||||
int (*port_toggle_bits)(struct device *port, gpio_port_pins_t pins);
|
||||
int (*pin_interrupt_configure)(struct device *port, unsigned int pin,
|
||||
unsigned int flags);
|
||||
enum gpio_int_mode, enum gpio_int_trig);
|
||||
int (*manage_callback)(struct device *port, struct gpio_callback *cb,
|
||||
bool set);
|
||||
int (*enable_callback)(struct device *port, int access_op, u32_t pin);
|
||||
|
@ -567,6 +593,10 @@ static inline int z_impl_gpio_pin_interrupt_configure(struct device *port,
|
|||
{
|
||||
const struct gpio_driver_api *api =
|
||||
(const struct gpio_driver_api *)port->driver_api;
|
||||
struct gpio_driver_data *const data =
|
||||
(struct gpio_driver_data *const)port->driver_data;
|
||||
enum gpio_int_trig trig;
|
||||
enum gpio_int_mode mode;
|
||||
|
||||
__ASSERT(pin < GPIO_MAX_PINS_PER_PORT, "Invalid pin number");
|
||||
|
||||
|
@ -574,7 +604,17 @@ static inline int z_impl_gpio_pin_interrupt_configure(struct device *port,
|
|||
((flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1)) != 0),
|
||||
"At least one of GPIO_INT_LOW_0, GPIO_INT_HIGH_1 has to be "
|
||||
"enabled.");
|
||||
return api->pin_interrupt_configure(port, pin, flags);
|
||||
|
||||
if (((flags & GPIO_INT_LEVELS_LOGICAL) != 0) &&
|
||||
((data->invert & BIT(pin)) != 0)) {
|
||||
/* Invert signal bits */
|
||||
flags ^= (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1);
|
||||
}
|
||||
|
||||
trig = (enum gpio_int_trig)(flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1));
|
||||
mode = (enum gpio_int_mode)(flags & (GPIO_INT_EDGE | GPIO_INT_ENABLE));
|
||||
|
||||
return api->pin_interrupt_configure(port, pin, mode, trig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -593,6 +633,12 @@ static inline int z_impl_gpio_pin_interrupt_configure(struct device *port,
|
|||
static inline int gpio_pin_configure(struct device *port, u32_t pin,
|
||||
unsigned int flags)
|
||||
{
|
||||
const struct gpio_driver_api *api =
|
||||
(const struct gpio_driver_api *)port->driver_api;
|
||||
struct gpio_driver_data *data =
|
||||
(struct gpio_driver_data *)port->driver_data;
|
||||
int ret;
|
||||
|
||||
__ASSERT((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) !=
|
||||
(GPIO_PULL_UP | GPIO_PULL_DOWN),
|
||||
"Pull Up and Pull Down should not be enabled simultaneously");
|
||||
|
@ -601,7 +647,21 @@ static inline int gpio_pin_configure(struct device *port, u32_t pin,
|
|||
|| (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);
|
||||
ret = gpio_config(port, GPIO_ACCESS_BY_PIN, pin, flags);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((flags & GPIO_ACTIVE_LOW) != 0) {
|
||||
data->invert |= BIT(pin);
|
||||
} else {
|
||||
data->invert &= ~BIT(pin);
|
||||
}
|
||||
if (api->pin_interrupt_configure) {
|
||||
ret = z_impl_gpio_pin_interrupt_configure(port, pin, flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue