PRSDK-7943: board: Fix build issue with C++ on DDR thermal monitor
[processor-sdk/pdk.git] / packages / ti / board / src / j721e_evm / board_ddrtempmonitor.c
1 /******************************************************************************
2  * Copyright (c) 2019 Texas Instruments Incorporated - http://www.ti.com
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *    Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  *    Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the
14  *    distribution.
15  *
16  *    Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *****************************************************************************/
33 #include <string.h>
34 #include <ti/csl/csl_lpddr.h>
35 #include "board_ddr.h"
37 #ifdef BUILD_MCU1_0
38 typedef struct Board_DDRThermalMgmtInstance_s
39 {
40     LPDDR4_Config      boardDDRCfg;
41     LPDDR4_PrivateData boardRuntimeDDRPd;
42     uint32_t           boardDDRInitRefreshRate[LPDDR4_FSP_2+1];
43     HwiP_Handle        boardTempInterruptHandle;
44     Board_thermalMgmtCallbackFunction_t appCallBackFunction;
45 } Board_DDRThermalMgmtInstance_t;
47 #ifdef __cplusplus
48 #pragma DATA_SECTION(".data:BOARD_DDR_thermalManagement");
49 #else
50 #pragma DATA_SECTION(gBoard_DDRThermalMgmtInstance, ".data:BOARD_DDR_thermalManagement");
51 #endif
52 static Board_DDRThermalMgmtInstance_t gBoard_DDRThermalMgmtInstance;
54 /* Local defines */
55 #define BOARD_SCICLIENT_RESP_TIMEOUT 1000000
57 #ifdef __cplusplus
58 #pragma DATA_SECTION(".const:BOARD_DDR_thermalManagement");
59 #else
60 #pragma DATA_SECTION(gRefreshRateMultFactor, ".const:BOARD_DDR_thermalManagement");
61 #endif
62 /* Multiplication factors assumes scaling by 8 */
63 static const uint32_t gRefreshRateMultFactor[BOARD_MAX_TEMP_CHECK_REFRESH_RATE_VALUE+1] =
64 {
65     32U,  /* 4 x */
66     32U,  /* 4 x */
67     16U,  /* 2 x */
68     8U,   /* 1 x */
69     4U,   /* 0.5 x */
70     2U,   /* 0.25 x */
71     2U,   /* 0.25 x with derating */
72     2U,   /* 0.25 x with derating */
73 };
74 #ifdef __cplusplus
75 #pragma DATA_SECTION(".const:BOARD_DDR_thermalManagement");
76 #else
77 #pragma DATA_SECTION(gBoardDDRFSPNum, ".const:BOARD_DDR_thermalManagement");
78 #endif
80 static const LPDDR4_CtlFspNum gBoardDDRFSPNum[LPDDR4_FSP_2+1] =
81 {
82     LPDDR4_FSP_0,
83     LPDDR4_FSP_1,
84     LPDDR4_FSP_2,
85 };
87 #ifdef __cplusplus
88 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
89 #else
90 #pragma CODE_SECTION(Board_updateRefreshRate, ".text:BOARD_DDR_thermalManagement");
91 #endif
93 void Board_updateRefreshRate(const LPDDR4_CtlFspNum fsNum, uint32_t refreshMultFactor)
94 {
95     uint32_t refreshRate;
96     uint32_t status;
98     /* Calculate refresh rate */
99     refreshRate = (gBoard_DDRThermalMgmtInstance.boardDDRInitRefreshRate[fsNum] * refreshMultFactor) >> 3U;
101     /* Take action to update Refresh rate */
102     status = LPDDR4_SetRefreshRate(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), &fsNum, &refreshRate);
104     if (status > 0U)
105     {
106         BOARD_DEBUG_LOG("LPDDR4_GetRefreshRate: FAIL\n");
107         /* Add Assert if needed*/
108     }
111 #ifdef __cplusplus
112 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
113 #else
114 #pragma CODE_SECTION(Board_updateAllRefreshRate, ".text:BOARD_DDR_thermalManagement");
115 #endif
117 void Board_updateAllRefreshRate(uint32_t refreshMultFactor)
120     Board_updateRefreshRate(LPDDR4_FSP_0, refreshMultFactor);
121     Board_updateRefreshRate(LPDDR4_FSP_1, refreshMultFactor);
122     Board_updateRefreshRate(LPDDR4_FSP_2, refreshMultFactor);
125 #ifdef __cplusplus
126 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
127 #else
128 #pragma CODE_SECTION(Board_DDRInterruptHandler, ".text:BOARD_DDR_thermalManagement");
129 #endif
130 /**
131  * \brief Interrupt handler for DDR events
132  *
133  * Handles DDR events including temperature change events.
134  *
135  * \return  BOARD_SOK in case of success or appropriate error code
136  *
137  */
138 void Board_DDRInterruptHandler(uintptr_t arg)
140     bool     irqStatus;
141     uint32_t regValue;
142     uint32_t status;
143     uint32_t tempCheckRefreshRateIndex;
144     
145     /* Get DDR interrupt status to check on thermal events */
146     LPDDR4_CheckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_CHANGE, &irqStatus);
147     if (irqStatus)
148     {
149         /* Check Temp check register to check on the temperature change:
150          * Decide on refresh rate
151          */
152         /* Read Temp check register */
153         status = LPDDR4_ReadReg(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_CTL_REGS,
154                                 LPDDR4__AUTO_TEMPCHK_VAL_0__REG_OFFSET,
155                                 &regValue);
156         if (status == 0U)
157         {
158             /* Calculate refresh rate index */
159             tempCheckRefreshRateIndex = ((regValue & LPDDR4__AUTO_TEMPCHK_VAL_0_MASK)
160                                          >>  LPDDR4__AUTO_TEMPCHK_VAL_0_SHIFT )
161                                         & LPDDR4__AUTO_TEMPCHK_OP0_MASK;
163             /* Adjust refresh rate */
164             Board_updateAllRefreshRate(gRefreshRateMultFactor[tempCheckRefreshRateIndex]);
165         
166             /* Call application callback function */
167             if (gBoard_DDRThermalMgmtInstance.appCallBackFunction != NULL)
168             {
169                 gBoard_DDRThermalMgmtInstance.appCallBackFunction((Board_DDRTempEventType)
170                                                                   (BOARD_DDR_TEMP_EVENT_LOW_TEMP_ALARM
171                                                                    + tempCheckRefreshRateIndex));
172             }
173         }
175         /* Ack interrupt */
176         LPDDR4_AckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_CHANGE);
177     }
178     /* Get DDR interrupt status to check on alarm events */
179     LPDDR4_CheckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_ALERT, &irqStatus);
180     if (irqStatus)
181     {
182         /* High or Low temperature alarm : call application callback */
183         if (gBoard_DDRThermalMgmtInstance.appCallBackFunction != NULL)
184         {
185             gBoard_DDRThermalMgmtInstance.appCallBackFunction(BOARD_DDR_TEMP_EVENT_TEMP_ALERT);
186         }
187         /* Ack interrupt */
188         LPDDR4_AckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_ALERT);
189     }
191     /* NOTE: Code to handle other DDR events can be added here */
195 /**
196  * \brief DDR Temperature monitoring initialization function
197  *
198  * Configures and initializes DDR temperature handling.
199  * NOTE: This assumes that the DDR parameters are already have the thermal events
200  *       enabled in the DDR controller. This only handles software handling of the
201  *       thermal events
202  *
203  * \return  BOARD_SOK in case of success or appropriate error code 
204  *
205  */
206 Board_STATUS Board_DDRTempMonitoringInit(Board_thermalMgmtCallbackFunction_t callbackFunction)
208     Board_STATUS                status = BOARD_SOK;
209     OsalRegisterIntrParams_t    intrPrms;
210     OsalInterruptRetCode_e      osalRet;
211     uint64_t                    interruptMask;
212     uint32_t                    lpddrStatus;
213     uint32_t                    fspIndex;
214     
215     struct tisci_msg_rm_irq_release_req irq_release_req =
216     {
217         .ia_id          = 0,
218         .vint           = 0,
219         .global_event   = 0,
220         .vint_status_bit_index = 0,
221     };
222     struct tisci_msg_rm_irq_set_req irq_set_req =
223     {
224         .ia_id          = 0,
225         .vint           = 0,
226         .global_event   = 0,
227         .vint_status_bit_index = 0,
228     };
229     struct tisci_msg_rm_irq_set_resp resp;
231     /* Initialize LPDDR4 driver */
232     gBoard_DDRThermalMgmtInstance.boardDDRCfg.ctlBase = (struct LPDDR4_CtlRegs_s *)BOARD_DDR_SS_BASE;
234     status = LPDDR4_Init(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), &(gBoard_DDRThermalMgmtInstance.boardDDRCfg));
236     if ((status > 0U) ||
237         (gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd.ctlBase != (struct LPDDR4_CtlRegs_s *)gBoard_DDRThermalMgmtInstance.boardDDRCfg.ctlBase))
238     {
239         BOARD_DEBUG_LOG("LPDDR4_Init: FAIL\n");
240         status = BOARD_FAIL;
241     }
243     if (status == BOARD_SOK)
244     {
245         /* Read and preserve the initial Refresh Rates as baseline */
246         for (fspIndex = 0; fspIndex <= LPDDR4_FSP_2; fspIndex++)
247         {
248             lpddrStatus = LPDDR4_GetRefreshRate(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), &gBoardDDRFSPNum[fspIndex],
249                                                 &(gBoard_DDRThermalMgmtInstance.boardDDRInitRefreshRate[gBoardDDRFSPNum[fspIndex]]));
250             if (lpddrStatus > 0U)
251             {
252                 BOARD_DEBUG_LOG("LPDDR4_GetRefreshRate: FAIL\n");
253                 status = BOARD_FAIL;
254                 break;
255             }
256         }
257     }
258     
259     if (status == BOARD_SOK)
260     {
261         /* Configure interrupt router to route DDR Ctrl interrupt to Monitoring
262          * CPU
263          */
264         /* Request irq release for specified interrupt source */
265         irq_release_req.valid_params = TISCI_MSG_VALUE_RM_DST_ID_VALID
266                                        | TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
267         irq_release_req.src_id = TISCI_DEV_DDR0;
268         irq_release_req.src_index = 0; /* First interrupt in DDR group is the DDR controller interrupt */
269         irq_release_req.dst_id = TISCI_DEV_MCU_R5FSS0_CORE0;
270         irq_release_req.dst_host_irq = CSLR_MCU_R5FSS0_CORE0_INTR_MAIN2MCU_LVL_INTRTR0_OUTL_63;
272         /* Call irq Release */
273         if (CSL_PASS != Sciclient_rmIrqRelease(&irq_release_req, BOARD_SCICLIENT_RESP_TIMEOUT))
274         {
275             /* Ignore if the release fails, as this is expected the first time the image is booted */
276         }
278         /* Request irq set for specified interrupt source */
279         irq_set_req.valid_params = TISCI_MSG_VALUE_RM_DST_ID_VALID
280                                    | TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
281         irq_set_req.src_id = TISCI_DEV_DDR0;
282         irq_set_req.src_index = 0; /* First interrupt in DDR group is the DDR controller interrupt */
283         irq_set_req.dst_id = TISCI_DEV_MCU_R5FSS0_CORE0;
284         irq_set_req.dst_host_irq = CSLR_MCU_R5FSS0_CORE0_INTR_MAIN2MCU_LVL_INTRTR0_OUTL_63;
286         /* Call irq Set */
287         if (CSL_PASS != Sciclient_rmIrqSet(&irq_set_req, &resp, BOARD_SCICLIENT_RESP_TIMEOUT))
288         {
289             status = BOARD_FAIL;
290         }
291     }
293     if (status == BOARD_SOK)
294     {
296         /* Register DDR Control event handler */
297         Osal_RegisterInterrupt_initParams(&intrPrms); 
298         
299         intrPrms.corepacConfig.corepacEventNum  = 0;
300         intrPrms.corepacConfig.intVecNum        = CSLR_MCU_R5FSS0_CORE0_INTR_MAIN2MCU_LVL_INTRTR0_OUTL_63;
301         intrPrms.corepacConfig.arg              = (uintptr_t)(&(gBoard_DDRThermalMgmtInstance.boardTempInterruptHandle));
302         intrPrms.corepacConfig.isrRoutine       = &Board_DDRInterruptHandler;
304         /* Clear Interrupt */
305         Osal_ClearInterrupt(intrPrms.corepacConfig.corepacEventNum, intrPrms.corepacConfig.intVecNum);
307         /* Register interrupts */
308         osalRet = Osal_RegisterInterrupt(&intrPrms, &(gBoard_DDRThermalMgmtInstance.boardTempInterruptHandle));
309         if (osalRet != OSAL_INT_SUCCESS)
310         {
311             status = BOARD_FAIL;
312         }
313     }
315     if (status == BOARD_SOK)
316     {
317         /* Unmask only DDR thermal interrupt events */
318         interruptMask = (uint64_t)(0xffffffffffffffffU)
319                         & (~(((((uint64_t)1U) << LPDDR4_TEMP_CHANGE)
320                              | (((uint64_t)1U) << LPDDR4_TEMP_ALERT))));
321         LPDDR4_SetCtlInterruptMask(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), (const uint64_t *)(&interruptMask));
323         /* Enable DDR controller interrupt */
324         Osal_EnableInterrupt(intrPrms.corepacConfig.corepacEventNum, intrPrms.corepacConfig.intVecNum);
325     }
327     if (status == BOARD_SOK)
328     {
329         gBoard_DDRThermalMgmtInstance.appCallBackFunction = NULL;
330         if (callbackFunction != NULL)
331         {
332             /* Register callback function */
333             gBoard_DDRThermalMgmtInstance.appCallBackFunction = callbackFunction;
334         }
335     }
336     return status;
338 #endif /* BUILD_MCU1_0 */