From 5f0996638051c1b710f456021a1fe6738b69d3ac Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Tue, 17 Sep 2019 17:55:33 -0500 Subject: [PATCH] gpio: Update mcux igpio driver to use new gpio api Updates the mcux igpio driver and all associated boards to use new device tree compatible gpio configuration flags. Implements new port get/set/clear/toggle and pin_interrupt_configure functions recently added to the gpio api. Assumes the gpio api layer handles translating logical flags to physical flags. Removes port configuration support since that feature is deprecated in the new gpio api. Tested with: - samples/basic/blinky - samples/basic/button - tests/drivers/gpio/gpio_api_1pin On boards: - mimxrt1015_evk - mimxrt1020_evk - mimxrt1050_evk - mimxrt1060_evk - mimxrt1064_evk Signed-off-by: Maureen Helm --- boards/arm/mimxrt1015_evk/mimxrt1015_evk.dts | 4 +- boards/arm/mimxrt1020_evk/mimxrt1020_evk.dts | 4 +- boards/arm/mimxrt1050_evk/mimxrt1050_evk.dts | 4 +- boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts | 4 +- boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts | 4 +- drivers/gpio/gpio_mcux_igpio.c | 174 ++++++++++++++----- 6 files changed, 139 insertions(+), 55 deletions(-) diff --git a/boards/arm/mimxrt1015_evk/mimxrt1015_evk.dts b/boards/arm/mimxrt1015_evk/mimxrt1015_evk.dts index ee4731e1e59..e6db04c84d9 100644 --- a/boards/arm/mimxrt1015_evk/mimxrt1015_evk.dts +++ b/boards/arm/mimxrt1015_evk/mimxrt1015_evk.dts @@ -25,7 +25,7 @@ leds { compatible = "gpio-leds"; green_led: led-1 { - gpios = <&gpio3 21 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio3 21 GPIO_ACTIVE_LOW>; label = "User LD1"; }; }; @@ -34,7 +34,7 @@ compatible = "gpio-keys"; user_button: button-1 { label = "User SW4"; - gpios = <&gpio2 9 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio2 9 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/arm/mimxrt1020_evk/mimxrt1020_evk.dts b/boards/arm/mimxrt1020_evk/mimxrt1020_evk.dts index 946db6db0dd..72c12d36ab0 100644 --- a/boards/arm/mimxrt1020_evk/mimxrt1020_evk.dts +++ b/boards/arm/mimxrt1020_evk/mimxrt1020_evk.dts @@ -32,7 +32,7 @@ leds { compatible = "gpio-leds"; green_led: led-1 { - gpios = <&gpio1 5 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; label = "User LD1"; }; }; @@ -41,7 +41,7 @@ compatible = "gpio-keys"; user_button: button-1 { label = "User SW8"; - gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/arm/mimxrt1050_evk/mimxrt1050_evk.dts b/boards/arm/mimxrt1050_evk/mimxrt1050_evk.dts index 80be9d6096a..07e0b797a4f 100644 --- a/boards/arm/mimxrt1050_evk/mimxrt1050_evk.dts +++ b/boards/arm/mimxrt1050_evk/mimxrt1050_evk.dts @@ -32,7 +32,7 @@ leds { compatible = "gpio-leds"; green_led: led_0 { - gpios = <&gpio1 9 0>; + gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; label = "User LD1"; }; }; @@ -41,7 +41,7 @@ compatible = "gpio-keys"; user_button: button_0 { label = "User SW8"; - gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts index 84e248994ca..888e8cefcb8 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts @@ -32,7 +32,7 @@ leds { compatible = "gpio-leds"; green_led: led-1 { - gpios = <&gpio1 9 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; label = "User LD1"; }; }; @@ -41,7 +41,7 @@ compatible = "gpio-keys"; user_button: button-1 { label = "User SW8"; - gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; }; }; diff --git a/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts b/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts index cc31f82053a..b739fdd47d9 100644 --- a/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts +++ b/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts @@ -33,7 +33,7 @@ leds { compatible = "gpio-leds"; green_led: led-1 { - gpios = <&gpio1 9 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; label = "User LD1"; }; }; @@ -50,7 +50,7 @@ compatible = "gpio-keys"; user_button: button-1 { label = "User SW8"; - gpios = <&gpio5 0 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; }; }; diff --git a/drivers/gpio/gpio_mcux_igpio.c b/drivers/gpio/gpio_mcux_igpio.c index 2d5d3c74fce..37ebda34d4b 100644 --- a/drivers/gpio/gpio_mcux_igpio.c +++ b/drivers/gpio/gpio_mcux_igpio.c @@ -18,6 +18,8 @@ struct mcux_igpio_config { }; struct mcux_igpio_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data general; /* port ISR callback routine address */ sys_slist_t callbacks; /* pin callback routine enable flags, by pin number */ @@ -28,49 +30,34 @@ static int mcux_igpio_configure(struct device *dev, int access_op, u32_t pin, int flags) { const struct mcux_igpio_config *config = dev->config->config_info; - gpio_pin_config_t pin_config; - u32_t i; + GPIO_Type *base = config->base; - /* Check for an invalid pin configuration */ - if ((flags & GPIO_INT) && (flags & GPIO_DIR_OUT)) { - return -EINVAL; + if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) { + return -ENOTSUP; } - pin_config.direction = ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) - ? kGPIO_DigitalInput : kGPIO_DigitalOutput; - - pin_config.outputLogic = 0; - - if (flags & GPIO_INT) { - if (flags & GPIO_INT_EDGE) { - if (flags & GPIO_INT_ACTIVE_HIGH) { - pin_config.interruptMode = kGPIO_IntRisingEdge; - } else if (flags & GPIO_INT_DOUBLE_EDGE) { - pin_config.interruptMode = - kGPIO_IntRisingOrFallingEdge; - } else { - pin_config.interruptMode = - kGPIO_IntFallingEdge; - } - } else { /* GPIO_INT_LEVEL */ - if (flags & GPIO_INT_ACTIVE_HIGH) { - pin_config.interruptMode = kGPIO_IntHighLevel; - } else { - pin_config.interruptMode = kGPIO_IntLowLevel; - } - } - } else { - pin_config.interruptMode = kGPIO_NoIntmode; + if ((flags & GPIO_SINGLE_ENDED) != 0) { + return -ENOTSUP; } - if (access_op == GPIO_ACCESS_BY_PIN) { - GPIO_PinInit(config->base, pin, &pin_config); - } else { /* GPIO_ACCESS_BY_PORT */ - for (i = 0U; i < 32; i++) { - GPIO_PinInit(config->base, i, &pin_config); - } + if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) { + return -ENOTSUP; } + if (access_op == GPIO_ACCESS_BY_PORT) { + return -ENOTSUP; + } + + if (flags & GPIO_OUTPUT_INIT_HIGH) { + base->DR_SET = BIT(pin); + } + + if (flags & GPIO_OUTPUT_INIT_LOW) { + base->DR_CLEAR = BIT(pin); + } + + WRITE_BIT(base->GDIR, pin, flags & GPIO_OUTPUT); + return 0; } @@ -102,6 +89,103 @@ static int mcux_igpio_read(struct device *dev, return 0; } +static int mcux_igpio_port_get_raw(struct device *dev, u32_t *value) +{ + const struct mcux_igpio_config *config = dev->config->config_info; + GPIO_Type *base = config->base; + + *value = base->DR; + + return 0; +} + +static int mcux_igpio_port_set_masked_raw(struct device *dev, u32_t mask, + u32_t value) +{ + const struct mcux_igpio_config *config = dev->config->config_info; + GPIO_Type *base = config->base; + + base->DR = (base->DR & ~mask) | (mask & value); + + return 0; +} + +static int mcux_igpio_port_set_bits_raw(struct device *dev, u32_t mask) +{ + const struct mcux_igpio_config *config = dev->config->config_info; + GPIO_Type *base = config->base; + + base->DR_SET = mask; + + return 0; +} + +static int mcux_igpio_port_clear_bits_raw(struct device *dev, u32_t mask) +{ + const struct mcux_igpio_config *config = dev->config->config_info; + GPIO_Type *base = config->base; + + base->DR_CLEAR = mask; + + return 0; +} + +static int mcux_igpio_port_toggle_bits(struct device *dev, u32_t mask) +{ + const struct mcux_igpio_config *config = dev->config->config_info; + GPIO_Type *base = config->base; + + base->DR_TOGGLE = mask; + + return 0; +} + +static int mcux_igpio_pin_interrupt_configure(struct device *dev, + unsigned int pin, enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + const struct mcux_igpio_config *config = dev->config->config_info; + struct mcux_igpio_data *data = dev->driver_data; + GPIO_Type *base = config->base; + unsigned int key; + u8_t icr; + int shift; + + if ((mode == GPIO_INT_MODE_EDGE) && (trig == GPIO_INT_TRIG_LOW)) { + icr = 3; + } else if ((mode == GPIO_INT_MODE_EDGE) && + (trig == GPIO_INT_TRIG_HIGH)) { + icr = 2; + } else if ((mode == GPIO_INT_MODE_LEVEL) && + (trig == GPIO_INT_TRIG_HIGH)) { + icr = 1; + } else { + icr = 0; + } + + if (pin < 16) { + shift = 2 * pin; + base->ICR1 = (base->ICR1 & ~(3 << shift)) | (icr << shift); + } else if (pin < 32) { + shift = 2 * (pin - 16); + base->ICR2 = (base->ICR2 & ~(3 << shift)) | (icr << shift); + } else { + return -EINVAL; + } + + key = irq_lock(); + + WRITE_BIT(base->EDGE_SEL, pin, trig == GPIO_INT_TRIG_BOTH); + WRITE_BIT(base->ISR, pin, mode != GPIO_INT_MODE_DISABLED); + WRITE_BIT(base->IMR, pin, mode != GPIO_INT_MODE_DISABLED); + WRITE_BIT(data->pin_callback_enables, pin, + mode != GPIO_INT_MODE_DISABLED); + + irq_unlock(key); + + return 0; +} + static int mcux_igpio_manage_callback(struct device *dev, struct gpio_callback *callback, bool set) { @@ -113,15 +197,12 @@ static int mcux_igpio_manage_callback(struct device *dev, static int mcux_igpio_enable_callback(struct device *dev, int access_op, u32_t pin) { - const struct mcux_igpio_config *config = dev->config->config_info; struct mcux_igpio_data *data = dev->driver_data; if (access_op == GPIO_ACCESS_BY_PIN) { data->pin_callback_enables |= BIT(pin); - GPIO_PortEnableInterrupts(config->base, BIT(pin)); } else { data->pin_callback_enables = 0xFFFFFFFF; - GPIO_PortEnableInterrupts(config->base, 0xFFFFFFFF); } return 0; @@ -130,14 +211,11 @@ static int mcux_igpio_enable_callback(struct device *dev, static int mcux_igpio_disable_callback(struct device *dev, int access_op, u32_t pin) { - const struct mcux_igpio_config *config = dev->config->config_info; struct mcux_igpio_data *data = dev->driver_data; if (access_op == GPIO_ACCESS_BY_PIN) { - GPIO_PortDisableInterrupts(config->base, BIT(pin)); data->pin_callback_enables &= ~BIT(pin); } else { - GPIO_PortDisableInterrupts(config->base, 0); data->pin_callback_enables = 0U; } @@ -149,20 +227,26 @@ static void mcux_igpio_port_isr(void *arg) struct device *dev = (struct device *)arg; const struct mcux_igpio_config *config = dev->config->config_info; struct mcux_igpio_data *data = dev->driver_data; + GPIO_Type *base = config->base; u32_t enabled_int, int_flags; - int_flags = GPIO_PortGetInterruptFlags(config->base); + int_flags = base->ISR; enabled_int = int_flags & data->pin_callback_enables; + base->ISR = enabled_int; gpio_fire_callbacks(&data->callbacks, dev, enabled_int); - - GPIO_ClearPinsInterruptFlags(config->base, enabled_int); } static const struct gpio_driver_api mcux_igpio_driver_api = { .config = mcux_igpio_configure, .write = mcux_igpio_write, .read = mcux_igpio_read, + .port_get_raw = mcux_igpio_port_get_raw, + .port_set_masked_raw = mcux_igpio_port_set_masked_raw, + .port_set_bits_raw = mcux_igpio_port_set_bits_raw, + .port_clear_bits_raw = mcux_igpio_port_clear_bits_raw, + .port_toggle_bits = mcux_igpio_port_toggle_bits, + .pin_interrupt_configure = mcux_igpio_pin_interrupt_configure, .manage_callback = mcux_igpio_manage_callback, .enable_callback = mcux_igpio_enable_callback, .disable_callback = mcux_igpio_disable_callback,