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 errata SSWF021#45 workaround
0009  *   implementation.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com
0014  *
0015  *
0016  *  Redistribution and use in source and binary forms, with or without
0017  *  modification, are permitted provided that the following conditions
0018  *  are met:
0019  *
0020  *    Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  *
0023  *    Redistributions in binary form must reproduce the above copyright
0024  *    notice, this list of conditions and the following disclaimer in the
0025  *    documentation and/or other materials provided with the
0026  *    distribution.
0027  *
0028  *    Neither the name of Texas Instruments Incorporated nor the names of
0029  *    its contributors may be used to endorse or promote products derived
0030  *    from this software without specific prior written permission.
0031  *
0032  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0033  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0034  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0035  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0036  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0037  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0038  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0039  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0040  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0041  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0042  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0043  *
0044  */
0045 #include <bsp/ti_herc/errata_SSWF021_45.h>
0046 #include <bsp/tms570.h>
0047 
0048 #define SYS_CLKSRC_PLL1 0x00000002U
0049 #define SYS_CLKSRC_PLL2 0x00000040U
0050 #define SYS_CLKCNTRL_PENA 0x00000100U
0051 #define ESM_SR1_PLL1SLIP 0x400U
0052 #define ESM_SR4_PLL2SLIP 0x400U
0053 #define PLL1 0x08
0054 #define PLL2 0x80
0055 #define dcc1CNT1_CLKSRC_PLL1 0x0000A000U
0056 #define dcc1CNT1_CLKSRC_PLL2 0x0000A001U
0057 
0058 static uint32_t check_frequency(uint32_t cnt1_clksrc);
0059 static uint32_t disable_plls(uint32_t plls);
0060 
0061 /** @fn uint32_t _errata_SSWF021_45_both_plls(uint32_t count)
0062  *   @brief This handles the errata for PLL1 and PLL2. This function is called
0063  *      in device startup
0064  *
0065  *   @param[in] count : Number of retries until both PLLs are locked
0066  *      successfully Minimum value recommended is 5
0067  *
0068  *   @return 0 = Success (the PLL or both PLLs have successfully locked and then
0069  *               been disabled)
0070  *           1 = PLL1 failed to successfully lock in "count" tries
0071  *           2 = PLL2 failed to successfully lock in "count" tries
0072  *           3 = Neither PLL1 nor PLL2 successfully locked in "count" tries
0073  *           4 = The workaround function was not able to disable at least one of
0074  *               the PLLs. The most likely reason is that a PLL is already being
0075  *               used as a clock source. This can be caused by the workaround
0076  *               function being called from the wrong place in the code.
0077  */
0078 uint32_t _errata_SSWF021_45_both_plls(uint32_t count) {
0079     uint32_t failCode, retries, clkCntlSav;
0080 
0081     /* save CLKCNTL */
0082     clkCntlSav = TMS570_SYS1.CLKCNTL;
0083     /* First set VCLK2 = HCLK */
0084     TMS570_SYS1.CLKCNTL = clkCntlSav & 0x000F0100U;
0085     /* Now set VCLK = HCLK and enable peripherals */
0086     TMS570_SYS1.CLKCNTL = SYS_CLKCNTRL_PENA;
0087     failCode = 0U;
0088     for (retries = 0U; (retries < count); retries++) {
0089         failCode = 0U;
0090         /* Disable PLL1 and PLL2 */
0091         failCode = disable_plls(SYS_CLKSRC_PLL1 | SYS_CLKSRC_PLL2);
0092         if (failCode != 0U) {
0093             break;
0094         }
0095 
0096         /* Clear Global Status Register */
0097         TMS570_SYS1.GLBSTAT = 0x00000301U;
0098         /* Clear the ESM PLL slip flags */
0099         TMS570_ESM.SR[0U] = ESM_SR1_PLL1SLIP;
0100         TMS570_ESM.SR4 = ESM_SR4_PLL2SLIP;
0101         /* set both PLLs to OSCIN/1*27/(2*1) */
0102         TMS570_SYS1.PLLCTL1 = 0x20001A00U;
0103         TMS570_SYS1.PLLCTL2 = 0x3FC0723DU;
0104         TMS570_SYS2.PLLCTL3 = 0x20001A00U;
0105         TMS570_SYS1.CSDISCLR = SYS_CLKSRC_PLL1 | SYS_CLKSRC_PLL2;
0106         /* Check for (PLL1 valid or PLL1 slip) and (PLL2 valid or PLL2 slip) */
0107         while ((((TMS570_SYS1.CSVSTAT & SYS_CLKSRC_PLL1) == 0U) &&
0108                 ((TMS570_ESM.SR[0U] & ESM_SR1_PLL1SLIP) == 0U)) ||
0109                (((TMS570_SYS1.CSVSTAT & SYS_CLKSRC_PLL2) == 0U) &&
0110                 ((TMS570_ESM.SR4 & ESM_SR4_PLL2SLIP) == 0U))) {
0111             /* Wait */
0112         }
0113         /* If PLL1 valid, check the frequency */
0114         if (((TMS570_ESM.SR[0U] & ESM_SR1_PLL1SLIP) != 0U) ||
0115             ((TMS570_SYS1.GLBSTAT & 0x00000300U) != 0U)) {
0116             failCode |= 1U;
0117         } else {
0118             failCode |= check_frequency(dcc1CNT1_CLKSRC_PLL1);
0119         }
0120         /* If PLL2 valid, check the frequency */
0121         if (((TMS570_ESM.SR4 & ESM_SR4_PLL2SLIP) != 0U) ||
0122             ((TMS570_SYS1.GLBSTAT & 0x00000300U) != 0U)) {
0123             failCode |= 2U;
0124         } else {
0125             failCode |= (check_frequency(dcc1CNT1_CLKSRC_PLL2) << 1U);
0126         }
0127         if (failCode == 0U) {
0128             break;
0129         }
0130     }
0131     /* To avoid MISRA violation 382S
0132        (void)missing for discarded return value */
0133     failCode = disable_plls(SYS_CLKSRC_PLL1 | SYS_CLKSRC_PLL2);
0134     /* restore CLKCNTL, VCLKR and PENA first */
0135     TMS570_SYS1.CLKCNTL = (clkCntlSav & 0x000F0100U);
0136     /* restore CLKCNTL, VCLK2R */
0137     TMS570_SYS1.CLKCNTL = clkCntlSav;
0138     return failCode;
0139 }
0140 
0141 /** @fn uint32_t _errata_SSWF021_45_pll1(uint32_t count)
0142  *   @brief This handles the errata for PLL1. This function is called in device
0143  *       startup
0144  *
0145  *   @param[in] count : Number of retries until both PLL1 is locked successfully
0146  *                      Minimum value recommended is 5
0147  *
0148  *   @return 0 = Success (the PLL or both PLLs have successfully locked and then
0149  *               been disabled)
0150  *           1 = PLL1 failed to successfully lock in "count" tries
0151  *           2 = PLL2 failed to successfully lock in "count" tries
0152  *           3 = Neither PLL1 nor PLL2 successfully locked in "count" tries
0153  *           4 = The workaround function was not able to disable at least one of
0154  *               the PLLs. The most likely reason is that a PLL is already being
0155  *               used as a clock source. This can be caused by the workaround
0156  *               function being called from the wrong place in the code.
0157  */
0158 uint32_t _errata_SSWF021_45_pll1(uint32_t count) {
0159     uint32_t failCode, retries, clkCntlSav;
0160 
0161     /* save CLKCNTL */
0162     clkCntlSav = TMS570_SYS1.CLKCNTL;
0163     /* First set VCLK2 = HCLK */
0164     TMS570_SYS1.CLKCNTL = clkCntlSav & 0x000F0100U;
0165     /* Now set VCLK = HCLK and enable peripherals */
0166     TMS570_SYS1.CLKCNTL = SYS_CLKCNTRL_PENA;
0167     failCode = 0U;
0168     for (retries = 0U; (retries < count); retries++) {
0169         failCode = 0U;
0170         /* Disable PLL1 */
0171         failCode = disable_plls(SYS_CLKSRC_PLL1);
0172         if (failCode != 0U) {
0173             break;
0174         }
0175 
0176         /* Clear Global Status Register */
0177         TMS570_SYS1.GLBSTAT = 0x00000301U;
0178         /* Clear the ESM PLL slip flags */
0179         TMS570_ESM.SR[0U] = ESM_SR1_PLL1SLIP;
0180         /* set  PLL1 to OSCIN/1*27/(2*1) */
0181         TMS570_SYS1.PLLCTL1 = 0x20001A00U;
0182         TMS570_SYS1.PLLCTL2 = 0x3FC0723DU;
0183         TMS570_SYS1.CSDISCLR = SYS_CLKSRC_PLL1;
0184         /* Check for PLL1 valid or PLL1 slip*/
0185         while (((TMS570_SYS1.CSVSTAT & SYS_CLKSRC_PLL1) == 0U) &&
0186                ((TMS570_ESM.SR[0U] & ESM_SR1_PLL1SLIP) == 0U)) {
0187             /* Wait */
0188         }
0189         /* If PLL1 valid, check the frequency */
0190         if (((TMS570_ESM.SR[0U] & ESM_SR1_PLL1SLIP) != 0U) ||
0191             ((TMS570_SYS1.GLBSTAT & 0x00000300U) != 0U)) {
0192             failCode |= 1U;
0193         } else {
0194             failCode |= check_frequency(dcc1CNT1_CLKSRC_PLL1);
0195         }
0196         if (failCode == 0U) {
0197             break;
0198         }
0199     }
0200     /* To avoid MISRA violation 382S
0201        (void)missing for discarded return value */
0202     failCode = disable_plls(SYS_CLKSRC_PLL1);
0203     /* restore CLKCNTL, VCLKR and PENA first */
0204     TMS570_SYS1.CLKCNTL = (clkCntlSav & 0x000F0100U);
0205     /* restore CLKCNTL, VCLK2R */
0206     TMS570_SYS1.CLKCNTL = clkCntlSav;
0207     return failCode;
0208 }
0209 
0210 /** @fn uint32_t _errata_SSWF021_45_pll2(uint32_t count)
0211  *   @brief This handles the errata for PLL2. This function is called in device
0212  *           startup
0213  *
0214  *   @param[in] count : Number of retries until PLL2 is locked successfully
0215  *                      Minimum value recommended is 5
0216  *
0217  *   @return 0 = Success (the PLL or both PLLs have successfully locked and then
0218  *       been disabled)
0219  *           1 = PLL1 failed to successfully lock in "count" tries
0220  *           2 = PLL2 failed to successfully lock in "count" tries
0221  *           3 = Neither PLL1 nor PLL2 successfully locked in "count" tries
0222  *           4 = The workaround function was not able to disable at least one of
0223  *               the PLLs. The most likely reason is that a PLL is already being
0224  *               used as a clock source. This can be caused by the workaround
0225  *               function being called from the wrong place in the code.
0226  */
0227 uint32_t _errata_SSWF021_45_pll2(uint32_t count) {
0228     uint32_t failCode, retries, clkCntlSav;
0229 
0230     /* save CLKCNTL */
0231     clkCntlSav = TMS570_SYS1.CLKCNTL;
0232     /* First set VCLK2 = HCLK */
0233     TMS570_SYS1.CLKCNTL = clkCntlSav & 0x000F0100U;
0234     /* Now set VCLK = HCLK and enable peripherals */
0235     TMS570_SYS1.CLKCNTL = SYS_CLKCNTRL_PENA;
0236     failCode = 0U;
0237     for (retries = 0U; (retries < count); retries++) {
0238         failCode = 0U;
0239         /* Disable PLL2 */
0240         failCode = disable_plls(SYS_CLKSRC_PLL2);
0241         if (failCode != 0U) {
0242             break;
0243         }
0244 
0245         /* Clear Global Status Register */
0246         TMS570_SYS1.GLBSTAT = 0x00000301U;
0247         /* Clear the ESM PLL slip flags */
0248         TMS570_ESM.SR4 = ESM_SR4_PLL2SLIP;
0249         /* set PLL2 to OSCIN/1*27/(2*1) */
0250         TMS570_SYS2.PLLCTL3 = 0x20001A00U;
0251         TMS570_SYS1.CSDISCLR = SYS_CLKSRC_PLL2;
0252         /* Check for PLL2 valid or PLL2 slip */
0253         while (((TMS570_SYS1.CSVSTAT & SYS_CLKSRC_PLL2) == 0U) &&
0254                ((TMS570_ESM.SR4 & ESM_SR4_PLL2SLIP) == 0U)) {
0255             /* Wait */
0256         }
0257         /* If PLL2 valid, check the frequency */
0258         if (((TMS570_ESM.SR4 & ESM_SR4_PLL2SLIP) != 0U) ||
0259             ((TMS570_SYS1.GLBSTAT & 0x00000300U) != 0U)) {
0260             failCode |= 2U;
0261         } else {
0262             failCode |= (check_frequency(dcc1CNT1_CLKSRC_PLL2) << 1U);
0263         }
0264         if (failCode == 0U) {
0265             break;
0266         }
0267     }
0268     /* To avoid MISRA violation 382S
0269        (void)missing for discarded return value */
0270     failCode = disable_plls(SYS_CLKSRC_PLL2);
0271     /* restore CLKCNTL, VCLKR and PENA first */
0272     TMS570_SYS1.CLKCNTL = (clkCntlSav & 0x000F0100U);
0273     /* restore CLKCNTL, VCLK2R */
0274     TMS570_SYS1.CLKCNTL = clkCntlSav;
0275     return failCode;
0276 }
0277 
0278 /** @fn uint32_t check_frequency(uint32_t cnt1_clksrc)
0279  *   @brief This function checks for the PLL frequency.
0280  *
0281  *   @param[in] cnt1_clksrc : Clock source for Counter1
0282  *                            0U - PLL1      (clock source 0)
0283  *                            1U - PLL2      (clock source 1)
0284  *
0285  *   @return   DCC Error status
0286  *             0 - DCC error has not occurred
0287  *             1 - DCC error has occurred
0288  */
0289 static uint32_t check_frequency(uint32_t cnt1_clksrc) {
0290     /* Setup DCC1 */
0291     /** DCC1 Global Control register configuration */
0292     TMS570_DCC1.GCTRL =
0293         (uint32_t)0x5U |                   /** Disable  DCC1 */
0294         (uint32_t)((uint32_t)0x5U << 4U) | /** No Error Interrupt */
0295         (uint32_t)((uint32_t)0xAU << 8U) | /** Single Shot mode */
0296         (uint32_t)((uint32_t)0x5U << 12U); /** No Done Interrupt */
0297     /* Clear ERR and DONE bits */
0298     TMS570_DCC1.STAT = 3U;
0299     /** DCC1 Clock0 Counter Seed value configuration */
0300     TMS570_DCC1.CNT0SEED = 68U;
0301     /** DCC1 Clock0 Valid Counter Seed value configuration */
0302     TMS570_DCC1.VALID0SEED = 4U;
0303     /** DCC1 Clock1 Counter Seed value configuration */
0304     TMS570_DCC1.CNT1SEED = 972U;
0305     /** DCC1 Clock1 Source 1 Select */
0306     TMS570_DCC1.CNT1CLKSRC =
0307         (uint32_t)((uint32_t)10U << 12U) | /** DCC Enable / Disable Key */
0308         (uint32_t)cnt1_clksrc;             /** DCC1 Clock Source 1 */
0309 
0310     TMS570_DCC1.CNT0CLKSRC =
0311         (uint32_t)DCC1_CNT0_OSCIN; /** DCC1 Clock Source 0 */
0312 
0313     /** DCC1 Global Control register configuration */
0314     TMS570_DCC1.GCTRL =
0315         (uint32_t)0xAU |                   /** Enable  DCC1 */
0316         (uint32_t)((uint32_t)0x5U << 4U) | /** No Error Interrupt */
0317         (uint32_t)((uint32_t)0xAU << 8U) | /** Single Shot mode */
0318         (uint32_t)((uint32_t)0x5U << 12U); /** No Done Interrupt */
0319     while (TMS570_DCC1.STAT == 0U) {
0320         /* Wait */
0321     }
0322     return (TMS570_DCC1.STAT & 0x01U);
0323 }
0324 
0325 /** @fn uint32_t disable_plls(uint32_t plls)
0326  *   @brief This function disables plls and clears the respective ESM flags.
0327  *
0328  *   @param[in] plls : Clock source for Counter1
0329  *                            2U - PLL1
0330  *                            40U - PLL2
0331  *
0332  *   @return   failCode
0333  *      0 = Success (the PLL or both PLLs have successfully locked and
0334  *          then been disabled)
0335  *      4 = The workaround function was not able to disable at least one
0336  *          of the PLLs. The most likely reason is that a PLL is already being
0337  *          used as a clock source. This can be caused by the workaround
0338  *          function being called from the wrong place in the code.
0339  */
0340 static uint32_t disable_plls(uint32_t plls) {
0341     uint32_t timeout, failCode;
0342 
0343     TMS570_SYS1.CSDISSET = plls;
0344     failCode = 0U;
0345     timeout = 0x10U;
0346     timeout--;
0347     while (((TMS570_SYS1.CSVSTAT & (plls)) != 0U) && (timeout != 0U)) {
0348         /* Clear ESM and GLBSTAT PLL slip flags */
0349         TMS570_SYS1.GLBSTAT = 0x00000300U;
0350 
0351         if ((plls & SYS_CLKSRC_PLL1) == SYS_CLKSRC_PLL1) {
0352             TMS570_ESM.SR[0U] = ESM_SR1_PLL1SLIP;
0353         }
0354         if ((plls & SYS_CLKSRC_PLL2) == SYS_CLKSRC_PLL2) {
0355             TMS570_ESM.SR4 = ESM_SR4_PLL2SLIP;
0356         }
0357         timeout--;
0358         /* Wait */
0359     }
0360     if (timeout == 0U) {
0361         failCode = 4U;
0362     } else {
0363         failCode = 0U;
0364     }
0365     return failCode;
0366 }