Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:39

0001 /* SPDX-License-Identifier: BSD-3-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsARMTMS570
0007  *
0008  * @brief This source file contains parts of the system initialization.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2022 Airbus U.S. Space & Defense, Inc
0013  * Copyright (C) 2016 Pavel Pisa <pisa@cmp.felk.cvut.cz>
0014  * Copyright (C) 2009-2015 Texas Instruments Incorporated - www.ti.com
0015  *
0016  *
0017  *  Redistribution and use in source and binary forms, with or without
0018  *  modification, are permitted provided that the following conditions
0019  *  are met:
0020  *
0021  *    Redistributions of source code must retain the above copyright
0022  *    notice, this list of conditions and the following disclaimer.
0023  *
0024  *    Redistributions in binary form must reproduce the above copyright
0025  *    notice, this list of conditions and the following disclaimer in the
0026  *    documentation and/or other materials provided with the
0027  *    distribution.
0028  *
0029  *    Neither the name of Texas Instruments Incorporated nor the names of
0030  *    its contributors may be used to endorse or promote products derived
0031  *    from this software without specific prior written permission.
0032  *
0033  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0034  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0035  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0036  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0037  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0038  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0039  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0040  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0041  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0042  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0043  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0044  *
0045  */
0046 
0047 #include <bsp/tms570.h>
0048 #include <bsp/tms570_hwinit.h>
0049 #include <bsp/tms570-pinmux.h>
0050 
0051 typedef enum Tms570ClockDisableSources {
0052     TMS570_CLKDIS_SRC_OSC  = 0x01, ///< External high-speed oscillator as clock source
0053     TMS570_CLKDIS_SRC_PLL1 = 0x02, 
0054     TMS570_CLKDIS_SRC_RESERVED = 0x04, ///< reserved. not tied to actual clock source
0055     TMS570_CLKDIS_SRC_EXT_CLK1 = 0x08, 
0056     TMS570_CLKDIS_SRC_LOW_FREQ_LPO = 0x10, 
0057     TMS570_CLKDIS_SRC_HIGH_FREQ_LPO = 0x20, 
0058     TMS570_CLKDIS_SRC_PLL2 = 0x40, 
0059     TMS570_CLKDIS_SRC_EXT_CLK2 = 0x80, 
0060 } Tms570ClockDisableSources;
0061 
0062 // Source selection for G, H, and V clocks SYS1.GHVSRC reg
0063 typedef enum Tms570GhvClockSources {
0064   TMS570_SYS_CLK_SRC_OSC = 0U,          /**< Alias for oscillator clock Source                */
0065   TMS570_SYS_CLK_SRC_PLL1 = 1U,         /**< Alias for Pll1 clock Source                      */
0066   TMS570_SYS_CLK_SRC_EXTERNAL1 = 3U,    /**< Alias for external clock Source                  */
0067   TMS570_SYS_CLK_SRC_LPO_LOW = 4U,      /**< Alias for low power oscillator low clock Source  */
0068   TMS570_SYS_CLK_SRC_LPO_HIGH = 5U,     /**< Alias for low power oscillator high clock Source */
0069   TMS570_SYS_CLK_SRC_PLL2 = 6U,         /**< Alias for Pll2 clock Source                      */
0070   TMS570_SYS_CLK_SRC_EXTERNAL2 = 7U,    /**< Alias for external 2 clock Source                */
0071   TMS570_SYS_CLK_SRC_VCLK = 9U          /**< Alias for synchronous VCLK1 clock Source         */
0072 } Tms570GhvClockSources;
0073 
0074 /*
0075  * The next construct allows to compute values for individual
0076  * PINMMR registers based on the multiple processing
0077  * complete pin functions list at compile time.
0078  * Each line computes 32-bit value which selects function
0079  * of consecutive four pins. Each pin function is defined
0080  * by single byte.
0081  */
0082 static const uint32_t tms570_pinmmr_init_data[] = {
0083   TMS570_PINMMR_REG_VAL( 0, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0084   TMS570_PINMMR_REG_VAL( 1, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0085   TMS570_PINMMR_REG_VAL( 2, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0086   TMS570_PINMMR_REG_VAL( 3, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0087   TMS570_PINMMR_REG_VAL( 4, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0088   TMS570_PINMMR_REG_VAL( 5, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0089   TMS570_PINMMR_REG_VAL( 6, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0090   TMS570_PINMMR_REG_VAL( 7, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0091   TMS570_PINMMR_REG_VAL( 8, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0092   TMS570_PINMMR_REG_VAL( 9, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0093   TMS570_PINMMR_REG_VAL( 10, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0094   TMS570_PINMMR_REG_VAL( 11, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0095   TMS570_PINMMR_REG_VAL( 12, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0096   TMS570_PINMMR_REG_VAL( 13, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0097   TMS570_PINMMR_REG_VAL( 14, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0098   TMS570_PINMMR_REG_VAL( 15, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0099   TMS570_PINMMR_REG_VAL( 16, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0100   TMS570_PINMMR_REG_VAL( 17, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0101   TMS570_PINMMR_REG_VAL( 18, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0102   TMS570_PINMMR_REG_VAL( 19, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0103   TMS570_PINMMR_REG_VAL( 20, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0104   TMS570_PINMMR_REG_VAL( 21, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0105   TMS570_PINMMR_REG_VAL( 22, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0106   TMS570_PINMMR_REG_VAL( 23, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0107   TMS570_PINMMR_REG_VAL( 24, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0108   TMS570_PINMMR_REG_VAL( 25, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0109   TMS570_PINMMR_REG_VAL( 26, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0110   TMS570_PINMMR_REG_VAL( 27, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0111   TMS570_PINMMR_REG_VAL( 28, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0112   TMS570_PINMMR_REG_VAL( 29, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0113   TMS570_PINMMR_REG_VAL( 30, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0114   TMS570_PINMMR_REG_VAL( 31, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0115   TMS570_PINMMR_REG_VAL( 32, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0116   TMS570_PINMMR_REG_VAL( 33, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0117   TMS570_PINMMR_REG_VAL( 34, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0118   TMS570_PINMMR_REG_VAL( 35, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0119   TMS570_PINMMR_REG_VAL( 36, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0120   TMS570_PINMMR_REG_VAL( 37, TMS570LC4357_PINMMR_DEFAULT_INIT_LIST ),
0121 };
0122 
0123 void tms570_pinmux_init( void )
0124 {
0125     tms570_bsp_pinmmr_config(tms570_pinmmr_init_data, 0, RTEMS_ARRAY_SIZE(tms570_pinmmr_init_data));
0126 
0127     tms570_pin_config_prepare();
0128     TMS570_PINMUX[174] = (TMS570_PINMUX[174] & ~(UINT32_C(0x3) << 8)) | (UINT32_C(0x2) << 8); // emif output-enable bit8= 0, bit9= 1
0129     tms570_pin_config_complete();
0130 
0131     /* Set ECLK pin to GPIO input */
0132     TMS570_SYS1.SYSPC1 = 0;
0133     TMS570_SYS1.SYSPC2 = 0;
0134 }
0135 
0136 void tms570_emif_sdram_init( void )
0137 {
0138     uint32_t dummy;
0139 
0140     /* Do not run attempt to initialize SDRAM when code is running from it */
0141     if ( tms570_running_from_sdram() )
0142         return;
0143 
0144     // Following the initialization procedure as described in EMIF-errata #5 for the tms570lc43
0145     // at EMIF clock rates >= 40Mhz
0146     // Note step one of this procedure is running this EMIF initialization sequence before PLL
0147     // and clocks are mapped/enabled
0148     // For additional details on startup procedure see tms570lc43 TRM s21.2.5.5.B
0149 
0150     // Set SDRAM timings. These are dependent on the EMIF CLK rate, which = VCLK3
0151     // Set these based on the final EMIF clock rate once PLL & VCLK is enabled
0152     TMS570_EMIF.SDTIMR  = (uint32_t)1U << 27U|
0153                 (uint32_t)0U << 24U|
0154                 (uint32_t)0U << 20U|
0155                 (uint32_t)0U << 19U|
0156                 (uint32_t)1U << 16U|
0157                 (uint32_t)1U << 12U|
0158                 (uint32_t)1U << 8U|
0159                 (uint32_t)0U << 4U;
0160 
0161     /* Minimum number of ECLKOUT cycles from Self-Refresh exit to any command */
0162     // Also set this based on the final EMIF clk
0163     TMS570_EMIF.SDSRETR = 2;
0164     // Program the RR Field of SDRCR to provide 200us of initialization time
0165     // Per Errata#5, for EMIF startup, set this based on the non-VLCK3 clk rate.
0166     // The Errata is this register must be calculated as `SDRCR = 200us * EMIF_CLK`
0167     //  (typically this would be `SDRCR = (200us * EMIF_CLK) / 8` ) 
0168     //  Since the PLL's arent enabled yet, EMIF_CLK would be EXT_OSCIN / 2
0169     TMS570_EMIF.SDRCR = 1600;
0170 
0171     TMS570_EMIF.SDCR   = ((uint32_t)0U << 31U)|
0172             ((uint32_t)1U << 14U)|
0173             ((uint32_t)2U << 9U)|
0174             ((uint32_t)1U << 8U)|
0175             ((uint32_t)2U << 4U)|
0176             ((uint32_t)0); // pagesize = 256
0177 
0178     // Read of SDRAM memory location causes processor to wait until SDRAM Initialization completes
0179     dummy = *(volatile uint32_t*)TMS570_MEMORY_SDRAM_ORIGIN;
0180     (void) dummy;
0181 
0182     // Program the RR field to the default Refresh Interval of the SDRAM
0183     // Program this to the correct interval for the VCLK3/EMIF_CLK rate
0184     // Do this in the typical way per TRM: SDRCR = ((200us * EMIF_CLK) / 8) + 1
0185     TMS570_EMIF.SDRCR = 1251;
0186 
0187     /* Place the EMIF in Self Refresh Mode For Clock Change          */
0188     /* Must only write to the upper byte of the SDCR to avoid        */
0189     /* a second initialization sequence                              */
0190     /* The byte address depends on endian (0x3U in LE, 0x00 in BE32) */
0191     *((volatile unsigned char *)(&TMS570_EMIF.SDCR) + 0x0U) = 0x80;
0192 }
0193 
0194 /**
0195  * @brief Setup all system PLLs (HCG:setupPLL)
0196  *
0197  */
0198 void tms570_pll_init( void )
0199 {
0200     //based on HalCoGen setupPLL method
0201     uint32_t pll12_dis = TMS570_CLKDIS_SRC_PLL1 | TMS570_CLKDIS_SRC_PLL2;
0202 
0203     /* Disable PLL1 and PLL2 */
0204     TMS570_SYS1.CSDISSET = pll12_dis;
0205 
0206     /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Hardware status bit read check" */
0207     while ( ( TMS570_SYS1.CSDIS & pll12_dis ) != pll12_dis ) {
0208         /* Wait */
0209     }
0210 
0211     /* Clear Global Status Register */
0212     TMS570_SYS1.GLBSTAT = 0x301U;
0213 
0214     // Configure PLL control registers
0215 
0216     /**   - Setup pll control register 1:
0217      *     - Disable reset on oscillator slip (ROS)
0218      *     - Enable bypass on pll slip
0219      *        TODO: desired: switches to OSC when PLL slip detected
0220      *     - setup Pll output clock divider to max before Lock
0221      *     - Disable reset on oscillator fail
0222      *     - Setup reference clock divider
0223      *     - Setup Pll multiplier
0224      *
0225      *     - PLL1: 16MHz OSC in -> 300MHz PLL1 out
0226      */
0227     TMS570_SYS1.PLLCTL1 =  (TMS570_SYS1_PLLCTL1_ROS * 0)
0228                         |  (uint32_t)0x40000000U
0229                         |  TMS570_SYS1_PLLCTL1_PLLDIV(0x1F)
0230                         |  (TMS570_SYS1_PLLCTL1_ROF * 0)
0231                         |  TMS570_SYS1_PLLCTL1_REFCLKDIV(4U - 1U)
0232                         |  TMS570_SYS1_PLLCTL1_PLLMUL((75U - 1U) << 8);
0233 
0234     /**   - Setup pll control register 2
0235      *     - Setup spreading rate
0236      *     - Setup bandwidth adjustment
0237      *     - Setup internal Pll output divider
0238      *     - Setup spreading amount
0239      */
0240     TMS570_SYS1.PLLCTL2 =  ((uint32_t)255U << 22U)
0241                         |  ((uint32_t)7U << 12U)
0242                         |  ((uint32_t)(1U - 1U) << 9U)
0243                         |  61U;
0244 
0245     // Initialize Pll2
0246 
0247     /**   - Setup pll2 control register :
0248      *     - setup Pll output clock divider to max before Lock
0249      *     - Setup reference clock divider
0250      *     - Setup internal Pll output divider
0251      *     - Setup Pll multiplier
0252      */
0253     TMS570_SYS2.PLLCTL3 = TMS570_SYS2_PLLCTL3_ODPLL2(1U - 1U)
0254                         | TMS570_SYS2_PLLCTL3_PLLDIV2(0x1FU)
0255                         | TMS570_SYS2_PLLCTL3_REFCLKDIV2(8U - 1U)
0256                         | TMS570_SYS2_PLLCTL3_PLLMUL2(( 150U - 1U) << 8 );
0257 
0258     // Enable PLL(s) to start up or Lock
0259     // Enable all clock sources except the following
0260     TMS570_SYS1.CSDIS = (TMS570_CLKDIS_SRC_EXT_CLK2 | TMS570_CLKDIS_SRC_EXT_CLK1 | TMS570_CLKDIS_SRC_RESERVED);
0261 }
0262 
0263 void tms570_map_clock_init(void)
0264 {
0265     // based on HalCoGen mapClocks method
0266     uint32_t sys_csvstat, sys_csdis;
0267 
0268     TMS570_SYS2.HCLKCNTL = 1U;
0269 
0270     /** @b Initialize @b Clock @b Tree: */
0271     /** - Disable / Enable clock domain */
0272     TMS570_SYS1.CDDIS = ( 0U << 4U ) |  /* AVCLK 1 ON */
0273                         ( 1U << 5U ) |  /* AVCLK 2 OFF */
0274                         ( 0U << 8U ) |  /* VCLK3 ON */
0275                         ( 0U << 9U ) |  /* VCLK4 ON */
0276                         ( 0U << 10U ) | /* AVCLK 3 ON */
0277                         ( 0U << 11U );  /* AVCLK 4 ON */
0278 
0279     /* Work Around for Errata SYS#46:
0280     * Despite this being a LS3137 errata, hardware testing on the LC4357 indicates this wait is still necessary
0281     */
0282     sys_csvstat = TMS570_SYS1.CSVSTAT;
0283     sys_csdis = TMS570_SYS1.CSDIS;
0284 
0285     while ( ( sys_csvstat & ( ( sys_csdis ^ 0xFFU ) & 0xFFU ) ) !=
0286             ( ( sys_csdis ^ 0xFFU ) & 0xFFU ) ) {
0287         sys_csvstat = TMS570_SYS1.CSVSTAT;
0288         sys_csdis = TMS570_SYS1.CSDIS;
0289     }
0290 
0291     TMS570_SYS1.GHVSRC =  TMS570_SYS1_GHVSRC_GHVWAKE(TMS570_SYS_CLK_SRC_PLL1)
0292                         | TMS570_SYS1_GHVSRC_HVLPM(TMS570_SYS_CLK_SRC_PLL1)
0293                         | TMS570_SYS1_GHVSRC_GHVSRC(TMS570_SYS_CLK_SRC_PLL1);
0294 
0295     /** - Setup RTICLK1 and RTICLK2 clocks */
0296     TMS570_SYS1.RCLKSRC = ((uint32_t)1U << 24U)        /* RTI2 divider (Not applicable for lock-step device)  */
0297                         | ((uint32_t)TMS570_SYS_CLK_SRC_VCLK << 16U) /* RTI2 clock source (Not applicable for lock-step device) Field not in TRM? */
0298                         | ((uint32_t)1U << 8U)         /* RTI1 divider */
0299                         | ((uint32_t)TMS570_SYS_CLK_SRC_VCLK << 0U); /* RTI1 clock source */
0300 
0301     /** - Setup asynchronous peripheral clock sources for AVCLK1 and AVCLK2 */
0302     TMS570_SYS1.VCLKASRC =  TMS570_SYS1_VCLKASRC_VCLKA2S(TMS570_SYS_CLK_SRC_VCLK)
0303                         | TMS570_SYS1_VCLKASRC_VCLKA1S(TMS570_SYS_CLK_SRC_VCLK);
0304 
0305     /** - Setup synchronous peripheral clock dividers for VCLK1, VCLK2, VCLK3 */
0306 
0307     // VCLK2 = PLL1 / HCLK_DIV / 2 = 75MHz
0308     TMS570_SYS1.CLKCNTL  = (TMS570_SYS1.CLKCNTL & ~TMS570_SYS1_CLKCNTL_VCLK2R(0xF))
0309                         | TMS570_SYS1_CLKCNTL_VCLK2R(0x1);
0310     // VLCK1 = PLL1 / HCLK_DIV / 2 = 75MHz
0311     TMS570_SYS1.CLKCNTL  = (TMS570_SYS1.CLKCNTL & ~TMS570_SYS1_CLKCNTL_VCLKR(0xF))
0312                         | TMS570_SYS1_CLKCNTL_VCLKR(0x1);
0313 
0314     // VCLK3 = PLL1 / HCLK_DIV / 3 = 50MHz
0315     TMS570_SYS2.CLK2CNTRL = (TMS570_SYS2.CLK2CNTRL & ~TMS570_SYS2_CLK2CNTRL_VCLK3R(0xF))
0316                         | TMS570_SYS2_CLK2CNTRL_VCLK3R(0x2);
0317 
0318     TMS570_SYS2.VCLKACON1 =   TMS570_SYS2_VCLKACON1_VCLKA4R(1U - 1U)
0319                             | (TMS570_SYS2_VCLKACON1_VCLKA4_DIV_CDDIS * 0)
0320                             | TMS570_SYS2_VCLKACON1_VCLKA4S(TMS570_SYS_CLK_SRC_VCLK)
0321                             | TMS570_SYS2_VCLKACON1_VCLKA3R(1U - 1U)
0322                             | (TMS570_SYS2_VCLKACON1_VCLKA3_DIV_CDDIS * 0)
0323                             | TMS570_SYS2_VCLKACON1_VCLKA3S(TMS570_SYS_CLK_SRC_VCLK);
0324 
0325     /* Now the PLLs are locked and the PLL outputs can be sped up */
0326     /* The R-divider was programmed to be 0xF. Now this divider is changed to programmed value */
0327     TMS570_SYS1.PLLCTL1 = (TMS570_SYS1.PLLCTL1 & 0xE0FFFFFFU) | (uint32_t)((uint32_t)(1U - 1U) << 24U);
0328     /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> " Clear and write to the volatile register " */
0329     TMS570_SYS2.PLLCTL3 = (TMS570_SYS2.PLLCTL3 & 0xE0FFFFFFU) | (uint32_t)((uint32_t)(1U - 1U) << 24U);
0330 
0331     /* Enable/Disable Frequency modulation */
0332     TMS570_SYS1.PLLCTL2 |= 0x00000000U;
0333 }