-
Notifications
You must be signed in to change notification settings - Fork 8.2k
[TOPIC-GPIO] gpio: Update mcux igpio driver to use new gpio api #19247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| /* | ||
| * Copyright (c) 2019 Nordic Semiconductor ASA | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change copyright
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept the Nordic copyright because I copied the file from another board |
||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| / { | ||
| resources { | ||
| compatible = "test,gpio_basic_api"; | ||
| out-gpios = <&gpio1 23 0>; /* Arduino D0 */ | ||
| in-gpios = <&gpio1 22 0>; /* Arduino D1 */ | ||
| }; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,10 @@ | |
| #include <fsl_port.h> | ||
| #endif | ||
|
|
||
| #ifdef CONFIG_BOARD_MIMXRT1050_EVK | ||
| #include <fsl_iomuxc.h> | ||
| #endif | ||
|
|
||
| static void board_setup(void) | ||
| { | ||
| #ifdef DT_INST_0_TEST_GPIO_BASIC_API | ||
|
|
@@ -34,6 +38,22 @@ static void board_setup(void) | |
| pinmux_pin_set(pmx, PIN_OUT, PORT_PCR_MUX(kPORT_MuxAsGpio)); | ||
| pinmux_pin_set(pmx, PIN_IN, PORT_PCR_MUX(kPORT_MuxAsGpio)); | ||
| #endif | ||
|
|
||
| #ifdef CONFIG_BOARD_MIMXRT1050_EVK | ||
| IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_06_GPIO1_IO22, 0); | ||
| IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_07_GPIO1_IO23, 0); | ||
|
|
||
| IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_06_GPIO1_IO22, | ||
| IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | | ||
| IOMUXC_SW_PAD_CTL_PAD_HYS_MASK | | ||
| IOMUXC_SW_PAD_CTL_PAD_SPEED(2) | | ||
| IOMUXC_SW_PAD_CTL_PAD_DSE(6)); | ||
|
|
||
| IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_07_GPIO1_IO23, | ||
| IOMUXC_SW_PAD_CTL_PAD_PKE_MASK | | ||
| IOMUXC_SW_PAD_CTL_PAD_SPEED(2) | | ||
| IOMUXC_SW_PAD_CTL_PAD_DSE(6)); | ||
| #endif | ||
|
Comment on lines
+42
to
+56
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i moved this to board's pinmux initialization
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes this is ugly here, but I also don't want to make it the default pinmux configuration for the board. I think it's more likely these pins will be used for UART. |
||
| } | ||
|
|
||
| void test_main(void) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.