From 43c70505085d57e09fb7b08a26dfedbad02f568e Mon Sep 17 00:00:00 2001 From: Tavish Naruka Date: Thu, 12 Jun 2025 16:46:22 +0900 Subject: [PATCH] hal: add startup code for TMS570LC43 Adds soc init code including MPU configuration and PLL errata handling for the TI Hercules family SoC TMS570LC43xx. Portions of this code were taken or adapter from Halcogen code generator. This HAL is not really complete, as the currently implemented drivers do not depend on Halcogen and so were not needed. Signed-off-by: Tavish Naruka --- CMakeLists.txt | 1 + hercules/tms570lc43/CMakeLists.txt | 13 + hercules/tms570lc43/README.md | 13 + hercules/tms570lc43/source/asm_funcs.S | 286 +++++++++++++++ hercules/tms570lc43/source/soc_init.c | 363 ++++++++++++++++++++ hercules/tms570lc43/source/soc_pll_errata.c | 227 ++++++++++++ 6 files changed, 903 insertions(+) create mode 100644 hercules/tms570lc43/CMakeLists.txt create mode 100644 hercules/tms570lc43/README.md create mode 100644 hercules/tms570lc43/source/asm_funcs.S create mode 100644 hercules/tms570lc43/source/soc_init.c create mode 100644 hercules/tms570lc43/source/soc_pll_errata.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a26bab..4788d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(simplelink) add_subdirectory(simplelink_lpf3) add_subdirectory(mspm0) +add_subdirectory(hercules/tms570lc43) diff --git a/hercules/tms570lc43/CMakeLists.txt b/hercules/tms570lc43/CMakeLists.txt new file mode 100644 index 0000000..16f150e --- /dev/null +++ b/hercules/tms570lc43/CMakeLists.txt @@ -0,0 +1,13 @@ +if(CONFIG_HAS_TMS570_HALCOGEN_CODE) + zephyr_include_directories( + include + ) + + zephyr_library() + zephyr_library_compile_definitions(${COMPILER}) + zephyr_library_sources( + source/soc_init.c + source/asm_funcs.S + source/soc_pll_errata.c + ) +endif() \ No newline at end of file diff --git a/hercules/tms570lc43/README.md b/hercules/tms570lc43/README.md new file mode 100644 index 0000000..5d7898d --- /dev/null +++ b/hercules/tms570lc43/README.md @@ -0,0 +1,13 @@ +Halcogen exported code for TMS570LC43xx MCU +=========================================== + +There is no HAL available from TI to download and include for TMS570 +or hercules series per se, we have code generated by their tool Halcogen +fo this family if chips. + +This directory contains code exported and adapted from that, and the +reason to include it here is simply due to licensing of the said code. + +The modifications are mainly to make the code less verbose while still +mostly keeping it similar. The assembly portions in particular are +mostly as is. diff --git a/hercules/tms570lc43/source/asm_funcs.S b/hercules/tms570lc43/source/asm_funcs.S new file mode 100644 index 0000000..61edf99 --- /dev/null +++ b/hercules/tms570lc43/source/asm_funcs.S @@ -0,0 +1,286 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 2025 ispace, inc. + * + * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +/* Exports */ +GTEXT(_mpuInit_) +GTEXT(soc_reset_hook) + +#define MINITGCR =#0xFFFFFF5C +#define MSIENA =#0xFFFFFF60 +#define MSTCGSTAT =#0xFFFFFF68 + +#define r1Base =#0x00000000 +#define r2Base =#0x00000000 +#define r3Base =#0x08000000 +#define r4Base =#0xF8000000 +#define r5Base =#0x60000000 +#define r6Base =#0x80000000 +#define r7Base =#0xF0000000 +#define r8Base =#0x00000000 +#define r9Base =#0x00000000 +#define r10Base =#0x00000000 +#define r11Base =#0x00000000 +#define r12Base =#0x00000000 +#define r13Base =#0x00000000 +#define r14Base =#0x00000000 +#define r15Base =#0x00000000 +#define r16Base =#0xFFF80000 + +/** + * initialise memory areas (adapted from _memInit_ generated by Halcogen) + * NOTE: do not use callee saved registers + */ +SECTION_FUNC(TEXT, soc_reset_hook) + ldr r12, MINITGCR /* Load MINITGCR register address */ + mov r10, #0xA + str r10, [r12] /* Enable global memory hardware initialization */ + + ldr r11, MSIENA /* Load MSIENA register address */ + mov r10, #0x1 /* Bit position 0 of MSIENA corresponds to SRAM */ + str r10, [r11] /* Enable auto hardware initalisation for SRAM */ +mloop: /* Loop till memory hardware initialization comletes */ + ldr r9, MSTCGSTAT /* check MSTCGSTAT */ + ldr r10, [r9] + tst r10, #0x100 + beq mloop + + ldr r11, MSIENA /* Load MSIENA register address */ + mov r10, #0x4 /* Bit position 2 of MSIENA corresponds to VIM RAM */ + str r10, [r11] /* Enable auto hardware initalisation for VIM RAM */ +mloop2: /* Loop till memory hardware initialization comletes */ + ldr r9, MSTCGSTAT /* check MSTCGSTAT */ + ldr r10, [r9] + tst r10, #0x100 + beq mloop2 + + mov r10, #5 + str r10, [r12] /* Disable global memory hardware initialization */ + + /* now stack is usable */ + push {lr} + bl soc_platform_init + pop {lr} + + bx lr + +SECTION_FUNC(TEXT, _mpuInit_) + /* Disable mpu */ + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #1 + dsb + mcr p15, #0, r0, c1, c0, #0 + isb + /* Disable background region */ + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #0x20000 + mcr p15, #0, r0, c1, c0, #0 + /* Setup region 1 */ + mov r0, #0 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r1Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0008 + orr r0, r0, #0x1000 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((1 << 15) + (1 << 14) + (1 << 13) + (1 << 12) + (1 << 11) + (1 << 10) + (1 << 9) + (1 << 8) + (0x1F << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 2 */ + mov r0, #1 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r2Base + mcr p15, #0, r0, c6, c1, #0 + /* non cached flash */ + mov r0, #0x000C + /* cached flash */ + /* mov r0, #0x0002 */ + orr r0, r0, #0x0600 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x15 << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 3 */ + mov r0, #2 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r3Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x000B + orr r0, r0, #0x1300 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x12 << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 4 */ + mov r0, #3 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r4Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0010 + orr r0, r0, #0x1300 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (1 << 10) + (1 << 9) + (1 << 8) + (0x1A << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 5 */ + mov r0, #4 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r5Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0000 + orr r0, r0, #0x0300 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((1 << 15) + (1 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x1B << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 6 */ + mov r0, #5 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r6Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0006 + orr r0, r0, #0x0300 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x1A << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 7 */ + mov r0, #6 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r7Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0008 + orr r0, r0, #0x1200 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x16 << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 8 */ + mov r0, #7 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r8Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0010 + orr r0, r0, #0x1200 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 9 */ + mov r0, #8 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r9Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0006 + orr r0, r0, #0x1200 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 10 */ + mov r0, #9 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r10Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x000C + orr r0, r0, #0x1300 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 11 */ + mov r0, #10 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r11Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0006 + orr r0, r0, #0x0600 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 12 */ + mov r0, #11 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r12Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0006 + orr r0, r0, #0x1600 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 13 */ + mov r0, #12 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r13Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0006 + orr r0, r0, #0x1600 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 14 */ + mov r0, #13 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r14Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0006 + orr r0, r0, #0x1600 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 15 */ + mov r0, #14 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r15Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0006 + orr r0, r0, #0x1600 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x04 << 1) + (0)) + mcr p15, #0, r0, c6, c1, #2 + /* Setup region 16 */ + mov r0, #15 + mcr p15, #0, r0, c6, c2, #0 + ldr r0, r16Base + mcr p15, #0, r0, c6, c1, #0 + mov r0, #0x0010 + orr r0, r0, #0x1200 + mcr p15, #0, r0, c6, c1, #4 + movw r0, #((0 << 15) + (0 << 14) + (0 << 13) + (0 << 12) + (0 << 11) + (0 << 10) + (0 << 9) + (0 << 8) + (0x12 << 1) + (1)) + mcr p15, #0, r0, c6, c1, #2 + + /* Enable mpu */ + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #1 + dsb + mcr p15, #0, r0, c1, c0, #0 + isb + bx lr diff --git a/hercules/tms570lc43/source/soc_init.c b/hercules/tms570lc43/source/soc_init.c new file mode 100644 index 0000000..446f052 --- /dev/null +++ b/hercules/tms570lc43/source/soc_init.c @@ -0,0 +1,363 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 2025 ispace, inc. + * + * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include "soc_internal.h" +#include "soc_defaults.h" + +#define TMS570_RST_BIT (0x02 << 14) + +void sys_arch_reboot(int type) +{ + /* clear the reset reason before going into reset */ + sys_write32(0xFFFF, REG_SYSESR); + + /* we need to disable POM register before we reset CPU */ + sys_write32(0, REG_POMGLBCTRL); + sys_write32(TMS570_RST_BIT, REG_SYSECR); +} + +static void system_init(void) +{ + uint32_t _csvstat, _csdis, _clkcntl; + + /* disable PLL1 and PLL2 */ + sys_write32(CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2, REG_SYS1_CSDISSET); + while ((sys_read32(REG_SYS1_CSDIS) & (CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2)) + != (CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2)) { + /* wait */ + } + + sys_write32((GLBSTAT_OSCFAIL | GLBSTAT_RFSLIP | GLBSTAT_FBSLIP), + REG_SYS1_GBLSTAT); + sys_write32(PLLCTL1_INIT_VALUE, REG_SYS1_PLLCTL1); + sys_write32(PLLCTL2_INIT_VALUE, REG_SYS1_PLLCTL2); + sys_write32(PLLCTL3_INIT_VALUE, REG_SYS2_PLLCTL3); + + /* Enable PLL(s) to start up or Lock */ + sys_write32((~(CSDIS_SRC_OSC | CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2 | + CSDIS_SRC_LFLPO | CSDIS_SRC_HFLPO)) & CSDIS_SRC_MASK, + REG_SYS1_CSDIS); + sys_write32(CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2, REG_SYS1_CSDISCLR); + + /* Disable Peripherals before peripheral powerup */ + sys_write32(sys_read32(REG_SYS1_CLKCNTL) & ~CLKCNTL_PENA, + REG_SYS1_CLKCNTL); + + /* Release peripherals from reset, enable clocks to all peripherals */ + /* Power-up all peripherals */ + sys_write32(0xffffffff, REG_PCR1_PSPWRDWNCLR0); + sys_write32(0xffffffff, REG_PCR1_PSPWRDWNCLR1); + sys_write32(0xffffffff, REG_PCR1_PSPWRDWNCLR2); + sys_write32(0xffffffff, REG_PCR1_PSPWRDWNCLR3); + + sys_write32(0xffffffff, REG_PCR2_PSPWRDWNCLR0); + sys_write32(0xffffffff, REG_PCR2_PSPWRDWNCLR1); + sys_write32(0xffffffff, REG_PCR2_PSPWRDWNCLR2); + sys_write32(0xffffffff, REG_PCR2_PSPWRDWNCLR3); + + sys_write32(0xffffffff, REG_PCR3_PSPWRDWNCLR0); + sys_write32(0xffffffff, REG_PCR3_PSPWRDWNCLR1); + sys_write32(0xffffffff, REG_PCR3_PSPWRDWNCLR2); + sys_write32(0xffffffff, REG_PCR3_PSPWRDWNCLR3); + + /* Enable Peripherals */ + sys_write32(sys_read32(REG_SYS1_CLKCNTL) | CLKCNTL_PERIPHENA, + REG_SYS1_CLKCNTL); + + /* Setup flash read mode, address wait states and data wait states */ + sys_write32(FRDCNTL_INIT_VALUE, REG_FCR_FRDCNTL); + sys_write32(FSM_WR_ENA_ENABLE_VAL, REG_FCR_FSM_WR_ENA); + sys_write32(EEPROM_CONFIG_INIT_VALUE, REG_FCR_EEPROM_CONFIG); + sys_write32(FSM_WR_ENA_DISABLE_VAL, REG_FCR_FSM_WR_ENA); + /** - Setup flash bank power modes */ + sys_write32(FBPWRMODE_INIT_VALUE, REG_FCR_FBPWRMODE); + + /* Initialize Clock Tree */ + /* Setup system clock divider for HCLK */ + sys_write32(1 << HCLKCNTL_HCLKR_OFFSET, REG_SYS2_HCLKCNTL); + /* Disable / Enable clock domain */ + sys_write32(CDDIS_VCLKA2, REG_SYS1_CDDIS); + /* Wait for until clocks are locked */ + do { + _csvstat = sys_read32(REG_SYS1_CSVSTAT); + _csdis = sys_read32(REG_SYS1_CSDIS); + } while ((_csvstat & ((_csdis ^ 0xFF) & 0xFF)) + != ((_csdis ^ 0xFFU) & 0xFFU)); + + /* + * All clock domains are working off the default clock sources until now. + * Setup GCLK, HCLK and VCLK clock source for normal operation, power down + * mode and after wakeup + */ + sys_write32(GHVSRC_INIT_VALUE, REG_SYS1_GHVSRC); + /* Setup RTICLK1 */ + sys_write32(RCLKSRC_INIT_VALUE, REG_SYS1_RCLKSRC); + /* Setup asynchronous peripheral clock sources for AVCLK1 and AVCLK2 */ + sys_write32(VCLKASRC_INIT_VALUE, REG_SYS1_VCLKASRC); + + /* Setup synchronous peripheral clock dividers for VCLK1, VCLK2, VCLK3 */ + /** + * Please check the note about VCLK and VCLK2 clock ratio + * restrictions in TRM. The default value is the same as what we are + * setting it to, but the order of setting matters, and both cannot be + * set together. + */ + _clkcntl = sys_read32(REG_SYS1_CLKCNTL); + sys_write32((1 << CLKCNTL_VCLKR_OFFSET) | (_clkcntl & ~CLKCNTL_VCLK2R_MASK), + REG_SYS1_CLKCNTL); + sys_write32((1 << CLKCNTL_VCLK2R_OFFSET) | (_clkcntl & ~CLKCNTL_VCLKR_MASK), + REG_SYS1_CLKCNTL); + sys_write32((1 << CLK2CNTRL_VCLK3R_OFFSET) | (sys_read32(REG_SYS2_CLK2CNTRL) + & ~CLK2CNTRL_VCLK3R_MASK), REG_SYS2_CLK2CNTRL); + sys_write32(VCLKACON1_INIT_VALUE, REG_SYS2_VCLKACON1); + + /* Now the PLLs are locked and the PLL outputs can be sped up */ + /* The R-divider was programmed to be 0x1F. The divider is now changed to programmed value */ + sys_write32((0 << PLLCTL1_PLLDIV_OFFSET) | (sys_read32(REG_SYS1_PLLCTL1) + & PLLCTL1_PLLDIV_MASK), REG_SYS1_PLLCTL1); + sys_write32((0 << PLLCTL3_PLLDIV2_OFFSET) | (sys_read32(REG_SYS2_PLLCTL3) + & PLLCTL3_PLLDIV2_MASK), REG_SYS2_PLLCTL3); +} + +static resetSource_t get_reset_source(void) +{ + resetSource_t rst_source; + + if ((sys_read32(REG_SYSESR) & (uint32_t)POWERON_RESET) != 0U) { + /* power-on reset condition */ + rst_source = POWERON_RESET; + /* Clear all exception status Flag and proceed since it's power up */ + sys_write32(0x0000FFFFU, REG_SYSESR); + } + + else if ((sys_read32(REG_SYSESR) & (uint32_t)EXT_RESET) != 0U) { + sys_write32((uint32_t)EXT_RESET, REG_SYSESR); + + /*** Check for other causes of EXT_RESET that would take precedence **/ + if ((sys_read32(REG_SYSESR) & (uint32_t)OSC_FAILURE_RESET) != 0U) { + /** + * Reset caused due to oscillator failure. + * Add user code here to handle oscillator failure + */ + rst_source = OSC_FAILURE_RESET; + sys_write32((uint32_t)OSC_FAILURE_RESET, REG_SYSESR); + } else if ((sys_read32(REG_SYSESR) & (uint32_t)WATCHDOG_RESET) != 0U) { + /* Reset caused due watchdog violation */ + rst_source = WATCHDOG_RESET; + sys_write32((uint32_t)WATCHDOG_RESET, REG_SYSESR); + } else if ((sys_read32(REG_SYSESR) & (uint32_t)WATCHDOG2_RESET) != 0U) { + /* Reset caused due watchdog violation */ + rst_source = WATCHDOG2_RESET; + sys_write32((uint32_t)WATCHDOG2_RESET, REG_SYSESR); + } else if ((sys_read32(REG_SYSESR) & (uint32_t)SW_RESET) != 0U) { + /* Reset caused due to software reset. */ + rst_source = SW_RESET; + sys_write32((uint32_t)SW_RESET, REG_SYSESR); + } else { + /* Reset caused due to External reset. */ + rst_source = EXT_RESET; + } + } else if ((sys_read32(REG_SYSESR) & (uint32_t)DEBUG_RESET) != 0U) { + /* Reset caused due Debug reset request */ + rst_source = DEBUG_RESET; + sys_write32((uint32_t)DEBUG_RESET, REG_SYSESR); + } else if ((sys_read32(REG_SYSESR) & (uint32_t)CPU0_RESET) != 0U) { + /** + * Reset caused due to CPU0 reset. CPU reset can be caused by CPU self-test + * completion, or by toggling the "CPU RESET" bit of the CPU Reset Control Register. + */ + rst_source = CPU0_RESET; + sys_write32((uint32_t)CPU0_RESET, REG_SYSESR); + } else { + /* No_reset occurred. */ + rst_source = NO_RESET; + } + + return rst_source; +} + +static void esm_init(void) +{ + /** - Disable error pin channels */ + sys_write32(0xFFFFFFFFU, REG_ESM_DEPAPR1); + sys_write32(0xFFFFFFFFU, REG_ESM_IEPCR4); + sys_write32(0xFFFFFFFFU, REG_ESM_IEPCR7); + + /** - Disable interrupts */ + sys_write32(0xFFFFFFFFU, REG_ESM_IECR1); + sys_write32(0xFFFFFFFFU, REG_ESM_IECR4); + sys_write32(0xFFFFFFFFU, REG_ESM_IECR7); + + /** - Clear error status flags */ + sys_write32(0xFFFFFFFFU, REG_ESM_SR1_0); + sys_write32(0xFFFFFFFFU, REG_ESM_SR1_1); + sys_write32(0xFFFFFFFFU, REG_ESM_SSR2); + sys_write32(0xFFFFFFFFU, REG_ESM_SR1_2); + sys_write32(0xFFFFFFFFU, REG_ESM_SR4_0); + sys_write32(0xFFFFFFFFU, REG_ESM_SR7_0); + + /** - Setup LPC preload */ + sys_write32(16384U - 1U, REG_ESM_LTCPR); + + /** - Reset error pin */ + if (sys_read32(REG_ESM_EPSR) == 0U) { + sys_write32(0x00000005U, REG_ESM_EKR); + } else { + sys_write32(0x00000000U, REG_ESM_EKR); + } + + /** - Clear interrupt level */ + sys_write32(0xFFFFFFFFU, REG_ESM_ILCR1); + sys_write32(0xFFFFFFFFU, REG_ESM_ILCR4); + sys_write32(0xFFFFFFFFU, REG_ESM_ILCR7); + + /** - Set interrupt level */ + sys_write32(0, REG_ESM_ILSR1); + sys_write32(0, REG_ESM_ILSR4); + sys_write32(0, REG_ESM_ILSR7); + + /** - Enable error pin channels */ + sys_write32(0, REG_ESM_EEPAPR1); + sys_write32(0, REG_ESM_IEPSR4); + sys_write32(0, REG_ESM_IEPSR7); + + /** - Enable interrupts */ + sys_write32(0, REG_ESM_IESR1); + sys_write32(0, REG_ESM_IESR4); + sys_write32(0, REG_ESM_IESR7); +} + +static void cache_enable(void) +{ + if (IS_ENABLED(CONFIG_ICACHE)) { + if (!(__get_SCTLR() & SCTLR_I_Msk)) { + L1C_InvalidateICacheAll(); + __set_SCTLR(__get_SCTLR() | SCTLR_I_Msk); + barrier_isync_fence_full(); + } + } + + if (IS_ENABLED(CONFIG_DCACHE)) { + if (!(__get_SCTLR() & SCTLR_C_Msk)) { + L1C_InvalidateDCacheAll(); + __set_SCTLR(__get_SCTLR() | SCTLR_C_Msk); + barrier_dsync_fence_full(); + } + } +} + +/** + * Enable CPU Event Export + * This allows the CPU to signal any single-bit or double-bit errors detected + * by its ECC logic for accesses to program flash or data RAM. + */ +static void event_bus_export(void) +{ + uint32_t temp; + + /* set X bit (bit 4) in cp15 PMSR */ + __get_CP(15, 0, temp, 9, 12, 0); + temp |= BIT(4); + __set_CP(15, 0, temp, 9, 12, 0); +} + +void soc_platform_init(void) +{ + const int pll_retries = 5; + resetSource_t rstSrc; + + /* XXX: removing this delay makes the CPU stuck */ + for (volatile uint64_t i = 0; i < 0xfffff; i++) { + /* wait */ + } + + rstSrc = get_reset_source(); + + switch (rstSrc) { + case POWERON_RESET: + /* Add condition to check whether PLL can be started successfully */ + if (_errata_SSWF021_45_both_plls(pll_retries) != 0U) { + /* Put system in a safe state */ + /* Handle PLL failure */ + } + + case DEBUG_RESET: + case EXT_RESET: + /** + * Check if there were ESM group3 errors during power-up. + * These could occur during eFuse auto-load or during reads from flash OTP + * during power-up. Device operation is not reliable and not recommended + * in this case. + */ + if (sys_read32(REG_ESM_SR1_2) != 0U) { + /* Handle group3 notification */ + } + + /** + * Configure system response to error conditions signaled to the ESM group1. + * This function can be configured from the ESM tab of HALCoGen + */ + esm_init(); + break; + + case OSC_FAILURE_RESET: + break; + + case WATCHDOG_RESET: + case WATCHDOG2_RESET: + break; + + case CPU0_RESET: + break; + + case SW_RESET: + break; + + default: + break; + } + + event_bus_export(); + _mpuInit_(); + cache_enable(); + system_init(); +} diff --git a/hercules/tms570lc43/source/soc_pll_errata.c b/hercules/tms570lc43/source/soc_pll_errata.c new file mode 100644 index 0000000..726ea3b --- /dev/null +++ b/hercules/tms570lc43/source/soc_pll_errata.c @@ -0,0 +1,227 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (C) 2025 ispace, inc. + * + * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "soc_internal.h" +#include "soc_defaults.h" + +#define ESM_SR1_PLL1SLIP 0x400U +#define ESM_SR4_PLL2SLIP 0x400U + +#define dcc1CNT1_CLKSRC_PLL1 0x0000A000U +#define dcc1CNT1_CLKSRC_PLL2 0x0000A001U + +enum dcc1clocksource { + DCC1_CNT0_HF_LPO = 0x5U, /**< Alias for DCC1 CNT 0 CLOCK SOURCE 0 */ + DCC1_CNT0_TCK = 0xAU, /**< Alias for DCC1 CNT 0 CLOCK SOURCE 1 */ + DCC1_CNT0_OSCIN = 0xFU, /**< Alias for DCC1 CNT 0 CLOCK SOURCE 2 */ + + DCC1_CNT1_PLL1 = 0x0U, /**< Alias for DCC1 CNT 1 CLOCK SOURCE 0 */ + DCC1_CNT1_PLL2 = 0x1U, /**< Alias for DCC1 CNT 1 CLOCK SOURCE 1 */ + DCC1_CNT1_LF_LPO = 0x2U, /**< Alias for DCC1 CNT 1 CLOCK SOURCE 2 */ + DCC1_CNT1_HF_LPO = 0x3U, /**< Alias for DCC1 CNT 1 CLOCK SOURCE 3 */ + DCC1_CNT1_EXTCLKIN1 = 0x5U, /**< Alias for DCC1 CNT 1 CLOCK SOURCE 4 */ + DCC1_CNT1_EXTCLKIN2 = 0x6U, /**< Alias for DCC1 CNT 1 CLOCK SOURCE 6 */ + DCC1_CNT1_VCLK = 0x8U, /**< Alias for DCC1 CNT 1 CLOCK SOURCE 8 */ + DCC1_CNT1_N2HET1_31 = 0xAU /**< Alias for DCC1 CNT 1 CLOCK SOURCE 9 */ +}; + +#define REG_DCC_GCTRL (DRV_DCC + 0x0000) /**< 0x0000: DCC Control */ +#define REG_DCC_REV (DRV_DCC + 0x0004) /**< 0x0004: DCC Revision Id */ +#define REG_DCC_CNT0SEED (DRV_DCC + 0x0008) /**< 0x0008: DCC Counter0 Seed */ +#define REG_DCC_VALID0SEED (DRV_DCC + 0x000C) /**< 0x000C: DCC Valid0 Seed */ +#define REG_DCC_CNT1SEED (DRV_DCC + 0x0010) /**< 0x0010: DCC Counter1 Seed */ +#define REG_DCC_STAT (DRV_DCC + 0x0014) /**< 0x0014: DCC Status */ +#define REG_DCC_CNT0 (DRV_DCC + 0x0018) /**< 0x0018: DCC Counter0 Value */ +#define REG_DCC_VALID0 (DRV_DCC + 0x001C) /**< 0x001C: DCC Valid0 Value */ +#define REG_DCC_CNT1 (DRV_DCC + 0x0020) /**< 0x0020: DCC Counter1 Value */ +#define REG_DCC_CNT1CLKSRC (DRV_DCC + 0x0024) /**< 0x0024: DCC Counter1 Clock Source */ +#define REG_DCC_CNT0CLKSRC (DRV_DCC + 0x0028) /**< 0x0028: DCC Counter0 Clock Source */ + +static uint32_t disable_plls(uint32_t plls) +{ + uint32_t timeout, failCode; + + sys_write32(plls, REG_SYS1_CSDISSET); + failCode = 0U; + timeout = 0x10U; + timeout--; + + while (((sys_read32(REG_SYS1_CSVSTAT) & (plls)) != 0U) && (timeout != 0U)) { + /* Clear ESM and GLBSTAT PLL slip flags */ + sys_write32(0x00000300U, REG_SYS1_GBLSTAT); + + if ((plls & CSDIS_SRC_PLL1) == CSDIS_SRC_PLL1) { + sys_write32(ESM_SR1_PLL1SLIP, REG_ESM_SR1_0); + } + if ((plls & CSDIS_SRC_PLL2) == CSDIS_SRC_PLL2) { + sys_write32(ESM_SR4_PLL2SLIP, REG_ESM_SR4_0); + } + + timeout--; + /* Wait */ + } + + if (timeout == 0U) { + failCode = 4U; + } else { + failCode = 0U; + } + + return failCode; +} + +static uint32_t check_frequency(uint32_t cnt1_clksrc) +{ + uint32_t val; + + /* Setup DCC1 */ + /** DCC1 Global Control register configuration */ + val = (uint32_t)0x5U | /** Disable DCC1 */ + (uint32_t)((uint32_t)0x5U << 4U) | /** No Error Interrupt */ + (uint32_t)((uint32_t)0xAU << 8U) | /** Single Shot mode */ + (uint32_t)((uint32_t)0x5U << 12U); /** No Done Interrupt */ + sys_write32(val, REG_DCC_GCTRL); + + /* Clear ERR and DONE bits */ + sys_write32(3, REG_DCC_STAT); + + /** DCC1 Clock0 Counter Seed value configuration */ + sys_write32(68U, REG_DCC_CNT0SEED); + + /** DCC1 Clock0 Valid Counter Seed value configuration */ + sys_write32(4U, REG_DCC_VALID0SEED); + + /** DCC1 Clock1 Counter Seed value configuration */ + sys_write32(972U, REG_DCC_CNT1SEED); + + /** DCC1 Clock1 Source 1 Select */ + val = (uint32_t)((uint32_t)10U << 12U) | /** DCC Enable / Disable Key */ + (uint32_t) cnt1_clksrc; /** DCC1 Clock Source 1 */ + sys_write32(val, REG_DCC_CNT1CLKSRC); + + val = (uint32_t)DCC1_CNT0_OSCIN; /** DCC1 Clock Source 0 */ + sys_write32(val, REG_DCC_CNT0CLKSRC); + + /** DCC1 Global Control register configuration */ + val = (uint32_t)0xAU | /** Enable DCC1 */ + (uint32_t)((uint32_t)0x5U << 4U) | /** No Error Interrupt */ + (uint32_t)((uint32_t)0xAU << 8U) | /** Single Shot mode */ + (uint32_t)((uint32_t)0x5U << 12U); /** No Done Interrupt */ + sys_write32(val, REG_DCC_GCTRL); + + while (sys_read32(REG_DCC_STAT) == 0U) { + /* Wait */ + } + + return (sys_read32(REG_DCC_STAT) & 0x01U); +} + +uint32_t _errata_SSWF021_45_both_plls(uint32_t count) +{ + uint32_t fail_code, retries, clk_cntl_sav; + + clk_cntl_sav = sys_read32(REG_SYS1_CLKCNTL); + + /* First set VCLK2 = HCLK */ + sys_write32(clk_cntl_sav & 0x000F0100U, REG_SYS1_CLKCNTL); + /* Now set VCLK = HCLK and enable peripherals */ + sys_write32(CLKCNTL_PENA, REG_SYS1_CLKCNTL); + + fail_code = 0U; + + for (retries = 0U; retries < count; retries++) { + fail_code = 0U; + + /* Disable PLL1 and PLL2 */ + fail_code = disable_plls(CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2); + + if (fail_code != 0U) { + break; + } + + /* Clear Global Status Register */ + sys_write32(0x00000301U, REG_SYS1_GBLSTAT); + /* Clear the ESM PLL slip flags */ + sys_write32(ESM_SR1_PLL1SLIP, REG_ESM_SR1_0); + sys_write32(ESM_SR4_PLL2SLIP, REG_ESM_SR4_0); + /* set both PLLs to OSCIN/1*27/(2*1) */ + sys_write32(0x20001A00U, REG_SYS1_PLLCTL1); + sys_write32(0x3FC0723DU, REG_SYS1_PLLCTL2); + sys_write32(0x20001A00U, REG_SYS2_PLLCTL3); + sys_write32(CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2, REG_SYS1_CSDISCLR); + + /* Check for (PLL1 valid or PLL1 slip) and (PLL2 valid or PLL2 slip) */ + while ((((sys_read32(REG_SYS1_CSVSTAT) & CSDIS_SRC_PLL1) == 0U) + && ((sys_read32(REG_ESM_SR1_0) & ESM_SR1_PLL1SLIP) == 0U)) + || (((sys_read32(REG_SYS1_CSVSTAT) & CSDIS_SRC_PLL2) == 0U) + && ((sys_read32(REG_ESM_SR4_0) & ESM_SR4_PLL2SLIP) == 0U))) { + /* Wait */ + } + + /* If PLL1 valid, check the frequency */ + if (((sys_read32(REG_ESM_SR1_0) & ESM_SR1_PLL1SLIP) != 0U) + || ((sys_read32(REG_SYS1_GBLSTAT) & 0x00000300U) != 0U)) { + fail_code |= 1U; + } else { + fail_code |= check_frequency(dcc1CNT1_CLKSRC_PLL1); + } + + /* If PLL2 valid, check the frequency */ + if (((sys_read32(REG_ESM_SR4_0) & ESM_SR4_PLL2SLIP) != 0U) + || ((sys_read32(REG_SYS1_GBLSTAT) & 0x00000300U) != 0U)) { + fail_code |= 2U; + } else { + fail_code |= (check_frequency(dcc1CNT1_CLKSRC_PLL2) << 1U); + } + + if (fail_code == 0U) { + break; + } + } + + /* To avoid MISRA violation 382S (void)missing for discarded return value */ + fail_code = disable_plls(CSDIS_SRC_PLL1 | CSDIS_SRC_PLL2); + /* restore CLKCNTL, VCLKR and PENA first */ + sys_write32(clk_cntl_sav & 0x000F0100U, REG_SYS1_CLKCNTL); + /* restore CLKCNTL, VCLK2R */ + sys_write32(clk_cntl_sav, REG_SYS1_CLKCNTL); + + return fail_code; +}