101 lines
2.4 KiB
C
101 lines
2.4 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "FreeRTOS.h"
|
|
#include "semphr.h"
|
|
#include "hwspinlock.h"
|
|
#include "uart.h"
|
|
#include "register.h"
|
|
|
|
#ifndef PRINT_DBG
|
|
#define PRINT_DBG(...) //printf(__VA_ARGS__)
|
|
#define PRINT_ERR(...) printf(__VA_ARGS__)
|
|
#define PRINT(...) printf(__VA_ARGS__)
|
|
#endif
|
|
#define HWTAG "HWSPIN"
|
|
|
|
SemaphoreHandle_t xHwLockSemp[HWSPINLOCK_NUMS];
|
|
struct hwspinlock_prop {
|
|
uint32_t xAddr;
|
|
uint32_t xCpus;
|
|
};
|
|
struct hwspinlock_prop prop;
|
|
|
|
BaseType_t vHwspinLock_get(struct hwspinlock_t *hwspinlock, uint32_t id)
|
|
{
|
|
BaseType_t ret = pdTRUE;
|
|
uint32_t ulLockVal = hwspinlock->lock_data[0];
|
|
uint32_t ulCnt = 0;
|
|
|
|
if (ulLockVal != 0) {
|
|
PRINT_ERR("[%s]: locked0 idx %x by %x\n", HWTAG, id, ulLockVal);
|
|
return pdFALSE;
|
|
}
|
|
ret = xSemaphoreTake(xHwLockSemp[id], portMAX_DELAY);
|
|
if (ret == pdFALSE) {
|
|
PRINT_ERR("[%s]: Async get sempaphore fail\n", HWTAG);
|
|
configASSERT(ret);
|
|
}
|
|
lock_retry:
|
|
hwspinlock->lock_data[0] = AML_MUTEX_AO_PROC_ID;
|
|
ulLockVal = hwspinlock->lock_data[0];
|
|
if (ulLockVal == 0 && ulCnt < 3) {
|
|
ulCnt += 1;
|
|
goto lock_retry;
|
|
}
|
|
if (AML_MUTEX_AO_PROC_ID != ulLockVal) {
|
|
PRINT_ERR("[%s]: locked1 idx %x by %x\n", HWTAG, id, ulLockVal);
|
|
xSemaphoreGive(xHwLockSemp[id]);
|
|
ret = pdFALSE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void vHwspinLock_release(struct hwspinlock_t *hwspinlock, uint32_t id)
|
|
{
|
|
uint32_t ulLockVal = 0;
|
|
|
|
if (uxSemaphoreGetCount(xHwLockSemp[id])) {
|
|
PRINT_ERR("[%s]: No hwspinlock required before\n", HWTAG);
|
|
return;
|
|
}
|
|
|
|
ulLockVal = hwspinlock->lock_data[0];
|
|
if (ulLockVal != AML_MUTEX_AO_PROC_ID) {
|
|
PRINT_ERR("[%s]: Release idx %x locked by %x\n", HWTAG, id, ulLockVal);
|
|
return;
|
|
}
|
|
|
|
hwspinlock->lock_data[0] = AML_MUTEX_AO_PROC_ID;
|
|
xSemaphoreGive(xHwLockSemp[id]);
|
|
}
|
|
|
|
void vHwspinLock_init(struct hwspinlock_t **hwspinlock, uint32_t id,
|
|
void *hwspinlock_addr)
|
|
{
|
|
uint32_t xAddrOff = id * sizeof(struct hwspinlock_t);
|
|
|
|
if (!hwspinlock_addr)
|
|
hwspinlock_addr = (char *)prop.xAddr + xAddrOff;
|
|
*hwspinlock = hwspinlock_addr;
|
|
PRINT_DBG("hwspinlock addr %p\n", hwspinlock_addr);
|
|
}
|
|
|
|
void vHwLockInit(uint32_t xAddr, uint32_t xCpus)
|
|
{
|
|
int idx = 0;
|
|
|
|
prop.xAddr = xAddr;
|
|
prop.xCpus = xCpus;
|
|
|
|
for (idx = 0; idx < HWSPINLOCK_NUMS; idx++) {
|
|
xHwLockSemp[idx] = xSemaphoreCreateBinary();
|
|
configASSERT(xHwLockSemp[idx]);
|
|
xSemaphoreGive(xHwLockSemp[idx]);
|
|
}
|
|
PRINT_ERR("hwspinlock init\n");
|
|
}
|