diff --git a/boards/focaltech/ft9001_eval/Kconfig.ft9001_eval b/boards/focaltech/ft9001_eval/Kconfig.ft9001_eval new file mode 100644 index 0000000000000..34da2097ad19c --- /dev/null +++ b/boards/focaltech/ft9001_eval/Kconfig.ft9001_eval @@ -0,0 +1,5 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FT9001_EVAL + select SOC_FT9001 diff --git a/boards/focaltech/ft9001_eval/board.cmake b/boards/focaltech/ft9001_eval/board.cmake new file mode 100644 index 0000000000000..d882a5aff90a7 --- /dev/null +++ b/boards/focaltech/ft9001_eval/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=FT9001" "--speed=4000") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/focaltech/ft9001_eval/board.yml b/boards/focaltech/ft9001_eval/board.yml new file mode 100644 index 0000000000000..0c5e33a1c1912 --- /dev/null +++ b/boards/focaltech/ft9001_eval/board.yml @@ -0,0 +1,6 @@ +board: + name: ft9001_eval + full_name: FocalTech FT9001 Evaluation Board + vendor: focaltech + socs: + - name: ft9001 diff --git a/boards/focaltech/ft9001_eval/doc/index.rst b/boards/focaltech/ft9001_eval/doc/index.rst new file mode 100644 index 0000000000000..41346195d2a6d --- /dev/null +++ b/boards/focaltech/ft9001_eval/doc/index.rst @@ -0,0 +1,44 @@ +:orphan: + +.. _focaltech_ft9001_eval: + +.. zephyr:board:: ft9001_eval + +FT9001 Evaluation Board +####################### + +The **FT9001-EVAL** board is a hardware platform designed for evaluating and +debugging the FocalTech FT9001 MCU, a high-performance ARM Cortex-M4F processor +running at up to 160 MHz. + +It includes 32 KB of ROM and 256 KB of RAM, divided into 224 KB of standard SRAM +and a distinct 32 KB DBUS-connected block. + +Hardware +******** + +- FocalTech FT9001 SoC (ARM Cortex-M4F compatible) +- 32 KB boot ROM +- 256 KB on-chip SRAM: + - 224 KB standard SRAM + - 32 KB DBUS-connected SRAM +- 2 MB external flash memory (SPI interface) +- 2x UART interfaces +- 2x SPI interface +- External GPIO pins with interrupt capability + +Supported Features +****************** + +.. zephyr:board-supported-hw:: + +Building and Running +******************** + +Build and flash the :zephyr:code-sample:`hello_world` sample application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: ft9001_eval + :goals: build flash + :compact: diff --git a/boards/focaltech/ft9001_eval/ft9001_eval-pinctrl.dtsi b/boards/focaltech/ft9001_eval/ft9001_eval-pinctrl.dtsi new file mode 100644 index 0000000000000..e04c431ccbec8 --- /dev/null +++ b/boards/focaltech/ft9001_eval/ft9001_eval-pinctrl.dtsi @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + usart3_default: usart3_default { + group1 { + pinmux = , + ; + }; + + group2 { + /* Disable I2S */ + pinmux = , + ; + }; + + group3 { + /* Disable PWMT1 */ + pinmux = , + ; + }; + }; + + /* Pin28 configured as GINT40 */ + gint40_default: gint40_default { + group1 { + /* First level mux: SSI5 -> SPI1_SS */ + pinmux = ; + }; + + group2 { + /* Second level mux: SPI1_SS -> GINT40 */ + pinmux = ; + }; + }; + + /* Pin26 configured as GINT41 */ + gint41_default: gint41_default { + group1 { + /* First level mux: SSI5 -> SPI1_SCK */ + pinmux = ; + }; + + group2 { + /* Second level mux: SPI1_SCK -> GINT41 */ + pinmux = ; + }; + }; + + /* Pin29 configured as GINT42 */ + gint42_default: gint42_default { + group1 { + /* First level mux: SSI5 -> SPI1_MISO */ + pinmux = ; + }; + + group2 { + /* Second level mux: SPI1_MISO -> GINT42 */ + pinmux = ; + }; + }; + + /* Pin27 configured as GINT43 */ + gint43_default: gint43_default { + group1 { + /* First level mux: SSI5 -> SPI1_MOSI */ + pinmux = ; + }; + + group2 { + /* Second level mux: SPI1_MOSI -> GINT43 */ + pinmux = ; + }; + }; +}; diff --git a/boards/focaltech/ft9001_eval/ft9001_eval.dts b/boards/focaltech/ft9001_eval/ft9001_eval.dts new file mode 100644 index 0000000000000..7cc8e8b90d188 --- /dev/null +++ b/boards/focaltech/ft9001_eval/ft9001_eval.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "ft9001_eval-pinctrl.dtsi" +#include + +/ { + model = "FocalTech FT9001 Evaluation Board"; + compatible = "focaltech,ft9001-eval", "focaltech,ft9001"; + + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,flash = &flash0; + zephyr,sram = &sram0; + zephyr,sram2 = &sramd0; + zephyr,flash-controller = &efm; + zephyr,code-partition = &app_partition; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + romcfg_partition: partition@0 { + label = "romcfg"; + reg = <0x00000000 0x00001000>; + read-only; + }; + + app_partition: partition@1000 { + label = "app"; + reg = <0x00001000 0x001FF000>; + }; + }; +}; + +&usart2 { + current-speed = <115200>; + parity = "none"; + stop-bits = "1"; + data-bits = <8>; + hw-flow-control; + status = "okay"; +}; + +&efm { + status = "okay"; +}; + +&eport1 { + mask = <0x20>; + ngpios = <8>; + status = "okay"; +}; + +&eport5 { + mask = <0xFF>; + ngpios = <8>; + status = "okay"; +}; + +&eport7 { + mask = <0x3C>; + ngpios = <8>; + status = "okay"; +}; diff --git a/boards/focaltech/ft9001_eval/ft9001_eval.yaml b/boards/focaltech/ft9001_eval/ft9001_eval.yaml new file mode 100644 index 0000000000000..18b062d4c590d --- /dev/null +++ b/boards/focaltech/ft9001_eval/ft9001_eval.yaml @@ -0,0 +1,12 @@ +identifier: ft9001_eval +name: FocalTech FT9001 Evaluation Board +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 256 +flash: 2048 +supported: + - serial +vendor: focaltech diff --git a/boards/focaltech/ft9001_eval/ft9001_eval_defconfig b/boards/focaltech/ft9001_eval/ft9001_eval_defconfig new file mode 100644 index 0000000000000..b45a1af7a7da0 --- /dev/null +++ b/boards/focaltech/ft9001_eval/ft9001_eval_defconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_USE_DT_CODE_PARTITION=y diff --git a/boards/focaltech/ft9001_eval/support/openocd.cfg b/boards/focaltech/ft9001_eval/support/openocd.cfg new file mode 100644 index 0000000000000..a4225eeabcd75 --- /dev/null +++ b/boards/focaltech/ft9001_eval/support/openocd.cfg @@ -0,0 +1,31 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +# FT9001 OpenOCD Configuration +# +# This configuration supports debugging the FT9001 evaluation board +# using CMSIS-DAP compatible debuggers (such as DAPLink, J-Link, etc.) +# +# Usage: openocd -f boards/arm/ft9001_eval/support/openocd.cfg + +source [find interface/cmsis-dap.cfg] +transport select swd + +set CHIPNAME ft9001 +set CPUTAPID 0x790007a3 + +source [find target/stm32f4x.cfg] + +reset_config trst_and_srst separate + +# Configure target events for better debugging experience +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 13100d651592d..479b4a52b8613 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -133,3 +133,4 @@ endif() zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MAX32 clock_control_max32.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_WCH_RCC clock_control_wch_rcc.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_FOCALTECH_FT9001 clock_control_ft9001.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index e2c4a071ab09a..af8746db6d311 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -34,6 +34,8 @@ source "drivers/clock_control/Kconfig.beetle" source "drivers/clock_control/Kconfig.bflb" +source "drivers/clock_control/Kconfig.focaltech" + source "drivers/clock_control/Kconfig.fixed" source "drivers/clock_control/Kconfig.lpc11u6x" diff --git a/drivers/clock_control/Kconfig.focaltech b/drivers/clock_control/Kconfig.focaltech new file mode 100644 index 0000000000000..6508025114111 --- /dev/null +++ b/drivers/clock_control/Kconfig.focaltech @@ -0,0 +1,14 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_FOCALTECH_FT9001 + bool "FocalTech FT9001 Clock Power Module (CPM) driver" + default y + depends on DT_HAS_FOCALTECH_FT9001_CPM_ENABLED + help + Enable clock control driver for FocalTech FT9001 SoC. + This driver provides support for controlling peripheral + clocks through the Clock Power Module (CPM) which manages + clock gating for various on-chip peripherals including + UART, SPI, I2C, CAN, USB, crypto engines, and memory + controllers. diff --git a/drivers/clock_control/clock_control_ft9001.c b/drivers/clock_control/clock_control_ft9001.c new file mode 100644 index 0000000000000..a006758830e7b --- /dev/null +++ b/drivers/clock_control/clock_control_ft9001.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT focaltech_ft9001_cpm + +#include +#include +#include +#include +#include + +/** Clock register offset (from encoded id) */ +#define FT9001_CLOCK_REG_OFFSET(id) (((id) >> FOCALTECH_CLOCK_SHIFT) & 0xFFFFU) +/** Clock control bit (from encoded id) */ +#define FT9001_CLOCK_BIT(id) ((id) & FOCALTECH_CLOCK_MASK) + +struct clock_control_ft9001_config { + uint32_t base; +}; + +/** + * @brief Enable a clock + * + * @param dev Clock control device + * @param sys Clock subsystem ID + * + * @retval 0 Always successful + */ +static int clock_control_ft9001_on(const struct device *dev, clock_control_subsys_t sys) +{ + const struct clock_control_ft9001_config *config = dev->config; + uint32_t id = POINTER_TO_UINT(sys); + uint32_t reg_offset = FT9001_CLOCK_REG_OFFSET(id); + uint32_t bit = FT9001_CLOCK_BIT(id); + volatile uint32_t *reg = (volatile uint32_t *)(config->base + reg_offset); + + *reg |= BIT(bit); + + return 0; +} + +/** + * @brief Disable a clock + * + * @param dev Clock control device + * @param sys Clock subsystem ID + * + * @retval 0 Always successful + */ +static int clock_control_ft9001_off(const struct device *dev, clock_control_subsys_t sys) +{ + const struct clock_control_ft9001_config *config = dev->config; + uint32_t id = POINTER_TO_UINT(sys); + uint32_t reg_offset = FT9001_CLOCK_REG_OFFSET(id); + uint32_t bit = FT9001_CLOCK_BIT(id); + volatile uint32_t *reg = (volatile uint32_t *)(config->base + reg_offset); + + *reg &= ~BIT(bit); + + return 0; +} + +/** + * @brief Get clock status + * + * @param dev Clock control device + * @param sys Clock subsystem ID + * + * @retval CLOCK_CONTROL_STATUS_ON if clock is enabled + * @retval CLOCK_CONTROL_STATUS_OFF if clock is disabled + */ +static enum clock_control_status clock_control_ft9001_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + const struct clock_control_ft9001_config *config = dev->config; + uint32_t id = POINTER_TO_UINT(sys); + uint32_t reg_offset = FT9001_CLOCK_REG_OFFSET(id); + uint32_t bit = FT9001_CLOCK_BIT(id); + volatile uint32_t *reg = (volatile uint32_t *)(config->base + reg_offset); + + if ((*reg & BIT(bit)) != 0) { + return CLOCK_CONTROL_STATUS_ON; + } + + return CLOCK_CONTROL_STATUS_OFF; +} + +static const struct clock_control_driver_api clock_control_ft9001_api = { + .on = clock_control_ft9001_on, + .off = clock_control_ft9001_off, + .get_status = clock_control_ft9001_get_status, +}; + +static const struct clock_control_ft9001_config ft9001_cpm_config = { + .base = DT_INST_REG_ADDR(0), +}; + +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &ft9001_cpm_config, PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_control_ft9001_api); diff --git a/drivers/reset/CMakeLists.txt b/drivers/reset/CMakeLists.txt index 363720f271304..a26b7c67a9726 100644 --- a/drivers/reset/CMakeLists.txt +++ b/drivers/reset/CMakeLists.txt @@ -16,3 +16,4 @@ zephyr_library_sources_ifdef(CONFIG_RESET_NXP_RSTCTL reset_nxp_rstctl.c) zephyr_library_sources_ifdef(CONFIG_RESET_MMIO reset_mmio.c) zephyr_library_sources_ifdef(CONFIG_RESET_MCHP_MSS reset_mchp_mss.c) zephyr_library_sources_ifdef(CONFIG_RESET_SF32LB reset_sf32lb.c) +zephyr_library_sources_ifdef(CONFIG_RESET_FOCALTECH_FT9001 reset_ft9001.c) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index b5c76cc70c9fe..9b4ab3c4b04fc 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -40,5 +40,6 @@ rsource "Kconfig.nxp_rstctl" rsource "Kconfig.mmio" rsource "Kconfig.mchp_mss" rsource "Kconfig.sf32lb" +rsource "Kconfig.focaltech" endif # RESET diff --git a/drivers/reset/Kconfig.focaltech b/drivers/reset/Kconfig.focaltech new file mode 100644 index 0000000000000..1ce18376ce57a --- /dev/null +++ b/drivers/reset/Kconfig.focaltech @@ -0,0 +1,14 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +config RESET_FOCALTECH_FT9001 + bool "FocalTech FT9001 Reset Control Module driver" + default y + depends on DT_HAS_FOCALTECH_FT9001_CPM_RCTL_ENABLED + help + Enable reset control driver for FocalTech FT9001 SoC. + This driver provides support for controlling peripheral + resets through the Reset Control Module which manages + reset signals for various on-chip peripherals including + UART, SPI, I2C, CAN, USB, crypto engines, and memory + controllers. diff --git a/drivers/reset/reset_ft9001.c b/drivers/reset/reset_ft9001.c new file mode 100644 index 0000000000000..239a5c78f7359 --- /dev/null +++ b/drivers/reset/reset_ft9001.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT focaltech_ft9001_cpm_rctl + +#include +#include +#include +#include +#include + +/** Reset register offset (from encoded id) */ +#define FT9001_RESET_REG_OFFSET(id) (((id) >> FOCALTECH_RESET_SHIFT) & 0xFFFFU) +/** Reset control bit (from encoded id) */ +#define FT9001_RESET_BIT(id) ((id) & FOCALTECH_RESET_MASK) + +struct reset_ft9001_config { + uint32_t base; +}; + +/** + * @brief Get reset line status + * + * @param dev Reset controller device + * @param id Reset line ID + * @param status Pointer to store reset line status (0=deasserted, 1=asserted) + * + * @retval 0 Always successful + */ +static int reset_ft9001_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const struct reset_ft9001_config *config = dev->config; + uint32_t reg_offset = FT9001_RESET_REG_OFFSET(id); + uint32_t bit = FT9001_RESET_BIT(id); + volatile uint32_t *reg = (volatile uint32_t *)(config->base + reg_offset); + + *status = !!(*reg & BIT(bit)); + + return 0; +} + +/** + * @brief Assert a reset line + * + * @param dev Reset controller device + * @param id Reset line ID + * + * @retval 0 Always successful + */ +static int reset_ft9001_line_assert(const struct device *dev, uint32_t id) +{ + const struct reset_ft9001_config *config = dev->config; + uint32_t reg_offset = FT9001_RESET_REG_OFFSET(id); + uint32_t bit = FT9001_RESET_BIT(id); + volatile uint32_t *reg = (volatile uint32_t *)(config->base + reg_offset); + + *reg |= BIT(bit); + + return 0; +} + +/** + * @brief Deassert a reset line + * + * @param dev Reset controller device + * @param id Reset line ID + * + * @retval 0 Always successful + */ +static int reset_ft9001_line_deassert(const struct device *dev, uint32_t id) +{ + const struct reset_ft9001_config *config = dev->config; + uint32_t reg_offset = FT9001_RESET_REG_OFFSET(id); + uint32_t bit = FT9001_RESET_BIT(id); + volatile uint32_t *reg = (volatile uint32_t *)(config->base + reg_offset); + + *reg &= ~BIT(bit); + + return 0; +} + +/** + * @brief Toggle a reset line (assert then deassert) + * + * @param dev Reset controller device + * @param id Reset line ID + * + * @retval 0 Always successful + */ +static int reset_ft9001_line_toggle(const struct device *dev, uint32_t id) +{ + reset_ft9001_line_assert(dev, id); + reset_ft9001_line_deassert(dev, id); + + return 0; +} + +static const struct reset_driver_api reset_ft9001_driver_api = { + .status = reset_ft9001_status, + .line_assert = reset_ft9001_line_assert, + .line_deassert = reset_ft9001_line_deassert, + .line_toggle = reset_ft9001_line_toggle, +}; + +static const struct reset_ft9001_config ft9001_reset_config = { + .base = DT_REG_ADDR(DT_PARENT(DT_DRV_INST(0))), +}; + +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &ft9001_reset_config, PRE_KERNEL_1, + CONFIG_RESET_INIT_PRIORITY, &reset_ft9001_driver_api); diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 63520ac12639d..d5f5d7a4c6d67 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -37,6 +37,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_EMUL uart_emul.c) 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_FOCALTECH uart_ft9001.c) zephyr_library_sources_ifdef(CONFIG_UART_GECKO uart_gecko.c) zephyr_library_sources_ifdef(CONFIG_UART_HOSTLINK uart_hostlink.c) zephyr_library_sources_ifdef(CONFIG_UART_IMX uart_imx.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0d58009f31eb2..7a5bff4f87348 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -177,6 +177,7 @@ rsource "Kconfig.efinix_sapphire" rsource "Kconfig.emul" rsource "Kconfig.ene" rsource "Kconfig.esp32" +rsource "Kconfig.focaltech" rsource "Kconfig.gd32" rsource "Kconfig.gecko" rsource "Kconfig.hostlink" diff --git a/drivers/serial/Kconfig.focaltech b/drivers/serial/Kconfig.focaltech new file mode 100644 index 0000000000000..f0a683913d15e --- /dev/null +++ b/drivers/serial/Kconfig.focaltech @@ -0,0 +1,11 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +config UART_FOCALTECH + bool "FocalTech FT9001 MCU serial driver" + default y + depends on DT_HAS_FOCALTECH_FT9001_USART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + help + Enable UART driver for FocalTech FT9001 SoC. diff --git a/drivers/serial/uart_ft9001.c b/drivers/serial/uart_ft9001.c new file mode 100644 index 0000000000000..da3ce2bc0915f --- /dev/null +++ b/drivers/serial/uart_ft9001.c @@ -0,0 +1,599 @@ +/* + * Copyright (c) 2025, FocalTech Systems Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief UART driver for FocalTech FT9001 SoC (register-based implementation) + * + * This driver provides UART support using direct register operations based on + * the FocalTech FT9001 UART hardware specification. + */ + +#define DT_DRV_COMPAT focaltech_ft9001_usart + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(uart_ft9001, CONFIG_UART_LOG_LEVEL); + +/* FT9001 UART register structure (based on HAL) */ +struct ft9001_uart_regs { + __IO uint8_t SCIBDL; /* 0x00 - Baud Rate Low */ + __IO uint8_t SCIBDH; /* 0x01 - Baud Rate High */ + __IO uint8_t SCICR2; /* 0x02 - Control Register 2 */ + __IO uint8_t SCICR1; /* 0x03 - Control Register 1 */ + __IO uint8_t SCISR2; /* 0x04 - Status Register 2 */ + __IO uint8_t SCISR1; /* 0x05 - Status Register 1 */ + __IO uint8_t SCIDRL; /* 0x06 - Data Register Low */ + __IO uint8_t SCIDRH; /* 0x07 - Data Register High */ + __IO uint8_t SCIPORT; /* 0x08 - Port Register */ + __IO uint8_t SCIPURD; /* 0x09 - Pull-up Disable Register */ + __IO uint8_t SCIBRDF; /* 0x0A - Baud Rate Fraction */ + __IO uint8_t SCIDDR; /* 0x0B - Data Direction Register */ + __IO uint8_t SCIIRCR; /* 0x0C - IrDA Control Register */ + __IO uint8_t SCITR; /* 0x0D - Test Register */ + __IO uint8_t SCIFCR; /* 0x0E - FIFO Control Register */ + __IO uint8_t SCIIRDR; /* 0x0F - IrDA Data Register */ + __IO uint8_t SCIDCR; /* 0x10 - DMA Control Register */ + __IO uint8_t SCIFSR; /* 0x11 - FIFO Status Register */ + __IO uint8_t SCIRXTOCTR; /* 0x12 - RX Timeout Counter */ + __IO uint8_t SCIFCR2; /* 0x13 - FIFO Control Register 2 */ + __IO uint8_t SCIFCTRL; /* 0x14 - FIFO Control Register */ + __IO uint8_t SCIFSR2; /* 0x15 - FIFO Status Register 2 */ +}; + +/* Control Register 1 bits */ +#define SCICR1_M_MASK 0x10 /* Frame length */ +#define SCICR1_PE_MASK 0x02 /* Parity enable */ +#define SCICR1_PT_MASK 0x01 /* Parity type */ + +/* Control Register 2 bits */ +#define SCICR2_TE_MASK 0x08 /* Transmitter enable */ +#define SCICR2_RE_MASK 0x04 /* Receiver enable */ + +/* FIFO Control Register bits */ +#define SCIFCR_RFEN 0x80 /* RX FIFO enable */ +#define SCIFCR_TFEN 0x40 /* TX FIFO enable */ +#define SCIFCR_RXFLSEL_1_8 0x00 /* RX FIFO trigger level */ +#define SCIFCR_TXFLSEL_1_8 0x04 /* TX FIFO trigger level */ + +/* FIFO Control Register 2 bits */ +#define SCIFCR2_RXFTOE 0x04 /* RX FIFO timeout enable */ +#define SCIFCR2_TXFCLR 0x02 /* TX FIFO clear */ +#define SCIFCR2_RXFCLR 0x01 /* RX FIFO clear */ +#define SCIFCR2_TXFIE 0x80 /* TX FIFO interrupt enable */ +#define SCIFCR2_RXFIE 0x20 /* RX FIFO interrupt enable */ +#define SCIFCR2_RXFTOIE 0x08 /* RX FIFO timeout interrupt enable */ +#define SCIFCR2_RXORIE 0x10 /* RX overrun interrupt enable */ + +/* FIFO Status Register bits */ +#define SCIFSR_TFULL_MASK 0x08 /* TX FIFO full */ +#define SCIFSR_TEMPTY_MASK 0x04 /* TX FIFO empty */ +#define SCIFSR_REMPTY_MASK 0x01 /* RX FIFO empty */ +#define SCIFSR_RFTS_MASK 0x20 /* RX FIFO trigger level reached */ +#define SCIFSR_FTC_MASK 0x40 /* Frame transmission complete */ + +/* Status Register 2 bits */ +#define SCISR2_FOR_MASK 0x08 /* FIFO overrun */ +#define SCISR2_FPF_MASK 0x01 /* Parity error */ +#define SCISR2_FNF_MASK 0x04 /* Noise error */ +#define SCISR2_FFE_MASK 0x02 /* Frame error */ + +/* HAL compatibility defines */ +#define UART_DATA_FRAME_LEN_10BIT 0 +#define UART_DATA_FRAME_LEN_11BIT SCICR1_M_MASK +#define UART_PARITY_NONE 2 +#define UART_PARITY_EVE 0 +#define UART_PARITY_ODD SCICR1_PT_MASK +#define UART_INT_MODE 1 + +/** + * @brief UART device configuration structure + */ +struct uart_ft9001_config { + struct ft9001_uart_regs *base; /* UART base address */ + uint32_t clkid; /* Clock control ID */ + struct reset_dt_spec reset; /* Reset control */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_config_func_t irq_config_func; /* IRQ config function */ +#endif +}; + +/** + * @brief UART device runtime data structure + */ +struct uart_ft9001_data { + struct uart_config uart_cfg; /* UART configuration */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t cb; /* Callback function */ + void *cb_data; /* Callback data */ +#endif +}; + +#define DEV_CFG(dev) ((const struct uart_ft9001_config *)(dev)->config) +#define DEV_DATA(dev) ((struct uart_ft9001_data *)(dev)->data) + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static void uart_ft9001_isr(const struct device *dev); +#endif + +/** + * @brief Configure UART hardware (based on HAL UART_Init) + */ +static void uart_ft9001_hw_init(struct ft9001_uart_regs *base, const struct uart_config *cfg, + uint32_t sys_freq) +{ + uint16_t bandrate_i; + uint8_t bandrate_f; + uint8_t bandrate_h; + uint8_t bandrate_l; + + /* Calculate baud rate divisors (from HAL) */ + bandrate_i = ((uint16_t)(sys_freq * 4 / cfg->baudrate)) >> 6; + bandrate_f = (((uint16_t)(sys_freq * 8 / cfg->baudrate) + 1) / 2) & 0x003f; + bandrate_h = (uint8_t)((bandrate_i >> 8) & 0x00ff); + bandrate_l = (uint8_t)(bandrate_i & 0x00ff); + + /* Disable UART */ + base->SCICR2 = 0; + base->SCIFCR = 0; + + /* Enable FIFO mode */ + base->SCIFCR = SCIFCR_RFEN | SCIFCR_TFEN; + + /* Set baud rate (write fraction before integer) */ + base->SCIBRDF = bandrate_f; + base->SCIBDH = bandrate_h; + base->SCIBDL = bandrate_l; + + /* Configure frame format */ + base->SCICR1 = 0x00; + if (cfg->data_bits == UART_CFG_DATA_BITS_9) { + base->SCICR1 |= UART_DATA_FRAME_LEN_11BIT; + } else { + base->SCICR1 |= UART_DATA_FRAME_LEN_10BIT; + } + + /* Configure parity */ + if (cfg->parity == UART_CFG_PARITY_NONE) { + /* Parity disabled - no additional bits to set */ + } else { + base->SCICR1 |= SCICR1_PE_MASK; /* Enable parity */ + if (cfg->parity == UART_CFG_PARITY_ODD) { + base->SCICR1 |= SCICR1_PT_MASK; /* Odd parity */ + } + /* Even parity is default when PE=1, PT=0 */ + } + + /* Set FIFO waterlines */ + base->SCIFCR |= (SCIFCR_RXFLSEL_1_8 | SCIFCR_TXFLSEL_1_8); + base->SCIDRL = 0; /* Clear data register */ + + /* Configure FIFO control 2 */ + base->SCIFCR2 = 0; + base->SCIFCR2 |= SCIFCR2_RXFTOE; /* Enable RX FIFO timeout */ + base->SCIFCR2 |= (SCIFCR2_RXFCLR | SCIFCR2_TXFCLR); /* Clear FIFOs */ + + /* Clear status registers */ + base->SCIFSR2 = base->SCIFSR2; + + /* Enable transmitter and receiver */ + base->SCICR2 |= SCICR2_TE_MASK | SCICR2_RE_MASK; +} + +/** + * @brief Initialize the UART device + */ +static int uart_ft9001_init(const struct device *dev) +{ + const struct device *clk = DEVICE_DT_GET(DT_NODELABEL(cpm)); + const struct uart_ft9001_config *config = DEV_CFG(dev); + struct uart_ft9001_data *data = DEV_DATA(dev); + uint32_t sys_freq; + int ret = 0; + + LOG_DBG("Initializing UART at base %p", config->base); + + /* Enable UART clock */ + ret = clock_control_on(clk, (clock_control_subsys_t *)(uintptr_t)config->clkid); + if (ret < 0) { + LOG_ERR("Could not enable UART clock"); + return ret; + } + + /* Get system frequency */ + ret = clock_control_get_rate(clk, (clock_control_subsys_t *)(uintptr_t)config->clkid, + &sys_freq); + if (ret < 0) { + LOG_WRN("Could not get UART clock rate, using default"); + sys_freq = 160000000 / 2; /* Default assumption */ + } + + /* Toggle reset line */ + ret = reset_line_toggle_dt(&config->reset); + if (ret < 0) { + LOG_ERR("UART reset failed"); + return ret; + } + + /* Initialize hardware */ + uart_ft9001_hw_init(config->base, &data->uart_cfg, sys_freq); + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + /* Configure interrupts */ + config->irq_config_func(dev); + /* Initially disable all interrupts */ + config->base->SCIFCR2 &= + ~(SCIFCR2_TXFIE | SCIFCR2_RXFIE | SCIFCR2_RXFTOIE | SCIFCR2_RXORIE); +#endif + + LOG_INF("UART initialized at %p, baudrate %d", config->base, data->uart_cfg.baudrate); + return 0; +} + +/** + * @brief Read a character from UART (polling mode) + */ +static int uart_ft9001_poll_in(const struct device *dev, unsigned char *c) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + if (config->base->SCIFSR & SCIFSR_REMPTY_MASK) { + return -1; /* No data available */ + } + + *c = config->base->SCIDRL; + return 0; +} + +/** + * @brief Send a character via UART (polling mode) + */ +static void uart_ft9001_poll_out(const struct device *dev, unsigned char c) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + /* Wait for TX FIFO not full */ + while (config->base->SCIFSR & SCIFSR_TFULL_MASK) { + /* Wait */ + } + + /* Send character */ + config->base->SCIDRL = c & 0xff; + + /* Wait for transmission complete */ + while (1) { + if ((config->base->SCIFSR & SCIFSR_TEMPTY_MASK) && + (config->base->SCIFSR & SCIFSR_FTC_MASK)) { + break; + } + } +} + +/** + * @brief Check for UART errors + */ +static int uart_ft9001_err_check(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + int z_err = 0; + + /* Check error flags in SCIFSR2 */ + z_err = ((config->base->SCIFSR2 & SCISR2_FOR_MASK) ? (1 << 0) : 0) | /* Overrun */ + ((config->base->SCIFSR2 & SCISR2_FPF_MASK) ? (1 << 1) : 0) | /* Parity */ + ((config->base->SCIFSR2 & SCISR2_FNF_MASK) ? (1 << 5) : 0) | /* Noise */ + ((config->base->SCIFSR2 & SCISR2_FFE_MASK) ? (1 << 2) : 0); /* Frame */ + + /* Clear error flags by writing back */ + config->base->SCIFSR2 = config->base->SCIFSR2; + + return z_err; +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE +/** + * @brief Configure UART parameters at runtime + */ +static int uart_ft9001_configure(const struct device *dev, const struct uart_config *cfg) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + struct uart_ft9001_data *data = DEV_DATA(dev); + const struct device *clk = DEVICE_DT_GET(DT_NODELABEL(cpm)); + uint32_t sys_freq; + int ret; + + /* Validate configuration */ + if (cfg->stop_bits != UART_CFG_STOP_BITS_1) { + return -ENOTSUP; + } + if (cfg->data_bits != UART_CFG_DATA_BITS_8 && cfg->data_bits != UART_CFG_DATA_BITS_9) { + return -ENOTSUP; + } + if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { + return -ENOTSUP; + } + + /* Get clock frequency */ + ret = clock_control_get_rate(clk, (clock_control_subsys_t *)(uintptr_t)config->clkid, + &sys_freq); + if (ret < 0) { + sys_freq = 160000000 / 2; + } + + /* Reconfigure hardware */ + uart_ft9001_hw_init(config->base, cfg, sys_freq); + + /* Update stored configuration */ + data->uart_cfg = *cfg; + + return 0; +} + +/** + * @brief Get current UART configuration + */ +static int uart_ft9001_config_get(const struct device *dev, struct uart_config *cfg) +{ + const struct uart_ft9001_data *data = DEV_DATA(dev); + + *cfg = data->uart_cfg; + return 0; +} +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +/** + * @brief Fill TX FIFO with data + */ +static int uart_ft9001_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + int num_tx = 0; + + for (num_tx = 0; num_tx < size; num_tx++) { + if (config->base->SCIFSR & SCIFSR_TFULL_MASK) { + break; /* TX FIFO full */ + } + config->base->SCIDRL = tx_data[num_tx]; + } + + return num_tx; +} + +/** + * @brief Read data from RX FIFO + */ +static int uart_ft9001_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + int i = 0; + + while (!(config->base->SCIFSR & SCIFSR_REMPTY_MASK) && (i < size)) { + rx_data[i] = config->base->SCIDRL; + i++; + } + + return i; +} + +/** + * @brief Enable TX interrupt + */ +static void uart_ft9001_irq_tx_enable(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + config->base->SCIFCR2 |= SCIFCR2_TXFIE; +} + +/** + * @brief Disable TX interrupt + */ +static void uart_ft9001_irq_tx_disable(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + config->base->SCIFCR2 &= ~SCIFCR2_TXFIE; +} + +/** + * @brief Check if TX is ready + */ +static int uart_ft9001_irq_tx_ready(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + return !(config->base->SCIFSR & SCIFSR_TFULL_MASK); +} + +/** + * @brief Enable RX interrupt + */ +static void uart_ft9001_irq_rx_enable(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + config->base->SCIFCR2 |= (SCIFCR2_RXFIE | SCIFCR2_RXFTOIE); +} + +/** + * @brief Disable RX interrupt + */ +static void uart_ft9001_irq_rx_disable(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + config->base->SCIFCR2 &= ~(SCIFCR2_RXFIE | SCIFCR2_RXFTOIE); +} + +/** + * @brief Check if TX is complete + */ +static int uart_ft9001_irq_tx_complete(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + return ((config->base->SCIFSR & SCIFSR_TEMPTY_MASK) && + (config->base->SCIFSR & SCIFSR_FTC_MASK)); +} + +/** + * @brief Check if RX data is ready + */ +static int uart_ft9001_irq_rx_ready(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + return ((config->base->SCIFSR & SCIFSR_RFTS_MASK) || + !(config->base->SCIFSR & SCIFSR_REMPTY_MASK)); +} + +/** + * @brief Enable error interrupt + */ +static void uart_ft9001_irq_err_enable(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + config->base->SCIFCR2 |= (SCIFCR2_RXORIE | SCIFCR2_RXFTOIE); +} + +/** + * @brief Disable error interrupt + */ +static void uart_ft9001_irq_err_disable(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + config->base->SCIFCR2 &= ~(SCIFCR2_RXORIE | SCIFCR2_RXFTOIE); +} + +/** + * @brief Check if interrupt is pending + */ +static int uart_ft9001_irq_is_pending(const struct device *dev) +{ + const struct uart_ft9001_config *config = DEV_CFG(dev); + + /* Check if TX or RX interrupts are pending */ + return ((!(config->base->SCIFSR & SCIFSR_TFULL_MASK) && + (config->base->SCIFCR2 & SCIFCR2_TXFIE)) || + (((config->base->SCIFSR & SCIFSR_RFTS_MASK) || + !(config->base->SCIFSR & SCIFSR_REMPTY_MASK)) && + (config->base->SCIFCR2 & SCIFCR2_RXFIE))); +} + +/** + * @brief Update interrupt status + */ +static int uart_ft9001_irq_update(const struct device *dev) +{ + return 1; +} + +/** + * @brief Set interrupt callback + */ +static void uart_ft9001_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct uart_ft9001_data *data = DEV_DATA(dev); + + data->cb = cb; + data->cb_data = cb_data; +} + +/** + * @brief UART interrupt service routine + */ +static void uart_ft9001_isr(const struct device *dev) +{ + struct uart_ft9001_data *data = DEV_DATA(dev); + + if (data->cb) { + data->cb(dev, data->cb_data); + } +} + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +/* UART driver API structure */ +static const struct uart_driver_api uart_ft9001_driver_api = { + .poll_in = uart_ft9001_poll_in, + .poll_out = uart_ft9001_poll_out, + .err_check = uart_ft9001_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = uart_ft9001_configure, + .config_get = uart_ft9001_config_get, +#endif +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_ft9001_fifo_fill, + .fifo_read = uart_ft9001_fifo_read, + .irq_tx_enable = uart_ft9001_irq_tx_enable, + .irq_tx_disable = uart_ft9001_irq_tx_disable, + .irq_tx_ready = uart_ft9001_irq_tx_ready, + .irq_rx_enable = uart_ft9001_irq_rx_enable, + .irq_rx_disable = uart_ft9001_irq_rx_disable, + .irq_tx_complete = uart_ft9001_irq_tx_complete, + .irq_rx_ready = uart_ft9001_irq_rx_ready, + .irq_err_enable = uart_ft9001_irq_err_enable, + .irq_err_disable = uart_ft9001_irq_err_disable, + .irq_is_pending = uart_ft9001_irq_is_pending, + .irq_update = uart_ft9001_irq_update, + .irq_callback_set = uart_ft9001_irq_callback_set, +#endif +}; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#define FOCALTECH_UART_IRQ_HANDLER(idx) \ + static void uart_ft9001_cfg_func_##idx(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), uart_ft9001_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + irq_enable(DT_INST_IRQN(idx)); \ + } +#define FOCALTECH_UART_IRQ_HANDLER_FUNC_INIT(idx) .irq_config_func = uart_ft9001_cfg_func_##idx, +#else +#define FOCALTECH_UART_IRQ_HANDLER(idx) +#define FOCALTECH_UART_IRQ_HANDLER_FUNC_INIT(idx) +#endif + +/** + * @brief Macro to define a FocalTech FT9001 UART device instance + */ +#define UART_FOCALTECH_FT9001_DEVICE(idx) \ + FOCALTECH_UART_IRQ_HANDLER(idx) \ + \ + static struct uart_ft9001_data uart_ft9001_data_##idx = { \ + .uart_cfg = \ + { \ + .baudrate = DT_INST_PROP(idx, current_speed), \ + .parity = UART_CFG_PARITY_NONE, \ + .stop_bits = UART_CFG_STOP_BITS_1, \ + .data_bits = UART_CFG_DATA_BITS_8, \ + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, \ + }, \ + }; \ + \ + static const struct uart_ft9001_config uart_ft9001_cfg_##idx = { \ + .base = (struct ft9001_uart_regs *)DT_INST_REG_ADDR(idx), \ + .clkid = DT_INST_CLOCKS_CELL(idx, id), \ + .reset = RESET_DT_SPEC_INST_GET(idx), \ + FOCALTECH_UART_IRQ_HANDLER_FUNC_INIT(idx)}; \ + \ + DEVICE_DT_INST_DEFINE(idx, uart_ft9001_init, NULL, &uart_ft9001_data_##idx, \ + &uart_ft9001_cfg_##idx, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ + (void *)&uart_ft9001_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(UART_FOCALTECH_FT9001_DEVICE); diff --git a/dts/arm/focaltech/ft9001/ft9001.dtsi b/dts/arm/focaltech/ft9001/ft9001.dtsi new file mode 100644 index 0000000000000..6ca59691c3265 --- /dev/null +++ b/dts/arm/focaltech/ft9001/ft9001.dtsi @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv7m-mpu"; + reg = <0xe000ed90 0x40>; + }; + }; + }; + + soc { + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(224)>; + }; + + sramd0: memory@1fff8000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x1fff8000 DT_SIZE_K(32)>; + zephyr,memory-region = "DTCM"; + }; + + pinctrl: pin-controller@40000000 { + compatible = "focaltech,ft9001-pinctrl"; + reg = <0x40000000 0x1000>; + clocks = <&cpm FOCALTECH_CLOCK_IO_CTRL>; + status = "disabled"; + }; + + ccm: ccm@40001000 { + compatible = "focaltech,ft9001-ccm"; + reg = <0x40001000 0x1000>; + status = "disabled"; + }; + + cpm: cpm@40004000 { + compatible = "focaltech,ft9001-cpm"; + reg = <0x40004000 0x1000>; + #clock-cells = <1>; + status = "okay"; + + rctl: reset-controller { + compatible = "focaltech,ft9001-cpm-rctl"; + #reset-cells = <1>; + status = "okay"; + }; + }; + + efm: flash-controller@40003000 { + compatible = "focaltech,ft9001-flash-controller"; + reg = <0x40003000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@10000000 { + compatible = "focaltech,ft9001-nv-flash", "soc-nv-flash"; + reg = <0x10000000 0x200000>; + write-block-size = <1>; + }; + }; + + usart2: usart@40014000 { + compatible = "focaltech,ft9001-usart"; + reg = <0x40014000 0x1000>; + interrupts = <33 0>; + clocks = <&cpm FOCALTECH_CLOCK_SCI2>; + resets = <&rctl FOCALTECH_RESET_SCI2>; + status = "disabled"; + }; + + usart3: usart@4001d000 { + compatible = "focaltech,ft9001-usart"; + reg = <0x4001d000 0x1000>; + interrupts = <61 0>; + clocks = <&cpm FOCALTECH_CLOCK_SCI3>; + resets = <&rctl FOCALTECH_RESET_SCI3>; + status = "disabled"; + }; + + eport0: eport@40019000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40019000 0x1000>; + interrupts = <41 0>, + <42 0>, + <43 0>, + <44 0>, + <45 0>, + <46 0>, + <47 0>, + <48 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT0>; + resets = <&rctl FOCALTECH_RESET_EPORT0>; + status = "disabled"; + }; + + eport1: eport@4001a000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x4001a000 0x1000>; + interrupts = <49 0>, + <50 0>, + <51 0>, + <52 0>, + <53 0>, + <54 0>, + <55 0>, + <56 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT1>; + resets = <&rctl FOCALTECH_RESET_EPORT1>; + status = "disabled"; + }; + + eport2: eport@40024000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40024000 0x1000>; + interrupts = <92 0>, + <93 0>, + <94 0>, + <95 0>, + <96 0>, + <97 0>, + <98 0>, + <99 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT2>; + resets = <&rctl FOCALTECH_RESET_EPORT2>; + status = "disabled"; + }; + + eport3: gpio@40025000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + reg = <0x40025000 0x1000>; + #gpio-cells = <2>; + interrupts = <100 0>, + <101 0>, + <102 0>, + <103 0>, + <104 0>, + <105 0>, + <106 0>, + <107 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT3>; + resets = <&rctl FOCALTECH_RESET_EPORT3>; + status = "disabled"; + }; + + eport4: eport@40026000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40026000 0x1000>; + interrupts = <108 0>, + <109 0>, + <110 0>, + <111 0>, + <112 0>, + <113 0>, + <114 0>, + <115 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT4>; + resets = <&rctl FOCALTECH_RESET_EPORT4>; + status = "disabled"; + }; + + eport5: eport@40027000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40027000 0x1000>; + interrupts = <116 0>, + <117 0>, + <118 0>, + <119 0>, + <120 0>, + <121 0>, + <122 0>, + <123 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT5>; + resets = <&rctl FOCALTECH_RESET_EPORT5>; + status = "disabled"; + }; + + eport6: eport@40028000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40028000 0x1000>; + interrupts = <124 0>, + <125 0>, + <126 0>, + <127 0>, + <128 0>, + <129 0>, + <130 0>, + <131 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT6>; + resets = <&rctl FOCALTECH_RESET_EPORT6>; + status = "disabled"; + }; + + eport7: eport@40029000 { + compatible = "focaltech,ft9001-eport", "focaltech,ft9001-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40029000 0x1000>; + interrupts = <132 0>, + <133 0>, + <134 0>, + <135 0>, + <136 0>, + <137 0>, + <138 0>, + <139 0>; + clocks = <&cpm FOCALTECH_CLOCK_EPORT7>; + resets = <&rctl FOCALTECH_RESET_EPORT7>; + status = "disabled"; + }; + + wdt0: watchdog@40005000 { + compatible = "focaltech,ft9001-wdt"; + reg = <0x40005000 0x1000>; + clocks = <&cpm FOCALTECH_CLOCK_WDT>; + resets = <&rctl FOCALTECH_RESET_WDT>; + status = "disabled"; + }; + + tc0: timer@40006000 { + compatible = "focaltech,ft9001-timer"; + reg = <0x40006000 0x1000>; + interrupts = <2 0>; + clocks = <&cpm FOCALTECH_CLOCK_TC>; + resets = <&rctl FOCALTECH_RESET_TC>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/bindings/clock/focaltech,ft9001-cpm.yaml b/dts/bindings/clock/focaltech,ft9001-cpm.yaml new file mode 100644 index 0000000000000..aed29a03393d1 --- /dev/null +++ b/dts/bindings/clock/focaltech,ft9001-cpm.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +description: | + FocalTech FT9001 Clock & Power Manager (CPM) specifiers use the packed IDs + defined in include/zephyr/dt-bindings/clock/focaltech_ft9001_clock.h + +compatible: "focaltech,ft9001-cpm" + +include: [clock-controller.yaml, base.yaml] + +properties: + "#clock-cells": + const: 1 + +clock-cells: + - id diff --git a/dts/bindings/reset/focaltech,ft9001-cpm-rctl.yaml b/dts/bindings/reset/focaltech,ft9001-cpm-rctl.yaml new file mode 100644 index 0000000000000..02a513c4b4f6b --- /dev/null +++ b/dts/bindings/reset/focaltech,ft9001-cpm-rctl.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +description: | + FocalTech FT9001 Reset controller (CPM subnode). + Reset specifiers use the packed IDs defined in + include/zephyr/dt-bindings/reset/focaltech_ft9001_reset.h + +compatible: "focaltech,ft9001-cpm-rctl" + +include: [reset-controller.yaml] + +properties: + "#reset-cells": + const: 1 + +reset-cells: + - id diff --git a/dts/bindings/serial/focaltech,ft9001-usart.yaml b/dts/bindings/serial/focaltech,ft9001-usart.yaml new file mode 100644 index 0000000000000..f81462aef914d --- /dev/null +++ b/dts/bindings/serial/focaltech,ft9001-usart.yaml @@ -0,0 +1,33 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +description: | + FocalTech FT9001 USART controller node + + The FT9001 USART (Universal Synchronous/Asynchronous Receiver/Transmitter) + controller provides serial communication capabilities with support for: + - Asynchronous UART communication + - Configurable baud rates + - Hardware flow control (optional) + - Interrupt-driven and polling operation modes + - 7, 8, or 9-bit data formats + - Even, odd, or no parity + - 1 or 2 stop bits + - FIFO buffering for improved performance + +compatible: "focaltech,ft9001-usart" + +include: [uart-controller.yaml, reset-device.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + resets: + required: true + + clocks: + required: true diff --git a/include/zephyr/dt-bindings/clock/focaltech_ft9001_clocks.h b/include/zephyr/dt-bindings/clock/focaltech_ft9001_clocks.h new file mode 100644 index 0000000000000..cb6f2d0b2f3cc --- /dev/null +++ b/include/zephyr/dt-bindings/clock/focaltech_ft9001_clocks.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_FOCALTECH_FT9001_CLOCKS_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_FOCALTECH_FT9001_CLOCKS_H_ + +/** + * @defgroup focaltech_clock_macros FocalTech Clock Configuration Macros + * @brief Macros for encoding clock register and bit information + * @{ + */ + +#define FOCALTECH_CLOCK_SHIFT 6U +#define FOCALTECH_CLOCK_MASK ((1U << FOCALTECH_CLOCK_SHIFT) - 1U) + +#define FOCALTECH_CLOCK_CONFIG(reg, bit) \ + (((FOCALTECH_##reg##_OFFSET) << FOCALTECH_CLOCK_SHIFT) | ((bit) & FOCALTECH_CLOCK_MASK)) + +/** @} */ + +/** + * @defgroup focaltech_clk_regs FocalTech Clock Power Module Registers + * @brief Clock Power Module Register offsets + * @{ + */ + +/** Multi Clock Gate Control Register */ +#define FOCALTECH_MULTICGCR_OFFSET 0x3CU +/** System Clock Gate Control Register */ +#define FOCALTECH_SYSCGCR_OFFSET 0x40U +/** AHB3 Clock Gate Control Register */ +#define FOCALTECH_AHB3CGCR_OFFSET 0x44U +/** Algorithm Clock Gate Control Register */ +#define FOCALTECH_ARITHCGCR_OFFSET 0x48U +/** IPS Clock Gate Control Register */ +#define FOCALTECH_IPSCGCR_OFFSET 0x4CU +/** EPORT Clock Gate Control Register */ +#define FOCALTECH_EPORTCGCR_OFFSET 0x84U + +/** @} */ + +/** + * @defgroup focaltech_clk_enables FocalTech Clock Enable/Disable Definitions + * @brief Clock enable/disable definitions for peripherals + * @{ + */ + +/** + * @defgroup focaltech_multicgcr_clocks MULTICGCR Clock Control + * @brief Multi Clock Gate Control Register peripherals + * @{ + */ + +/** OTP AHB clock */ +#define FOCALTECH_CLOCK_OTP_AHB FOCALTECH_CLOCK_CONFIG(MULTICGCR, 0U) +/** MCC clock */ +#define FOCALTECH_CLOCK_MCC FOCALTECH_CLOCK_CONFIG(MULTICGCR, 1U) +/** MCC address clock */ +#define FOCALTECH_CLOCK_MCCADR FOCALTECH_CLOCK_CONFIG(MULTICGCR, 2U) +/** ADC clock */ +#define FOCALTECH_CLOCK_ADC FOCALTECH_CLOCK_CONFIG(MULTICGCR, 3U) +/** MESH clock */ +#define FOCALTECH_CLOCK_MESH FOCALTECH_CLOCK_CONFIG(MULTICGCR, 4U) +/** TC clock */ +#define FOCALTECH_CLOCK_TC FOCALTECH_CLOCK_CONFIG(MULTICGCR, 5U) +/** Clock output */ +#define FOCALTECH_CLOCK_CLKOUT FOCALTECH_CLOCK_CONFIG(MULTICGCR, 6U) +/** Key controller clock */ +#define FOCALTECH_CLOCK_KEY_CTRL FOCALTECH_CLOCK_CONFIG(MULTICGCR, 7U) +/** CCM reset clock */ +#define FOCALTECH_CLOCK_CCM_RESET FOCALTECH_CLOCK_CONFIG(MULTICGCR, 8U) +/** OTP IPS clock */ +#define FOCALTECH_CLOCK_OTP_IPS FOCALTECH_CLOCK_CONFIG(MULTICGCR, 9U) +/** CPM IPS clock */ +#define FOCALTECH_CLOCK_CPM_IPS FOCALTECH_CLOCK_CONFIG(MULTICGCR, 10U) +/** Trace clock */ +#define FOCALTECH_CLOCK_TRACE FOCALTECH_CLOCK_CONFIG(MULTICGCR, 11U) +/** I2S master clock */ +#define FOCALTECH_CLOCK_I2S_M FOCALTECH_CLOCK_CONFIG(MULTICGCR, 12U) +/** I2S slave clock */ +#define FOCALTECH_CLOCK_I2S_S FOCALTECH_CLOCK_CONFIG(MULTICGCR, 13U) +/** CRC0 clock */ +#define FOCALTECH_CLOCK_CRC0 FOCALTECH_CLOCK_CONFIG(MULTICGCR, 14U) +/** CRC1 clock */ +#define FOCALTECH_CLOCK_CRC1 FOCALTECH_CLOCK_CONFIG(MULTICGCR, 15U) + +/** @} */ + +/** + * @defgroup focaltech_syscgcr_clocks SYSCGCR Clock Control + * @brief System Clock Gate Control Register peripherals + * @{ + */ + +/** SSI slave 1 clock */ +#define FOCALTECH_CLOCK_SSISLV1 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 0U) +/** DMAC1 clock */ +#define FOCALTECH_CLOCK_DMAC1 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 1U) +/** DMAC2 clock */ +#define FOCALTECH_CLOCK_DMAC2 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 2U) +/** AHB2 MUX clock */ +#define FOCALTECH_CLOCK_AHB2_MUX FOCALTECH_CLOCK_CONFIG(SYSCGCR, 3U) +/** PXLP1 AHB clock */ +#define FOCALTECH_CLOCK_PXLP1_AHB FOCALTECH_CLOCK_CONFIG(SYSCGCR, 10U) +/** PXLP2 AHB clock */ +#define FOCALTECH_CLOCK_PXLP2_AHB FOCALTECH_CLOCK_CONFIG(SYSCGCR, 11U) +/** SRAM data clock */ +#define FOCALTECH_CLOCK_SRAMD FOCALTECH_CLOCK_CONFIG(SYSCGCR, 12U) +/** SRAM0 clock */ +#define FOCALTECH_CLOCK_SRAM0 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 13U) +/** SRAM1 clock */ +#define FOCALTECH_CLOCK_SRAM1 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 14U) +/** SRAM2 clock */ +#define FOCALTECH_CLOCK_SRAM2 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 15U) +/** SRAM3/4 clock */ +#define FOCALTECH_CLOCK_SRAM3_4 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 16U) +/** SSI4 clock */ +#define FOCALTECH_CLOCK_SSI4 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 17U) +/** SSI5 clock */ +#define FOCALTECH_CLOCK_SSI5 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 18U) +/** SSI6 clock */ +#define FOCALTECH_CLOCK_SSI6 FOCALTECH_CLOCK_CONFIG(SYSCGCR, 19U) + +/** @} */ + +/** + * @defgroup focaltech_ahb3cgcr_clocks AHB3CGCR Clock Control + * @brief AHB3 Clock Gate Control Register peripherals + * @{ + */ + +/** ROM clock */ +#define FOCALTECH_CLOCK_ROM FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 0U) +/** ROM OTP MUX clock */ +#define FOCALTECH_CLOCK_ROM_OTP_MUX FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 1U) +/** AHB3 MUX clock */ +#define FOCALTECH_CLOCK_AHB3_MUX FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 2U) +/** USB controller clock */ +#define FOCALTECH_CLOCK_USBC FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 3U) +/** PXLP1 APB clock */ +#define FOCALTECH_CLOCK_PXLP1_APB FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 4U) +/** PXLP2 APB clock */ +#define FOCALTECH_CLOCK_PXLP2_APB FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 5U) +/** I2S1 clock */ +#define FOCALTECH_CLOCK_I2S1 FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 6U) +/** I2S2 clock */ +#define FOCALTECH_CLOCK_I2S2 FOCALTECH_CLOCK_CONFIG(AHB3CGCR, 7U) + +/** @} */ + +/** + * @defgroup focaltech_arithcgcr_clocks ARITHCGCR Clock Control + * @brief Algorithm Clock Gate Control Register peripherals + * @{ + */ + +/** AES clock */ +#define FOCALTECH_CLOCK_AES FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 1U) +/** SM4 clock */ +#define FOCALTECH_CLOCK_SM4 FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 2U) +/** RF AES SM4 clock */ +#define FOCALTECH_CLOCK_RF_AES_SM4 FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 4U) +/** Crypto clock */ +#define FOCALTECH_CLOCK_CRYPTO FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 5U) +/** SHA clock */ +#define FOCALTECH_CLOCK_SHA FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 6U) +/** EDMAC0 clock */ +#define FOCALTECH_CLOCK_EDMAC0 FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 7U) +/** DES clock */ +#define FOCALTECH_CLOCK_DES FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 8U) +/** ZUC clock */ +#define FOCALTECH_CLOCK_ZUC FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 9U) +/** AHB2MLB clock */ +#define FOCALTECH_CLOCK_AHB2MLB FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 10U) +/** AHB2IPS2 clock */ +#define FOCALTECH_CLOCK_AHB2IPS2 FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 11U) +/** TRNG clock */ +#define FOCALTECH_CLOCK_TRNG FOCALTECH_CLOCK_CONFIG(ARITHCGCR, 12U) + +/** @} */ + +/** + * @defgroup focaltech_ipscgcr_clocks IPSCGCR Clock Control + * @brief IPS Clock Gate Control Register peripherals + * @{ + */ + +/** IO controller clock */ +#define FOCALTECH_CLOCK_IO_CTRL FOCALTECH_CLOCK_CONFIG(IPSCGCR, 0U) +/** Watchdog timer clock */ +#define FOCALTECH_CLOCK_WDT FOCALTECH_CLOCK_CONFIG(IPSCGCR, 1U) +/** RTC clock */ +#define FOCALTECH_CLOCK_RTC FOCALTECH_CLOCK_CONFIG(IPSCGCR, 2U) +/** PIT1 clock */ +#define FOCALTECH_CLOCK_PIT1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 3U) +/** PIT2 clock */ +#define FOCALTECH_CLOCK_PIT2 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 4U) +/** USI1 clock */ +#define FOCALTECH_CLOCK_USI1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 5U) +/** EDMAC1 clock */ +#define FOCALTECH_CLOCK_EDMAC1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 6U) +/** SPI1 clock */ +#define FOCALTECH_CLOCK_SPI1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 7U) +/** SPI2 clock */ +#define FOCALTECH_CLOCK_SPI2 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 8U) +/** SPI3 clock */ +#define FOCALTECH_CLOCK_SPI3 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 9U) +/** SCI1 clock */ +#define FOCALTECH_CLOCK_SCI1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 10U) +/** SCI2 clock */ +#define FOCALTECH_CLOCK_SCI2 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 11U) +/** USI2 clock */ +#define FOCALTECH_CLOCK_USI2 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 12U) +/** CAN1 clock */ +#define FOCALTECH_CLOCK_CAN1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 13U) +/** I2C1 clock */ +#define FOCALTECH_CLOCK_I2C1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 14U) +/** PWM0 clock */ +#define FOCALTECH_CLOCK_PWM0 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 15U) +/** I2C2 clock */ +#define FOCALTECH_CLOCK_I2C2 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 16U) +/** CAN2 clock */ +#define FOCALTECH_CLOCK_CAN2 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 17U) +/** SCI3 clock */ +#define FOCALTECH_CLOCK_SCI3 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 18U) +/** QADC clock */ +#define FOCALTECH_CLOCK_QADC FOCALTECH_CLOCK_CONFIG(IPSCGCR, 20U) +/** DAC clock */ +#define FOCALTECH_CLOCK_DAC FOCALTECH_CLOCK_CONFIG(IPSCGCR, 21U) +/** MCC IPS clock */ +#define FOCALTECH_CLOCK_MCC_IPS FOCALTECH_CLOCK_CONFIG(IPSCGCR, 22U) +/** PWMT1 clock */ +#define FOCALTECH_CLOCK_PWMT1 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 23U) +/** LD clock */ +#define FOCALTECH_CLOCK_LD FOCALTECH_CLOCK_CONFIG(IPSCGCR, 24U) +/** PWMT2 clock */ +#define FOCALTECH_CLOCK_PWMT2 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 25U) +/** PGD clock */ +#define FOCALTECH_CLOCK_PGD FOCALTECH_CLOCK_CONFIG(IPSCGCR, 26U) +/** Security detector clock */ +#define FOCALTECH_CLOCK_SEC_DET FOCALTECH_CLOCK_CONFIG(IPSCGCR, 27U) +/** PCI clock */ +#define FOCALTECH_CLOCK_PCI FOCALTECH_CLOCK_CONFIG(IPSCGCR, 28U) +/** PMU RTC clock */ +#define FOCALTECH_CLOCK_PMURTC FOCALTECH_CLOCK_CONFIG(IPSCGCR, 29U) +/** AHB2IPS clock */ +#define FOCALTECH_CLOCK_AHB2IPS FOCALTECH_CLOCK_CONFIG(IPSCGCR, 30U) +/** PWMT3 clock */ +#define FOCALTECH_CLOCK_PWMT3 FOCALTECH_CLOCK_CONFIG(IPSCGCR, 31U) + +/** @} */ + +/** + * @defgroup focaltech_eportcgcr_clocks EPORTCGCR Clock Control + * @brief EPORT Clock Gate Control Register peripherals + * @{ + */ + +/** EPORT0 clock */ +#define FOCALTECH_CLOCK_EPORT0 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 0U) +/** EPORT1 clock */ +#define FOCALTECH_CLOCK_EPORT1 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 1U) +/** EPORT2 clock */ +#define FOCALTECH_CLOCK_EPORT2 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 2U) +/** EPORT3 clock */ +#define FOCALTECH_CLOCK_EPORT3 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 3U) +/** EPORT4 clock */ +#define FOCALTECH_CLOCK_EPORT4 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 4U) +/** EPORT5 clock */ +#define FOCALTECH_CLOCK_EPORT5 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 5U) +/** EPORT6 clock */ +#define FOCALTECH_CLOCK_EPORT6 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 6U) +/** EPORT7 clock */ +#define FOCALTECH_CLOCK_EPORT7 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 7U) +/** ACMP1 clock */ +#define FOCALTECH_CLOCK_ACMP1 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 8U) +/** ACMP2 clock */ +#define FOCALTECH_CLOCK_ACMP2 FOCALTECH_CLOCK_CONFIG(EPORTCGCR, 9U) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_FOCALTECH_FT9001_CLOCKS_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/focaltech_ft9001_pinctrl.h b/include/zephyr/dt-bindings/pinctrl/focaltech_ft9001_pinctrl.h new file mode 100644 index 0000000000000..09bb6d1649d7f --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/focaltech_ft9001_pinctrl.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_FOCALTECH_FT9001_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_FOCALTECH_FT9001_PINCTRL_H_ + +/** + * @defgroup focaltech_pinctrl_macros FocalTech IOCTRL Pin Control + * @brief Pin control macros for FocalTech FT9001 SoC + * @{ + */ + +/* + * Pinmux encoding: + * bit[0:0] - VALUE (0 = default, 1 = alternate) + * bit[5:1] - BIT position in register + * bit[25:6] - Register offset + */ +#define FOCALTECH_IOCTRL_BASE 0x40000000U + +#define FOCALTECH_PINCTRL_VALUE_POS 0U +#define FOCALTECH_PINCTRL_BIT_POS 1U +#define FOCALTECH_PINCTRL_REG_POS 6U + +#define FOCALTECH_PINCTRL_VALUE_MASK 0x1U +#define FOCALTECH_PINCTRL_BIT_MASK 0x1FU +#define FOCALTECH_PINCTRL_REG_MASK 0xFFFFFU + +#define FOCALTECH_PINMUX(reg, bit, value) \ + (((reg) << FOCALTECH_PINCTRL_REG_POS) | ((bit) << FOCALTECH_PINCTRL_BIT_POS) | \ + ((value) << FOCALTECH_PINCTRL_VALUE_POS)) + +#define FOCALTECH_PINCTRL_REG_GET(pinmux) \ + ((((pinmux) >> FOCALTECH_PINCTRL_REG_POS) & FOCALTECH_PINCTRL_REG_MASK) | \ + FOCALTECH_IOCTRL_BASE) + +#define FOCALTECH_PINCTRL_BIT_GET(pinmux) \ + (((pinmux) >> FOCALTECH_PINCTRL_BIT_POS) & FOCALTECH_PINCTRL_BIT_MASK) + +#define FOCALTECH_PINCTRL_VALUE_GET(pinmux) \ + (((pinmux) >> FOCALTECH_PINCTRL_VALUE_POS) & FOCALTECH_PINCTRL_VALUE_MASK) + +/** + * @defgroup focaltech_pinctrl_regs IOCTRL Register Offsets + * @brief IOCTRL register offsets + * @{ + */ + +#define FOCALTECH_IOCTRL_SPICR_OFFSET 0x00000U +#define FOCALTECH_IOCTRL_I2CCR_OFFSET 0x00008U +#define FOCALTECH_IOCTRL_SCICR_OFFSET 0x0000CU +#define FOCALTECH_IOCTRL_SWAPCR_OFFSET 0x0001CU +#define FOCALTECH_IOCTRL_CLKRSTCR_OFFSET 0x00044U +#define FOCALTECH_IOCTRL_EPORT2CR_OFFSET 0x00054U +#define FOCALTECH_IOCTRL_EPORT3CR_OFFSET 0x00058U +#define FOCALTECH_IOCTRL_EPORT4CR_OFFSET 0x0005CU +#define FOCALTECH_IOCTRL_EPORT5CR_OFFSET 0x00060U +#define FOCALTECH_IOCTRL_EPORT6CR_OFFSET 0x00064U +#define FOCALTECH_IOCTRL_EPORT7CR_OFFSET 0x00068U +#define FOCALTECH_IOCTRL_SWAPCR2_OFFSET 0x0006CU +#define FOCALTECH_IOCTRL_SWAPCR3_OFFSET 0x00070U +#define FOCALTECH_IOCTRL_SWAPCR4_OFFSET 0x00074U +#define FOCALTECH_IOCTRL_SWAPCR5_OFFSET 0x00078U + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_FOCALTECH_FT9001_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/reset/focaltech_ft9001_reset.h b/include/zephyr/dt-bindings/reset/focaltech_ft9001_reset.h new file mode 100644 index 0000000000000..bc1c90b2d821b --- /dev/null +++ b/include/zephyr/dt-bindings/reset/focaltech_ft9001_reset.h @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_FOCALTECH_FT9001_RESET_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_FOCALTECH_FT9001_RESET_H_ + +/** + * @defgroup focaltech_reset_macros FocalTech Reset Configuration Macros + * @brief Macros for encoding reset register and bit information + * @{ + */ + +#define FOCALTECH_RESET_SHIFT 6U +#define FOCALTECH_RESET_MASK ((1U << FOCALTECH_RESET_SHIFT) - 1U) + +#define FOCALTECH_RESET_CONFIG(reg, bit) \ + (((FOCALTECH_##reg##_OFFSET) << FOCALTECH_RESET_SHIFT) | ((bit) & FOCALTECH_RESET_MASK)) + +/** @} */ + +/** + * @defgroup focaltech_reset_regs FocalTech Reset Control Module Registers + * @brief Reset Control Module Register offsets + * @{ + */ + +/** EPORT Reset Control Register */ +#define FOCALTECH_EPORTRSTCR_OFFSET 0x88U +/** Multi Reset Control Register */ +#define FOCALTECH_MULTIRSTCR_OFFSET 0xACU +/** System Reset Control Register */ +#define FOCALTECH_SYSRSTCR_OFFSET 0xB0U +/** AHB3 Reset Control Register */ +#define FOCALTECH_AHB3RSTCR_OFFSET 0xB4U +/** Algorithm Reset Control Register */ +#define FOCALTECH_ARITHRSTCR_OFFSET 0xB8U +/** IPS Reset Control Register */ +#define FOCALTECH_IPSRSTCR_OFFSET 0xBCU + +/** @} */ + +/** + * @defgroup focaltech_reset_enables FocalTech Reset Enable/Disable Definitions + * @brief Reset enable/disable definitions for peripherals + * @{ + */ + +/** + * @defgroup focaltech_eportrstr_resets EPORTRSTR Reset Control + * @brief EPORT Reset Control Register peripherals + * @{ + */ + +/** EPORT0 reset */ +#define FOCALTECH_RESET_EPORT0 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 0U) +/** EPORT1 reset */ +#define FOCALTECH_RESET_EPORT1 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 1U) +/** EPORT2 reset */ +#define FOCALTECH_RESET_EPORT2 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 2U) +/** EPORT3 reset */ +#define FOCALTECH_RESET_EPORT3 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 3U) +/** EPORT4 reset */ +#define FOCALTECH_RESET_EPORT4 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 4U) +/** EPORT5 reset */ +#define FOCALTECH_RESET_EPORT5 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 5U) +/** EPORT6 reset */ +#define FOCALTECH_RESET_EPORT6 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 6U) +/** EPORT7 reset */ +#define FOCALTECH_RESET_EPORT7 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 7U) +/** ACMP1 reset */ +#define FOCALTECH_RESET_ACMP1 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 8U) +/** ACMP2 reset */ +#define FOCALTECH_RESET_ACMP2 FOCALTECH_RESET_CONFIG(EPORTRSTCR, 9U) + +/** @} */ + +/** + * @defgroup focaltech_multirstcr_resets MULTIRSTCR Reset Control + * @brief Multi Reset Control Register peripherals + * @{ + */ + +/** OTP AHB reset */ +#define FOCALTECH_RESET_OTP_AHB FOCALTECH_RESET_CONFIG(MULTIRSTCR, 0U) +/** MCC reset */ +#define FOCALTECH_RESET_MCC FOCALTECH_RESET_CONFIG(MULTIRSTCR, 1U) +/** MCC address reset */ +#define FOCALTECH_RESET_MCCADR FOCALTECH_RESET_CONFIG(MULTIRSTCR, 2U) +/** ADC reset */ +#define FOCALTECH_RESET_ADC FOCALTECH_RESET_CONFIG(MULTIRSTCR, 3U) +/** MESH reset */ +#define FOCALTECH_RESET_MESH FOCALTECH_RESET_CONFIG(MULTIRSTCR, 4U) +/** TC reset */ +#define FOCALTECH_RESET_TC FOCALTECH_RESET_CONFIG(MULTIRSTCR, 5U) +/** Clock output reset */ +#define FOCALTECH_RESET_CLKOUT FOCALTECH_RESET_CONFIG(MULTIRSTCR, 6U) +/** Key controller reset */ +#define FOCALTECH_RESET_KEY_CTRL FOCALTECH_RESET_CONFIG(MULTIRSTCR, 7U) +/** CCM reset */ +#define FOCALTECH_RESET_CCM_RESET FOCALTECH_RESET_CONFIG(MULTIRSTCR, 8U) +/** OTP IPS reset */ +#define FOCALTECH_RESET_OTP_IPS FOCALTECH_RESET_CONFIG(MULTIRSTCR, 9U) +/** CPM IPS reset */ +#define FOCALTECH_RESET_CPM_IPS FOCALTECH_RESET_CONFIG(MULTIRSTCR, 10U) +/** Trace reset */ +#define FOCALTECH_RESET_TRACE FOCALTECH_RESET_CONFIG(MULTIRSTCR, 11U) +/** I2S master reset */ +#define FOCALTECH_RESET_I2S_M FOCALTECH_RESET_CONFIG(MULTIRSTCR, 12U) +/** I2S slave reset */ +#define FOCALTECH_RESET_I2S_S FOCALTECH_RESET_CONFIG(MULTIRSTCR, 13U) +/** CRC0 reset */ +#define FOCALTECH_RESET_CRC0 FOCALTECH_RESET_CONFIG(MULTIRSTCR, 14U) +/** CRC1 reset */ +#define FOCALTECH_RESET_CRC1 FOCALTECH_RESET_CONFIG(MULTIRSTCR, 15U) + +/** @} */ + +/** + * @defgroup focaltech_sysrstcr_resets SYSRSTCR Reset Control + * @brief System Reset Control Register peripherals + * @{ + */ + +/** SSI slave 1 reset */ +#define FOCALTECH_RESET_SSISLV1 FOCALTECH_RESET_CONFIG(SYSRSTCR, 0U) +/** DMAC1 reset */ +#define FOCALTECH_RESET_DMAC1 FOCALTECH_RESET_CONFIG(SYSRSTCR, 1U) +/** DMAC2 reset */ +#define FOCALTECH_RESET_DMAC2 FOCALTECH_RESET_CONFIG(SYSRSTCR, 2U) +/** AHB2 MUX reset */ +#define FOCALTECH_RESET_AHB2_MUX FOCALTECH_RESET_CONFIG(SYSRSTCR, 3U) +/** PXLP1 AHB reset */ +#define FOCALTECH_RESET_PXLP1_AHB FOCALTECH_RESET_CONFIG(SYSRSTCR, 10U) +/** PXLP2 AHB reset */ +#define FOCALTECH_RESET_PXLP2_AHB FOCALTECH_RESET_CONFIG(SYSRSTCR, 11U) +/** SRAM data reset */ +#define FOCALTECH_RESET_SRAMD FOCALTECH_RESET_CONFIG(SYSRSTCR, 12U) +/** SRAM0 reset */ +#define FOCALTECH_RESET_SRAM0 FOCALTECH_RESET_CONFIG(SYSRSTCR, 13U) +/** SRAM1 reset */ +#define FOCALTECH_RESET_SRAM1 FOCALTECH_RESET_CONFIG(SYSRSTCR, 14U) +/** SRAM2 reset */ +#define FOCALTECH_RESET_SRAM2 FOCALTECH_RESET_CONFIG(SYSRSTCR, 15U) +/** SRAM3/4 reset */ +#define FOCALTECH_RESET_SRAM3_4 FOCALTECH_RESET_CONFIG(SYSRSTCR, 16U) +/** SSI4 reset */ +#define FOCALTECH_RESET_SSI4 FOCALTECH_RESET_CONFIG(SYSRSTCR, 17U) +/** SSI5 reset */ +#define FOCALTECH_RESET_SSI5 FOCALTECH_RESET_CONFIG(SYSRSTCR, 18U) +/** SSI6 reset */ +#define FOCALTECH_RESET_SSI6 FOCALTECH_RESET_CONFIG(SYSRSTCR, 19U) + +/** @} */ + +/** + * @defgroup focaltech_ahb3rstcr_resets AHB3RSTCR Reset Control + * @brief AHB3 Reset Control Register peripherals + * @{ + */ + +/** ROM reset */ +#define FOCALTECH_RESET_ROM FOCALTECH_RESET_CONFIG(AHB3RSTCR, 0U) +/** ROM OTP MUX reset */ +#define FOCALTECH_RESET_ROM_OTP_MUX FOCALTECH_RESET_CONFIG(AHB3RSTCR, 1U) +/** AHB3 MUX reset */ +#define FOCALTECH_RESET_AHB3_MUX FOCALTECH_RESET_CONFIG(AHB3RSTCR, 2U) +/** USB controller reset */ +#define FOCALTECH_RESET_USBC FOCALTECH_RESET_CONFIG(AHB3RSTCR, 3U) +/** PXLP1 APB reset */ +#define FOCALTECH_RESET_PXLP1_APB FOCALTECH_RESET_CONFIG(AHB3RSTCR, 4U) +/** PXLP2 APB reset */ +#define FOCALTECH_RESET_PXLP2_APB FOCALTECH_RESET_CONFIG(AHB3RSTCR, 5U) +/** I2S1 reset */ +#define FOCALTECH_RESET_I2S1 FOCALTECH_RESET_CONFIG(AHB3RSTCR, 6U) +/** I2S2 reset */ +#define FOCALTECH_RESET_I2S2 FOCALTECH_RESET_CONFIG(AHB3RSTCR, 7U) + +/** @} */ + +/** + * @defgroup focaltech_arithrstcr_resets ARITHRSTCR Reset Control + * @brief Algorithm Reset Control Register peripherals + * @{ + */ + +/** AES reset */ +#define FOCALTECH_RESET_AES FOCALTECH_RESET_CONFIG(ARITHRSTCR, 1U) +/** SM4 reset */ +#define FOCALTECH_RESET_SM4 FOCALTECH_RESET_CONFIG(ARITHRSTCR, 2U) +/** RF AES SM4 reset */ +#define FOCALTECH_RESET_RF_AES_SM4 FOCALTECH_RESET_CONFIG(ARITHRSTCR, 4U) +/** Crypto reset */ +#define FOCALTECH_RESET_CRYPTO FOCALTECH_RESET_CONFIG(ARITHRSTCR, 5U) +/** SHA reset */ +#define FOCALTECH_RESET_SHA FOCALTECH_RESET_CONFIG(ARITHRSTCR, 6U) +/** EDMAC0 reset */ +#define FOCALTECH_RESET_EDMAC0 FOCALTECH_RESET_CONFIG(ARITHRSTCR, 7U) +/** DES reset */ +#define FOCALTECH_RESET_DES FOCALTECH_RESET_CONFIG(ARITHRSTCR, 8U) +/** ZUC reset */ +#define FOCALTECH_RESET_ZUC FOCALTECH_RESET_CONFIG(ARITHRSTCR, 9U) +/** AHB2MLB reset */ +#define FOCALTECH_RESET_AHB2MLB FOCALTECH_RESET_CONFIG(ARITHRSTCR, 10U) +/** AHB2IPS2 reset */ +#define FOCALTECH_RESET_AHB2IPS2 FOCALTECH_RESET_CONFIG(ARITHRSTCR, 11U) +/** TRNG reset */ +#define FOCALTECH_RESET_TRNG FOCALTECH_RESET_CONFIG(ARITHRSTCR, 12U) + +/** @} */ + +/** + * @defgroup focaltech_ipsrstcr_resets IPSRSTCR Reset Control + * @brief IPS Reset Control Register peripherals + * @{ + */ + +/** IO controller reset */ +#define FOCALTECH_RESET_IO_CTRL FOCALTECH_RESET_CONFIG(IPSRSTCR, 0U) +/** Watchdog timer reset */ +#define FOCALTECH_RESET_WDT FOCALTECH_RESET_CONFIG(IPSRSTCR, 1U) +/** RTC reset */ +#define FOCALTECH_RESET_RTC FOCALTECH_RESET_CONFIG(IPSRSTCR, 2U) +/** PIT1 reset */ +#define FOCALTECH_RESET_PIT1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 3U) +/** PIT2 reset */ +#define FOCALTECH_RESET_PIT2 FOCALTECH_RESET_CONFIG(IPSRSTCR, 4U) +/** USI1 reset */ +#define FOCALTECH_RESET_USI1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 5U) +/** EDMAC1 reset */ +#define FOCALTECH_RESET_EDMAC1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 6U) +/** SPI1 reset */ +#define FOCALTECH_RESET_SPI1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 7U) +/** SPI2 reset */ +#define FOCALTECH_RESET_SPI2 FOCALTECH_RESET_CONFIG(IPSRSTCR, 8U) +/** SPI3 reset */ +#define FOCALTECH_RESET_SPI3 FOCALTECH_RESET_CONFIG(IPSRSTCR, 9U) +/** SCI1 reset */ +#define FOCALTECH_RESET_SCI1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 10U) +/** SCI2 reset */ +#define FOCALTECH_RESET_SCI2 FOCALTECH_RESET_CONFIG(IPSRSTCR, 11U) +/** USI2 reset */ +#define FOCALTECH_RESET_USI2 FOCALTECH_RESET_CONFIG(IPSRSTCR, 12U) +/** CAN1 reset */ +#define FOCALTECH_RESET_CAN1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 13U) +/** I2C1 reset */ +#define FOCALTECH_RESET_I2C1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 14U) +/** PWM0 reset */ +#define FOCALTECH_RESET_PWM0 FOCALTECH_RESET_CONFIG(IPSRSTCR, 15U) +/** I2C2 reset */ +#define FOCALTECH_RESET_I2C2 FOCALTECH_RESET_CONFIG(IPSRSTCR, 16U) +/** CAN2 reset */ +#define FOCALTECH_RESET_CAN2 FOCALTECH_RESET_CONFIG(IPSRSTCR, 17U) +/** SCI3 reset */ +#define FOCALTECH_RESET_SCI3 FOCALTECH_RESET_CONFIG(IPSRSTCR, 18U) +/** QADC reset */ +#define FOCALTECH_RESET_QADC FOCALTECH_RESET_CONFIG(IPSRSTCR, 20U) +/** DAC reset */ +#define FOCALTECH_RESET_DAC FOCALTECH_RESET_CONFIG(IPSRSTCR, 21U) +/** MCC IPS reset */ +#define FOCALTECH_RESET_MCC_IPS FOCALTECH_RESET_CONFIG(IPSRSTCR, 22U) +/** PWMT1 reset */ +#define FOCALTECH_RESET_PWMT1 FOCALTECH_RESET_CONFIG(IPSRSTCR, 23U) +/** LD reset */ +#define FOCALTECH_RESET_LD FOCALTECH_RESET_CONFIG(IPSRSTCR, 24U) +/** PWMT2 reset */ +#define FOCALTECH_RESET_PWMT2 FOCALTECH_RESET_CONFIG(IPSRSTCR, 25U) +/** PGD reset */ +#define FOCALTECH_RESET_PGD FOCALTECH_RESET_CONFIG(IPSRSTCR, 26U) +/** Security detector reset */ +#define FOCALTECH_RESET_SEC_DET FOCALTECH_RESET_CONFIG(IPSRSTCR, 27U) +/** PCI reset */ +#define FOCALTECH_RESET_PCI FOCALTECH_RESET_CONFIG(IPSRSTCR, 28U) +/** PMU RTC reset */ +#define FOCALTECH_RESET_PMURTC FOCALTECH_RESET_CONFIG(IPSRSTCR, 29U) +/** AHB2IPS reset */ +#define FOCALTECH_RESET_AHB2IPS FOCALTECH_RESET_CONFIG(IPSRSTCR, 30U) +/** PWMT3 reset */ +#define FOCALTECH_RESET_PWMT3 FOCALTECH_RESET_CONFIG(IPSRSTCR, 31U) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_FOCALTECH_FT9001_RESET_H_ */ diff --git a/soc/focaltech/CMakeLists.txt b/soc/focaltech/CMakeLists.txt new file mode 100644 index 0000000000000..e06b1c03c7761 --- /dev/null +++ b/soc/focaltech/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(ft9001) diff --git a/soc/focaltech/Kconfig b/soc/focaltech/Kconfig new file mode 100644 index 0000000000000..6686b285bd69f --- /dev/null +++ b/soc/focaltech/Kconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +rsource "*/Kconfig" diff --git a/soc/focaltech/Kconfig.defconfig b/soc/focaltech/Kconfig.defconfig new file mode 100644 index 0000000000000..cebbc042e2155 --- /dev/null +++ b/soc/focaltech/Kconfig.defconfig @@ -0,0 +1,4 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +rsource "*/Kconfig.defconfig" diff --git a/soc/focaltech/Kconfig.soc b/soc/focaltech/Kconfig.soc new file mode 100644 index 0000000000000..8efd3a16508ae --- /dev/null +++ b/soc/focaltech/Kconfig.soc @@ -0,0 +1,4 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +rsource "*/Kconfig.soc" diff --git a/soc/focaltech/ft9001/CMakeLists.txt b/soc/focaltech/ft9001/CMakeLists.txt new file mode 100644 index 0000000000000..683ef188e95ac --- /dev/null +++ b/soc/focaltech/ft9001/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + soc.c + ft9001_xip.c +) + +zephyr_include_directories(.) + +zephyr_code_relocate(FILES ft9001_xip.c LOCATION RAM) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/focaltech/ft9001/Kconfig b/soc/focaltech/ft9001/Kconfig new file mode 100644 index 0000000000000..1c8ba2b1fadd5 --- /dev/null +++ b/soc/focaltech/ft9001/Kconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FT9001 + select ARM + select CPU_CORTEX_M4 + select CPU_HAS_FPU + select CPU_HAS_ARM_MPU + select CPU_CORTEX_M_HAS_SYSTICK + select CPU_CORTEX_M_HAS_VTOR + select SOC_EARLY_INIT_HOOK + select BUILD_OUTPUT_HEX + select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE diff --git a/soc/focaltech/ft9001/Kconfig.defconfig b/soc/focaltech/ft9001/Kconfig.defconfig new file mode 100644 index 0000000000000..c699e69881fef --- /dev/null +++ b/soc/focaltech/ft9001/Kconfig.defconfig @@ -0,0 +1,21 @@ +# Copyright (c) 2025, FocalTech Systems CO.,Ltd +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FT9001 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) + +config NUM_IRQS + default 140 + +config RESET + default y + +config CLOCK_CONTROL + default y + +config XIP + default y + +endif # SOC_FT9001 diff --git a/soc/focaltech/ft9001/Kconfig.soc b/soc/focaltech/ft9001/Kconfig.soc new file mode 100644 index 0000000000000..e2701dc8e4b02 --- /dev/null +++ b/soc/focaltech/ft9001/Kconfig.soc @@ -0,0 +1,10 @@ +# Copyright (c) 2025, FocalTech Systems Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FT9001 + bool + help + Build for the FocalTech FT9001 MCU (ARM Cortex-M4F). + +config SOC + default "ft9001" if SOC_FT9001 diff --git a/soc/focaltech/ft9001/ft9001_xip.c b/soc/focaltech/ft9001/ft9001_xip.c new file mode 100644 index 0000000000000..0c7a319d41c18 --- /dev/null +++ b/soc/focaltech/ft9001/ft9001_xip.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(ft9001_xip, CONFIG_LOG_DEFAULT_LEVEL); + +/* addresses & masks (SoC-specific) */ +#define FT9001_CLK_CFG_ADDR 0x40004008u +#define FT9001_CLK_UPD_ADDR 0x40004018u +#define FT9001_CLK_UPD_GO_MASK 0x02u + +#define FT9001_GPIO_SDA_IN_ADDR 0x40017009u +#define FT9001_GPIO_SDA_LOW_MASK 0x02u + +#define FT9001_DCACHE_BASE 0x40055000u +#define FT9001_DCACHE_EN_MASK 0x01u +#define FT9001_DCACHE_CPEA_OFF 0x180u +#define FT9001_DCACHE_CPES_OFF 0x184u +#define FT9001_DCACHE_CPES_GO_MASK 0x01u + +#define FT9001_FLASH_FIRST_SECTOR 0x10000000u +#define FT9001_FLASH_CMD_SECTOR_ERASE 0x20u +#define FT9001_ROM_FLASH_ERASE_ADDR (0x0400747Au | 1u) + +/** + * @brief Short delay using NOPs. + * + * This is a simple delay function that uses NOP instructions to create a + * short delay. The number of NOPs can be adjusted based on the required delay. + */ +static inline void short_delay_nops(int n) +{ + for (int i = 0; i < n; i++) { + __NOP(); + } +} + +/** + * @brief Copy the .ramfunc section from flash to SRAM. + * + * Zephyr normally copies RAM-resident functions during boot, but this helper + * can be invoked early in SoC init if a manual move is required. + */ +void copy_ramfunc(void) +{ + size_t size = (size_t)(__ramfunc_end - __ramfunc_start); + + if (size == 0) { + return; + } + + memcpy((void *)__ramfunc_start, (const void *)__ramfunc_load_start, size); + + /* Small delay to ensure data is visible before execution */ + short_delay_nops(8); +} + +/** + * @brief Switch XIP clock divider. + * + * @param clk_div Lower four bits are the divider value. + */ +__ramfunc void xip_clock_switch(uint32_t clk_div) +{ + uint32_t val = sys_read32(FT9001_CLK_CFG_ADDR); + + val = (val & 0xFFFFFFF0u) | (clk_div & 0x0Fu); + sys_write32(val, FT9001_CLK_CFG_ADDR); + + sys_write32(sys_read32(FT9001_CLK_UPD_ADDR) | FT9001_CLK_UPD_GO_MASK, FT9001_CLK_UPD_ADDR); + + short_delay_nops(8); +} + +/** + * @brief Check I2C_SDA and, if low, erase the first flash sector then jump + * back to ROM boot code. + * + * This routine must run from RAM (.ramfunc) because it erases the very first + * sector at 0x1000 0000 while XIP is active. + */ +__ramfunc void xip_return_to_boot(void) +{ + /* Quick exit if SDA is high, nothing to do */ + if (sys_read8(FT9001_GPIO_SDA_IN_ADDR) & FT9001_GPIO_SDA_LOW_MASK) { + return; + } + + /* SDA low: start fallback sequence */ + uint32_t primask_backup = __get_PRIMASK(); + + __disable_irq(); + + /* 1. Invalidate D-Cache */ + if (sys_read32(FT9001_DCACHE_BASE) & FT9001_DCACHE_EN_MASK) { + sys_write32(0x10000000u, FT9001_DCACHE_BASE + FT9001_DCACHE_CPEA_OFF); + sys_write32(0x10001001u, FT9001_DCACHE_BASE + FT9001_DCACHE_CPES_OFF); + while (sys_read32(FT9001_DCACHE_BASE + FT9001_DCACHE_CPES_OFF) & + FT9001_DCACHE_CPES_GO_MASK) { + /* busy-wait */ + } + } + + /* 2. Build erase descriptor */ + struct flash_cfg { + uint8_t ssi_id; + uint8_t sys_div; + uint8_t is_qpi_mode; + uint16_t stand_baudr; + uint16_t quad_baudr; + uint32_t rx_sample_delay; + uint8_t cmd; + uint32_t value; + uint8_t is_mask_interrupt; + uint8_t program_mode; + uint32_t addr; + uint16_t len; + uint32_t buf; + uint32_t delay; + uint32_t timeout; + }; + + struct flash_cfg cfg = { + .ssi_id = 1, + .sys_div = 2, + .is_qpi_mode = 0, + .stand_baudr = 0x0002, + .quad_baudr = 0x0002, + .rx_sample_delay = 1, + .cmd = FT9001_FLASH_CMD_SECTOR_ERASE, + .value = 0, + .is_mask_interrupt = 1, + .program_mode = 0, + .addr = FT9001_FLASH_FIRST_SECTOR, + .len = 0, + .buf = 0, + .delay = 10, + .timeout = 0xFFFFFFFFu, + }; + + /* 3. Call ROM helper (Thumb) */ + uintptr_t entry = FT9001_ROM_FLASH_ERASE_ADDR; + typedef uint8_t (*flash_erase_fn_t)(struct flash_cfg *); + flash_erase_fn_t flash_erase = (flash_erase_fn_t)entry; + + (void)flash_erase(&cfg); + + /* Halt and wait for reset */ + __set_PRIMASK(primask_backup); + while (true) { + barrier_dsync_fence_full(); + } +} diff --git a/soc/focaltech/ft9001/pinctrl_soc.h b/soc/focaltech/ft9001/pinctrl_soc.h new file mode 100644 index 0000000000000..1d02d80250b25 --- /dev/null +++ b/soc/focaltech/ft9001/pinctrl_soc.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FocalTech FT9001 SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_ARM_FOCALTECH_FT9001_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_FOCALTECH_FT9001_PINCTRL_SOC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +/** @brief Type for FT9001 pin configuration. + * + * Bits: + * - 0-25: FT9001_PINMUX bit field. + * - 26-31: Pin configuration bit field (@ref FT9001_PINCFG). + */ +typedef uint32_t pinctrl_soc_pin_t; + +/** + * @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) | \ + ((FT9001_PUPD_PULLUP * DT_PROP(node_id, bias_pull_up)) << FT9001_PUPD_POS) | \ + ((FT9001_PUPD_PULLDOWN * DT_PROP(node_id, bias_pull_down)) << FT9001_PUPD_POS) | \ + ((FT9001_OTYPE_OD * DT_PROP(node_id, drive_open_drain)) << FT9001_OTYPE_POS) | \ + (DT_ENUM_IDX(node_id, slew_rate) << FT9001_OSPEED_POS)), + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#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)} + +/** @endcond */ + +/** + * @name FT9001 pull-up/down configuration + * @{ + */ +#define FT9001_PUPD_NONE 0U /**< No pull-up/down */ +#define FT9001_PUPD_PULLUP 1U /**< Pull-up */ +#define FT9001_PUPD_PULLDOWN 2U /**< Pull-down */ +/** @} */ + +/** + * @name FT9001 output type configuration + * @{ + */ +#define FT9001_OTYPE_PP 0U /**< Push-pull */ +#define FT9001_OTYPE_OD 1U /**< Open-drain */ +/** @} */ + +/** + * @name FT9001 output speed configuration + * @{ + */ +#define FT9001_OSPEED_10MHZ 0U /**< Maximum 10MHz */ +#define FT9001_OSPEED_2MHZ 1U /**< Maximum 2MHz */ +#define FT9001_OSPEED_50MHZ 2U /**< Maximum 50MHz */ +#define FT9001_OSPEED_MAX 3U /**< Maximum speed */ +/** @} */ + +/** + * @name FT9001 pin configuration bit field positions and masks + * @{ + */ +#define FT9001_PUPD_POS 29U /**< PUPD field position */ +#define FT9001_PUPD_MSK 0x3U /**< PUPD field mask */ +#define FT9001_OTYPE_POS 28U /**< OTYPE field position */ +#define FT9001_OTYPE_MSK 0x1U /**< OTYPE field mask */ +#define FT9001_OSPEED_POS 26U /**< OSPEED field position */ +#define FT9001_OSPEED_MSK 0x3U /**< OSPEED field mask */ +/** @} */ + +/** + * @brief Obtain PUPD field from pinctrl_soc_pin_t configuration. + * @param pincfg pinctrl_soc_pin_t bit field value. + */ +#define FT9001_PUPD_GET(pincfg) (((pincfg) >> FT9001_PUPD_POS) & FT9001_PUPD_MSK) + +/** + * @brief Obtain OTYPE field from pinctrl_soc_pin_t configuration. + * @param pincfg pinctrl_soc_pin_t bit field value. + */ +#define FT9001_OTYPE_GET(pincfg) (((pincfg) >> FT9001_OTYPE_POS) & FT9001_OTYPE_MSK) + +/** + * @brief Obtain OSPEED field from pinctrl_soc_pin_t configuration. + * @param pincfg pinctrl_soc_pin_t bit field value. + */ +#define FT9001_OSPEED_GET(pincfg) (((pincfg) >> FT9001_OSPEED_POS) & FT9001_OSPEED_MSK) + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_FOCALTECH_FT9001_PINCTRL_SOC_H_ */ diff --git a/soc/focaltech/ft9001/soc.c b/soc/focaltech/ft9001/soc.c new file mode 100644 index 0000000000000..d5744c30a8079 --- /dev/null +++ b/soc/focaltech/ft9001/soc.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +void soc_early_init_hook(void) +{ + unsigned int key = irq_lock(); + + /* Configure the Vector Table location */ +#ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR + extern char _vector_start[]; + + SCB->VTOR = (uintptr_t)_vector_start; /* Linker guarantees correct alignment */ + __DSB(); + __ISB(); /* Ensure new vector table is used immediately */ +#endif + +#ifdef CONFIG_XIP + xip_clock_switch(1); +#endif + + irq_unlock(key); +} diff --git a/soc/focaltech/ft9001/soc.h b/soc/focaltech/ft9001/soc.h new file mode 100644 index 0000000000000..3476e47a4cea4 --- /dev/null +++ b/soc/focaltech/ft9001/soc.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025, FocalTech Systems CO.,Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SOC_ARM_FOCALTECH_FT9001_SOC_H_ +#define _SOC_ARM_FOCALTECH_FT9001_SOC_H_ + +/* CMSIS required definitions */ +#define __FPU_PRESENT CONFIG_CPU_HAS_FPU +#define __MPU_PRESENT CONFIG_CPU_HAS_ARM_MPU + +/* Add include for DTS generated information */ +#include +#include + +#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +__ramfunc void xip_clock_switch(uint32_t clk_div); +__ramfunc void xip_return_to_boot(void); + +#ifdef __cplusplus +} +#endif +#endif /* !_ASMLANGUAGE && !__ASSEMBLER__ */ + +#endif /* _SOC_ARM_FOCALTECH_FT9001_SOC_H_ */ diff --git a/soc/focaltech/soc.yml b/soc/focaltech/soc.yml new file mode 100644 index 0000000000000..1facbf685b2dc --- /dev/null +++ b/soc/focaltech/soc.yml @@ -0,0 +1,2 @@ +socs: + - name: ft9001