From 2e6a1d0bc67166f4d11761392e929522fd65bc06 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Wed, 16 Apr 2025 18:16:55 +0900 Subject: [PATCH 1/8] soc: ti: add TI Hercules TMS570LC43x SoC Adds new SoC. Some of the necessary startup code is based on the vendor provides tool (halcogen) and it includes SoC init and some errata handling. That code originally had BSD-3-clause license, so it cannot be part of this commit, and has been moved to TI hal repository (modules/hal/ti). The Halcogen code was mostly adapted to zephyr coding style and the the dependencies were minimized. As for erratas, the included one right now is PLL startup problem errata. We also have CORTEX-R5#7 (ARM ID-780125), but it was not included because: 1. Halcogen code does not implement it 3. This is Cortex R5 errata, Xilinx R5 implementation has this note https://adaptivesupport.amd.com/s/article/65878 Signed-off-by: Tavish Naruka --- dts/arm/ti/tms570.dtsi | 91 +++++++++ soc/ti/hercules/CMakeLists.txt | 5 + soc/ti/hercules/Kconfig | 8 + soc/ti/hercules/Kconfig.defconfig | 8 + soc/ti/hercules/Kconfig.soc | 10 + soc/ti/hercules/soc.yml | 6 + soc/ti/hercules/ti_tms570lc43x/CMakeLists.txt | 21 ++ soc/ti/hercules/ti_tms570lc43x/Kconfig | 16 ++ .../hercules/ti_tms570lc43x/Kconfig.defconfig | 26 +++ soc/ti/hercules/ti_tms570lc43x/Kconfig.soc | 23 +++ soc/ti/hercules/ti_tms570lc43x/linker.ld | 7 + soc/ti/hercules/ti_tms570lc43x/soc.h | 43 +++++ soc/ti/hercules/ti_tms570lc43x/soc_defaults.h | 83 ++++++++ soc/ti/hercules/ti_tms570lc43x/soc_internal.h | 180 ++++++++++++++++++ 14 files changed, 527 insertions(+) create mode 100644 dts/arm/ti/tms570.dtsi create mode 100644 soc/ti/hercules/CMakeLists.txt create mode 100644 soc/ti/hercules/Kconfig create mode 100644 soc/ti/hercules/Kconfig.defconfig create mode 100644 soc/ti/hercules/Kconfig.soc create mode 100644 soc/ti/hercules/soc.yml create mode 100644 soc/ti/hercules/ti_tms570lc43x/CMakeLists.txt create mode 100644 soc/ti/hercules/ti_tms570lc43x/Kconfig create mode 100644 soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig create mode 100644 soc/ti/hercules/ti_tms570lc43x/Kconfig.soc create mode 100644 soc/ti/hercules/ti_tms570lc43x/linker.ld create mode 100644 soc/ti/hercules/ti_tms570lc43x/soc.h create mode 100644 soc/ti/hercules/ti_tms570lc43x/soc_defaults.h create mode 100644 soc/ti/hercules/ti_tms570lc43x/soc_internal.h diff --git a/dts/arm/ti/tms570.dtsi b/dts/arm/ti/tms570.dtsi new file mode 100644 index 0000000000000..c21d5b3c3da23 --- /dev/null +++ b/dts/arm/ti/tms570.dtsi @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 ispace inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-r5"; + reg = <0>; + status = "okay"; + }; + }; + + clocks { + /* + * OSC_IN (16 MHZ) + * -> PLL1 (300 MHz) + * -> GCLK1 (300 MHz) + * -> HCLK (150 MHz) + * -> VCLK (75 MHz) + * -> RTICLK (75 MHz, divider is bypassed when VCLK is the source) + */ + + osc_in: osc_in { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "okay"; + }; + + clk_vclk: clk_vclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "okay"; + }; + + clk_rticlk: clk_rticlk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "okay"; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + + sys: sys@ffffff00 { + reg = <0xffffff00 256>, /* SYS1 */ + <0xffffe100 256>, /* SYS2 */ + <0xffff1000 0x800>, /* PCR1 */ + <0xfcff1000 0x800>, /* PCR2 */ + <0xfff78000 0x800>, /* PCR3 */ + <0xfff87000 0x1000>, /* FCR */ + <0xfffff500 0x100>, /* ESM */ + <0xFFFFFF00 0xfc>, /* SYSBASE */ + <0xFFFFFC98 4>, /* WATCHDOG_STATUS */ + <0xFFFFEC00 44>, /* DCC */ + <0xFFA04000 0x10>; /* POM_CONTROL_BASE */ + }; + + sram0: memory@8000000 { + compatible = "mmio-sram"; + reg = <0x08000000 DT_SIZE_K(512)>; + }; + + flc0: flash_controller@f0000000 { + compatible = "flash-controller"; + reg = <0xf0000000 0x00480000>; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0x00000000 DT_SIZE_M(4)>; + }; + }; + }; +}; diff --git a/soc/ti/hercules/CMakeLists.txt b/soc/ti/hercules/CMakeLists.txt new file mode 100644 index 0000000000000..5cb8e1d66d852 --- /dev/null +++ b/soc/ti/hercules/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_NAME}) + +zephyr_include_directories(${SOC_NAME}) diff --git a/soc/ti/hercules/Kconfig b/soc/ti/hercules/Kconfig new file mode 100644 index 0000000000000..aceb77ea1ea6d --- /dev/null +++ b/soc/ti/hercules/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_TI_HERCULES + +rsource "*/Kconfig" + +endif # SOC_FAMILY_TI_HERCULES diff --git a/soc/ti/hercules/Kconfig.defconfig b/soc/ti/hercules/Kconfig.defconfig new file mode 100644 index 0000000000000..5e01391c63dd4 --- /dev/null +++ b/soc/ti/hercules/Kconfig.defconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_TI_HERCULES + +rsource "*/Kconfig.defconfig" + +endif # SOC_FAMILY_TI_HERCULES diff --git a/soc/ti/hercules/Kconfig.soc b/soc/ti/hercules/Kconfig.soc new file mode 100644 index 0000000000000..5b8b1feaab5ee --- /dev/null +++ b/soc/ti/hercules/Kconfig.soc @@ -0,0 +1,10 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_TI_HERCULES + bool + +config SOC_FAMILY + default "ti_hercules" if SOC_FAMILY_TI_HERCULES + +rsource "*/Kconfig.soc" diff --git a/soc/ti/hercules/soc.yml b/soc/ti/hercules/soc.yml new file mode 100644 index 0000000000000..9336e8a25ef8e --- /dev/null +++ b/soc/ti/hercules/soc.yml @@ -0,0 +1,6 @@ +family: +- name: ti_hercules + series: + - name: ti_tms570 + socs: + - name: ti_tms570lc43x diff --git a/soc/ti/hercules/ti_tms570lc43x/CMakeLists.txt b/soc/ti/hercules/ti_tms570lc43x/CMakeLists.txt new file mode 100644 index 0000000000000..de3445de6731c --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/CMakeLists.txt @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 + +# TMS470 requires the ARM "legacy Word Invariant Addressing big-endian mode" +zephyr_compile_options( + -mbe32 + ${TOOLCHAIN_C_FLAGS} +) + +zephyr_ld_options( + -mbe32 + ${TOOLCHAIN_LD_FLAGS} +) + +zephyr_library_include_directories( + ${ZEPHYR_BASE}/kernel/include + ${ZEPHYR_BASE}/arch/arm/include + ) + +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/ti/hercules/ti_tms570lc43x/Kconfig b/soc/ti/hercules/ti_tms570lc43x/Kconfig new file mode 100644 index 0000000000000..e50482ce889ff --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/Kconfig @@ -0,0 +1,16 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_TI_TMS570LC43X + select ARM + select CPU_CORTEX_R5 + select BIG_ENDIAN + select CPU_HAS_DCLS + select CPU_HAS_ARM_MPU + select CPU_HAS_DCACHE + select CPU_HAS_ICACHE + select CACHE_MANAGEMENT + select SOC_RESET_HOOK + select ARM_CUSTOM_INTERRUPT_CONTROLLER + select HAS_TMS570_HALCOGEN_CODE + imply XIP diff --git a/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig b/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig new file mode 100644 index 0000000000000..9207b360f66f6 --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig @@ -0,0 +1,26 @@ +# Copyright (c) Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_TI_TMS570LC43X + +config SYS_CLOCK_EXISTS + default n + +config MULTITHREADING + default n + +config GEN_SW_ISR_TABLE + default n + +config GEN_ISR_TABLES + default n + +# launchpad is 16MHz +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/soc/rti,clock-frequency) + +config NUM_IRQS + # must be >= the highest interrupt number used + default 127 + +endif # SOC_TI_TMS570LC43X diff --git a/soc/ti/hercules/ti_tms570lc43x/Kconfig.soc b/soc/ti/hercules/ti_tms570lc43x/Kconfig.soc new file mode 100644 index 0000000000000..f454e1cd8f548 --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/Kconfig.soc @@ -0,0 +1,23 @@ +# Copyright (c) 2024 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_TI_TMS570 + bool + select SOC_FAMILY_TI_HERCULES + help + TI Hercules family + +config SOC_TI_TMS570LC43X + bool + select SOC_SERIES_TI_TMS570 + help + TI TMS570LC43X + +config HAS_TMS570_HALCOGEN_CODE + bool + +config SOC_SERIES + default "ti_tms570" if SOC_SERIES_TI_TMS570 + +config SOC + default "ti_tms570lc43x" if SOC_TI_TMS570LC43X diff --git a/soc/ti/hercules/ti_tms570lc43x/linker.ld b/soc/ti/hercules/ti_tms570lc43x/linker.ld new file mode 100644 index 0000000000000..367c97892be26 --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/linker.ld @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include diff --git a/soc/ti/hercules/ti_tms570lc43x/soc.h b/soc/ti/hercules/ti_tms570lc43x/soc.h new file mode 100644 index 0000000000000..939d1be7e0e03 --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/soc.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __TMS570_SOC_H__ +#define __TMS570_SOC_H__ + +/* Do not let CMSIS to handle GIC and Timer */ +#include +#define __GIC_PRESENT 0 + +/* these are the default "Interrupt request assignments", see table in datasheet with same name */ +#define IRQ_NUM_ESM_HIGH 0 /* cannot be remapped, is NMI (FIQ) */ +#define IRQ_RTI_COMPARE_0 2 /* RTI1 compare interrupt 0 */ +#define IRQ_RTI_COMPARE_1 3 /* RTI1 compare interrupt 1 */ +#define IRQ_RTI_COMPARE_2 4 /* RTI1 compare interrupt 2 */ +#define IRQ_RTI_COMPARE_3 5 /* RTI1 compare interrupt 3 */ +#define IRQ_RTI_OVERFLOW_0 6 /* RTI1 overflow interrupt 1 */ +#define IRQ_RTI_OVERFLOW_1 7 /* RTI1 overflow interrupt 1 */ +#define IRQ_RTI_TIME_BASE 8 /* RTI1 time-base */ +#define IRQ_GIO_HIGH_LEVEL 9 /* GIO high level interrupt */ +#define IRQ_NUM_ESM_LOW 20 /* ESM low level interrupt */ + +#define DRV_SYS DT_NODELABEL(sys) + +#define DRV_SYS1 DT_REG_ADDR_BY_IDX(DRV_SYS, 0) +#define DRV_SYS2 DT_REG_ADDR_BY_IDX(DRV_SYS, 1) +#define DRV_PCR1 DT_REG_ADDR_BY_IDX(DRV_SYS, 2) +#define DRV_PCR2 DT_REG_ADDR_BY_IDX(DRV_SYS, 3) +#define DRV_PCR3 DT_REG_ADDR_BY_IDX(DRV_SYS, 4) +#define DRV_FCR DT_REG_ADDR_BY_IDX(DRV_SYS, 5) +#define DRV_ESM DT_REG_ADDR_BY_IDX(DRV_SYS, 6) +#define DRV_SYSBASE DT_REG_ADDR_BY_IDX(DRV_SYS, 7) +#define DRV_WATCHDOG_STATUS DT_REG_ADDR_BY_IDX(DRV_SYS, 8) +#define DRV_DCC DT_REG_ADDR_BY_IDX(DRV_SYS, 9) +#define DRV_POM_CONTROL DT_REG_ADDR_BY_IDX(DRV_SYS, 10) + +#define DRV_VIMRAM DT_REG_ADDR_BY_IDX(DT_NODELABEL(vim), 2) +#define DRV_VIMRAM_SZ DT_REG_SIZE_BY_IDX(DT_NODELABEL(vim), 2) + +#endif /* __TMS570_SOC_H__ */ diff --git a/soc/ti/hercules/ti_tms570lc43x/soc_defaults.h b/soc/ti/hercules/ti_tms570lc43x/soc_defaults.h new file mode 100644 index 0000000000000..9e6698c31c569 --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/soc_defaults.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __TMS570_SOC_PRIVATE_H__ +#define __TMS570_SOC_PRIVATE_H__ + +#define OSC_IN_FREQ_MHZ DT_PROP(DT_NODELABEL(osc_in), clock_frequency) / 1000000 + +/** + * - BPOS = 1, Bypass on PLL Slip is enabled + * - PLLDIV = 31 (R = 32) + * - REFCLKDIV = OSC_IN_FREQ_MHZ - 1 (ref clock divider) + * - PLLMUL = 0x9500 (NF, multiplication factor = 0x95+1 = 150) + * + * NOTE: the divider value is changed later on, to be 0 (R=1) + */ +#define PLLCTL1_INIT_VALUE (1 << PLLCTL1_BPOS_OFFSET | \ + 31 << PLLCTL1_PLLDIV_OFFSET | \ + (OSC_IN_FREQ_MHZ - 1) << PLLCTL1_REFCLKDIV_OFFSET | \ + 0x9500) + +/** + *- SPREADINGRATE = 255 (NS = 256) + *- MULMOD = 7 + *- ODPLL = 0 (OD, output divider = 0) + *- SPR_AMOUNT = 61 (NV = 62/2048) + */ +#define PLLCTL2_INIT_VALUE (255 << PLLCTL2_SPREADINGRATE_OFFSET | \ + 7 << PLLCTL2_MULMOD_OFFSET | \ + 61 << PLLCTL2_SPR_AMOUNT_OFFSET) + +/** + *- ODPLL2 = 0 (OD2 = 1) + *- PLLDIV2 = 31 (R2 = 32) + *- REFCLKDIV2 = 7 (NR2 = 8) + *- PLLMUL2 = 0x9500 (NF2 = 150) + */ +#define PLLCTL3_INIT_VALUE (31 << PLLCTL3_PLLDIV2_OFFSET | \ + 7 << PLLCTL3_REFCLKDIV2_OFFSET | \ + 0x9500 << PLLCTL3_PLLMUL2_OFFSET) + +/** + *- RWAIT = 3 Random/data Read Wait State + *- PFUENB = 1 Prefetch Enable for Port B + *- PFUENA = 1 Prefetch Enable for Port A + */ +#define FRDCNTL_INIT_VALUE (3 << FRDCNTL_RWAIT_OFFSET | FRDCNTL_PFUENA | FRDCNTL_PFUENB) + +/** + * - EEPROM Wait state Counter = 9 + */ +#define EEPROM_CONFIG_INIT_VALUE (9 << EWAIT_OFFSET) + +#define FBPWRMODE_INIT_VALUE (BANKPWR_VAL_ACTIVE << BANKPWR0_OFFSET | \ + BANKPWR_VAL_ACTIVE << BANKPWR1_OFFSET | \ + BANKPWR_VAL_ACTIVE << BANKPWR7_OFFSET) + +/* GCLK, HCLK and VCLK source is PLL1 */ +#define GHVSRC_INIT_VALUE (1 << GHVWAKE_OFFSET | 1 << HVLPM_OFFSET | 1 << GHVSRC_OFFSET) + +/** + * - RTI1DIV = 0, divider = 1 (NOTE: divider is bypassed when VCLK is the source) + * - RTI1SRC = 9, VCLK as source, 8 to 0xF is VCLK + */ +#define RCLKSRC_INIT_VALUE (0 << RTI1DIV_OFFSET | 9 << RTI1SRC_OFFSET) + +/** + *- VCLKA1S = 9, VCLK is source + *- VCLKA2S = 9, VCLK is source + */ +#define VCLKASRC_INIT_VALUE (9 << VCLKA1S_OFFSET | 9 << VCLKA2S_OFFSET) + +/* + * - VCLKA4R = 0, divider=1 + * - VCLKA4_DIV_CDDIS = 0, Disable the VCLKA4 divider output + * - VCLKA4S = 9, source=VCLK + */ +#define VCLKACON1_INIT_VALUE (0 << VCLKA4R_OFFSET | VCLKA4_DIV_CDDIS | 9 << VCLKA4S_OFFSET) + +#endif /* __TMS570_SOC_PRIVATE_H__ */ diff --git a/soc/ti/hercules/ti_tms570lc43x/soc_internal.h b/soc/ti/hercules/ti_tms570lc43x/soc_internal.h new file mode 100644 index 0000000000000..10e451f645517 --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/soc_internal.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __TMS570_SOC_INTERNAL_H__ +#define __TMS570_SOC_INTERNAL_H__ + +#include +#include + +/* Primary System Control Registers (SYS) */ +#define REG_SYS1_CSDIS (DRV_SYS1 + 0x0030) +#define REG_SYS1_CSDISSET (DRV_SYS1 + 0x0034) +#define REG_SYS1_CSDISCLR (DRV_SYS1 + 0x0038) +#define REG_SYS1_CDDIS (DRV_SYS1 + 0x003C) +#define REG_SYS1_GHVSRC (DRV_SYS1 + 0x0048) +#define REG_SYS1_VCLKASRC (DRV_SYS1 + 0x004C) +#define REG_SYS1_RCLKSRC (DRV_SYS1 + 0x0050) +#define REG_SYS1_CSVSTAT (DRV_SYS1 + 0x0054) +#define REG_SYS1_PLLCTL1 (DRV_SYS1 + 0x0070) +#define REG_SYS1_PLLCTL2 (DRV_SYS1 + 0x0074) +#define REG_SYS1_CLKCNTL (DRV_SYS1 + 0x00D0) +#define REG_SYS1_GBLSTAT (DRV_SYS1 + 0x00EC) + +/* Secondary System Control Registers (SYS2) */ +#define REG_SYS2_PLLCTL3 (DRV_SYS2 + 0x0000) +#define REG_SYS2_CLK2CNTRL (DRV_SYS2 + 0x003C) +#define REG_SYS2_VCLKACON1 (DRV_SYS2 + 0x0040) +#define REG_SYS2_HCLKCNTL (DRV_SYS2 + 0x0054) + +/* peripheral control resgisters */ +#define REG_PCR1_PSPWRDWNCLR0 (DRV_PCR1 + 0x00A0) +#define REG_PCR1_PSPWRDWNCLR1 (DRV_PCR1 + 0x00A4) +#define REG_PCR1_PSPWRDWNCLR2 (DRV_PCR1 + 0x00A8) +#define REG_PCR1_PSPWRDWNCLR3 (DRV_PCR1 + 0x00AC) + +#define REG_PCR2_PSPWRDWNCLR0 (DRV_PCR2 + 0x00A0) +#define REG_PCR2_PSPWRDWNCLR1 (DRV_PCR2 + 0x00A4) +#define REG_PCR2_PSPWRDWNCLR2 (DRV_PCR2 + 0x00A8) +#define REG_PCR2_PSPWRDWNCLR3 (DRV_PCR2 + 0x00AC) + +#define REG_PCR3_PSPWRDWNCLR0 (DRV_PCR3 + 0x00A0) +#define REG_PCR3_PSPWRDWNCLR1 (DRV_PCR3 + 0x00A4) +#define REG_PCR3_PSPWRDWNCLR2 (DRV_PCR3 + 0x00A8) +#define REG_PCR3_PSPWRDWNCLR3 (DRV_PCR3 + 0x00AC) + +/* flash control registers */ +#define REG_FCR_FRDCNTL (DRV_FCR + 0x0000) +#define REG_FCR_FBPWRMODE (DRV_FCR + 0x0040) +#define REG_FCR_FSM_WR_ENA (DRV_FCR + 0x0288) +#define REG_FCR_EEPROM_CONFIG (DRV_FCR + 0x02B8) + +/* error signalling module registers */ +#define REG_ESM_EEPAPR1 (DRV_ESM + 0x0000) +#define REG_ESM_DEPAPR1 (DRV_ESM + 0x0004) +#define REG_ESM_IESR1 (DRV_ESM + 0x0008) +#define REG_ESM_IECR1 (DRV_ESM + 0x000C) +#define REG_ESM_ILSR1 (DRV_ESM + 0x0010) +#define REG_ESM_ILCR1 (DRV_ESM + 0x0014) +#define REG_ESM_SR1_0 (DRV_ESM + 0x0018) +#define REG_ESM_SR1_1 (DRV_ESM + 0x001C) +#define REG_ESM_SR1_2 (DRV_ESM + 0x0020) +#define REG_ESM_EPSR (DRV_ESM + 0x0024) +#define REG_ESM_IOFFHR (DRV_ESM + 0x0028) +#define REG_ESM_IOFFLR (DRV_ESM + 0x002C) +#define REG_ESM_LTCR (DRV_ESM + 0x0030) +#define REG_ESM_LTCPR (DRV_ESM + 0x0034) +#define REG_ESM_EKR (DRV_ESM + 0x0038) +#define REG_ESM_SSR2 (DRV_ESM + 0x003C) +#define REG_ESM_IEPSR4 (DRV_ESM + 0x0040) +#define REG_ESM_IEPCR4 (DRV_ESM + 0x0044) +#define REG_ESM_IESR4 (DRV_ESM + 0x0048) +#define REG_ESM_IECR4 (DRV_ESM + 0x004C) +#define REG_ESM_ILSR4 (DRV_ESM + 0x0050) +#define REG_ESM_ILCR4 (DRV_ESM + 0x0054) +#define REG_ESM_SR4_0 (DRV_ESM + 0x0058) +#define REG_ESM_SR4_1 (DRV_ESM + 0x005C) +#define REG_ESM_SR4_2 (DRV_ESM + 0x0060) +#define REG_ESM_IEPSR7 (DRV_ESM + 0x0080) +#define REG_ESM_IEPCR7 (DRV_ESM + 0x0084) +#define REG_ESM_IESR7 (DRV_ESM + 0x0088) +#define REG_ESM_IECR7 (DRV_ESM + 0x008C) +#define REG_ESM_ILSR7 (DRV_ESM + 0x0090) +#define REG_ESM_ILCR7 (DRV_ESM + 0x0094) +#define REG_ESM_SR7_0 (DRV_ESM + 0x0098) +#define REG_ESM_SR7_1 (DRV_ESM + 0x009C) +#define REG_ESM_SR7_2 (DRV_ESM + 0x00A0) + +#define REG_SYSECR (DRV_SYSBASE + 0xE0) +#define REG_SYSESR (DRV_SYSBASE + 0xE4) + +#define REG_POMGLBCTRL (DRV_POM_CONTROL + 0x00) + +#define CSDIS_SRC_OSC BIT(0) +#define CSDIS_SRC_PLL1 BIT(1) +#define CSDIS_SRC_LFLPO BIT(4) +#define CSDIS_SRC_HFLPO BIT(5) +#define CSDIS_SRC_PLL2 BIT(6) +#define CSDIS_SRC_MASK (0xFF) + +#define GLBSTAT_OSCFAIL BIT(0) +#define GLBSTAT_RFSLIP BIT(8) +#define GLBSTAT_FBSLIP BIT(9) + +#define CLKCNTL_PERIPHENA BIT(8) + +#define FRDCNTL_RWAIT_OFFSET (8) +#define FRDCNTL_PFUENB BIT(1) +#define FRDCNTL_PFUENA BIT(0) + +#define FSM_WR_ENA_ENABLE_VAL (5 << 0) +#define FSM_WR_ENA_DISABLE_VAL (2 << 0) + +#define EWAIT_OFFSET (16) + +#define BANKPWR0_OFFSET (0) +#define BANKPWR1_OFFSET (2) +#define BANKPWR7_OFFSET (14) +#define BANKPWR_VAL_ACTIVE (3) + +#define GHVWAKE_OFFSET (24) +#define HVLPM_OFFSET (16) +#define GHVSRC_OFFSET (0) + +#define RTI1DIV_OFFSET (8) +#define RTI1SRC_OFFSET (0) + +#define VCLKA1S_OFFSET (0) +#define VCLKA2S_OFFSET (8) + +#define CLKCNTL_VCLKR_OFFSET (16) +#define CLKCNTL_VCLKR_MASK (0xF << CLKCNTL_VCLKR_OFFSET) +#define CLKCNTL_VCLK2R_OFFSET (24) +#define CLKCNTL_VCLK2R_MASK (0xF << CLKCNTL_VCLK2R_OFFSET) +#define CLKCNTL_PENA BIT(8) +#define CLK2CNTRL_VCLK3R_OFFSET (0) +#define CLK2CNTRL_VCLK3R_MASK (0xF << CLK2CNTRL_VCLK3R_OFFSET) + +#define VCLKA4R_OFFSET (24) +#define VCLKA4_DIV_CDDIS BIT(20) +#define VCLKA4S_OFFSET (16) + +#define PLLCTL1_PLLDIV_OFFSET (24) +#define PLLCTL1_PLLDIV_MASK ~(0x1F << PLLCTL1_PLLDIV_OFFSET) +#define PLLCTL1_BPOS_OFFSET (29) +#define PLLCTL1_REFCLKDIV_OFFSET (16) + +#define PLLCTL2_SPREADINGRATE_OFFSET (22) +#define PLLCTL2_MULMOD_OFFSET (12) +#define PLLCTL2_SPR_AMOUNT_OFFSET (0) + +#define PLLCTL3_PLLDIV2_OFFSET (24) +#define PLLCTL3_PLLDIV2_MASK ~(0x1F << PLLCTL3_PLLDIV2_OFFSET) +#define PLLCTL3_REFCLKDIV2_OFFSET (16) +#define PLLCTL3_PLLMUL2_OFFSET (0) + +#define HCLKCNTL_HCLKR_OFFSET (0) + +#define CDDIS_VCLKA2 BIT(5) + +typedef enum { + POWERON_RESET = 0x8000U, /**< Alias for Power On Reset */ + OSC_FAILURE_RESET = 0x4000U, /**< Alias for Osc Failure Reset */ + WATCHDOG_RESET = 0x2000U, /**< Alias for Watch Dog Reset */ + WATCHDOG2_RESET = 0x1000U, /**< Alias for Watch Dog 2 Reset */ + DEBUG_RESET = 0x0800U, /**< Alias for Debug Reset */ + INTERCONNECT_RESET = 0x0080U, /**< Alias for Interconnect Reset */ + CPU0_RESET = 0x0020U, /**< Alias for CPU 0 Reset */ + SW_RESET = 0x0010U, /**< Alias for Software Reset */ + EXT_RESET = 0x0008U, /**< Alias for External Reset */ + NO_RESET = 0x0000U /**< Alias for No Reset */ +} resetSource_t; + + +void _mpuInit_(void); +uint32_t _errata_SSWF021_45_both_plls(uint32_t count); + +#endif /* __TMS570_SOC_INTERNAL_H__ */ From caf5c0b1c360370060e9f4b221b448fe24d86813 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Wed, 23 Apr 2025 13:29:44 +0900 Subject: [PATCH 2/8] drivers: pinctrl: add tms570 driver Adds driver for TI TMS570 SoC. Signed-off-by: Tavish Naruka --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Kconfig.ti_tms570 | 9 ++++ drivers/pinctrl/pinctrl_ti_tms570.c | 45 ++++++++++++++++++++ dts/arm/ti/tms570.dtsi | 6 +++ dts/bindings/pinctrl/ti,tms570-pinmux.yaml | 21 +++++++++ soc/ti/hercules/ti_tms570lc43x/pinctrl_soc.h | 31 ++++++++++++++ 7 files changed, 114 insertions(+) create mode 100644 drivers/pinctrl/Kconfig.ti_tms570 create mode 100644 drivers/pinctrl/pinctrl_ti_tms570.c create mode 100644 dts/bindings/pinctrl/ti,tms570-pinmux.yaml create mode 100644 soc/ti/hercules/ti_tms570lc43x/pinctrl_soc.h diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index dd46c54f977b5..0c0ca3a5fcc0c 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -41,6 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_GECKO pinctrl_gecko.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_SILABS_SIWX91X pinctrl_silabs_siwx91x.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_SILABS_DBUS pinctrl_silabs_dbus.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_K3 pinctrl_ti_k3.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_TMS570 pinctrl_ti_tms570.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_EMSDP pinctrl_emsdp.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_CC32XX pinctrl_ti_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_NUMAKER pinctrl_numaker.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 05a097040688b..f6ded03296cc5 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -75,6 +75,7 @@ source "drivers/pinctrl/Kconfig.siwx91x" source "drivers/pinctrl/Kconfig.ti_k3" source "drivers/pinctrl/Kconfig.emsdp" source "drivers/pinctrl/Kconfig.ti_cc32xx" +source "drivers/pinctrl/Kconfig.ti_tms570" source "drivers/pinctrl/Kconfig.numaker" source "drivers/pinctrl/Kconfig.eos_s3" source "drivers/pinctrl/Kconfig.mci_io_mux" diff --git a/drivers/pinctrl/Kconfig.ti_tms570 b/drivers/pinctrl/Kconfig.ti_tms570 new file mode 100644 index 0000000000000..04ef79865b488 --- /dev/null +++ b/drivers/pinctrl/Kconfig.ti_tms570 @@ -0,0 +1,9 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_TI_TMS570 + bool "TI TMS570 pinctrl driver" + default y + depends on DT_HAS_TI_TMS570_PINMUX_ENABLED + help + Enable the TI TMS570 pinmux driver diff --git a/drivers/pinctrl/pinctrl_ti_tms570.c b/drivers/pinctrl/pinctrl_ti_tms570.c new file mode 100644 index 0000000000000..9616003d63c68 --- /dev/null +++ b/drivers/pinctrl/pinctrl_ti_tms570.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#define DT_DRV_COMPAT ti_tms570_pinmux +#define DRV_REG_ADDR DT_INST_REG_ADDR(0) + +#define REG_KICK0_OFFSET (0x38) +#define REG_KICK1_OFFSET (0x3C) + +/* value used to unlock */ +#define KICK0_VALUE (0x83E70B13) +#define KICK1_VALUE (0x95A4F1E0) + +#define REG_PINMMR_0_OFFSET (0x110) + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + uint32_t nibble_start; + uint32_t mask; + + ARG_UNUSED(reg); + + /* unlock */ + sys_write32(KICK0_VALUE, DRV_REG_ADDR + REG_KICK0_OFFSET); + sys_write32(KICK1_VALUE, DRV_REG_ADDR + REG_KICK1_OFFSET); + + for (uint8_t i = 0; i < pin_cnt; i++) { + nibble_start = (pins[i].bit / 4) * 4; + mask = 0xff << nibble_start; + sys_write32(mask & BIT(pins[i].bit), + DRV_REG_ADDR + REG_PINMMR_0_OFFSET + (pins[i].pinmmr * 4)); + } + + /* lock */ + sys_write32(0, DRV_REG_ADDR + REG_KICK0_OFFSET); + sys_write32(0, DRV_REG_ADDR + REG_KICK1_OFFSET); + + return 0; +} diff --git a/dts/arm/ti/tms570.dtsi b/dts/arm/ti/tms570.dtsi index c21d5b3c3da23..2e26cfaa17010 100644 --- a/dts/arm/ti/tms570.dtsi +++ b/dts/arm/ti/tms570.dtsi @@ -87,5 +87,11 @@ reg = <0x00000000 DT_SIZE_M(4)>; }; }; + + pinctrl: pin-controller@ffff1c00 { + compatible = "ti,tms570-pinmux"; + reg = <0xffff1c00 0x400>; + status = "okay"; + }; }; }; diff --git a/dts/bindings/pinctrl/ti,tms570-pinmux.yaml b/dts/bindings/pinctrl/ti,tms570-pinmux.yaml new file mode 100644 index 0000000000000..061d90e41a77e --- /dev/null +++ b/dts/bindings/pinctrl/ti,tms570-pinmux.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +description: TI TMS570 pinmux driver + +compatible: "ti,tms570-pinmux" + +include: base.yaml + +properties: + reg: + required: true + +child-binding: + properties: + pinmux: + required: true + type: array + description: | + TMS570 pin's configuration (select bit pair) based on the "Output Multiplexing" + table in the reference manual. diff --git a/soc/ti/hercules/ti_tms570lc43x/pinctrl_soc.h b/soc/ti/hercules/ti_tms570lc43x/pinctrl_soc.h new file mode 100644 index 0000000000000..384d884a3a88c --- /dev/null +++ b/soc/ti/hercules/ti_tms570lc43x/pinctrl_soc.h @@ -0,0 +1,31 @@ +/* + * Copyright 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_TI_TMS570_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_TI_TMS570_PINCTRL_SOC_H_ + +#include +#include + +typedef struct pinctrl_soc_pin_t { + uint8_t pinmmr; + uint8_t bit; +} pinctrl_soc_pin_t; + +#define TI_TMS570_DT_PIN(node_id) \ + { \ + .pinmmr = DT_PROP_BY_IDX(node_id, pinmux, 0), \ + .bit = DT_PROP_BY_IDX(node_id, pinmux, 1) \ + }, + +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + TI_TMS570_DT_PIN(DT_PROP_BY_IDX(node_id, prop, idx)) + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) } + + +#endif /* ZEPHYR_SOC_TI_TMS570_PINCTRL_SOC_H_ */ From 1548b0632aed957671538b8ff29483c5fb59d7d1 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Fri, 6 Jun 2025 15:39:22 +0900 Subject: [PATCH 3/8] drivers: serial: add tms570 uart driver Adds SCI peripheral UART driver for TMS570. Signed-off-by: Tavish Naruka --- drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 1 + drivers/serial/Kconfig.tms570 | 11 ++ drivers/serial/uart_tms570.c | 174 ++++++++++++++++++++++++ dts/arm/ti/tms570.dtsi | 12 ++ dts/bindings/serial/ti,tms570-uart.yaml | 12 ++ 6 files changed, 211 insertions(+) create mode 100644 drivers/serial/Kconfig.tms570 create mode 100644 drivers/serial/uart_tms570.c create mode 100644 dts/bindings/serial/ti,tms570-uart.yaml diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 05289856ac968..2adc932e2be9c 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -96,6 +96,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_STELLARIS uart_stellaris.c) zephyr_library_sources_ifdef(CONFIG_UART_STM32 uart_stm32.c) zephyr_library_sources_ifdef(CONFIG_UART_SY1XX uart_sy1xx.c) zephyr_library_sources_ifdef(CONFIG_UART_TELINK_B91 uart_b91.c) +zephyr_library_sources_ifdef(CONFIG_UART_TMS570 uart_tms570.c) zephyr_library_sources_ifdef(CONFIG_UART_WCH_USART uart_wch_usart.c) zephyr_library_sources_ifdef(CONFIG_UART_XEC uart_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_UART_XEN_HVC uart_hvc_xen.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 3a13969e5a9a6..9458d2d5a349e 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -234,6 +234,7 @@ rsource "Kconfig.stellaris" rsource "Kconfig.stm32" rsource "Kconfig.sy1xx" rsource "Kconfig.test" +rsource "Kconfig.tms570" rsource "Kconfig.uart_sam" rsource "Kconfig.usart_sam" rsource "Kconfig.wch_usart" diff --git a/drivers/serial/Kconfig.tms570 b/drivers/serial/Kconfig.tms570 new file mode 100644 index 0000000000000..d3b462e9f6239 --- /dev/null +++ b/drivers/serial/Kconfig.tms570 @@ -0,0 +1,11 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +config UART_TMS570 + bool "TI TMS570 series SCI USART driver" + default y + depends on DT_HAS_TI_TMS570_UART_ENABLED + select SERIAL_HAS_DRIVER + select PINCTRL + help + This option enables the TMS570 UART driver. diff --git a/drivers/serial/uart_tms570.c b/drivers/serial/uart_tms570.c new file mode 100644 index 0000000000000..418f6cbebb003 --- /dev/null +++ b/drivers/serial/uart_tms570.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT ti_tms570_uart + +#define VCLK_FREQUENCY DT_PROP(DT_NODELABEL(clk_vclk), clock_frequency) + +#define TMS570_GCR0 (0x00) +#define TMS570_GCR1 (0x04) +#define TMS570_GCR2 (0x08) +#define TMS570_SETINT (0x0c) +#define TMS570_CLEARINT (0x10) +#define TMS570_SETINTLVL (0x14) +#define TMS570_CLEARINTLVL (0x18) +#define TMS570_FLR (0x1c) +#define TMS570_INTVECT0 (0x20) +#define TMS570_INTVECT1 (0x24) +#define TMS570_FORMAT (0x28) +#define TMS570_BRS (0x2c) +#define TMS570_ED (0x30) +#define TMS570_RD (0x34) +#define TMS570_TD (0x38) +#define TMS570_PIO0 (0x3c) +#define TMS570_PIO1 (0x40) +#define TMS570_PIO2 (0x44) +#define TMS570_PIO3 (0x48) +#define TMS570_PIO4 (0x4c) +#define TMS570_PIO5 (0x50) +#define TMS570_PIO6 (0x54) +#define TMS570_PIO7 (0x58) +#define TMS570_PIO8 (0x5c) +#define TMS570_IODFTCTRL (0x90) + +#define TMS570_SCI_REG_GCR0 (dev_cfg->base_addr + TMS570_GCR0) +#define TMS570_SCI_REG_GCR1 (dev_cfg->base_addr + TMS570_GCR1) +#define TMS570_SCI_REG_CLEARINT (dev_cfg->base_addr + TMS570_CLEARINT) +#define TMS570_SCI_REG_CLEARINTLVL (dev_cfg->base_addr + TMS570_CLEARINTLVL) +#define TMS570_SCI_REG_FORMAT (dev_cfg->base_addr + TMS570_FORMAT) +#define TMS570_SCI_REG_BRS (dev_cfg->base_addr + TMS570_BRS) +#define TMS570_SCI_REG_FUNC (dev_cfg->base_addr + TMS570_PIO0) +#define TMS570_SCI_REG_PIO8 (dev_cfg->base_addr + TMS570_PIO8) +#define TMS570_SCI_REG_RD (dev_cfg->base_addr + TMS570_RD) +#define TMS570_SCI_REG_TD (dev_cfg->base_addr + TMS570_TD) +#define TMS570_SCI_REG_FLR (dev_cfg->base_addr + TMS570_FLR) + +#define GCR1_TXENA (1 << 25) +#define GCR1_RXENA (1 << 24) +#define GCR1_CONT (1 << 17) +#define GCR1_LOOPBACK (1 << 16) +#define GCR1_STOP_EXT_FRAME (1 << 13) +#define GCR1_HGEN_CTRL (1 << 12) +#define GCR1_CTYPE (1 << 11) +#define GCR1_MBUF_MODE (1 << 10) +#define GCR1_ADAPT (1 << 9) +#define GCR1_SLEEP (1 << 8) +#define GCR1_SWnRST (1 << 7) +#define GCR1_LIN_MODE (1 << 6) +#define GCR1_CLOCK (1 << 5) +#define GCR1_STOP_BIT_1 (0 << 4) +#define GCR1_STOP_BIT_2 (1 << 4) +#define GCR1_PARITY_ENA (1 << 2) +#define GCR1_PARITY_ODD ((0 << 3) | GCR1_PARITY_ENA) +#define GCR1_PARITY_EVEN ((1 << 3) | GCR1_PARITY_ENA) +#define GCR1_PARITY_NONE (0) +#define GCR1_TIMING_MODE_SYNC (0 << 1) +#define GCR1_TIMING_MODE_ASYNC (1 << 1) +#define GCR1_COMM_MODE (1 << 0) + +#define FLR_RX_RDY (1 << 9) +#define FLR_TX_RDY (1 << 8) + +#define FORMAT_CHARS_IN_FRAME(x) (((x - 1) & 0x7) << 16) +#define FORMAT_BITS_PER_CHAR(x) (((x - 1) & 0x7)) +#define FORMAT_8_BIT_1_CHAR (FORMAT_CHARS_IN_FRAME(1) | FORMAT_BITS_PER_CHAR(8)) + +#define PIO_TX_EN (1 << 2) +#define PIO_RX_EN (1 << 1) + +/* Device data structure */ +struct uart_tms570_dev_cfg_t { + const uint32_t base_addr; /* Register base address */ + const uint32_t baud_rate; /* Baud rate */ + const struct pinctrl_dev_config *pincfg; +}; + + +static void uart_tms570_poll_out(const struct device *dev, uint8_t c) +{ + const struct uart_tms570_dev_cfg_t *dev_cfg = + (const struct uart_tms570_dev_cfg_t *) dev->config; + + while ((sys_read32(TMS570_SCI_REG_FLR) & 0x00000100U) == 0U) { + /* wait */ + } + + sys_write32(c, TMS570_SCI_REG_TD); +} + +static int uart_tms570_poll_in(const struct device *dev, uint8_t *c) +{ + const struct uart_tms570_dev_cfg_t *dev_cfg = + (const struct uart_tms570_dev_cfg_t *) dev->config; + uint32_t flags; + + flags = sys_read32(TMS570_SCI_REG_FLR); + if ((flags & FLR_RX_RDY) != 0) { + *c = (uint8_t)sys_read32(TMS570_SCI_REG_RD); + return 0; + } else { + return -1; + } +} + +static int uart_tms570_init(const struct device *dev) +{ + const struct uart_tms570_dev_cfg_t *dev_cfg = + (const struct uart_tms570_dev_cfg_t *) dev->config; + + /* reset SCI */ + sys_write32(0, TMS570_SCI_REG_GCR0); + sys_write32(1, TMS570_SCI_REG_GCR0); + + /* enable and set up uart */ + sys_write32(GCR1_TXENA | GCR1_RXENA | /* enable both tx and rx */ + GCR1_CLOCK | /* internal clock (device has no clock pin) */ + GCR1_STOP_BIT_1 | + GCR1_PARITY_NONE | + GCR1_TIMING_MODE_ASYNC, + TMS570_SCI_REG_GCR1); + + /* make pins SCI mode */ + sys_write32(PIO_TX_EN | PIO_RX_EN, TMS570_SCI_REG_FUNC); + pinctrl_apply_state(dev_cfg->pincfg, PINCTRL_STATE_DEFAULT); + + /* baudrate */ + sys_write32(VCLK_FREQUENCY / ((dev_cfg->baud_rate - 1) * 16), TMS570_SCI_REG_BRS); + + /* we want 8 bit per char and 1 char per frame */ + sys_write32(FORMAT_8_BIT_1_CHAR, TMS570_SCI_REG_FORMAT); + + /* start */ + sys_write32(sys_read32(TMS570_SCI_REG_GCR1) | GCR1_SWnRST, TMS570_SCI_REG_GCR1); + + return 0; +} + +static const struct uart_driver_api uart_tms570_driver_api = { + .poll_in = uart_tms570_poll_in, + .poll_out = uart_tms570_poll_out, + .err_check = NULL, +}; + +#define TMS570_UART_INIT(idx) \ + PINCTRL_DT_INST_DEFINE(idx); \ + static struct uart_tms570_dev_cfg_t tms570__uart##idx##_cfg = { \ + .base_addr = DT_INST_REG_ADDR(idx), \ + .baud_rate = DT_INST_PROP(idx, current_speed), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ + }; \ + DEVICE_DT_INST_DEFINE(idx, &uart_tms570_init, NULL, NULL, \ + &tms570__uart##idx##_cfg, PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_tms570_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TMS570_UART_INIT) diff --git a/dts/arm/ti/tms570.dtsi b/dts/arm/ti/tms570.dtsi index 2e26cfaa17010..2763d3b76c0da 100644 --- a/dts/arm/ti/tms570.dtsi +++ b/dts/arm/ti/tms570.dtsi @@ -93,5 +93,17 @@ reg = <0xffff1c00 0x400>; status = "okay"; }; + + sci1: uart@fff7e400 { + compatible = "ti,tms570-uart"; + reg = <0xfff7e400 256>; + status = "disabled"; + }; + + sci3: uart@fff7e500 { + compatible = "ti,tms570-uart"; + reg = <0xfff7e500 256>; + status = "disabled"; + }; }; }; diff --git a/dts/bindings/serial/ti,tms570-uart.yaml b/dts/bindings/serial/ti,tms570-uart.yaml new file mode 100644 index 0000000000000..ae8c2f319e26c --- /dev/null +++ b/dts/bindings/serial/ti,tms570-uart.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2025, ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +description: TI TMS570 UART + +compatible: "ti,tms570-uart" + +include: [uart-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + reg: + required: true From 18cad3ce610f90b0092658760815b14df2804f20 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Fri, 6 Jun 2025 15:39:31 +0900 Subject: [PATCH 4/8] drivers: intc: add vim_tms570 interrupt controller Add TI VIM driver specific to the TMS570 chips. This driver/peripheral is not compatible with the existing intc_vim.c for some other TI chips. Signed-off-by: Tavish Naruka --- drivers/interrupt_controller/CMakeLists.txt | 1 + drivers/interrupt_controller/Kconfig | 2 + .../interrupt_controller/Kconfig.tms570_vim | 11 ++ .../interrupt_controller/intc_tms570_vim.c | 177 ++++++++++++++++++ dts/arm/ti/tms570.dtsi | 11 ++ .../interrupt-controller/ti,tms570-vim.yaml | 24 +++ .../hercules/ti_tms570lc43x/Kconfig.defconfig | 20 +- 7 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 drivers/interrupt_controller/Kconfig.tms570_vim create mode 100644 drivers/interrupt_controller/intc_tms570_vim.c create mode 100644 dts/bindings/interrupt-controller/ti,tms570-vim.yaml diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index 080dcfe331816..acb300c8bc6c4 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -34,6 +34,7 @@ zephyr_library_sources_ifdef(CONFIG_INTC_ESP32 intc_esp32.c) zephyr_library_sources_ifdef(CONFIG_SWERV_PIC intc_swerv_pic.c) zephyr_library_sources_ifdef(CONFIG_VEXRISCV_LITEX_IRQ intc_vexriscv_litex.c) zephyr_library_sources_ifdef(CONFIG_VIM intc_vim.c) +zephyr_library_sources_ifdef(CONFIG_TMS570_VIM intc_tms570_vim.c) zephyr_library_sources_ifdef(CONFIG_CLIC intc_clic.c) zephyr_library_sources_ifdef(CONFIG_CLIC intc_clic.S) zephyr_library_sources_ifdef(CONFIG_NRFX_CLIC intc_nrfx_clic.c) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index 3e6e554bc6d87..b320893d1a477 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -102,6 +102,8 @@ source "drivers/interrupt_controller/Kconfig.nxp_pint" source "drivers/interrupt_controller/Kconfig.vim" +source "drivers/interrupt_controller/Kconfig.tms570_vim" + source "drivers/interrupt_controller/Kconfig.renesas_rz" source "drivers/interrupt_controller/Kconfig.renesas_rx" diff --git a/drivers/interrupt_controller/Kconfig.tms570_vim b/drivers/interrupt_controller/Kconfig.tms570_vim new file mode 100644 index 0000000000000..3c5ffeb474f92 --- /dev/null +++ b/drivers/interrupt_controller/Kconfig.tms570_vim @@ -0,0 +1,11 @@ +# Copyright (C) 2025 ispace, inc. +# +# SPDX-License-Identifier: Apache-2.0 + +config TMS570_VIM + bool "TI Vectored Interrupt Manager (TMS570)" + default y + depends on DT_HAS_TI_TMS570_VIM_ENABLED + help + The TI Vectored Interrupt Manager provides hardware assistance for prioritizing + and aggregating the interrupt sources for TI herules ARM Cortex-R4/R5 processor cores. diff --git a/drivers/interrupt_controller/intc_tms570_vim.c b/drivers/interrupt_controller/intc_tms570_vim.c new file mode 100644 index 0000000000000..48178fad0a134 --- /dev/null +++ b/drivers/interrupt_controller/intc_tms570_vim.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "soc_internal.h" +#include + +#define DT_DRV_COMPAT ti_tms570_vim + +#define DRV_CONTROL_REG DT_INST_REG_ADDR_BY_IDX(0, 0) +#define DRV_ECC_REG DT_INST_REG_ADDR_BY_IDX(0, 1) +#define DRV_VIMRAM_REG DT_INST_REG_ADDR_BY_IDX(0, 2) +#define DRV_VIMRAM_REG_SIZE DT_INST_REG_SIZE_BY_IDX(0, 2) + +/* control registers */ +#define VIM_REG_IRQINDEX (DRV_CONTROL_REG + 0x00) +#define VIM_REG_FIQINDEX (DRV_CONTROL_REG + 0x04) +#define VIM_REG_REQMASKSET_0 (DRV_CONTROL_REG + 0x30) +#define VIM_REG_REQMASKCLR_0 (DRV_CONTROL_REG + 0x40) + +/* ECC related registers */ +#define VIM_ECC_CTL (DRV_ECC_REG + 0xF0) + +#define REQUMASK_IRQ_PER_REG (32u) + +static inline void set_reqmask_bit(unsigned int irq, uintptr_t reg_0_addr) +{ + sys_write32(1 << (irq % REQUMASK_IRQ_PER_REG), + reg_0_addr + (irq / REQUMASK_IRQ_PER_REG) * sizeof(uint32_t)); +} + +static inline int get_reqmask_bit(unsigned int irq, uintptr_t reg_0_addr) +{ + return sys_read32(reg_0_addr + (irq / REQUMASK_IRQ_PER_REG) * sizeof(uint32_t)); +} + +/* count of number of times the phantom interrupt happened */ +unsigned int nr_phantom_isr; + +static void phantom_isr(void) +{ + /** + * we don't want this to call the z_spurious_irq because we have seen + * phantom irq happen even though we don't expect it to happen. + */ + nr_phantom_isr++; +} + +#if defined(CONFIG_RUNTIME_NMI) +static void tms570_nmi_handler(void) +{ + uint32_t vec = sys_read32(REG_ESM_IOFFHR) - 1; + + if (vec < 32) { + sys_write32(1 << vec, REG_ESM_SR1_0); + printk("\nESM Group 1 chan %u\n", vec); + } else if (vec < 64) { + sys_write32(1 << (vec - 32), REG_ESM_SR1_1); + printk("\nESM Group 2 chan %u\n", vec - 32); + } else if (vec < 96U) { + sys_write32(1 << (vec - 64), REG_ESM_SR4_0); + printk("\nESM Group 1 chan %u\n", vec - 32); + } else if ((vec >= 128U) && (vec < 160U)) { + sys_write32(1 << (vec - 128), REG_ESM_SR7_0); + printk("\nESM Group 1 chan %u\n", vec - 96); + } else { + sys_write32(0xFFFFFFFF, REG_ESM_SR7_0); + sys_write32(0xFFFFFFFF, REG_ESM_SR4_0); + sys_write32(0xFFFFFFFF, REG_ESM_SR1_0); + sys_write32(0xFFFFFFFF, REG_ESM_SR1_1); + } + + sys_reboot(SYS_REBOOT_WARM); +} +#endif + +/** + * @brief Get active interrupt ID (IRQ only) + * + * @return Returns the ID of an active interrupt + */ +unsigned int z_soc_irq_get_active(void) +{ + unsigned int irq_idx; + + /* a 0 means phantom ISR, channel 0 starts from index 1 */ + irq_idx = sys_read32(VIM_REG_IRQINDEX); + if (irq_idx > 0) { + z_soc_irq_disable(irq_idx - 1); + return irq_idx - 1; + + } else { + phantom_isr(); + } + + return (CONFIG_NUM_IRQS + 1); +} + +void z_soc_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) +{ + /** + * not supported, all IRQ sources generate IRQ, instead of FIQ, + * and with the default priority. + */ +} + +void z_soc_irq_enable(unsigned int irq) +{ + set_reqmask_bit(irq, VIM_REG_REQMASKSET_0); +} + +void z_soc_irq_disable(unsigned int irq) +{ + set_reqmask_bit(irq, VIM_REG_REQMASKCLR_0); +} + +int z_soc_irq_is_enabled(unsigned int irq) +{ + return get_reqmask_bit(irq, VIM_REG_REQMASKSET_0); +} + +/** + * @brief Signal end-of-interrupt + * + * @param irq interrupt ID + */ +void z_soc_irq_eoi(unsigned int irq) +{ + z_soc_irq_enable(irq); +} + +void z_soc_irq_init(void) +{ + /** + * ref. SPNA218.pdf + * We are implementing what is referred to as "Legacy ARM7 Interrupts". + * We do not use the VIM_RAM at all. + * Sequence is like this: + * 1. Interrupt request happens + * 2. Exception vector 0x18 (IRQ) or 0x1C (FIQ) is taken + * - in case of IRQ "ldr pc, =_isr_wrapper" + * - in case of FIQ "ldr pc, =z_arm_nmi" + * 3. _isr_wrapper uses z_soc_irq_get_active to get index into + * _sw_isr_table for arg and ISR handler + * 4. run ISR handler + * + * Drivers attach interrupts using IRQ_CONNECT/IRQ_DIRECT_CONNECT like: + * IRQ_CONNECT(irqnum, irqnum, z_irq_spurious, NULL, 0); + */ + + /* Errata VIM#28 Workaround: Disable Single Bit error correction */ + sys_write32((0xAU << 0U) | (0x5U << 16U), VIM_ECC_CTL); + + /** + * We do not use VIM RAM, or need to care about ECC, but if we do not set + * the VIM RAM locations to a _valid_ memory address (memset to 0 doesn't work), + * it keeps generating ESM NMI with ESM group 1 status = 0x80008000. + * Doing the following stops it. + */ + uint32_t *p = (void *) DRV_VIMRAM_REG; + + for (int i = 0; i < DRV_VIMRAM_REG_SIZE / 4; i++) { + *(p + i) = (uint32_t) &z_irq_spurious; + } + +#if defined(CONFIG_RUNTIME_NMI) + z_arm_nmi_set_handler(tms570_nmi_handler); +#endif + + /* enable interrupt */ + arch_irq_unlock(0); +} diff --git a/dts/arm/ti/tms570.dtsi b/dts/arm/ti/tms570.dtsi index 2763d3b76c0da..dbceb1ec41658 100644 --- a/dts/arm/ti/tms570.dtsi +++ b/dts/arm/ti/tms570.dtsi @@ -94,6 +94,17 @@ status = "okay"; }; + vim: interrupt-controller@fffffe00 { + compatible = "ti,tms570-vim"; + reg = <0xfffffe00 0x00000100>, /* VIM control */ + <0xfffffd00 0x00000100>, /* ECC related */ + <0xfff82000 128>; /* VIM_RAM */ + status = "okay"; + interrupt-controller; + #interrupt-cells = <2>; + #address-cells = <1>; + }; + sci1: uart@fff7e400 { compatible = "ti,tms570-uart"; reg = <0xfff7e400 256>; diff --git a/dts/bindings/interrupt-controller/ti,tms570-vim.yaml b/dts/bindings/interrupt-controller/ti,tms570-vim.yaml new file mode 100644 index 0000000000000..e4e834e62ed26 --- /dev/null +++ b/dts/bindings/interrupt-controller/ti,tms570-vim.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +description: VIM for TMS570 + +compatible: "ti,tms570-vim" + +include: [interrupt-controller.yaml, base.yaml] + + +properties: + # NOTE: Register ranges: + # - 0 : VIM control registers + # - 1 : VIM ECC related registers + # - 2 : VIM RAM + reg: + required: true + + "#interrupt-cells": + const: 2 + +interrupt-cells: + - irq + - priority diff --git a/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig b/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig index 9207b360f66f6..0c42a3b66861f 100644 --- a/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig +++ b/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig @@ -4,18 +4,30 @@ if SOC_TI_TMS570LC43X config SYS_CLOCK_EXISTS - default n + default y -config MULTITHREADING +config DYNAMIC_INTERRUPTS default n config GEN_SW_ISR_TABLE - default n + default y config GEN_ISR_TABLES + default y + +config GEN_IRQ_VECTOR_TABLE default n -# launchpad is 16MHz +config USE_SWITCH + default n + +config RUNTIME_NMI + default y + +# 10ms OS tick from a 1MHz free-running clock +config SYS_CLOCK_TICKS_PER_SEC + default 100 + config SYS_CLOCK_HW_CYCLES_PER_SEC default $(dt_node_int_prop_int,/soc/rti,clock-frequency) From eb39308b46a8e409d1ef42a93202fb6cbc4b65a7 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Wed, 23 Apr 2025 13:56:28 +0900 Subject: [PATCH 5/8] drivers: timer: add TMS570 RTI timer as system timer Adds the RTI timer for TI TMS570 SoC and enables it as the system timer for enabling multithreading. Signed-off-by: Tavish Naruka --- drivers/timer/CMakeLists.txt | 1 + drivers/timer/Kconfig | 1 + drivers/timer/Kconfig.tms570_rti_timer | 11 ++ drivers/timer/tms570_rti_timer.c | 121 ++++++++++++++++++ dts/arm/ti/tms570.dtsi | 8 ++ dts/bindings/timer/ti,tms570-rti.yaml | 16 +++ .../hercules/ti_tms570lc43x/Kconfig.defconfig | 5 +- 7 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 drivers/timer/Kconfig.tms570_rti_timer create mode 100644 drivers/timer/tms570_rti_timer.c create mode 100644 dts/bindings/timer/ti,tms570-rti.yaml diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index a354de5e35e31..bbd5895a8cf7a 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -41,6 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_SAM0_RTC_TIMER sam0_rtc_timer.c) zephyr_library_sources_ifdef(CONFIG_SILABS_SLEEPTIMER_TIMER silabs_sleeptimer_timer.c) zephyr_library_sources_ifdef(CONFIG_STM32_LPTIM_TIMER stm32_lptim_timer.c) zephyr_library_sources_ifdef(CONFIG_TI_DM_TIMER ti_dmtimer.c) +zephyr_library_sources_ifdef(CONFIG_TMS570_RTI_TIMER tms570_rti_timer.c) zephyr_library_sources_ifdef(CONFIG_XLNX_PSTTC_TIMER xlnx_psttc_timer.c) zephyr_library_sources_ifdef(CONFIG_XTENSA_TIMER xtensa_sys_timer.c) zephyr_library_sources_ifdef(CONFIG_SMARTBOND_TIMER smartbond_timer.c) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 1cb165f329ff8..68e28daa5246e 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -99,6 +99,7 @@ source "drivers/timer/Kconfig.silabs" source "drivers/timer/Kconfig.smartbond" source "drivers/timer/Kconfig.stm32_lptim" source "drivers/timer/Kconfig.ti_dm_timer" +source "drivers/timer/Kconfig.tms570_rti_timer" source "drivers/timer/Kconfig.xlnx_psttc" source "drivers/timer/Kconfig.xtensa" source "drivers/timer/Kconfig.mtk_adsp" diff --git a/drivers/timer/Kconfig.tms570_rti_timer b/drivers/timer/Kconfig.tms570_rti_timer new file mode 100644 index 0000000000000..c8438c0863691 --- /dev/null +++ b/drivers/timer/Kconfig.tms570_rti_timer @@ -0,0 +1,11 @@ +# Copyright (C) 2025 ispace, inc. +# +# SPDX-License-Identifier: Apache-2.0 + +config TMS570_RTI_TIMER + bool "TI TMS570 RTI Timer" + default y + depends on SOC_TI_TMS570LC43X + help + This module implements a kernel device driver for the TI TMS570 RTI + timer. diff --git a/drivers/timer/tms570_rti_timer.c b/drivers/timer/tms570_rti_timer.c new file mode 100644 index 0000000000000..ad95ef8ba01a4 --- /dev/null +++ b/drivers/timer/tms570_rti_timer.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT ti_tms570_rti + +#define REG_RTI DT_INST_REG_ADDR_BY_IDX(0, 0) +#define RTI_CLK_FREQ DT_PROP(DT_NODELABEL(clk_rticlk), clock_frequency) + +#define RTI_INTFLAG_COMP0 BIT(0) +#define RTI_INTENA_COMP0 BIT(0) + +#define RTI_INTCLR_ALL (BIT(18) | BIT(17) | BIT(16) | \ + BIT(3) | BIT(2) | BIT(1) | BIT(0)) + +#define RTIGCTRL (REG_RTI + 0x00) +#define RTITBCTRL (REG_RTI + 0x04) +#define RTICAPCTRL (REG_RTI + 0x08) +#define RTICOMPCTRL (REG_RTI + 0x0C) +#define RTISETINTENA (REG_RTI + 0x80) +#define RTICLEARINTENA (REG_RTI + 0x84) +#define RTIINTFLAG (REG_RTI + 0x88) +#define RTIFRC0 (REG_RTI + 0x10) +#define RTIUC0 (REG_RTI + 0x14) +#define RTICPUC0 (REG_RTI + 0x18) +#define RTICAFRC0 (REG_RTI + 0x20) +#define RTICAUC0 (REG_RTI + 0x24) +#define RTICOMP0 (REG_RTI + 0x50) +#define RTIUDCP0 (REG_RTI + 0x54) + +#define RTIGCTRL_COS_OFFSET (15) +#define CNT1EN BIT(1) +#define CNT0EN BIT(0) + +static struct k_spinlock ticks_lock; +static volatile uint64_t ticks; + +uint32_t sys_clock_elapsed(void) +{ + return 0; +} + +uint32_t sys_clock_cycle_get_32(void) +{ + return sys_read32(RTIFRC0); +} + +static void rti_compare0_isr(const void *arg) +{ + ARG_UNUSED(arg); + + K_SPINLOCK(&ticks_lock) { + ticks += k_ticks_to_cyc_floor32(1); + } + + sys_write32(RTI_INTFLAG_COMP0, RTIINTFLAG); + sys_clock_announce(1); +} + +static int rti_timer_init(void) +{ + /** + * TODO Counter block 0 can be synchronized with Network Time (NTU), + * we can make use of that. + */ + + /* disable counters and interrupts */ + sys_write32(1 << RTIGCTRL_COS_OFFSET, RTIGCTRL); + sys_write32(RTI_INTCLR_ALL, RTICLEARINTENA); + + /** + * We use counter 0 and compare register 0. + */ + + /* default compare control and capture control */ + sys_write32(0, RTICOMPCTRL); + sys_write32(0, RTICAPCTRL); + + /* Initialize counter 0 */ + sys_write32(0, RTIUC0); + sys_write32(0, RTIFRC0); + sys_write32(0, RTITBCTRL); + + /** + * Set up free running counter interrupt cycle. + * UCx - up-counter or prescale counter - driven by RTICLK + * CPUCx - compare up-counter, it acts like a prescaler over UCx + * FRCx - when CPUCx value matches UCx, this reg is incremented by one + * COMPx - this is compared with FRCx, a match generates an interrupt + * UDCPx - UDCPx is added to COMPx when a match occues (COMPx matches FRCx), + * so that we can generate periodic interrupts1 + */ + sys_write32(RTI_CLK_FREQ / CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC - 1U, RTICPUC0); + /* free running counter, compare match period = 10 ms */ + sys_write32(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC, RTICOMP0); + sys_write32(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC, RTIUDCP0); + + /* Clear all pending interrupts */ + sys_write32(RTI_INTCLR_ALL, RTIINTFLAG); + + /* connect irq */ + IRQ_CONNECT(IRQ_RTI_COMPARE_0, IRQ_RTI_COMPARE_0, rti_compare0_isr, NULL, 0); + irq_enable(IRQ_RTI_COMPARE_0); + + /* Enable interrupt */ + sys_write32(RTI_INTENA_COMP0, RTISETINTENA); + /* Enable timer */ + sys_write32(sys_read32(RTIGCTRL) | CNT1EN | CNT0EN, RTIGCTRL); + + return 0; +} + +SYS_INIT(rti_timer_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/dts/arm/ti/tms570.dtsi b/dts/arm/ti/tms570.dtsi index dbceb1ec41658..4728a23625838 100644 --- a/dts/arm/ti/tms570.dtsi +++ b/dts/arm/ti/tms570.dtsi @@ -70,6 +70,14 @@ <0xFFA04000 0x10>; /* POM_CONTROL_BASE */ }; + rti: rti@fffffc00 { + compatible = "ti,tms570-rti"; + reg = <0xfffffc00 256>; + clock-frequency = ; + tick-frequency = <100>; + status = "okay"; + }; + sram0: memory@8000000 { compatible = "mmio-sram"; reg = <0x08000000 DT_SIZE_K(512)>; diff --git a/dts/bindings/timer/ti,tms570-rti.yaml b/dts/bindings/timer/ti,tms570-rti.yaml new file mode 100644 index 0000000000000..6e1c4d4ed3679 --- /dev/null +++ b/dts/bindings/timer/ti,tms570-rti.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Real-time interrupt for TMS570 + +compatible: "ti,tms570-rti" + +include: [base.yaml] + +properties: + clock-frequency: + type: int + description: Clock frequency of RTI up counter + tick-frequency: + type: int + description: Frequency of RTI interrupt for system tick diff --git a/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig b/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig index 0c42a3b66861f..c58a3665a445a 100644 --- a/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig +++ b/soc/ti/hercules/ti_tms570lc43x/Kconfig.defconfig @@ -24,12 +24,11 @@ config USE_SWITCH config RUNTIME_NMI default y -# 10ms OS tick from a 1MHz free-running clock config SYS_CLOCK_TICKS_PER_SEC - default 100 + default $(dt_node_int_prop_int,/soc/rti@fffffc00,tick-frequency) config SYS_CLOCK_HW_CYCLES_PER_SEC - default $(dt_node_int_prop_int,/soc/rti,clock-frequency) + default $(dt_node_int_prop_int,/soc/rti@fffffc00,clock-frequency) config NUM_IRQS # must be >= the highest interrupt number used From 9f417c3301389d4d6175a4415e294feaede25b24 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Wed, 23 Apr 2025 13:59:10 +0900 Subject: [PATCH 6/8] drivers: gpio: add TMS570 gpio driver Adds TI TMS570 SoC GPIO driver. Signed-off-by: Tavish Naruka --- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 1 + drivers/gpio/Kconfig.tms570 | 9 ++ drivers/gpio/gpio_tms570.c | 209 ++++++++++++++++++++++++++ dts/arm/ti/tms570.dtsi | 24 +++ dts/bindings/gpio/ti,tms570-gpio.yaml | 25 +++ 6 files changed, 269 insertions(+) create mode 100644 drivers/gpio/Kconfig.tms570 create mode 100644 drivers/gpio/gpio_tms570.c create mode 100644 dts/bindings/gpio/ti,tms570-gpio.yaml diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 0e1cf4155ed9a..90bdde33be1c4 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -117,6 +117,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_TCA6424A gpio_tca6424a.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TEST gpio_test.c) zephyr_library_sources_ifdef(CONFIG_GPIO_TLE9104 gpio_tle9104.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_TMS570 gpio_tms570.c) zephyr_library_sources_ifdef(CONFIG_GPIO_WCH_GPIO wch_gpio_ch32v00x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_XEC gpio_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_GPIO_XEC_V2 gpio_mchp_xec_v2.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 87271f0ff9411..c55def55b75d8 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -197,6 +197,7 @@ source "drivers/gpio/Kconfig.sy1xx" source "drivers/gpio/Kconfig.tca6424a" source "drivers/gpio/Kconfig.test" source "drivers/gpio/Kconfig.tle9104" +source "drivers/gpio/Kconfig.tms570" source "drivers/gpio/Kconfig.wch_ch32v00x" source "drivers/gpio/Kconfig.xec" source "drivers/gpio/Kconfig.xlnx" diff --git a/drivers/gpio/Kconfig.tms570 b/drivers/gpio/Kconfig.tms570 new file mode 100644 index 0000000000000..1ebe303394127 --- /dev/null +++ b/drivers/gpio/Kconfig.tms570 @@ -0,0 +1,9 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_TMS570 + bool "TMS570 GPIO driver" + default y + depends on DT_HAS_TI_TMS570_GPIO_ENABLED + help + Enable driver for the TI TMS570 GPIO controller. diff --git a/drivers/gpio/gpio_tms570.c b/drivers/gpio/gpio_tms570.c new file mode 100644 index 0000000000000..3262c4848851c --- /dev/null +++ b/drivers/gpio/gpio_tms570.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_tms570_gpio + +#include +#include +#include +#include +#include + +/* port registers */ +#define REG_DIR 0x0000 /* Data Direction Register */ +#define REG_DIN 0x0004 /* Data Input Register */ +#define REG_DOUT 0x0008 /* Data Output Register */ +#define REG_DSET 0x000C /* Data Output Set Register */ +#define REG_DCLR 0x0010 /* Data Output Clear Register */ +#define REG_PDR 0x0014 /* Open Drain Register */ +#define REG_PULDIS 0x0018 /* Pullup Disable Register */ +#define REG_PSL 0x001C /* Pull Up/Down Selection Register */ + +/* GIO base registers */ +#define REG_GCR0 0x0000 /* Global Control Register */ +#define REG_INTDET 0x0008 /* Interrupt Detect Register*/ +#define REG_POL 0x000C /* Interrupt Polarity Register */ +#define REG_ENASET 0x0010 /* Interrupt Enable Set Register */ +#define REG_ENACLR 0x0014 /* Interrupt Enable Clear Register */ +#define REG_LVLSET 0x0018 /* Interrupt Priority Set Register */ +#define REG_LVLCLR 0x001C /* Interrupt Priority Clear Register */ +#define REG_FLG 0x0020 /* Interrupt Flag Register */ +#define REG_OFF1 0x0024 /* Interrupt Offset A Register */ +#define REG_OFF2 0x0028 /* Interrupt Offset B Register */ +#define REG_EMU1 0x002C /* Emulation 1 Register */ +#define REG_EMU2 0x0030 /* Emulation 2 Register */ + +struct gpio_tms570_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + uint32_t reg_gio; + uint32_t reg_port; +}; + +struct gpio_tms570_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; +}; + +static int gpio_tms570_set_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_tms570_config *config = dev->config; + + sys_write32(pins, config->reg_port + REG_DSET); + + return 0; +} + +static int gpio_tms570_clear_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_tms570_config *config = dev->config; + uint32_t val; + + val = sys_read32(config->reg_port + REG_DIN); + sys_write32(val & pins, config->reg_port + REG_DCLR); + + return 0; +} + +static int gpio_tms570_port_set_masked_raw(const struct device *dev, + gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_tms570_config *config = dev->config; + uint32_t cur_out; + uint32_t cur_dir; + uint32_t val_set; + uint32_t val_clr; + + cur_out = sys_read32(config->reg_port + REG_DIN); + cur_dir = sys_read32(config->reg_port + REG_DIR); + val_clr = cur_dir & cur_out & ~value & mask; + val_set = cur_dir & ~cur_out & value & mask; + + sys_write32(val_clr, config->reg_port + REG_DCLR); + sys_write32(val_set, config->reg_port + REG_DSET); + + return 0; +} + +static int gpio_tms570_port_toggle_bits(const struct device *dev, + gpio_port_pins_t pins) +{ + const struct gpio_tms570_config *config = dev->config; + uint32_t cur_out; + uint32_t cur_dir; + uint32_t val_set; + uint32_t val_clr; + + cur_out = sys_read32(config->reg_port + REG_DIN); + cur_dir = sys_read32(config->reg_port + REG_DIR); + val_clr = cur_dir & cur_out & pins; + val_set = cur_dir & ~cur_out & pins; + sys_write32(val_clr, config->reg_port + REG_DCLR); + sys_write32(val_set, config->reg_port + REG_DSET); + + return 0; +} + + +static int gpio_tms570_get(const struct device *dev, gpio_port_value_t *value) +{ + const struct gpio_tms570_config *config = dev->config; + + *value = sys_read32(config->reg_port + REG_DIN); + + return 0; +} + +static int gpio_tms570_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_tms570_config *config = dev->config; + uint32_t current_config; + int ret; + + /* Read the current configuration of the pins */ + current_config = sys_read32(config->reg_port + REG_DIR); + + /* We only support changes in the direction of the pins */ + if ((flags & GPIO_INPUT) != 0U) { + /* Pins specified as input will have their DIR register's bit set to 0 */ + sys_write32(current_config & ~BIT(pin), config->reg_port + REG_DIR); + } else if ((flags & GPIO_OUTPUT) != 0U) { + /* Pins specified as output will have their DIR register's bit set to 1 */ + sys_write32(current_config | BIT(pin), config->reg_port + REG_DIR); + + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) { + ret = gpio_tms570_set_bits(dev, (gpio_port_pins_t)BIT(pin)); + if (ret < 0) { + return ret; + } + } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) { + ret = gpio_tms570_clear_bits(dev, (gpio_port_pins_t)BIT(pin)); + if (ret < 0) { + return ret; + } + } + } else { + return -EINVAL; + } + + return 0; +} + +static int gpio_tms570_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + return -ENOTSUP; +} + +static int gpio_tms570_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + return -ENOTSUP; +} + +static const struct gpio_driver_api gpio_tms570_api = { + .port_get_raw = gpio_tms570_get, + .port_set_masked_raw = gpio_tms570_port_set_masked_raw, + .port_set_bits_raw = gpio_tms570_set_bits, + .port_clear_bits_raw = gpio_tms570_clear_bits, + .pin_configure = gpio_tms570_configure, + .port_toggle_bits = gpio_tms570_port_toggle_bits, + .pin_interrupt_configure = gpio_tms570_pin_interrupt_configure, + .manage_callback = gpio_tms570_manage_callback, +}; + +static int gpio_tms570_init(const struct device *dev) +{ + const struct gpio_tms570_config *config = dev->config; + static int gpio_tms570_init_done; + + if (gpio_tms570_init_done == 0) { + gpio_tms570_init_done = 1; + sys_write32(1, config->reg_gio + REG_GCR0); + sys_write32(0xFFU, config->reg_gio + REG_ENACLR); + sys_write32(0xFFU, config->reg_gio + REG_LVLCLR); + } + + return 0; +} + +#define TMS570_GPIO_INIT(n) \ + static struct gpio_tms570_data gpio_tms570_data_##n = { \ + }; \ + static struct gpio_tms570_config gpio_tms570_config_##n = { \ + .common = { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .reg_port = DT_INST_REG_ADDR_BY_IDX(n, 0), \ + .reg_gio = DT_INST_REG_ADDR_BY_IDX(n, 1), \ + }; \ + DEVICE_DT_INST_DEFINE(n, gpio_tms570_init, NULL, \ + &gpio_tms570_data_##n, &gpio_tms570_config_##n, \ + POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_tms570_api); + +DT_INST_FOREACH_STATUS_OKAY(TMS570_GPIO_INIT) diff --git a/dts/arm/ti/tms570.dtsi b/dts/arm/ti/tms570.dtsi index 4728a23625838..0c11def4982ad 100644 --- a/dts/arm/ti/tms570.dtsi +++ b/dts/arm/ti/tms570.dtsi @@ -124,5 +124,29 @@ reg = <0xfff7e500 256>; status = "disabled"; }; + + gpio_a: gpio@fff7bc34 { + compatible = "ti,tms570-gpio"; + reg = <0xfff7bc34 0x34 /* GIO port base */ + 0xfff7bc00 0x20>; /* GIO base */ + interrupts = <13 0>; + interrupt-parent = <&vim>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + status = "okay"; + }; + + gpio_b: gpio@fff7bc54 { + compatible = "ti,tms570-gpio"; + reg = <0xfff7bc54 0x34 /* GIO port base */ + 0xfff7bc00 0x20>; /* GIO base */ + interrupts = <13 0>; + interrupt-parent = <&vim>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + status = "okay"; + }; }; }; diff --git a/dts/bindings/gpio/ti,tms570-gpio.yaml b/dts/bindings/gpio/ti,tms570-gpio.yaml new file mode 100644 index 0000000000000..ef3b21812028c --- /dev/null +++ b/dts/bindings/gpio/ti,tms570-gpio.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2025 ispace, inc. +# SPDX-License-Identifier: Apache-2.0 + +description: TMS570 GPIO + +compatible: "ti,tms570-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + # NOTE: Register ranges: + # - 0 : GIO port registers + # - 1 : GIO base registers + reg: + required: true + + interrupt-parent: + required: true + + ngpios: + required: true + +gpio-cells: + - pin + - flags From ae25f5aaa4bec4b23fd9e4f2a3dd4f811d1ea901 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Wed, 26 Mar 2025 18:24:41 +0900 Subject: [PATCH 7/8] boards: ti: tms570_launchxl2: add new board Adds minimal config for TI TMS570 launchpad which has the TMS570LC43 SoC. Signed-off-by: Tavish Naruka --- .../tms570_launchxl2/Kconfig.tms570_launchxl2 | 6 ++ boards/ti/tms570_launchxl2/board.yml | 6 ++ .../ti/tms570_launchxl2/tms570_launchxl2.dts | 61 +++++++++++++++++++ .../tms570_launchxl2_defconfig | 5 ++ 4 files changed, 78 insertions(+) create mode 100644 boards/ti/tms570_launchxl2/Kconfig.tms570_launchxl2 create mode 100644 boards/ti/tms570_launchxl2/board.yml create mode 100644 boards/ti/tms570_launchxl2/tms570_launchxl2.dts create mode 100644 boards/ti/tms570_launchxl2/tms570_launchxl2_defconfig diff --git a/boards/ti/tms570_launchxl2/Kconfig.tms570_launchxl2 b/boards/ti/tms570_launchxl2/Kconfig.tms570_launchxl2 new file mode 100644 index 0000000000000..b709ab52ec4c9 --- /dev/null +++ b/boards/ti/tms570_launchxl2/Kconfig.tms570_launchxl2 @@ -0,0 +1,6 @@ +# Copyright (c) 2025 ispace, inc. +# +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_TMS570_LAUNCHXL2 + select SOC_TI_TMS570LC43X if BOARD_TMS570_LAUNCHXL2 diff --git a/boards/ti/tms570_launchxl2/board.yml b/boards/ti/tms570_launchxl2/board.yml new file mode 100644 index 0000000000000..492629ade64e9 --- /dev/null +++ b/boards/ti/tms570_launchxl2/board.yml @@ -0,0 +1,6 @@ +board: + name: tms570_launchxl2 + full_name: Hercules TMS570LC43x LaunchPad + vendor: ti + socs: + - name: ti_tms570lc43x diff --git a/boards/ti/tms570_launchxl2/tms570_launchxl2.dts b/boards/ti/tms570_launchxl2/tms570_launchxl2.dts new file mode 100644 index 0000000000000..dd65e6f1b3bc6 --- /dev/null +++ b/boards/ti/tms570_launchxl2/tms570_launchxl2.dts @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 ispace, inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +/dts-v1/; + +#include +#include +#include + +/ { + + model = "Hercules TMS570LC43x LaunchPad Development Kit"; + compatible = "ti,hercules-tms570-launchpad", "ti,tms570"; + + chosen { + zephyr,console = &sci1; + zephyr,shell-uart = &sci1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + aliases { + led0 = &led_b7; + }; + + leds { + compatible = "gpio-leds"; + + led_b7: led_b7 { + gpios = <&gpio_b 7 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&sci1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <>; + pinctrl-names = "default"; +}; + +&sci3 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&sci3_rx &sci3_tx>; + pinctrl-names = "default"; +}; + +&pinctrl { + sci3_rx: sci3_rx { + pinmux = <29 17>; + }; + + sci3_tx: sci3_tx { + pinmux = <31 9>; + }; +}; diff --git a/boards/ti/tms570_launchxl2/tms570_launchxl2_defconfig b/boards/ti/tms570_launchxl2/tms570_launchxl2_defconfig new file mode 100644 index 0000000000000..1deb21c2fe954 --- /dev/null +++ b/boards/ti/tms570_launchxl2/tms570_launchxl2_defconfig @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y From 3a31b700dba7d71ebdc8c0a700e6ffee948e5fb7 Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Tue, 17 Jun 2025 14:09:31 +0900 Subject: [PATCH 8/8] doc: boards: add tms570_launchxl2 board documentation Adds basic information about the board about supported peripherals. Signed-off-by: Tavish Naruka --- boards/ti/tms570_launchxl2/doc/index.rst | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 boards/ti/tms570_launchxl2/doc/index.rst diff --git a/boards/ti/tms570_launchxl2/doc/index.rst b/boards/ti/tms570_launchxl2/doc/index.rst new file mode 100644 index 0000000000000..37e842281b9d6 --- /dev/null +++ b/boards/ti/tms570_launchxl2/doc/index.rst @@ -0,0 +1,45 @@ +.. zephyr:board:: tms570_launchxl2 + +Overview +******** + +The Texas Instruments Hercules |trade| TMS570LC43x LaunchPad |trade| (LAUNCHXL2-570LC43) is a +development kit for the TMS570LC4357 MCU. + +See the `TI LAUNCHXL2-570LC43 Product Page`_ for details. + +Hardware +******** + +This development kit features the TMS570LC4357 MCU, which is a lockstep cached 300MHz +ARM® Cortex®-R5F based TMS570 series automotive-grade MCU designed to aid in the +development of ISO 26262 and IEC 61508 functional safety applications. + +The board is equipped with two LEDs, two push buttons and BoosterPack connectors +for expansion. It also includes an integrated (XDS110) debugger. + +See the `TI TMS570LC4357 Product Page`_ for additional details. + +Supported Features +================== + +.. zephyr:board-supported-hw:: + + +Programming and Debugging +************************* + +.. zephyr:board-supported-runners:: + +Programming and debugging is supported via either on-board XDS110 debugger, or +via another debugger such as the SEGGER J-Link connected on the 20 pin JTAG +connector. + +References +********** + +.. target-notes:: + +.. _TI LAUNCHXL2-570LC43 Product Page: https://www.ti.com/tool/LAUNCHXL2-570LC43 + +.. _TI TMS570LC4357 Product Page: https://www.ti.com/product/TMS570LC4357