From dc6d0fd068c0d5382102e3485399e81ba3bd3d51 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Wed, 17 Sep 2025 14:07:58 +0800 Subject: [PATCH 01/10] MAINTAINERS: Add maintainers for hal_xhsc. Add TrackingRobot as maintainers for hal_xhsc. Signed-off-by: Yongbing Liu --- MAINTAINERS.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 6b839a8195a7c..d92265965831b 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -5732,6 +5732,15 @@ West: files: - modules/Kconfig.wurthelektronik +"West project: hal_xhsc": + status: maintained + maintainers: + - XH-YongbingLiu + files: + - modules/Kconfig.xhsc + labels: + - "platform: XHSC" + "West project: hal_xtensa": status: maintained maintainers: From 134c857bb49140e094925c80ad6c3b2a1f76fcc5 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:48:01 +0800 Subject: [PATCH 02/10] manifest: Add hal_xhsc to HAL group. Add HAL repository information for the first supported HC32F4A0_EVB and HC32F460_EVB. Signed-off-by: Yongbing Liu --- west.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/west.yml b/west.yml index 8ddf3001a042d..cc15e225cc715 100644 --- a/west.yml +++ b/west.yml @@ -279,6 +279,11 @@ manifest: path: modules/hal/wurthelektronik groups: - hal + - name: hal_xhsc + revision: a84e04900616f68097d80cda2e89eaa8af3afadd + path: modules/hal/xhsc + groups: + - hal - name: hal_xtensa revision: ba3f1ce6b066c3e40a8e6cad3fba0068ecfcd4ba path: modules/hal/xtensa From 4e1d4ea98ca630caaec9d09c7b3737dc68d20872 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:54:40 +0800 Subject: [PATCH 03/10] drivers: pinctrl: Add support for HC32F4A0 This is the initial commit to support pinctrl driver for XHSC HC32F4A0 Signed-off-by: Yongbing Liu --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Kconfig.hc32 | 9 ++ drivers/pinctrl/pinctrl_hc32.c | 143 ++++++++++++++++++ dts/bindings/pinctrl/xhsc,hc32-pinctrl.yaml | 57 +++++++ .../zephyr/dt-bindings/pinctrl/hc32-pinctrl.h | 142 +++++++++++++++++ 6 files changed, 353 insertions(+) create mode 100644 drivers/pinctrl/Kconfig.hc32 create mode 100644 drivers/pinctrl/pinctrl_hc32.c create mode 100644 dts/bindings/pinctrl/xhsc,hc32-pinctrl.yaml create mode 100644 include/zephyr/dt-bindings/pinctrl/hc32-pinctrl.h diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index ea46edf46dc5f..10970aa4f845d 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -58,6 +58,7 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_REALTEK_RTS5912 pinctrl_realtek_rts5 zephyr_library_sources_ifdef(CONFIG_PINCTRL_WCH_20X_30X_AFIO pinctrl_wch_20x_30x_afio.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_WCH_00X_AFIO pinctrl_wch_00x_afio.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_SF32LB52X pinctrl_sf32lb52x.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_HC32 pinctrl_hc32.c) add_subdirectory(renesas) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 9050f3ef5c998..e624f9f69af65 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -88,6 +88,7 @@ source "drivers/pinctrl/Kconfig.realtek_rts5912" source "drivers/pinctrl/Kconfig.wch_20x_30x_afio" source "drivers/pinctrl/Kconfig.wch_00x_afio" source "drivers/pinctrl/Kconfig.sf32lb52x" +source "drivers/pinctrl/Kconfig.hc32" rsource "renesas/Kconfig" diff --git a/drivers/pinctrl/Kconfig.hc32 b/drivers/pinctrl/Kconfig.hc32 new file mode 100644 index 0000000000000..9e5a5763e1062 --- /dev/null +++ b/drivers/pinctrl/Kconfig.hc32 @@ -0,0 +1,9 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_HC32 + bool "Pin controller driver for xhsc hc32 processors" + default y + depends on DT_HAS_XHSC_HC32_PINCTRL_ENABLED + help + Enable pin controller driver for xhsc hc32 processors. diff --git a/drivers/pinctrl/pinctrl_hc32.c b/drivers/pinctrl/pinctrl_hc32.c new file mode 100644 index 0000000000000..fe388adf63c32 --- /dev/null +++ b/drivers/pinctrl/pinctrl_hc32.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define HC32_GPIO_PORT_VALID(nodelabel) \ + (DT_NODE_EXISTS(DT_NODELABEL(nodelabel))) \ + ? (DT_NODE_HAS_STATUS(DT_NODELABEL(nodelabel), okay)) \ + : (0) + +/** + * @brief Array containing bool value to each GPIO port. + * + * Entries will be 0 if the GPIO port is not enabled. + */ +static volatile uint8_t gpio_ports_valid[] = { + HC32_GPIO_PORT_VALID(gpioa), HC32_GPIO_PORT_VALID(gpiob), HC32_GPIO_PORT_VALID(gpioc), + HC32_GPIO_PORT_VALID(gpiod), HC32_GPIO_PORT_VALID(gpioe), HC32_GPIO_PORT_VALID(gpiof), + HC32_GPIO_PORT_VALID(gpiog), HC32_GPIO_PORT_VALID(gpioh), HC32_GPIO_PORT_VALID(gpioi), +}; + +static inline uint8_t HC32_get_port(uint8_t port_num) +{ +#if defined(HC32F460) + if ('H' == (port_num + 'A')) { + return GPIO_PORT_H; + } else { + return port_num; + } +#elif defined(HC32F4A0) + return port_num; +#endif +} + +static inline bool HC32_pin_is_valid(uint16_t pin) +{ + return ((pin & GPIO_PIN_ALL) == 0); +} + +static int hc32_pin_configure(const uint32_t pin_mux) +{ + uint8_t port_num = HC32_PORT(pin_mux); + uint16_t pin_num = BIT(HC32_PIN(pin_mux)); + uint8_t mode = HC32_MODE(pin_mux); + uint16_t func_num = HC32_FUNC_NUM(pin_mux); + stc_gpio_init_t stc_gpio_init; + + GPIO_StructInit(&stc_gpio_init); + + if ((gpio_ports_valid[port_num] != 1) || (HC32_pin_is_valid(pin_num))) { + return -EINVAL; + } + port_num = HC32_get_port(port_num); + + switch (mode) { + case HC32_ANALOG: + stc_gpio_init.u16PinAttr = PIN_ATTR_ANALOG; + goto end; + + case HC32_GPIO: + func_num = 0; + stc_gpio_init.u16PinAttr = PIN_ATTR_DIGITAL; + if (HC32_INPUT_ENABLE == HC32_PIN_EN_DIR(pin_mux)) { + /* input */ + stc_gpio_init.u16PinDir = PIN_DIR_IN; + } else { + /* output */ + stc_gpio_init.u16PinDir = PIN_DIR_OUT; + if (HC32_OUTPUT_HIGH == HC32_OUT_LEVEL(pin_mux)) { + stc_gpio_init.u16PinState = PIN_STAT_SET; + } + } + break; + + case HC32_FUNC: + GPIO_SetFunc(port_num, pin_num, func_num); + break; + + case HC32_SUBFUNC: + GPIO_SetSubFunc(func_num); + GPIO_SubFuncCmd(port_num, pin_num, ENABLE); + break; + + default: + break; + } + + if (HC32_PULL_UP == HC32_PIN_BIAS(pin_mux)) { + stc_gpio_init.u16PullUp = PIN_PU_ON; + } + if (HC32_PUSH_PULL == HC32_PIN_DRV(pin_mux)) { + stc_gpio_init.u16PinOutputType = PIN_OUT_TYPE_CMOS; + } else { + stc_gpio_init.u16PinOutputType = PIN_OUT_TYPE_NMOS; + } + + switch (HC32_PIN_DRIVER_STRENGTH(pin_mux)) { + case HC32_DRIVER_STRENGTH_LOW: + stc_gpio_init.u16PinDrv = PIN_LOW_DRV; + break; + + case HC32_DRIVER_STRENGTH_MEDIUM: + stc_gpio_init.u16PinDrv = PIN_MID_DRV; + break; + + case HC32_DRIVER_STRENGTH_HIGH: + stc_gpio_init.u16PinDrv = PIN_HIGH_DRV; + break; + + default: + break; + } +#if defined(HC32F4A0) + stc_gpio_init.u16PinInputType = + (HC32_CINSEL(pin_mux) == HC32_CINSEL_SCHMITT) ? PIN_IN_TYPE_SMT : PIN_IN_TYPE_CMOS; +#endif + + stc_gpio_init.u16Invert = + (HC32_INVERT_ENABLE == HC32_INVERT(pin_mux)) ? PIN_INVT_ON : PIN_INVT_OFF; + +end: + return GPIO_Init(port_num, pin_num, &stc_gpio_init); +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + int ret = 0; + + ARG_UNUSED(reg); + + for (uint8_t i = 0U; i < pin_cnt; i++) { + ret = hc32_pin_configure(pins[i]); + if (ret < 0) { + return ret; + } + } + + return 0; +} diff --git a/dts/bindings/pinctrl/xhsc,hc32-pinctrl.yaml b/dts/bindings/pinctrl/xhsc,hc32-pinctrl.yaml new file mode 100644 index 0000000000000..f088c4a5db84a --- /dev/null +++ b/dts/bindings/pinctrl/xhsc,hc32-pinctrl.yaml @@ -0,0 +1,57 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +title: XHSC HC32 Pinctrl + +description: | + Based on pincfg-node.yaml binding. + + Note: `bias-disable` and `drive-push-pull` are default pin configurations. + They will be applied in case no `bias-foo` or `driver-bar` properties + are set. + +compatible: "xhsc,hc32-pinctrl" +include: base.yaml + +child-binding: + description: | + hc32 pin controller pin configuration state nodes. + child-binding: + description: + hc32 pin controller pin configuration group. + + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-pull-up + - drive-push-pull + - drive-open-drain + - input-enable + - output-enable + - output-high + - output-low + - input-schmitt-enable + - input-schmitt-disable + + properties: + pinmux: + required: true + type: array + description: | + Each array element represents pin muxing information of an individual + pin. + + drive-strength: + type: string + default: "low" + enum: + - "low" + - "medium" + - "high" + description: | + Pin output drive strength. + 0 (low) - sets pin to low drive strength, default set. + 1 (medium) - sets pin to medium drive strength + 2 (high) - sets pin to high drive strength + Default is "low" because it is the reset value. diff --git a/include/zephyr/dt-bindings/pinctrl/hc32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/hc32-pinctrl.h new file mode 100644 index 0000000000000..77176e6a0fd17 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/hc32-pinctrl.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_HC32_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_HC32_PINCTRL_H_ + +#define HC32_PORT(_mux) (((_mux) >> HC32_PORT_SHIFT) & HC32_PORT_MSK) + +#define HC32_PIN(_mux) (((_mux) >> HC32_PIN_SHIFT) & HC32_PIN_MSK) + +#define HC32_MODE(_mux) (((_mux) >> HC32_MODE_SHIFT) & HC32_MODE_MSK) + +#define HC32_FUNC_NUM(_mux) (((_mux) >> HC32_FUNC_SHIFT) & HC32_FUNC_MSK) + +#define HC32_PIN_BIAS(_mux) (_mux & HC32_PUR_MSK) +#define HC32_PIN_DRV(_mux) (_mux & HC32_NOD_MSK) +#define HC32_OUT_LEVEL(_mux) (_mux & HC32_OTYPE_MSK) +#define HC32_PIN_EN_DIR(_mux) (_mux & HC32_DIREN_MSK) +#define HC32_PIN_DRIVER_STRENGTH(_mux) (_mux & HC32_STRENGTH_MSK) +#define HC32_INVERT(_mux) (_mux & HC32_INVERT_MSK) +#define HC32_CINSEL(_mux) (_mux & HC32_CINSEL_MSK) + +/* pinmux filed in pinctrl_soc_pin*/ +/* + * @brief Pin modes + */ +#define HC32_ANALOG 0x00U +#define HC32_GPIO 0x01U +#define HC32_FUNC 0x02U +#define HC32_SUBFUNC 0x03U + +/* + * @brief Macro to generate pinmux int using port, pin number and mode arguments + * This is inspired from Linux equivalent st,HC32f429-pinctrl binding + */ +#define HC32_FUNC_SHIFT 10U +#define HC32_FUNC_MSK 0xFFU +#define HC32_MODE_SHIFT 8U +#define HC32_MODE_MSK 0x03U +#define HC32_PIN_SHIFT 4U +#define HC32_PIN_MSK 0x0FU +#define HC32_PORT_SHIFT 0U +#define HC32_PORT_MSK 0x0FU + +/* + * @brief pinmux bit field. + * + * Fields: + * - cfg [24:31] + * - func_num [ 10 :17] + * - mode [ 8 : 9 ] + * - pin [ 4 : 7 ] + * - port [ 0 : 3 ] + * + * @param port Port ('A'..'E', 'H') + * @param pin Pin (0..15) + * @param mode Mode (ANALOG, FUC, SUBFUC). + * @param func_num range:0--63. + * @param cfg configuration for pin + */ +#define HC32_PINMUX(port, pin, mode, func_num, cfg) \ + (((((port) - 'A') & HC32_PORT_MSK) << HC32_PORT_SHIFT) | \ + (((pin) & HC32_PIN_MSK) << HC32_PIN_SHIFT) | \ + (((HC32_##mode) & HC32_MODE_MSK) << HC32_MODE_SHIFT) | \ + (((func_num) & HC32_FUNC_MSK) << HC32_FUNC_SHIFT) | (cfg)) + +/* cfg filed in pinctrl_soc_pin*/ +/* + * @brief Definitions cfg bit pos and mask + */ +#define HC32_NO_PULL (0U << HC32_PUR_SHIFT) +#define HC32_PULL_UP (1U << HC32_PUR_SHIFT) + +#define HC32_PUSH_PULL (0U << HC32_NOD_SHIFT) +#define HC32_OPEN_DRAIN (1U << HC32_NOD_SHIFT) + +#define HC32_OUTPUT_LOW (0U << HC32_OTYPE_SHIFT) +#define HC32_OUTPUT_HIGH (1U << HC32_OTYPE_SHIFT) + +#define HC32_INPUT_ENABLE (0U << HC32_DIREN_SHIFT) +#define HC32_OUTPUT_ENABLE (1U << HC32_DIREN_SHIFT) + +#define HC32_DRIVER_STRENGTH_LOW (0U << HC32_STRENGTH_SHIFT) +#define HC32_DRIVER_STRENGTH_MEDIUM (1U << HC32_STRENGTH_SHIFT) +#define HC32_DRIVER_STRENGTH_HIGH (2U << HC32_STRENGTH_SHIFT) + +#define HC32_INVERT_DISABLE (0U << HC32_INVERT_SHIFT) +#define HC32_INVERT_ENABLE (1U << HC32_INVERT_SHIFT) + +#define HC32_CINSEL_SCHMITT (0U << HC32_CINSEL_SHIFT) +#define HC32_CINSEL_CMOS (1U << HC32_CINSEL_SHIFT) + +/* + * @brief Pin cfg bit field in pinmux. + * + * Fields: + * - CINSEL [31] + * - INVERT [30] + * - STRENGTH [28:29] + * - DIREN [ 27] + * - OTYPE [ 26 ] + * - NOD [ 25 ] + * - PUR [ 24 ] + */ + +/* PUR field position. */ +#define HC32_PUR_SHIFT 24U +/* PUR field mask. */ +#define HC32_PUR_MSK (1U << HC32_PUR_SHIFT) + +/* NOD field position. */ +#define HC32_NOD_SHIFT 25U +/* NOD field mask. */ +#define HC32_NOD_MSK (1U << HC32_NOD_SHIFT) + +/* Out default level field position. */ +#define HC32_OTYPE_SHIFT 26U +/* Out default level field mask. */ +#define HC32_OTYPE_MSK (1U << HC32_OTYPE_SHIFT) + +/* DIREN field position. */ +#define HC32_DIREN_SHIFT 27U +/* DIREN(I/O select) field mask. */ +#define HC32_DIREN_MSK (1U << HC32_DIREN_SHIFT) + +/* STRENGTH field position. */ +#define HC32_STRENGTH_SHIFT 28U +/* STRENGTH field mask. */ +#define HC32_STRENGTH_MSK (3U << HC32_STRENGTH_SHIFT) + +/* I/O invert data */ +#define HC32_INVERT_SHIFT 30U +#define HC32_INVERT_MSK (1U << HC32_INVERT_SHIFT) + +/* schmitt or CMOS select */ +#define HC32_CINSEL_SHIFT 31U +#define HC32_CINSEL_MSK (1U << HC32_CINSEL_SHIFT) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_HC32_PINCTRL_H_ */ From 2d5dccd60cf33bfd5e9f2f9356035ed27e1c732b Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:53:14 +0800 Subject: [PATCH 04/10] drivers: gpio: Add support for HC32F4A0 This is the initial commit to support gpio driver for XHSC HC32F4A0 Signed-off-by: Yongbing Liu --- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 1 + drivers/gpio/Kconfig.hc32 | 10 + drivers/gpio/gpio_hc32.c | 379 ++++++++++++++++++++++++++ drivers/gpio/gpio_hc32.h | 41 +++ dts/bindings/gpio/xhsc,hc32-gpio.yaml | 19 ++ 6 files changed, 451 insertions(+) create mode 100644 drivers/gpio/Kconfig.hc32 create mode 100644 drivers/gpio/gpio_hc32.c create mode 100644 drivers/gpio/gpio_hc32.h create mode 100644 dts/bindings/gpio/xhsc,hc32-gpio.yaml diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 6fb97fc1d0bb8..b6e484b6a31ba 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -36,6 +36,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_FXL6408 gpio_fxl6408.c) zephyr_library_sources_ifdef(CONFIG_GPIO_GD32 gpio_gd32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_GECKO gpio_gecko.c) zephyr_library_sources_ifdef(CONFIG_GPIO_GRGPIO2 gpio_grgpio2.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_HC32 gpio_hc32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_IMX gpio_imx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INTEL gpio_intel.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6c4376c7feeae..e46cb6de694c3 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -126,6 +126,7 @@ source "drivers/gpio/Kconfig.fxl6408" source "drivers/gpio/Kconfig.gd32" source "drivers/gpio/Kconfig.gecko" source "drivers/gpio/Kconfig.grgpio" +source "drivers/gpio/Kconfig.hc32" source "drivers/gpio/Kconfig.ifx_cat1" source "drivers/gpio/Kconfig.imx" source "drivers/gpio/Kconfig.intel" diff --git a/drivers/gpio/Kconfig.hc32 b/drivers/gpio/Kconfig.hc32 new file mode 100644 index 0000000000000..b45ef2a3fcf53 --- /dev/null +++ b/drivers/gpio/Kconfig.hc32 @@ -0,0 +1,10 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_HC32 + bool "GPIO Driver for HC32 MCUs" + default y + depends on DT_HAS_XHSC_HC32_GPIO_ENABLED + select HC32_LL_GPIO + help + Enable GPIO driver for HC32 line of MCUs diff --git a/drivers/gpio/gpio_hc32.c b/drivers/gpio/gpio_hc32.c new file mode 100644 index 0000000000000..4eb352f4a5b63 --- /dev/null +++ b/drivers/gpio/gpio_hc32.c @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT xhsc_hc32_gpio + +#include + +#include +#include +#include +#include "gpio_hc32.h" +#include +#include + +/** + * @brief Common GPIO driver for HC32 MCUs. + */ + +/** + * @brief EXTI interrupt callback + */ +static void gpio_hc32_isr(int line, void *arg) +{ + struct gpio_hc32_data *data = arg; + + EXTINT_ClearExtIntStatus(BIT(line)); + gpio_fire_callbacks(&data->cb, data->dev, BIT(line)); +} + +/** + * @brief Calculate the on/off status of the exit interrupt by the given flags + * + */ +static int gpio_hc32_cfg2ll_intr_on(gpio_flags_t flags) +{ + int ext_int = PIN_EXTINT_OFF; + + if ((flags & GPIO_INT_MASK) != 0) { + if ((flags & GPIO_INT_ENABLE) != 0) { + ext_int = PIN_EXTINT_ON; + } + } + + return ext_int; +} + +/** + * @brief Calculate interrupt trigger type by the given flags + * + */ +static int gpio_hc32_cfg2ll_intr_trig(gpio_flags_t flags) +{ + int trigger = HC32_EXTINT_TRIG_NOT_SUPPT; + + if ((flags & GPIO_INT_EDGE_BOTH) == GPIO_INT_EDGE_BOTH) { + trigger = HC32_EXTINT_TRIG_BOTH; + } else if ((flags & GPIO_INT_EDGE_RISING) == GPIO_INT_EDGE_RISING) { + trigger = HC32_EXTINT_TRIG_RISING; + } else if ((flags & GPIO_INT_EDGE_FALLING) == GPIO_INT_EDGE_FALLING) { + trigger = HC32_EXTINT_TRIG_FALLING; + } else if ((flags & GPIO_INT_LEVEL_LOW) == GPIO_INT_LEVEL_LOW) { + trigger = HC32_EXTINT_TRIG_LOW_LVL; + } else { + /* Nothing to do */ + } + + return trigger; +} + +/** + * @brief Calculate gpio output type + * + */ +static int gpio_hc32_cfg2ll_output_type(gpio_flags_t flags, uint16_t *out_type) +{ + if ((flags & GPIO_SINGLE_ENDED) != 0) { + if (flags & GPIO_LINE_OPEN_DRAIN) { + *out_type = PIN_OUT_TYPE_NMOS; + } else { + /* Output can't be open source */ + return -ENOTSUP; + } + } else { + *out_type = PIN_OUT_TYPE_CMOS; + } + + return 0; +} + +/** + * @brief Calculate gpio output status + * + */ +static int gpio_hc32_cfg2ll_output_status(gpio_flags_t flags, uint16_t *out_status) +{ + int ret = 0; + + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) { + *out_status = PIN_STAT_SET; + } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) { + *out_status = PIN_STAT_RST; + } else { + if ((flags & GPIO_OUTPUT_INIT_LOGICAL) != 0U) { + /* Don't support logical set */ + ret = -ENOTSUP; + } + } + + return ret; +} + +/** + * @brief Configure pin or port + */ +static int gpio_hc32_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + int intr_trigger; + const struct gpio_hc32_config *cfg = dev->config; + const struct gpio_hc32_data *data = (struct gpio_hc32_data *)dev->data; + const struct device *intc_dev = data->intc_dev; + const struct hc32_extint_driver_api *extint_api = intc_dev->api; + uint8_t hc32_port = cfg->port; + stc_gpio_init_t stc_gpio_init; + + GPIO_StructInit(&stc_gpio_init); + + /* GPIO input/output configuration flags */ + if ((flags & GPIO_OUTPUT) != 0U) { + /* output */ + stc_gpio_init.u16PinDir = PIN_DIR_OUT; + + if (0 != gpio_hc32_cfg2ll_output_type(flags, &stc_gpio_init.u16PinOutputType)) { + return -ENOTSUP; + } + + if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) { + /* No pull up or down in out mode*/ + return -ENOTSUP; + } + + if (0 != gpio_hc32_cfg2ll_output_status(flags, &stc_gpio_init.u16PinState)) { + /* Don't support logical set */ + return -ENOTSUP; + } + } else if ((flags & GPIO_INPUT) != 0) { + /* Input */ + stc_gpio_init.u16PinDir = PIN_DIR_IN; + + if ((flags & GPIO_PULL_UP) != 0) { + stc_gpio_init.u16PullUp = PIN_PU_ON; + } else { + if ((flags & GPIO_PULL_DOWN) != 0) { + /* No pull down */ + return -ENOTSUP; + } + } + } else { + /* Deactivated: Analog */ + stc_gpio_init.u16PinAttr = PIN_ATTR_ANALOG; + } + + /* GPIO interrupt configuration flags */ + stc_gpio_init.u16ExtInt = gpio_hc32_cfg2ll_intr_on(flags); + if (PIN_EXTINT_ON == stc_gpio_init.u16ExtInt) { + intr_trigger = gpio_hc32_cfg2ll_intr_trig(flags); + if (HC32_EXTINT_TRIG_NOT_SUPPT == intr_trigger) { + stc_gpio_init.u16ExtInt = PIN_EXTINT_OFF; + return -ENOTSUP; + } + extint_api->extint_set_trigger(intc_dev, pin, intr_trigger); + } + + return GPIO_Init(hc32_port, BIT(pin), &stc_gpio_init); +} + +#if defined(CONFIG_GPIO_GET_CONFIG) +static int gpio_hc32_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *flags) +{ + const struct gpio_hc32_config *cfg = dev->config; + uint16_t PCR_value = *(cfg->base + pin * 4); + gpio_flags_t hc32_flag = 0; + + /* only support input/output cfg */ + if ((PCR_value & GPIO_PCR_DDIS) == 0U) { + if (((PCR_value)&GPIO_PCR_POUTE) != 0U) { + hc32_flag |= GPIO_OUTPUT; + if ((PCR_value & GPIO_PCR_POUT) != 0U) { + hc32_flag |= GPIO_OUTPUT_INIT_HIGH; + } else { + hc32_flag |= GPIO_OUTPUT_INIT_LOW; + } + } else { + hc32_flag |= GPIO_INPUT; + if (((PCR_value)&GPIO_PCR_PUU) != 0U) { + hc32_flag |= GPIO_PULL_UP; + } + } + } else { + hc32_flag &= ~(GPIO_OUTPUT | GPIO_INPUT); + } + + if ((PCR_value & GPIO_PCR_NOD) != 0U) { + hc32_flag |= GPIO_OPEN_DRAIN; + } + + *flags = hc32_flag; + return 0; +} +#endif + +static int gpio_hc32_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_hc32_config *cfg = dev->config; + uint8_t port = cfg->port; + + *value = (uint32_t)GPIO_ReadInputPort(port); + + return 0; +} + +static int gpio_hc32_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_hc32_config *cfg = dev->config; + uint8_t port = cfg->port; + + GPIO_WritePort(port, mask); + + return 0; +} + +static int gpio_hc32_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_hc32_config *cfg = dev->config; + uint8_t port = cfg->port; + + GPIO_SetPins(port, pins); + + return 0; +} + +static int gpio_hc32_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_hc32_config *cfg = dev->config; + uint8_t port = cfg->port; + + GPIO_ResetPins(port, pins); + + return 0; +} + +static int gpio_hc32_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_hc32_config *cfg = dev->config; + uint8_t port = cfg->port; + + GPIO_TogglePins(port, pins); + + return 0; +} + +static int gpio_hc32_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct gpio_hc32_config *cfg = dev->config; + struct gpio_hc32_data *data = (struct gpio_hc32_data *)dev->data; + const struct device *intc_dev = data->intc_dev; + const struct hc32_extint_driver_api *extint_api = intc_dev->api; + uint8_t port = cfg->port; + int trigger = 0; + int err = 0; + +#ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT + if (mode == GPIO_INT_MODE_DISABLE_ONLY) { + extint_api->extint_disable(port, pin); + return 0; + } else if (mode == GPIO_INT_MODE_ENABLE_ONLY) { + extint_api->extint_enable(port, pin); + return 0; + } +#endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */ + + switch (mode) { + case GPIO_INT_DISABLE: + extint_api->extint_disable(intc_dev, port, pin); + extint_api->extint_unset_cb(intc_dev, pin); + extint_api->extint_set_trigger(intc_dev, pin, HC32_EXTINT_TRIG_FALLING); + return 0; + + case GPIO_INT_MODE_LEVEL: + if (trig == GPIO_INT_TRIG_LOW) { + trigger = HC32_EXTINT_TRIG_LOW_LVL; + } else { + return -ENOTSUP; + } + break; + + case GPIO_INT_MODE_EDGE: + switch (trig) { + case GPIO_INT_TRIG_BOTH: + trigger = HC32_EXTINT_TRIG_BOTH; + break; + case GPIO_INT_TRIG_HIGH: + trigger = HC32_EXTINT_TRIG_RISING; + break; + case GPIO_INT_TRIG_LOW: + /* Default trigger is falling edge */ + default: + trigger = HC32_EXTINT_TRIG_FALLING; + break; + } + break; + + default: + break; + } + + extint_api->extint_set_trigger(intc_dev, pin, trigger); + err = extint_api->extint_set_cb(intc_dev, pin, gpio_hc32_isr, (void *)data); + extint_api->extint_enable(intc_dev, port, pin); + + return err; +} + +static int gpio_hc32_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + struct gpio_hc32_data *data = dev->data; + + return gpio_manage_callback(&data->cb, callback, set); +} + +static uint32_t gpio_hc32_get_pending_int(const struct device *dev) +{ + return 0; +} + +static const struct gpio_driver_api gpio_hc32_driver = { + .pin_configure = gpio_hc32_configure, +#if defined(CONFIG_GPIO_GET_CONFIG) + .pin_get_config = gpio_hc32_get_config, +#endif /* CONFIG_GPIO_GET_CONFIG */ + .port_get_raw = gpio_hc32_port_get_raw, + .port_set_masked_raw = gpio_hc32_port_set_masked_raw, + .port_set_bits_raw = gpio_hc32_port_set_bits_raw, + .port_clear_bits_raw = gpio_hc32_port_clear_bits_raw, + .port_toggle_bits = gpio_hc32_port_toggle_bits, + .pin_interrupt_configure = gpio_hc32_pin_interrupt_configure, + .manage_callback = gpio_hc32_manage_callback, + .get_pending_int = gpio_hc32_get_pending_int, +}; + +static int gpio_hc32_init(const struct device *dev) +{ + struct gpio_hc32_data *data = dev->data; + + data->dev = dev; + return 0; +} + +#define GPIO_HC32_DEFINE(n) \ + static const struct gpio_hc32_config gpio_hc32_cfg_##n = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .base = (uint16_t *)DT_INST_REG_ADDR(n), \ + .port = n, \ + }; \ + static struct gpio_hc32_data gpio_hc32_data_##n = { \ + .intc_dev = DEVICE_DT_GET(DT_INST(0, xhsc_hc32_extint)), \ + }; \ + DEVICE_DT_INST_DEFINE(n, gpio_hc32_init, NULL, &gpio_hc32_data_##n, &gpio_hc32_cfg_##n, \ + POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, &gpio_hc32_driver); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_HC32_DEFINE) diff --git a/drivers/gpio/gpio_hc32.h b/drivers/gpio/gpio_hc32.h new file mode 100644 index 0000000000000..f452f41a64e9a --- /dev/null +++ b/drivers/gpio/gpio_hc32.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_GPIO_GPIO_HC32_H_ +#define ZEPHYR_DRIVERS_GPIO_GPIO_HC32_H_ + +/** + * @file header for HC32 GPIO + */ + +#include +#include +/** + * @brief configuration of GPIO device + */ +struct gpio_hc32_config { + struct gpio_driver_config common; + /* port PCRxy register base address */ + uint16_t *base; + /* IO port */ + uint8_t port; +}; + +/** + * @brief driver data + */ +struct gpio_hc32_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + /* Device's owner of this data */ + const struct device *dev; + /* External interrupt device */ + const struct device *intc_dev; + /* User ISR cb */ + sys_slist_t cb; +}; + +#endif /* ZEPHYR_DRIVERS_GPIO_GPIO_HC32_H_ */ diff --git a/dts/bindings/gpio/xhsc,hc32-gpio.yaml b/dts/bindings/gpio/xhsc,hc32-gpio.yaml new file mode 100644 index 0000000000000..a421fd778c5c7 --- /dev/null +++ b/dts/bindings/gpio/xhsc,hc32-gpio.yaml @@ -0,0 +1,19 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: XHSC HC32 GPIO + +compatible: "xhsc,hc32-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags From 9acba32f64ccfb759faa24ef66526d6ea6d10e40 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:51:08 +0800 Subject: [PATCH 05/10] drivers: clock_control: Add support for HC32F4A0 This is the initial commit to support clock_control driver for XHSC HC32F4A0 Signed-off-by: Yongbing Liu --- drivers/clock_control/CMakeLists.txt | 1 + drivers/clock_control/Kconfig | 2 + drivers/clock_control/Kconfig.hc32 | 7 + drivers/clock_control/clock_control_hc32.c | 417 ++++++++++++++++++ drivers/clock_control/clock_control_hc32.h | 86 ++++ dts/bindings/clock/xhsc,hc32-bus-fcg.yaml | 19 + .../clock/xhsc,hc32-clock-control.yaml | 15 + dts/bindings/clock/xhsc,hc32-clock-hrc.yaml | 8 + dts/bindings/clock/xhsc,hc32-clock-mrc.yaml | 8 + dts/bindings/clock/xhsc,hc32-clock-pll.yaml | 53 +++ dts/bindings/clock/xhsc,hc32-clock-sys.yaml | 107 +++++ dts/bindings/clock/xhsc,hc32-clock-xtal.yaml | 8 + .../clock/xhsc,hc32-clock-xtal32.yaml | 19 + .../clock_control/hc32_clock_control.h | 122 +++++ .../dt-bindings/clock/hc32f4_common_clock.h | 35 ++ .../zephyr/dt-bindings/clock/hc32f4a0_clock.h | 127 ++++++ 16 files changed, 1034 insertions(+) create mode 100644 drivers/clock_control/Kconfig.hc32 create mode 100644 drivers/clock_control/clock_control_hc32.c create mode 100644 drivers/clock_control/clock_control_hc32.h create mode 100644 dts/bindings/clock/xhsc,hc32-bus-fcg.yaml create mode 100644 dts/bindings/clock/xhsc,hc32-clock-control.yaml create mode 100644 dts/bindings/clock/xhsc,hc32-clock-hrc.yaml create mode 100644 dts/bindings/clock/xhsc,hc32-clock-mrc.yaml create mode 100644 dts/bindings/clock/xhsc,hc32-clock-pll.yaml create mode 100644 dts/bindings/clock/xhsc,hc32-clock-sys.yaml create mode 100644 dts/bindings/clock/xhsc,hc32-clock-xtal.yaml create mode 100644 dts/bindings/clock/xhsc,hc32-clock-xtal32.yaml create mode 100644 include/zephyr/drivers/clock_control/hc32_clock_control.h create mode 100644 include/zephyr/dt-bindings/clock/hc32f4_common_clock.h create mode 100644 include/zephyr/dt-bindings/clock/hc32f4a0_clock.h diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 659c058ef61a0..5619aaf6f57a1 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_ARM_SCMI clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_ESP32 clock_control_esp32.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK clock_control_fixed_rate.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_GD32 clock_control_gd32.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_HC32 clock_control_hc32.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_LITEX clock_control_litex.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_LPC11U6X clock_control_lpc11u6x.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MCHP_SAM_D5X_E5X clock_control_mchp_sam_d5x_e5x.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index e2c4a071ab09a..ba7806ff53aa4 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -122,4 +122,6 @@ source "drivers/clock_control/Kconfig.sf32lb_hxt48" source "drivers/clock_control/Kconfig.sf32lb_rcc" +source "drivers/clock_control/Kconfig.hc32" + endif # CLOCK_CONTROL diff --git a/drivers/clock_control/Kconfig.hc32 b/drivers/clock_control/Kconfig.hc32 new file mode 100644 index 0000000000000..a6620b13c5afd --- /dev/null +++ b/drivers/clock_control/Kconfig.hc32 @@ -0,0 +1,7 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_HC32 + bool "HC32 Clock Control" + default y + depends on DT_HAS_XHSC_HC32_CLOCK_CONTROL_ENABLED diff --git a/drivers/clock_control/clock_control_hc32.c b/drivers/clock_control/clock_control_hc32.c new file mode 100644 index 0000000000000..4e203ae6a0f33 --- /dev/null +++ b/drivers/clock_control/clock_control_hc32.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "clock_control_hc32.h" + +/** + * @defgroup EV_HC32F460_LQFP100_V2_XTAL_CONFIG EV_HC32F460_LQFP100_V2 XTAL Configure definition + * @{ + */ +#define BSP_XTAL_PORT (GPIO_PORT_H) +#define BSP_XTAL_IN_PIN (GPIO_PIN_01) +#define BSP_XTAL_OUT_PIN (GPIO_PIN_00) + +/** + * @defgroup EV_HC32F460_LQFP100_V2_XTAL32_CONFIG EV_HC32F460_LQFP100_V2 XTAL32 Configure definition + * @{ + */ +#define BSP_XTAL32_PORT (GPIO_PORT_C) +#define BSP_XTAL32_IN_PIN (GPIO_PIN_15) +#define BSP_XTAL32_OUT_PIN (GPIO_PIN_14) + +static void hc32_clock_stale(uint32_t flag) +{ + uint32_t stable_time = 0; + + while (RESET == CLK_GetStableStatus(flag)) { + if (stable_time++ >= 20000) { + break; + } + } +} + +#if HC32_XTAL_ENABLED +static void hc32_clock_xtal_init(void) +{ + stc_clock_xtal_init_t stc_xtal_init; + + GPIO_AnalogCmd(BSP_XTAL_PORT, BSP_XTAL_IN_PIN | BSP_XTAL_OUT_PIN, ENABLE); + + (void)CLK_XtalStructInit(&stc_xtal_init); + stc_xtal_init.u8Mode = CLK_XTAL_MD_OSC; + stc_xtal_init.u8Drv = XTAL_DRV; + stc_xtal_init.u8State = CLK_XTAL_ON; + stc_xtal_init.u8StableTime = CLK_XTAL_STB_2MS; + (void)CLK_XtalInit(&stc_xtal_init); + hc32_clock_stale(CLK_STB_FLAG_XTAL); +} +#endif /* HC32_XTAL_ENABLED */ + +#if HC32_XTAL32_ENABLED +static void hc32_clock_xtal32_init(void) +{ + stc_clock_xtal32_init_t stc_xtal32_init; + + (void)CLK_Xtal32StructInit(&stc_xtal32_init); + stc_xtal32_init.u8State = CLK_XTAL32_ON; + + if (1U == HC32_XTAL32_DRV) { + stc_xtal32_init.u8Drv = CLK_XTAL32_DRV_HIGH; + } else { + stc_xtal32_init.u8Drv = CLK_XTAL32_DRV_MID; + } + + stc_xtal32_init.u8Filter = CLK_XTAL32_FILTER_ALL_MD; + GPIO_AnalogCmd(BSP_XTAL32_PORT, BSP_XTAL32_IN_PIN | BSP_XTAL32_OUT_PIN, ENABLE); + (void)CLK_Xtal32Init(&stc_xtal32_init); +} +#endif /* HC32_XTAL32_ENABLED */ + +static void hc32_clock_hrc_init(void) +{ + CLK_HrcCmd(ENABLE); + hc32_clock_stale(CLK_STB_FLAG_HRC); +} + +static void hc32_clock_mrc_init(void) +{ + CLK_MrcCmd(ENABLE); +} + +static void hc32_clock_lrc_init(void) +{ + CLK_LrcCmd(ENABLE); +} + +#if HC32_PLL_ENABLED +static void hc32_clock_pll_init(void) +{ + stc_clock_pll_init_t stc_pll_init; + + (void)CLK_PLLStructInit(&stc_pll_init); + stc_pll_init.PLLCFGR = 0UL; + stc_pll_init.PLLCFGR_f.PLLM = (HC32_PLL_M_DIVISOR - 1UL); + stc_pll_init.PLLCFGR_f.PLLN = (HC32_PLL_N_MULTIPLIER - 1UL); + stc_pll_init.PLLCFGR_f.PLLP = (HC32_PLL_P_DIVISOR - 1UL); + stc_pll_init.PLLCFGR_f.PLLQ = (HC32_PLL_Q_DIVISOR - 1UL); + stc_pll_init.PLLCFGR_f.PLLR = (HC32_PLL_R_DIVISOR - 1UL); +#if HC32_PLL_SRC_XTAL + hc32_clock_xtal_init(); + stc_pll_init.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL; +#elif HC32_PLL_SRC_HRC + hc32_clock_hrc_init(); + stc_pll_init.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_HRC; +#endif + stc_pll_init.u8PLLState = CLK_PLL_ON; + (void)CLK_PLLInit(&stc_pll_init); + hc32_clock_stale(CLK_STB_FLAG_PLL); +} +#endif + +static void hc32_clk_conf(void) +{ +#if HC32_PLL_ENABLED + hc32_clock_pll_init(); +#endif +#if HC32_XTAL_ENABLED + hc32_clock_xtal_init(); +#endif +#if HC32_HRC_ENABLED + hc32_clock_hrc_init(); +#endif +#if HC32_MRC_ENABLED + hc32_clock_mrc_init(); +#endif +#if HC32_LRC_ENABLED + hc32_clock_lrc_init(); +#endif +#if HC32_XTAL32_ENABLED + hc32_clock_xtal32_init(); +#endif +} + +#if defined(HC32F460) +static uint8_t hc32_system_running_mode(uint32_t frequency) +{ + uint8_t running_mode; + + if (frequency >= 168000000) { + running_mode = 2; + } else { + if (frequency >= 8000000) { + running_mode = 1; + } else { + running_mode = 0; + } + } + + return running_mode; +} + +static void hc32_run_mode_switch(uint32_t old_freq, uint32_t new_freq) +{ + uint8_t old_run_mode; + uint8_t new_run_mode; + + new_run_mode = hc32_system_running_mode(new_freq); + old_run_mode = hc32_system_running_mode(old_freq); + + if (old_run_mode == 0) { + if (new_run_mode == 1) { + PWC_LowSpeedToHighSpeed(); + } else if (new_run_mode == 2) { + PWC_LowSpeedToHighPerformance(); + } else { + /* Nothing to do */ + } + } else if (old_run_mode == 1) { + if (new_run_mode == 0) { + PWC_HighSpeedToLowSpeed(); + } else if (new_run_mode == 2) { + PWC_HighSpeedToHighPerformance(); + } else { + /* Nothing to do */ + } + } else if (old_run_mode == 2) { + if (new_run_mode == 0) { + PWC_HighPerformanceToLowSpeed(); + } else if (new_run_mode == 1) { + PWC_HighPerformanceToHighSpeed(); + } else { + /* Nothing to do */ + } + } else { + /* Nothing to do */ + } +} +#elif defined(HC32F4A0) +static void hc32_run_mode_switch(uint32_t old_freq, uint32_t new_freq) +{ + uint8_t old_run_mode; + uint8_t new_run_mode; + + new_run_mode = (new_freq >= 8000000) ? 1 : 0; + old_run_mode = (old_freq >= 8000000) ? 1 : 0; + + if (new_run_mode > old_run_mode) { + PWC_LowSpeedToHighSpeed(); + } else if (new_run_mode < old_run_mode) { + PWC_HighSpeedToLowSpeed(); + } else { + ; + } +} +#endif + +static int hc32_clock_control_init(const struct device *dev) +{ + uint32_t old_core_freq; + uint32_t new_core_freq; + stc_clock_freq_t stc_clock_freq; + + ARG_UNUSED(dev); + CLK_GetClockFreq(&stc_clock_freq); + old_core_freq = stc_clock_freq.u32SysclkFreq; + /* Set bus clk div. */ + CLK_SetClockDiv(CLK_BUS_CLK_ALL, + (HC32_HCLK_DIV(HC32_HCLK_PRESCALER) | HC32_EXCLK_DIV(HC32_EXCLK_PRESCALER) | + HC32_PCLK(0, HC32_PCLK0_PRESCALER) | HC32_PCLK(1, HC32_PCLK1_PRESCALER) | + HC32_PCLK(2, HC32_PCLK2_PRESCALER) | HC32_PCLK(3, HC32_PCLK3_PRESCALER) | + HC32_PCLK(4, HC32_PCLK4_PRESCALER))); + + /* sram init include read/write wait cycle setting */ + SRAM_SetWaitCycle(SRAM_SRAM_ALL, SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1); + SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0); + + /* flash read wait cycle setting */ + (void)EFM_SetWaitCycle(EFM_WAIT_CYCLE); + /* 3 cycles for 126MHz ~ 200MHz */ + GPIO_SetReadWaitCycle(GPIO_RD_WAIT); + + hc32_clk_conf(); + +#if HC32_SYSCLK_SRC_PLL + CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL); +#elif HC32_SYSCLK_SRC_XTAL + CLK_SetSysClockSrc(CLK_SYSCLK_SRC_XTAL); +#elif HC32_SYSCLK_SRC_HRC + CLK_SetSysClockSrc(CLK_SYSCLK_SRC_HRC); +#elif HC32_SYSCLK_SRC_MRC + CLK_SetSysClockSrc(CLK_SYSCLK_SRC_MRC); +#endif + + CLK_GetClockFreq(&stc_clock_freq); + new_core_freq = stc_clock_freq.u32SysclkFreq; + hc32_run_mode_switch(old_core_freq, new_core_freq); + + return 0; +} + +static int hc32_clock_control_on(const struct device *dev, clock_control_subsys_t sub_system) +{ + struct hc32_modules_clock_sys *clk_sys = (struct hc32_modules_clock_sys *)sub_system; + const struct hc32_modules_clock_config *mod_conf = + (const struct hc32_modules_clock_config *)dev->config; + + if (IN_RANGE(clk_sys->fcg, HC32_CLK_FCG0, HC32_CLK_FCG3) == 0) { + return -ENOTSUP; + } + + sys_clear_bits(mod_conf->addr + HC32_CLK_MODULES_OFFSET(clk_sys->fcg), + HC32_CLK_MODULES_BIT(clk_sys->bits)); + + return 0; +} + +static int hc32_clock_control_off(const struct device *dev, clock_control_subsys_t sub_system) +{ + struct hc32_modules_clock_sys *clk_sys = (struct hc32_modules_clock_sys *)sub_system; + const struct hc32_modules_clock_config *mod_conf = + (const struct hc32_modules_clock_config *)dev->config; + + if (IN_RANGE(clk_sys->fcg, HC32_CLK_FCG0, HC32_CLK_FCG3) == 0) { + return -ENOTSUP; + } + + sys_set_bits(mod_conf->addr + HC32_CLK_MODULES_OFFSET(clk_sys->fcg), + HC32_CLK_MODULES_BIT(clk_sys->bits)); + + return 0; +} + +static int hc32_clock_control_get_subsys_rate(const struct device *dev, + clock_control_subsys_t sub_system, uint32_t *rate) +{ + struct hc32_modules_clock_sys *clk_sys = (struct hc32_modules_clock_sys *)sub_system; + + ARG_UNUSED(dev); + switch (clk_sys->bus) { +#if HC32_HRC_ENABLED + case HC32_CLK_SRC_HRC: + *rate = HC32_HRC_FREQ; + break; +#endif +#if HC32_MRC_ENABLED + case HC32_CLK_SRC_MRC: + *rate = HC32_MRC_FREQ; + break; +#endif +#if HC32_XTAL_ENABLED + case HC32_CLK_SRC_XTAL: + *rate = HC32_XTAL_FREQ; + break; +#endif +#if HC32_PLL_ENABLED + case HC32_CLK_SRC_PLL: + *rate = HC32_PLL_FREQ; + break; +#endif + case HC32_CLK_BUS_HCLK: + *rate = CORE_CLK_FREQ; + break; + case HC32_CLK_BUS_PCLK0: + *rate = PCLK0_FREQ; + break; + case HC32_CLK_BUS_PCLK1: + *rate = PCLK1_FREQ; + break; + case HC32_CLK_BUS_PCLK2: + *rate = PCLK2_FREQ; + break; + case HC32_CLK_BUS_PCLK3: + *rate = PCLK3_FREQ; + break; + case HC32_CLK_BUS_PCLK4: + *rate = PCLK4_FREQ; + break; + case HC32_SYS_CLK: + *rate = SYS_CLK_FREQ; + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static enum clock_control_status hc32_clock_control_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + struct hc32_modules_clock_sys *clk_sys = (struct hc32_modules_clock_sys *)sys; + const struct hc32_modules_clock_config *mod_conf = + (const struct hc32_modules_clock_config *)dev->config; + + if (IN_RANGE(clk_sys->fcg, HC32_CLK_FCG0, HC32_CLK_FCG3) == 0) { + return -CLOCK_CONTROL_STATUS_UNKNOWN; + } + + if (sys_test_bit(mod_conf->addr + HC32_CLK_MODULES_OFFSET(clk_sys->fcg), clk_sys->bits)) { + return CLOCK_CONTROL_STATUS_OFF; + } + + return CLOCK_CONTROL_STATUS_ON; +} + +static int hc32_clock_control_configure(const struct device *dev, clock_control_subsys_t sys, + void *data) +{ + uint32_t clk_sys = *(uint32_t *)sys; + uint32_t dat = *(uint32_t *)data; + + ARG_UNUSED(dev); + if (IN_RANGE(clk_sys, HC32_CLK_CONF_MIN, HC32_CLK_CONF_MAX) == 0) { + return -ENOTSUP; + } + switch (clk_sys) { + case HC32_CLK_CONF_PERI: + CLK_SetPeriClockSrc((uint16_t)dat); + break; + case HC32_CLK_CONF_USB: + CLK_SetUSBClockSrc((uint16_t)dat); + break; + case HC32_CLK_CONF_I2S: + CLK_SetI2SClockSrc((uint8_t)(dat >> 8), (uint8_t)dat); + break; + case HC32_CLK_CONF_TPIU: + CLK_SetTpiuClockDiv((uint8_t)dat & 0x03); + if ((uint8_t)dat & 0x80) { + CLK_TpiuClockCmd(ENABLE); + } else { + CLK_TpiuClockCmd(DISABLE); + } + break; + case HC32_CLK_CONF_SRC: + CLK_SetSysClockSrc((uint8_t)dat); + break; + case HC32_CLK_CONF_MCO: + CLK_MCOConfig(CLK_MCO1, (uint8_t)dat, CLK_MCO_DIV8); + CLK_MCOCmd(CLK_MCO1, ENABLE); + break; + default: + return -ENOTSUP; + } + return 0; +} + +static struct clock_control_driver_api hc32_clock_control_api = { + .on = hc32_clock_control_on, + .off = hc32_clock_control_off, + .get_rate = hc32_clock_control_get_subsys_rate, + .get_status = hc32_clock_control_get_status, + .configure = hc32_clock_control_configure, +}; + +static const struct hc32_modules_clock_config hc32_modules_clk = { + .addr = DT_REG_ADDR(DT_NODELABEL(bus_fcg)), +}; + +DEVICE_DT_DEFINE(DT_NODELABEL(clk_sys), &hc32_clock_control_init, NULL, NULL, &hc32_modules_clk, + PRE_KERNEL_1, 1, &hc32_clock_control_api); diff --git a/drivers/clock_control/clock_control_hc32.h b/drivers/clock_control/clock_control_hc32.h new file mode 100644 index 0000000000000..fafe2bbb52e5f --- /dev/null +++ b/drivers/clock_control/clock_control_hc32.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _HC32F4_CLOCK_ +#define _HC32F4_CLOCK_ + +#include +#include + +#if defined(HC32F460) +#define EFM_WAIT_CYCLE5_FREQ 168000000 +#define EFM_WAIT_CYCLE4_FREQ 132000000 +#define EFM_WAIT_CYCLE3_FREQ 99000000 +#define EFM_WAIT_CYCLE2_FREQ 66000000 +#define EFM_WAIT_CYCLE1_FREQ 33000000 +#elif defined(HC32F4A0) +#define EFM_WAIT_CYCLE5_FREQ 200000000 +#define EFM_WAIT_CYCLE4_FREQ 160000000 +#define EFM_WAIT_CYCLE3_FREQ 120000000 +#define EFM_WAIT_CYCLE2_FREQ 80000000 +#define EFM_WAIT_CYCLE1_FREQ 40000000 +#endif + +#if (CORE_CLK_FREQ > EFM_WAIT_CYCLE5_FREQ) +#define EFM_WAIT_CYCLE EFM_WAIT_CYCLE5 +#elif (CORE_CLK_FREQ > EFM_WAIT_CYCLE4_FREQ) +#define EFM_WAIT_CYCLE EFM_WAIT_CYCLE4 +#elif (CORE_CLK_FREQ > EFM_WAIT_CYCLE3_FREQ) +#define EFM_WAIT_CYCLE EFM_WAIT_CYCLE3 +#elif (CORE_CLK_FREQ > EFM_WAIT_CYCLE2_FREQ) +#define EFM_WAIT_CYCLE EFM_WAIT_CYCLE2 +#elif (CORE_CLK_FREQ > EFM_WAIT_CYCLE1_FREQ) +#define EFM_WAIT_CYCLE EFM_WAIT_CYCLE1 +#else +#define EFM_WAIT_CYCLE EFM_WAIT_CYCLE0 +#endif + +#if defined(HC32F460) +#if (CORE_CLK_FREQ > 126000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT3 +#elif (CORE_CLK_FREQ > 84000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT2 +#elif (CORE_CLK_FREQ > 42000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT1 +#else /* CORE_CLK_FREQ */ +#define GPIO_RD_WAIT GPIO_RD_WAIT0 +#endif /* CORE_CLK_FREQ */ +#elif defined(HC32F4A0) +#if (CORE_CLK_FREQ > 250000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT5 +#elif (CORE_CLK_FREQ > 200000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT4 +#elif (CORE_CLK_FREQ > 150000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT3 +#elif (CORE_CLK_FREQ > 100000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT2 +#elif (CORE_CLK_FREQ > 50000000) +#define GPIO_RD_WAIT GPIO_RD_WAIT1 +#else /* CORE_CLK_FREQ */ +#define GPIO_RD_WAIT GPIO_RD_WAIT0 +#endif /* CORE_CLK_FREQ */ +#endif /* HC32F460 & HC32F4A0*/ + +#if HC32_XTAL_ENABLED +#if ((HC32_XTAL_FREQ > 20000000) && (HC32_XTAL_FREQ <= 25000000)) +#define XTAL_DRV CLK_XTAL_DRV_HIGH +#elif (HC32_XTAL_FREQ > 16000000) +#define XTAL_DRV CLK_XTAL_DRV_MID +#elif (HC32_XTAL_FREQ > 8000000) +#define XTAL_DRV CLK_XTAL_DRV_LOW +#elif (HC32_XTAL_FREQ > 4000000) +#define XTAL_DRV CLK_XTAL_DRV_ULOW +#else +#error "xtal clock frequency not compatible" +#endif +#endif + +#define HC32_CLOCK_CONTROL_NAME "hc32-cc" + +struct hc32_modules_clock_config { + uint32_t addr; +}; +#endif /* !_HC32F4_CLOCK_ */ diff --git a/dts/bindings/clock/xhsc,hc32-bus-fcg.yaml b/dts/bindings/clock/xhsc,hc32-bus-fcg.yaml new file mode 100644 index 0000000000000..7ab51b71d3b44 --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-bus-fcg.yaml @@ -0,0 +1,19 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: | + HC32 Bus FCG + enable peripherals clock.get cells value ref macro HC32_MODULES_CLOCKS + +compatible: "xhsc,hc32-bus-fcg" + +include: [clock-controller.yaml, base.yaml] + +properties: + "#clock-cells": + const: 3 + +clock-cells: + - bus + - fcg + - bits diff --git a/dts/bindings/clock/xhsc,hc32-clock-control.yaml b/dts/bindings/clock/xhsc,hc32-clock-control.yaml new file mode 100644 index 0000000000000..1260e63d97d2c --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-clock-control.yaml @@ -0,0 +1,15 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 Clock Control + +compatible: "xhsc,hc32-clock-control" + +include: [base.yaml, pinctrl-device.yaml] + +properties: + + clock-conf: + type: array + description: | + clock control configuration diff --git a/dts/bindings/clock/xhsc,hc32-clock-hrc.yaml b/dts/bindings/clock/xhsc,hc32-clock-hrc.yaml new file mode 100644 index 0000000000000..7dae8a98d8c5a --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-clock-hrc.yaml @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 Hrc Clock + +compatible: "xhsc,hc32-clock-hrc" + +include: [fixed-clock.yaml] diff --git a/dts/bindings/clock/xhsc,hc32-clock-mrc.yaml b/dts/bindings/clock/xhsc,hc32-clock-mrc.yaml new file mode 100644 index 0000000000000..41d26669ba23b --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-clock-mrc.yaml @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 Mrc Clock + +compatible: "xhsc,hc32-clock-mrc" + +include: [fixed-clock.yaml] diff --git a/dts/bindings/clock/xhsc,hc32-clock-pll.yaml b/dts/bindings/clock/xhsc,hc32-clock-pll.yaml new file mode 100644 index 0000000000000..465426cdbda71 --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-clock-pll.yaml @@ -0,0 +1,53 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 PLL Clock + +compatible: "xhsc,hc32-clock-pll" + +include: [clock-controller.yaml, base.yaml] + +properties: + + clocks: + required: true + + clock-frequency: + type: int + required: true + + div-m: + type: int + required: true + description: | + Division factor for PLL + input clock + Valid range: 1 - 24 + + mul-n: + type: int + required: true + description: | + Main PLL multiplication factor for VCO + Valid range: 20 - 480 + + div-p: + type: int + description: | + PLL division factor for pll_p_ck + Valid range: 2 - 16 + + div-q: + type: int + description: | + PLL division factor for pll_q_ck + Valid range: 2 - 16 + + div-r: + type: int + description: | + PLL division factor for pll_r_ck + Valid range: 2 - 16 + + "#clock-cells": + const: 0 diff --git a/dts/bindings/clock/xhsc,hc32-clock-sys.yaml b/dts/bindings/clock/xhsc,hc32-clock-sys.yaml new file mode 100644 index 0000000000000..abfb40dadee12 --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-clock-sys.yaml @@ -0,0 +1,107 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 System Clock + +compatible: "xhsc,hc32-clock-sys" + +include: [base.yaml] + +properties: + div-hclk: + type: int + required: true + description: | + Division factor for HCLK + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + + div-exclk: + type: int + required: true + description: | + Division factor for ExMC CLK + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + + div-pclk0: + type: int + required: true + description: | + Division factor for PCLK0 + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + + div-pclk1: + type: int + required: true + description: | + Division factor for PCLK1 + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + + div-pclk2: + type: int + required: true + description: | + Division factor for PCLK2 + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + + div-pclk3: + type: int + required: true + description: | + Division factor for PCLK3 + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + + div-pclk4: + type: int + required: true + description: | + Division factor for PCLK4 + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 diff --git a/dts/bindings/clock/xhsc,hc32-clock-xtal.yaml b/dts/bindings/clock/xhsc,hc32-clock-xtal.yaml new file mode 100644 index 0000000000000..995c7b78be263 --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-clock-xtal.yaml @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 XTAL Clock + +compatible: "xhsc,hc32-clock-xtal" + +include: [fixed-clock.yaml] diff --git a/dts/bindings/clock/xhsc,hc32-clock-xtal32.yaml b/dts/bindings/clock/xhsc,hc32-clock-xtal32.yaml new file mode 100644 index 0000000000000..700416d733017 --- /dev/null +++ b/dts/bindings/clock/xhsc,hc32-clock-xtal32.yaml @@ -0,0 +1,19 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 XTAL32 Clock + +compatible: "xhsc,hc32-clock-xtal32" + +include: [fixed-clock.yaml] + +properties: + drive-strength: + type: int + required: true + enum: + - 0 # Medium drive strength, equals to DDL macro CLK_XTAL32_DRV_MID + - 1 # High drive strength, equals to DDL macro CLK_XTAL32_DRV_HIGH + description: | + Configure the driving current of the external low-speed crystal + based on varying capacitances. diff --git a/include/zephyr/drivers/clock_control/hc32_clock_control.h b/include/zephyr/drivers/clock_control/hc32_clock_control.h new file mode 100644 index 0000000000000..dc0b0c5286d15 --- /dev/null +++ b/include/zephyr/drivers/clock_control/hc32_clock_control.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_HC32_CLOCK_CONTROL_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_HC32_CLOCK_CONTROL_H_ + +#include "soc.h" +#include +#if defined(HC32F460) +#include +#elif defined(HC32F4A0) +#include +#endif + +#define HC32_HCLK_DIV_FN(v) CLK_HCLK_DIV##v +#define HC32_HCLK_DIV(v) HC32_HCLK_DIV_FN(v) +#define HC32_EXCLK_DIV_FN(v) CLK_EXCLK_DIV##v +#define HC32_EXCLK_DIV(v) HC32_EXCLK_DIV_FN(v) +#define HC32_PCLK_FN(n, v) CLK_PCLK##n##_DIV##v +#define HC32_PCLK(n, v) HC32_PCLK_FN(n, v) + +#define HC32_CLK_MODULES_BIT(bit) (1UL << (bit)) +#define HC32_CLK_MODULES_OFFSET(n) (4 * n) + +#define HC32_CLOCK_CONTROL_NODE DT_NODELABEL(clk_sys) +#define HC32_CLOCK_SYSTEM_NODE DT_NODELABEL(clocks) + +#define HC32_HCLK_PRESCALER DT_PROP(DT_NODELABEL(clk_sys), div_hclk) +#define HC32_EXCLK_PRESCALER DT_PROP(DT_NODELABEL(clk_sys), div_exclk) +#define HC32_PCLK0_PRESCALER DT_PROP(DT_NODELABEL(clk_sys), div_pclk0) +#define HC32_PCLK1_PRESCALER DT_PROP(DT_NODELABEL(clk_sys), div_pclk1) +#define HC32_PCLK2_PRESCALER DT_PROP(DT_NODELABEL(clk_sys), div_pclk2) +#define HC32_PCLK3_PRESCALER DT_PROP(DT_NODELABEL(clk_sys), div_pclk3) +#define HC32_PCLK4_PRESCALER DT_PROP(DT_NODELABEL(clk_sys), div_pclk4) + +#define SYS_CLK_FREQ DT_PROP(DT_CLOCKS_CTLR(DT_NODELABEL(clk_sys)), clock_frequency) +#define CORE_CLK_FREQ SYS_CLK_FREQ / DT_PROP(DT_NODELABEL(clk_sys), div_hclk) +#if (CORE_CLK_FREQ != CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) +#error "please confirm current cpu clock" +#endif +#define PCLK0_FREQ SYS_CLK_FREQ / DT_PROP(DT_NODELABEL(clk_sys), div_pclk0) +#define PCLK1_FREQ SYS_CLK_FREQ / DT_PROP(DT_NODELABEL(clk_sys), div_pclk1) +#define PCLK2_FREQ SYS_CLK_FREQ / DT_PROP(DT_NODELABEL(clk_sys), div_pclk2) +#define PCLK3_FREQ SYS_CLK_FREQ / DT_PROP(DT_NODELABEL(clk_sys), div_pclk3) +#define PCLK4_FREQ SYS_CLK_FREQ / DT_PROP(DT_NODELABEL(clk_sys), div_pclk4) + +#define DT_HC32_CLOCKS_CTLR DT_CLOCKS_CTLR(DT_NODELABEL(clk_sys)) +#if DT_SAME_NODE(DT_HC32_CLOCKS_CTLR, DT_NODELABEL(clk_pll)) +#define HC32_SYSCLK_SRC_PLL 1 +#elif DT_SAME_NODE(DT_HC32_CLOCKS_CTLR, DT_NODELABEL(clk_xtal)) +#define HC32_SYSCLK_SRC_XTAL 1 +#elif DT_SAME_NODE(DT_HC32_CLOCKS_CTLR, DT_NODELABEL(clk_hrc)) +#define HC32_SYSCLK_SRC_HRC 1 +#elif DT_SAME_NODE(DT_HC32_CLOCKS_CTLR, DT_NODELABEL(clk_mrc)) +#define HC32_SYSCLK_SRC_MRC 1 +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_pll), xhsc_hc32_clock_pll, okay) && \ + DT_NODE_HAS_PROP(DT_NODELABEL(clk_pll), clocks) +#if DT_SAME_NODE(DT_CLOCKS_CTLR(DT_NODELABEL(clk_pll)), DT_NODELABEL(clk_xtal)) +#define HC32_PLL_SRC_XTAL 1 +#else +#define HC32_PLL_SRC_HRC 1 +#endif +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_pll), xhsc_hc32_clock_pll, okay) +#define HC32_PLL_ENABLED 1 +#define HC32_PLL_M_DIVISOR DT_PROP(DT_NODELABEL(clk_pll), div_m) +#define HC32_PLL_N_MULTIPLIER DT_PROP(DT_NODELABEL(clk_pll), mul_n) +#define HC32_PLL_P_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(clk_pll), div_p) +#define HC32_PLL_P_DIVISOR DT_PROP_OR(DT_NODELABEL(clk_pll), div_p, 1) +#define HC32_PLL_Q_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(clk_pll), div_q) +#define HC32_PLL_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(clk_pll), div_q, 1) +#define HC32_PLL_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(clk_pll), div_r) +#define HC32_PLL_R_DIVISOR DT_PROP_OR(DT_NODELABEL(clk_pll), div_r, 1) +#define HC32_PLL_FREQ DT_PROP(DT_NODELABEL(clk_pll), clock_frequency) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_xtal), fixed_clock, okay) +#define HC32_XTAL_ENABLED 1 +#define HC32_XTAL_FREQ DT_PROP(DT_NODELABEL(clk_xtal), clock_frequency) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_xtal32), fixed_clock, okay) +#define HC32_XTAL32_ENABLED 1 +#define HC32_XTAL32_FREQ DT_PROP(DT_NODELABEL(clk_xtal32), clock_frequency) +#define HC32_XTAL32_DRV DT_PROP(DT_NODELABEL(clk_xtal32), drive_strength) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hrc), fixed_clock, okay) +#define HC32_HRC_ENABLED 1 +#define HC32_HRC_FREQ DT_PROP(DT_NODELABEL(clk_hrc), clock_frequency) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_mrc), fixed_clock, okay) +#define HC32_MRC_ENABLED 1 +#define HC32_MRC_FREQ DT_PROP(DT_NODELABEL(clk_mrc), clock_frequency) +#endif + +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_lrc), fixed_clock, okay) +#define HC32_LRC_ENABLED 1 +#define HC32_LRC_FREQ DT_PROP(DT_NODELABEL(clk_lrc), clock_frequency) +#endif + +#define HC32_MODULES_CLOCK_INFO(clk_index, node_id) \ + {.bus = DT_CLOCKS_CELL_BY_IDX(node_id, clk_index, bus), \ + .fcg = DT_CLOCKS_CELL_BY_IDX(node_id, clk_index, fcg), \ + .bits = DT_CLOCKS_CELL_BY_IDX(node_id, clk_index, bits)} + +#define HC32_MODULES_CLOCKS(node_id) \ + {LISTIFY(DT_NUM_CLOCKS(node_id), HC32_MODULES_CLOCK_INFO, (,), node_id) } + +struct hc32_modules_clock_sys { + uint32_t bus; + uint32_t fcg; + uint32_t bits; +}; +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_HC32_CLOCK_CONTROL_H_ */ diff --git a/include/zephyr/dt-bindings/clock/hc32f4_common_clock.h b/include/zephyr/dt-bindings/clock/hc32f4_common_clock.h new file mode 100644 index 0000000000000..426715c87baa1 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/hc32f4_common_clock.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_HC32F4_COMMON_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_HC32F4_COMMON_CLOCK_H_ + +#define HC32_CLK_FCG0 0 +#define HC32_CLK_FCG1 1 +#define HC32_CLK_FCG2 2 +#define HC32_CLK_FCG3 3 +#define HC32_CLK_FCG_AVALID 0xFF + +#define HC32_CLK_SRC_HRC (0x00) +#define HC32_CLK_SRC_MRC (0x01) +#define HC32_CLK_SRC_LRC (0x02) +#define HC32_CLK_SRC_XTAL (0x03) +#define HC32_CLK_SRC_XTAL32 (0x04) +#define HC32_CLK_SRC_PLL (0x05) +#define HC32_CLK_BUS_HCLK (0x07) +#define HC32_CLK_BUS_PCLK0 (0x08) +#define HC32_CLK_BUS_PCLK1 (0x09) +#define HC32_CLK_BUS_PCLK2 (0x0A) +#define HC32_CLK_BUS_PCLK3 (0x0B) +#define HC32_CLK_BUS_PCLK4 (0x0C) +#define HC32_SYS_CLK (0x0D) + +#define HC32_CLK_CONF_PERI (0) +#define HC32_CLK_CONF_TPIU (1) +#define HC32_CLK_CONF_SRC (2) +#define HC32_CLK_CONF_MCO (3) +#define HC32_CLK_CONF_MIN HC32_CLK_CONF_PERI +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_HC32F4_COMMON_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/hc32f4a0_clock.h b/include/zephyr/dt-bindings/clock/hc32f4a0_clock.h new file mode 100644 index 0000000000000..184961f3c191f --- /dev/null +++ b/include/zephyr/dt-bindings/clock/hc32f4a0_clock.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_HC32F4A0_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_HC32F4A0_CLOCK_H_ + +#include "hc32f4_common_clock.h" + +#define HC32_FCG0_PERIPH_SRAMH 0 +#define HC32_FCG0_PERIPH_SRAM1 4 +#define HC32_FCG0_PERIPH_SRAM2 5 +#define HC32_FCG0_PERIPH_SRAM3 6 +#define HC32_FCG0_PERIPH_SRAM4 7 +#define HC32_FCG0_PERIPH_SRAMB 10 +#define HC32_FCG0_PERIPH_KEY 13 +#define HC32_FCG0_PERIPH_DMA1 14 +#define HC32_FCG0_PERIPH_DMA2 15 +#define HC32_FCG0_PERIPH_FCM 16 +#define HC32_FCG0_PERIPH_AOS 17 +#define HC32_FCG0_PERIPH_CTC 18 +#define HC32_FCG0_PERIPH_MAU 19 +#define HC32_FCG0_PERIPH_AES 20 +#define HC32_FCG0_PERIPH_HASH 21 +#define HC32_FCG0_PERIPH_TRNG 22 +#define HC32_FCG0_PERIPH_CRC 23 +#define HC32_FCG0_PERIPH_DCU1 24 +#define HC32_FCG0_PERIPH_DCU2 25 +#define HC32_FCG0_PERIPH_DCU3 26 +#define HC32_FCG0_PERIPH_DCU4 27 +#define HC32_FCG0_PERIPH_DCU5 28 +#define HC32_FCG0_PERIPH_DCU6 29 +#define HC32_FCG0_PERIPH_DCU7 30 +#define HC32_FCG0_PERIPH_DCU8 31 + +#define HC32_FCG1_PERIPH_CAN1 0 +#define HC32_FCG1_PERIPH_CAN2 1 +#define HC32_FCG1_PERIPH_ETHMAC 2 +#define HC32_FCG1_PERIPH_QSPI 3 +#define HC32_FCG1_PERIPH_I2C1 4 +#define HC32_FCG1_PERIPH_I2C2 5 +#define HC32_FCG1_PERIPH_I2C3 6 +#define HC32_FCG1_PERIPH_I2C4 7 +#define HC32_FCG1_PERIPH_I2C5 8 +#define HC32_FCG1_PERIPH_I2C6 9 +#define HC32_FCG1_PERIPH_SDIOC1 10 +#define HC32_FCG1_PERIPH_SDIOC2 11 +#define HC32_FCG1_PERIPH_I2S1 12 +#define HC32_FCG1_PERIPH_I2S2 13 +#define HC32_FCG1_PERIPH_I2S3 14 +#define HC32_FCG1_PERIPH_I2S4 15 +#define HC32_FCG1_PERIPH_SPI1 16 +#define HC32_FCG1_PERIPH_SPI2 17 +#define HC32_FCG1_PERIPH_SPI3 18 +#define HC32_FCG1_PERIPH_SPI4 19 +#define HC32_FCG1_PERIPH_SPI5 20 +#define HC32_FCG1_PERIPH_SPI6 21 +#define HC32_FCG1_PERIPH_USBFS 22 +#define HC32_FCG1_PERIPH_USBHS 23 +#define HC32_FCG1_PERIPH_FMAC1 24 +#define HC32_FCG1_PERIPH_FMAC2 25 +#define HC32_FCG1_PERIPH_FMAC3 26 +#define HC32_FCG1_PERIPH_FMAC4 27 + +#define HC32_FCG2_PERIPH_TMR6_1 0 +#define HC32_FCG2_PERIPH_TMR6_2 1 +#define HC32_FCG2_PERIPH_TMR6_3 2 +#define HC32_FCG2_PERIPH_TMR6_4 3 +#define HC32_FCG2_PERIPH_TMR6_5 4 +#define HC32_FCG2_PERIPH_TMR6_6 5 +#define HC32_FCG2_PERIPH_TMR6_7 6 +#define HC32_FCG2_PERIPH_TMR6_8 7 +#define HC32_FCG2_PERIPH_TMR4_1 8 +#define HC32_FCG2_PERIPH_TMR4_2 9 +#define HC32_FCG2_PERIPH_TMR4_3 10 +#define HC32_FCG2_PERIPH_HRPWM 11 +#define HC32_FCG2_PERIPH_TMR0_1 12 +#define HC32_FCG2_PERIPH_TMR0_2 13 +#define HC32_FCG2_PERIPH_EMB 15 +#define HC32_FCG2_PERIPH_TMR2_1 16 +#define HC32_FCG2_PERIPH_TMR2_2 17 +#define HC32_FCG2_PERIPH_TMR2_3 18 +#define HC32_FCG2_PERIPH_TMR2_4 19 +#define HC32_FCG2_PERIPH_TMRA_1 20 +#define HC32_FCG2_PERIPH_TMRA_2 21 +#define HC32_FCG2_PERIPH_TMRA_3 22 +#define HC32_FCG2_PERIPH_TMRA_4 23 +#define HC32_FCG2_PERIPH_TMRA_5 24 +#define HC32_FCG2_PERIPH_TMRA_6 25 +#define HC32_FCG2_PERIPH_TMRA_7 26 +#define HC32_FCG2_PERIPH_TMRA_8 27 +#define HC32_FCG2_PERIPH_TMRA_9 28 +#define HC32_FCG2_PERIPH_TMRA_10 29 +#define HC32_FCG2_PERIPH_TMRA_11 30 +#define HC32_FCG2_PERIPH_TMRA_12 31 + +#define HC32_FCG3_PERIPH_ADC1 0 +#define HC32_FCG3_PERIPH_ADC2 1 +#define HC32_FCG3_PERIPH_ADC3 2 +#define HC32_FCG3_PERIPH_CMBIAS 3 +#define HC32_FCG3_PERIPH_DAC1 4 +#define HC32_FCG3_PERIPH_DAC2 5 +#define HC32_FCG3_PERIPH_CMP12 8 +#define HC32_FCG3_PERIPH_CMP34 9 +#define HC32_FCG3_PERIPH_OTS 12 +#define HC32_FCG3_PERIPH_DVP 15 +#define HC32_FCG3_PERIPH_EXMC_SMC 16 +#define HC32_FCG3_PERIPH_EXMC_DMC 17 +#define HC32_FCG3_PERIPH_EXMC_NMC 18 +#define HC32_FCG3_PERIPH_USART1 20 +#define HC32_FCG3_PERIPH_USART2 21 +#define HC32_FCG3_PERIPH_USART3 22 +#define HC32_FCG3_PERIPH_USART4 23 +#define HC32_FCG3_PERIPH_USART5 24 +#define HC32_FCG3_PERIPH_USART6 25 +#define HC32_FCG3_PERIPH_USART7 26 +#define HC32_FCG3_PERIPH_USART8 27 +#define HC32_FCG3_PERIPH_USART9 28 +#define HC32_FCG3_PERIPH_USART10 29 + +#define HC32_CLK_CONF_USB (4) +#define HC32_CLK_CONF_I2S (5) +#define HC32_CLK_CONF_CAN (6) +#define HC32_CLK_CONF_MAX HC32_CLK_CONF_CAN +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_HC32F4A0_CLOCK_H_ */ From 187e41977c30f8535eb5cf8e7322084c008c64e2 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:55:46 +0800 Subject: [PATCH 06/10] drivers: interrupt_controller: Add support for HC32F4A0 This is the initial commit to support interrupt controller Signed-off-by: Yongbing Liu --- drivers/interrupt_controller/CMakeLists.txt | 2 + drivers/interrupt_controller/Kconfig | 2 + drivers/interrupt_controller/Kconfig.hc32 | 29 + .../interrupt_controller/intc_extint_hc32.c | 267 ++++ drivers/interrupt_controller/intc_hc32.c | 47 + .../xhsc,hc32-extint.yaml | 19 + .../interrupt-controller/xhsc,hc32-intc.yaml | 20 + .../interrupt_controller/intc_extint_hc32.h | 45 + .../drivers/interrupt_controller/intc_hc32.h | 20 + .../interrupt-controller/hc32f4a0-int-evt.h | 1168 +++++++++++++++++ .../interrupt-controller/hc32f4a0-intc.h | 714 ++++++++++ 11 files changed, 2333 insertions(+) create mode 100644 drivers/interrupt_controller/Kconfig.hc32 create mode 100644 drivers/interrupt_controller/intc_extint_hc32.c create mode 100644 drivers/interrupt_controller/intc_hc32.c create mode 100644 dts/bindings/interrupt-controller/xhsc,hc32-extint.yaml create mode 100644 dts/bindings/interrupt-controller/xhsc,hc32-intc.yaml create mode 100644 include/zephyr/drivers/interrupt_controller/intc_extint_hc32.h create mode 100644 include/zephyr/drivers/interrupt_controller/intc_hc32.h create mode 100644 include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-int-evt.h create mode 100644 include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-intc.h diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index 44a0b7573a81e..d102752a8963b 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -16,6 +16,8 @@ zephyr_library_sources_ifdef(CONFIG_GIC_V3_ITS intc_gicv3_its.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INTC_STM32WB0 intc_gpio_stm32wb0.c) zephyr_library_sources_ifdef(CONFIG_HAZARD3_INTC intc_hazard3.c) zephyr_library_sources_ifdef(CONFIG_HAZARD3_INTC intc_hazard3.S) +zephyr_library_sources_ifdef(CONFIG_INTC_HC32 intc_hc32.c) +zephyr_library_sources_ifdef(CONFIG_INTC_EXTINT_HC32 intc_extint_hc32.c) zephyr_library_sources_ifdef(CONFIG_INTEL_VTD_ICTL intc_intel_vtd.c) zephyr_library_sources_ifdef(CONFIG_IOAPIC intc_ioapic.c) zephyr_library_sources_ifdef(CONFIG_ITE_IT51XXX_INTC intc_ite_it51xxx.c) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index d3954cc1f3c84..72a030a8da954 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -125,4 +125,6 @@ source "drivers/interrupt_controller/Kconfig.wch_pfic" source "drivers/interrupt_controller/Kconfig.wch_exti" +source "drivers/interrupt_controller/Kconfig.hc32" + endmenu diff --git a/drivers/interrupt_controller/Kconfig.hc32 b/drivers/interrupt_controller/Kconfig.hc32 new file mode 100644 index 0000000000000..d999b98d1cc9b --- /dev/null +++ b/drivers/interrupt_controller/Kconfig.hc32 @@ -0,0 +1,29 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config INTC_HC32 + bool "Interrupt/Event Controller (INTC) Driver for HC32 family of MCUs" + default y + depends on DT_HAS_XHSC_HC32_INTC_ENABLED + select HC32_LL_INTERRUPTS + select HC32_LL_INTERRUPTS_SHARE + help + Enable INTC driver for HC32 line of MCUs + +config INTC_EXTINT_HC32 + bool "External Interrupt Controller (EXTINT) Driver for HC32 family of MCUs" + default y + depends on DT_HAS_XHSC_HC32_EXTINT_ENABLED + select HC32_LL_INTERRUPTS + help + Enable EXTINT driver for HC32 line of MCUs + +if INTC_EXTINT_HC32 + +config INTC_EXTINT_USE_SHARE_INTERRUPT + bool "INTC EXTINT used share interrupt" + default y + help + INTC EXTINT respond to irq handlers with share interrupt. + +endif # INTC_EXTINT_HC32 diff --git a/drivers/interrupt_controller/intc_extint_hc32.c b/drivers/interrupt_controller/intc_extint_hc32.c new file mode 100644 index 0000000000000..a05c9394c345d --- /dev/null +++ b/drivers/interrupt_controller/intc_extint_hc32.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Driver for External Interrupt controller in HC32 MCUs + */ + +#define DT_DRV_COMPAT xhsc_hc32_extint +#define EXTINT_NODE DT_INST(0, DT_DRV_COMPAT) + +#include +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_INTC_LOG_LEVEL +#include +LOG_MODULE_REGISTER(intc_extint_hc32); + +#define INTC_EXTINT_NUM DT_PROP(EXTINT_NODE, extint_nums) +#define INTC_EXTINT_IRQN_DEF 0xFF + +static IRQn_Type extint_irq_table[INTC_EXTINT_NUM] = {[0 ... INTC_EXTINT_NUM - 1] = + INTC_EXTINT_IRQN_DEF}; + +/* wrapper for user callback */ +struct hc32_extint_cb { + hc32_extint_callback_t cb; + void *user; +}; + +struct hc32_extint_data { + /* callbacks */ + struct hc32_extint_cb cb[INTC_EXTINT_NUM]; +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + uint32_t extint_table; +#endif +}; + +/** + * @brief EXTINT ISR handler + */ +static void hc32_extint_isr(const void *arg) +{ + const struct device *dev = DEVICE_DT_GET(EXTINT_NODE); + struct hc32_extint_data *data = dev->data; + +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + uint32_t ch_idx; + + ARG_UNUSED(arg); + for (ch_idx = 0; ch_idx < INTC_EXTINT_NUM; ch_idx++) { + if (SET == EXTINT_GetExtIntStatus(BIT(ch_idx))) { + EXTINT_ClearExtIntStatus(BIT(ch_idx)); + /* run callback only if one is registered */ + if (data->cb[ch_idx].cb != NULL) { + data->cb[ch_idx].cb(ch_idx, data->cb[ch_idx].user); + } + } + } +#else + uint32_t ch = *(uint8_t *)arg; + + if (SET == EXTINT_GetExtIntStatus(BIT(ch))) { + EXTINT_ClearExtIntStatus(BIT(ch)); + /* run callback only if one is registered */ + if (data->cb[ch].cb != NULL) { + data->cb[ch].cb(ch, data->cb[ch].user); + } + } +#endif +} + +/* Configure irq information */ +static void hc32_irq_config(uint8_t ch, int irqn, int intsrc) +{ + /* fill irq table */ + extint_irq_table[ch] = (IRQn_Type)irqn; +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + INTC_ShareIrqCmd(intsrc, ENABLE); +#else + hc32_intc_irq_signin(irqn, intsrc); +#endif +} + +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) +#define HC32_EXTINT_INIT_SHARE(node_id, interrupts, idx) \ + hc32_irq_config(DT_PROP_BY_IDX(node_id, extint_chs, idx), \ + DT_IRQ_BY_IDX(node_id, idx, irq), DT_IRQ_BY_IDX(node_id, idx, int_src)); + +#else + +#define HC32_EXTINT_INIT(node_id, interrupts, idx) \ + static const uint8_t hc32_extint_ch_##idx = DT_PROP_BY_IDX(node_id, extint_chs, idx); \ + hc32_irq_config(hc32_extint_ch_##idx, DT_IRQ_BY_IDX(node_id, idx, irq), \ + DT_IRQ_BY_IDX(node_id, idx, int_src)); \ + IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq), DT_IRQ_BY_IDX(node_id, idx, priority), \ + hc32_extint_isr, &hc32_extint_ch_##idx, 0); +#endif + +/** + * @brief initialize intc device driver + */ +static int hc32_intc_init(const struct device *dev) +{ +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + struct hc32_extint_data *data = dev->data; + + data->extint_table = 0; + DT_FOREACH_PROP_ELEM(EXTINT_NODE, interrupt_names, HC32_EXTINT_INIT_SHARE); + IRQ_CONNECT(DT_IRQ_BY_IDX(EXTINT_NODE, 0, irq), DT_IRQ_BY_IDX(EXTINT_NODE, 0, priority), + hc32_extint_isr, NULL, 0); +#else + ARG_UNUSED(dev); + DT_FOREACH_PROP_ELEM(EXTINT_NODE, interrupt_names, HC32_EXTINT_INIT); +#endif + + return 0; +} + +static void hc32_extint_enable(const struct device *dev, int port, int pin) +{ + int irqnum = 0; +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + struct hc32_extint_data *data = dev->data; +#else + ARG_UNUSED(dev); +#endif + + if (pin >= INTC_EXTINT_NUM) { + __ASSERT_NO_MSG(pin); + } + /* Get matching extint irq number from irq_table */ + irqnum = extint_irq_table[pin]; + if (irqnum == INTC_EXTINT_IRQN_DEF) { + __ASSERT_NO_MSG(pin); + } + + /* Enable requested pin interrupt */ + GPIO_ExtIntCmd((uint8_t)port, BIT((uint32_t)pin), ENABLE); +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + if (0 == data->extint_table) { + /* Enable extint irq interrupt */ + irq_enable(irqnum); + } + SET_REG32_BIT(data->extint_table, BIT((uint32_t)pin)); +#else + /* Enable extint irq interrupt */ + irq_enable(irqnum); +#endif +} + +static void hc32_extint_disable(const struct device *dev, int port, int pin) +{ + int irqnum = 0; +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + struct hc32_extint_data *data = dev->data; +#else + ARG_UNUSED(dev); +#endif + + if (pin >= INTC_EXTINT_NUM) { + __ASSERT_NO_MSG(pin); + } + /* Get matching extint irq number from irq_table */ + irqnum = extint_irq_table[pin]; + if (irqnum == INTC_EXTINT_IRQN_DEF) { + __ASSERT_NO_MSG(pin); + } + + /* Disable requested pin interrupt */ + GPIO_ExtIntCmd((uint8_t)port, BIT((uint32_t)pin), DISABLE); +#if defined(CONFIG_INTC_EXTINT_USE_SHARE_INTERRUPT) + CLR_REG32_BIT(data->extint_table, BIT((uint32_t)pin)); + if (0 == data->extint_table) { + /* Disable extint irq interrupt */ + irq_disable(irqnum); + } +#else + /* Disable extint irq interrupt */ + irq_disable(irqnum); +#endif +} + +static void hc32_extint_trigger(const struct device *dev, int pin, int trigger) +{ + stc_extint_init_t stc_extint_init; + + ARG_UNUSED(dev); + + if (pin >= INTC_EXTINT_NUM) { + __ASSERT_NO_MSG(pin); + } + + /* ExtInt config */ + (void)EXTINT_StructInit(&stc_extint_init); + switch (trigger) { + case HC32_EXTINT_TRIG_FALLING: + stc_extint_init.u32Edge = EXTINT_TRIG_FALLING; + break; + case HC32_EXTINT_TRIG_RISING: + stc_extint_init.u32Edge = EXTINT_TRIG_RISING; + break; + case HC32_EXTINT_TRIG_BOTH: + stc_extint_init.u32Edge = EXTINT_TRIG_BOTH; + break; + case HC32_EXTINT_TRIG_LOW_LVL: + stc_extint_init.u32Edge = EXTINT_TRIG_LOW; + break; + default: + __ASSERT_NO_MSG(trigger); + break; + } + EXTINT_Init(BIT((uint32_t)pin), &stc_extint_init); +} + +static int hc32_extint_set_callback(const struct device *dev, int pin, hc32_extint_callback_t cb, + void *user) +{ + struct hc32_extint_data *data = dev->data; + + if (pin >= INTC_EXTINT_NUM) { + __ASSERT_NO_MSG(pin); + } + + if ((data->cb[pin].cb == cb) && (data->cb[pin].user == user)) { + return 0; + } + /* if callback already exists/maybe-running return busy */ + if (data->cb[pin].cb != NULL) { + return -EBUSY; + } + data->cb[pin].cb = cb; + data->cb[pin].user = user; + + return 0; +} + +static void hc32_extint_unset_callback(const struct device *dev, int pin) +{ + struct hc32_extint_data *data = dev->data; + + if (pin >= INTC_EXTINT_NUM) { + __ASSERT_NO_MSG(pin); + } + + data->cb[pin].cb = NULL; + data->cb[pin].user = NULL; +} + +static struct hc32_extint_data extint_data; +static const struct hc32_extint_driver_api extint_api = { + .extint_enable = hc32_extint_enable, + .extint_disable = hc32_extint_disable, + .extint_set_trigger = hc32_extint_trigger, + .extint_set_cb = hc32_extint_set_callback, + .extint_unset_cb = hc32_extint_unset_callback, +}; + +DEVICE_DT_DEFINE(EXTINT_NODE, &hc32_intc_init, NULL, &extint_data, NULL, PRE_KERNEL_1, + CONFIG_INTC_INIT_PRIORITY, &extint_api); diff --git a/drivers/interrupt_controller/intc_hc32.c b/drivers/interrupt_controller/intc_hc32.c new file mode 100644 index 0000000000000..91abda57fab91 --- /dev/null +++ b/drivers/interrupt_controller/intc_hc32.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Driver for interrupt/event controller in HC32 MCUs + */ + +#define DT_DRV_COMPAT xhsc_hc32_intc + +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_INTC_LOG_LEVEL +#include +LOG_MODULE_REGISTER(intc_hc32); + +int hc32_intc_irq_signin(int irqn, int intsrc) +{ + stc_irq_signin_config_t stc_irq_sign_config; + + stc_irq_sign_config.enIRQn = (IRQn_Type)irqn; + stc_irq_sign_config.enIntSrc = (en_int_src_t)intsrc; + stc_irq_sign_config.pfnCallback = NULL; + if (LL_OK != INTC_IrqSignIn(&stc_irq_sign_config)) { + LOG_ERR("intc signin failed!"); + return -EACCES; + } + + return 0; +} + +int hc32_intc_irq_signout(int irqn) +{ + if (LL_OK != INTC_IrqSignOut((IRQn_Type)irqn)) { + LOG_ERR("intc signout failed!"); + return -EACCES; + } + + return 0; +} diff --git a/dts/bindings/interrupt-controller/xhsc,hc32-extint.yaml b/dts/bindings/interrupt-controller/xhsc,hc32-extint.yaml new file mode 100644 index 0000000000000..9a0c72e07340f --- /dev/null +++ b/dts/bindings/interrupt-controller/xhsc,hc32-extint.yaml @@ -0,0 +1,19 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: XHSC HC32 family Interrupt Controller + +compatible: "xhsc,hc32-extint" + +include: [base.yaml] + +properties: + extint-nums: + type: int + required: true + description: Number of extint supported by the interrupt controller. + + extint-chs: + type: array + required: true + description: Description of the external channel for each interrupt vector. diff --git a/dts/bindings/interrupt-controller/xhsc,hc32-intc.yaml b/dts/bindings/interrupt-controller/xhsc,hc32-intc.yaml new file mode 100644 index 0000000000000..7700e288ec079 --- /dev/null +++ b/dts/bindings/interrupt-controller/xhsc,hc32-intc.yaml @@ -0,0 +1,20 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: XHSC HC32 family Interrupt Controller + +compatible: "xhsc,hc32-intc" + +include: [base.yaml, interrupt-controller.yaml] + +properties: + reg: + required: true + + "#interrupt-cells": + const: 3 + +interrupt-cells: + - irq + - priority + - int_src diff --git a/include/zephyr/drivers/interrupt_controller/intc_extint_hc32.h b/include/zephyr/drivers/interrupt_controller/intc_extint_hc32.h new file mode 100644 index 0000000000000..324aef4a2d305 --- /dev/null +++ b/include/zephyr/drivers/interrupt_controller/intc_extint_hc32.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Driver for external interrupt/event controller in HC32 MCUs + */ + +#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTINT_HC32_H_ +#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTINT_HC32_H_ + +#include + +/** + * @brief external trigger flags + */ +enum hc32_extint_trigger { + HC32_EXTINT_TRIG_FALLING = 0x0, /* trigger on falling edge */ + HC32_EXTINT_TRIG_RISING = 0x1, /* trigger on rising edge */ + HC32_EXTINT_TRIG_BOTH = 0x2, /* trigger on falling edge */ + HC32_EXTINT_TRIG_LOW_LVL = 0x3, /* trigger on low level */ + HC32_EXTINT_TRIG_NOT_SUPPT, /* trigger not supported */ +}; + +/* callback for exti interrupt */ +typedef void (*hc32_extint_callback_t)(int pin, void *user); + +typedef void (*hc32_extint_enable_t)(const struct device *dev, int port, int pin); +typedef void (*hc32_extint_disable_t)(const struct device *dev, int port, int pin); +typedef void (*hc32_extint_trigger_t)(const struct device *dev, int pin, int trigger); +typedef int (*hc32_extint_set_callback_t)(const struct device *dev, int pin, + hc32_extint_callback_t cb, void *user); +typedef void (*hc32_extint_unset_callback_t)(const struct device *dev, int pin); + +struct hc32_extint_driver_api { + hc32_extint_enable_t extint_enable; + hc32_extint_disable_t extint_disable; + hc32_extint_trigger_t extint_set_trigger; + hc32_extint_set_callback_t extint_set_cb; + hc32_extint_unset_callback_t extint_unset_cb; +}; + +#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTINT_HC32_H_ */ diff --git a/include/zephyr/drivers/interrupt_controller/intc_hc32.h b/include/zephyr/drivers/interrupt_controller/intc_hc32.h new file mode 100644 index 0000000000000..bfc84bdf6f5b7 --- /dev/null +++ b/include/zephyr/drivers/interrupt_controller/intc_hc32.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Driver for interrupt/event controller in HC32 MCUs + */ + +#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_HC32_H_ +#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_HC32_H_ + +#include + +/* intc config */ +int hc32_intc_irq_signin(int irqn, int intsrc); +int hc32_intc_irq_signout(int irqn); + +#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_HC32_H_ */ diff --git a/include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-int-evt.h b/include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-int-evt.h new file mode 100644 index 0000000000000..89e581dcb03e6 --- /dev/null +++ b/include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-int-evt.h @@ -0,0 +1,1168 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_HC32F4A0_INT_EVT_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_HC32F4A0_INT_EVT_H_ + +/** + * @brief Interrupt Vector Number + */ +#define NonMaskableInt_IRQn -14 /* Non Maskable */ +#define HardFault_IRQn -13 /* Hard Fault */ +#define MemoryManagement_IRQn -12 /* MemManage Fault */ +#define BusFault_IRQn -11 /* Bus Fault */ +#define UsageFault_IRQn -10 /* Usage Fault */ +#define SVCall_IRQn -5 /* SVCall */ +#define DebugMonitor_IRQn -4 /* DebugMonitor */ +#define PendSV_IRQn -2 /* Pend SV */ +#define SysTick_IRQn -1 /* System Tick */ +#define INT000_IRQn 0 +#define INT001_IRQn 1 +#define INT002_IRQn 2 +#define INT003_IRQn 3 +#define INT004_IRQn 4 +#define INT005_IRQn 5 +#define INT006_IRQn 6 +#define INT007_IRQn 7 +#define INT008_IRQn 8 +#define INT009_IRQn 9 +#define INT010_IRQn 10 +#define INT011_IRQn 11 +#define INT012_IRQn 12 +#define INT013_IRQn 13 +#define INT014_IRQn 14 +#define INT015_IRQn 15 +#define INT016_IRQn 16 +#define INT017_IRQn 17 +#define INT018_IRQn 18 +#define INT019_IRQn 19 +#define INT020_IRQn 20 +#define INT021_IRQn 21 +#define INT022_IRQn 22 +#define INT023_IRQn 23 +#define INT024_IRQn 24 +#define INT025_IRQn 25 +#define INT026_IRQn 26 +#define INT027_IRQn 27 +#define INT028_IRQn 28 +#define INT029_IRQn 29 +#define INT030_IRQn 30 +#define INT031_IRQn 31 +#define INT032_IRQn 32 +#define INT033_IRQn 33 +#define INT034_IRQn 34 +#define INT035_IRQn 35 +#define INT036_IRQn 36 +#define INT037_IRQn 37 +#define INT038_IRQn 38 +#define INT039_IRQn 39 +#define INT040_IRQn 40 +#define INT041_IRQn 41 +#define INT042_IRQn 42 +#define INT043_IRQn 43 +#define INT044_IRQn 44 +#define INT045_IRQn 45 +#define INT046_IRQn 46 +#define INT047_IRQn 47 +#define INT048_IRQn 48 +#define INT049_IRQn 49 +#define INT050_IRQn 50 +#define INT051_IRQn 51 +#define INT052_IRQn 52 +#define INT053_IRQn 53 +#define INT054_IRQn 54 +#define INT055_IRQn 55 +#define INT056_IRQn 56 +#define INT057_IRQn 57 +#define INT058_IRQn 58 +#define INT059_IRQn 59 +#define INT060_IRQn 60 +#define INT061_IRQn 61 +#define INT062_IRQn 62 +#define INT063_IRQn 63 +#define INT064_IRQn 64 +#define INT065_IRQn 65 +#define INT066_IRQn 66 +#define INT067_IRQn 67 +#define INT068_IRQn 68 +#define INT069_IRQn 69 +#define INT070_IRQn 70 +#define INT071_IRQn 71 +#define INT072_IRQn 72 +#define INT073_IRQn 73 +#define INT074_IRQn 74 +#define INT075_IRQn 75 +#define INT076_IRQn 76 +#define INT077_IRQn 77 +#define INT078_IRQn 78 +#define INT079_IRQn 79 +#define INT080_IRQn 80 +#define INT081_IRQn 81 +#define INT082_IRQn 82 +#define INT083_IRQn 83 +#define INT084_IRQn 84 +#define INT085_IRQn 85 +#define INT086_IRQn 86 +#define INT087_IRQn 87 +#define INT088_IRQn 88 +#define INT089_IRQn 89 +#define INT090_IRQn 90 +#define INT091_IRQn 91 +#define INT092_IRQn 92 +#define INT093_IRQn 93 +#define INT094_IRQn 94 +#define INT095_IRQn 95 +#define INT096_IRQn 96 +#define INT097_IRQn 97 +#define INT098_IRQn 98 +#define INT099_IRQn 99 +#define INT100_IRQn 100 +#define INT101_IRQn 101 +#define INT102_IRQn 102 +#define INT103_IRQn 103 +#define INT104_IRQn 104 +#define INT105_IRQn 105 +#define INT106_IRQn 106 +#define INT107_IRQn 107 +#define INT108_IRQn 108 +#define INT109_IRQn 109 +#define INT110_IRQn 110 +#define INT111_IRQn 111 +#define INT112_IRQn 112 +#define INT113_IRQn 113 +#define INT114_IRQn 114 +#define INT115_IRQn 115 +#define INT116_IRQn 116 +#define INT117_IRQn 117 +#define INT118_IRQn 118 +#define INT119_IRQn 119 +#define INT120_IRQn 120 +#define INT121_IRQn 121 +#define INT122_IRQn 122 +#define INT123_IRQn 123 +#define INT124_IRQn 124 +#define INT125_IRQn 125 +#define INT126_IRQn 126 +#define INT127_IRQn 127 +#define INT128_IRQn 128 +#define INT129_IRQn 129 +#define INT130_IRQn 130 +#define INT131_IRQn 131 +#define INT132_IRQn 132 +#define INT133_IRQn 133 +#define INT134_IRQn 134 +#define INT135_IRQn 135 +#define INT136_IRQn 136 +#define INT137_IRQn 137 +#define INT138_IRQn 138 +#define INT139_IRQn 139 +#define INT140_IRQn 140 +#define INT141_IRQn 141 +#define INT142_IRQn 142 +#define INT143_IRQn 143 + +/** + * @brief Interrupt Priority Level + */ +#define DDL_IRQ_PRIO_00 (0U) +#define DDL_IRQ_PRIO_01 (1U) +#define DDL_IRQ_PRIO_02 (2U) +#define DDL_IRQ_PRIO_03 (3U) +#define DDL_IRQ_PRIO_04 (4U) +#define DDL_IRQ_PRIO_05 (5U) +#define DDL_IRQ_PRIO_06 (6U) +#define DDL_IRQ_PRIO_07 (7U) +#define DDL_IRQ_PRIO_08 (8U) +#define DDL_IRQ_PRIO_09 (9U) +#define DDL_IRQ_PRIO_10 (10U) +#define DDL_IRQ_PRIO_11 (11U) +#define DDL_IRQ_PRIO_12 (12U) +#define DDL_IRQ_PRIO_13 (13U) +#define DDL_IRQ_PRIO_14 (14U) +/* kernal used */ +/* #define DDL_IRQ_PRIO_15 (15U) */ + +#define DDL_IRQ_PRIO_DEFAULT (DDL_IRQ_PRIO_10) + +/** + * @brief Interrupt Source Number + */ +#define INT_SRC_SWI_IRQ0 0U /* SWI_IRQ0 */ +#define INT_SRC_SWI_IRQ1 1U /* SWI_IRQ1 */ +#define INT_SRC_SWI_IRQ2 2U /* SWI_IRQ2 */ +#define INT_SRC_SWI_IRQ3 3U /* SWI_IRQ3 */ +#define INT_SRC_SWI_IRQ4 4U /* SWI_IRQ4 */ +#define INT_SRC_SWI_IRQ5 5U /* SWI_IRQ5 */ +#define INT_SRC_SWI_IRQ6 6U /* SWI_IRQ6 */ +#define INT_SRC_SWI_IRQ7 7U /* SWI_IRQ7 */ +#define INT_SRC_SWI_IRQ8 8U /* SWI_IRQ8 */ +#define INT_SRC_SWI_IRQ9 9U /* SWI_IRQ9 */ +#define INT_SRC_SWI_IRQ10 10U /* SWI_IRQ10 */ +#define INT_SRC_SWI_IRQ11 11U /* SWI_IRQ11 */ +#define INT_SRC_SWI_IRQ12 12U /* SWI_IRQ12 */ +#define INT_SRC_SWI_IRQ13 13U /* SWI_IRQ13 */ +#define INT_SRC_SWI_IRQ14 14U /* SWI_IRQ14 */ +#define INT_SRC_SWI_IRQ15 15U /* SWI_IRQ15 */ +#define INT_SRC_SWI_IRQ16 16U /* SWI_IRQ16 */ +#define INT_SRC_SWI_IRQ17 17U /* SWI_IRQ17 */ +#define INT_SRC_SWI_IRQ18 18U /* SWI_IRQ18 */ +#define INT_SRC_SWI_IRQ19 19U /* SWI_IRQ19 */ +#define INT_SRC_SWI_IRQ20 20U /* SWI_IRQ20 */ +#define INT_SRC_SWI_IRQ21 21U /* SWI_IRQ21 */ +#define INT_SRC_SWI_IRQ22 22U /* SWI_IRQ22 */ +#define INT_SRC_SWI_IRQ23 23U /* SWI_IRQ23 */ +#define INT_SRC_SWI_IRQ24 24U /* SWI_IRQ24 */ +#define INT_SRC_SWI_IRQ25 25U /* SWI_IRQ25 */ +#define INT_SRC_SWI_IRQ26 26U /* SWI_IRQ26 */ +#define INT_SRC_SWI_IRQ27 27U /* SWI_IRQ27 */ +#define INT_SRC_SWI_IRQ28 28U /* SWI_IRQ28 */ +#define INT_SRC_SWI_IRQ29 29U /* SWI_IRQ29 */ +#define INT_SRC_SWI_IRQ30 30U /* SWI_IRQ30 */ +#define INT_SRC_SWI_IRQ31 31U /* SWI_IRQ31 */ + +/* External Interrupt. */ +#define INT_SRC_PORT_EIRQ0 0U /* PORT_EIRQ0 */ +#define INT_SRC_PORT_EIRQ1 1U /* PORT_EIRQ1 */ +#define INT_SRC_PORT_EIRQ2 2U /* PORT_EIRQ2 */ +#define INT_SRC_PORT_EIRQ3 3U /* PORT_EIRQ3 */ +#define INT_SRC_PORT_EIRQ4 4U /* PORT_EIRQ4 */ +#define INT_SRC_PORT_EIRQ5 5U /* PORT_EIRQ5 */ +#define INT_SRC_PORT_EIRQ6 6U /* PORT_EIRQ6 */ +#define INT_SRC_PORT_EIRQ7 7U /* PORT_EIRQ7 */ +#define INT_SRC_PORT_EIRQ8 8U /* PORT_EIRQ8 */ +#define INT_SRC_PORT_EIRQ9 9U /* PORT_EIRQ9 */ +#define INT_SRC_PORT_EIRQ10 10U /* PORT_EIRQ10 */ +#define INT_SRC_PORT_EIRQ11 11U /* PORT_EIRQ11 */ +#define INT_SRC_PORT_EIRQ12 12U /* PORT_EIRQ12 */ +#define INT_SRC_PORT_EIRQ13 13U /* PORT_EIRQ13 */ +#define INT_SRC_PORT_EIRQ14 14U /* PORT_EIRQ14 */ +#define INT_SRC_PORT_EIRQ15 15U /* PORT_EIRQ15 */ + +/* DMA_1 */ +#define INT_SRC_DMA1_TC0 32U /* DMA_1_TC0 */ +#define INT_SRC_DMA1_TC1 33U /* DMA_1_TC1 */ +#define INT_SRC_DMA1_TC2 34U /* DMA_1_TC2 */ +#define INT_SRC_DMA1_TC3 35U /* DMA_1_TC3 */ +#define INT_SRC_DMA1_TC4 36U /* DMA_1_TC4 */ +#define INT_SRC_DMA1_TC5 37U /* DMA_1_TC5 */ +#define INT_SRC_DMA1_TC6 38U /* DMA_1_TC6 */ +#define INT_SRC_DMA1_TC7 39U /* DMA_1_TC7 */ +#define INT_SRC_DMA1_BTC0 40U /* DMA_1_BTC0 */ +#define INT_SRC_DMA1_BTC1 41U /* DMA_1_BTC1 */ +#define INT_SRC_DMA1_BTC2 42U /* DMA_1_BTC2 */ +#define INT_SRC_DMA1_BTC3 43U /* DMA_1_BTC3 */ +#define INT_SRC_DMA1_BTC4 44U /* DMA_1_BTC4 */ +#define INT_SRC_DMA1_BTC5 45U /* DMA_1_BTC5 */ +#define INT_SRC_DMA1_BTC6 46U /* DMA_1_BTC6 */ +#define INT_SRC_DMA1_BTC7 47U /* DMA_1_BTC7 */ +#define INT_SRC_DMA1_ERR 48U /* DMA_1_ERR */ +/* EFM */ +#define INT_SRC_EFM_PEERR 49U /* EFM_PEERR */ +#define INT_SRC_EFM_RDCOL 50U /* EFM_RDCOL */ +#define INT_SRC_EFM_OPTEND 51U /* EFM_OPTEND */ +/* QSPI */ +#define INT_SRC_QSPI_INTR 54U /* QSPI_INTR */ +/* DCU */ +#define INT_SRC_DCU1 55U /* DCU1 */ +#define INT_SRC_DCU2 56U /* DCU2 */ +#define INT_SRC_DCU3 57U /* DCU3 */ +#define INT_SRC_DCU4 58U /* DCU4 */ +#define INT_SRC_DCU5 59U /* DCU5 */ +#define INT_SRC_DCU6 60U /* DCU6 */ +#define INT_SRC_DCU7 61U /* DCU7 */ +#define INT_SRC_DCU8 62U /* DCU8 */ +/* DMA2 */ +#define INT_SRC_DMA2_TC0 64U /* DMA_2_TC0 */ +#define INT_SRC_DMA2_TC1 65U /* DMA_2_TC1 */ +#define INT_SRC_DMA2_TC2 66U /* DMA_2_TC2 */ +#define INT_SRC_DMA2_TC3 67U /* DMA_2_TC3 */ +#define INT_SRC_DMA2_TC4 68U /* DMA_2_TC4 */ +#define INT_SRC_DMA2_TC5 69U /* DMA_2_TC5 */ +#define INT_SRC_DMA2_TC6 70U /* DMA_2_TC6 */ +#define INT_SRC_DMA2_TC7 71U /* DMA_2_TC7 */ +#define INT_SRC_DMA2_BTC0 72U /* DMA_2_BTC0 */ +#define INT_SRC_DMA2_BTC1 73U /* DMA_2_BTC1 */ +#define INT_SRC_DMA2_BTC2 74U /* DMA_2_BTC2 */ +#define INT_SRC_DMA2_BTC3 75U /* DMA_2_BTC3 */ +#define INT_SRC_DMA2_BTC4 76U /* DMA_2_BTC4 */ +#define INT_SRC_DMA2_BTC5 77U /* DMA_2_BTC5 */ +#define INT_SRC_DMA2_BTC6 78U /* DMA_2_BTC6 */ +#define INT_SRC_DMA2_BTC7 79U /* DMA_2_BTC7 */ +#define INT_SRC_DMA2_ERR 80U /* DMA_2_ERR */ +/* MAU */ +#define INT_SRC_MAU_SQRT 83U /* MAU_SQRT */ +/* DVP */ +#define INT_SRC_DVP_FRAMSTA 84U /* DVP_FRAMSTA */ +#define INT_SRC_DVP_LINESTA 85U /* DVP_LINESTA */ +#define INT_SRC_DVP_LINEEND 86U /* DVP_LINEEND */ +#define INT_SRC_DVP_FRAMEND 87U /* DVP_FRAMEND */ +#define INT_SRC_DVP_SQUERR 88U /* DVP_SQUERR */ +#define INT_SRC_DVP_FIFOERR 89U /* DVP_FIFOERR */ +/* FMAC */ +#define INT_SRC_FMAC_1 91U /* FMAC_1_FIR */ +#define INT_SRC_FMAC_2 92U /* FMAC_2_FIR */ +#define INT_SRC_FMAC_3 93U /* FMAC_3_FIR */ +#define INT_SRC_FMAC_4 94U /* FMAC_4_FIR */ +/* TIMER0 */ +#define INT_SRC_TMR0_1_CMP_A 96U /* TMR0_1_CMPA */ +#define INT_SRC_TMR0_1_CMP_B 97U /* TMR0_1_CMPB */ +#define INT_SRC_TMR0_2_CMP_A 98U /* TMR0_2_CMPA */ +#define INT_SRC_TMR0_2_CMP_B 99U /* TMR0_2_CMPB */ +/* TIMER2 */ +#define INT_SRC_TMR2_1_CMP_A 100U /* TMR2_1_CMPA */ +#define INT_SRC_TMR2_1_CMP_B 101U /* TMR2_1_CMPB */ +#define INT_SRC_TMR2_1_OVF_A 102U /* TMR2_1_OVFA */ +#define INT_SRC_TMR2_1_OVF_B 103U /* TMR2_1_OVFB */ +#define INT_SRC_TMR2_2_CMP_A 104U /* TMR2_2_CMPA */ +#define INT_SRC_TMR2_2_CMP_B 105U /* TMR2_2_CMPB */ +#define INT_SRC_TMR2_2_OVF_A 106U /* TMR2_2_OVFA */ +#define INT_SRC_TMR2_2_OVF_B 107U /* TMR2_2_OVFB */ +#define INT_SRC_TMR2_3_CMP_A 108U /* TMR2_3_CMPA */ +#define INT_SRC_TMR2_3_CMP_B 109U /* TMR2_3_CMPB */ +#define INT_SRC_TMR2_3_OVF_A 110U /* TMR2_3_OVFA */ +#define INT_SRC_TMR2_3_OVF_B 111U /* TMR2_3_OVFB */ +#define INT_SRC_TMR2_4_CMP_A 112U /* TMR2_4_CMPA */ +#define INT_SRC_TMR2_4_CMP_B 113U /* TMR2_4_CMPB */ +#define INT_SRC_TMR2_4_OVF_A 114U /* TMR2_4_OVFA */ +#define INT_SRC_TMR2_4_OVF_B 115U /* TMR2_4_OVFB */ +/* RTC */ +#define INT_SRC_RTC_TP 120U /* RTC_TP */ +#define INT_SRC_RTC_ALM 121U /* RTC_ALM */ +#define INT_SRC_RTC_PRD 122U /* RTC_PRD */ +/* XTAL */ +#define INT_SRC_XTAL_STOP 125U /* XTAL_STOP */ +/* WKTM */ +#define INT_SRC_WKTM_PRD 126U /* WKTM_PRD */ +/* SWDT */ +#define INT_SRC_SWDT_REFUDF 127U /* SWDT_REFUDF */ +/* TIMER6_1 */ +#define INT_SRC_TMR6_1_GCMP_A 128U /* TMR6_1_GCMA */ +#define INT_SRC_TMR6_1_GCMP_B 129U /* TMR6_1_GCMB */ +#define INT_SRC_TMR6_1_GCMP_C 130U /* TMR6_1_GCMC */ +#define INT_SRC_TMR6_1_GCMP_D 131U /* TMR6_1_GCMD */ +#define INT_SRC_TMR6_1_GCMP_E 132U /* TMR6_1_GCME */ +#define INT_SRC_TMR6_1_GCMP_F 133U /* TMR6_1_GCMF */ +#define INT_SRC_TMR6_1_OVF 134U /* TMR6_1_GOVF */ +#define INT_SRC_TMR6_1_UDF 135U /* TMR6_1_GUDF */ +/* TIMER4_1 */ +#define INT_SRC_TMR4_1_GCMP_UH 136U /* TMR4_1_GCMUH */ +#define INT_SRC_TMR4_1_GCMP_UL 137U /* TMR4_1_GCMUL */ +#define INT_SRC_TMR4_1_GCMP_VH 138U /* TMR4_1_GCMVH */ +#define INT_SRC_TMR4_1_GCMP_VL 139U /* TMR4_1_GCMVL */ +#define INT_SRC_TMR4_1_GCMP_WH 140U /* TMR4_1_GCMWH */ +#define INT_SRC_TMR4_1_GCMP_WL 141U /* TMR4_1_GCMWL */ +#define INT_SRC_TMR4_1_OVF 142U /* TMR4_1_GOVF */ +#define INT_SRC_TMR4_1_UDF 143U /* TMR4_1_GUDF */ +/* TIMER6_2 */ +#define INT_SRC_TMR6_2_GCMP_A 144U /* TMR6_2_GCMA */ +#define INT_SRC_TMR6_2_GCMP_B 145U /* TMR6_2_GCMB */ +#define INT_SRC_TMR6_2_GCMP_C 146U /* TMR6_2_GCMC */ +#define INT_SRC_TMR6_2_GCMP_D 147U /* TMR6_2_GCMD */ +#define INT_SRC_TMR6_2_GCMP_E 148U /* TMR6_2_GCME */ +#define INT_SRC_TMR6_2_GCMP_F 149U /* TMR6_2_GCMF */ +#define INT_SRC_TMR6_2_OVF 150U /* TMR6_2_GOVF */ +#define INT_SRC_TMR6_2_UDF 151U /* TMR6_2_GUDF */ +/* TIMER4_2 */ +#define INT_SRC_TMR4_2_GCMP_UH 152U /* TMR4_2_GCMUH */ +#define INT_SRC_TMR4_2_GCMP_UL 153U /* TMR4_2_GCMUL */ +#define INT_SRC_TMR4_2_GCMP_VH 154U /* TMR4_2_GCMVH */ +#define INT_SRC_TMR4_2_GCMP_VL 155U /* TMR4_2_GCMVL */ +#define INT_SRC_TMR4_2_GCMP_WH 156U /* TMR4_2_GCMWH */ +#define INT_SRC_TMR4_2_GCMP_WL 157U /* TMR4_2_GCMWL */ +#define INT_SRC_TMR4_2_OVF 158U /* TMR4_2_GOVF */ +#define INT_SRC_TMR4_2_UDF 159U /* TMR4_2_GUDF */ +/* TIMER6_3 */ +#define INT_SRC_TMR6_3_GCMP_A 160U /* TMR6_3_GCMA */ +#define INT_SRC_TMR6_3_GCMP_B 161U /* TMR6_3_GCMB */ +#define INT_SRC_TMR6_3_GCMP_C 162U /* TMR6_3_GCMC */ +#define INT_SRC_TMR6_3_GCMP_D 163U /* TMR6_3_GCMD */ +#define INT_SRC_TMR6_3_GCMP_E 164U /* TMR6_3_GCME */ +#define INT_SRC_TMR6_3_GCMP_F 165U /* TMR6_3_GCMF */ +#define INT_SRC_TMR6_3_OVF 166U /* TMR6_3_GOVF */ +#define INT_SRC_TMR6_3_UDF 167U /* TMR6_3_GUDF */ +/* TIMER4_3 */ +#define INT_SRC_TMR4_3_GCMP_UH 168U /* TMR4_3_GCMUH */ +#define INT_SRC_TMR4_3_GCMP_UL 169U /* TMR4_3_GCMUL */ +#define INT_SRC_TMR4_3_GCMP_VH 170U /* TMR4_3_GCMVH */ +#define INT_SRC_TMR4_3_GCMP_VL 171U /* TMR4_3_GCMVL */ +#define INT_SRC_TMR4_3_GCMP_WH 172U /* TMR4_3_GCMWH */ +#define INT_SRC_TMR4_3_GCMP_WL 173U /* TMR4_3_GCMWL */ +#define INT_SRC_TMR4_3_OVF 174U /* TMR4_3_GOVF */ +#define INT_SRC_TMR4_3_UDF 175U /* TMR4_3_GUDF */ +/* TIMER6_1 */ +#define INT_SRC_TMR6_1_DTE 176U /* TMR6_1_GDTE */ +#define INT_SRC_TMR6_1_SCMP_A 179U /* TMR6_1_SCMA */ +#define INT_SRC_TMR6_1_SCMP_B 180U /* TMR6_1_SCMB */ +/* TIMER4_1 */ +#define INT_SRC_TMR4_1_RELOAD_U 181U /* TMR4_1_RLOU */ +#define INT_SRC_TMR4_1_RELOAD_V 182U /* TMR4_1_RLOV */ +#define INT_SRC_TMR4_1_RELOAD_W 183U /* TMR4_1_RLOW */ +/* TIMER6_2 */ +#define INT_SRC_TMR6_2_DTE 184U /* TMR6_2_GDTE */ +#define INT_SRC_TMR6_2_SCMP_A 187U /* TMR6_2_SCMA */ +#define INT_SRC_TMR6_2_SCMP_B 188U /* TMR6_2_SCMB */ +/* TIMER4_2 */ +#define INT_SRC_TMR4_2_RELOAD_U 189U /* TMR4_2_RLOU */ +#define INT_SRC_TMR4_2_RELOAD_V 190U /* TMR4_2_RLOV */ +#define INT_SRC_TMR4_2_RELOAD_W 191U /* TMR4_2_RLOW */ +/* TIMER6_3 */ +#define INT_SRC_TMR6_3_DTE 192U /* TMR6_3_GDTE */ +#define INT_SRC_TMR6_3_SCMP_A 195U /* TMR6_3_SCMA */ +#define INT_SRC_TMR6_3_SCMP_B 196U /* TMR6_3_SCMB */ +/* TIMER4_3 */ +#define INT_SRC_TMR4_3_RELOAD_U 197U /* TMR4_3_RLOU */ +#define INT_SRC_TMR4_3_RELOAD_V 198U /* TMR4_3_RLOV */ +#define INT_SRC_TMR4_3_RELOAD_W 199U /* TMR4_3_RLOW */ +/* TIMER6_4 TIMER6_5 */ +#define INT_SRC_TMR6_4_GCMP_A 208U /* TMR6_4_GCMA */ +#define INT_SRC_TMR6_4_GCMP_B 209U /* TMR6_4_GCMB */ +#define INT_SRC_TMR6_4_GCMP_C 210U /* TMR6_4_GCMC */ +#define INT_SRC_TMR6_4_GCMP_D 211U /* TMR6_4_GCMD */ +#define INT_SRC_TMR6_4_GCMP_E 212U /* TMR6_4_GCME */ +#define INT_SRC_TMR6_4_GCMP_F 213U /* TMR6_4_GCMF */ +#define INT_SRC_TMR6_4_OVF 214U /* TMR6_4_GOVF */ +#define INT_SRC_TMR6_4_UDF 215U /* TMR6_4_GUDF */ +#define INT_SRC_TMR6_4_DTE 216U /* TMR6_4_GDTE */ +#define INT_SRC_TMR6_4_SCMP_A 219U /* TMR6_4_SCMA */ +#define INT_SRC_TMR6_4_SCMP_B 220U /* TMR6_4_SCMB */ +#define INT_SRC_TMR6_5_GCMP_A 224U /* TMR6_5_GCMA */ +#define INT_SRC_TMR6_5_GCMP_B 225U /* TMR6_5_GCMB */ +#define INT_SRC_TMR6_5_GCMP_C 226U /* TMR6_5_GCMC */ +#define INT_SRC_TMR6_5_GCMP_D 227U /* TMR6_5_GCMD */ +#define INT_SRC_TMR6_5_GCMP_E 228U /* TMR6_5_GCME */ +#define INT_SRC_TMR6_5_GCMP_F 229U /* TMR6_5_GCMF */ +#define INT_SRC_TMR6_5_OVF 230U /* TMR6_5_GOVF */ +#define INT_SRC_TMR6_5_UDF 231U /* TMR6_5_GUDF */ +#define INT_SRC_TMR6_5_DTE 232U /* TMR6_5_GDTE */ +#define INT_SRC_TMR6_5_SCMP_A 235U /* TMR6_5_SCMA */ +#define INT_SRC_TMR6_5_SCMP_B 236U /* TMR6_5_SCMB */ +/* TIMERA_1 */ +#define INT_SRC_TMRA_1_OVF 237U /* TMRA_1_OVF */ +#define INT_SRC_TMRA_1_UDF 238U /* TMRA_1_UDF */ +#define INT_SRC_TMRA_1_CMP 239U /* TMRA_1_CMP */ +/* TIMER6_6 */ +#define INT_SRC_TMR6_6_GCMP_A 240U /* TMR6_6_GCMA */ +#define INT_SRC_TMR6_6_GCMP_B 241U /* TMR6_6_GCMB */ +#define INT_SRC_TMR6_6_GCMP_C 242U /* TMR6_6_GCMC */ +#define INT_SRC_TMR6_6_GCMP_D 243U /* TMR6_6_GCMD */ +#define INT_SRC_TMR6_6_GCMP_E 244U /* TMR6_6_GCME */ +#define INT_SRC_TMR6_6_GCMP_F 245U /* TMR6_6_GCMF */ +#define INT_SRC_TMR6_6_OVF 246U /* TMR6_6_GOVF */ +#define INT_SRC_TMR6_6_UDF 247U /* TMR6_6_GUDF */ +#define INT_SRC_TMR6_6_DTE 248U /* TMR6_6_GDTE */ +#define INT_SRC_TMR6_6_SCMP_A 251U /* TMR6_6_SCMA */ +#define INT_SRC_TMR6_6_SCMP_B 252U /* TMR6_6_SCMB */ +/* TIMERA_2 */ +#define INT_SRC_TMRA_2_OVF 253U /* TMRA_2_OVF */ +#define INT_SRC_TMRA_2_UDF 254U /* TMRA_2_UDF */ +#define INT_SRC_TMRA_2_CMP 255U /* TMRA_2_CMP */ +/* TIMER6_7 */ +#define INT_SRC_TMR6_7_GCMP_A 256U /* TMR6_7_GCMA */ +#define INT_SRC_TMR6_7_GCMP_B 257U /* TMR6_7_GCMB */ +#define INT_SRC_TMR6_7_GCMP_C 258U /* TMR6_7_GCMC */ +#define INT_SRC_TMR6_7_GCMP_D 259U /* TMR6_7_GCMD */ +#define INT_SRC_TMR6_7_GCMP_E 260U /* TMR6_7_GCME */ +#define INT_SRC_TMR6_7_GCMP_F 261U /* TMR6_7_GCMF */ +#define INT_SRC_TMR6_7_OVF 262U /* TMR6_7_GOVF */ +#define INT_SRC_TMR6_7_UDF 263U /* TMR6_7_GUDF */ +#define INT_SRC_TMR6_7_DTE 264U /* TMR6_7_GDTE */ +#define INT_SRC_TMR6_7_SCMP_A 267U /* TMR6_7_SCMA */ +#define INT_SRC_TMR6_7_SCMP_B 268U /* TMR6_7_SCMB */ +/* TIMERA_3 */ +#define INT_SRC_TMRA_3_OVF 269U /* TMRA_3_OVF */ +#define INT_SRC_TMRA_3_UDF 270U /* TMRA_3_UDF */ +#define INT_SRC_TMRA_3_CMP 271U /* TMRA_3_CMP */ +/* TIMER6_8 */ +#define INT_SRC_TMR6_8_GCMP_A 272U /* TMR6_8_GCMA */ +#define INT_SRC_TMR6_8_GCMP_B 273U /* TMR6_8_GCMB */ +#define INT_SRC_TMR6_8_GCMP_C 274U /* TMR6_8_GCMC */ +#define INT_SRC_TMR6_8_GCMP_D 275U /* TMR6_8_GCMD */ +#define INT_SRC_TMR6_8_GCMP_E 276U /* TMR6_8_GCME */ +#define INT_SRC_TMR6_8_GCMP_F 277U /* TMR6_8_GCMF */ +#define INT_SRC_TMR6_8_OVF 278U /* TMR6_8_GOVF */ +#define INT_SRC_TMR6_8_UDF 279U /* TMR6_8_GUDF */ +#define INT_SRC_TMR6_8_DTE 280U /* TMR6_8_GDTE */ +#define INT_SRC_TMR6_8_SCMP_A 283U /* TMR6_8_SCMA */ +#define INT_SRC_TMR6_8_SCMP_B 284U /* TMR6_8_SCMB */ +/* TIMERA_4 */ +#define INT_SRC_TMRA_4_OVF 285U /* TMRA_4_OVF */ +#define INT_SRC_TMRA_4_UDF 286U /* TMRA_4_UDF */ +#define INT_SRC_TMRA_4_CMP 287U /* TMRA_4_CMP */ +/* EMB */ +#define INT_SRC_EMB_GR0 288U /* EMB_GR0 */ +#define INT_SRC_EMB_GR1 289U /* EMB_GR1 */ +#define INT_SRC_EMB_GR2 290U /* EMB_GR2 */ +#define INT_SRC_EMB_GR3 291U /* EMB_GR3 */ +#define INT_SRC_EMB_GR4 292U /* EMB_GR4 */ +#define INT_SRC_EMB_GR5 293U /* EMB_GR5 */ +#define INT_SRC_EMB_GR6 294U /* EMB_GR6 */ +/* USBHS */ +#define INT_SRC_USBHS_EP1_OUT 295U /* USBHS_EP1_OUT */ +#define INT_SRC_USBHS_EP1_IN 296U /* USBHS_EP1_IN */ +#define INT_SRC_USBHS_GLB 297U /* USBHS_GLB */ +#define INT_SRC_USBHS_WKUP 298U /* USBHS_WKUP */ +/* USART1 USART2 */ +#define INT_SRC_USART1_EI 300U /* USART_1_EI */ +#define INT_SRC_USART1_RI 301U /* USART_1_RI */ +#define INT_SRC_USART1_TI 302U /* USART_1_TI */ +#define INT_SRC_USART1_TCI 303U /* USART_1_TCI */ +#define INT_SRC_USART1_RTO 304U /* USART_1_RTO */ +#define INT_SRC_USART2_EI 305U /* USART_2_EI */ +#define INT_SRC_USART2_RI 306U /* USART_2_RI */ +#define INT_SRC_USART2_TI 307U /* USART_2_TI */ +#define INT_SRC_USART2_TCI 308U /* USART_2_TCI */ +#define INT_SRC_USART2_RTO 309U /* USART_2_RTO */ +/* SPI1 SPI2 */ +#define INT_SRC_SPI1_SPRI 310U /* SPI_1_SPRI */ +#define INT_SRC_SPI1_SPTI 311U /* SPI_1_SPTI */ +#define INT_SRC_SPI1_SPII 312U /* SPI_1_SPII */ +#define INT_SRC_SPI1_SPEI 313U /* SPI_1_SPEI */ +#define INT_SRC_SPI2_SPRI 315U /* SPI_2_SPRI */ +#define INT_SRC_SPI2_SPTI 316U /* SPI_2_SPTI */ +#define INT_SRC_SPI2_SPII 317U /* SPI_2_SPII */ +#define INT_SRC_SPI2_SPEI 318U /* SPI_2_SPEI */ +/* TIMERA_5 TIMERA_6 TIMERA_7 TIMERA*/ +#define INT_SRC_TMRA_5_OVF 320U /* TMRA_5_OVF */ +#define INT_SRC_TMRA_5_UDF 321U /* TMRA_5_UDF */ +#define INT_SRC_TMRA_5_CMP 322U /* TMRA_5_CMP */ +#define INT_SRC_TMRA_6_OVF 323U /* TMRA_6_OVF */ +#define INT_SRC_TMRA_6_UDF 324U /* TMRA_6_UDF */ +#define INT_SRC_TMRA_6_CMP 325U /* TMRA_6_CMP */ +#define INT_SRC_TMRA_7_OVF 326U /* TMRA_7_OVF */ +#define INT_SRC_TMRA_7_UDF 327U /* TMRA_7_UDF */ +#define INT_SRC_TMRA_7_CMP 328U /* TMRA_7_CMP */ +#define INT_SRC_TMRA_8_OVF 329U /* TMRA_8_OVF */ +#define INT_SRC_TMRA_8_UDF 330U /* TMRA_8_UDF */ +#define INT_SRC_TMRA_8_CMP 331U /* TMRA_8_CMP */ +/* USART3 USART4 */ +#define INT_SRC_USART3_EI 332U /* USART_3_EI */ +#define INT_SRC_USART3_RI 333U /* USART_3_RI */ +#define INT_SRC_USART3_TI 334U /* USART_3_TI */ +#define INT_SRC_USART3_TCI 335U /* USART_3_TCI */ +#define INT_SRC_USART4_EI 336U /* USART_4_EI */ +#define INT_SRC_USART4_RI 337U /* USART_4_RI */ +#define INT_SRC_USART4_TI 338U /* USART_4_TI */ +#define INT_SRC_USART4_TCI 339U /* USART_4_TCI */ +/* CAN1 CAN2 */ +#define INT_SRC_CAN1_HOST 340U /* CAN_1_HOST */ +#define INT_SRC_CAN2_HOST 341U /* CAN_2_HOST */ +/* SPI3 SPI4 */ +#define INT_SRC_SPI3_SPRI 342U /* SPI_3_SPRI */ +#define INT_SRC_SPI3_SPTI 343U /* SPI_3_SPTI */ +#define INT_SRC_SPI3_SPII 344U /* SPI_3_SPII */ +#define INT_SRC_SPI3_SPEI 345U /* SPI_3_SPEI */ +#define INT_SRC_SPI4_SPRI 347U /* SPI_4_SPRI */ +#define INT_SRC_SPI4_SPTI 348U /* SPI_4_SPTI */ +#define INT_SRC_SPI4_SPII 349U /* SPI_4_SPII */ +#define INT_SRC_SPI4_SPEI 350U /* SPI_4_SPEI */ +/* TIMERA_9 TIMERA_10 TIMER_11 TIMER */ +#define INT_SRC_TMRA_9_OVF 352U /* TMRA_9_OVF */ +#define INT_SRC_TMRA_9_UDF 353U /* TMRA_9_UDF */ +#define INT_SRC_TMRA_9_CMP 354U /* TMRA_9_CMP */ +#define INT_SRC_TMRA_10_OVF 355U /* TMRA_10_OVF */ +#define INT_SRC_TMRA_10_UDF 356U /* TMRA_10_UDF */ +#define INT_SRC_TMRA_10_CMP 357U /* TMRA_10_CMP */ +#define INT_SRC_TMRA_11_OVF 358U /* TMRA_11_OVF */ +#define INT_SRC_TMRA_11_UDF 359U /* TMRA_11_UDF */ +#define INT_SRC_TMRA_11_CMP 360U /* TMRA_11_CMP */ +#define INT_SRC_TMRA_12_OVF 361U /* TMRA_12_OVF */ +#define INT_SRC_TMRA_12_UDF 362U /* TMRA_12_UDF */ +#define INT_SRC_TMRA_12_CMP 363U /* TMRA_12_CMP */ +/* USART5 USART6 */ +#define INT_SRC_USART5_BRKWKPI 364U /* USART_5_BRKWKPI */ +#define INT_SRC_USART5_EI 365U /* USART_5_EI */ +#define INT_SRC_USART5_RI 366U /* USART_5_RI */ +#define INT_SRC_USART5_TI 367U /* USART_5_TI */ +#define INT_SRC_USART5_TCI 368U /* USART_5_TCI */ +#define INT_SRC_USART6_EI 369U /* USART_6_EI */ +#define INT_SRC_USART6_RI 370U /* USART_6_RI */ +#define INT_SRC_USART6_TI 371U /* USART_6_TI */ +#define INT_SRC_USART6_TCI 372U /* USART_6_TCI */ +#define INT_SRC_USART6_RTO 373U /* USART_6_RTO */ +/* SPI5 SPI6 */ +#define INT_SRC_SPI5_SPRI 374U /* SPI_5_SPRI */ +#define INT_SRC_SPI5_SPTI 375U /* SPI_5_SPTI */ +#define INT_SRC_SPI5_SPII 376U /* SPI_5_SPII */ +#define INT_SRC_SPI5_SPEI 377U /* SPI_5_SPEI */ +#define INT_SRC_SPI6_SPRI 379U /* SPI_6_SPRI */ +#define INT_SRC_SPI6_SPTI 380U /* SPI_6_SPTI */ +#define INT_SRC_SPI6_SPII 381U /* SPI_6_SPII */ +#define INT_SRC_SPI6_SPEI 382U /* SPI_6_SPEI */ +/* I2S1 I2S2 */ +#define INT_SRC_I2S1_TXIRQOUT 384U /* I2S_1_TXIRQOUT */ +#define INT_SRC_I2S1_RXIRQOUT 385U /* I2S_1_RXIRQOUT */ +#define INT_SRC_I2S1_ERRIRQOUT 386U /* I2S_1_ERRIRQOUT */ +#define INT_SRC_I2S2_TXIRQOUT 387U /* I2S_2_TXIRQOUT */ +#define INT_SRC_I2S2_RXIRQOUT 388U /* I2S_2_RXIRQOUT */ +#define INT_SRC_I2S2_ERRIRQOUT 389U /* I2S_2_ERRIRQOUT */ +/* USART7 USART8 */ +#define INT_SRC_USART7_EI 390U /* USART_7_EI */ +#define INT_SRC_USART7_RI 391U /* USART_7_RI */ +#define INT_SRC_USART7_TI 392U /* USART_7_TI */ +#define INT_SRC_USART7_TCI 393U /* USART_7_TCI */ +#define INT_SRC_USART7_RTO 394U /* USART_7_RTO */ +#define INT_SRC_USART8_EI 395U /* USART_8_EI */ +#define INT_SRC_USART8_RI 396U /* USART_8_RI */ +#define INT_SRC_USART8_TI 397U /* USART_8_TI */ +#define INT_SRC_USART8_TCI 398U /* USART_8_TCI */ +/* USBFS */ +#define INT_SRC_USBFS_GLB 399U /* USBFS_GLB */ +#define INT_SRC_USBFS_WKUP 400U /* USBFS_WKUP */ +/* HASH */ +#define INT_SRC_HASH 401U /* HASH_INT */ +/* SDIOC */ +#define INT_SRC_SDIOC1_SD 404U /* SDIOC_1_SD */ +#define INT_SRC_SDIOC2_SD 407U /* SDIOC_2_SD */ +/* EVENT PORT */ +#define INT_SRC_EVENT_PORT1 408U /* EVENT_PORT1 */ +#define INT_SRC_EVENT_PORT2 409U /* EVENT_PORT2 */ +#define INT_SRC_EVENT_PORT3 410U /* EVENT_PORT3 */ +#define INT_SRC_EVENT_PORT4 411U /* EVENT_PORT4 */ +/* ETHER */ +#define INT_SRC_ETH_GLB_INT 412U /* ETH_GLB_INT */ +#define INT_SRC_ETH_WKP_INT 413U /* ETH_WKP_INT */ +/* I2S3 I2S4 */ +#define INT_SRC_I2S3_TXIRQOUT 416U /* I2S_3_TXIRQOUT */ +#define INT_SRC_I2S3_RXIRQOUT 417U /* I2S_3_RXIRQOUT */ +#define INT_SRC_I2S3_ERRIRQOUT 418U /* I2S_3_ERRIRQOUT */ +#define INT_SRC_I2S4_TXIRQOUT 419U /* I2S_4_TXIRQOUT */ +#define INT_SRC_I2S4_RXIRQOUT 420U /* I2S_4_RXIRQOUT */ +#define INT_SRC_I2S4_ERRIRQOUT 421U /* I2S_4_ERRIRQOUT */ +/* USART9 USART10 */ +#define INT_SRC_USART9_EI 422U /* USART_9_EI */ +#define INT_SRC_USART9_RI 423U /* USART_9_RI */ +#define INT_SRC_USART9_TI 424U /* USART_9_TI */ +#define INT_SRC_USART9_TCI 425U /* USART_9_TCI */ +#define INT_SRC_USART10_BRKWKPI 426U /* USART_10_BRKWKPI */ +#define INT_SRC_USART10_EI 427U /* USART_10_EI */ +#define INT_SRC_USART10_RI 428U /* USART_10_RI */ +#define INT_SRC_USART10_TI 429U /* USART_10_TI */ +#define INT_SRC_USART10_TCI 430U /* USART_10_TCI */ +/* I2C1 I2C2 I2C3 */ +#define INT_SRC_I2C1_RXI 432U /* I2C_1_RXI */ +#define INT_SRC_I2C1_TXI 433U /* I2C_1_TXI */ +#define INT_SRC_I2C1_TEI 434U /* I2C_1_TEI */ +#define INT_SRC_I2C1_EEI 435U /* I2C_1_EEI */ +#define INT_SRC_I2C2_RXI 436U /* I2C_2_RXI */ +#define INT_SRC_I2C2_TXI 437U /* I2C_2_TXI */ +#define INT_SRC_I2C2_TEI 438U /* I2C_2_TEI */ +#define INT_SRC_I2C2_EEI 439U /* I2C_2_EEI */ +#define INT_SRC_I2C3_RXI 440U /* I2C_3_RXI */ +#define INT_SRC_I2C3_TXI 441U /* I2C_3_TXI */ +#define INT_SRC_I2C3_TEI 442U /* I2C_3_TEI */ +#define INT_SRC_I2C3_EEI 443U /* I2C_3_EEI */ +/* ACMP */ +#define INT_SRC_CMP1 444U /* CMP1 */ +#define INT_SRC_CMP2 445U /* CMP2 */ +#define INT_SRC_CMP3 446U /* CMP3 */ +#define INT_SRC_CMP4 447U /* CMP4 */ +/* I2C4 I2C5 I2C6 */ +#define INT_SRC_I2C4_RXI 448U /* I2C_4_RXI */ +#define INT_SRC_I2C4_TXI 449U /* I2C_4_TXI */ +#define INT_SRC_I2C4_TEI 450U /* I2C_4_TEI */ +#define INT_SRC_I2C4_EEI 451U /* I2C_4_EEI */ +#define INT_SRC_I2C5_RXI 452U /* I2C_5_RXI */ +#define INT_SRC_I2C5_TXI 453U /* I2C_5_TXI */ +#define INT_SRC_I2C5_TEI 454U /* I2C_5_TEI */ +#define INT_SRC_I2C5_EEI 455U /* I2C_5_EEI */ +#define INT_SRC_I2C6_RXI 456U /* I2C_6_RXI */ +#define INT_SRC_I2C6_TXI 457U /* I2C_6_TXI */ +#define INT_SRC_I2C6_TEI 458U /* I2C_6_TEI */ +#define INT_SRC_I2C6_EEI 459U /* I2C_6_EEI */ +/* USART1 */ +#define INT_SRC_USART1_WUPI 460U /* USART_1_WUPI */ +/* LVD */ +#define INT_SRC_LVD1 461U /* LVD1 */ +#define INT_SRC_LVD2 462U /* LVD2 */ +/* OTS */ +#define INT_SRC_OTS 463U /* OTS */ +/* FCM */ +#define INT_SRC_FCMFERRI 464U /* FCMFERRI */ +#define INT_SRC_FCMMENDI 465U /* FCMMENDI */ +#define INT_SRC_FCMCOVFI 466U /* FCMCOVFI */ +/* WDT */ +#define INT_SRC_WDT_REFUDF 467U /* WDT_REFUDF */ +/* CTC */ +#define INT_SRC_CTC_ERR 468U /* CTC_ERR */ +/* ADC */ +#define INT_SRC_ADC1_EOCA 480U /* ADC_1_EOCA */ +#define INT_SRC_ADC1_EOCB 481U /* ADC_1_EOCB */ +#define INT_SRC_ADC1_CMP0 482U /* ADC_1_CMP0 */ +#define INT_SRC_ADC1_CMP1 483U /* ADC_1_CMP1 */ +#define INT_SRC_ADC2_EOCA 484U /* ADC_2_EOCA */ +#define INT_SRC_ADC2_EOCB 485U /* ADC_2_EOCB */ +#define INT_SRC_ADC2_CMP0 486U /* ADC_2_CMP0 */ +#define INT_SRC_ADC2_CMP1 487U /* ADC_2_CMP1 */ +#define INT_SRC_ADC3_EOCA 488U /* ADC_3_EOCA */ +#define INT_SRC_ADC3_EOCB 489U /* ADC_3_EOCB */ +#define INT_SRC_ADC3_CMP0 490U /* ADC_3_CMP0 */ +#define INT_SRC_ADC3_CMP1 491U /* ADC_3_CMP1 */ +/* TRNG */ +#define INT_SRC_TRNG_END 492U /* TRNG_END */ +/* NFC */ +#define INT_SRC_NFC_INT 496U /* NFC_INT */ +#define INT_SRC_MAX 511U + +/** + * @brief Event Source Number + */ +#define EVT_SRC_SWI_IRQ0 0 /* SWI_IRQ0 */ +#define EVT_SRC_SWI_IRQ1 1 /* SWI_IRQ1 */ +#define EVT_SRC_SWI_IRQ2 2 /* SWI_IRQ2 */ +#define EVT_SRC_SWI_IRQ3 3 /* SWI_IRQ3 */ +#define EVT_SRC_SWI_IRQ4 4 /* SWI_IRQ4 */ +#define EVT_SRC_SWI_IRQ5 5 /* SWI_IRQ5 */ +#define EVT_SRC_SWI_IRQ6 6 /* SWI_IRQ6 */ +#define EVT_SRC_SWI_IRQ7 7 /* SWI_IRQ7 */ +#define EVT_SRC_SWI_IRQ8 8 /* SWI_IRQ8 */ +#define EVT_SRC_SWI_IRQ9 9 /* SWI_IRQ9 */ +#define EVT_SRC_SWI_IRQ10 10 /* SWI_IRQ10 */ +#define EVT_SRC_SWI_IRQ11 11 /* SWI_IRQ11 */ +#define EVT_SRC_SWI_IRQ12 12 /* SWI_IRQ12 */ +#define EVT_SRC_SWI_IRQ13 13 /* SWI_IRQ13 */ +#define EVT_SRC_SWI_IRQ14 14 /* SWI_IRQ14 */ +#define EVT_SRC_SWI_IRQ15 15 /* SWI_IRQ15 */ +#define EVT_SRC_SWI_IRQ16 16 /* SWI_IRQ16 */ +#define EVT_SRC_SWI_IRQ17 17 /* SWI_IRQ17 */ +#define EVT_SRC_SWI_IRQ18 18 /* SWI_IRQ18 */ +#define EVT_SRC_SWI_IRQ19 19 /* SWI_IRQ19 */ +#define EVT_SRC_SWI_IRQ20 20 /* SWI_IRQ20 */ +#define EVT_SRC_SWI_IRQ21 21 /* SWI_IRQ21 */ +#define EVT_SRC_SWI_IRQ22 22 /* SWI_IRQ22 */ +#define EVT_SRC_SWI_IRQ23 23 /* SWI_IRQ23 */ +#define EVT_SRC_SWI_IRQ24 24 /* SWI_IRQ24 */ +#define EVT_SRC_SWI_IRQ25 25 /* SWI_IRQ25 */ +#define EVT_SRC_SWI_IRQ26 26 /* SWI_IRQ26 */ +#define EVT_SRC_SWI_IRQ27 27 /* SWI_IRQ27 */ +#define EVT_SRC_SWI_IRQ28 28 /* SWI_IRQ28 */ +#define EVT_SRC_SWI_IRQ29 29 /* SWI_IRQ29 */ +#define EVT_SRC_SWI_IRQ30 30 /* SWI_IRQ30 */ +#define EVT_SRC_SWI_IRQ31 31 /* SWI_IRQ31 */ + +/* External Interrupt. */ +#define EVT_SRC_PORT_EIRQ0 0 /* PORT_EIRQ0 */ +#define EVT_SRC_PORT_EIRQ1 1 /* PORT_EIRQ1 */ +#define EVT_SRC_PORT_EIRQ2 2 /* PORT_EIRQ2 */ +#define EVT_SRC_PORT_EIRQ3 3 /* PORT_EIRQ3 */ +#define EVT_SRC_PORT_EIRQ4 4 /* PORT_EIRQ4 */ +#define EVT_SRC_PORT_EIRQ5 5 /* PORT_EIRQ5 */ +#define EVT_SRC_PORT_EIRQ6 6 /* PORT_EIRQ6 */ +#define EVT_SRC_PORT_EIRQ7 7 /* PORT_EIRQ7 */ +#define EVT_SRC_PORT_EIRQ8 8 /* PORT_EIRQ8 */ +#define EVT_SRC_PORT_EIRQ9 9 /* PORT_EIRQ9 */ +#define EVT_SRC_PORT_EIRQ10 10 /* PORT_EIRQ10 */ +#define EVT_SRC_PORT_EIRQ11 11 /* PORT_EIRQ11 */ +#define EVT_SRC_PORT_EIRQ12 12 /* PORT_EIRQ12 */ +#define EVT_SRC_PORT_EIRQ13 13 /* PORT_EIRQ13 */ +#define EVT_SRC_PORT_EIRQ14 14 /* PORT_EIRQ14 */ +#define EVT_SRC_PORT_EIRQ15 15 /* PORT_EIRQ15 */ + +/* DMA_1 */ +#define EVT_SRC_DMA1_TC0 32U /* DMA_1_TC0 */ +#define EVT_SRC_DMA1_TC1 33U /* DMA_1_TC1 */ +#define EVT_SRC_DMA1_TC2 34U /* DMA_1_TC2 */ +#define EVT_SRC_DMA1_TC3 35U /* DMA_1_TC3 */ +#define EVT_SRC_DMA1_TC4 36U /* DMA_1_TC4 */ +#define EVT_SRC_DMA1_TC5 37U /* DMA_1_TC5 */ +#define EVT_SRC_DMA1_TC6 38U /* DMA_1_TC6 */ +#define EVT_SRC_DMA1_TC7 39U /* DMA_1_TC7 */ +#define EVT_SRC_DMA1_BTC0 40U /* DMA_1_BTC0 */ +#define EVT_SRC_DMA1_BTC1 41U /* DMA_1_BTC1 */ +#define EVT_SRC_DMA1_BTC2 42U /* DMA_1_BTC2 */ +#define EVT_SRC_DMA1_BTC3 43U /* DMA_1_BTC3 */ +#define EVT_SRC_DMA1_BTC4 44U /* DMA_1_BTC4 */ +#define EVT_SRC_DMA1_BTC5 45U /* DMA_1_BTC5 */ +#define EVT_SRC_DMA1_BTC6 46U /* DMA_1_BTC6 */ +#define EVT_SRC_DMA1_BTC7 47U /* DMA_1_BTC7 */ +/* EFM */ +#define EVT_SRC_EFM_OPTEND 51U /* EFM_OPTEND */ +/* USBFS */ +#define EVT_SRC_USBFS_SOF 52U /* USBFS_SOF */ +/* USBHS */ +#define EVT_SRC_USBHS_SOF 53U /* USBHS_SOF */ +/* DCU */ +#define EVT_SRC_DCU1 55U /* DCU1 */ +#define EVT_SRC_DCU2 56U /* DCU2 */ +#define EVT_SRC_DCU3 57U /* DCU3 */ +#define EVT_SRC_DCU4 58U /* DCU4 */ +#define EVT_SRC_DCU5 59U /* DCU5 */ +#define EVT_SRC_DCU6 60U /* DCU6 */ +#define EVT_SRC_DCU7 61U /* DCU7 */ +#define EVT_SRC_DCU8 62U /* DCU8 */ +/* DMA_2 */ +#define EVT_SRC_DMA2_TC0 64U /* DMA_2_TC0 */ +#define EVT_SRC_DMA2_TC1 65U /* DMA_2_TC1 */ +#define EVT_SRC_DMA2_TC2 66U /* DMA_2_TC2 */ +#define EVT_SRC_DMA2_TC3 67U /* DMA_2_TC3 */ +#define EVT_SRC_DMA2_TC4 68U /* DMA_2_TC4 */ +#define EVT_SRC_DMA2_TC5 69U /* DMA_2_TC5 */ +#define EVT_SRC_DMA2_TC6 70U /* DMA_2_TC6 */ +#define EVT_SRC_DMA2_TC7 71U /* DMA_2_TC7 */ +#define EVT_SRC_DMA2_BTC0 72U /* DMA_2_BTC0 */ +#define EVT_SRC_DMA2_BTC1 73U /* DMA_2_BTC1 */ +#define EVT_SRC_DMA2_BTC2 74U /* DMA_2_BTC2 */ +#define EVT_SRC_DMA2_BTC3 75U /* DMA_2_BTC3 */ +#define EVT_SRC_DMA2_BTC4 76U /* DMA_2_BTC4 */ +#define EVT_SRC_DMA2_BTC5 77U /* DMA_2_BTC5 */ +#define EVT_SRC_DMA2_BTC6 78U /* DMA_2_BTC6 */ +#define EVT_SRC_DMA2_BTC7 79U /* DMA_2_BTC7 */ +/* MAU */ +#define EVT_SRC_MAU_SQRT 83U /* MAU_SQRT */ +/* DVP */ +#define EVT_SRC_DVP_FRAMSTA 84U /* DVP_FRAMSTA */ +#define EVT_SRC_DVP_LINESTA 85U /* DVP_LINESTA */ +#define EVT_SRC_DVP_LINEEND 86U /* DVP_LINEEND */ +#define EVT_SRC_DVP_FRAMEND 87U /* DVP_FRAMEND */ +#define EVT_SRC_DVP_SQUERR 88U /* DVP_SQUERR */ +#define EVT_SRC_DVP_FIFOERR 89U /* DVP_FIFOERR */ +#define EVT_SRC_DVP_DMAREQ 90U /* DVP_DMAREQ */ +/* FMAC */ +#define EVT_SRC_FMAC_1 91U /* FMAC_1_FIR */ +#define EVT_SRC_FMAC_2 92U /* FMAC_2_FIR */ +#define EVT_SRC_FMAC_3 93U /* FMAC_3_FIR */ +#define EVT_SRC_FMAC_4 94U /* FMAC_4_FIR */ +/* TIMER0 */ +#define EVT_SRC_TMR0_1_CMP_A 96U /* TMR0_1_CMPA */ +#define EVT_SRC_TMR0_1_CMP_B 97U /* TMR0_1_CMPB */ +#define EVT_SRC_TMR0_2_CMP_A 98U /* TMR0_2_CMPA */ +#define EVT_SRC_TMR0_2_CMP_B 99U /* TMR0_2_CMPB */ +/* TIMER2 */ +#define EVT_SRC_TMR2_1_CMP_A 100U /* TMR2_1_CMPA */ +#define EVT_SRC_TMR2_1_CMP_B 101U /* TMR2_1_CMPB */ +#define EVT_SRC_TMR2_1_OVF_A 102U /* TMR2_1_OVFA */ +#define EVT_SRC_TMR2_1_OVF_B 103U /* TMR2_1_OVFB */ +#define EVT_SRC_TMR2_2_CMP_A 104U /* TMR2_2_CMPA */ +#define EVT_SRC_TMR2_2_CMP_B 105U /* TMR2_2_CMPB */ +#define EVT_SRC_TMR2_2_OVF_A 106U /* TMR2_2_OVFA */ +#define EVT_SRC_TMR2_2_OVF_B 107U /* TMR2_2_OVFB */ +#define EVT_SRC_TMR2_3_CMP_A 108U /* TMR2_3_CMPA */ +#define EVT_SRC_TMR2_3_CMP_B 109U /* TMR2_3_CMPB */ +#define EVT_SRC_TMR2_3_OVF_A 110U /* TMR2_3_OVFA */ +#define EVT_SRC_TMR2_3_OVF_B 111U /* TMR2_3_OVFB */ +#define EVT_SRC_TMR2_4_CMP_A 112U /* TMR2_4_CMPA */ +#define EVT_SRC_TMR2_4_CMP_B 113U /* TMR2_4_CMPB */ +#define EVT_SRC_TMR2_4_OVF_A 114U /* TMR2_4_OVFA */ +#define EVT_SRC_TMR2_4_OVF_B 115U /* TMR2_4_OVFB */ +/* RTC */ +#define EVT_SRC_RTC_ALM 121U /* RTC_ALM */ +#define EVT_SRC_RTC_PRD 122U /* RTC_PRD */ +/* TIMER6_1 */ +#define EVT_SRC_TMR6_1_GCMP_A 128U /* TMR6_1_GCMA */ +#define EVT_SRC_TMR6_1_GCMP_B 129U /* TMR6_1_GCMB */ +#define EVT_SRC_TMR6_1_GCMP_C 130U /* TMR6_1_GCMC */ +#define EVT_SRC_TMR6_1_GCMP_D 131U /* TMR6_1_GCMD */ +#define EVT_SRC_TMR6_1_GCMP_E 132U /* TMR6_1_GCME */ +#define EVT_SRC_TMR6_1_GCMP_F 133U /* TMR6_1_GCMF */ +#define EVT_SRC_TMR6_1_OVF 134U /* TMR6_1_GOVF */ +#define EVT_SRC_TMR6_1_UDF 135U /* TMR6_1_GUDF */ +/* TIMER4_1 */ +#define EVT_SRC_TMR4_1_SCMP0 136U /* TMR4_1_SCM0 */ +#define EVT_SRC_TMR4_1_SCMP1 137U /* TMR4_1_SCM1 */ +#define EVT_SRC_TMR4_1_SCMP2 138U /* TMR4_1_SCM2 */ +#define EVT_SRC_TMR4_1_SCMP3 139U /* TMR4_1_SCM3 */ +#define EVT_SRC_TMR4_1_SCMP4 140U /* TMR4_1_SCM4 */ +#define EVT_SRC_TMR4_1_SCMP5 141U /* TMR4_1_SCM5 */ +/* TIMER6_2 */ +#define EVT_SRC_TMR6_2_GCMP_A 144U /* TMR6_2_GCMA */ +#define EVT_SRC_TMR6_2_GCMP_B 145U /* TMR6_2_GCMB */ +#define EVT_SRC_TMR6_2_GCMP_C 146U /* TMR6_2_GCMC */ +#define EVT_SRC_TMR6_2_GCMP_D 147U /* TMR6_2_GCMD */ +#define EVT_SRC_TMR6_2_GCMP_E 148U /* TMR6_2_GCME */ +#define EVT_SRC_TMR6_2_GCMP_F 149U /* TMR6_2_GCMF */ +#define EVT_SRC_TMR6_2_OVF 150U /* TMR6_2_GOVF */ +#define EVT_SRC_TMR6_2_UDF 151U /* TMR6_2_GUDF */ +/* TIMER4_2 */ +#define EVT_SRC_TMR4_2_SCMP0 152U /* TMR4_2_SCM0 */ +#define EVT_SRC_TMR4_2_SCMP1 153U /* TMR4_2_SCM1 */ +#define EVT_SRC_TMR4_2_SCMP2 154U /* TMR4_2_SCM2 */ +#define EVT_SRC_TMR4_2_SCMP3 155U /* TMR4_2_SCM3 */ +#define EVT_SRC_TMR4_2_SCMP4 156U /* TMR4_2_SCM4 */ +#define EVT_SRC_TMR4_2_SCMP5 157U /* TMR4_2_SCM5 */ +/* TIMER6_3 */ +#define EVT_SRC_TMR6_3_GCMP_A 160U /* TMR6_3_GCMA */ +#define EVT_SRC_TMR6_3_GCMP_B 161U /* TMR6_3_GCMB */ +#define EVT_SRC_TMR6_3_GCMP_C 162U /* TMR6_3_GCMC */ +#define EVT_SRC_TMR6_3_GCMP_D 163U /* TMR6_3_GCMD */ +#define EVT_SRC_TMR6_3_GCMP_E 164U /* TMR6_3_GCME */ +#define EVT_SRC_TMR6_3_GCMP_F 165U /* TMR6_3_GCMF */ +#define EVT_SRC_TMR6_3_OVF 166U /* TMR6_3_GOVF */ +#define EVT_SRC_TMR6_3_UDF 167U /* TMR6_3_GUDF */ +/* TIMER4_3 */ +#define EVT_SRC_TMR4_3_SCMP0 168U /* TMR4_3_SCM0 */ +#define EVT_SRC_TMR4_3_SCMP1 169U /* TMR4_3_SCM1 */ +#define EVT_SRC_TMR4_3_SCMP2 170U /* TMR4_3_SCM2 */ +#define EVT_SRC_TMR4_3_SCMP3 171U /* TMR4_3_SCM3 */ +#define EVT_SRC_TMR4_3_SCMP4 172U /* TMR4_3_SCM4 */ +#define EVT_SRC_TMR4_3_SCMP5 173U /* TMR4_3_SCM5 */ +/* TIMER6 */ +#define EVT_SRC_TMR6_1_SCMP_A 179U /* TMR6_1_SCMA */ +#define EVT_SRC_TMR6_1_SCMP_B 180U /* TMR6_1_SCMB */ +#define EVT_SRC_TMR6_2_SCMP_A 187U /* TMR6_2_SCMA */ +#define EVT_SRC_TMR6_2_SCMP_B 188U /* TMR6_2_SCMB */ +#define EVT_SRC_TMR6_3_SCMP_A 195U /* TMR6_3_SCMA */ +#define EVT_SRC_TMR6_3_SCMP_B 196U /* TMR6_3_SCMB */ +#define EVT_SRC_TMR6_4_GCMP_A 208U /* TMR6_4_GCMA */ +#define EVT_SRC_TMR6_4_GCMP_B 209U /* TMR6_4_GCMB */ +#define EVT_SRC_TMR6_4_GCMP_C 210U /* TMR6_4_GCMC */ +#define EVT_SRC_TMR6_4_GCMP_D 211U /* TMR6_4_GCMD */ +#define EVT_SRC_TMR6_4_GCMP_E 212U /* TMR6_4_GCME */ +#define EVT_SRC_TMR6_4_GCMP_F 213U /* TMR6_4_GCMF */ +#define EVT_SRC_TMR6_4_OVF 214U /* TMR6_4_GOVF */ +#define EVT_SRC_TMR6_4_UDF 215U /* TMR6_4_GUDF */ +#define EVT_SRC_TMR6_4_SCMP_A 219U /* TMR6_4_SCMA */ +#define EVT_SRC_TMR6_4_SCMP_B 220U /* TMR6_4_SCMB */ +#define EVT_SRC_TMR6_5_GCMP_A 224U /* TMR6_5_GCMA */ +#define EVT_SRC_TMR6_5_GCMP_B 225U /* TMR6_5_GCMB */ +#define EVT_SRC_TMR6_5_GCMP_C 226U /* TMR6_5_GCMC */ +#define EVT_SRC_TMR6_5_GCMP_D 227U /* TMR6_5_GCMD */ +#define EVT_SRC_TMR6_5_GCMP_E 228U /* TMR6_5_GCME */ +#define EVT_SRC_TMR6_5_GCMP_F 229U /* TMR6_5_GCMF */ +#define EVT_SRC_TMR6_5_OVF 230U /* TMR6_5_GOVF */ +#define EVT_SRC_TMR6_5_UDF 231U /* TMR6_5_GUDF */ +#define EVT_SRC_TMR6_5_SCMP_A 235U /* TMR6_5_SCMA */ +#define EVT_SRC_TMR6_5_SCMP_B 236U /* TMR6_5_SCMB */ +/* TIMERA_1 */ +#define EVT_SRC_TMRA_1_OVF 237U /* TMRA_1_OVF */ +#define EVT_SRC_TMRA_1_UDF 238U /* TMRA_1_UDF */ +#define EVT_SRC_TMRA_1_CMP 239U /* TMRA_1_CMP */ +/* TIMER6_6 */ +#define EVT_SRC_TMR6_6_GCMP_A 240U /* TMR6_6_GCMA */ +#define EVT_SRC_TMR6_6_GCMP_B 241U /* TMR6_6_GCMB */ +#define EVT_SRC_TMR6_6_GCMP_C 242U /* TMR6_6_GCMC */ +#define EVT_SRC_TMR6_6_GCMP_D 243U /* TMR6_6_GCMD */ +#define EVT_SRC_TMR6_6_GCMP_E 244U /* TMR6_6_GCME */ +#define EVT_SRC_TMR6_6_GCMP_F 245U /* TMR6_6_GCMF */ +#define EVT_SRC_TMR6_6_OVF 246U /* TMR6_6_GOVF */ +#define EVT_SRC_TMR6_6_UDF 247U /* TMR6_6_GUDF */ +#define EVT_SRC_TMR6_6_SCMP_A 251U /* TMR6_6_SCMA */ +#define EVT_SRC_TMR6_6_SCMP_B 252U /* TMR6_6_SCMB */ +/* TIMERA_2 */ +#define EVT_SRC_TMRA_2_OVF 253U /* TMRA_2_OVF */ +#define EVT_SRC_TMRA_2_UDF 254U /* TMRA_2_UDF */ +#define EVT_SRC_TMRA_2_CMP 255U /* TMRA_2_CMP */ +/* TIMER6_7 */ +#define EVT_SRC_TMR6_7_GCMP_A 256U /* TMR6_7_GCMA */ +#define EVT_SRC_TMR6_7_GCMP_B 257U /* TMR6_7_GCMB */ +#define EVT_SRC_TMR6_7_GCMP_C 258U /* TMR6_7_GCMC */ +#define EVT_SRC_TMR6_7_GCMP_D 259U /* TMR6_7_GCMD */ +#define EVT_SRC_TMR6_7_GCMP_E 260U /* TMR6_7_GCME */ +#define EVT_SRC_TMR6_7_GCMP_F 261U /* TMR6_7_GCMF */ +#define EVT_SRC_TMR6_7_OVF 262U /* TMR6_7_GOVF */ +#define EVT_SRC_TMR6_7_UDF 263U /* TMR6_7_GUDF */ +#define EVT_SRC_TMR6_7_SCMP_A 267U /* TMR6_7_SCMA */ +#define EVT_SRC_TMR6_7_SCMP_B 268U /* TMR6_7_SCMB */ +/* TIMERA_3 */ +#define EVT_SRC_TMRA_3_OVF 269U /* TMRA_3_OVF */ +#define EVT_SRC_TMRA_3_UDF 270U /* TMRA_3_UDF */ +#define EVT_SRC_TMRA_3_CMP 271U /* TMRA_3_CMP */ +/* TIMER6_8 */ +#define EVT_SRC_TMR6_8_GCMP_A 272U /* TMR6_8_GCMA */ +#define EVT_SRC_TMR6_8_GCMP_B 273U /* TMR6_8_GCMB */ +#define EVT_SRC_TMR6_8_GCMP_C 274U /* TMR6_8_GCMC */ +#define EVT_SRC_TMR6_8_GCMP_D 275U /* TMR6_8_GCMD */ +#define EVT_SRC_TMR6_8_GCMP_E 276U /* TMR6_8_GCME */ +#define EVT_SRC_TMR6_8_GCMP_F 277U /* TMR6_8_GCMF */ +#define EVT_SRC_TMR6_8_OVF 278U /* TMR6_8_GOVF */ +#define EVT_SRC_TMR6_8_UDF 279U /* TMR6_8_GUDF */ +#define EVT_SRC_TMR6_8_SCMP_A 283U /* TMR6_8_SCMA */ +#define EVT_SRC_TMR6_8_SCMP_B 284U /* TMR6_8_SCMB */ +/* TIMERA_4 */ +#define EVT_SRC_TMRA_4_OVF 285U /* TMRA_4_OVF */ +#define EVT_SRC_TMRA_4_UDF 286U /* TMRA_4_UDF */ +#define EVT_SRC_TMRA_4_CMP 287U /* TMRA_4_CMP */ +/* AOS_STRG */ +#define EVT_SRC_AOS_STRG 299U /* AOS_STRG */ +/* USART1 USART2 */ +#define EVT_SRC_USART1_EI 300U /* USART_1_EI */ +#define EVT_SRC_USART1_RI 301U /* USART_1_RI */ +#define EVT_SRC_USART1_TI 302U /* USART_1_TI */ +#define EVT_SRC_USART1_TCI 303U /* USART_1_TCI */ +#define EVT_SRC_USART1_RTO 304U /* USART_1_RTO */ +#define EVT_SRC_USART2_EI 305U /* USART_2_EI */ +#define EVT_SRC_USART2_RI 306U /* USART_2_RI */ +#define EVT_SRC_USART2_TI 307U /* USART_2_TI */ +#define EVT_SRC_USART2_TCI 308U /* USART_2_TCI */ +#define EVT_SRC_USART2_RTO 309U /* USART_2_RTO */ +/* SPI1 SPI2 */ +#define EVT_SRC_SPI1_SPRI 310U /* SPI_1_SPRI */ +#define EVT_SRC_SPI1_SPTI 311U /* SPI_1_SPTI */ +#define EVT_SRC_SPI1_SPII 312U /* SPI_1_SPII */ +#define EVT_SRC_SPI1_SPEI 313U /* SPI_1_SPEI */ +#define EVT_SRC_SPI1_SPEND 314U /* SPI_1_SPEND */ +#define EVT_SRC_SPI2_SPRI 315U /* SPI_2_SPRI */ +#define EVT_SRC_SPI2_SPTI 316U /* SPI_2_SPTI */ +#define EVT_SRC_SPI2_SPII 317U /* SPI_2_SPII */ +#define EVT_SRC_SPI2_SPEI 318U /* SPI_2_SPEI */ +#define EVT_SRC_SPI2_SPEND 319U /* SPI_2_SPEND */ +/* TIMERA_5 TIMERA_6 TIMERA_7 TIMERA_8 */ +#define EVT_SRC_TMRA_5_OVF 320U /* TMRA_5_OVF */ +#define EVT_SRC_TMRA_5_UDF 321U /* TMRA_5_UDF */ +#define EVT_SRC_TMRA_5_CMP 322U /* TMRA_5_CMP */ +#define EVT_SRC_TMRA_6_OVF 323U /* TMRA_6_OVF */ +#define EVT_SRC_TMRA_6_UDF 324U /* TMRA_6_UDF */ +#define EVT_SRC_TMRA_6_CMP 325U /* TMRA_6_CMP */ +#define EVT_SRC_TMRA_7_OVF 326U /* TMRA_7_OVF */ +#define EVT_SRC_TMRA_7_UDF 327U /* TMRA_7_UDF */ +#define EVT_SRC_TMRA_7_CMP 328U /* TMRA_7_CMP */ +#define EVT_SRC_TMRA_8_OVF 329U /* TMRA_8_OVF */ +#define EVT_SRC_TMRA_8_UDF 330U /* TMRA_8_UDF */ +#define EVT_SRC_TMRA_8_CMP 331U /* TMRA_8_CMP */ +/* USART3 USART4 */ +#define EVT_SRC_USART3_EI 332U /* USART_3_EI */ +#define EVT_SRC_USART3_RI 333U /* USART_3_RI */ +#define EVT_SRC_USART3_TI 334U /* USART_3_TI */ +#define EVT_SRC_USART3_TCI 335U /* USART_3_TCI */ +#define EVT_SRC_USART4_EI 336U /* USART_4_EI */ +#define EVT_SRC_USART4_RI 337U /* USART_4_RI */ +#define EVT_SRC_USART4_TI 338U /* USART_4_TI */ +#define EVT_SRC_USART4_TCI 339U /* USART_4_TCI */ +/* SPI3 SPI4 */ +#define EVT_SRC_SPI3_SPRI 342U /* SPI_3_SPRI */ +#define EVT_SRC_SPI3_SPTI 343U /* SPI_3_SPTI */ +#define EVT_SRC_SPI3_SPII 344U /* SPI_3_SPII */ +#define EVT_SRC_SPI3_SPEI 345U /* SPI_3_SPEI */ +#define EVT_SRC_SPI3_SPEND 346U /* SPI_3_SPEND */ +#define EVT_SRC_SPI4_SPRI 347U /* SPI_4_SPRI */ +#define EVT_SRC_SPI4_SPTI 348U /* SPI_4_SPTI */ +#define EVT_SRC_SPI4_SPII 349U /* SPI_4_SPII */ +#define EVT_SRC_SPI4_SPEI 350U /* SPI_4_SPEI */ +#define EVT_SRC_SPI4_SPEND 351U /* SPI_4_SPEND */ +/* TIMERA_9 TIMERA_10 TIMERA_11 TIMERA_12 */ +#define EVT_SRC_TMRA_9_OVF 352U /* TMRA_9_OVF */ +#define EVT_SRC_TMRA_9_UDF 353U /* TMRA_9_UDF */ +#define EVT_SRC_TMRA_9_CMP 354U /* TMRA_9_CMP */ +#define EVT_SRC_TMRA_10_OVF 355U /* TMRA_10_OVF */ +#define EVT_SRC_TMRA_10_UDF 356U /* TMRA_10_UDF */ +#define EVT_SRC_TMRA_10_CMP 357U /* TMRA_10_CMP */ +#define EVT_SRC_TMRA_11_OVF 358U /* TMRA_11_OVF */ +#define EVT_SRC_TMRA_11_UDF 359U /* TMRA_11_UDF */ +#define EVT_SRC_TMRA_11_CMP 360U /* TMRA_11_CMP */ +#define EVT_SRC_TMRA_12_OVF 361U /* TMRA_12_OVF */ +#define EVT_SRC_TMRA_12_UDF 362U /* TMRA_12_UDF */ +#define EVT_SRC_TMRA_12_CMP 363U /* TMRA_12_CMP */ +/* USART5 USART6 */ +#define EVT_SRC_USART5_BRKWKPI 364U /* USART_5_BRKWKPI */ +#define EVT_SRC_USART5_EI 365U /* USART_5_EI */ +#define EVT_SRC_USART5_RI 366U /* USART_5_RI */ +#define EVT_SRC_USART5_TI 367U /* USART_5_TI */ +#define EVT_SRC_USART5_TCI 368U /* USART_5_TCI */ +#define EVT_SRC_USART6_EI 369U /* USART_6_EI */ +#define EVT_SRC_USART6_RI 370U /* USART_6_RI */ +#define EVT_SRC_USART6_TI 371U /* USART_6_TI */ +#define EVT_SRC_USART6_TCI 372U /* USART_6_TCI */ +#define EVT_SRC_USART6_RTO 373U /* USART_6_RTO */ +/* SPI5 SPI6 */ +#define EVT_SRC_SPI5_SPRI 374U /* SPI_5_SPRI */ +#define EVT_SRC_SPI5_SPTI 375U /* SPI_5_SPTI */ +#define EVT_SRC_SPI5_SPII 376U /* SPI_5_SPII */ +#define EVT_SRC_SPI5_SPEI 377U /* SPI_5_SPEI */ +#define EVT_SRC_SPI5_SPEND 378U /* SPI_5_SPEND */ +#define EVT_SRC_SPI6_SPRI 379U /* SPI_6_SPRI */ +#define EVT_SRC_SPI6_SPTI 380U /* SPI_6_SPTI */ +#define EVT_SRC_SPI6_SPII 381U /* SPI_6_SPII */ +#define EVT_SRC_SPI6_SPEI 382U /* SPI_6_SPEI */ +#define EVT_SRC_SPI6_SPEND 383U /* SPI_6_SPEND */ +/* I2S1 I2S2 */ +#define EVT_SRC_I2S1_TXIRQOUT 384U /* I2S_1_TXIRQOUT */ +#define EVT_SRC_I2S1_RXIRQOUT 385U /* I2S_1_RXIRQOUT */ +#define EVT_SRC_I2S2_TXIRQOUT 387U /* I2S_2_TXIRQOUT */ +#define EVT_SRC_I2S2_RXIRQOUT 388U /* I2S_2_RXIRQOUT */ +/* USART7 USART8 */ +#define EVT_SRC_USART7_EI 390U /* USART_7_EI */ +#define EVT_SRC_USART7_RI 391U /* USART_7_RI */ +#define EVT_SRC_USART7_TI 392U /* USART_7_TI */ +#define EVT_SRC_USART7_TCI 393U /* USART_7_TCI */ +#define EVT_SRC_USART7_RTO 394U /* USART_7_RTO */ +#define EVT_SRC_USART8_EI 395U /* USART_8_EI */ +#define EVT_SRC_USART8_RI 396U /* USART_8_RI */ +#define EVT_SRC_USART8_TI 397U /* USART_8_TI */ +#define EVT_SRC_USART8_TCI 398U /* USART_8_TCI */ +/* HASH */ +#define EVT_SRC_HASH 401U /* HASH_INT */ +/* SDIOC */ +#define EVT_SRC_SDIOC1_DMAR 402U /* SDIOC_1_DMAR */ +#define EVT_SRC_SDIOC1_DMAW 403U /* SDIOC_1_DMAW */ +#define EVT_SRC_SDIOC2_DMAR 405U /* SDIOC_2_DMAR */ +#define EVT_SRC_SDIOC2_DMAW 406U /* SDIOC_2_DMAW */ +/* EVENT PORT */ +#define EVT_SRC_EVENT_PORT1 408U /* EVENT_PORT1 */ +#define EVT_SRC_EVENT_PORT2 409U /* EVENT_PORT2 */ +#define EVT_SRC_EVENT_PORT3 410U /* EVENT_PORT3 */ +#define EVT_SRC_EVENT_PORT4 411U /* EVENT_PORT4 */ +/* ETHER */ +#define EVT_SRC_ETH_PPS_OUT_0 414U /* ETH_PPS_OUT_0 */ +#define EVT_SRC_ETH_PPS_OUT_1 415U /* ETH_PPS_OUT_1 */ +/* I2S3 I2S4 */ +#define EVT_SRC_I2S3_TXIRQOUT 416U /* I2S_3_TXIRQOUT */ +#define EVT_SRC_I2S3_RXIRQOUT 417U /* I2S_3_RXIRQOUT */ +#define EVT_SRC_I2S4_TXIRQOUT 419U /* I2S_4_TXIRQOUT */ +#define EVT_SRC_I2S4_RXIRQOUT 420U /* I2S_4_RXIRQOUT */ +/* USART9 USART10 */ +#define EVT_SRC_USART9_EI 422U /* USART_9_EI */ +#define EVT_SRC_USART9_RI 423U /* USART_9_RI */ +#define EVT_SRC_USART9_TI 424U /* USART_9_TI */ +#define EVT_SRC_USART9_TCI 425U /* USART_9_TCI */ +#define EVT_SRC_USART10_BRKWKPI 426U /* USART_10_BRKWKPI */ +#define EVT_SRC_USART10_EI 427U /* USART_10_EI */ +#define EVT_SRC_USART10_RI 428U /* USART_10_RI */ +#define EVT_SRC_USART10_TI 429U /* USART_10_TI */ +#define EVT_SRC_USART10_TCI 430U /* USART_10_TCI */ +/* I2C1 I2C2 I2C3 */ +#define EVT_SRC_I2C1_RXI 432U /* I2C_1_RXI */ +#define EVT_SRC_I2C1_TXI 433U /* I2C_1_TXI */ +#define EVT_SRC_I2C1_TEI 434U /* I2C_1_TEI */ +#define EVT_SRC_I2C1_EEI 435U /* I2C_1_EEI */ +#define EVT_SRC_I2C2_RXI 436U /* I2C_2_RXI */ +#define EVT_SRC_I2C2_TXI 437U /* I2C_2_TXI */ +#define EVT_SRC_I2C2_TEI 438U /* I2C_2_TEI */ +#define EVT_SRC_I2C2_EEI 439U /* I2C_2_EEI */ +#define EVT_SRC_I2C3_RXI 440U /* I2C_3_RXI */ +#define EVT_SRC_I2C3_TXI 441U /* I2C_3_TXI */ +#define EVT_SRC_I2C3_TEI 442U /* I2C_3_TEI */ +#define EVT_SRC_I2C3_EEI 443U /* I2C_3_EEI */ +/* ACMP */ +#define EVT_SRC_CMP1 444U /* CMP1 */ +#define EVT_SRC_CMP2 445U /* CMP2 */ +#define EVT_SRC_CMP3 446U /* CMP3 */ +#define EVT_SRC_CMP4 447U /* CMP4 */ +/* I2C4 I2C5 I2C6 */ +#define EVT_SRC_I2C4_RXI 448U /* I2C_4_RXI */ +#define EVT_SRC_I2C4_TXI 449U /* I2C_4_TXI */ +#define EVT_SRC_I2C4_TEI 450U /* I2C_4_TEI */ +#define EVT_SRC_I2C4_EEI 451U /* I2C_4_EEI */ +#define EVT_SRC_I2C5_RXI 452U /* I2C_5_RXI */ +#define EVT_SRC_I2C5_TXI 453U /* I2C_5_TXI */ +#define EVT_SRC_I2C5_TEI 454U /* I2C_5_TEI */ +#define EVT_SRC_I2C5_EEI 455U /* I2C_5_EEI */ +#define EVT_SRC_I2C6_RXI 456U /* I2C_6_RXI */ +#define EVT_SRC_I2C6_TXI 457U /* I2C_6_TXI */ +#define EVT_SRC_I2C6_TEI 458U /* I2C_6_TEI */ +#define EVT_SRC_I2C6_EEI 459U /* I2C_6_EEI */ +/* LVD */ +#define EVT_SRC_LVD1 461U /* LVD1 */ +#define EVT_SRC_LVD2 462U /* LVD2 */ +/* OTS */ +#define EVT_SRC_OTS 463U /* OTS */ +/* WDT */ +#define EVT_SRC_WDT_REFUDF 467U /* WDT_REFUDF */ +/* ADC */ +#define EVT_SRC_ADC1_EOCA 480U /* ADC_1_EOCA */ +#define EVT_SRC_ADC1_EOCB 481U /* ADC_1_EOCB */ +#define EVT_SRC_ADC1_CMP0 482U /* ADC_1_CMP0 */ +#define EVT_SRC_ADC1_CMP1 483U /* ADC_1_CMP1 */ +#define EVT_SRC_ADC2_EOCA 484U /* ADC_2_EOCA */ +#define EVT_SRC_ADC2_EOCB 485U /* ADC_2_EOCB */ +#define EVT_SRC_ADC2_CMP0 486U /* ADC_2_CMP0 */ +#define EVT_SRC_ADC2_CMP1 487U /* ADC_2_CMP1 */ +#define EVT_SRC_ADC3_EOCA 488U /* ADC_3_EOCA */ +#define EVT_SRC_ADC3_EOCB 489U /* ADC_3_EOCB */ +#define EVT_SRC_ADC3_CMP0 490U /* ADC_3_CMP0 */ +#define EVT_SRC_ADC3_CMP1 491U /* ADC_3_CMP1 */ +/* TRNG */ +#define EVT_SRC_TRNG_END 492U /* TRNG_END */ +#define EVT_SRC_MAX 511U + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_HC32F4A0_INT_EVT_H_ */ diff --git a/include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-intc.h b/include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-intc.h new file mode 100644 index 0000000000000..bde0f5f3ee4f6 --- /dev/null +++ b/include/zephyr/dt-bindings/interrupt-controller/hc32f4a0-intc.h @@ -0,0 +1,714 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_HC32F4A0_INTC_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_HC32F4A0_INTC_H_ + +#include + +/* Ext ch0 */ +#define HC32_EXTINT0_IRQ_NUM INT128_IRQn +#define HC32_EXTINT0_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch1 */ +#define HC32_EXTINT1_IRQ_NUM INT128_IRQn +#define HC32_EXTINT1_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch2 */ +#define HC32_EXTINT2_IRQ_NUM INT128_IRQn +#define HC32_EXTINT2_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch3 */ +#define HC32_EXTINT3_IRQ_NUM INT128_IRQn +#define HC32_EXTINT3_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch4 */ +#define HC32_EXTINT4_IRQ_NUM INT128_IRQn +#define HC32_EXTINT4_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch5 */ +#define HC32_EXTINT5_IRQ_NUM INT128_IRQn +#define HC32_EXTINT5_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch6 */ +#define HC32_EXTINT6_IRQ_NUM INT128_IRQn +#define HC32_EXTINT6_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch7 */ +#define HC32_EXTINT7_IRQ_NUM INT128_IRQn +#define HC32_EXTINT7_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch8 */ +#define HC32_EXTINT8_IRQ_NUM INT128_IRQn +#define HC32_EXTINT8_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch9 */ +#define HC32_EXTINT9_IRQ_NUM INT128_IRQn +#define HC32_EXTINT9_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch10 */ +#define HC32_EXTINT10_IRQ_NUM INT128_IRQn +#define HC32_EXTINT10_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch11 */ +#define HC32_EXTINT11_IRQ_NUM INT128_IRQn +#define HC32_EXTINT11_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch12 */ +#define HC32_EXTINT12_IRQ_NUM INT128_IRQn +#define HC32_EXTINT12_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch13 */ +#define HC32_EXTINT13_IRQ_NUM INT128_IRQn +#define HC32_EXTINT13_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch14 */ +#define HC32_EXTINT14_IRQ_NUM INT128_IRQn +#define HC32_EXTINT14_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* Ext ch15 */ +#define HC32_EXTINT15_IRQ_NUM INT128_IRQn +#define HC32_EXTINT15_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* DMA1 ch0 */ +#define HC32_DMA1_CH0_IRQ_NUM INT038_IRQn +#define HC32_DMA1_CH0_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch1 */ +#define HC32_DMA1_CH1_IRQ_NUM INT039_IRQn +#define HC32_DMA1_CH1_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch2 */ +#define HC32_DMA1_CH2_IRQ_NUM INT040_IRQn +#define HC32_DMA1_CH2_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch3 */ +#define HC32_DMA1_CH3_IRQ_NUM INT041_IRQn +#define HC32_DMA1_CH3_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 err */ +#define HC32_DMA1_ERR_IRQ_NUM INT042_IRQn +#define HC32_DMA1_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch4 */ +#define HC32_DMA1_CH4_IRQ_NUM INT043_IRQn +#define HC32_DMA1_CH4_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch5 */ +#define HC32_DMA1_CH5_IRQ_NUM INT008_IRQn +#define HC32_DMA1_CH5_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch6 */ +#define HC32_DMA1_CH6_IRQ_NUM INT007_IRQn +#define HC32_DMA1_CH6_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch7 */ +#define HC32_DMA1_CH7_IRQ_NUM INT006_IRQn +#define HC32_DMA1_CH7_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* DMA2 ch0 */ +#define HC32_DMA2_CH0_IRQ_NUM INT044_IRQn +#define HC32_DMA2_CH0_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA2 ch1 */ +#define HC32_DMA2_CH1_IRQ_NUM INT045_IRQn +#define HC32_DMA2_CH1_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA2 ch2 */ +#define HC32_DMA2_CH2_IRQ_NUM INT046_IRQn +#define HC32_DMA2_CH2_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA2 ch3 */ +#define HC32_DMA2_CH3_IRQ_NUM INT047_IRQn +#define HC32_DMA2_CH3_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA2 err */ +#define HC32_DMA2_ERR_IRQ_NUM INT048_IRQn +#define HC32_DMA2_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA2 ch4 */ +#define HC32_DMA2_CH4_IRQ_NUM INT049_IRQn +#define HC32_DMA2_CH4_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch5 */ +#define HC32_DMA2_CH5_IRQ_NUM INT005_IRQn +#define HC32_DMA2_CH5_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch6 */ +#define HC32_DMA2_CH6_IRQ_NUM INT004_IRQn +#define HC32_DMA2_CH6_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* DMA1 ch7 */ +#define HC32_DMA2_CH7_IRQ_NUM INT003_IRQn +#define HC32_DMA2_CH7_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* USART */ +#define HC32_UART1_RXERR_IRQ_NUM INT010_IRQn +#define HC32_UART1_RXERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART1_RX_IRQ_NUM INT014_IRQn +#define HC32_UART1_RX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART1_TX_IRQ_NUM INT015_IRQn +#define HC32_UART1_TX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART1_TX_CPLT_IRQ_NUM INT016_IRQn +#define HC32_UART1_TX_CPLT_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART1_RXTO_IRQ_NUM INT011_IRQn +#define HC32_UART1_RXTO_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART2_RXERR_IRQ_NUM INT086_IRQn +#define HC32_UART2_RXERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART2_RX_IRQ_NUM INT087_IRQn +#define HC32_UART2_RX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART2_TX_IRQ_NUM INT088_IRQn +#define HC32_UART2_TX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART2_TX_CPLT_IRQ_NUM INT089_IRQn +#define HC32_UART2_TX_CPLT_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART2_RXTO_IRQ_NUM INT090_IRQn +#define HC32_UART2_RXTO_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART3_RXERR_IRQ_NUM INT092_IRQn +#define HC32_UART3_RXERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART3_RX_IRQ_NUM INT093_IRQn +#define HC32_UART3_RX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART3_TX_IRQ_NUM INT094_IRQn +#define HC32_UART3_TX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART3_TX_CPLT_IRQ_NUM INT095_IRQn +#define HC32_UART3_TX_CPLT_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART3_RXTO_IRQ_NUM INT096_IRQn +#define HC32_UART3_RXTO_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART4_RXERR_IRQ_NUM INT092_IRQn +#define HC32_UART4_RXERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART4_RX_IRQ_NUM INT093_IRQn +#define HC32_UART4_RX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART4_TX_IRQ_NUM INT094_IRQn +#define HC32_UART4_TX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART4_RXTO_IRQ_NUM INT096_IRQn +#define HC32_UART4_RXTO_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_UART4_TX_CPLT_IRQ_NUM INT095_IRQn +#define HC32_UART4_TX_CPLT_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* SPI */ +#define HC32_SPI1_ERR_IRQ_NUM INT086_IRQn +#define HC32_SPI1_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI1_RBF_IRQ_NUM INT087_IRQn +#define HC32_SPI1_RBF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI1_TBE_IRQ_NUM INT088_IRQn +#define HC32_SPI1_TBE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI2_ERR_IRQ_NUM INT089_IRQn +#define HC32_SPI2_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI2_RBF_IRQ_NUM INT090_IRQn +#define HC32_SPI2_RBF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI2_TBE_IRQ_NUM INT091_IRQn +#define HC32_SPI2_TBE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI3_ERR_IRQ_NUM INT092_IRQn +#define HC32_SPI3_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI3_RBF_IRQ_NUM INT093_IRQn +#define HC32_SPI3_RBF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI3_TBE_IRQ_NUM INT094_IRQn +#define HC32_SPI3_TBE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI4_ERR_IRQ_NUM INT095_IRQn +#define HC32_SPI4_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI4_RBF_IRQ_NUM INT096_IRQn +#define HC32_SPI4_RBF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI4_TBE_IRQ_NUM INT097_IRQn +#define HC32_SPI4_TBE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI5_ERR_IRQ_NUM INT098_IRQn +#define HC32_SPI5_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI5_RBF_IRQ_NUM INT099_IRQn +#define HC32_SPI5_RBF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI5_TBE_IRQ_NUM INT100_IRQn +#define HC32_SPI5_TBE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI6_ERR_IRQ_NUM INT101_IRQn +#define HC32_SPI6_ERR_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI6_RBF_IRQ_NUM INT102_IRQn +#define HC32_SPI6_RBF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_SPI6_TBE_IRQ_NUM INT103_IRQn +#define HC32_SPI6_TBE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* RTC */ +#define HC32_RTC_ALARM_IRQ_NUM INT050_IRQn +#define HC32_RTC_ALARM_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_RTC_PRD_IRQ_NUM INT051_IRQn +#define HC32_RTC_PRD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA1*/ +#define HC32_TMRA1_OVF_IRQ_NUM INT074_IRQn +#define HC32_TMRA1_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA1_UDF_IRQ_NUM INT075_IRQn +#define HC32_TMRA1_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA1_CMP_IRQ_NUM INT076_IRQn +#define HC32_TMRA1_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA2*/ +#define HC32_TMRA2_OVF_IRQ_NUM INT077_IRQn +#define HC32_TMRA2_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA2_UDF_IRQ_NUM INT078_IRQn +#define HC32_TMRA2_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA2_CMP_IRQ_NUM INT079_IRQn +#define HC32_TMRA2_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA3*/ +#define HC32_TMRA3_OVF_IRQ_NUM INT080_IRQn +#define HC32_TMRA3_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA3_UDF_IRQ_NUM INT081_IRQn +#define HC32_TMRA3_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA3_CMP_IRQ_NUM INT082_IRQn +#define HC32_TMRA3_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA4*/ +#define HC32_TMRA4_OVF_IRQ_NUM INT083_IRQn +#define HC32_TMRA4_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA4_UDF_IRQ_NUM INT084_IRQn +#define HC32_TMRA4_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA4_CMP_IRQ_NUM INT085_IRQn +#define HC32_TMRA4_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA5*/ +#define HC32_TMRA5_OVF_IRQ_NUM INT092_IRQn +#define HC32_TMRA5_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA5_UDF_IRQ_NUM INT093_IRQn +#define HC32_TMRA5_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA5_CMP_IRQ_NUM INT094_IRQn +#define HC32_TMRA5_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA6*/ +#define HC32_TMRA6_OVF_IRQ_NUM INT092_IRQn +#define HC32_TMRA6_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA6_UDF_IRQ_NUM INT093_IRQn +#define HC32_TMRA6_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA6_CMP_IRQ_NUM INT094_IRQn +#define HC32_TMRA6_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA7*/ +#define HC32_TMRA7_OVF_IRQ_NUM INT095_IRQn +#define HC32_TMRA7_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA7_UDF_IRQ_NUM INT096_IRQn +#define HC32_TMRA7_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA7_CMP_IRQ_NUM INT097_IRQn +#define HC32_TMRA7_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA8*/ +#define HC32_TMRA8_OVF_IRQ_NUM INT095_IRQn +#define HC32_TMRA8_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA8_UDF_IRQ_NUM INT096_IRQn +#define HC32_TMRA8_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA8_CMP_IRQ_NUM INT097_IRQn +#define HC32_TMRA8_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA9*/ +#define HC32_TMRA9_OVF_IRQ_NUM INT098_IRQn +#define HC32_TMRA9_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA9_UDF_IRQ_NUM INT099_IRQn +#define HC32_TMRA9_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA9_CMP_IRQ_NUM INT100_IRQn +#define HC32_TMRA9_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA10*/ +#define HC32_TMRA10_OVF_IRQ_NUM INT098_IRQn +#define HC32_TMRA10_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA10_UDF_IRQ_NUM INT099_IRQn +#define HC32_TMRA10_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA10_CMP_IRQ_NUM INT100_IRQn +#define HC32_TMRA10_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA11*/ +#define HC32_TMRA11_OVF_IRQ_NUM INT101_IRQn +#define HC32_TMRA11_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA11_UDF_IRQ_NUM INT102_IRQn +#define HC32_TMRA11_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA11_CMP_IRQ_NUM INT103_IRQn +#define HC32_TMRA11_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* TimerA12*/ +#define HC32_TMRA12_OVF_IRQ_NUM INT101_IRQn +#define HC32_TMRA12_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA12_UDF_IRQ_NUM INT102_IRQn +#define HC32_TMRA12_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMRA12_CMP_IRQ_NUM INT103_IRQn +#define HC32_TMRA12_CMP_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer41*/ +#define HC32_TMR41_CMP_UH_IRQ_NUM INT092_IRQn +#define HC32_TMR41_CMP_UH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR41_CMP_UL_IRQ_NUM INT093_IRQn +#define HC32_TMR41_CMP_UL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR41_CMP_VH_IRQ_NUM INT094_IRQn +#define HC32_TMR41_CMP_VH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR41_CMP_VL_IRQ_NUM INT095_IRQn +#define HC32_TMR41_CMP_VL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR41_CMP_WH_IRQ_NUM INT012_IRQn +#define HC32_TMR41_CMP_WH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR41_CMP_WL_IRQ_NUM INT013_IRQn +#define HC32_TMR41_CMP_WL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR41_OVF_IRQ_NUM INT096_IRQn +#define HC32_TMR41_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR41_UDF_IRQ_NUM INT097_IRQn +#define HC32_TMR41_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer42*/ +#define HC32_TMR42_CMP_UH_IRQ_NUM INT092_IRQn +#define HC32_TMR42_CMP_UH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR42_CMP_UL_IRQ_NUM INT093_IRQn +#define HC32_TMR42_CMP_UL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR42_CMP_VH_IRQ_NUM INT094_IRQn +#define HC32_TMR42_CMP_VH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR42_CMP_VL_IRQ_NUM INT095_IRQn +#define HC32_TMR42_CMP_VL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR42_CMP_WH_IRQ_NUM INT012_IRQn +#define HC32_TMR42_CMP_WH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR42_CMP_WL_IRQ_NUM INT013_IRQn +#define HC32_TMR42_CMP_WL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR42_OVF_IRQ_NUM INT096_IRQn +#define HC32_TMR42_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR42_UDF_IRQ_NUM INT097_IRQn +#define HC32_TMR42_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer43 */ +#define HC32_TMR43_CMP_UH_IRQ_NUM INT098_IRQn +#define HC32_TMR43_CMP_UH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR43_CMP_UL_IRQ_NUM INT099_IRQn +#define HC32_TMR43_CMP_UL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR43_CMP_VH_IRQ_NUM INT100_IRQn +#define HC32_TMR43_CMP_VH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR43_CMP_VL_IRQ_NUM INT101_IRQn +#define HC32_TMR43_CMP_VL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR43_CMP_WH_IRQ_NUM INT012_IRQn +#define HC32_TMR43_CMP_WH_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR43_CMP_WL_IRQ_NUM INT013_IRQn +#define HC32_TMR43_CMP_WL_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR43_OVF_IRQ_NUM INT102_IRQn +#define HC32_TMR43_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR43_UDF_IRQ_NUM INT103_IRQn +#define HC32_TMR43_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer61 interrupt */ +#define HC32_TMR61_CMPA_IRQ_NUM INT056_IRQn +#define HC32_TMR61_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR61_CMPB_IRQ_NUM INT057_IRQn +#define HC32_TMR61_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR61_CMPC_IRQ_NUM INT058_IRQn +#define HC32_TMR61_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR61_CMPD_IRQ_NUM INT059_IRQn +#define HC32_TMR61_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR61_CMPE_IRQ_NUM INT060_IRQn +#define HC32_TMR61_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR61_CMPF_IRQ_NUM INT061_IRQn +#define HC32_TMR61_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR61_OVF_IRQ_NUM INT030_IRQn +#define HC32_TMR61_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR61_UDF_IRQ_NUM INT031_IRQn +#define HC32_TMR61_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer62 interrupt */ +#define HC32_TMR62_CMPA_IRQ_NUM INT056_IRQn +#define HC32_TMR62_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR62_CMPB_IRQ_NUM INT057_IRQn +#define HC32_TMR62_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR62_CMPC_IRQ_NUM INT058_IRQn +#define HC32_TMR62_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR62_CMPD_IRQ_NUM INT059_IRQn +#define HC32_TMR62_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR62_CMPE_IRQ_NUM INT060_IRQn +#define HC32_TMR62_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR62_CMPF_IRQ_NUM INT061_IRQn +#define HC32_TMR62_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR62_OVF_IRQ_NUM INT030_IRQn +#define HC32_TMR62_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR62_UDF_IRQ_NUM INT031_IRQn +#define HC32_TMR62_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer63 interrupt */ +#define HC32_TMR63_CMPA_IRQ_NUM INT062_IRQn +#define HC32_TMR63_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR63_CMPB_IRQ_NUM INT063_IRQn +#define HC32_TMR63_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR63_CMPC_IRQ_NUM INT064_IRQn +#define HC32_TMR63_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR63_CMPD_IRQ_NUM INT065_IRQn +#define HC32_TMR63_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR63_CMPE_IRQ_NUM INT066_IRQn +#define HC32_TMR63_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR63_CMPF_IRQ_NUM INT067_IRQn +#define HC32_TMR63_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR63_OVF_IRQ_NUM INT028_IRQn +#define HC32_TMR63_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR63_UDF_IRQ_NUM INT029_IRQn +#define HC32_TMR63_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer64 interrupt */ +#define HC32_TMR64_CMPA_IRQ_NUM INT068_IRQn +#define HC32_TMR64_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR64_CMPB_IRQ_NUM INT069_IRQn +#define HC32_TMR64_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR64_CMPC_IRQ_NUM INT070_IRQn +#define HC32_TMR64_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR64_CMPD_IRQ_NUM INT071_IRQn +#define HC32_TMR64_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR64_CMPE_IRQ_NUM INT072_IRQn +#define HC32_TMR64_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR64_CMPF_IRQ_NUM INT073_IRQn +#define HC32_TMR64_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR64_OVF_IRQ_NUM INT026_IRQn +#define HC32_TMR64_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR64_UDF_IRQ_NUM INT027_IRQn +#define HC32_TMR64_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer65 interrupt */ +#define HC32_TMR65_CMPA_IRQ_NUM INT074_IRQn +#define HC32_TMR65_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR65_CMPB_IRQ_NUM INT075_IRQn +#define HC32_TMR65_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR65_CMPC_IRQ_NUM INT076_IRQn +#define HC32_TMR65_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR65_CMPD_IRQ_NUM INT077_IRQn +#define HC32_TMR65_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR65_CMPE_IRQ_NUM INT078_IRQn +#define HC32_TMR65_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR65_CMPF_IRQ_NUM INT079_IRQn +#define HC32_TMR65_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR65_OVF_IRQ_NUM INT024_IRQn +#define HC32_TMR65_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR65_UDF_IRQ_NUM INT025_IRQn +#define HC32_TMR65_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer66 interrupt */ +#define HC32_TMR66_CMPA_IRQ_NUM INT074_IRQn +#define HC32_TMR66_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR66_CMPB_IRQ_NUM INT075_IRQn +#define HC32_TMR66_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR66_CMPC_IRQ_NUM INT076_IRQn +#define HC32_TMR66_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR66_CMPD_IRQ_NUM INT077_IRQn +#define HC32_TMR66_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR66_CMPE_IRQ_NUM INT078_IRQn +#define HC32_TMR66_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR66_CMPF_IRQ_NUM INT079_IRQn +#define HC32_TMR66_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR66_OVF_IRQ_NUM INT024_IRQn +#define HC32_TMR66_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR66_UDF_IRQ_NUM INT025_IRQn +#define HC32_TMR66_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer67 interrupt */ +#define HC32_TMR67_CMPA_IRQ_NUM INT080_IRQn +#define HC32_TMR67_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR67_CMPB_IRQ_NUM INT081_IRQn +#define HC32_TMR67_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR67_CMPC_IRQ_NUM INT082_IRQn +#define HC32_TMR67_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR67_CMPD_IRQ_NUM INT083_IRQn +#define HC32_TMR67_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR67_CMPE_IRQ_NUM INT084_IRQn +#define HC32_TMR67_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR67_CMPF_IRQ_NUM INT085_IRQn +#define HC32_TMR67_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR67_OVF_IRQ_NUM INT022_IRQn +#define HC32_TMR67_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR67_UDF_IRQ_NUM INT023_IRQn +#define HC32_TMR67_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* Timer68 interrupt */ +#define HC32_TMR68_CMPA_IRQ_NUM INT080_IRQn +#define HC32_TMR68_CMPA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR68_CMPB_IRQ_NUM INT081_IRQn +#define HC32_TMR68_CMPB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR68_CMPC_IRQ_NUM INT082_IRQn +#define HC32_TMR68_CMPC_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR68_CMPD_IRQ_NUM INT083_IRQn +#define HC32_TMR68_CMPD_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR68_CMPE_IRQ_NUM INT084_IRQn +#define HC32_TMR68_CMPE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR68_CMPF_IRQ_NUM INT085_IRQn +#define HC32_TMR68_CMPF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR68_OVF_IRQ_NUM INT022_IRQn +#define HC32_TMR68_OVF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#define HC32_TMR68_UDF_IRQ_NUM INT023_IRQn +#define HC32_TMR68_UDF_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* I2C share */ +#define HC32_I2C_IRQ_SHARE1_NUM INT141_IRQn +#define HC32_I2C_IRQ_SHARE1_PRIO DDL_IRQ_PRIO_DEFAULT +/* I2C1 */ +#define HC32_I2C1_EE_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C1_EE_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO +#define HC32_I2C1_TE_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C1_TE_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO +#define HC32_I2C1_TX_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C1_TX_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO +#define HC32_I2C1_RX_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C1_RX_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO +/* I2C2 */ +#define HC32_I2C2_EE_IRQ_NUM INT110_IRQn +#define HC32_I2C2_EE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_I2C2_TE_IRQ_NUM INT111_IRQn +#define HC32_I2C2_TE_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_I2C2_TX_IRQ_NUM INT112_IRQn +#define HC32_I2C2_TX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_I2C2_RX_IRQ_NUM INT113_IRQn +#define HC32_I2C2_RX_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +/* I2C3 */ +#define HC32_I2C3_EE_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C3_EE_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO +#define HC32_I2C3_TE_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C3_TE_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO +#define HC32_I2C3_TX_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C3_TX_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO +#define HC32_I2C3_RX_IRQ_NUM HC32_I2C_IRQ_SHARE1_NUM +#define HC32_I2C3_RX_IRQ_PRIO HC32_I2C_IRQ_SHARE1_PRIO + +#define HC32_I2C_IRQ_SHARE2_NUM INT142_IRQn +#define HC32_I2C_IRQ_SHARE2_PRIO DDL_IRQ_PRIO_DEFAULT +/* I2C4 */ +#define HC32_I2C4_EE_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C4_EE_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C4_TE_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C4_TE_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C4_TX_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C4_TX_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C4_RX_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C4_RX_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +/* I2C5 */ +#define HC32_I2C5_EE_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C5_EE_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C5_TE_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C5_TE_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C5_TX_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C5_TX_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C5_RX_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C5_RX_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +/* I2C6 */ +#define HC32_I2C6_EE_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C6_EE_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C6_TE_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C6_TE_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C6_TX_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C6_TX_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO +#define HC32_I2C6_RX_IRQ_NUM HC32_I2C_IRQ_SHARE2_NUM +#define HC32_I2C6_RX_IRQ_PRIO HC32_I2C_IRQ_SHARE2_PRIO + +/* ADC */ +#define HC32_ADC1_EOCA_IRQ_NUM INT122_IRQn +#define HC32_ADC1_EOCA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_ADC1_EOCB_IRQ_NUM INT123_IRQn +#define HC32_ADC1_EOCB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_ADC2_EOCA_IRQ_NUM INT122_IRQn +#define HC32_ADC2_EOCA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_ADC2_EOCB_IRQ_NUM INT123_IRQn +#define HC32_ADC2_EOCB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_ADC3_EOCA_IRQ_NUM INT122_IRQn +#define HC32_ADC3_EOCA_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT +#define HC32_ADC3_EOCB_IRQ_NUM INT123_IRQn +#define HC32_ADC3_EOCB_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +/* QSPI */ +#define HC32_QSPI_IRQ_NUM INT043_IRQn +#define HC32_QSPI_IRQ_PRIO DDL_IRQ_PRIO_DEFAULT + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_HC32F4A0_INTC_H_ */ From 9f765e03beb0b8f9aab15c8417c0f9463a289865 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:57:27 +0800 Subject: [PATCH 07/10] drivers: serial: Add support for HC32F4A0 This is the initial commit to support USART driver for XHSC HC32F4A0 Signed-off-by: Yongbing Liu --- drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 1 + drivers/serial/Kconfig.hc32 | 16 + drivers/serial/uart_hc32.c | 1364 +++++++++++++++++++++++ drivers/serial/uart_hc32.h | 98 ++ dts/bindings/serial/xhsc,hc32-uart.yaml | 19 + 6 files changed, 1499 insertions(+) create mode 100644 drivers/serial/Kconfig.hc32 create mode 100644 drivers/serial/uart_hc32.c create mode 100644 drivers/serial/uart_hc32.h create mode 100644 dts/bindings/serial/xhsc,hc32-uart.yaml diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 63520ac12639d..b6988ddeede53 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -38,6 +38,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_ENE_KB106X uart_ene_kb106x.c) zephyr_library_sources_ifdef(CONFIG_UART_ENE_KB1200 uart_ene_kb1200.c) zephyr_library_sources_ifdef(CONFIG_UART_ESP32 uart_esp32.c) zephyr_library_sources_ifdef(CONFIG_UART_GECKO uart_gecko.c) +zephyr_library_sources_ifdef(CONFIG_UART_HC32 uart_hc32.c) zephyr_library_sources_ifdef(CONFIG_UART_HOSTLINK uart_hostlink.c) zephyr_library_sources_ifdef(CONFIG_UART_IMX uart_imx.c) zephyr_library_sources_ifdef(CONFIG_UART_INFINEON_CAT1 uart_ifx_cat1.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0d58009f31eb2..b545575d44668 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -179,6 +179,7 @@ rsource "Kconfig.ene" rsource "Kconfig.esp32" rsource "Kconfig.gd32" rsource "Kconfig.gecko" +rsource "Kconfig.hc32" rsource "Kconfig.hostlink" rsource "Kconfig.ifx_cat1" rsource "Kconfig.imx" diff --git a/drivers/serial/Kconfig.hc32 b/drivers/serial/Kconfig.hc32 new file mode 100644 index 0000000000000..6fffd5233b9ce --- /dev/null +++ b/drivers/serial/Kconfig.hc32 @@ -0,0 +1,16 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config UART_HC32 + bool "HC32 MCU serial driver" + default y + depends on DT_HAS_XHSC_HC32_UART_ENABLED + select SERIAL_HAS_DRIVER + select HC32_LL_USART + select SERIAL_SUPPORT_INTERRUPT if DT_HAS_XHSC_HC32_INTC_ENABLED + select UART_INTERRUPT_DRIVEN if DT_HAS_XHSC_HC32_INTC_ENABLED + select PINCTRL + help + This option enables the UART driver for HC32 family of + processors. + Set y if you wish to use serial port on HC32 MCU. diff --git a/drivers/serial/uart_hc32.c b/drivers/serial/uart_hc32.c new file mode 100644 index 0000000000000..f173c712300e7 --- /dev/null +++ b/drivers/serial/uart_hc32.c @@ -0,0 +1,1364 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT xhsc_hc32_uart + +/** + * @brief Driver for UART port on HC32 family processor. + * @note + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DMA_TO_BE_SUPPORTED +#include +#include +#endif + +#include +#include "uart_hc32.h" + +#include +#include + +#include +#include +LOG_MODULE_REGISTER(uart_hc32, CONFIG_UART_LOG_LEVEL); + +/* This symbol takes the value 1 if one of the device instances */ +/* is configured in dts with a domain clock */ +#if HC32_DT_INST_DEV_DOMAIN_CLOCK_SUPPORT +#define HC32_UART_DOMAIN_CLOCK_SUPPORT 1 +#else +#define HC32_UART_DOMAIN_CLOCK_SUPPORT 0 +#endif + +static inline void uart_hc32_set_parity(const struct device *dev, uint32_t parity) +{ + const struct uart_hc32_config *config = dev->config; + + USART_SetParity(config->usart, parity); +} + +static inline uint32_t uart_hc32_get_parity(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetParity(config->usart); +} + +static inline void uart_hc32_set_stopbits(const struct device *dev, uint32_t stopbits) +{ + const struct uart_hc32_config *config = dev->config; + + USART_SetStopBit(config->usart, stopbits); +} + +static inline uint32_t uart_hc32_get_stopbits(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetStopBit(config->usart); +} + +static inline void uart_hc32_set_databits(const struct device *dev, uint32_t databits) +{ + const struct uart_hc32_config *config = dev->config; + + USART_SetDataWidth(config->usart, databits); +} + +static inline uint32_t uart_hc32_get_databits(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetDataWidth(config->usart); +} + +static inline void uart_hc32_set_hwctrl(const struct device *dev, uint32_t hwctrl) +{ + const struct uart_hc32_config *config = dev->config; + + USART_SetHWFlowControl(config->usart, hwctrl); +} + +static inline uint32_t uart_hc32_get_hwctrl(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetHWFlowControl(config->usart); +} + +static inline void uart_hc32_set_baudrate(const struct device *dev, uint32_t baud_rate) +{ + const struct uart_hc32_config *config = dev->config; + + (void)USART_SetBaudrate(config->usart, baud_rate, NULL); +} + +static inline uint32_t uart_hc32_cfg2ll_parity(enum uart_config_parity parity) +{ + uint32_t ret_ll_parity = USART_PARITY_NONE; + + switch (parity) { + case UART_CFG_PARITY_ODD: + ret_ll_parity = USART_PARITY_ODD; + break; + case UART_CFG_PARITY_EVEN: + ret_ll_parity = USART_PARITY_EVEN; + break; + case UART_CFG_PARITY_NONE: + default: + break; + } + + return ret_ll_parity; +} + +static inline enum uart_config_parity uart_hc32_ll2cfg_parity(uint32_t parity) +{ + enum uart_config_parity ret_cfg_parity = UART_CFG_PARITY_NONE; + + switch (parity) { + case USART_PARITY_ODD: + ret_cfg_parity = UART_CFG_PARITY_ODD; + break; + case USART_PARITY_EVEN: + ret_cfg_parity = UART_CFG_PARITY_EVEN; + break; + case USART_PARITY_NONE: + default: + break; + } + + return ret_cfg_parity; +} + +static inline uint32_t uart_hc32_cfg2ll_stopbits(enum uart_config_stop_bits sb) +{ + uint32_t ret_ll_stopbits = USART_STOPBIT_1BIT; + +#ifdef USART_STOPBIT_2BIT + if (sb == UART_CFG_STOP_BITS_2) { + ret_ll_stopbits = USART_STOPBIT_2BIT; + } +#endif /* USART_STOPBIT_2BIT */ + + return ret_ll_stopbits; +} + +static inline enum uart_config_stop_bits uart_hc32_ll2cfg_stopbits(uint32_t sb) +{ + enum uart_config_stop_bits ret_cfg_stopbits = UART_CFG_STOP_BITS_1; + +#ifdef USART_STOPBIT_2BIT + if (sb == USART_STOPBIT_2BIT) { + ret_cfg_stopbits = UART_CFG_STOP_BITS_2; + } +#endif /* USART_STOPBIT_2BIT */ + + return ret_cfg_stopbits; +} + +static inline uint32_t uart_hc32_cfg2ll_databits(enum uart_config_data_bits db) +{ + uint32_t ret_ll_databits = USART_DATA_WIDTH_8BIT; + +/* Some MCU's don't support 9B datawidth */ +#ifdef USART_DATA_WIDTH_9BIT + if (db == UART_CFG_DATA_BITS_9) { + ret_ll_databits = USART_DATA_WIDTH_9BIT; + } +#endif /* USART_DATA_WIDTH_9BIT */ + + return ret_ll_databits; +} + +static inline enum uart_config_data_bits uart_hc32_ll2cfg_databits(uint32_t db) +{ + enum uart_config_data_bits ret_cfg_databits = UART_CFG_DATA_BITS_8; + +/* Some MCU's don't support 9B datawidth */ +#ifdef USART_DATA_WIDTH_9BIT + if (db == USART_DATA_WIDTH_9BIT) { + ret_cfg_databits = UART_CFG_DATA_BITS_9; + } +#endif /* USART_DATA_WIDTH_9BIT */ + + return ret_cfg_databits; +} + +/** + * @brief Get DDL hardware flow control define from + * Zephyr hardware flow control option. + * @note Supports only UART_CFG_FLOW_CTRL_RTS_CTS and UART_CFG_FLOW_CTRL_RS485. + * @param fc: Zephyr hardware flow control option. + * @retval USART_HW_FLOWCTRL_RTS, for device under supporting RTS_CTS. + */ +static inline uint32_t uart_hc32_cfg2ll_hwctrl(enum uart_config_flow_control fc) +{ + /* default config */ + return USART_HW_FLOWCTRL_RTS; +} + +/** + * @brief Get Zephyr hardware flow control option from + * DDL hardware flow control define. + * @note + * @param fc: DDL hardware flow control definition. + * @retval UART_CFG_FLOW_CTRL_RTS_CTS, or UART_CFG_FLOW_CTRL_NONE. + */ +static inline enum uart_config_flow_control uart_hc32_ll2cfg_hwctrl(uint32_t fc) +{ + /* DDL driver compatible with cfg, just return none */ + return UART_CFG_FLOW_CTRL_NONE; +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE +static int uart_hc32_configure(const struct device *dev, const struct uart_config *cfg) +{ + const struct uart_hc32_config *config = dev->config; + struct uart_hc32_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; + const uint32_t parity = uart_hc32_cfg2ll_parity(cfg->parity); + const uint32_t stopbits = uart_hc32_cfg2ll_stopbits(cfg->stop_bits); + const uint32_t databits = uart_hc32_cfg2ll_databits(cfg->data_bits); + + /* Hardware doesn't support mark or space parity */ + if ((cfg->parity == UART_CFG_PARITY_MARK) || (cfg->parity == UART_CFG_PARITY_SPACE)) { + return -ENOTSUP; + } + + /* Driver does not supports parity + 9 databits */ + if ((cfg->parity != UART_CFG_PARITY_NONE) && (cfg->data_bits == USART_DATA_WIDTH_9BIT)) { + return -ENOTSUP; + } + + /* When the transformed ddl parity don't match with what was requested, + * then it's not supported + */ + if (uart_hc32_ll2cfg_parity(parity) != cfg->parity) { + return -ENOTSUP; + } + + /* When the transformed ddl stop bits don't match with what was requested, + * then it's not supported + */ + if (uart_hc32_ll2cfg_stopbits(stopbits) != cfg->stop_bits) { + return -ENOTSUP; + } + + /* When the transformed ddl databits don't match with what was requested, + * then it's not supported + */ + if (uart_hc32_ll2cfg_databits(databits) != cfg->data_bits) { + return -ENOTSUP; + } + + USART_FuncCmd(config->usart, USART_TX | USART_RX, DISABLE); + uart_hc32_set_parity(dev, parity); + uart_hc32_set_stopbits(dev, stopbits); + uart_hc32_set_databits(dev, databits); + uart_hc32_set_baudrate(dev, uart_cfg->baudrate); + USART_FuncCmd(config->usart, USART_TX | USART_RX, ENABLE); + + return 0; +} + +static int uart_hc32_config_get(const struct device *dev, struct uart_config *cfg) +{ + struct uart_hc32_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; + + cfg->baudrate = uart_cfg->baudrate; + cfg->parity = uart_hc32_ll2cfg_parity(uart_hc32_get_parity(dev)); + cfg->stop_bits = uart_hc32_ll2cfg_stopbits(uart_hc32_get_stopbits(dev)); + cfg->data_bits = uart_hc32_ll2cfg_databits(uart_hc32_get_databits(dev)); + cfg->flow_ctrl = uart_hc32_ll2cfg_hwctrl(uart_hc32_get_hwctrl(dev)); + + return 0; +} +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +static int uart_hc32_poll_in(const struct device *dev, unsigned char *c) +{ + const struct uart_hc32_config *config = dev->config; + + if (USART_GetStatus(config->usart, USART_FLAG_OVERRUN | USART_FLAG_RX_TIMEOUT)) { + + USART_ClearStatus(config->usart, USART_FLAG_OVERRUN | USART_FLAG_FRAME_ERR); + } + + if (SET != USART_GetStatus(config->usart, USART_FLAG_RX_FULL)) { + return EIO; + } + + *c = (unsigned char)USART_ReadData(config->usart); + return 0; +} + +static void uart_hc32_poll_out(const struct device *dev, unsigned char c) +{ + unsigned int key; + const struct uart_hc32_config *config = dev->config; + + key = irq_lock(); + while (1) { + if (USART_GetStatus(config->usart, USART_FLAG_TX_EMPTY)) { + break; + } + } + + USART_WriteData(config->usart, (uint16_t)c); + irq_unlock(key); +} + +static int uart_hc32_err_check(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + uint32_t err = 0U; + + if (USART_GetStatus(config->usart, USART_FLAG_OVERRUN)) { + err |= UART_ERROR_OVERRUN; + } + + if (USART_GetStatus(config->usart, USART_FLAG_FRAME_ERR)) { + err |= UART_ERROR_FRAMING; + } + + if (USART_GetStatus(config->usart, USART_FLAG_PARITY_ERR)) { + err |= UART_ERROR_PARITY; + } + + return err; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +typedef void (*fifo_fill_fn)(const struct device *dev, const void *tx_data, const uint8_t offset); + +static int uart_hc32_fifo_fill_visitor(const struct device *dev, const void *tx_data, int size, + fifo_fill_fn fill_fn) +{ + const struct uart_hc32_config *config = dev->config; + uint8_t num_tx = 0U; + unsigned int key; + + if (!USART_GetStatus(config->usart, USART_FLAG_TX_EMPTY)) { + return num_tx; + } + + /* Lock interrupts to prevent nested interrupts or thread switch */ + key = irq_lock(); + + /* TXE flag will be set by hardware when moving data */ + while ((size - num_tx > 0) && USART_GetStatus(config->usart, USART_FLAG_TX_EMPTY)) { + /* Send a character */ + fill_fn(dev, tx_data, num_tx); + num_tx++; + } + + irq_unlock(key); + + return num_tx; +} + +static void fifo_fill_with_u8(const struct device *dev, const void *tx_data, const uint8_t offset) +{ + const uint8_t *data = (const uint8_t *)tx_data; + /* Send a character (8bit) */ + uart_hc32_poll_out(dev, data[offset]); +} + +static int uart_hc32_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + if (UART_CFG_DATA_BITS_9 == uart_hc32_ll2cfg_databits(uart_hc32_get_databits(dev))) { + return -ENOTSUP; + } + return uart_hc32_fifo_fill_visitor(dev, (const void *)tx_data, size, fifo_fill_with_u8); +} + +typedef void (*fifo_read_fn)(const struct uart_hc32_config *config, void *rx_data, + const uint8_t offset); + +static int uart_hc32_fifo_read_visitor(const struct device *dev, void *rx_data, const int size, + fifo_read_fn read_fn) +{ + const struct uart_hc32_config *config = dev->config; + uint8_t num_rx = 0U; + + while ((size - num_rx > 0) && USART_GetStatus(config->usart, USART_FLAG_RX_FULL)) { + /* RXNE flag will be cleared upon read from RDR register */ + + read_fn(config, rx_data, num_rx); + num_rx++; + + /* Clear overrun error flag */ + if (USART_GetStatus(config->usart, USART_FLAG_OVERRUN)) { + USART_ClearStatus(config->usart, USART_FLAG_OVERRUN); + } + } + + return num_rx; +} + +static void fifo_read_with_u8(const struct uart_hc32_config *config, void *rx_data, + const uint8_t offset) +{ + uint8_t *data = (uint8_t *)rx_data; + + USART_UART_Receive(config->usart, &data[offset], 1U, 0xFFU); +} + +static int uart_hc32_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + if (UART_CFG_DATA_BITS_9 == uart_hc32_ll2cfg_databits(uart_hc32_get_databits(dev))) { + + return -ENOTSUP; + } + return uart_hc32_fifo_read_visitor(dev, (void *)rx_data, size, fifo_read_with_u8); +} + +static void uart_hc32_irq_tx_enable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + USART_FuncCmd(config->usart, USART_INT_TX_EMPTY | USART_INT_TX_CPLT, ENABLE); +} + +static void uart_hc32_irq_tx_disable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + USART_FuncCmd(config->usart, USART_INT_TX_EMPTY | USART_INT_TX_CPLT, DISABLE); +} + +static int uart_hc32_irq_tx_ready(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetStatus(config->usart, USART_FLAG_TX_EMPTY); +} + +static int uart_hc32_irq_tx_complete(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetStatus(config->usart, USART_FLAG_TX_CPLT); +} + +static void uart_hc32_irq_rx_enable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + USART_FuncCmd(config->usart, USART_INT_RX, ENABLE); +} + +static void uart_hc32_irq_rx_disable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + USART_FuncCmd(config->usart, USART_INT_RX, DISABLE); +} + +static int uart_hc32_irq_rx_ready(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetStatus(config->usart, USART_FLAG_RX_FULL); +} + +static void uart_hc32_irq_err_enable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + /* Enable FE, ORE parity error interruption */ + USART_FuncCmd(config->usart, USART_RX_TIMEOUT | USART_INT_RX_TIMEOUT, ENABLE); +} + +static void uart_hc32_irq_err_disable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + USART_FuncCmd(config->usart, USART_RX_TIMEOUT | USART_INT_RX_TIMEOUT, DISABLE); +} + +static int uart_hc32_irq_is_pending(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + + return USART_GetStatus(config->usart, USART_FLAG_ALL); +} + +static int uart_hc32_irq_update(const struct device *dev) +{ + ARG_UNUSED(dev); + return 1; +} + +/* + * user may use void *user_data = x to specify irq type, the x may be: + * 0:usart_hc32f4_rx_error_isr + * 1:usart_hc32f4_rx_full_isr + * 2:usart_hc32f4_tx_empty_isr + * 3:usart_hc32f4_tx_complete_isr + * 4:usart_hc32f4_rx_timeout_isr + * others or user_data = NULL:set cb for all interrupt handlers + */ +static void uart_hc32_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *user_data) +{ + uint32_t i; + struct uart_hc32_data *data = dev->data; + + if ((user_data == NULL) || (*(uint32_t *)user_data >= HC32_UART_INT_NUM)) { + for (i = 0; i < HC32_UART_INT_NUM; i++) { + data->cb[i].user_cb = cb; + data->cb[i].user_data = user_data; + } + } else { + i = *(uint32_t *)user_data; + data->cb[i].user_cb = cb; + data->cb[i].user_data = user_data; + } +} + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +#ifdef DMA_TO_BE_SUPPORTED + +static inline void async_user_callback(struct uart_hc32_data *data, struct uart_event *event) +{ + if (data->async_cb) { + data->async_cb(data->uart_dev, event, data->async_user_data); + } +} + +static inline void async_evt_rx_rdy(struct uart_hc32_data *data) +{ + LOG_DBG("rx_rdy: (%d %d)", data->dma_rx.offset, data->dma_rx.counter); + + struct uart_event event = {.type = UART_RX_RDY, + .data.rx.buf = data->dma_rx.rx_buffer, + .data.rx.len = data->dma_rx.counter - data->dma_rx.offset, + .data.rx.offset = data->dma_rx.offset}; + + /* update the current pos for new data */ + data->dma_rx.offset = data->dma_rx.counter; + + /* send event only for new data */ + if (event.data.rx.len > 0) { + async_user_callback(data, &event); + } +} + +static inline void async_evt_rx_err(struct uart_hc32_data *data, int err_code) +{ + LOG_DBG("rx error: %d", err_code); + + struct uart_event event = {.type = UART_RX_STOPPED, + .data.rx_stop.reason = err_code, + .data.rx_stop.data.len = data->dma_rx.counter, + .data.rx_stop.data.offset = 0, + .data.rx_stop.data.buf = data->dma_rx.rx_buffer}; + + async_user_callback(data, &event); +} + +static inline void async_evt_tx_done(struct uart_hc32_data *data) +{ + LOG_DBG("tx done: %d", data->dma_tx.counter); + + struct uart_event event = {.type = UART_TX_DONE, + .data.tx.buf = data->dma_tx.tx_buffer, + .data.tx.len = data->dma_tx.counter}; + + /* Reset tx buffer */ + data->dma_tx.buffer_length = 0; + data->dma_tx.counter = 0; + + async_user_callback(data, &event); +} + +static inline void async_evt_tx_abort(struct uart_hc32_data *data) +{ + LOG_DBG("tx abort: %d", data->dma_tx.counter); + + struct uart_event event = {.type = UART_TX_ABORTED, + .data.tx.buf = data->dma_tx.tx_buffer, + .data.tx.len = data->dma_tx.counter}; + + /* Reset tx buffer */ + data->dma_tx.buffer_length = 0; + data->dma_tx.counter = 0; + + async_user_callback(data, &event); +} + +static inline void async_evt_rx_buf_request(struct uart_hc32_data *data) +{ + struct uart_event evt = { + .type = UART_RX_BUF_REQUEST, + }; + + async_user_callback(data, &evt); +} + +static inline void async_evt_rx_buf_release(struct uart_hc32_data *data) +{ + struct uart_event evt = { + .type = UART_RX_BUF_RELEASED, + .data.rx_buf.buf = data->dma_rx.rx_buffer, + }; + + async_user_callback(data, &evt); +} + +static inline void async_timer_start(struct k_work_delayable *work, int32_t timeout) +{ + if ((timeout != SYS_FOREVER_US) && (timeout != 0)) { + /* start timer */ + LOG_DBG("async timer started for %d us", timeout); + k_work_reschedule(work, K_USEC(timeout)); + } +} + +static inline void async_timer_restart(struct k_work_delayable *work, int32_t timeout, void *fn) +{ + if (timeout != 0) { + (void)k_work_cancel_delayable(work); + k_work_init_delayable(work, fn); + LOG_DBG("async timer re-started for %d us", timeout); + k_work_reschedule(work, K_USEC(timeout)); + } +} + +static void uart_hc32_dma_rx_flush(const struct device *dev) +{ + struct dma_status stat; + struct uart_hc32_data *data = dev->data; + + if (dma_get_status(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &stat) == 0) { + size_t rx_rcv_len = data->dma_rx.buffer_length - stat.pending_length; + + if (rx_rcv_len > data->dma_rx.offset) { + data->dma_rx.counter = rx_rcv_len; + + async_evt_rx_rdy(data); + } + } +} + +static int uart_hc32_async_callback_set(const struct device *dev, uart_callback_t callback, + void *user_data) +{ + struct uart_hc32_data *data = dev->data; + +#if CONFIG_UART_INTERRUPT_DRIVEN + for (uint8_t i = 0; i < HC32_UART_INT_NUM; i++) { + data->cb[i].user_cb = NULL; + data->cb[i].user_data = NULL; + } +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->async_cb = callback; + data->async_user_data = user_data; +#endif /* CONFIG_UART_EXCLUSIVE_API_CALLBACKS */ + + return 0; +} + +static inline void uart_hc32_dma_tx_disable(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static inline void uart_hc32_dma_rx_enable(const struct device *dev) +{ + struct uart_hc32_data *data = dev->data; + + data->dma_rx.enabled = true; +} + +static inline void uart_hc32_dma_rx_disable(const struct device *dev) +{ + struct uart_hc32_data *data = dev->data; + + data->dma_rx.enabled = false; +} + +static int uart_hc32_async_rx_disable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + struct uart_hc32_data *data = dev->data; + struct uart_event disabled_event = {.type = UART_RX_DISABLED}; + + if (!data->dma_rx.enabled) { + async_user_callback(data, &disabled_event); + return -EFAULT; + } + + uart_hc32_dma_rx_flush(dev); + + async_evt_rx_buf_release(data); + + uart_hc32_dma_rx_disable(dev); + + (void)k_work_cancel_delayable(&data->dma_rx.timeout_work); + + dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel); + + if (data->rx_next_buffer) { + struct uart_event rx_next_buf_release_evt = { + .type = UART_RX_BUF_RELEASED, + .data.rx_buf.buf = data->rx_next_buffer, + }; + async_user_callback(data, &rx_next_buf_release_evt); + } + + data->rx_next_buffer = NULL; + data->rx_next_buffer_len = 0; + + /* When async rx is disabled, enable instance of uart to function normally */ + USART_FuncCmd(config->usart, USART_INT_RX, ENABLE); + + LOG_DBG("rx: disabled"); + + async_user_callback(data, &disabled_event); + + return 0; +} + +void uart_hc32_dma_tx_cb(const struct device *dma_dev, void *user_data, uint32_t channel, + int status) +{ + struct dma_hc32_config_user_data *cfg = user_data; + struct device *uart_dev = cfg->user_data; + struct uart_hc32_data *data = uart_dev->data; + struct dma_status stat; + + unsigned int key = irq_lock(); + + /* Disable TX */ + uart_hc32_dma_tx_disable(uart_dev); + + (void)k_work_cancel_delayable(&data->dma_tx.timeout_work); + + if (!dma_get_status(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &stat)) { + data->dma_tx.counter = data->dma_tx.buffer_length - stat.pending_length; + } + + data->dma_tx.buffer_length = 0; + + async_evt_tx_done(data); + + irq_unlock(key); +} + +static void uart_hc32_dma_replace_buffer(const struct device *dev) +{ + struct uart_hc32_data *data = dev->data; + + /* Replace the buffer and reload the DMA */ + LOG_DBG("Replacing RX buffer: %d", data->rx_next_buffer_len); + + /* reload DMA */ + data->dma_rx.offset = 0; + data->dma_rx.counter = 0; + data->dma_rx.rx_buffer = data->rx_next_buffer; + data->dma_rx.buffer_length = data->rx_next_buffer_len; + data->dma_rx.blk_cfg.block_size = data->dma_rx.buffer_length; + data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.rx_buffer; + data->rx_next_buffer = NULL; + data->rx_next_buffer_len = 0; + + dma_reload(data->dma_rx.dma_dev, data->dma_rx.dma_channel, + data->dma_rx.blk_cfg.source_address, data->dma_rx.blk_cfg.dest_address, + data->dma_rx.blk_cfg.block_size); + + dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel); + + /* Request next buffer */ + async_evt_rx_buf_request(data); +} + +static int uart_hc32_async_tx_abort(const struct device *dev) +{ + struct uart_hc32_data *data = dev->data; + size_t tx_buffer_length = data->dma_tx.buffer_length; + struct dma_status stat; + + if (tx_buffer_length == 0) { + return -EFAULT; + } + + (void)k_work_cancel_delayable(&data->dma_tx.timeout_work); + if (!dma_get_status(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &stat)) { + data->dma_tx.counter = tx_buffer_length - stat.pending_length; + } + + dma_suspend(data->dma_tx.dma_dev, data->dma_tx.dma_channel); + dma_stop(data->dma_tx.dma_dev, data->dma_tx.dma_channel); + async_evt_tx_abort(data); + + return 0; +} + +static void uart_hc32_async_rx_timeout(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct hc32_dma_cfg *rx_stream = CONTAINER_OF(dwork, struct hc32_dma_cfg, timeout_work); + struct uart_hc32_data *data = CONTAINER_OF(rx_stream, struct uart_hc32_data, dma_rx); + const struct device *dev = data->uart_dev; + + LOG_DBG("rx timeout"); + + if (data->dma_rx.counter == data->dma_rx.buffer_length) { + uart_hc32_async_rx_disable(dev); + } else { + uart_hc32_dma_rx_flush(dev); + async_timer_restart(&data->dma_rx.timeout_work, data->dma_rx.timeout, + uart_hc32_async_rx_timeout); + } +} + +static void uart_hc32_async_tx_timeout(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct hc32_dma_cfg *tx_stream = CONTAINER_OF(dwork, struct hc32_dma_cfg, timeout_work); + struct uart_hc32_data *data = CONTAINER_OF(tx_stream, struct uart_hc32_data, dma_tx); + const struct device *dev = data->uart_dev; + + uart_hc32_async_tx_abort(dev); + + LOG_DBG("tx: async timeout"); + + async_timer_restart(&data->dma_tx.timeout_work, data->dma_tx.timeout, + uart_hc32_async_tx_timeout); +} + +void uart_hc32_dma_rx_cb(const struct device *dma_dev, void *user_data, uint32_t channel, + int status) +{ + struct dma_hc32_config_user_data *cfg = user_data; + struct device *uart_dev = cfg->user_data; + struct uart_hc32_data *data = uart_dev->data; + + if (status < 0) { + async_evt_rx_err(data, status); + return; + } + + /* true since this functions occurs when buffer if full */ + data->dma_rx.counter = data->dma_rx.buffer_length; + + async_evt_rx_rdy(data); + + if (data->rx_next_buffer != NULL) { + async_evt_rx_buf_release(data); + uart_hc32_dma_replace_buffer(uart_dev); + async_timer_restart(&data->dma_rx.timeout_work, data->dma_tx.timeout, + uart_hc32_async_rx_timeout); + } else { + (void)k_work_cancel_delayable(&data->dma_rx.timeout_work); + } +} + +static int uart_hc32_async_tx(const struct device *dev, const uint8_t *tx_data, size_t buf_size, + int32_t timeout) +{ + const struct uart_hc32_config *config = dev->config; + struct uart_hc32_data *data = dev->data; + CM_USART_TypeDef *usartx = ((CM_USART_TypeDef *)config->usart); + int ret; + + if (data->dma_tx.dma_dev == NULL) { + return -ENODEV; + } + + if (data->dma_tx.buffer_length != 0) { + return -EBUSY; + } + + data->dma_tx.tx_buffer = tx_data; + data->dma_tx.buffer_length = buf_size; + data->dma_tx.timeout = timeout; + + LOG_DBG("tx: l=%d", data->dma_tx.buffer_length); + USART_FuncCmd(config->usart, USART_INT_TX_EMPTY, DISABLE); + /* TC flag = 1 after init and not generate TC event request. */ + USART_FuncCmd(config->usart, USART_TX, DISABLE); + + /* set source address */ + data->dma_tx.blk_cfg.source_address = (uint32_t)data->dma_tx.tx_buffer; + data->dma_tx.blk_cfg.dest_address = (uint32_t)&usartx->TDR; + data->dma_tx.blk_cfg.block_size = data->dma_tx.buffer_length; + + ret = dma_config(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &data->dma_tx.dma_cfg); + + if (ret != 0) { + LOG_ERR("dma tx config error!"); + return -EINVAL; + } + + /* Start and enable TX DMA requests */ + if (dma_start(data->dma_tx.dma_dev, data->dma_tx.dma_channel)) { + LOG_ERR("UART err: TX DMA start failed!"); + return -EFAULT; + } + + /* TC flag = 1 after init and not generate TC event request.*/ + USART_FuncCmd(config->usart, USART_TX, ENABLE); + + /* Start TX timer */ + async_timer_start(&data->dma_tx.timeout_work, data->dma_tx.timeout); + + return 0; +} + +static int uart_hc32_async_rx_enable(const struct device *dev, uint8_t *rx_buf, size_t buf_size, + int32_t timeout) +{ + const struct uart_hc32_config *config = dev->config; + struct uart_hc32_data *data = dev->data; + CM_USART_TypeDef *usartx = ((CM_USART_TypeDef *)config->usart); + int ret; + + if (data->dma_rx.dma_dev == NULL) { + return -ENODEV; + } + + if (data->dma_rx.enabled) { + LOG_WRN("RX was already enabled"); + return -EBUSY; + } + + USART_FuncCmd(config->usart, USART_INT_RX, DISABLE); + + data->dma_rx.offset = 0; + data->dma_rx.rx_buffer = rx_buf; + data->dma_rx.buffer_length = buf_size; + data->dma_rx.counter = 0; + data->dma_rx.timeout = timeout; + + data->dma_rx.blk_cfg.block_size = buf_size; + data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.rx_buffer; + data->dma_rx.blk_cfg.source_address = (uint32_t)&usartx->RDR; + + ret = dma_config(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &(data->dma_rx.dma_cfg)); + + if (ret != 0) { + LOG_ERR("UART ERR: RX DMA config failed!"); + return -EINVAL; + } + + if (dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel)) { + LOG_ERR("UART ERR: RX DMA start failed!"); + return -EFAULT; + } + + /* Enable RX DMA requests */ + uart_hc32_dma_rx_enable(dev); + + USART_FuncCmd(config->usart, USART_RX, ENABLE); + + /* Request next buffer */ + async_evt_rx_buf_request(data); + + async_timer_start(&data->dma_rx.timeout_work, data->dma_rx.timeout); + + LOG_DBG("async rx enabled"); + + return ret; +} + +static int uart_hc32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf, size_t len) +{ + struct uart_hc32_data *data = dev->data; + + LOG_DBG("replace buffer (%d)", len); + data->rx_next_buffer = buf; + data->rx_next_buffer_len = len; + + return 0; +} + +static int uart_hc32_async_init(const struct device *dev) +{ + struct uart_hc32_data *data = dev->data; + + data->uart_dev = dev; + + if (data->dma_rx.dma_dev != NULL) { + if (!device_is_ready(data->dma_rx.dma_dev)) { + return -ENODEV; + } + } + + if (data->dma_tx.dma_dev != NULL) { + if (!device_is_ready(data->dma_tx.dma_dev)) { + return -ENODEV; + } + } + + /* Disable both TX and RX DMA requests */ + uart_hc32_dma_rx_disable(dev); + uart_hc32_dma_tx_disable(dev); + + /* Configure dma rx config */ + memset(&data->dma_rx.blk_cfg, 0U, sizeof(data->dma_rx.blk_cfg)); + + data->dma_rx.blk_cfg.dest_address = 0; /* dest not ready */ + data->dma_rx.blk_cfg.source_addr_adj = data->dma_rx.src_addr_increment; + data->dma_rx.blk_cfg.dest_addr_adj = data->dma_rx.dst_addr_increment; + + /* RX disable circular buffer */ + data->dma_rx.blk_cfg.source_reload_en = 0; + data->dma_rx.blk_cfg.dest_reload_en = 0; + + data->dma_rx.dma_cfg.head_block = &data->dma_rx.blk_cfg; + + /* user_data will be assigned to dev when support dma uart */ + data->dma_rx.user_cfg.user_data = NULL; + data->dma_rx.dma_cfg.user_data = (void *)&data->dma_rx.user_cfg; + + data->rx_next_buffer = NULL; + data->rx_next_buffer_len = 0; + + k_work_init_delayable(&data->dma_rx.timeout_work, uart_hc32_async_rx_timeout); + + /* Configure dma tx config */ + memset(&data->dma_tx.blk_cfg, 0U, sizeof(data->dma_tx.blk_cfg)); + + data->dma_tx.blk_cfg.source_address = 0U; /* not ready */ + data->dma_tx.blk_cfg.source_addr_adj = data->dma_tx.src_addr_increment; + data->dma_tx.blk_cfg.dest_addr_adj = data->dma_tx.dst_addr_increment; + data->dma_tx.dma_cfg.head_block = &data->dma_tx.blk_cfg; + + /* user_data will be assigned to dev when support dma uart */ + data->dma_tx.user_cfg.user_data = NULL; + data->dma_tx.dma_cfg.user_data = (void *)&data->dma_tx.user_cfg; + k_work_init_delayable(&data->dma_tx.timeout_work, uart_hc32_async_tx_timeout); + + return 0; +} +#endif /* DMA_TO_BE_SUPPORTED */ + +static const struct uart_driver_api uart_hc32_driver_api = { + .poll_in = uart_hc32_poll_in, + .poll_out = uart_hc32_poll_out, + .err_check = uart_hc32_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = uart_hc32_configure, + .config_get = uart_hc32_config_get, +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_hc32_fifo_fill, + .fifo_read = uart_hc32_fifo_read, + .irq_tx_enable = uart_hc32_irq_tx_enable, + .irq_tx_disable = uart_hc32_irq_tx_disable, + .irq_tx_ready = uart_hc32_irq_tx_ready, + .irq_tx_complete = uart_hc32_irq_tx_complete, + .irq_rx_enable = uart_hc32_irq_rx_enable, + .irq_rx_disable = uart_hc32_irq_rx_disable, + .irq_rx_ready = uart_hc32_irq_rx_ready, + .irq_err_enable = uart_hc32_irq_err_enable, + .irq_err_disable = uart_hc32_irq_err_disable, + .irq_is_pending = uart_hc32_irq_is_pending, + .irq_update = uart_hc32_irq_update, + .irq_callback_set = uart_hc32_irq_callback_set, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#ifdef DMA_TO_BE_SUPPORTED + .callback_set = uart_hc32_async_callback_set, + .tx = uart_hc32_async_tx, + .tx_abort = uart_hc32_async_tx_abort, + .rx_enable = uart_hc32_async_rx_enable, + .rx_disable = uart_hc32_async_rx_disable, + .rx_buf_rsp = uart_hc32_async_rx_buf_rsp, +#endif /* DMA_TO_BE_SUPPORTED */ +}; + +static int uart_hc32_registers_configure(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + struct uart_hc32_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; + stc_usart_uart_init_t stcUartInit; + + USART_FuncCmd(config->usart, HC32_UART_FUNC, DISABLE); + + (void)USART_UART_StructInit(&stcUartInit); + stcUartInit.u32ClockDiv = USART_CLK_DIV16; + stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT; + stcUartInit.u32Baudrate = uart_cfg->baudrate; + stcUartInit.u32StopBit = uart_hc32_cfg2ll_stopbits(uart_cfg->stop_bits); + stcUartInit.u32Parity = uart_hc32_cfg2ll_parity(uart_cfg->parity); + + (void)USART_UART_Init(config->usart, &stcUartInit, NULL); + USART_FuncCmd(config->usart, USART_TX | USART_RX, ENABLE); + + return 0; +} + +static inline void __uart_hc32_get_clock(const struct device *dev) +{ + struct uart_hc32_data *data = dev->data; + const struct device *const clk = DEVICE_DT_GET(HC32_CLOCK_CONTROL_NODE); + + data->clock = clk; +} + +static int uart_hc32_clocks_enable(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + struct uart_hc32_data *data = dev->data; + int err; + + __uart_hc32_get_clock(dev); + + if (!device_is_ready(data->clock)) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + + /* enable clock */ + err = clock_control_on(data->clock, (clock_control_subsys_t)(config->clk_cfg)); + if (err != 0) { + LOG_ERR("Could not enable UART clock"); + return err; + } + return 0; +} + +/** + * @brief Initialize UART channel + * + * This routine is called to reset the chip in a quiescent state. + * It is assumed that this function is called only once per UART. + * + * @param dev UART device struct + * + * @return 0 + */ +static int uart_hc32_init(const struct device *dev) +{ + const struct uart_hc32_config *config = dev->config; + int err; + + err = uart_hc32_clocks_enable(dev); + if (err < 0) { + return err; + } + + /* Configure dt provided device signals when available */ + err = pinctrl_apply_state(config->pin_cfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + return err; + } + + err = uart_hc32_registers_configure(dev); + if (err < 0) { + return err; + } + +#if defined(CONFIG_UART_INTERRUPT_DRIVEN) + if ((uart_irq_config_func_t)NULL != config->irq_config_func) { + config->irq_config_func(dev); + } +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + + /* config DMA */ +#ifdef DMA_TO_BE_SUPPORTED + return uart_hc32_async_init(dev); +#else + return 0; +#endif +} + +#if defined(DMA_TO_BE_SUPPORTED) + +/* src_dev and dest_dev should be 'MEMORY' or 'PERIPHERAL'. */ +#define UART_DMA_CHANNEL_INIT(index, dir, dir_cap, src_dev, dest_dev) \ + .dma_dev = DEVICE_DT_GET(HC32_DMA_CTLR(index, dir)), \ + .dma_channel = DT_INST_DMAS_CELL_BY_NAME(index, dir, channel), \ + .dma_cfg = \ + { \ + .channel_direction = \ + HC32_DMA_CONFIG_DIRECTION(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ + .source_data_size = \ + HC32_DMA_CONFIG_DATA_SIZE(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ + .dest_data_size = \ + HC32_DMA_CONFIG_DATA_SIZE(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ + .source_burst_length = 1, /* SINGLE transfer */ \ + .dest_burst_length = 1, \ + .block_count = 1, \ + .dma_callback = uart_hc32_dma_##dir##_cb, \ + }, \ + .user_cfg = \ + { \ + .slot = HC32_DMA_SLOT(index, dir), \ + }, \ + .src_addr_increment = \ + HC32_DMA_CONFIG_##src_dev##_ADDR_INC(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ + .dst_addr_increment = \ + HC32_DMA_CONFIG_##dest_dev##_ADDR_INC(HC32_DMA_CHANNEL_CONFIG(index, dir)), +#else +#define HC32_UART_DMA_CFG_DECL(index) +#endif /* DMA_TO_BE_SUPPORTED */ + +#ifdef DMA_TO_BE_SUPPORTED +/* If defined async, let dma deal with transmission */ +#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) \ + .dma_##dir = {COND_CODE_1( \ + DT_INST_DMAS_HAS_NAME(index, dir), \ + (UART_DMA_CHANNEL_INIT(index, dir, DIR, src, dest)), \ + ()) }, +#else +#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) +#endif /* DMA_TO_BE_SUPPORTED */ + +#define DT_USART_HAS_INTR(node_id) IS_ENABLED(DT_CAT4(node_id, _P_, interrupts, _EXISTS)) + +#define DT_IS_INTR_EXIST(index) DT_USART_HAS_INTR(DT_INST(index, xhsc_hc32_uart)) + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +#define DT_IS_HC32_USART_INT_DEF(node_id, isr_name) \ + IS_ENABLED(DT_CAT4(node_id, _IRQ_NAME_, isr_name, _VAL_irq_EXISTS)) + +#define DT_IS_HC32_UART_INTR_EXIST(index, isr_name) \ + DT_IS_HC32_USART_INT_DEF(DT_INST(index, xhsc_hc32_uart), isr_name) + +#define USART_IRQ_ISR_CONFIG(isr_name, index) \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, isr_name, irq), \ + DT_INST_IRQ_BY_NAME(index, isr_name, priority), \ + DT_CAT4(usart_hc32_, isr_name, _isr_, index), DEVICE_DT_INST_GET(index), 0); \ + hc32_intc_irq_signin(DT_INST_IRQ_BY_NAME(index, isr_name, irq), \ + DT_INST_IRQ_BY_NAME(index, isr_name, int_src)); \ + irq_enable(DT_INST_IRQ_BY_NAME(index, isr_name, irq)); + +#define HC32_UART_IRQ_HANDLER_DECL(index) \ + static void usart_hc32_config_func_##index(const struct device *dev); \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, ore), \ + (static void usart_hc32_ore_isr_##index(const struct device *dev);) \ + , ()) \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, rxne), \ + (static void usart_hc32_rxne_isr_##index(const struct device *dev);) \ + , ()) \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, tc), \ + (static void usart_hc32_tc_isr_##index(const struct device *dev);) \ + , ()) \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, txe), \ + (static void usart_hc32_txe_isr_##index(const struct device *dev);) \ + , ()) + +#define HC32_UART_IRQ_HANDLER_DEF_BY_NAME(index, name, cb_idx) \ + static void usart_hc32_##name##_isr_##index(const struct device *dev) \ + { \ + struct uart_hc32_data *const data = dev->data; \ + \ + if (data->cb[cb_idx].user_cb) { \ + data->cb[cb_idx].user_cb(dev, data->cb[cb_idx].user_data); \ + } \ + } + +#define HC32_UART_IRQ_HANDLER_DEF(index) \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, ore), \ + (HC32_UART_IRQ_HANDLER_DEF_BY_NAME(index, ore, HC32_UART_IDX_EI)), \ + ()) \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, rxne), \ + (HC32_UART_IRQ_HANDLER_DEF_BY_NAME(index, rxne, HC32_UART_IDX_EI)), \ + ()) \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, tc), \ + (HC32_UART_IRQ_HANDLER_DEF_BY_NAME(index, tc, HC32_UART_IDX_EI)), \ + ()) \ + COND_CODE_1(DT_IS_HC32_UART_INTR_EXIST(index, txe), \ + (HC32_UART_IRQ_HANDLER_DEF_BY_NAME(index, txe, HC32_UART_IDX_EI)), \ + ()) \ + \ + static void usart_hc32_config_func_##index(const struct device *dev) \ + { \ + COND_CODE_1( \ + DT_IS_HC32_UART_INTR_EXIST(index, ore), \ + (USART_IRQ_ISR_CONFIG(ore, index)), ()) \ + COND_CODE_1( \ + DT_IS_HC32_UART_INTR_EXIST(index, rxne), \ + (USART_IRQ_ISR_CONFIG(rxne, index)), ()) \ + COND_CODE_1( \ + DT_IS_HC32_UART_INTR_EXIST(index, tc), \ + (USART_IRQ_ISR_CONFIG(tc, index)), ()) \ + COND_CODE_1( \ + DT_IS_HC32_UART_INTR_EXIST(index, txe), \ + (USART_IRQ_ISR_CONFIG(txe, index)), ()) \ + } + +#define HC32_UART_IRQ_HANDLER_FUNC(index) .irq_config_func = usart_hc32_config_func_##index, +#define HC32_UART_IRQ_HANDLER_NULL(index) .irq_config_func = (uart_irq_config_func_t)NULL, + +#define HC32_UART_IRQ_HANDLER_PRE_FUNC(index) \ + COND_CODE_1( \ + DT_IS_INTR_EXIST(index), \ + (HC32_UART_IRQ_HANDLER_FUNC(index)), \ + (HC32_UART_IRQ_HANDLER_NULL(index))) + +#define HC32_UART_IRQ_HANDLER_PRE_DECL(index) \ + COND_CODE_1( \ + DT_IS_INTR_EXIST(index), \ + (HC32_UART_IRQ_HANDLER_DECL(index)), \ + ()) + +#define HC32_UART_IRQ_HANDLER_PRE_DEF(index) \ + COND_CODE_1( \ + DT_IS_INTR_EXIST(index), \ + (HC32_UART_IRQ_HANDLER_DEF(index)), \ + ()) +#else /* CONFIG_UART_INTERRUPT_DRIVEN */ +#define HC32_UART_IRQ_HANDLER_PRE_DECL(index) +#define HC32_UART_IRQ_HANDLER_PRE_DEF(index) +#define HC32_UART_IRQ_HANDLER_PRE_FUNC(index) +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +#define HC32_UART_CLOCK_DECL(index) \ + static struct hc32_modules_clock_sys uart_fcg_config_##index[] = \ + HC32_MODULES_CLOCKS(DT_DRV_INST(index)); + +#define HC32_UART_INIT(index) \ + HC32_UART_CLOCK_DECL(index) \ + HC32_UART_IRQ_HANDLER_PRE_DECL(index) \ + PINCTRL_DT_INST_DEFINE(index); \ + static struct uart_config uart_cfg_##index = { \ + .baudrate = DT_INST_PROP_OR(index, current_speed, HC32_UART_DEFAULT_BAUDRATE), \ + .parity = DT_INST_ENUM_IDX_OR(index, parity, HC32_UART_DEFAULT_PARITY), \ + .stop_bits = DT_INST_ENUM_IDX_OR(index, stop_bits, HC32_UART_DEFAULT_STOP_BITS), \ + .data_bits = DT_INST_ENUM_IDX_OR(index, data_bits, HC32_UART_DEFAULT_DATA_BITS), \ + .flow_ctrl = DT_INST_PROP(index, hw_flow_control) ? UART_CFG_FLOW_CTRL_RTS_CTS \ + : UART_CFG_FLOW_CTRL_NONE, \ + }; \ + static const struct uart_hc32_config uart_hc32_cfg_##index = { \ + .usart = (CM_USART_TypeDef *)DT_INST_REG_ADDR(index), \ + .pin_cfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ + .clk_cfg = uart_fcg_config_##index, \ + HC32_UART_IRQ_HANDLER_PRE_FUNC(index)}; \ + static struct uart_hc32_data uart_hc32_data_##index = { \ + .uart_cfg = &uart_cfg_##index, \ + UART_DMA_CHANNEL(index, rx, RX, SOURCE, DEST) \ + UART_DMA_CHANNEL(index, tx, TX, SOURCE, DEST)}; \ + DEVICE_DT_INST_DEFINE(index, &uart_hc32_init, NULL, &uart_hc32_data_##index, \ + &uart_hc32_cfg_##index, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_hc32_driver_api); \ + HC32_UART_IRQ_HANDLER_PRE_DEF(index) + +DT_INST_FOREACH_STATUS_OKAY(HC32_UART_INIT) diff --git a/drivers/serial/uart_hc32.h b/drivers/serial/uart_hc32.h new file mode 100644 index 0000000000000..fa009cfec0ac2 --- /dev/null +++ b/drivers/serial/uart_hc32.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Driver for interrupt/event controller in HC32 MCUs + */ + +#ifndef ZEPHYR_DRIVERS_SERIAL_UART_HC32_H_ +#define ZEPHYR_DRIVERS_SERIAL_UART_HC32_H_ + +#include +#include +#include + +#include + +#define HC32_UART_DEFAULT_BAUDRATE 115200 +#define HC32_UART_DEFAULT_PARITY UART_CFG_PARITY_NONE +#define HC32_UART_DEFAULT_STOP_BITS UART_CFG_STOP_BITS_1 +#define HC32_UART_DEFAULT_DATA_BITS UART_CFG_DATA_BITS_8 + +#define HC32_UART_FUNC (USART_TX | USART_RX | USART_INT_RX | USART_INT_TX_CPLT | USART_INT_TX_EMPTY) + +#if CONFIG_UART_INTERRUPT_DRIVEN +enum UART_TYPE { + HC32_UART_IDX_EI, + HC32_UART_IDX_RI, + HC32_UART_IDX_TI, + HC32_UART_IDX_TCI, + HC32_UART_INT_NUM +}; +#endif /* UART_INTERRUPT_DRIVEN */ + +/* device config */ +struct uart_hc32_config { + /* USART instance */ + CM_USART_TypeDef *usart; + /* clock subsystem driving this peripheral */ + struct hc32_modules_clock_sys *clk_cfg; + /* pin muxing */ + const struct pinctrl_dev_config *pin_cfg; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_config_func_t irq_config_func; +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +#ifdef CONFIG_UART_ASYNC_API +struct hc32_dma_cfg { + const struct device *dma_dev; + uint32_t dma_channel; + struct dma_config dma_cfg; + uint16_t src_addr_increment; + uint16_t dst_addr_increment; + struct dma_block_config blk_cfg; + size_t buffer_length; + size_t offset; + const uint8_t *tx_buffer; + uint8_t *rx_buffer; + volatile size_t counter; + int32_t timeout; + struct k_work_delayable timeout_work; + bool enabled; + struct dma_hc32_config_user_data user_cfg; +}; +#endif + +struct hc32_usart_cb_data { + /** Callback function */ + uart_irq_callback_user_data_t user_cb; + /** User data. */ + void *user_data; +}; + +/* driver data */ +struct uart_hc32_data { + /* clock device */ + const struct device *clock; + /* uart config */ + struct uart_config *uart_cfg; +#if defined(CONFIG_UART_INTERRUPT_DRIVEN) + struct hc32_usart_cb_data cb[HC32_UART_INT_NUM]; +#endif + +#ifdef CONFIG_UART_ASYNC_API + const struct device *uart_dev; + uart_callback_t async_cb; + void *async_user_data; + struct hc32_dma_cfg dma_tx; + struct hc32_dma_cfg dma_rx; + uint8_t *rx_next_buffer; + size_t rx_next_buffer_len; +#endif +}; + +#endif /* ZEPHYR_DRIVERS_SERIAL_UART_HC32_H_ */ diff --git a/dts/bindings/serial/xhsc,hc32-uart.yaml b/dts/bindings/serial/xhsc,hc32-uart.yaml new file mode 100644 index 0000000000000..2743c96b0ab92 --- /dev/null +++ b/dts/bindings/serial/xhsc,hc32-uart.yaml @@ -0,0 +1,19 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +compatible: "xhsc,hc32-uart" + +include: [uart-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true From a7b619f48c66b78607aa35da13a1d2111c7573e7 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:58:29 +0800 Subject: [PATCH 08/10] soc: xhsc: Add support for XHSC HC32F4A0 Add support for XHSC HC32F4A0 Signed-off-by: Yongbing Liu --- dts/arm/xhsc/f4/hc32f4a0.dtsi | 295 ++++++++++++++++++ .../xhsc,hc32-flash-controller.yaml | 8 + dts/bindings/vendor-prefixes.txt | 1 + modules/Kconfig | 1 + modules/Kconfig.xhsc | 179 +++++++++++ soc/xhsc/hc32/CMakeLists.txt | 17 + soc/xhsc/hc32/Kconfig | 11 + soc/xhsc/hc32/Kconfig.defconfig | 8 + soc/xhsc/hc32/Kconfig.soc | 10 + soc/xhsc/hc32/common/CMakeLists.txt | 4 + soc/xhsc/hc32/common/pinctrl_soc.h | 67 ++++ soc/xhsc/hc32/flash_config.ld | 9 + soc/xhsc/hc32/hc32f4xx/CMakeLists.txt | 8 + soc/xhsc/hc32/hc32f4xx/Kconfig | 14 + soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig | 8 + .../hc32/hc32f4xx/Kconfig.defconfig.hc32f4a0 | 19 ++ soc/xhsc/hc32/hc32f4xx/Kconfig.soc | 23 ++ soc/xhsc/hc32/hc32f4xx/soc.c | 36 +++ soc/xhsc/hc32/hc32f4xx/soc.h | 16 + soc/xhsc/hc32/soc.yml | 7 + soc/xhsc/hc32/user_noinit.ld | 20 ++ 21 files changed, 761 insertions(+) create mode 100644 dts/arm/xhsc/f4/hc32f4a0.dtsi create mode 100644 dts/bindings/flash_controller/xhsc,hc32-flash-controller.yaml create mode 100644 modules/Kconfig.xhsc create mode 100644 soc/xhsc/hc32/CMakeLists.txt create mode 100644 soc/xhsc/hc32/Kconfig create mode 100644 soc/xhsc/hc32/Kconfig.defconfig create mode 100644 soc/xhsc/hc32/Kconfig.soc create mode 100644 soc/xhsc/hc32/common/CMakeLists.txt create mode 100644 soc/xhsc/hc32/common/pinctrl_soc.h create mode 100644 soc/xhsc/hc32/flash_config.ld create mode 100644 soc/xhsc/hc32/hc32f4xx/CMakeLists.txt create mode 100644 soc/xhsc/hc32/hc32f4xx/Kconfig create mode 100644 soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig create mode 100644 soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig.hc32f4a0 create mode 100644 soc/xhsc/hc32/hc32f4xx/Kconfig.soc create mode 100644 soc/xhsc/hc32/hc32f4xx/soc.c create mode 100644 soc/xhsc/hc32/hc32f4xx/soc.h create mode 100644 soc/xhsc/hc32/soc.yml create mode 100644 soc/xhsc/hc32/user_noinit.ld diff --git a/dts/arm/xhsc/f4/hc32f4a0.dtsi b/dts/arm/xhsc/f4/hc32f4a0.dtsi new file mode 100644 index 0000000000000..0112205138090 --- /dev/null +++ b/dts/arm/xhsc/f4/hc32f4a0.dtsi @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + flash-controller@40010400 { + compatible = "xhsc,hc32-flash-controller"; + reg = <0x40010400 0x0400>; + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 0x200000>; + erase-block-size = <8192>; + write-block-size = <4>; + }; + }; + + /* The on-chip SRAM is split into SRAM0 and SRAMH regions that form a + * contiguous block in the memory map, however misaligned accesses + * across the 0x2000_0000 boundary are not supported in the Arm + * Cortex-M4 architecture. + */ + sramh: memory@1ffe0000 { + device_type = "memory"; + compatible ="zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "SRAMH"; + reg = <0x1ffe0000 DT_SIZE_K(128)>; + }; + + sram0: memory@20000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(384)>; + }; + + sramb: memory@200F0000 { + device_type = "memory"; + compatible = "zephyr,memory-region","mmio-sram"; + zephyr,memory-region = "SRAMB"; + reg = <0x200F0000 DT_SIZE_K(4)>; + }; + + soc { + clocks: clock@40048400{ + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40048400 0x400>; + compatible = "xhsc,hc32-clock-control"; + clock-conf = ; + + clk_xtal: clock_xtal { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <8000000>; + }; + + clk_xtal32: clock_xtal32 { + #clock-cells = <0>; + compatible = "xhsc,hc32-clock-xtal32"; + clock-frequency = <32768>; + drive-strength = <0>; + }; + + clk_hrc: clock_hrc { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <16000000>; + }; + + clk_mrc: clock_mrc { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <8000000>; + }; + + clk_lrc: clock_lrc { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_pll: clock_pll { + #clock-cells = <0>; + compatible = "xhsc,hc32-clock-pll"; + clock-frequency = <240000000>; + clocks = <&clk_xtal>; + div-m = <1>; + mul-n = <120>; + div-p = <4>; + div-q = <4>; + div-r = <4>; + }; + + clk_sys: clock_system { + compatible = "xhsc,hc32-clock-sys"; + clocks = <&clk_pll>; + div-hclk = <1>; + div-exclk = <2>; + div-pclk0 = <1>; + div-pclk1 = <2>; + div-pclk2 = <4>; + div-pclk3 = <4>; + div-pclk4 = <2>; + }; + + bus_fcg: pwc_fcg@40048000 { + #clock-cells = <3>; + compatible = "xhsc,hc32-bus-fcg"; + reg = <0x40048000 DT_SIZE_K(1)>; + }; + }; + + pinctrl: pin-controller@40053c00 { + compatible = "xhsc,hc32-pinctrl"; + reg = <0x40053c00 0x400>; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + gpioa: gpio@40053c00 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053c00 0x40>; + }; + + gpiob: gpio@40053c40 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053c40 0x40>; + }; + + gpioc: gpio@40053c80 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053c80 0x40>; + }; + + gpiod: gpio@40053cc0 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053cc0 0x40>; + }; + + gpioe: gpio@40053d00 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053d00 0x40>; + }; + + gpiof: gpio@40053d40 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053d40 0x40>; + }; + + gpiog: gpio@40053d80 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053d80 0x40>; + }; + + gpioh: gpio@40053dc0 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053dc0 0x40>; + }; + + gpioi: gpio@40053e00 { + compatible = "xhsc,hc32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40053e00 0x40>; + }; + }; + + intc: interrupt-controller@40051000 { + compatible = "xhsc,hc32-intc"; + reg = <0x40051000 0x1000>; + interrupt-controller; + #interrupt-cells = <3>; + status = "okay"; + + extint { + compatible = "xhsc,hc32-extint"; + interrupt-parent = <&intc>; + extint-nums = <16>; + extint-chs = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "extint0", "extint1", "extint2", "extint3", + "extint4", "extint5", "extint6", "extint7", + "extint8", "extint9", "extint10", "extint11", + "extint12", "extint13", "extint14", "extint15"; + status = "okay"; + }; + }; + + usart1: serial@4001cc00 { + compatible = "xhsc,hc32-uart"; + reg = <0x4001cc00 0x400>; + clocks = <&bus_fcg HC32_CLK_BUS_PCLK1 HC32_CLK_FCG3 \ + HC32_FCG3_PERIPH_USART1>; + status = "disabled"; + }; + + usart2: serial@4001d000 { + compatible = "xhsc,hc32-uart"; + reg = <0x4001d000 0x400>; + clocks = <&bus_fcg HC32_CLK_BUS_PCLK1 HC32_CLK_FCG3 \ + HC32_FCG3_PERIPH_USART2>; + status = "disabled"; + }; + + usart3: serial@4001d400 { + compatible = "xhsc,hc32-uart"; + reg = <0x4001d400 0x400>; + clocks = <&bus_fcg HC32_CLK_BUS_PCLK1 HC32_CLK_FCG3 \ + HC32_FCG3_PERIPH_USART3>; + status = "disabled"; + }; + + usart4: serial@4001d800 { + compatible = "xhsc,hc32-uart"; + reg = <0x4001d800 0x400>; + clocks = <&bus_fcg HC32_CLK_BUS_PCLK1 HC32_CLK_FCG3 \ + HC32_FCG3_PERIPH_USART4>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/bindings/flash_controller/xhsc,hc32-flash-controller.yaml b/dts/bindings/flash_controller/xhsc,hc32-flash-controller.yaml new file mode 100644 index 0000000000000..f3b93709cdc5c --- /dev/null +++ b/dts/bindings/flash_controller/xhsc,hc32-flash-controller.yaml @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: HC32 F4 flash controller + +compatible: "xhsc,hc32-flash-controller" + +include: flash-controller.yaml diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index db92063114842..cb3ba6bc899ce 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -771,6 +771,7 @@ wurth Wurth Elektronik x-powers X-Powers xen Xen Hypervisor xes Extreme Engineering Solutions (X-ES) +xhsc Xiaohua Semiconductor Co., Ltd. xiaomi Xiaomi Technology Co., Ltd. xillybus Xillybus Ltd. xingbangda Shenzhen Xingbangda Display Technology Co., Ltd diff --git a/modules/Kconfig b/modules/Kconfig index b66955981fa04..63809a1183b83 100644 --- a/modules/Kconfig +++ b/modules/Kconfig @@ -48,6 +48,7 @@ source "modules/zcbor/Kconfig" source "modules/Kconfig.mcuboot" source "modules/Kconfig.intel" source "modules/hostap/Kconfig" +source "modules/Kconfig.xhsc" comment "Unavailable modules, please install those via the project manifest." diff --git a/modules/Kconfig.xhsc b/modules/Kconfig.xhsc new file mode 100644 index 0000000000000..342af8ca2b521 --- /dev/null +++ b/modules/Kconfig.xhsc @@ -0,0 +1,179 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config HAS_HC32_DDL + bool + select HAS_CMSIS_CORE + depends on SOC_FAMILY_XHSC_HC32 + +if HAS_HC32_DDL + +config HC32_DDL_DEBUG + bool + help + If enable assert function in hc32_ddl drivers + +config HC32_LL_ICG + bool + default y + +config HC32_LL_ADC + bool + +config HC32_LL_AES + bool + +config HC32_LL_AOS + bool + +config HC32_LL_CAN + bool + +config HC32_LL_CLK + bool + default y + +config HC32_LL_CMP + bool + +config HC32_LL_CRC + bool + +config HC32_LL_CTC + bool + +config HC32_LL_DAC + bool + +config HC32_LL_DBGC + bool + +config HC32_LL_DCU + bool + +config HC32_LL_DMA + bool + +config HC32_LL_DMC + bool + +config HC32_LL_DVP + bool + +config HC32_LL_EFM + bool + default y + +config HC32_LL_EMB + bool + +config HC32_LL_ETH + bool + +config HC32_LL_EVENT_PORT + bool + +config HC32_LL_FCG + bool + default y + +config HC32_LL_FCM + bool + +config HC32_LL_FMAC + bool + +config HC32_LL_GPIO + bool + default y + +config HC32_LL_HASH + bool + +config HC32_LL_HRPWM + bool + +config HC32_LL_I2C + bool + +config HC32_LL_I2S + bool + +config HC32_LL_INTERRUPTS + bool + +config HC32_LL_INTERRUPTS_SHARE + bool + +config HC32_LL_KEYSCAN + bool + +config HC32_LL_MAU + bool + +config HC32_LL_MPU + bool + +config HC32_LL_NFC + bool + +config HC32_LL_OTS + bool + +config HC32_LL_PWC + bool + default y + +config HC32_LL_QSPI + bool + +config HC32_LL_RMU + bool + +config HC32_LL_RTC + bool + +config HC32_LL_SDIOC + bool + +config HC32_LL_SMC + bool + +config HC32_LL_SPI + bool + +config HC32_LL_SRAM + bool + default y + +config HC32_LL_SWDT + bool + +config HC32_LL_TMR0 + bool + +config HC32_LL_TMR2 + bool + +config HC32_LL_TMR4 + bool + +config HC32_LL_TMR6 + bool + +config HC32_LL_TMRA + bool + +config HC32_LL_TRNG + bool + +config HC32_LL_USART + bool + +config HC32_LL_USB + bool + +config HC32_LL_WDT + bool + +endif diff --git a/soc/xhsc/hc32/CMakeLists.txt b/soc/xhsc/hc32/CMakeLists.txt new file mode 100644 index 0000000000000..c6bb9a7896f33 --- /dev/null +++ b/soc/xhsc/hc32/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(common) +add_subdirectory(${SOC_SERIES}) + +zephyr_linker_sources( + ROM_START + SORT_KEY ${CONFIG_HC32_FLASH_CONFIG_OFFSET} + flash_config.ld +) + +zephyr_linker_sources( + RAM_SECTIONS + SORT_KEY _noinit_user + user_noinit.ld +) diff --git a/soc/xhsc/hc32/Kconfig b/soc/xhsc/hc32/Kconfig new file mode 100644 index 0000000000000..62d6bfef2a5ae --- /dev/null +++ b/soc/xhsc/hc32/Kconfig @@ -0,0 +1,11 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_XHSC_HC32 + bool + +if SOC_FAMILY_XHSC_HC32 + +rsource "*/Kconfig" + +endif # SOC_FAMILY_XHSC_HC32 diff --git a/soc/xhsc/hc32/Kconfig.defconfig b/soc/xhsc/hc32/Kconfig.defconfig new file mode 100644 index 0000000000000..64180a98c8cda --- /dev/null +++ b/soc/xhsc/hc32/Kconfig.defconfig @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_XHSC_HC32 + +rsource "*/Kconfig.defconfig" + +endif # SOC_FAMILY_XHSC_HC32 diff --git a/soc/xhsc/hc32/Kconfig.soc b/soc/xhsc/hc32/Kconfig.soc new file mode 100644 index 0000000000000..46954d27cd2fb --- /dev/null +++ b/soc/xhsc/hc32/Kconfig.soc @@ -0,0 +1,10 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_XHSC_HC32 + bool + +config SOC_FAMILY + default "xhsc_hc32" if SOC_FAMILY_XHSC_HC32 + +rsource "*/Kconfig.soc" diff --git a/soc/xhsc/hc32/common/CMakeLists.txt b/soc/xhsc/hc32/common/CMakeLists.txt new file mode 100644 index 0000000000000..20b05f2b077c7 --- /dev/null +++ b/soc/xhsc/hc32/common/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(.) diff --git a/soc/xhsc/hc32/common/pinctrl_soc.h b/soc/xhsc/hc32/common/pinctrl_soc.h new file mode 100644 index 0000000000000..98974f39d3614 --- /dev/null +++ b/soc/xhsc/hc32/common/pinctrl_soc.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * HC32 SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_ARM_XHSC_HC32_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_XHSC_HC32_COMMON_PINCTRL_SOC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Type for HC32 pin. */ +typedef uint32_t pinctrl_soc_pin_t; + +/** + * @brief Utility macro to initialize pinmux field. + * + * @param node_id Node identifier. + */ +#define Z_PINCTRL_HC32_PINCFG(node_id) \ + (((HC32_NO_PULL * DT_PROP(node_id, bias_disable)) << HC32_PUR_SHIFT) | \ + ((HC32_PULL_UP * DT_PROP(node_id, bias_pull_up)) << HC32_PUR_SHIFT) | \ + ((HC32_PUSH_PULL * DT_PROP(node_id, drive_push_pull)) << HC32_NOD_SHIFT) | \ + ((HC32_OPEN_DRAIN * DT_PROP(node_id, drive_open_drain)) << HC32_NOD_SHIFT) | \ + ((HC32_OUTPUT_LOW * DT_PROP(node_id, output_low)) << HC32_OTYPE_SHIFT) | \ + ((HC32_OUTPUT_HIGH * DT_PROP(node_id, output_high)) << HC32_OTYPE_SHIFT) | \ + ((HC32_INPUT_ENABLE * DT_PROP(node_id, input_enable)) << HC32_DIREN_SHIFT) | \ + ((HC32_OUTPUT_ENABLE * DT_PROP(node_id, output_enable)) << HC32_DIREN_SHIFT) | \ + (DT_ENUM_IDX(node_id, drive_strength) << HC32_STRENGTH_SHIFT)) + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param prop Property name. + * @param idx Property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + DT_PROP_BY_IDX(node_id, prop, idx) | Z_PINCTRL_HC32_PINCFG(node_id), + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param state_prop State property name. + * @param idx State property entry index. + */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT)} + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_XHSC_HC32_COMMON_PINCTRL_SOC_H_ */ diff --git a/soc/xhsc/hc32/flash_config.ld b/soc/xhsc/hc32/flash_config.ld new file mode 100644 index 0000000000000..e00db35a0bab0 --- /dev/null +++ b/soc/xhsc/hc32/flash_config.ld @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +. = CONFIG_HC32_FLASH_CONFIG_OFFSET; +KEEP(*(.icg_sec)) +KEEP(*(".icg_sec.*")) diff --git a/soc/xhsc/hc32/hc32f4xx/CMakeLists.txt b/soc/xhsc/hc32/hc32f4xx/CMakeLists.txt new file mode 100644 index 0000000000000..2556e20aa5a1a --- /dev/null +++ b/soc/xhsc/hc32/hc32f4xx/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(.) + +zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/xhsc/hc32/hc32f4xx/Kconfig b/soc/xhsc/hc32/hc32f4xx/Kconfig new file mode 100644 index 0000000000000..6620e693c78d5 --- /dev/null +++ b/soc/xhsc/hc32/hc32f4xx/Kconfig @@ -0,0 +1,14 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_HC32F4XX + select ARM + select CPU_CORTEX_M_HAS_SYSTICK + select CPU_CORTEX_M_HAS_VTOR + select CPU_CORTEX_M4 + select CPU_HAS_ARM_MPU + select CPU_HAS_FPU + select HAS_HC32_DDL + select SOC_RESET_HOOK + help + Enable support for xhsc hc32f4xx MCU series diff --git a/soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig b/soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig new file mode 100644 index 0000000000000..311a792d379b8 --- /dev/null +++ b/soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_HC32F4XX + +rsource "Kconfig.defconfig.hc32*" + +endif # SOC_SERIES_HC32F4XX diff --git a/soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig.hc32f4a0 b/soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig.hc32f4a0 new file mode 100644 index 0000000000000..0a749bc1efc73 --- /dev/null +++ b/soc/xhsc/hc32/hc32f4xx/Kconfig.defconfig.hc32f4a0 @@ -0,0 +1,19 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_HC32F4A0 + +config NUM_IRQS + default 143 + +config SYS_CLOCK_TICKS_PER_SEC + default 1000 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_nodelabel_int_prop,clk_pll,clock-frequency) + +config HC32_FLASH_CONFIG_OFFSET + hex + default 0x400 + +endif # SOC_HC32F4A0 diff --git a/soc/xhsc/hc32/hc32f4xx/Kconfig.soc b/soc/xhsc/hc32/hc32f4xx/Kconfig.soc new file mode 100644 index 0000000000000..d2313bbce4dd9 --- /dev/null +++ b/soc/xhsc/hc32/hc32f4xx/Kconfig.soc @@ -0,0 +1,23 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_HC32F4XX + bool + select SOC_FAMILY_XHSC_HC32 + help + Enable support for XHSC HC32F4XX MCU series + +config SOC_SERIES + default "hc32f4xx" if SOC_SERIES_HC32F4XX + +config SOC_HC32F460 + bool + select SOC_SERIES_HC32F4XX + +config SOC_HC32F4A0 + bool + select SOC_SERIES_HC32F4XX + +config SOC + default "hc32f460" if SOC_HC32F460 + default "hc32f4a0" if SOC_HC32F4A0 diff --git a/soc/xhsc/hc32/hc32f4xx/soc.c b/soc/xhsc/hc32/hc32f4xx/soc.c new file mode 100644 index 0000000000000..a51a430e3306c --- /dev/null +++ b/soc/xhsc/hc32/hc32f4xx/soc.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/** + * @brief Perform basic hardware initialization at boot. + * + * This needs to be run from the very beginning. + * So the init priority has to be 0 (zero). + * + * @return 0 + */ +static int xhsc_hc32f4_init(void) +{ + LL_PERIPH_WE(LL_PERIPH_ALL); + + /* Enable Flash cache for both instruction and data */ +#if defined(HC32F460) + EFM_CacheCmd(ENABLE); +#elif defined(HC32F4A0) + EFM_PrefetchCmd(ENABLE); + EFM_DCacheCmd(ENABLE); + EFM_ICacheCmd(ENABLE); +#endif + + return 0; +} + +SYS_INIT(xhsc_hc32f4_init, PRE_KERNEL_1, 0); diff --git a/soc/xhsc/hc32/hc32f4xx/soc.h b/soc/xhsc/hc32/hc32f4xx/soc.h new file mode 100644 index 0000000000000..5511cdb88c4cb --- /dev/null +++ b/soc/xhsc/hc32/hc32f4xx/soc.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SOC__H_ +#define _SOC__H_ + +#ifndef _ASMLANGUAGE + +#include + +#endif /* !_ASMLANGUAGE */ + +#endif /* _SOC__H_ */ diff --git a/soc/xhsc/hc32/soc.yml b/soc/xhsc/hc32/soc.yml new file mode 100644 index 0000000000000..c0788596bee11 --- /dev/null +++ b/soc/xhsc/hc32/soc.yml @@ -0,0 +1,7 @@ +family: +- name: xhsc_hc32 + series: + - name: hc32f4xx + socs: + - name: hc32f460 + - name: hc32f4a0 diff --git a/soc/xhsc/hc32/user_noinit.ld b/soc/xhsc/hc32/user_noinit.ld new file mode 100644 index 0000000000000..302a1a6e3c185 --- /dev/null +++ b/soc/xhsc/hc32/user_noinit.ld @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Copied from linker.ld */ + +SECTION_DATA_PROLOGUE(.user_noinit,,) +{ + . = ALIGN(4); + __user_noinit_start = .; + *(.user_noinit) + *(".user_noinit.*") + + . = ALIGN(4); + __user_noinit_end = .; +} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +__user_noinit_size = __user_noinit_end - __user_noinit_start; +__user_noinit_load_start = LOADADDR(.user_noinit); From b0bbe923147ad81fcca97f81abf32128468d21c0 Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Fri, 8 Aug 2025 17:59:15 +0800 Subject: [PATCH 09/10] boards: xhsc: hc32f4a0_evb: Add minimal support for board HC32F4A0_EVB This adds minimal support for board HC32F4A0_EVB Signed-off-by: Yongbing Liu --- boards/xhsc/hc32f4a0_evb/Kconfig.hc32f4a0_evb | 5 + boards/xhsc/hc32f4a0_evb/board.cmake | 8 ++ boards/xhsc/hc32f4a0_evb/board.yml | 5 + boards/xhsc/hc32f4a0_evb/doc/board.webp | Bin 0 -> 61986 bytes boards/xhsc/hc32f4a0_evb/doc/index.rst | 127 ++++++++++++++++++ .../hc32f4a0_evb/hc32f4a0_evb-pinctrl.dtsi | 37 +++++ boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.dts | 121 +++++++++++++++++ boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.yaml | 16 +++ .../xhsc/hc32f4a0_evb/hc32f4a0_evb_defconfig | 17 +++ boards/xhsc/index.rst | 10 ++ 10 files changed, 346 insertions(+) create mode 100644 boards/xhsc/hc32f4a0_evb/Kconfig.hc32f4a0_evb create mode 100644 boards/xhsc/hc32f4a0_evb/board.cmake create mode 100644 boards/xhsc/hc32f4a0_evb/board.yml create mode 100644 boards/xhsc/hc32f4a0_evb/doc/board.webp create mode 100644 boards/xhsc/hc32f4a0_evb/doc/index.rst create mode 100644 boards/xhsc/hc32f4a0_evb/hc32f4a0_evb-pinctrl.dtsi create mode 100644 boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.dts create mode 100644 boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.yaml create mode 100644 boards/xhsc/hc32f4a0_evb/hc32f4a0_evb_defconfig create mode 100644 boards/xhsc/index.rst diff --git a/boards/xhsc/hc32f4a0_evb/Kconfig.hc32f4a0_evb b/boards/xhsc/hc32f4a0_evb/Kconfig.hc32f4a0_evb new file mode 100644 index 0000000000000..131284c468a08 --- /dev/null +++ b/boards/xhsc/hc32f4a0_evb/Kconfig.hc32f4a0_evb @@ -0,0 +1,5 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_HC32F4A0_EVB + select SOC_HC32F4A0 diff --git a/boards/xhsc/hc32f4a0_evb/board.cmake b/boards/xhsc/hc32f4a0_evb/board.cmake new file mode 100644 index 0000000000000..dd1cd8ec9248b --- /dev/null +++ b/boards/xhsc/hc32f4a0_evb/board.cmake @@ -0,0 +1,8 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(pyocd "--target=HC32F4A0" "--frequency=10000000") +board_runner_args(jlink "--device=HC32F4A0" "--speed=4000") + +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/xhsc/hc32f4a0_evb/board.yml b/boards/xhsc/hc32f4a0_evb/board.yml new file mode 100644 index 0000000000000..05a0890ddc5e5 --- /dev/null +++ b/boards/xhsc/hc32f4a0_evb/board.yml @@ -0,0 +1,5 @@ +board: + name: hc32f4a0_evb + vendor: xhsc + socs: + - name: hc32f4a0 diff --git a/boards/xhsc/hc32f4a0_evb/doc/board.webp b/boards/xhsc/hc32f4a0_evb/doc/board.webp new file mode 100644 index 0000000000000000000000000000000000000000..1d7dda73e7184452a1419b4d2e73c5b99b401816 GIT binary patch literal 61986 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 + +&pinctrl { + usart1_default: usart1_default { + group0 { + pinmux = , + ; + }; + }; + + usart2_default: usart2_default { + group1 { + pinmux = , + ; + }; + }; + + usart3_default: usart3_default { + group1 { + pinmux = , + ; + }; + }; + + usart4_default: usart4_default { + group1 { + pinmux = , + ; + }; + }; +}; diff --git a/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.dts b/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.dts new file mode 100644 index 0000000000000..21d907658a707 --- /dev/null +++ b/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.dts @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "hc32f4a0_evb-pinctrl.dtsi" +#include + +/ { + model = "xhsc, EV_F4A0_LQ176_Rev1.0 board"; + compatible = "xhsc,hc32f4a0_evb"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + }; + + leds { + compatible = "gpio-leds"; + + green_led: led_0 { + gpios = <&gpioc 9 GPIO_ACTIVE_HIGH>; + label = "User LED"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_button: button { + label = "Wkup_key"; + gpios = <&gpioa 0 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led; + sw0 = &user_button; + }; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&gpiog { + status = "okay"; +}; + +&gpioh { + status = "okay"; +}; + +&gpioi { + status = "okay"; +}; + +&clk_xtal { + status = "okay"; +}; + +&clk_xtal32 { + status = "okay"; +}; + +&clk_hrc { + status = "okay"; +}; + +&clk_mrc { + status = "okay"; +}; + +&clk_lrc { + status = "okay"; +}; + +&clk_pll { + status = "okay"; +}; + +&usart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&usart1_default>; + pinctrl-names = "default"; + interrupt-parent = <&intc>; + interrupts = , + , + ; + interrupt-names = "ore", "rxne", "tc"; +}; diff --git a/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.yaml b/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.yaml new file mode 100644 index 0000000000000..cbdfdfd485c78 --- /dev/null +++ b/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb.yaml @@ -0,0 +1,16 @@ +identifier: hc32f4a0_evb +name: XHSC hc32f4a0_evb +type: mcu +arch: arm +ram: 512 +flash: 2048 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - clock control + - interrupt control + - serial +vendor: xhsc diff --git a/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb_defconfig b/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb_defconfig new file mode 100644 index 0000000000000..90f7f212a65ae --- /dev/null +++ b/boards/xhsc/hc32f4a0_evb/hc32f4a0_evb_defconfig @@ -0,0 +1,17 @@ +# Copyright (C) 2024-2025, Xiaohua Semiconductor Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable FPU +CONFIG_FPU=y + +# GPIO Controller +CONFIG_GPIO=y + +CONFIG_CLOCK_CONTROL=y + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y diff --git a/boards/xhsc/index.rst b/boards/xhsc/index.rst new file mode 100644 index 0000000000000..d25f3ed75c2b7 --- /dev/null +++ b/boards/xhsc/index.rst @@ -0,0 +1,10 @@ +.. _boards-xhsc: + +XHSC +############## + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* From ffbe8f4222ed6675e210ecf089f8cfbfc5a0ae1b Mon Sep 17 00:00:00 2001 From: Yongbing Liu Date: Thu, 9 Oct 2025 15:02:58 +0800 Subject: [PATCH 10/10] drivers: serial: Remove dma support The serial DMA feature has been temporarily removed for the convenience of the PR reviewers. This functionality will be added back in the next PR. Signed-off-by: Yongbing Liu --- drivers/serial/uart_hc32.c | 583 +------------------------------------ drivers/serial/uart_hc32.h | 22 -- 2 files changed, 1 insertion(+), 604 deletions(-) diff --git a/drivers/serial/uart_hc32.c b/drivers/serial/uart_hc32.c index f173c712300e7..5ed96501c9d11 100644 --- a/drivers/serial/uart_hc32.c +++ b/drivers/serial/uart_hc32.c @@ -22,11 +22,6 @@ #include #include -#ifdef DMA_TO_BE_SUPPORTED -#include -#include -#endif - #include #include "uart_hc32.h" @@ -537,526 +532,6 @@ static void uart_hc32_irq_callback_set(const struct device *dev, uart_irq_callba #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ -#ifdef DMA_TO_BE_SUPPORTED - -static inline void async_user_callback(struct uart_hc32_data *data, struct uart_event *event) -{ - if (data->async_cb) { - data->async_cb(data->uart_dev, event, data->async_user_data); - } -} - -static inline void async_evt_rx_rdy(struct uart_hc32_data *data) -{ - LOG_DBG("rx_rdy: (%d %d)", data->dma_rx.offset, data->dma_rx.counter); - - struct uart_event event = {.type = UART_RX_RDY, - .data.rx.buf = data->dma_rx.rx_buffer, - .data.rx.len = data->dma_rx.counter - data->dma_rx.offset, - .data.rx.offset = data->dma_rx.offset}; - - /* update the current pos for new data */ - data->dma_rx.offset = data->dma_rx.counter; - - /* send event only for new data */ - if (event.data.rx.len > 0) { - async_user_callback(data, &event); - } -} - -static inline void async_evt_rx_err(struct uart_hc32_data *data, int err_code) -{ - LOG_DBG("rx error: %d", err_code); - - struct uart_event event = {.type = UART_RX_STOPPED, - .data.rx_stop.reason = err_code, - .data.rx_stop.data.len = data->dma_rx.counter, - .data.rx_stop.data.offset = 0, - .data.rx_stop.data.buf = data->dma_rx.rx_buffer}; - - async_user_callback(data, &event); -} - -static inline void async_evt_tx_done(struct uart_hc32_data *data) -{ - LOG_DBG("tx done: %d", data->dma_tx.counter); - - struct uart_event event = {.type = UART_TX_DONE, - .data.tx.buf = data->dma_tx.tx_buffer, - .data.tx.len = data->dma_tx.counter}; - - /* Reset tx buffer */ - data->dma_tx.buffer_length = 0; - data->dma_tx.counter = 0; - - async_user_callback(data, &event); -} - -static inline void async_evt_tx_abort(struct uart_hc32_data *data) -{ - LOG_DBG("tx abort: %d", data->dma_tx.counter); - - struct uart_event event = {.type = UART_TX_ABORTED, - .data.tx.buf = data->dma_tx.tx_buffer, - .data.tx.len = data->dma_tx.counter}; - - /* Reset tx buffer */ - data->dma_tx.buffer_length = 0; - data->dma_tx.counter = 0; - - async_user_callback(data, &event); -} - -static inline void async_evt_rx_buf_request(struct uart_hc32_data *data) -{ - struct uart_event evt = { - .type = UART_RX_BUF_REQUEST, - }; - - async_user_callback(data, &evt); -} - -static inline void async_evt_rx_buf_release(struct uart_hc32_data *data) -{ - struct uart_event evt = { - .type = UART_RX_BUF_RELEASED, - .data.rx_buf.buf = data->dma_rx.rx_buffer, - }; - - async_user_callback(data, &evt); -} - -static inline void async_timer_start(struct k_work_delayable *work, int32_t timeout) -{ - if ((timeout != SYS_FOREVER_US) && (timeout != 0)) { - /* start timer */ - LOG_DBG("async timer started for %d us", timeout); - k_work_reschedule(work, K_USEC(timeout)); - } -} - -static inline void async_timer_restart(struct k_work_delayable *work, int32_t timeout, void *fn) -{ - if (timeout != 0) { - (void)k_work_cancel_delayable(work); - k_work_init_delayable(work, fn); - LOG_DBG("async timer re-started for %d us", timeout); - k_work_reschedule(work, K_USEC(timeout)); - } -} - -static void uart_hc32_dma_rx_flush(const struct device *dev) -{ - struct dma_status stat; - struct uart_hc32_data *data = dev->data; - - if (dma_get_status(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &stat) == 0) { - size_t rx_rcv_len = data->dma_rx.buffer_length - stat.pending_length; - - if (rx_rcv_len > data->dma_rx.offset) { - data->dma_rx.counter = rx_rcv_len; - - async_evt_rx_rdy(data); - } - } -} - -static int uart_hc32_async_callback_set(const struct device *dev, uart_callback_t callback, - void *user_data) -{ - struct uart_hc32_data *data = dev->data; - -#if CONFIG_UART_INTERRUPT_DRIVEN - for (uint8_t i = 0; i < HC32_UART_INT_NUM; i++) { - data->cb[i].user_cb = NULL; - data->cb[i].user_data = NULL; - } -#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ - -#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) - data->async_cb = callback; - data->async_user_data = user_data; -#endif /* CONFIG_UART_EXCLUSIVE_API_CALLBACKS */ - - return 0; -} - -static inline void uart_hc32_dma_tx_disable(const struct device *dev) -{ - ARG_UNUSED(dev); -} - -static inline void uart_hc32_dma_rx_enable(const struct device *dev) -{ - struct uart_hc32_data *data = dev->data; - - data->dma_rx.enabled = true; -} - -static inline void uart_hc32_dma_rx_disable(const struct device *dev) -{ - struct uart_hc32_data *data = dev->data; - - data->dma_rx.enabled = false; -} - -static int uart_hc32_async_rx_disable(const struct device *dev) -{ - const struct uart_hc32_config *config = dev->config; - struct uart_hc32_data *data = dev->data; - struct uart_event disabled_event = {.type = UART_RX_DISABLED}; - - if (!data->dma_rx.enabled) { - async_user_callback(data, &disabled_event); - return -EFAULT; - } - - uart_hc32_dma_rx_flush(dev); - - async_evt_rx_buf_release(data); - - uart_hc32_dma_rx_disable(dev); - - (void)k_work_cancel_delayable(&data->dma_rx.timeout_work); - - dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel); - - if (data->rx_next_buffer) { - struct uart_event rx_next_buf_release_evt = { - .type = UART_RX_BUF_RELEASED, - .data.rx_buf.buf = data->rx_next_buffer, - }; - async_user_callback(data, &rx_next_buf_release_evt); - } - - data->rx_next_buffer = NULL; - data->rx_next_buffer_len = 0; - - /* When async rx is disabled, enable instance of uart to function normally */ - USART_FuncCmd(config->usart, USART_INT_RX, ENABLE); - - LOG_DBG("rx: disabled"); - - async_user_callback(data, &disabled_event); - - return 0; -} - -void uart_hc32_dma_tx_cb(const struct device *dma_dev, void *user_data, uint32_t channel, - int status) -{ - struct dma_hc32_config_user_data *cfg = user_data; - struct device *uart_dev = cfg->user_data; - struct uart_hc32_data *data = uart_dev->data; - struct dma_status stat; - - unsigned int key = irq_lock(); - - /* Disable TX */ - uart_hc32_dma_tx_disable(uart_dev); - - (void)k_work_cancel_delayable(&data->dma_tx.timeout_work); - - if (!dma_get_status(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &stat)) { - data->dma_tx.counter = data->dma_tx.buffer_length - stat.pending_length; - } - - data->dma_tx.buffer_length = 0; - - async_evt_tx_done(data); - - irq_unlock(key); -} - -static void uart_hc32_dma_replace_buffer(const struct device *dev) -{ - struct uart_hc32_data *data = dev->data; - - /* Replace the buffer and reload the DMA */ - LOG_DBG("Replacing RX buffer: %d", data->rx_next_buffer_len); - - /* reload DMA */ - data->dma_rx.offset = 0; - data->dma_rx.counter = 0; - data->dma_rx.rx_buffer = data->rx_next_buffer; - data->dma_rx.buffer_length = data->rx_next_buffer_len; - data->dma_rx.blk_cfg.block_size = data->dma_rx.buffer_length; - data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.rx_buffer; - data->rx_next_buffer = NULL; - data->rx_next_buffer_len = 0; - - dma_reload(data->dma_rx.dma_dev, data->dma_rx.dma_channel, - data->dma_rx.blk_cfg.source_address, data->dma_rx.blk_cfg.dest_address, - data->dma_rx.blk_cfg.block_size); - - dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel); - - /* Request next buffer */ - async_evt_rx_buf_request(data); -} - -static int uart_hc32_async_tx_abort(const struct device *dev) -{ - struct uart_hc32_data *data = dev->data; - size_t tx_buffer_length = data->dma_tx.buffer_length; - struct dma_status stat; - - if (tx_buffer_length == 0) { - return -EFAULT; - } - - (void)k_work_cancel_delayable(&data->dma_tx.timeout_work); - if (!dma_get_status(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &stat)) { - data->dma_tx.counter = tx_buffer_length - stat.pending_length; - } - - dma_suspend(data->dma_tx.dma_dev, data->dma_tx.dma_channel); - dma_stop(data->dma_tx.dma_dev, data->dma_tx.dma_channel); - async_evt_tx_abort(data); - - return 0; -} - -static void uart_hc32_async_rx_timeout(struct k_work *work) -{ - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct hc32_dma_cfg *rx_stream = CONTAINER_OF(dwork, struct hc32_dma_cfg, timeout_work); - struct uart_hc32_data *data = CONTAINER_OF(rx_stream, struct uart_hc32_data, dma_rx); - const struct device *dev = data->uart_dev; - - LOG_DBG("rx timeout"); - - if (data->dma_rx.counter == data->dma_rx.buffer_length) { - uart_hc32_async_rx_disable(dev); - } else { - uart_hc32_dma_rx_flush(dev); - async_timer_restart(&data->dma_rx.timeout_work, data->dma_rx.timeout, - uart_hc32_async_rx_timeout); - } -} - -static void uart_hc32_async_tx_timeout(struct k_work *work) -{ - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct hc32_dma_cfg *tx_stream = CONTAINER_OF(dwork, struct hc32_dma_cfg, timeout_work); - struct uart_hc32_data *data = CONTAINER_OF(tx_stream, struct uart_hc32_data, dma_tx); - const struct device *dev = data->uart_dev; - - uart_hc32_async_tx_abort(dev); - - LOG_DBG("tx: async timeout"); - - async_timer_restart(&data->dma_tx.timeout_work, data->dma_tx.timeout, - uart_hc32_async_tx_timeout); -} - -void uart_hc32_dma_rx_cb(const struct device *dma_dev, void *user_data, uint32_t channel, - int status) -{ - struct dma_hc32_config_user_data *cfg = user_data; - struct device *uart_dev = cfg->user_data; - struct uart_hc32_data *data = uart_dev->data; - - if (status < 0) { - async_evt_rx_err(data, status); - return; - } - - /* true since this functions occurs when buffer if full */ - data->dma_rx.counter = data->dma_rx.buffer_length; - - async_evt_rx_rdy(data); - - if (data->rx_next_buffer != NULL) { - async_evt_rx_buf_release(data); - uart_hc32_dma_replace_buffer(uart_dev); - async_timer_restart(&data->dma_rx.timeout_work, data->dma_tx.timeout, - uart_hc32_async_rx_timeout); - } else { - (void)k_work_cancel_delayable(&data->dma_rx.timeout_work); - } -} - -static int uart_hc32_async_tx(const struct device *dev, const uint8_t *tx_data, size_t buf_size, - int32_t timeout) -{ - const struct uart_hc32_config *config = dev->config; - struct uart_hc32_data *data = dev->data; - CM_USART_TypeDef *usartx = ((CM_USART_TypeDef *)config->usart); - int ret; - - if (data->dma_tx.dma_dev == NULL) { - return -ENODEV; - } - - if (data->dma_tx.buffer_length != 0) { - return -EBUSY; - } - - data->dma_tx.tx_buffer = tx_data; - data->dma_tx.buffer_length = buf_size; - data->dma_tx.timeout = timeout; - - LOG_DBG("tx: l=%d", data->dma_tx.buffer_length); - USART_FuncCmd(config->usart, USART_INT_TX_EMPTY, DISABLE); - /* TC flag = 1 after init and not generate TC event request. */ - USART_FuncCmd(config->usart, USART_TX, DISABLE); - - /* set source address */ - data->dma_tx.blk_cfg.source_address = (uint32_t)data->dma_tx.tx_buffer; - data->dma_tx.blk_cfg.dest_address = (uint32_t)&usartx->TDR; - data->dma_tx.blk_cfg.block_size = data->dma_tx.buffer_length; - - ret = dma_config(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &data->dma_tx.dma_cfg); - - if (ret != 0) { - LOG_ERR("dma tx config error!"); - return -EINVAL; - } - - /* Start and enable TX DMA requests */ - if (dma_start(data->dma_tx.dma_dev, data->dma_tx.dma_channel)) { - LOG_ERR("UART err: TX DMA start failed!"); - return -EFAULT; - } - - /* TC flag = 1 after init and not generate TC event request.*/ - USART_FuncCmd(config->usart, USART_TX, ENABLE); - - /* Start TX timer */ - async_timer_start(&data->dma_tx.timeout_work, data->dma_tx.timeout); - - return 0; -} - -static int uart_hc32_async_rx_enable(const struct device *dev, uint8_t *rx_buf, size_t buf_size, - int32_t timeout) -{ - const struct uart_hc32_config *config = dev->config; - struct uart_hc32_data *data = dev->data; - CM_USART_TypeDef *usartx = ((CM_USART_TypeDef *)config->usart); - int ret; - - if (data->dma_rx.dma_dev == NULL) { - return -ENODEV; - } - - if (data->dma_rx.enabled) { - LOG_WRN("RX was already enabled"); - return -EBUSY; - } - - USART_FuncCmd(config->usart, USART_INT_RX, DISABLE); - - data->dma_rx.offset = 0; - data->dma_rx.rx_buffer = rx_buf; - data->dma_rx.buffer_length = buf_size; - data->dma_rx.counter = 0; - data->dma_rx.timeout = timeout; - - data->dma_rx.blk_cfg.block_size = buf_size; - data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.rx_buffer; - data->dma_rx.blk_cfg.source_address = (uint32_t)&usartx->RDR; - - ret = dma_config(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &(data->dma_rx.dma_cfg)); - - if (ret != 0) { - LOG_ERR("UART ERR: RX DMA config failed!"); - return -EINVAL; - } - - if (dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel)) { - LOG_ERR("UART ERR: RX DMA start failed!"); - return -EFAULT; - } - - /* Enable RX DMA requests */ - uart_hc32_dma_rx_enable(dev); - - USART_FuncCmd(config->usart, USART_RX, ENABLE); - - /* Request next buffer */ - async_evt_rx_buf_request(data); - - async_timer_start(&data->dma_rx.timeout_work, data->dma_rx.timeout); - - LOG_DBG("async rx enabled"); - - return ret; -} - -static int uart_hc32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf, size_t len) -{ - struct uart_hc32_data *data = dev->data; - - LOG_DBG("replace buffer (%d)", len); - data->rx_next_buffer = buf; - data->rx_next_buffer_len = len; - - return 0; -} - -static int uart_hc32_async_init(const struct device *dev) -{ - struct uart_hc32_data *data = dev->data; - - data->uart_dev = dev; - - if (data->dma_rx.dma_dev != NULL) { - if (!device_is_ready(data->dma_rx.dma_dev)) { - return -ENODEV; - } - } - - if (data->dma_tx.dma_dev != NULL) { - if (!device_is_ready(data->dma_tx.dma_dev)) { - return -ENODEV; - } - } - - /* Disable both TX and RX DMA requests */ - uart_hc32_dma_rx_disable(dev); - uart_hc32_dma_tx_disable(dev); - - /* Configure dma rx config */ - memset(&data->dma_rx.blk_cfg, 0U, sizeof(data->dma_rx.blk_cfg)); - - data->dma_rx.blk_cfg.dest_address = 0; /* dest not ready */ - data->dma_rx.blk_cfg.source_addr_adj = data->dma_rx.src_addr_increment; - data->dma_rx.blk_cfg.dest_addr_adj = data->dma_rx.dst_addr_increment; - - /* RX disable circular buffer */ - data->dma_rx.blk_cfg.source_reload_en = 0; - data->dma_rx.blk_cfg.dest_reload_en = 0; - - data->dma_rx.dma_cfg.head_block = &data->dma_rx.blk_cfg; - - /* user_data will be assigned to dev when support dma uart */ - data->dma_rx.user_cfg.user_data = NULL; - data->dma_rx.dma_cfg.user_data = (void *)&data->dma_rx.user_cfg; - - data->rx_next_buffer = NULL; - data->rx_next_buffer_len = 0; - - k_work_init_delayable(&data->dma_rx.timeout_work, uart_hc32_async_rx_timeout); - - /* Configure dma tx config */ - memset(&data->dma_tx.blk_cfg, 0U, sizeof(data->dma_tx.blk_cfg)); - - data->dma_tx.blk_cfg.source_address = 0U; /* not ready */ - data->dma_tx.blk_cfg.source_addr_adj = data->dma_tx.src_addr_increment; - data->dma_tx.blk_cfg.dest_addr_adj = data->dma_tx.dst_addr_increment; - data->dma_tx.dma_cfg.head_block = &data->dma_tx.blk_cfg; - - /* user_data will be assigned to dev when support dma uart */ - data->dma_tx.user_cfg.user_data = NULL; - data->dma_tx.dma_cfg.user_data = (void *)&data->dma_tx.user_cfg; - k_work_init_delayable(&data->dma_tx.timeout_work, uart_hc32_async_tx_timeout); - - return 0; -} -#endif /* DMA_TO_BE_SUPPORTED */ - static const struct uart_driver_api uart_hc32_driver_api = { .poll_in = uart_hc32_poll_in, .poll_out = uart_hc32_poll_out, @@ -1081,14 +556,6 @@ static const struct uart_driver_api uart_hc32_driver_api = { .irq_update = uart_hc32_irq_update, .irq_callback_set = uart_hc32_irq_callback_set, #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ -#ifdef DMA_TO_BE_SUPPORTED - .callback_set = uart_hc32_async_callback_set, - .tx = uart_hc32_async_tx, - .tx_abort = uart_hc32_async_tx_abort, - .rx_enable = uart_hc32_async_rx_enable, - .rx_disable = uart_hc32_async_rx_disable, - .rx_buf_rsp = uart_hc32_async_rx_buf_rsp, -#endif /* DMA_TO_BE_SUPPORTED */ }; static int uart_hc32_registers_configure(const struct device *dev) @@ -1180,56 +647,9 @@ static int uart_hc32_init(const struct device *dev) } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ - /* config DMA */ -#ifdef DMA_TO_BE_SUPPORTED - return uart_hc32_async_init(dev); -#else return 0; -#endif } -#if defined(DMA_TO_BE_SUPPORTED) - -/* src_dev and dest_dev should be 'MEMORY' or 'PERIPHERAL'. */ -#define UART_DMA_CHANNEL_INIT(index, dir, dir_cap, src_dev, dest_dev) \ - .dma_dev = DEVICE_DT_GET(HC32_DMA_CTLR(index, dir)), \ - .dma_channel = DT_INST_DMAS_CELL_BY_NAME(index, dir, channel), \ - .dma_cfg = \ - { \ - .channel_direction = \ - HC32_DMA_CONFIG_DIRECTION(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ - .source_data_size = \ - HC32_DMA_CONFIG_DATA_SIZE(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ - .dest_data_size = \ - HC32_DMA_CONFIG_DATA_SIZE(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ - .source_burst_length = 1, /* SINGLE transfer */ \ - .dest_burst_length = 1, \ - .block_count = 1, \ - .dma_callback = uart_hc32_dma_##dir##_cb, \ - }, \ - .user_cfg = \ - { \ - .slot = HC32_DMA_SLOT(index, dir), \ - }, \ - .src_addr_increment = \ - HC32_DMA_CONFIG_##src_dev##_ADDR_INC(HC32_DMA_CHANNEL_CONFIG(index, dir)), \ - .dst_addr_increment = \ - HC32_DMA_CONFIG_##dest_dev##_ADDR_INC(HC32_DMA_CHANNEL_CONFIG(index, dir)), -#else -#define HC32_UART_DMA_CFG_DECL(index) -#endif /* DMA_TO_BE_SUPPORTED */ - -#ifdef DMA_TO_BE_SUPPORTED -/* If defined async, let dma deal with transmission */ -#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) \ - .dma_##dir = {COND_CODE_1( \ - DT_INST_DMAS_HAS_NAME(index, dir), \ - (UART_DMA_CHANNEL_INIT(index, dir, DIR, src, dest)), \ - ()) }, -#else -#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) -#endif /* DMA_TO_BE_SUPPORTED */ - #define DT_USART_HAS_INTR(node_id) IS_ENABLED(DT_CAT4(node_id, _P_, interrupts, _EXISTS)) #define DT_IS_INTR_EXIST(index) DT_USART_HAS_INTR(DT_INST(index, xhsc_hc32_uart)) @@ -1354,8 +774,7 @@ static int uart_hc32_init(const struct device *dev) HC32_UART_IRQ_HANDLER_PRE_FUNC(index)}; \ static struct uart_hc32_data uart_hc32_data_##index = { \ .uart_cfg = &uart_cfg_##index, \ - UART_DMA_CHANNEL(index, rx, RX, SOURCE, DEST) \ - UART_DMA_CHANNEL(index, tx, TX, SOURCE, DEST)}; \ + }; \ DEVICE_DT_INST_DEFINE(index, &uart_hc32_init, NULL, &uart_hc32_data_##index, \ &uart_hc32_cfg_##index, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ &uart_hc32_driver_api); \ diff --git a/drivers/serial/uart_hc32.h b/drivers/serial/uart_hc32.h index fa009cfec0ac2..a76cad9d4a49d 100644 --- a/drivers/serial/uart_hc32.h +++ b/drivers/serial/uart_hc32.h @@ -47,26 +47,6 @@ struct uart_hc32_config { #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ }; -#ifdef CONFIG_UART_ASYNC_API -struct hc32_dma_cfg { - const struct device *dma_dev; - uint32_t dma_channel; - struct dma_config dma_cfg; - uint16_t src_addr_increment; - uint16_t dst_addr_increment; - struct dma_block_config blk_cfg; - size_t buffer_length; - size_t offset; - const uint8_t *tx_buffer; - uint8_t *rx_buffer; - volatile size_t counter; - int32_t timeout; - struct k_work_delayable timeout_work; - bool enabled; - struct dma_hc32_config_user_data user_cfg; -}; -#endif - struct hc32_usart_cb_data { /** Callback function */ uart_irq_callback_user_data_t user_cb; @@ -88,8 +68,6 @@ struct uart_hc32_data { const struct device *uart_dev; uart_callback_t async_cb; void *async_user_data; - struct hc32_dma_cfg dma_tx; - struct hc32_dma_cfg dma_rx; uint8_t *rx_next_buffer; size_t rx_next_buffer_len; #endif