Build Fix: Fix build issues with Board DDR Temp 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 <ti/csl/arch/csl_arch.h>
36 #include "board_ddr.h"
38 #ifdef BUILD_MCU
39 typedef struct Board_DDRThermalMgmtInstance_s
40 {
41     LPDDR4_Config      boardDDRCfg;
42     LPDDR4_PrivateData boardRuntimeDDRPd;
43     uint32_t           boardDDRInitRefreshRate[LPDDR4_FSP_2+1];
44     uint32_t           boardDDRTrasMax[LPDDR4_FSP_2+1];
45     HwiP_Handle        boardTempInterruptHandle;
46     Board_thermalMgmtCallbackFunction_t appCallBackFunction;
47     uint16_t           devIdCore;
48     uint16_t           devIdIr;
49 } Board_DDRThermalMgmtInstance_t;
51 #ifdef __cplusplus
52 #pragma DATA_SECTION(".data:BOARD_DDR_thermalManagement");
53 #else
54 #pragma DATA_SECTION(gBoard_DDRThermalMgmtInstance, ".data:BOARD_DDR_thermalManagement");
55 #endif
56 static Board_DDRThermalMgmtInstance_t gBoard_DDRThermalMgmtInstance;
58 /* Local defines */
59 #define BOARD_SCICLIENT_RESP_TIMEOUT 1000000
61 #ifdef __cplusplus
62 #pragma DATA_SECTION(".const:BOARD_DDR_thermalManagement");
63 #else
64 #pragma DATA_SECTION(gRefreshRateMultFactor, ".const:BOARD_DDR_thermalManagement");
65 #endif
66 /* Multiplication factors assumes scaling by 8 */
67 static const uint32_t gRefreshRateMultFactor[BOARD_MAX_TEMP_CHECK_REFRESH_RATE_VALUE+1] =
68 {
69     32U,  /* 4 x */
70     32U,  /* 4 x */
71     16U,  /* 2 x */
72     8U,   /* 1 x */
73     4U,   /* 0.5 x */
74     2U,   /* 0.25 x */
75     2U,   /* 0.25 x with derating */
76     2U,   /* 0.25 x with derating */
77 };
78 #ifdef __cplusplus
79 #pragma DATA_SECTION(".const:BOARD_DDR_thermalManagement");
80 #else
81 #pragma DATA_SECTION(gBoardDDRFSPNum, ".const:BOARD_DDR_thermalManagement");
82 #endif
84 static const LPDDR4_CtlFspNum gBoardDDRFSPNum[LPDDR4_FSP_2+1] =
85 {
86     LPDDR4_FSP_0,
87     LPDDR4_FSP_1,
88     LPDDR4_FSP_2,
89 };
91 #ifdef __cplusplus
92 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
93 #else
94 #pragma CODE_SECTION(Board_updateRefreshRate, ".text:BOARD_DDR_thermalManagement");
95 #endif
97 void Board_updateRefreshRate(const LPDDR4_CtlFspNum fsNum, uint32_t refreshMultFactor)
98 {
99     uint32_t refreshRate;
100     uint32_t trasMax;
101     uint32_t status;
103     /* Calculate refresh rate */
104     refreshRate = (gBoard_DDRThermalMgmtInstance.boardDDRInitRefreshRate[fsNum] * refreshMultFactor) >> 3U;
105     trasMax = (gBoard_DDRThermalMgmtInstance.boardDDRTrasMax[fsNum] * refreshMultFactor) >> 3U;
107     /* Take action to update Refresh rate */
108     status = LPDDR4_SetRefreshRate(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), &fsNum, &refreshRate, &trasMax);
110     if (status > 0U)
111     {
112         BOARD_DEBUG_LOG("LPDDR4_GetRefreshRate: FAIL\n");
113         /* Add Assert if needed*/
114     }
117 #ifdef __cplusplus
118 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
119 #else
120 #pragma CODE_SECTION(Board_DDRSetDevId, ".text:BOARD_DDR_thermalManagement");
121 #endif
123 static void Board_DDRSetDevId()
124
125     CSL_ArmR5CPUInfo info;
127     CSL_armR5GetCpuID(&info);
128     if (info.grpId == (uint32_t)CSL_ARM_R5_CLUSTER_GROUP_ID_0)
129     {
130         /* MCU SS Pulsar R5 SS */
131         /* For R5 cores in the MCU domain MAIN2MCU_LVL_INTRTR0 is the base interrupt to the VIM. */
132         gBoard_DDRThermalMgmtInstance.devIdIr   = TISCI_DEV_MAIN2MCU_LVL_INTRTR0;
133         gBoard_DDRThermalMgmtInstance.devIdCore = (info.cpuID == CSL_ARM_R5_CPU_ID_0)?
134                                                         TISCI_DEV_MCU_R5FSS0_CORE0:
135                                                         TISCI_DEV_MCU_R5FSS0_CORE1;
136     }
137     else if (info.grpId == (uint32_t)CSL_ARM_R5_CLUSTER_GROUP_ID_1)
138     {
139         /* MAIN SS Pulsar R5 SS0 */
140         gBoard_DDRThermalMgmtInstance.devIdIr   = TISCI_DEV_R5FSS0_INTROUTER0;
141         gBoard_DDRThermalMgmtInstance.devIdCore = (info.cpuID == CSL_ARM_R5_CPU_ID_0)?
142                                                         TISCI_DEV_R5FSS0_CORE0:
143                                                         TISCI_DEV_R5FSS0_CORE1;
144     }
145     else if (info.grpId == (uint32_t)CSL_ARM_R5_CLUSTER_GROUP_ID_2)
146     {
147         /* MAIN SS Pulsar R5 SS1 */
148         gBoard_DDRThermalMgmtInstance.devIdIr   = TISCI_DEV_R5FSS1_INTROUTER0;
149         gBoard_DDRThermalMgmtInstance.devIdCore = (info.cpuID == CSL_ARM_R5_CPU_ID_0)?
150                                                         TISCI_DEV_R5FSS1_CORE0:
151                                                         TISCI_DEV_R5FSS1_CORE1;
152     }
153     
154     return;
157 #ifdef __cplusplus
158 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
159 #else
160 #pragma CODE_SECTION(Board_DDRGetIntNum, ".text:BOARD_DDR_thermalManagement");
161 #endif
163 static Board_STATUS Board_DDRGetIntNum(uint16_t *coreInterruptIdx)
165     Board_STATUS    status = BOARD_SOK;
166     uint16_t        irIntrIdx;
167     struct tisci_msg_rm_get_resource_range_resp res = {0};
168     struct tisci_msg_rm_get_resource_range_req  req = {0};
170     req.type           = gBoard_DDRThermalMgmtInstance.devIdIr;
171     req.subtype        = (uint8_t)TISCI_RESASG_SUBTYPE_IR_OUTPUT;
172     req.secondary_host = (uint8_t)TISCI_MSG_VALUE_RM_UNUSED_SECONDARY_HOST;
174     res.range_num = 0;
175     res.range_start = 0;
177     /* Get interrupt number range */
178     status =  Sciclient_rmGetResourceRange(
179                 &req,
180                 &res,
181                 SCICLIENT_SERVICE_WAIT_FOREVER);
182     if (CSL_PASS != status || res.range_num == 0) {
183         /* Try with HOST_ID_ALL */
184         req.type           = gBoard_DDRThermalMgmtInstance.devIdIr;
185         req.subtype        = (uint8_t)TISCI_RESASG_SUBTYPE_IR_OUTPUT;
186         req.secondary_host = TISCI_HOST_ID_ALL;
188         status = Sciclient_rmGetResourceRange(
189                 &req,
190                 &res,
191                 SCICLIENT_SERVICE_WAIT_FOREVER);
192     }
193     if ((CSL_PASS == status) && (res.range_num != 0))
194     {
195         /* Translate IR Idx to Core Interrupt Idx */
196         irIntrIdx = res.range_start;
197         status = Sciclient_rmIrqTranslateIrOutput(gBoard_DDRThermalMgmtInstance.devIdIr,
198                                                   irIntrIdx,
199                                                   gBoard_DDRThermalMgmtInstance.devIdCore,
200                                                   coreInterruptIdx);
201     }
202     else
203     {
204         status = BOARD_FAIL;
205     }
207     return status;
210 #ifdef __cplusplus
211 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
212 #else
213 #pragma CODE_SECTION(Board_updateAllRefreshRate, ".text:BOARD_DDR_thermalManagement");
214 #endif
216 void Board_updateAllRefreshRate(uint32_t refreshMultFactor)
219     Board_updateRefreshRate(LPDDR4_FSP_0, refreshMultFactor);
220     Board_updateRefreshRate(LPDDR4_FSP_1, refreshMultFactor);
221     Board_updateRefreshRate(LPDDR4_FSP_2, refreshMultFactor);
224 #ifdef __cplusplus
225 #pragma CODE_SECTION(".text:BOARD_DDR_thermalManagement");
226 #else
227 #pragma CODE_SECTION(Board_DDRInterruptHandler, ".text:BOARD_DDR_thermalManagement");
228 #endif
229 /**
230  * \brief Interrupt handler for DDR events
231  *
232  * Handles DDR events including temperature change events.
233  *
234  * \return  BOARD_SOK in case of success or appropriate error code
235  *
236  */
237 void Board_DDRInterruptHandler(uintptr_t arg)
239     bool     irqStatus;
240     uint32_t regValue;
241     uint32_t status;
242     uint32_t tempCheckRefreshRateIndex;
243     
244     /* Get DDR interrupt status to check on thermal events */
245     LPDDR4_CheckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_CHANGE, &irqStatus);
246     if (irqStatus)
247     {
248         /* Check Temp check register to check on the temperature change:
249          * Decide on refresh rate
250          */
251         /* Read Temp check register */
252         status = LPDDR4_ReadReg(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_CTL_REGS,
253                                 LPDDR4__AUTO_TEMPCHK_VAL_0__REG_OFFSET,
254                                 &regValue);
255         if (status == 0U)
256         {
257             /* Calculate refresh rate index */
258             tempCheckRefreshRateIndex = ((regValue & LPDDR4__AUTO_TEMPCHK_VAL_0_MASK)
259                                          >>  LPDDR4__AUTO_TEMPCHK_VAL_0_SHIFT )
260                                         & LPDDR4__AUTO_TEMPCHK_OP0_MASK;
262             /* Adjust refresh rate */
263             Board_updateAllRefreshRate(gRefreshRateMultFactor[tempCheckRefreshRateIndex]);
264         
265             /* Call application callback function */
266             if (gBoard_DDRThermalMgmtInstance.appCallBackFunction != NULL)
267             {
268                 gBoard_DDRThermalMgmtInstance.appCallBackFunction((Board_DDRTempEventType)
269                                                                   (BOARD_DDR_TEMP_EVENT_LOW_TEMP_ALARM
270                                                                    + tempCheckRefreshRateIndex));
271             }
272         }
274         /* Ack interrupt */
275         LPDDR4_AckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_CHANGE);
276     }
277     /* Get DDR interrupt status to check on alarm events */
278     LPDDR4_CheckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_ALERT, &irqStatus);
279     if (irqStatus)
280     {
281         /* High or Low temperature alarm : call application callback */
282         if (gBoard_DDRThermalMgmtInstance.appCallBackFunction != NULL)
283         {
284             gBoard_DDRThermalMgmtInstance.appCallBackFunction(BOARD_DDR_TEMP_EVENT_TEMP_ALERT);
285         }
286         /* Ack interrupt */
287         LPDDR4_AckCtlInterrupt (&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), LPDDR4_TEMP_ALERT);
288     }
290     /* NOTE: Code to handle other DDR events can be added here */
294 /**
295  * \brief DDR Temperature monitoring initialization function
296  *
297  * Configures and initializes DDR temperature handling.
298  * NOTE: This assumes that the DDR parameters are already have the thermal events
299  *       enabled in the DDR controller. This only handles software handling of the
300  *       thermal events
301  *
302  * \return  BOARD_SOK in case of success or appropriate error code 
303  *
304  */
305 Board_STATUS Board_DDRTempMonitoringInit(Board_thermalMgmtCallbackFunction_t callbackFunction)
307     Board_STATUS                status = BOARD_SOK;
308     OsalRegisterIntrParams_t    intrPrms;
309     OsalInterruptRetCode_e      osalRet;
310     uint64_t                    interruptMask;
311     uint32_t                    lpddrStatus;
312     uint32_t                    fspIndex;
313     uint16_t                    coreInterruptIdx;
314     
315     struct tisci_msg_rm_irq_release_req irq_release_req =
316     {
317         .ia_id          = 0,
318         .vint           = 0,
319         .global_event   = 0,
320         .vint_status_bit_index = 0,
321     };
322     struct tisci_msg_rm_irq_set_req irq_set_req =
323     {
324         .ia_id          = 0,
325         .vint           = 0,
326         .global_event   = 0,
327         .vint_status_bit_index = 0,
328     };
329     struct tisci_msg_rm_irq_set_resp resp;
331     /* Initialize LPDDR4 driver */
332     gBoard_DDRThermalMgmtInstance.boardDDRCfg.ctlBase = (struct LPDDR4_CtlRegs_s *)BOARD_DDR_CTL_CFG_BASE;
334     status = LPDDR4_Init(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), &(gBoard_DDRThermalMgmtInstance.boardDDRCfg));
336     if ((status > 0U) ||
337         (gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd.ctlBase != (struct LPDDR4_CtlRegs_s *)gBoard_DDRThermalMgmtInstance.boardDDRCfg.ctlBase))
338     {
339         BOARD_DEBUG_LOG("LPDDR4_Init: FAIL\n");
340         status = BOARD_FAIL;
341     }
343     if (status == BOARD_SOK)
344     {
345         /* Read and preserve the initial Refresh Rates as baseline */
346         for (fspIndex = 0; fspIndex <= LPDDR4_FSP_2; fspIndex++)
347         {
348             lpddrStatus = LPDDR4_GetRefreshRate(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), &gBoardDDRFSPNum[fspIndex],
349                                                 &(gBoard_DDRThermalMgmtInstance.boardDDRInitRefreshRate[gBoardDDRFSPNum[fspIndex]]),
350                                                 &(gBoard_DDRThermalMgmtInstance.boardDDRTrasMax[gBoardDDRFSPNum[fspIndex]]));
351             if (lpddrStatus > 0U)
352             {
353                 BOARD_DEBUG_LOG("LPDDR4_GetRefreshRate: FAIL\n");
354                 status = BOARD_FAIL;
355                 break;
356             }
357         }
358     }
359     
360     if (status == BOARD_SOK)
361     {
362         Board_DDRSetDevId();
363         /* Get the Core IRQ Idx */
364         status = Board_DDRGetIntNum(&coreInterruptIdx);
365     }
367     if (status == BOARD_SOK)
368     {
369         /* Configure interrupt router to route DDR Ctrl interrupt to Monitoring
370          * CPU
371          */
372         /* Request irq release for specified interrupt source */
373         irq_release_req.valid_params = TISCI_MSG_VALUE_RM_DST_ID_VALID
374                                        | TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
375         irq_release_req.src_id = TISCI_DEV_DDR0;
376         irq_release_req.src_index = 0; /* First interrupt in DDR group is the DDR controller interrupt */
377         irq_release_req.dst_id = gBoard_DDRThermalMgmtInstance.devIdCore;
378         irq_release_req.dst_host_irq = coreInterruptIdx;
380         /* Call irq Release */
381         if (CSL_PASS != Sciclient_rmIrqRelease(&irq_release_req, BOARD_SCICLIENT_RESP_TIMEOUT))
382         {
383             /* Ignore if the release fails, as this is expected the first time the image is booted */
384         }
386         /* Request irq set for specified interrupt source */
387         irq_set_req.valid_params = TISCI_MSG_VALUE_RM_DST_ID_VALID
388                                    | TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
389         irq_set_req.src_id = TISCI_DEV_DDR0;
390         irq_set_req.src_index = 0; /* First interrupt in DDR group is the DDR controller interrupt */
391         irq_set_req.dst_id = gBoard_DDRThermalMgmtInstance.devIdCore;
392         irq_set_req.dst_host_irq = coreInterruptIdx;
394         /* Call irq Set */
395         if (CSL_PASS != Sciclient_rmIrqSet(&irq_set_req, &resp, BOARD_SCICLIENT_RESP_TIMEOUT))
396         {
397             status = BOARD_FAIL;
398         }
399     }
401     if (status == BOARD_SOK)
402     {
404         /* Register DDR Control event handler */
405         Osal_RegisterInterrupt_initParams(&intrPrms); 
406         
407         intrPrms.corepacConfig.corepacEventNum  = 0;
408         intrPrms.corepacConfig.intVecNum        = coreInterruptIdx;
409         intrPrms.corepacConfig.arg              = (uintptr_t)(&(gBoard_DDRThermalMgmtInstance.boardTempInterruptHandle));
410         intrPrms.corepacConfig.isrRoutine       = &Board_DDRInterruptHandler;
412         /* Clear Interrupt */
413         Osal_ClearInterrupt(intrPrms.corepacConfig.corepacEventNum, intrPrms.corepacConfig.intVecNum);
415         /* Register interrupts */
416         osalRet = Osal_RegisterInterrupt(&intrPrms, &(gBoard_DDRThermalMgmtInstance.boardTempInterruptHandle));
417         if (osalRet != OSAL_INT_SUCCESS)
418         {
419             status = BOARD_FAIL;
420         }
421     }
423     if (status == BOARD_SOK)
424     {
425         /* Unmask only DDR thermal interrupt events */
426         interruptMask = (uint64_t)(0xffffffffffffffffU)
427                         & (~(((((uint64_t)1U) << LPDDR4_TEMP_CHANGE)
428                              | (((uint64_t)1U) << LPDDR4_TEMP_ALERT))));
429         LPDDR4_SetCtlInterruptMask(&(gBoard_DDRThermalMgmtInstance.boardRuntimeDDRPd), (const uint64_t *)(&interruptMask));
431         /* Enable DDR controller interrupt */
432         Osal_EnableInterrupt(intrPrms.corepacConfig.corepacEventNum, intrPrms.corepacConfig.intVecNum);
433     }
435     if (status == BOARD_SOK)
436     {
437         gBoard_DDRThermalMgmtInstance.appCallBackFunction = NULL;
438         if (callbackFunction != NULL)
439         {
440             /* Register callback function */
441             gBoard_DDRThermalMgmtInstance.appCallBackFunction = callbackFunction;
442         }
443     }
444     return status;
447 #endif /* BUILD_MCU*/