drivers: gpio: esp32: use dts and improve code checks

This PR updates GPIO driver to use DTS information
regarding gpio availability.

This also fixes interrupt handling and
also removes kconfig definition for GPIO port.

A few configuration checks were also added to
improve code usage.

Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
This commit is contained in:
Sylvio Alves 2021-10-19 17:09:38 -03:00 committed by Anas Nashif
parent 7c10e0d947
commit b0717d518e
7 changed files with 91 additions and 100 deletions

View file

@ -39,6 +39,7 @@
&trng0 {
status = "okay";
};
&gpio0 {
status = "okay";
};

View file

@ -59,6 +59,14 @@
hw-flow-control;
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&i2c0 {
status = "okay";
clock-frequency = <I2C_BITRATE_FAST>;

View file

@ -28,6 +28,14 @@
current-speed = <115200>;
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&timer0 {
status = "okay";
};

View file

@ -3,28 +3,8 @@
# Copyright (c) 2017 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
menuconfig GPIO_ESP32
config GPIO_ESP32
bool "ESP32 GPIO"
depends on SOC_ESP32 || SOC_ESP32S2 || SOC_ESP32C3
help
Enables the ESP32 GPIO driver
if GPIO_ESP32
config GPIO_ESP32_0
bool "ESP32 GPIO (pins 0-31)"
default y
help
Include support for GPIO pins 0-31 on the ESP32.
if !SOC_ESP32C3
config GPIO_ESP32_1
bool "ESP32 GPIO (pins 32-39)"
default y
help
Include support for GPIO pins 32-39 on the ESP32.
endif # SOC_ESP32C3
endif # GPIO_ESP32

View file

@ -53,7 +53,7 @@ struct gpio_esp32_config {
struct gpio_driver_config drv_cfg;
gpio_dev_t *const gpio_base;
gpio_dev_t *const gpio_dev;
const bool gpio_port0;
const int gpio_port;
};
struct gpio_esp32_data {
@ -77,7 +77,7 @@ static inline int gpio_get_pin_offset(const struct device *dev)
{
struct gpio_esp32_config *const cfg = DEV_CFG(dev);
return ((cfg->gpio_port0) ? 0 : 32);
return ((cfg->gpio_port) ? 32 : 0);
}
static int gpio_esp32_config(const struct device *dev,
@ -88,35 +88,48 @@ static int gpio_esp32_config(const struct device *dev,
struct gpio_esp32_data *data = dev->data;
uint32_t io_pin = pin + gpio_get_pin_offset(dev);
uint32_t key;
int r = 0;
int ret = 0;
if (!gpio_pin_is_valid(io_pin)) {
LOG_ERR("Selected IO pin is not valid.");
return -EINVAL;
}
key = irq_lock();
/* Set pin function as GPIO */
pinmux_pin_set(data->pinmux, io_pin, PIN_FUNC_GPIO);
ret = pinmux_pin_set(data->pinmux, io_pin, PIN_FUNC_GPIO);
if (ret < 0) {
LOG_ERR("Invalid pinmux configuration.");
goto end;
}
if (flags & GPIO_PULL_UP) {
pinmux_pin_pullup(data->pinmux, io_pin, PINMUX_PULLUP_ENABLE);
ret = pinmux_pin_pullup(data->pinmux, io_pin, PINMUX_PULLUP_ENABLE);
} else if (flags & GPIO_PULL_DOWN) {
pinmux_pin_pullup(data->pinmux, io_pin, PINMUX_PULLUP_DISABLE);
ret = pinmux_pin_pullup(data->pinmux, io_pin, PINMUX_PULLUP_DISABLE);
}
if (ret < 0) {
LOG_ERR("Invalid pinmux configuration.");
goto end;
}
if (flags & GPIO_OUTPUT) {
if (!gpio_pin_is_output_capable(pin)) {
LOG_ERR("GPIO can only be used as input");
return -EINVAL;
ret = -EINVAL;
goto end;
}
if (flags & GPIO_SINGLE_ENDED) {
if (flags & GPIO_LINE_OPEN_DRAIN) {
gpio_ll_od_enable(cfg->gpio_base, io_pin);
} else {
r = -ENOTSUP;
LOG_ERR("GPIO configuration not supported");
ret = -ENOTSUP;
goto end;
}
} else {
gpio_ll_od_disable(cfg->gpio_base, io_pin);
@ -135,7 +148,8 @@ static int gpio_esp32_config(const struct device *dev,
gpio_ll_set_drive_capability(cfg->gpio_base, io_pin, GPIO_DRIVE_CAP_0);
break;
default:
return -EINVAL;
ret = -EINVAL;
goto end;
}
/* Set output pin initial value */
@ -145,24 +159,29 @@ static int gpio_esp32_config(const struct device *dev,
gpio_ll_set_level(cfg->gpio_base, io_pin, 0);
}
r = pinmux_pin_input_enable(data->pinmux, io_pin, PINMUX_OUTPUT_ENABLED);
} else { /* Input */
r = pinmux_pin_input_enable(data->pinmux, io_pin, PINMUX_INPUT_ENABLED);
ret = pinmux_pin_input_enable(data->pinmux, io_pin, PINMUX_OUTPUT_ENABLED);
if (ret < 0) {
goto end;
}
}
if (flags & GPIO_INPUT) {
ret = pinmux_pin_input_enable(data->pinmux, io_pin, PINMUX_INPUT_ENABLED);
}
end:
irq_unlock(key);
return r;
return ret;
}
static int gpio_esp32_port_get_raw(const struct device *port, uint32_t *value)
{
struct gpio_esp32_config *const cfg = DEV_CFG(port);
if (cfg->gpio_port0) {
if (cfg->gpio_port == 0) {
*value = cfg->gpio_dev->in;
#if defined(CONFIG_GPIO_ESP32_1)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
} else {
*value = cfg->gpio_dev->in1.data;
#endif
@ -178,9 +197,9 @@ static int gpio_esp32_port_set_masked_raw(const struct device *port,
uint32_t key = irq_lock();
if (cfg->gpio_port0) {
if (cfg->gpio_port == 0) {
cfg->gpio_dev->out = (cfg->gpio_dev->out & ~mask) | (mask & value);
#if defined(CONFIG_GPIO_ESP32_1)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
} else {
cfg->gpio_dev->out1.data = (cfg->gpio_dev->out1.data & ~mask) | (mask & value);
#endif
@ -196,9 +215,9 @@ static int gpio_esp32_port_set_bits_raw(const struct device *port,
{
struct gpio_esp32_config *const cfg = DEV_CFG(port);
if (cfg->gpio_port0) {
if (cfg->gpio_port == 0) {
cfg->gpio_dev->out_w1ts = pins;
#if defined(CONFIG_GPIO_ESP32_1)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
} else {
cfg->gpio_dev->out1_w1ts.data = pins;
#endif
@ -212,9 +231,9 @@ static int gpio_esp32_port_clear_bits_raw(const struct device *port,
{
struct gpio_esp32_config *const cfg = DEV_CFG(port);
if (cfg->gpio_port0) {
if (cfg->gpio_port == 0) {
cfg->gpio_dev->out_w1tc = pins;
#if defined(CONFIG_GPIO_ESP32_1)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
} else {
cfg->gpio_dev->out1_w1tc.data = pins;
#endif
@ -229,9 +248,9 @@ static int gpio_esp32_port_toggle_bits(const struct device *port,
struct gpio_esp32_config *const cfg = DEV_CFG(port);
uint32_t key = irq_lock();
if (cfg->gpio_port0) {
if (cfg->gpio_port == 0) {
cfg->gpio_dev->out ^= pins;
#if defined(CONFIG_GPIO_ESP32_1)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
} else {
cfg->gpio_dev->out1.data ^= pins;
#endif
@ -312,11 +331,12 @@ static uint32_t gpio_esp32_get_pending_int(const struct device *dev)
uint32_t irq_status;
uint32_t const core_id = CPU_ID();
#if defined(CONFIG_GPIO_ESP32_1)
gpio_ll_get_intr_status_high(cfg->gpio_base, core_id, &irq_status);
#else
gpio_ll_get_intr_status(cfg->gpio_base, core_id, &irq_status);
#endif
if (cfg->gpio_port == 0) {
gpio_ll_get_intr_status(cfg->gpio_base, core_id, &irq_status);
} else {
gpio_ll_get_intr_status_high(cfg->gpio_base, core_id, &irq_status);
}
return irq_status;
}
@ -327,15 +347,17 @@ static void IRAM_ATTR gpio_esp32_fire_callbacks(const struct device *dev)
uint32_t irq_status;
uint32_t const core_id = CPU_ID();
#if defined(CONFIG_GPIO_ESP32_1)
gpio_ll_get_intr_status_high(cfg->gpio_base, core_id, &irq_status);
gpio_ll_clear_intr_status_high(cfg->gpio_base, irq_status);
#else
gpio_ll_get_intr_status(cfg->gpio_base, core_id, &irq_status);
gpio_ll_clear_intr_status(cfg->gpio_base, irq_status);
#endif
if (cfg->gpio_port == 0) {
gpio_ll_get_intr_status(cfg->gpio_base, core_id, &irq_status);
gpio_ll_clear_intr_status(cfg->gpio_base, irq_status);
} else {
gpio_ll_get_intr_status_high(cfg->gpio_base, core_id, &irq_status);
gpio_ll_clear_intr_status_high(cfg->gpio_base, irq_status);
}
gpio_fire_callbacks(&data->cb, dev, irq_status);
if (irq_status != 0) {
gpio_fire_callbacks(&data->cb, dev, irq_status);
}
}
static void IRAM_ATTR gpio_esp32_isr(void *param);
@ -381,15 +403,14 @@ static const struct gpio_driver_api gpio_esp32_driver_api = {
};
#define ESP_SOC_GPIO_INIT(_id) \
static struct gpio_esp32_config gpio_data_##_id; \
\
static struct gpio_esp32_data gpio_data_##_id; \
static struct gpio_esp32_config gpio_config_##_id = { \
.drv_cfg = { \
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(_id), \
}, \
.gpio_base = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0)), \
.gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio##_id)), \
.gpio_port0 = _id ? false : true \
.gpio_port = _id \
}; \
DEVICE_DT_DEFINE(DT_NODELABEL(gpio##_id), \
&gpio_esp32_init, \
@ -398,30 +419,19 @@ static const struct gpio_driver_api gpio_esp32_driver_api = {
&gpio_config_##_id, \
POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&gpio_esp32_driver_api)
&gpio_esp32_driver_api);
/*
* GPIOs are divided in two groups for ESP32 because the callback
* API works with 32-bit bitmasks to manage interrupt callbacks,
* and the device has 40 GPIO pins.
*/
#if defined(CONFIG_GPIO_ESP32_0)
ESP_SOC_GPIO_INIT(0);
#endif
#if defined(CONFIG_GPIO_ESP32_1)
ESP_SOC_GPIO_INIT(1);
#endif
DT_INST_FOREACH_STATUS_OKAY(ESP_SOC_GPIO_INIT);
static void IRAM_ATTR gpio_esp32_isr(void *param)
{
ARG_UNUSED(param);
#if defined(CONFIG_GPIO_ESP32_0)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio0), okay)
gpio_esp32_fire_callbacks(DEVICE_DT_INST_GET(0));
#endif
#if defined(CONFIG_GPIO_ESP32_1)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
gpio_esp32_fire_callbacks(DEVICE_DT_INST_GET(1));
#endif
ARG_UNUSED(param);
}

View file

@ -12,6 +12,7 @@
#include <esp32/rom/gpio.h>
#include <soc/gpio_sig_map.h>
#include <soc/ledc_reg.h>
#include <drivers/gpio/gpio_esp32.h>
#include <soc.h>
#include <errno.h>
@ -89,23 +90,6 @@ static inline void clear_mask32(uint32_t v, uint32_t mem_addr)
{
sys_write32(sys_read32(mem_addr) & ~v, mem_addr);
}
static const char *esp32_get_gpio_for_pin(int pin)
{
if (pin < 32) {
#if defined(CONFIG_GPIO_ESP32_0)
return DT_INST_LABEL(0);
#else
return NULL;
#endif /* CONFIG_GPIO_ESP32_0 */
}
#if defined(CONFIG_GPIO_ESP32_1)
return DT_INST_LABEL(1);
#else
return NULL;
#endif /* CONFIG_GPIO_ESP32_1 */
}
/* end Remove after PR 5113 */
static uint8_t pwm_led_esp32_get_gpio_config(uint8_t pin,
@ -225,7 +209,7 @@ static int pwm_led_esp32_channel_set(int pin, bool speed_mode, int channel,
pwm_led_esp32_bind_channel_timer(speed_mode, channel, timer);
/* Set pin */
device_name = esp32_get_gpio_for_pin(pin);
device_name = gpio_esp32_get_gpio_for_pin(pin);
if (!device_name) {
return -EINVAL;
}

View file

@ -8,18 +8,18 @@
static const char *gpio_esp32_get_gpio_for_pin(int pin)
{
if (pin < 32) {
#if defined(CONFIG_GPIO_ESP32_0)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio0), okay)
return DT_LABEL(DT_INST(0, espressif_esp32_gpio));
#else
return NULL;
#endif /* CONFIG_GPIO_ESP32_0 */
#endif
}
#if defined(CONFIG_GPIO_ESP32_1)
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
return DT_LABEL(DT_INST(1, espressif_esp32_gpio));
#else
return NULL;
#endif /* CONFIG_GPIO_ESP32_1 */
#endif
}
#endif /* ZEPHYR_INCLUDE_DRIVERS_GPIO_GPIO_ESP32_H_ */