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