1 /******************************************************************************\r
2 * Copyright (c) 2019 Texas Instruments Incorporated - http://www.ti.com\r
3 *\r
4 * Redistribution and use in source and binary forms, with or without\r
5 * modification, are permitted provided that the following conditions\r
6 * are met:\r
7 *\r
8 * Redistributions of source code must retain the above copyright\r
9 * notice, this list of conditions and the following disclaimer.\r
10 *\r
11 * Redistributions in binary form must reproduce the above copyright\r
12 * notice, this list of conditions and the following disclaimer in the\r
13 * documentation and/or other materials provided with the\r
14 * distribution.\r
15 *\r
16 * Neither the name of Texas Instruments Incorporated nor the names of\r
17 * its contributors may be used to endorse or promote products derived\r
18 * from this software without specific prior written permission.\r
19 *\r
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31 *\r
32 *****************************************************************************/\r
33 \r
34 /**\r
35 * \file board_pll.c\r
36 *\r
37 * \brief Board pll configurations\r
38 *\r
39 */\r
40 \r
41 #include "board_internal.h"\r
42 #include "board_pll.h"\r
43 #include <ti/drv/sciclient/sciclient.h>\r
44 \r
45 static Board_PllClkCfg_t gBoardPllClkCfg[] =\r
46 {\r
47 \r
48 { TISCI_DEV_MCU_UART0,\r
49 TISCI_DEV_MCU_UART0_FCLK_CLK,\r
50 96000000\r
51 }, //MCU_PLL0_HSDIV2_CLKOUT,\r
52 \r
53 { TISCI_DEV_MCU_I2C0,\r
54 TISCI_DEV_MCU_UART0_FCLK_CLK,\r
55 96000000\r
56 }, //MCU_PLL0_HSDIV1_CLKOUT,\r
57 \r
58 { TISCI_DEV_UART0,\r
59 TISCI_DEV_UART0_FCLK_CLK,\r
60 48000000\r
61 }, //MAIN_PLL1_HSDIV1_CLKOUT,\r
62 \r
63 { TISCI_DEV_FSS0_OSPI_0,\r
64 TISCI_DEV_FSS0_OSPI_0_OSPI_RCLK_CLK,\r
65 166666666\r
66 }, //MAIN_PLL0_HSDIV1_CLKOUT,\r
67 \r
68 { TISCI_DEV_PRU_ICSSG1,\r
69 TISCI_DEV_PRU_ICSSG1_CORE_CLK,\r
70 250000000\r
71 }, //MAIN_PLL0_HSDIV9_CLKOUT,\r
72 \r
73 { TISCI_DEV_PRU_ICSSG1,\r
74 TISCI_DEV_PRU_ICSSG1_UCLK_CLK,\r
75 192000000\r
76 }, //MAIN_PLL1_HSDIV0_CLKOUT,\r
77 \r
78 { TISCI_DEV_PRU_ICSSG1,\r
79 TISCI_DEV_PRU_ICSSG1_RGMII_MHZ_250_CLK,\r
80 250000000\r
81 }, //MAIN_PLL0_HSDIV4_CLKOUT,\r
82 \r
83 { TISCI_DEV_MCAN0,\r
84 TISCI_DEV_MCAN0_MCANSS_CCLK_CLK,\r
85 80000000\r
86 }, //MAIN_PLL0_HSDIV2_CLKOUT,\r
87 \r
88 };\r
89 \r
90 /**\r
91 * \brief PLL clock enable\r
92 *\r
93 * This function is used to set the PLL Module clock frequency\r
94 *\r
95 * \param moduleId [IN] Module for which the state should be set.\r
96 * Refer Sciclient_PmDeviceIds in sciclient_fmwMsgParams.h\r
97 * \param clockId [IN] Clock Id for the module.\r
98 * Refer Sciclient_PmModuleClockIds in sciclient_fmwMsgParams.h\r
99 * \param clkRate [IN] Value of the clock frequency to be set\r
100 *\r
101 * \return int32_t\r
102 * CSL_PASS - on Success\r
103 * CSL_EFAIL - on Failure\r
104 *\r
105 */\r
106 static int32_t Board_PLLSetModuleClkFreq(uint32_t modId,\r
107 uint32_t clkId,\r
108 uint64_t clkRate)\r
109 {\r
110 uint32_t i = 0U;\r
111 int32_t status = CSL_EFAIL;\r
112 uint64_t respClkRate = 0;\r
113 uint32_t numParents = 0U;\r
114 uint32_t moduleClockParentChanged = 0U;\r
115 uint32_t clockStatus = 0U;\r
116 uint32_t origParent = 0U;\r
117 uint32_t foundParent = 0U;\r
118 \r
119 /* Check if the clock is enabled or not */\r
120 status = Sciclient_pmModuleGetClkStatus(modId,\r
121 clkId,\r
122 &clockStatus,\r
123 SCICLIENT_SERVICE_WAIT_FOREVER);\r
124 if (status == CSL_PASS)\r
125 {\r
126 /* Get the number of parents for the clock */\r
127 status = Sciclient_pmGetModuleClkNumParent(modId,\r
128 clkId,\r
129 &numParents,\r
130 SCICLIENT_SERVICE_WAIT_FOREVER);\r
131 if ((status == CSL_PASS) && (numParents > 1U))\r
132 {\r
133 status = Sciclient_pmGetModuleClkParent(modId, clkId, &origParent,\r
134 SCICLIENT_SERVICE_WAIT_FOREVER);\r
135 }\r
136 }\r
137 if (status == CSL_PASS)\r
138 {\r
139 /* Disabling the clock */\r
140 status = Sciclient_pmModuleClkRequest(\r
141 modId,\r
142 clkId,\r
143 TISCI_MSG_VALUE_CLOCK_SW_STATE_UNREQ,\r
144 0U,\r
145 SCICLIENT_SERVICE_WAIT_FOREVER);\r
146 }\r
147 if (status == CSL_PASS)\r
148 {\r
149 foundParent = 0U;\r
150 /* Try to loop and change parents of the clock */\r
151 for(i=0U;i<numParents;i++)\r
152 {\r
153 if (numParents > 1U)\r
154 {\r
155 /* Setting the new parent */\r
156 status = Sciclient_pmSetModuleClkParent(\r
157 modId,\r
158 clkId,\r
159 clkId+i+1,\r
160 SCICLIENT_SERVICE_WAIT_FOREVER);\r
161 /* Check if the clock can be set to desirable freq. */\r
162 if (status == CSL_PASS)\r
163 {\r
164 moduleClockParentChanged = 1U;\r
165 }\r
166 }\r
167 if (status == CSL_PASS)\r
168 {\r
169 status = Sciclient_pmQueryModuleClkFreq(modId,\r
170 clkId,\r
171 clkRate,\r
172 &respClkRate,\r
173 SCICLIENT_SERVICE_WAIT_FOREVER);\r
174 }\r
175 if ((status == CSL_PASS) && (respClkRate == clkRate))\r
176 {\r
177 foundParent = 1U;\r
178 break;\r
179 }\r
180 }\r
181 }\r
182 if (foundParent == 1U)\r
183 {\r
184 /* Set the clock at the desirable frequency*/\r
185 status = Sciclient_pmSetModuleClkFreq(\r
186 modId,\r
187 clkId,\r
188 clkRate,\r
189 TISCI_MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE,\r
190 SCICLIENT_SERVICE_WAIT_FOREVER);\r
191 }\r
192 else\r
193 {\r
194 status = CSL_EFAIL;\r
195 }\r
196 if ((status == CSL_PASS) &&\r
197 (clockStatus == TISCI_MSG_VALUE_CLOCK_SW_STATE_UNREQ))\r
198 {\r
199 /* Restore the clock again to original state */\r
200 status = Sciclient_pmModuleClkRequest(\r
201 modId,\r
202 clkId,\r
203 clockStatus,\r
204 0U,\r
205 SCICLIENT_SERVICE_WAIT_FOREVER);\r
206 }\r
207 if ((status != CSL_PASS) && (moduleClockParentChanged == 1U))\r
208 {\r
209 /* Setting the original parent if failure */\r
210 status = Sciclient_pmSetModuleClkParent(\r
211 modId,\r
212 clkId,\r
213 origParent,\r
214 SCICLIENT_SERVICE_WAIT_FOREVER);\r
215 }\r
216 return status;\r
217 }\r
218 \r
219 \r
220 /**\r
221 * \brief Function to initialize module clock frequency\r
222 *\r
223 * \param moduleId [IN] Module for which the state should be set.\r
224 * Refer Sciclient_PmDeviceIds in sciclient_fmwMsgParams.h\r
225 * \param clockId [IN] Clock Id for the module.\r
226 * Refer Sciclient_PmModuleClockIds in sciclient_fmwMsgParams.h\r
227 * \param clkRate [IN] Value of the clock frequency to be set\r
228 \r
229 * \return Board_STATUS\r
230 */\r
231 Board_STATUS Board_PLLInit(uint32_t modId,\r
232 uint32_t clkId,\r
233 uint64_t clkRate)\r
234 {\r
235 int32_t status = CSL_EFAIL;\r
236 \r
237 status = Board_PLLSetModuleClkFreq(modId, clkId, clkRate);\r
238 if(status != CSL_PASS)\r
239 {\r
240 return BOARD_FAIL;\r
241 }\r
242 \r
243 return BOARD_SOK;\r
244 }\r
245 \r
246 /**\r
247 * \brief Function to initialize all the PLL clocks with default values\r
248 *\r
249 * \return Board_STATUS\r
250 */\r
251 Board_STATUS Board_PLLInitAll(void)\r
252 {\r
253 Board_STATUS status = BOARD_SOK;\r
254 uint32_t index;\r
255 uint32_t loopCount;\r
256 \r
257 loopCount = sizeof (gBoardPllClkCfg)/sizeof(Board_PllClkCfg_t);\r
258 \r
259 for (index = 0; index < loopCount; index++)\r
260 {\r
261 status = Board_PLLInit(gBoardPllClkCfg[index].tisciDevID,\r
262 gBoardPllClkCfg[index].tisciClkID,\r
263 gBoardPllClkCfg[index].clkRate);\r
264 if(status != BOARD_SOK)\r
265 {\r
266 BOARD_DEBUG_LOG("Failed to set the PLL clock freq at index =%d\n\n",index);\r
267 }\r
268 }\r
269 \r
270 /*\r
271 * Temporary solution for enabling M4F application load via SBL.\r
272 * Actual fix will be in SYSFW doing early PLL initialization for MCU_PLLCTRL0\r
273 * \r
274 * MCU_PLLCTRL0's PLLCTL, set PLLENSRC = 0 and PLLEN = 1\r
275 */\r
276 HW_WR_REG32((CSL_MCU_PLLCTRL0_BASE + 0x100UL), 0x49U);\r
277 \r
278 return status;\r
279 }\r