-
Notifications
You must be signed in to change notification settings - Fork 8.2k
[TOPIC-GPIO] gpio: Update rv32m1 gpio driver to use new gpio api #19664
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 |
|---|---|---|
|
|
@@ -34,25 +34,72 @@ struct gpio_rv32m1_data { | |
| u32_t pin_callback_enables; | ||
| }; | ||
|
|
||
| static u32_t get_port_pcr_irqc_value_from_flags(struct device *dev, | ||
| u32_t pin, enum gpio_int_mode mode, | ||
| enum gpio_int_trig trig) | ||
| { | ||
| port_interrupt_t port_interrupt = 0; | ||
|
|
||
| if (mode == GPIO_INT_MODE_DISABLED) { | ||
| port_interrupt = kPORT_InterruptOrDMADisabled; | ||
| } else { | ||
| if (mode == GPIO_INT_MODE_LEVEL) { | ||
| if (trig == GPIO_INT_TRIG_LOW) { | ||
| port_interrupt = kPORT_InterruptLogicZero; | ||
| } else { | ||
| port_interrupt = kPORT_InterruptLogicOne; | ||
| } | ||
| } else { | ||
| switch (trig) { | ||
| case GPIO_INT_TRIG_LOW: | ||
| port_interrupt = kPORT_InterruptFallingEdge; | ||
| break; | ||
| case GPIO_INT_TRIG_HIGH: | ||
| port_interrupt = kPORT_InterruptRisingEdge; | ||
| break; | ||
| case GPIO_INT_TRIG_BOTH: | ||
| port_interrupt = kPORT_InterruptEitherEdge; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return PORT_PCR_IRQC(port_interrupt); | ||
| } | ||
|
|
||
| static int gpio_rv32m1_configure(struct device *dev, | ||
| int access_op, u32_t pin, int flags) | ||
| { | ||
| const struct gpio_rv32m1_config *config = dev->config->config_info; | ||
| GPIO_Type *gpio_base = config->gpio_base; | ||
| PORT_Type *port_base = config->port_base; | ||
| port_interrupt_t port_interrupt = 0; | ||
| struct gpio_rv32m1_data *data = dev->driver_data; | ||
| u32_t mask = 0U; | ||
| u32_t pcr = 0U; | ||
| u8_t i; | ||
|
|
||
| /* Check for an invalid pin number */ | ||
| if (pin >= ARRAY_SIZE(port_base->PCR)) { | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| /* Check for an invalid pin configuration */ | ||
| if ((flags & GPIO_INT) && (flags & GPIO_DIR_OUT)) { | ||
| if ((flags & GPIO_INT_ENABLE) && ((flags & GPIO_INPUT) == 0)) { | ||
|
||
| return -EINVAL; | ||
| } | ||
|
|
||
| if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) { | ||
| return -ENOTSUP; | ||
| } | ||
|
|
||
| if ((flags & GPIO_SINGLE_ENDED) != 0) { | ||
| return -ENOTSUP; | ||
| } | ||
|
|
||
| /* Check if GPIO port supports interrupts */ | ||
| if ((flags & GPIO_INT) && ((config->flags & GPIO_INT) == 0U)) { | ||
| return -EINVAL; | ||
| if ((flags & GPIO_INT_ENABLE) && | ||
| ((config->flags & GPIO_INT_ENABLE) == 0U)) { | ||
|
||
| return -ENOTSUP; | ||
| } | ||
|
|
||
| /* The flags contain options that require touching registers in the | ||
|
|
@@ -63,15 +110,25 @@ static int gpio_rv32m1_configure(struct device *dev, | |
| */ | ||
|
|
||
| if (access_op == GPIO_ACCESS_BY_PIN) { | ||
| if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) { | ||
| switch (flags & GPIO_DIR_MASK) { | ||
| case GPIO_INPUT: | ||
| gpio_base->PDDR &= ~BIT(pin); | ||
| } else { /* GPIO_DIR_OUT */ | ||
| break; | ||
| case GPIO_OUTPUT: | ||
| if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { | ||
| gpio_base->PSOR = BIT(pin); | ||
| } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { | ||
| gpio_base->PCOR = BIT(pin); | ||
| } | ||
| gpio_base->PDDR |= BIT(pin); | ||
| break; | ||
| default: | ||
| return -ENOTSUP; | ||
| } | ||
| } else { /* GPIO_ACCESS_BY_PORT */ | ||
| if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) { | ||
| if ((flags & GPIO_INPUT) != 0) { | ||
| gpio_base->PDDR = 0x0; | ||
| } else { /* GPIO_DIR_OUT */ | ||
| } else { /* GPIO_OUTPUT */ | ||
| gpio_base->PDDR = 0xFFFFFFFF; | ||
| } | ||
| } | ||
|
|
@@ -81,11 +138,11 @@ static int gpio_rv32m1_configure(struct device *dev, | |
| */ | ||
| mask |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; | ||
|
|
||
| if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) { | ||
| if ((flags & GPIO_PULL_UP) != 0) { | ||
| /* Enable the pull and select the pullup resistor. */ | ||
| pcr |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; | ||
|
|
||
| } else if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_DOWN) { | ||
| } else if ((flags & GPIO_PULL_DOWN) != 0) { | ||
| /* Enable the pull and select the pulldown resistor (deselect | ||
| * the pullup resistor. | ||
| */ | ||
|
|
@@ -97,44 +154,27 @@ static int gpio_rv32m1_configure(struct device *dev, | |
| */ | ||
| mask |= PORT_PCR_IRQC_MASK; | ||
|
||
|
|
||
| if (flags & GPIO_INT) { | ||
| if (flags & GPIO_INT_EDGE) { | ||
| if (flags & GPIO_INT_ACTIVE_HIGH) { | ||
| port_interrupt = kPORT_InterruptRisingEdge; | ||
| } else if (flags & GPIO_INT_DOUBLE_EDGE) { | ||
| port_interrupt = kPORT_InterruptEitherEdge; | ||
| } else { | ||
| port_interrupt = kPORT_InterruptFallingEdge; | ||
| } | ||
| } else { /* GPIO_INT_LEVEL */ | ||
| if (flags & GPIO_INT_ACTIVE_HIGH) { | ||
| port_interrupt = kPORT_InterruptLogicOne; | ||
| } else { | ||
| port_interrupt = kPORT_InterruptLogicZero; | ||
| } | ||
| } | ||
| pcr |= PORT_PCR_IRQC(port_interrupt); | ||
| } | ||
|
|
||
| mask |= PORT_PCR_MUX_MASK; | ||
|
|
||
| /* Now we can write the PORT PCR register(s). If accessing by pin, we | ||
| * only need to write one PCR register. Otherwise, write all the PCR | ||
| * registers in the PORT module (one for each pin). | ||
| */ | ||
| if (access_op == GPIO_ACCESS_BY_PIN) { | ||
| port_base->PCR[pin] = (port_base->PCR[pin] & ~mask) | pcr | | ||
| PORT_PCR_MUX(kPORT_MuxAsGpio); | ||
| port_base->PCR[pin] = (port_base->PCR[pin] & ~mask) | pcr; | ||
| WRITE_BIT(data->pin_callback_enables, pin, | ||
|
||
| flags & GPIO_INT_ENABLE); | ||
| } else { /* GPIO_ACCESS_BY_PORT */ | ||
| for (i = 0U; i < ARRAY_SIZE(port_base->PCR); i++) { | ||
| port_base->PCR[i] = (port_base->PCR[pin] & ~mask) | pcr | ||
| | PORT_PCR_MUX(kPORT_MuxAsGpio); | ||
| port_base->PCR[i] = (port_base->PCR[pin] & ~mask) | pcr; | ||
| } | ||
| if (flags & GPIO_INT_ENABLE) { | ||
| data->pin_callback_enables = 0xFFFFFFFF; | ||
| } else { | ||
| data->pin_callback_enables = 0x0; | ||
| } | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_write(struct device *dev, | ||
| int access_op, u32_t pin, u32_t value) | ||
| { | ||
|
|
@@ -180,6 +220,86 @@ static int gpio_rv32m1_read(struct device *dev, | |
| return 0; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_port_get_raw(struct device *dev, u32_t *value) | ||
| { | ||
| const struct gpio_rv32m1_config *config = dev->config->config_info; | ||
| GPIO_Type *gpio_base = config->gpio_base; | ||
|
|
||
| *value = gpio_base->PDIR; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_port_set_masked_raw(struct device *dev, u32_t mask, | ||
| u32_t value) | ||
| { | ||
| const struct gpio_rv32m1_config *config = dev->config->config_info; | ||
| GPIO_Type *gpio_base = config->gpio_base; | ||
|
|
||
| gpio_base->PDOR = (gpio_base->PDOR & ~mask) | (mask & value); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_port_set_bits_raw(struct device *dev, u32_t mask) | ||
| { | ||
| const struct gpio_rv32m1_config *config = dev->config->config_info; | ||
| GPIO_Type *gpio_base = config->gpio_base; | ||
|
|
||
| gpio_base->PSOR = mask; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_port_clear_bits_raw(struct device *dev, u32_t mask) | ||
| { | ||
| const struct gpio_rv32m1_config *config = dev->config->config_info; | ||
| GPIO_Type *gpio_base = config->gpio_base; | ||
|
|
||
| gpio_base->PCOR = mask; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_port_toggle_bits(struct device *dev, u32_t mask) | ||
| { | ||
| const struct gpio_rv32m1_config *config = dev->config->config_info; | ||
| GPIO_Type *gpio_base = config->gpio_base; | ||
|
|
||
| gpio_base->PTOR = mask; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_pin_interrupt_configure(struct device *dev, | ||
| unsigned int pin, enum gpio_int_mode mode, | ||
| enum gpio_int_trig trig) | ||
| { | ||
| const struct gpio_rv32m1_config *config = dev->config->config_info; | ||
| PORT_Type *port_base = config->port_base; | ||
| struct gpio_rv32m1_data *data = dev->driver_data; | ||
|
|
||
| /* Check for an invalid pin number */ | ||
| if (pin >= ARRAY_SIZE(port_base->PCR)) { | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| /* Check if GPIO port supports interrupts */ | ||
| if ((mode != GPIO_INT_MODE_DISABLED) && | ||
| ((config->flags & GPIO_INT_ENABLE) == 0U)) { | ||
| return -ENOTSUP; | ||
| } | ||
|
|
||
| u32_t pcr = get_port_pcr_irqc_value_from_flags(dev, pin, mode, trig); | ||
|
|
||
| port_base->PCR[pin] = (port_base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | pcr; | ||
|
|
||
| WRITE_BIT(data->pin_callback_enables, pin, mode != GPIO_INT_DISABLE); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| static int gpio_rv32m1_manage_callback(struct device *dev, | ||
| struct gpio_callback *callback, bool set) | ||
| { | ||
|
|
@@ -231,7 +351,7 @@ static void gpio_rv32m1_port_isr(void *arg) | |
| gpio_fire_callbacks(&data->callbacks, dev, enabled_int); | ||
|
|
||
| /* Clear the port interrupts */ | ||
| config->port_base->ISFR = 0xFFFFFFFF; | ||
| config->port_base->ISFR = enabled_int; | ||
| } | ||
|
|
||
| static int gpio_rv32m1_init(struct device *dev) | ||
|
|
@@ -260,6 +380,12 @@ static const struct gpio_driver_api gpio_rv32m1_driver_api = { | |
| .config = gpio_rv32m1_configure, | ||
| .write = gpio_rv32m1_write, | ||
| .read = gpio_rv32m1_read, | ||
| .port_get_raw = gpio_rv32m1_port_get_raw, | ||
| .port_set_masked_raw = gpio_rv32m1_port_set_masked_raw, | ||
| .port_set_bits_raw = gpio_rv32m1_port_set_bits_raw, | ||
| .port_clear_bits_raw = gpio_rv32m1_port_clear_bits_raw, | ||
| .port_toggle_bits = gpio_rv32m1_port_toggle_bits, | ||
| .pin_interrupt_configure = gpio_rv32m1_pin_interrupt_configure, | ||
| .manage_callback = gpio_rv32m1_manage_callback, | ||
| .enable_callback = gpio_rv32m1_enable_callback, | ||
| .disable_callback = gpio_rv32m1_disable_callback, | ||
|
|
@@ -272,7 +398,7 @@ static const struct gpio_rv32m1_config gpio_rv32m1_porta_config = { | |
| .gpio_base = (GPIO_Type *) DT_OPENISA_RV32M1_GPIO_GPIO_A_BASE_ADDRESS, | ||
| .port_base = PORTA, | ||
| #ifdef DT_OPENISA_RV32M1_GPIO_GPIO_A_IRQ_0 | ||
| .flags = GPIO_INT, | ||
| .flags = GPIO_INT_ENABLE, | ||
| #else | ||
| .flags = 0, | ||
| #endif | ||
|
|
@@ -317,7 +443,7 @@ static const struct gpio_rv32m1_config gpio_rv32m1_portb_config = { | |
| .gpio_base = (GPIO_Type *) DT_OPENISA_RV32M1_GPIO_GPIO_B_BASE_ADDRESS, | ||
| .port_base = PORTB, | ||
| #ifdef DT_OPENISA_RV32M1_GPIO_GPIO_B_IRQ_0 | ||
| .flags = GPIO_INT, | ||
| .flags = GPIO_INT_ENABLE, | ||
| #else | ||
| .flags = 0, | ||
| #endif | ||
|
|
@@ -362,7 +488,7 @@ static const struct gpio_rv32m1_config gpio_rv32m1_portc_config = { | |
| .gpio_base = (GPIO_Type *) DT_OPENISA_RV32M1_GPIO_GPIO_C_BASE_ADDRESS, | ||
| .port_base = PORTC, | ||
| #ifdef DT_OPENISA_RV32M1_GPIO_GPIO_C_IRQ_0 | ||
| .flags = GPIO_INT, | ||
| .flags = GPIO_INT_ENABLE, | ||
| #else | ||
| .flags = 0, | ||
| #endif | ||
|
|
@@ -408,7 +534,7 @@ static const struct gpio_rv32m1_config gpio_rv32m1_portd_config = { | |
| .gpio_base = (GPIO_Type *) DT_OPENISA_RV32M1_GPIO_GPIO_D_BASE_ADDRESS, | ||
| .port_base = PORTD, | ||
| #ifdef DT_OPENISA_RV32M1_GPIO_GPIO_D_IRQ_0 | ||
| .flags = GPIO_INT, | ||
| .flags = GPIO_INT_ENABLE, | ||
| #else | ||
| .flags = 0, | ||
| #endif | ||
|
|
@@ -453,7 +579,7 @@ static const struct gpio_rv32m1_config gpio_rv32m1_porte_config = { | |
| .gpio_base = (GPIO_Type *) DT_OPENISA_RV32M1_GPIO_GPIO_E_BASE_ADDRESS, | ||
| .port_base = PORTE, | ||
| #ifdef DT_OPENISA_RV32M1_GPIO_GPIO_E_IRQ_0 | ||
| .flags = GPIO_INT, | ||
| .flags = GPIO_INT_ENABLE, | ||
| #else | ||
| .flags = 0, | ||
| #endif | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is not used anymore by
gpio_rv32m1_configure. We could move it directly abovegpio_rv32m1_pin_interrupt_configure. It would make the code easier to read.