From 232e2c5a3c18868c19475a02f410f4584addc928 Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Fri, 24 Jan 2025 17:10:13 -0300 Subject: [PATCH] drivers: uart: espressif: Add LP UART driver Add LP UART driver for LP Core Signed-off-by: Lucas Tamborrino --- ...si => esp32c6_devkitc_hpcore-pinctrl.dtsi} | 0 .../esp32c6_devkitc_hpcore.dts | 2 +- .../esp32c6_devkitc_lpcore.dts | 7 + .../esp32c6_devkitc_lpcore.yaml | 2 + .../esp32c6_devkitc_lpcore_defconfig | 4 + drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig.esp32 | 8 + drivers/serial/lpuart_esp32.c | 204 ++++++++++++++++++ .../serial/espressif,esp32-lpuart.yaml | 40 ++++ .../espressif/esp32c6/esp32c6_common.dtsi | 7 + .../espressif/esp32c6/esp32c6_lpcore.dtsi | 7 + soc/espressif/esp32c6/default_lpcore.ld | 4 + 12 files changed, 285 insertions(+), 1 deletion(-) rename boards/espressif/esp32c6_devkitc/{esp32c6_devkitc-pinctrl.dtsi => esp32c6_devkitc_hpcore-pinctrl.dtsi} (100%) create mode 100644 drivers/serial/lpuart_esp32.c create mode 100644 dts/bindings/serial/espressif,esp32-lpuart.yaml diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_hpcore-pinctrl.dtsi similarity index 100% rename from boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi rename to boards/espressif/esp32c6_devkitc/esp32c6_devkitc_hpcore-pinctrl.dtsi diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_hpcore.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_hpcore.dts index 45306b57328..ef8dbea59b3 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_hpcore.dts +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_hpcore.dts @@ -7,7 +7,7 @@ /dts-v1/; #include -#include "esp32c6_devkitc-pinctrl.dtsi" +#include "esp32c6_devkitc_hpcore-pinctrl.dtsi" #include #include diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.dts index f9aa25a41c2..739781e692b 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.dts +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.dts @@ -15,5 +15,12 @@ chosen { zephyr,sram = &sramlp; zephyr,code-partition = &slot0_lpcore_partition; + zephyr,console = &lp_uart; + zephyr,shell-uart = &lp_uart; }; }; + +&lp_uart { + status = "okay"; + current-speed = <115200>; +}; diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.yaml b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.yaml index 18732cddb5f..49e25bcdba0 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.yaml +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore.yaml @@ -6,6 +6,8 @@ toolchain: - zephyr supported: - cpu + - uart + - serial testing: only_tags: - introduction diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore_defconfig b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore_defconfig index 13d59f76b7d..42ee26028f9 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore_defconfig +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_lpcore_defconfig @@ -9,7 +9,11 @@ CONFIG_THREAD_CUSTOM_DATA=n CONFIG_BOOT_BANNER=n # Console +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y CONFIG_PRINTK=n +CONFIG_CBPRINTF_NANO=y # Build CONFIG_SIZE_OPTIMIZATIONS=y diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 1a453ea210c..aa97c9e0ae2 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -15,6 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_USB_CDC_ACM ${ZEPHYR_BASE}/misc/empty_file.c # zephyr-keep-sorted-start zephyr_library_sources_ifdef(CONFIG_LEUART_GECKO leuart_gecko.c) +zephyr_library_sources_ifdef(CONFIG_LPUART_ESP32 lpuart_esp32.c) zephyr_library_sources_ifdef(CONFIG_SERIAL_ESP32_USB serial_esp32_usb.c) zephyr_library_sources_ifdef(CONFIG_UART_ALTERA uart_altera.c) zephyr_library_sources_ifdef(CONFIG_UART_ALTERA_JTAG uart_altera_jtag.c) diff --git a/drivers/serial/Kconfig.esp32 b/drivers/serial/Kconfig.esp32 index 83dcc3f8780..e4ea9b5d6ee 100644 --- a/drivers/serial/Kconfig.esp32 +++ b/drivers/serial/Kconfig.esp32 @@ -43,3 +43,11 @@ config UART_ESP32_RX_FIFO_THRESH range 1 127 help Configure the RX FIFO threshold for ESP32 UART driver. + +config LPUART_ESP32 + bool "ESP32 LP UART driver" + default y + depends on DT_HAS_ESPRESSIF_ESP32_LPUART_ENABLED + select SERIAL_HAS_DRIVER + help + Enable the ESP32 LP UART. diff --git a/drivers/serial/lpuart_esp32.c b/drivers/serial/lpuart_esp32.c new file mode 100644 index 00000000000..8e53a4f638b --- /dev/null +++ b/drivers/serial/lpuart_esp32.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2025 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT espressif_esp32_lpuart + +#include +#include + +#include +#if defined(CONFIG_SOC_ESP32C6_HPCORE) +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#define ESP_LP_UART_TX_IDLE_NUM_DEFAULT (0U) + +struct lp_uart_esp32_data { + uart_hal_context_t hal; +}; + +struct lp_uart_esp32_config { + uint8_t tx_io_num; + uint8_t rx_io_num; + uint8_t rts_io_num; + uint8_t cts_io_num; + int baud_rate; + uint8_t data_bits; + uint8_t parity; + uint8_t stop_bits; + uint8_t flow_ctrl; + uint8_t rx_flow_ctrl_thresh; + uint8_t lp_uart_source_clk; +}; + +static int lp_uart_esp32_poll_in(const struct device *dev, unsigned char *p_char) +{ + struct lp_uart_esp32_data *data = dev->data; + int inout_rd_len = 1; + + if (uart_hal_get_rxfifo_len(&data->hal) == 0) { + return -1; + } + + uart_hal_read_rxfifo(&data->hal, p_char, &inout_rd_len); + + return 0; +} + +static void lp_uart_esp32_poll_out(const struct device *dev, unsigned char c) +{ + struct lp_uart_esp32_data *data = dev->data; + int tx_len = 0; + + /* Wait for space in FIFO */ + while (uart_hal_get_txfifo_len(&data->hal) == 0) { + ; /* Wait */ + } + + uart_hal_write_txfifo(&data->hal, (const void *)&c, 1, &tx_len); +} + +#if defined(CONFIG_SOC_ESP32C6_HPCORE) + +static int lp_uart_esp32_param_config(const struct device *dev) +{ + const struct lp_uart_esp32_config *const cfg = dev->config; + struct lp_uart_esp32_data *data = dev->data; + uint32_t sclk_freq = 0; + + if ((cfg->rx_flow_ctrl_thresh > SOC_LP_UART_FIFO_LEN) || + (cfg->flow_ctrl > UART_CFG_FLOW_CTRL_RTS_CTS) || + (cfg->data_bits > UART_CFG_DATA_BITS_8)) { + return -EINVAL; + } + + /* Get LP UART source clock frequency */ + switch (clk_ll_rtc_fast_get_src()) { + case SOC_RTC_FAST_CLK_SRC_XTAL_DIV: +#if CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 /* SOC_RTC_FAST_CLK_SRC_XTAL_D4 */ + sclk_freq = clk_hal_xtal_get_freq_mhz() * MHZ(1) >> 2; +#else /* SOC_RTC_FAST_CLK_SRC_XTAL_D2 */ + sclk_freq = clk_hal_xtal_get_freq_mhz() * MHZ(1) >> 1; +#endif + break; + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + sclk_freq = + esp_clk_tree_rc_fast_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / + clk_ll_rc_fast_get_divider(); + break; +#if SOC_CLK_LP_FAST_SUPPORT_LP_PLL + case SOC_RTC_FAST_CLK_SRC_LP_PLL: + sclk_freq = clk_ll_lp_pll_get_freq_mhz() * MHZ(1); + break; +#endif + default: + return -EINVAL; + } + + lp_uart_ll_enable_bus_clock(0, true); + lp_uart_ll_set_source_clk(data->hal.dev, cfg->lp_uart_source_clk); + lp_uart_ll_sclk_enable(0); + + /* Initialize LP UART HAL with default parameters */ + uart_hal_init(&data->hal, LP_UART_NUM_0); + + /* Set protocol parameters from the configuration */ + lp_uart_ll_set_baudrate(data->hal.dev, cfg->baud_rate, sclk_freq); + uart_hal_set_parity(&data->hal, cfg->parity); + uart_hal_set_data_bit_num(&data->hal, cfg->data_bits); + uart_hal_set_stop_bits(&data->hal, cfg->stop_bits); + uart_hal_set_tx_idle_num(&data->hal, ESP_LP_UART_TX_IDLE_NUM_DEFAULT); + uart_hal_set_hw_flow_ctrl(&data->hal, cfg->flow_ctrl, cfg->rx_flow_ctrl_thresh); + + /* Reset Tx/Rx FIFOs */ + uart_hal_rxfifo_rst(&data->hal); + uart_hal_txfifo_rst(&data->hal); + + return 0; +} + +static void lp_uart_esp32_config_io(int pin, int direction, int func) +{ + int rtc_io_num = rtc_io_num_map[pin]; + + rtcio_hal_function_select(rtc_io_num, RTCIO_FUNC_RTC); + rtcio_hal_set_direction(rtc_io_num, direction); + rtcio_hal_iomux_func_sel(rtc_io_num, func); +} + +static void lp_uart_esp32_set_pin(const struct device *dev) +{ + const struct lp_uart_esp32_config *const cfg = dev->config; + + /* Configure Tx Pin */ + lp_uart_esp32_config_io(cfg->tx_io_num, RTC_GPIO_MODE_OUTPUT_ONLY, LP_U0TXD_MUX_FUNC); + + /* Configure Rx Pin */ + lp_uart_esp32_config_io(cfg->rx_io_num, RTC_GPIO_MODE_INPUT_ONLY, LP_U0RXD_GPIO_NUM); + + /* Configure RTS Pin */ + lp_uart_esp32_config_io(cfg->rts_io_num, RTC_GPIO_MODE_OUTPUT_ONLY, LP_U0RTS_MUX_FUNC); + + /* Configure CTS Pin */ + lp_uart_esp32_config_io(cfg->cts_io_num, RTC_GPIO_MODE_INPUT_ONLY, LP_U0CTS_MUX_FUNC); +} + +static int lp_uart_esp32_init(const struct device *dev) +{ + int ret = 0; + + ret = lp_uart_esp32_param_config(dev); + if (ret != 0) { + return -EINVAL; + } + + /* Configure LP UART IO pins */ + lp_uart_esp32_set_pin(dev); + return 0; +} + +#endif /* CONFIG_SOC_ESP32C6_HPCORE */ + +static DEVICE_API(uart, lp_uart_esp32_api) = { + .poll_in = lp_uart_esp32_poll_in, + .poll_out = lp_uart_esp32_poll_out, +}; + +static struct lp_uart_esp32_data lp_uart_esp32_data = { + .hal = { + .dev = (uart_dev_t *)DT_REG_ADDR(DT_NODELABEL(lp_uart)), + }, +}; + +static const struct lp_uart_esp32_config lp_uart_esp32_cfg = { + .tx_io_num = DT_PROP(DT_NODELABEL(lp_uart), tx_pin), + .rx_io_num = DT_PROP(DT_NODELABEL(lp_uart), rx_pin), + .rts_io_num = DT_PROP(DT_NODELABEL(lp_uart), rts_pin), + .cts_io_num = DT_PROP(DT_NODELABEL(lp_uart), cts_pin), + .baud_rate = DT_PROP(DT_NODELABEL(lp_uart), current_speed), + .data_bits = DT_PROP_OR(DT_NODELABEL(lp_uart), data_bits, UART_CFG_DATA_BITS_8), + .parity = DT_ENUM_IDX(DT_NODELABEL(lp_uart), parity), + .stop_bits = DT_PROP_OR(DT_NODELABEL(lp_uart), stop_bits, UART_CFG_STOP_BITS_1), + .flow_ctrl = DT_PROP_OR(DT_NODELABEL(lp_uart), flow_ctrl, UART_CFG_FLOW_CTRL_NONE), + .rx_flow_ctrl_thresh = 0, + .lp_uart_source_clk = LP_UART_SCLK_DEFAULT, +}; + +#if defined(CONFIG_SOC_ESP32C6_HPCORE) +#define LP_UART_ESP32_INIT_FUNC lp_uart_esp32_init +#else +#define LP_UART_ESP32_INIT_FUNC NULL +#endif + +DEVICE_DT_DEFINE(DT_NODELABEL(lp_uart), LP_UART_ESP32_INIT_FUNC, NULL, &lp_uart_esp32_data, + &lp_uart_esp32_cfg, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, &lp_uart_esp32_api); diff --git a/dts/bindings/serial/espressif,esp32-lpuart.yaml b/dts/bindings/serial/espressif,esp32-lpuart.yaml new file mode 100644 index 00000000000..c6802374571 --- /dev/null +++ b/dts/bindings/serial/espressif,esp32-lpuart.yaml @@ -0,0 +1,40 @@ +description: ESP32 Low Power UART + +compatible: "espressif,esp32-lpuart" + +include: uart-controller.yaml + +properties: + reg: + required: true + + tx-pin: + type: int + default: 5 + enum: + - 5 + description: In ESP32-C6, TX pin is fixed to GPIO5 + + rx-pin: + type: int + default: 4 + enum: + - 4 + description: In ESP32-C6, RX pin is fixed to GPIO4 + + rts-pin: + type: int + default: 2 + enum: + - 2 + description: In ESP32-C6, RTS pin is fixed to GPIO2 + + cts-pin: + type: int + default: 3 + enum: + - 3 + description: In ESP32-C6, CTS pin is fixed to GPIO3 + + current-speed: + type: int diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi index 590630eafde..840ca3ba7b8 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -274,6 +274,13 @@ current-speed = <115200>; }; + lp_uart: uart@600b1400 { + compatible = "espressif,esp32-lpuart"; + reg = <0x600b1400 DT_SIZE_K(4)>; + status = "disabled"; + current-speed = <115200>; + }; + usb_serial: uart@6000f000 { compatible = "espressif,esp32-usb-serial"; reg = <0x6000F000 0x1000>; diff --git a/dts/riscv/espressif/esp32c6/esp32c6_lpcore.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_lpcore.dtsi index 240000f12eb..319bc571805 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_lpcore.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_lpcore.dtsi @@ -59,5 +59,12 @@ /* Flash size is specified in SOC/SIP dtsi */ }; }; + + lp_uart: uart@600b1400 { + compatible = "espressif,esp32-lpuart"; + reg = <0x600b1400 DT_SIZE_K(4)>; + status = "disabled"; + }; + }; }; diff --git a/soc/espressif/esp32c6/default_lpcore.ld b/soc/espressif/esp32c6/default_lpcore.ld index b1fcd3c12b4..2730eaffbb4 100644 --- a/soc/espressif/esp32c6/default_lpcore.ld +++ b/soc/espressif/esp32c6/default_lpcore.ld @@ -54,6 +54,8 @@ SECTIONS __text_region_start = ABSOLUTE(.); *(.text) *(.text*) + *(.iram1) + *(.iram1.*) __text_region_end = ABSOLUTE(.); } >ram @@ -104,11 +106,13 @@ SECTIONS .bss ALIGN(4) : { + __bss_start = .; *(.bss) *(.bss*) *(.sbss) *(.sbss*) PROVIDE(end = .); + __bss_end = .; _heap_sentry = .; } >ram