1 /*
2  * Copyright 2017-2018 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_common.h"
10 #include "fsl_debug_console.h"
11 #include "board.h"
12 #include "fsl_gpio.h"
13 #if defined(SDK_I2C_BASED_COMPONENT_USED) && SDK_I2C_BASED_COMPONENT_USED
14 #include "fsl_lpi2c.h"
15 #endif /* SDK_I2C_BASED_COMPONENT_USED */
16 #ifdef FSL_RTOS_FREE_RTOS
17 #include "FreeRTOS.h"
18 #include "task.h"
19 #include "semphr.h"
20 #include "timers.h"
21 #endif
22 #include "svc/irq/irq_api.h"
23 #include "svc/misc/misc_api.h"
24 
25 #ifdef BOARD_USE_SCFW_IRQ
26 #include "fsl_mu.h"
27 #endif
28 /*******************************************************************************
29  * Typedef
30  ******************************************************************************/
31 #ifdef BOARD_USE_SCFW_IRQ
32 typedef struct _pad_ele *pad_ele_t;
33 
34 struct _pad_ele
35 {
36     sc_pad_t pad;
37     pad_ele_t next;
38     pad_ele_t prev;
39 };
40 #endif
41 
42 /*******************************************************************************
43  * Variables
44  ******************************************************************************/
45 static sc_ipc_t ipcHandle; /* ipc handle */
46 #ifdef BOARD_USE_SCFW_IRQ
47 #ifdef FSL_RTOS_FREE_RTOS
48 static TimerHandle_t s_scuEventTimer = NULL;
49 #endif
50 static sc_rm_pt_t a_pt;
51 static eventHandler s_BOARDEventHandler[kSCEvent_Last] = {NULL};
52 static void *s_BOARDEventHandlerParam[kSCEvent_Last]   = {NULL};
53 static pad_ele_t wakeup_padlist                        = NULL;
54 #endif
55 
56 /*******************************************************************************
57  * Code
58  ******************************************************************************/
BOARD_InitRpc(void)59 sc_ipc_t BOARD_InitRpc(void)
60 {
61     /* Initialize the IPC channel to communicate with SCFW */
62     SystemInitScfwIpc();
63 
64     ipcHandle = SystemGetScfwIpcHandle();
65     if (ipcHandle)
66     {
67         CLOCK_Init(ipcHandle);
68     }
69 
70     /*
71      * Current core reports it is done to SCFW when early boot mode is enabled.
72      * This mode is used to minimize the time from POR to M4 execution for some specific fast-boot use-cases.
73      * Please refer to Boot Flow chapter of System Controller Firmware Porting Guide document for more information.
74      */
75     if (sc_misc_boot_done(ipcHandle, BOARD_M4_CPU_RSRC) != SC_ERR_NONE)
76     {
77         assert(0);
78     }
79     return ipcHandle;
80 }
81 
BOARD_GetRpcHandle(void)82 sc_ipc_t BOARD_GetRpcHandle(void)
83 {
84     return ipcHandle;
85 }
86 
87 /*
88  * Pre Configuration of some pins
89  *  - Some physical pins default map to the same functionality and has priority, avoid such conflict
90  *    at the beginning.
91  */
BOARD_InitPinsPre(void)92 void BOARD_InitPinsPre(void)
93 {
94 }
95 
96 /* Initialize debug console. */
BOARD_InitDebugConsole(void)97 void BOARD_InitDebugConsole(void)
98 {
99     uint32_t freq = SC_133MHZ;
100 
101     /* Power on Local LPUART for M4 Core0. */
102     sc_pm_set_resource_power_mode(ipcHandle, SC_R_M4_0_UART, SC_PM_PW_MODE_ON);
103     /* Enable clock of Local LPUART for M4 Core0. */
104     CLOCK_EnableClockExt(kCLOCK_M4_0_Lpuart, 0);
105     /* Set clock Frequncy of Local LPUART for M4 Core0. */
106     freq = CLOCK_SetIpFreq(kCLOCK_M4_0_Lpuart, freq);
107 
108     /* Initialize Debug Console using local LPUART for M4 Core0. */
109     DbgConsole_Init(BOARD_DEBUG_UART_INSTANCE, BOARD_DEBUG_UART_BAUDRATE, BOARD_DEBUG_UART_TYPE, freq);
110 }
111 
112 /* Power on base board*/
BOARD_PowerOnBaseBoard(void)113 void BOARD_PowerOnBaseBoard(void)
114 {
115     // Currently only needed for VAL Board
116 }
117 
118 /* Initialize MPU, configure non-cacheable memory */
BOARD_InitMemory(void)119 void BOARD_InitMemory(void)
120 {
121 #if defined(__CC_ARM) || defined(__ARMCC_VERSION)
122     extern uint32_t Load$$LR$$LR_cache_region$$Base[];
123     extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[];
124     uint32_t cacheStart = (uint32_t)Load$$LR$$LR_cache_region$$Base;
125     uint32_t size       = (cacheStart < 0x20000000U) ? (0) : ((uint32_t)Image$$ARM_LIB_STACK$$ZI$$Limit - cacheStart);
126 #else
127     extern uint32_t __CACHE_REGION_START[];
128     extern uint32_t __CACHE_REGION_SIZE[];
129     uint32_t cacheStart = (uint32_t)__CACHE_REGION_START;
130     uint32_t size       = (uint32_t)__CACHE_REGION_SIZE;
131 #endif
132     uint32_t i = 0;
133     /* Make sure outstanding transfers are done. */
134     __DMB();
135     /* Disable the MPU. */
136     MPU->CTRL = 0;
137 
138     /*
139        The ARMv7-M default address map define the address space 0x20000000 to 0x3FFFFFFF as SRAM with Normal type, but
140        there the address
141        space 0x28000000 ~ 0x3FFFFFFF has been physically mapped to smart subsystems, so there need change the default
142        memory attributes.
143        Since the base address of MPU region should be multiples of region size, to make it simple, the MPU region 0 set
144        the all 512M of SRAM space
145        with device attributes, then disable subregion 0 and 1 (address space 0x20000000 ~ 0x27FFFFFF) to use the
146        background memory attributes.
147     */
148 
149     /* Select Region 0 and set its base address to the M4 code bus start address. */
150     MPU->RBAR = (0x20000000U & MPU_RBAR_ADDR_Msk) | MPU_RBAR_VALID_Msk | (0 << MPU_RBAR_REGION_Pos);
151 
152     /* Region 0 setting:
153      * 1) Disable Instruction Access;
154      * 2) AP = 011b, full access;
155      * 3) Non-shared device;
156      * 4) Region Not Shared;
157      * 5) Sub-Region 0,1 Disabled;
158      * 6) MPU Protection Region size = 512M byte;
159      * 7) Enable Region 0.
160      */
161     MPU->RASR = (0x1 << MPU_RASR_XN_Pos) | (0x3 << MPU_RASR_AP_Pos) | (0x2 << MPU_RASR_TEX_Pos) |
162                 (0x3 << MPU_RASR_SRD_Pos) | (28 << MPU_RASR_SIZE_Pos) | MPU_RASR_ENABLE_Msk;
163 
164     /*
165        Non-cacheable area is provided in DDR memory, the DDR region 2MB - 128MB totally 126MB is revserved for CM4
166        cores.
167        You can put global or static uninitialized variables in NonCacheable section(initialized variables in
168        NonCacheable.init section)
169        to make them uncacheable. Since the base address of MPU region should be multiples of region size, to make it
170        simple,
171        the MPU region 1 set the address space 0x80000000 ~ 0xFFFFFFFF to be non-cacheable(disable sub-region 6,7 to use
172        the background memory
173        attributes for address space 0xE0000000 ~ 0xFFFFFFFF). Then MPU region 2 set the text and data section to be
174        cacheable if the program running
175        on DDR. The cacheable area base address should be multiples of its size in linker file, they can be modified per
176        your needs.
177     */
178 
179     /* Select Region 1 and set its base address to the DDR start address. */
180     MPU->RBAR = (0x80000000U & MPU_RBAR_ADDR_Msk) | MPU_RBAR_VALID_Msk | (1 << MPU_RBAR_REGION_Pos);
181 
182     /* Region 1 setting:
183      * 1) Enable Instruction Access;
184      * 2) AP = 011b, full access;
185      * 3) Shared Device;
186      * 4) Sub-Region 6,7 Disabled;
187      * 5) MPU Protection Region size = 2048M byte;
188      * 6) Enable Region 1.
189      */
190     MPU->RASR = (0x3 << MPU_RASR_AP_Pos) | (0x1 << MPU_RASR_B_Pos) | (0xC0 << MPU_RASR_SRD_Pos) |
191                 (30 << MPU_RASR_SIZE_Pos) | MPU_RASR_ENABLE_Msk;
192 
193     while ((size >> i) > 0x1U)
194     {
195         i++;
196     }
197 
198     /* If run on DDR, configure text and data section to be cacheable */
199     if (i != 0)
200     {
201         /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
202         assert((size & (size - 1)) == 0);
203         assert(!(cacheStart % size));
204         assert(size == (uint32_t)(1 << i));
205         assert(i >= 5);
206 
207         /* Select Region 2 and set its base address to the cache able region start address. */
208         MPU->RBAR = (cacheStart & MPU_RBAR_ADDR_Msk) | MPU_RBAR_VALID_Msk | (2 << MPU_RBAR_REGION_Pos);
209 
210         /* Region 2 setting:
211          * 1) Enable Instruction Access;
212          * 2) AP = 011b, full access;
213          * 3) Outer and inner Cacheable, write and read allocate;
214          * 4) Region Not Shared;
215          * 5) All Sub-Region Enabled;
216          * 6) MPU Protection Region size get from linker file;
217          * 7) Enable Region 2.
218          */
219         MPU->RASR = (0x3 << MPU_RASR_AP_Pos) | (0x1 << MPU_RASR_TEX_Pos) | (0x1 << MPU_RASR_C_Pos) |
220                     (0x1 << MPU_RASR_B_Pos) | ((i - 1) << MPU_RASR_SIZE_Pos) | MPU_RASR_ENABLE_Msk;
221     }
222 
223     /* Enable Privileged default memory map and the MPU. */
224     MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_PRIVDEFENA_Msk;
225     /* Memory barriers to ensure subsequence data & instruction
226      * transfers using updated MPU settings.
227      */
228     __DSB();
229     __ISB();
230 }
231 
232 #if defined(SDK_I2C_BASED_COMPONENT_USED) && SDK_I2C_BASED_COMPONENT_USED
BOARD_LPI2C_Init(LPI2C_Type * base,uint32_t clkSrc_Hz)233 void BOARD_LPI2C_Init(LPI2C_Type *base, uint32_t clkSrc_Hz)
234 {
235     lpi2c_master_config_t lpi2cConfig = {0};
236 
237     /*
238      * lpi2cConfig.debugEnable = false;
239      * lpi2cConfig.ignoreAck = false;
240      * lpi2cConfig.pinConfig = kLPI2C_2PinOpenDrain;
241      * lpi2cConfig.baudRate_Hz = 100000U;
242      * lpi2cConfig.busIdleTimeout_ns = 0;
243      * lpi2cConfig.pinLowTimeout_ns = 0;
244      * lpi2cConfig.sdaGlitchFilterWidth_ns = 0;
245      * lpi2cConfig.sclGlitchFilterWidth_ns = 0;
246      */
247     LPI2C_MasterGetDefaultConfig(&lpi2cConfig);
248     LPI2C_MasterInit(base, &lpi2cConfig, clkSrc_Hz);
249 }
250 
BOARD_LPI2C_Deinit(LPI2C_Type * base)251 void BOARD_LPI2C_Deinit(LPI2C_Type *base)
252 {
253     LPI2C_MasterDeinit(base);
254 }
255 
BOARD_LPI2C_Send(LPI2C_Type * base,const uint8_t dev_addr,uint32_t subAddress,uint32_t subaddressSize,uint8_t * txBuff,uint32_t txSize)256 status_t BOARD_LPI2C_Send(LPI2C_Type *base,
257                           const uint8_t dev_addr,
258                           uint32_t subAddress,
259                           uint32_t subaddressSize,
260                           uint8_t *txBuff,
261                           uint32_t txSize)
262 {
263     lpi2c_master_transfer_t xfer;
264 
265     xfer.flags          = kLPI2C_TransferDefaultFlag;
266     xfer.slaveAddress   = dev_addr;
267     xfer.direction      = kLPI2C_Write;
268     xfer.subaddress     = subAddress;
269     xfer.subaddressSize = subaddressSize;
270     xfer.data           = txBuff;
271     xfer.dataSize       = txSize;
272 
273     return LPI2C_MasterTransferBlocking(base, &xfer);
274 }
275 
BOARD_LPI2C_SendWithoutSubAddr(LPI2C_Type * base,uint32_t baudRate_Hz,uint8_t deviceAddress,uint8_t * txBuff,uint8_t txBuffSize,bool needStop)276 status_t BOARD_LPI2C_SendWithoutSubAddr(
277     LPI2C_Type *base, uint32_t baudRate_Hz, uint8_t deviceAddress, uint8_t *txBuff, uint8_t txBuffSize, bool needStop)
278 {
279     status_t reVal;
280     size_t txCount = 0xFFU;
281     size_t txSize  = 0;
282 
283     /*
284      * I2C SCLK cycle duration in us, get the next larger integer if can not be divided with no remainder to retain
285      * enough time
286      */
287     uint32_t delayUsPerSCLK = (1000000U + baudRate_Hz - 1U) / baudRate_Hz;
288 
289     /* Send master blocking data to slave */
290     reVal = LPI2C_MasterStart(base, deviceAddress, kLPI2C_Write);
291     if (kStatus_Success == reVal)
292     {
293         /* Check master tx FIFO empty or not */
294         LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
295         while (txCount)
296         {
297             LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
298         }
299         /*
300          * wait for 18 cycle to ensure the ack/nack cycle ends
301          *
302          * Note : In theory 9 cycles is enough for host to detect a slave NAK, however
303          * on board circut may cause SDA pull up slower than expected, result a delayed
304          * NAK signal. Here we increase the delay cycle twice of original for a
305          * safe NAK detection
306          */
307         SDK_DelayAtLeastUs(18 * delayUsPerSCLK, SystemCoreClock);
308         /* Check communicate with slave successful or not */
309         if (LPI2C_MasterGetStatusFlags(base) & kLPI2C_MasterNackDetectFlag)
310         {
311             return kStatus_LPI2C_Nak;
312         }
313 
314         /* Check each response from slave */
315         for (txSize = 0; txSize < txBuffSize; txSize++)
316         {
317             reVal = LPI2C_MasterSend(base, &txBuff[txSize], 1);
318             /* Check master tx FIFO empty or not */
319             LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
320             while (txCount)
321             {
322                 LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
323             }
324             /* wait for 9 cycle to ensure the ack/nack cycle ends */
325             SDK_DelayAtLeastUs(9 * delayUsPerSCLK, SystemCoreClock);
326             /* Check communicate with slave successful or not */
327             if (LPI2C_MasterGetStatusFlags(base) & kLPI2C_MasterNackDetectFlag)
328             {
329                 return kStatus_LPI2C_Nak;
330             }
331         }
332 
333         if (reVal != kStatus_Success)
334         {
335             return reVal;
336         }
337 
338         if (needStop)
339         {
340             reVal = LPI2C_MasterStop(base);
341             if (reVal != kStatus_Success)
342             {
343                 return reVal;
344             }
345         }
346     }
347 
348     return reVal;
349 }
350 
BOARD_LPI2C_Receive(LPI2C_Type * base,uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * rxBuff,uint8_t rxBuffSize)351 status_t BOARD_LPI2C_Receive(LPI2C_Type *base,
352                              uint8_t deviceAddress,
353                              uint32_t subAddress,
354                              uint8_t subAddressSize,
355                              uint8_t *rxBuff,
356                              uint8_t rxBuffSize)
357 {
358     lpi2c_master_transfer_t xfer;
359 
360     xfer.flags          = kLPI2C_TransferDefaultFlag;
361     xfer.slaveAddress   = deviceAddress;
362     xfer.direction      = kLPI2C_Read;
363     xfer.subaddress     = subAddress;
364     xfer.subaddressSize = subAddressSize;
365     xfer.data           = rxBuff;
366     xfer.dataSize       = rxBuffSize;
367 
368     return LPI2C_MasterTransferBlocking(base, &xfer);
369 }
370 
BOARD_LPI2C_ReceiveWithoutSubAddr(LPI2C_Type * base,uint32_t baudRate_Hz,uint8_t deviceAddress,uint8_t * rxBuff,uint8_t rxBuffSize,uint8_t flags)371 status_t BOARD_LPI2C_ReceiveWithoutSubAddr(
372     LPI2C_Type *base, uint32_t baudRate_Hz, uint8_t deviceAddress, uint8_t *rxBuff, uint8_t rxBuffSize, uint8_t flags)
373 {
374     status_t reVal;
375     size_t txCount = 0xFFU;
376     /*
377      * I2C SCLK cycle duration in us, get the next larger integer if can not be divided with no remainder to retain
378      * enough time
379      */
380     uint32_t delayUsPerSCLK = (1000000U + baudRate_Hz - 1U) / baudRate_Hz;
381 
382     reVal = LPI2C_MasterStart(base, deviceAddress, kLPI2C_Read);
383     if (kStatus_Success == reVal)
384     {
385         /* Check master tx FIFO empty or not */
386         LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
387         while (txCount)
388         {
389             LPI2C_MasterGetFifoCounts(base, NULL, &txCount);
390         }
391         /* wait for 9 cycle to ensure the ack/nack cycle ends */
392         SDK_DelayAtLeastUs(9 * delayUsPerSCLK, SystemCoreClock);
393         /* Check communicate with slave successful or not */
394         if (LPI2C_MasterGetStatusFlags(base) & kLPI2C_MasterNackDetectFlag)
395         {
396             return kStatus_LPI2C_Nak;
397         }
398 
399         reVal = LPI2C_MasterReceive(base, rxBuff, rxBuffSize);
400         if (reVal != kStatus_Success)
401         {
402             return reVal;
403         }
404 
405         reVal = LPI2C_MasterStop(base);
406         if (reVal != kStatus_Success)
407         {
408             return reVal;
409         }
410     }
411     return reVal;
412 }
413 
BOARD_LPI2C_SendSCCB(LPI2C_Type * base,uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * txBuff,uint8_t txBuffSize)414 status_t BOARD_LPI2C_SendSCCB(LPI2C_Type *base,
415                               uint8_t deviceAddress,
416                               uint32_t subAddress,
417                               uint8_t subAddressSize,
418                               uint8_t *txBuff,
419                               uint8_t txBuffSize)
420 {
421     lpi2c_master_transfer_t xfer;
422 
423     xfer.flags          = kLPI2C_TransferDefaultFlag;
424     xfer.slaveAddress   = deviceAddress;
425     xfer.direction      = kLPI2C_Write;
426     xfer.subaddress     = subAddress;
427     xfer.subaddressSize = subAddressSize;
428     xfer.data           = txBuff;
429     xfer.dataSize       = txBuffSize;
430 
431     return LPI2C_MasterTransferBlocking(base, &xfer);
432 }
433 
BOARD_LPI2C_ReceiveSCCB(LPI2C_Type * base,uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * rxBuff,uint8_t rxBuffSize)434 status_t BOARD_LPI2C_ReceiveSCCB(LPI2C_Type *base,
435                                  uint8_t deviceAddress,
436                                  uint32_t subAddress,
437                                  uint8_t subAddressSize,
438                                  uint8_t *rxBuff,
439                                  uint8_t rxBuffSize)
440 {
441     status_t status;
442     lpi2c_master_transfer_t xfer;
443 
444     xfer.flags          = kLPI2C_TransferDefaultFlag;
445     xfer.slaveAddress   = deviceAddress;
446     xfer.direction      = kLPI2C_Write;
447     xfer.subaddress     = subAddress;
448     xfer.subaddressSize = subAddressSize;
449     xfer.data           = NULL;
450     xfer.dataSize       = 0;
451 
452     status = LPI2C_MasterTransferBlocking(base, &xfer);
453 
454     if (kStatus_Success == status)
455     {
456         xfer.subaddressSize = 0;
457         xfer.direction      = kLPI2C_Read;
458         xfer.data           = rxBuff;
459         xfer.dataSize       = rxBuffSize;
460 
461         status = LPI2C_MasterTransferBlocking(base, &xfer);
462     }
463 
464     return status;
465 }
466 
BOARD_Display0_I2C_Init(void)467 void BOARD_Display0_I2C_Init(void)
468 {
469     uint32_t lpi2cClkFreq_Hz = SC_24MHZ;
470     sc_err_t err             = SC_ERR_NONE;
471     sc_ipc_t ipc             = BOARD_GetRpcHandle();
472 
473     err = sc_pm_set_resource_power_mode(ipc, SC_R_MIPI_0_I2C_0, SC_PM_PW_MODE_ON);
474     if (SC_ERR_NONE != err)
475     {
476         assert(false);
477     }
478 
479     err = sc_pm_set_clock_rate(ipc, SC_R_MIPI_0_I2C_0, SC_PM_CLK_PER, &lpi2cClkFreq_Hz);
480     if (SC_ERR_NONE != err)
481     {
482         assert(false);
483     }
484 
485     BOARD_LPI2C_Init(BOARD_DISPLAY0_I2C_BASEADDR, lpi2cClkFreq_Hz);
486 }
487 
BOARD_Display1_I2C_Init(void)488 void BOARD_Display1_I2C_Init(void)
489 {
490     uint32_t lpi2cClkFreq_Hz = SC_24MHZ;
491     sc_err_t err             = SC_ERR_NONE;
492     sc_ipc_t ipc             = BOARD_GetRpcHandle();
493 
494     err = sc_pm_set_resource_power_mode(ipc, SC_R_MIPI_1_I2C_0, SC_PM_PW_MODE_ON);
495     if (SC_ERR_NONE != err)
496     {
497         assert(false);
498     }
499 
500     err = sc_pm_set_clock_rate(ipc, SC_R_MIPI_1_I2C_0, SC_PM_CLK_PER, &lpi2cClkFreq_Hz);
501     if (SC_ERR_NONE != err)
502     {
503         assert(false);
504     }
505 
506     BOARD_LPI2C_Init(BOARD_DISPLAY1_I2C_BASEADDR, lpi2cClkFreq_Hz);
507 }
508 
BOARD_Display0_I2C_Deinit(void)509 void BOARD_Display0_I2C_Deinit(void)
510 {
511     sc_err_t err = SC_ERR_NONE;
512     sc_ipc_t ipc = BOARD_GetRpcHandle();
513 
514     BOARD_LPI2C_Deinit(BOARD_DISPLAY0_I2C_BASEADDR);
515 
516     err = sc_pm_set_resource_power_mode(ipc, SC_R_MIPI_0_I2C_0, SC_PM_PW_MODE_OFF);
517     if (SC_ERR_NONE != err)
518     {
519         assert(false);
520     }
521 }
522 
BOARD_Display1_I2C_Deinit(void)523 void BOARD_Display1_I2C_Deinit(void)
524 {
525     sc_err_t err = SC_ERR_NONE;
526     sc_ipc_t ipc = BOARD_GetRpcHandle();
527 
528     BOARD_LPI2C_Deinit(BOARD_DISPLAY1_I2C_BASEADDR);
529 
530     err = sc_pm_set_resource_power_mode(ipc, SC_R_MIPI_1_I2C_0, SC_PM_PW_MODE_OFF);
531     if (SC_ERR_NONE != err)
532     {
533         assert(false);
534     }
535 }
536 
BOARD_Display0_I2C_Send(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,const uint8_t * txBuff,uint8_t txBuffSize)537 status_t BOARD_Display0_I2C_Send(
538     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, const uint8_t *txBuff, uint8_t txBuffSize)
539 {
540     return BOARD_LPI2C_Send(BOARD_DISPLAY0_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, (uint8_t *)txBuff,
541                             txBuffSize);
542 }
543 
BOARD_Display0_I2C_Receive(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * rxBuff,uint8_t rxBuffSize)544 status_t BOARD_Display0_I2C_Receive(
545     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, uint8_t *rxBuff, uint8_t rxBuffSize)
546 {
547     return BOARD_LPI2C_Receive(BOARD_DISPLAY0_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, rxBuff,
548                                rxBuffSize);
549 }
550 
BOARD_Display1_I2C_Send(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,const uint8_t * txBuff,uint8_t txBuffSize)551 status_t BOARD_Display1_I2C_Send(
552     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, const uint8_t *txBuff, uint8_t txBuffSize)
553 {
554     return BOARD_LPI2C_Send(BOARD_DISPLAY1_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, (uint8_t *)txBuff,
555                             txBuffSize);
556 }
557 
BOARD_Display1_I2C_Receive(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * rxBuff,uint8_t rxBuffSize)558 status_t BOARD_Display1_I2C_Receive(
559     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, uint8_t *rxBuff, uint8_t rxBuffSize)
560 {
561     return BOARD_LPI2C_Receive(BOARD_DISPLAY1_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, rxBuff,
562                                rxBuffSize);
563 }
564 
BOARD_Camera0_I2C_Init(void)565 void BOARD_Camera0_I2C_Init(void)
566 {
567     uint32_t lpi2cClkFreq_Hz = SC_24MHZ;
568     sc_err_t err             = SC_ERR_NONE;
569     sc_ipc_t ipc             = BOARD_GetRpcHandle();
570 
571     err = sc_pm_set_resource_power_mode(ipc, BOARD_CAMERA0_I2C_RSRC, SC_PM_PW_MODE_ON);
572     if (SC_ERR_NONE != err)
573     {
574         assert(false);
575     }
576 
577     err = sc_pm_set_clock_rate(ipc, BOARD_CAMERA0_I2C_RSRC, SC_PM_CLK_PER, &lpi2cClkFreq_Hz);
578     if (SC_ERR_NONE != err)
579     {
580         assert(false);
581     }
582 
583     lpi2c_master_config_t lpi2cConfig = {0};
584     /*
585      * lpi2cConfig.debugEnable = false;
586      * lpi2cConfig.ignoreAck = false;
587      * lpi2cConfig.pinConfig = kLPI2C_2PinOpenDrain;
588      * lpi2cConfig.baudRate_Hz = 100000U;
589      * lpi2cConfig.busIdleTimeout_ns = 0;
590      * lpi2cConfig.pinLowTimeout_ns = 0;
591      * lpi2cConfig.sdaGlitchFilterWidth_ns = 0;
592      * lpi2cConfig.sclGlitchFilterWidth_ns = 0;
593      */
594     LPI2C_MasterGetDefaultConfig(&lpi2cConfig);
595     lpi2cConfig.baudRate_Hz = 400000U;
596     LPI2C_MasterInit(BOARD_CAMERA0_I2C_BASEADDR, &lpi2cConfig, lpi2cClkFreq_Hz);
597 }
598 
BOARD_Camera1_I2C_Init(void)599 void BOARD_Camera1_I2C_Init(void)
600 {
601     uint32_t lpi2cClkFreq_Hz = SC_24MHZ;
602     sc_err_t err             = SC_ERR_NONE;
603     sc_ipc_t ipc             = BOARD_GetRpcHandle();
604 
605     err = sc_pm_set_resource_power_mode(ipc, BOARD_CAMERA1_I2C_RSRC, SC_PM_PW_MODE_ON);
606     if (SC_ERR_NONE != err)
607     {
608         assert(false);
609     }
610 
611     err = sc_pm_set_clock_rate(ipc, BOARD_CAMERA1_I2C_RSRC, SC_PM_CLK_PER, &lpi2cClkFreq_Hz);
612     if (SC_ERR_NONE != err)
613     {
614         assert(false);
615     }
616 
617     BOARD_LPI2C_Init(BOARD_CAMERA1_I2C_BASEADDR, lpi2cClkFreq_Hz);
618 }
619 
BOARD_Camera0_I2C_Deinit(void)620 void BOARD_Camera0_I2C_Deinit(void)
621 {
622     sc_err_t err = SC_ERR_NONE;
623     sc_ipc_t ipc = BOARD_GetRpcHandle();
624 
625     BOARD_LPI2C_Deinit(BOARD_CAMERA0_I2C_BASEADDR);
626 
627     err = sc_pm_set_resource_power_mode(ipc, BOARD_CAMERA0_I2C_RSRC, SC_PM_PW_MODE_OFF);
628     if (SC_ERR_NONE != err)
629     {
630         assert(false);
631     }
632 }
633 
BOARD_Camera1_I2C_Deinit(void)634 void BOARD_Camera1_I2C_Deinit(void)
635 {
636     sc_err_t err = SC_ERR_NONE;
637     sc_ipc_t ipc = BOARD_GetRpcHandle();
638 
639     BOARD_LPI2C_Deinit(BOARD_CAMERA1_I2C_BASEADDR);
640 
641     err = sc_pm_set_resource_power_mode(ipc, BOARD_CAMERA1_I2C_RSRC, SC_PM_PW_MODE_OFF);
642     if (SC_ERR_NONE != err)
643     {
644         assert(false);
645     }
646 }
647 
BOARD_Camera0_I2C_SendSCCB(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,const uint8_t * txBuff,uint8_t txBuffSize)648 status_t BOARD_Camera0_I2C_SendSCCB(
649     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, const uint8_t *txBuff, uint8_t txBuffSize)
650 {
651     return BOARD_LPI2C_SendSCCB(BOARD_CAMERA0_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize,
652                                 (uint8_t *)txBuff, txBuffSize);
653 }
654 
BOARD_Camera0_I2C_ReceiveSCCB(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * rxBuff,uint8_t rxBuffSize)655 status_t BOARD_Camera0_I2C_ReceiveSCCB(
656     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, uint8_t *rxBuff, uint8_t rxBuffSize)
657 {
658     return BOARD_LPI2C_ReceiveSCCB(BOARD_CAMERA0_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, rxBuff,
659                                    rxBuffSize);
660 }
661 
BOARD_Camera1_I2C_SendSCCB(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,const uint8_t * txBuff,uint8_t txBuffSize)662 status_t BOARD_Camera1_I2C_SendSCCB(
663     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, const uint8_t *txBuff, uint8_t txBuffSize)
664 {
665     return BOARD_LPI2C_SendSCCB(BOARD_CAMERA1_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize,
666                                 (uint8_t *)txBuff, txBuffSize);
667 }
668 
BOARD_Camera1_I2C_ReceiveSCCB(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * rxBuff,uint8_t rxBuffSize)669 status_t BOARD_Camera1_I2C_ReceiveSCCB(
670     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, uint8_t *rxBuff, uint8_t rxBuffSize)
671 {
672     return BOARD_LPI2C_ReceiveSCCB(BOARD_CAMERA1_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, rxBuff,
673                                    rxBuffSize);
674 }
675 
BOARD_Codec_I2C_Init(void)676 void BOARD_Codec_I2C_Init(void)
677 {
678     BOARD_LPI2C_Init(BOARD_CODEC_I2C_BASEADDR, BOARD_CODEC_I2C_CLOCK_FREQ);
679 }
680 
BOARD_Codec_I2C_Send(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,const uint8_t * txBuff,uint8_t txBuffSize)681 status_t BOARD_Codec_I2C_Send(
682     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, const uint8_t *txBuff, uint8_t txBuffSize)
683 {
684     return BOARD_LPI2C_Send(BOARD_CODEC_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, (uint8_t *)txBuff,
685                             txBuffSize);
686 }
687 
BOARD_Codec_I2C_Receive(uint8_t deviceAddress,uint32_t subAddress,uint8_t subAddressSize,uint8_t * rxBuff,uint8_t rxBuffSize)688 status_t BOARD_Codec_I2C_Receive(
689     uint8_t deviceAddress, uint32_t subAddress, uint8_t subAddressSize, uint8_t *rxBuff, uint8_t rxBuffSize)
690 {
691     return BOARD_LPI2C_Receive(BOARD_CODEC_I2C_BASEADDR, deviceAddress, subAddress, subAddressSize, rxBuff, rxBuffSize);
692 }
693 #endif
694 
695 #ifdef BOARD_USE_SCFW_IRQ
BOARDInvokeHandler(sc_event_type_t event)696 static inline void BOARDInvokeHandler(sc_event_type_t event)
697 {
698     eventHandler handler = s_BOARDEventHandler[event];
699     void *param          = s_BOARDEventHandlerParam[event];
700     if (handler)
701     {
702         handler(param);
703     }
704 }
705 /*
706  * Register APP Specific SCU Event Handler
707  */
BOARD_CheckNextWakeupButton(void)708 static sc_pad_t BOARD_CheckNextWakeupButton(void)
709 {
710     pad_ele_t pad_ele;
711     sc_pad_wakeup_t status;
712 
713     pad_ele = wakeup_padlist;
714     if (NULL == pad_ele)
715     {
716         return 0;
717     }
718 
719     for (;;)
720     {
721         sc_pad_get_wakeup(ipcHandle, pad_ele->pad, &status);
722         if (SC_PAD_WAKEUP_OFF == status)
723         {
724             return pad_ele->pad;
725         }
726         else
727         {
728             pad_ele = pad_ele->next;
729             if (pad_ele == wakeup_padlist)
730             {
731                 return 0;
732             }
733         }
734     }
735 }
736 
BOARD_RegisterEventHandler(sc_event_type_t event,eventHandler handler,void * param)737 void BOARD_RegisterEventHandler(sc_event_type_t event, eventHandler handler, void *param)
738 {
739     s_BOARDEventHandler[event]      = handler;
740     s_BOARDEventHandlerParam[event] = param;
741 }
742 
743 /*
744  * BOARD_SCEventHandler act as callback of the timer started by SCEvent IRQ
745  */
746 #ifdef FSL_RTOS_FREE_RTOS
BOARD_SCEventHandler(TimerHandle_t xTimer)747 static void BOARD_SCEventHandler(TimerHandle_t xTimer)
748 #else
749 static void BOARD_SCEventHandler(void)
750 #endif
751 {
752     uint32_t status;
753     sc_irq_status(ipcHandle, IPC_MU_RSRC, SC_IRQ_GROUP_REBOOT, &status);
754     /*
755      * If Peer Core Reset happens
756      */
757     if (status & (0x1 << a_pt))
758     {
759         BOARDInvokeHandler(kSCEvent_PeerCoreReboot);
760     }
761 
762     sc_irq_status(ipcHandle, IPC_MU_RSRC, SC_IRQ_GROUP_WAKE, &status);
763     if (status & SC_IRQ_BUTTON)
764     {
765         BOARDInvokeHandler(kSCEvent_Button);
766     }
767     if (status & SC_IRQ_PAD)
768     {
769         *(sc_pad_t *)s_BOARDEventHandlerParam[kSCEvent_Pad] = BOARD_CheckNextWakeupButton();
770         BOARDInvokeHandler(kSCEvent_Pad);
771     }
772     /*
773      * TODO Other Event happens
774      */
775 }
776 
Padlist_Find(pad_ele_t head,sc_pad_t pad)777 static inline pad_ele_t Padlist_Find(pad_ele_t head, sc_pad_t pad)
778 {
779     pad_ele_t pad_ele;
780     if (NULL == head)
781         return NULL;
782     pad_ele = head;
783     for (;;)
784     {
785         if (pad_ele->pad == pad)
786         {
787             return pad_ele;
788         }
789         pad_ele = pad_ele->next;
790         if (pad_ele == head)
791         {
792             return NULL;
793         }
794     }
795 }
796 
Padlist_Insert(pad_ele_t head,pad_ele_t ele)797 static inline void Padlist_Insert(pad_ele_t head, pad_ele_t ele)
798 {
799     assert(head);
800     assert(ele);
801 
802     ele->prev        = head->prev;
803     ele->next        = head;
804     head->prev->next = ele;
805     head->prev       = ele;
806 }
807 
Padlist_Remove(pad_ele_t head,pad_ele_t ele)808 static inline void Padlist_Remove(pad_ele_t head, pad_ele_t ele)
809 {
810     ele->prev->next = ele->next;
811     ele->next->prev = ele->prev;
812 }
813 /*
814  * BOARD_EnablePadWakeup
815  */
816 
BOARD_EnablePadWakeup(sc_pad_t pad,bool enable,sc_pad_wakeup_t pad_wakeup_config)817 void BOARD_EnablePadWakeup(sc_pad_t pad, bool enable, sc_pad_wakeup_t pad_wakeup_config)
818 {
819     pad_ele_t pad_ele;
820 
821     if (enable)
822     {
823         /*
824          * Create the new element
825          */
826         if (Padlist_Find(wakeup_padlist, pad))
827         {
828             /*
829              * Already enabled
830              */
831             return;
832         }
833         else
834         {
835             pad_ele       = malloc(sizeof(struct _pad_ele));
836             pad_ele->next = pad_ele;
837             pad_ele->prev = pad_ele;
838             pad_ele->pad  = pad;
839             /*
840              * Insert to link list
841              */
842             if (NULL == wakeup_padlist)
843             {
844                 wakeup_padlist = pad_ele;
845             }
846             else
847             {
848                 Padlist_Insert(wakeup_padlist, pad_ele);
849             }
850 
851             /*
852              * Invoke SCFW to enable the pad wakeup
853              */
854             sc_pad_set_wakeup(ipcHandle, pad, pad_wakeup_config);
855         }
856     }
857     else
858     {
859         pad_ele = Padlist_Find(wakeup_padlist, pad);
860         if (pad_ele != NULL)
861         {
862             if (pad_ele->next == pad_ele)
863             {
864                 wakeup_padlist = NULL;
865             }
866             else
867             {
868                 Padlist_Remove(wakeup_padlist, pad_ele);
869             }
870             pad_ele->pad  = 0;
871             pad_ele->next = NULL;
872             pad_ele->prev = NULL;
873             free(pad_ele);
874             sc_pad_set_wakeup(ipcHandle, pad, SC_PAD_WAKEUP_OFF);
875         }
876         else
877         {
878             /*
879              * not enabled yet
880              */
881             return;
882         }
883     }
884 }
885 
886 /*
887  * Enable/Disable Receiving IRQ from SCFW
888  */
BOARD_EnableSCEvent(uint32_t mask,bool enable)889 void BOARD_EnableSCEvent(uint32_t mask, bool enable)
890 {
891     sc_ipc_t ipc;
892     uint32_t status;
893     ipc                                      = BOARD_GetRpcHandle();
894     static uint8_t enable_cnt[kSCEvent_Last] = {0};
895     static uint8_t overall_enable_cnt        = 0;
896 
897     if (enable)
898     {
899         /*
900          * Enable Peer Core Reset IRQ
901          */
902         if (mask & SC_EVENT_MASK(kSCEvent_PeerCoreReboot))
903         {
904             if (1 == ++enable_cnt[kSCEvent_PeerCoreReboot])
905             {
906                 sc_rm_get_resource_owner(ipc, SC_R_A35, &a_pt);
907                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_REBOOT, 0x1 << a_pt, true);
908             }
909             overall_enable_cnt++;
910         }
911         /*
912          * PAD IRQ
913          */
914         if (mask & SC_EVENT_MASK(kSCEvent_Pad))
915         {
916             if (1 == ++enable_cnt[kSCEvent_Pad])
917             {
918                 /*
919                  * Clear the interrupt first to avoid residue pending status
920                  */
921                 sc_irq_status(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_WAKE, &status);
922                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_WAKE, SC_IRQ_PAD, true);
923             }
924             overall_enable_cnt++;
925         }
926         /*
927          * BUTTON IRQ
928          */
929         if (mask & SC_EVENT_MASK(kSCEvent_Button))
930         {
931             if (1 == ++enable_cnt[kSCEvent_Button])
932             {
933                 /*
934                  * Clear the interrupt first to avoid residue pending status
935                  */
936                 sc_irq_status(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_WAKE, &status);
937                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, true);
938             }
939             overall_enable_cnt++;
940         }
941         /*
942          *  SYSCTR IRQ
943          */
944         if (mask & SC_EVENT_MASK(kSCEvent_SysCtr))
945         {
946             if (1 == ++enable_cnt[kSCEvent_SysCtr])
947             {
948                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_SYSCTR, SC_IRQ_SYSCTR, true);
949             }
950             overall_enable_cnt++;
951         }
952         /*
953          * TODO Enable Other IRQ
954          */
955 
956         /*
957          * Clear any pending Flags
958          */
959         /*
960          * Enable the MU Interrupt to receive SCFW IRQ
961          */
962     }
963     else
964     {
965         /*
966          * Disable Peer Core Reset IRQ
967          */
968         if ((mask & SC_EVENT_MASK(kSCEvent_PeerCoreReboot)) && (enable_cnt[kSCEvent_PeerCoreReboot] > 0))
969         {
970             if (0 == --enable_cnt[kSCEvent_PeerCoreReboot])
971             {
972                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_REBOOT, 0x1 << a_pt, false);
973             }
974             overall_enable_cnt--;
975         }
976         /*
977          * PAD IRQ
978          */
979         if ((mask & SC_EVENT_MASK(kSCEvent_Pad)) && (enable_cnt[kSCEvent_Pad] > 0))
980         {
981             if (0 == --enable_cnt[kSCEvent_Pad])
982             {
983                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_WAKE, SC_IRQ_PAD, false);
984             }
985             overall_enable_cnt--;
986         }
987         /*
988          * BUTTON IRQ
989          */
990         if ((mask & SC_EVENT_MASK(kSCEvent_Button)) && (enable_cnt[kSCEvent_Button] > 0))
991         {
992             if (0 == --enable_cnt[kSCEvent_Button])
993             {
994                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false);
995             }
996             overall_enable_cnt--;
997         }
998         /*
999          *  SYSCTR IRQ
1000          */
1001         if ((mask & (1 << kSCEvent_SysCtr)) && (enable_cnt[kSCEvent_SysCtr] > 0))
1002         {
1003             if (0 == --enable_cnt[kSCEvent_SysCtr])
1004             {
1005                 sc_irq_enable(ipc, IPC_MU_RSRC, SC_IRQ_GROUP_SYSCTR, SC_IRQ_SYSCTR, false);
1006             }
1007             overall_enable_cnt--;
1008         }
1009         /*
1010          * TODO Disable Other IRQ
1011          */
1012         /*
1013          * Disable the MU Interrupt to receive SCFW IRQ
1014          */
1015     }
1016 }
1017 
1018 /*
1019  * BOARD_Enable_SCIRQ
1020  * Note : The SCU IRQ must be enabled for M4 to enter WAIT/STOP mode
1021  * If NVIC don't enable the M4_MU1_A_IRQn IRQ, WFI will simply exit
1022  */
BOARD_Enable_SCIRQ(bool enable)1023 void BOARD_Enable_SCIRQ(bool enable)
1024 {
1025     static uint32_t enable_cnt = 0;
1026     MU_ClearStatusFlags(IPC_MU, MU_SR_GIPn_MASK);
1027 
1028     if (enable)
1029     {
1030         enable_cnt++;
1031         /*
1032          * Create a timer
1033          */
1034         if (enable_cnt == 1)
1035         {
1036 #ifdef FSL_RTOS_FREE_RTOS
1037             /*
1038              * SCFW API cannot be invoked in ISR context. The Reboot ISR will start a timer with its callback
1039              * handling follow up SCFW API call. Timer period set to 1 to let the callback get executed ASAP
1040              */
1041             s_scuEventTimer = xTimerCreate("ScuEvent", 1U, pdFALSE, NULL, BOARD_SCEventHandler);
1042             if (!s_scuEventTimer)
1043             {
1044                 assert(false);
1045             }
1046 #endif
1047             NVIC_SetPriority(IPC_MU_IRQn, SC_RPC_MU_INTERRUPT_PRIORITY);
1048             EnableIRQ(IPC_MU_IRQn);
1049             MU_EnableInterrupts(IPC_MU, MU_SR_GIPn_MASK);
1050         }
1051     }
1052     else
1053     {
1054         assert(enable_cnt > 0);
1055         enable_cnt--;
1056         if (enable_cnt == 0)
1057         {
1058             /*
1059              * Destroy the timer
1060              */
1061 #ifdef FSL_RTOS_FREE_RTOS
1062             if (s_scuEventTimer)
1063             {
1064                 xTimerDelete(s_scuEventTimer, portMAX_DELAY);
1065                 s_scuEventTimer = NULL;
1066             }
1067 #endif
1068             MU_DisableInterrupts(IPC_MU, MU_SR_GIPn_MASK);
1069             DisableIRQ(IPC_MU_IRQn);
1070         }
1071     }
1072 }
1073 
1074 /*
1075  * Handler for SCEvent Triggling MU IRQ
1076  */
BOARD_MU_IRQHandler(void)1077 void BOARD_MU_IRQHandler(void)
1078 {
1079     /* Clear interrupt flag */
1080     MU_ClearStatusFlags(IPC_MU, MU_SR_GIPn_MASK);
1081 
1082 #ifdef FSL_RTOS_FREE_RTOS
1083     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
1084     if (s_scuEventTimer)
1085     {
1086         xTimerStartFromISR(s_scuEventTimer, &xHigherPriorityTaskWoken);
1087         if (xHigherPriorityTaskWoken != pdFALSE)
1088         {
1089             portYIELD_FROM_ISR(pdTRUE);
1090         }
1091     }
1092 #else
1093     BOARD_SCEventHandler();
1094 #endif
1095 }
1096 #endif
1097