403 lines
7.6 KiB
C
Executable File
403 lines
7.6 KiB
C
Executable File
// Copyright 2020-2021 Beken
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <driver/int.h>
|
|
#include <os/mem.h>
|
|
#include "clock_driver.h"
|
|
#include "sys_driver.h"
|
|
#include "psram_hal.h"
|
|
#include "driver/psram_types.h"
|
|
#include "psram_driver.h"
|
|
#include <driver/psram.h>
|
|
#include <modules/pm.h>
|
|
#if (CONFIG_PSRAM_AUTO_DETECT)
|
|
#include "bk_ef.h"
|
|
#endif
|
|
|
|
#define PSRAM_CHECK_FLAG 0x3CA5C3A5
|
|
typedef struct {
|
|
uint32_t psram_id;
|
|
uint32_t magic_code;
|
|
} psram_flash_t;
|
|
|
|
#if (CONFIG_PSRAM_AUTO_DETECT)
|
|
static bool s_psram_id_need_write = false;
|
|
static beken_semaphore_t s_psram_sem = NULL;
|
|
static beken_thread_t psram_task = NULL;
|
|
#endif
|
|
|
|
extern void delay_us(uint32_t us);
|
|
static bool s_psram_server_is_init = false;
|
|
static bool s_psram_heap_is_init = false;
|
|
static uint8_t s_psram_channelmap = 0;
|
|
#if (CONFIG_SYS_CPU0)
|
|
static psram_flash_t s_psram_id = {0};
|
|
#endif
|
|
#define PSRAM_RETURN_ON_SERVER_NOT_INIT() do {\
|
|
if (!s_psram_server_is_init) {\
|
|
return BK_ERR_PSRAM_SERVER_NOT_INIT;\
|
|
}\
|
|
} while(0)
|
|
|
|
bk_err_t bk_psram_set_clk(psram_clk_t clk)
|
|
{
|
|
bk_err_t ret = BK_OK;
|
|
|
|
psram_hal_set_clk(clk);
|
|
|
|
return ret;
|
|
}
|
|
bk_err_t bk_psram_heap_init_flag_set(bool init)
|
|
{
|
|
bk_err_t ret = BK_OK;
|
|
s_psram_heap_is_init = init;
|
|
return ret;
|
|
}
|
|
bool bk_psram_heap_init_flag_get()
|
|
{
|
|
return s_psram_heap_is_init;
|
|
}
|
|
|
|
bk_err_t bk_psram_set_voltage(psram_voltage_t voltage)
|
|
{
|
|
bk_err_t ret = BK_OK;
|
|
|
|
psram_hal_set_voltage(voltage);
|
|
|
|
return ret;
|
|
}
|
|
|
|
bk_err_t bk_psram_set_transfer_mode(psram_tansfer_mode_t transfer_mode)
|
|
{
|
|
bk_err_t ret = BK_OK;
|
|
|
|
psram_hal_set_transfer_mode(transfer_mode);
|
|
|
|
return ret;
|
|
}
|
|
|
|
psram_write_through_area_t bk_psram_alloc_write_through_channel(void)
|
|
{
|
|
uint8_t channel = 0;
|
|
for (channel = 0; channel < PSRAM_WRITE_THROUGH_AREA_COUNT; channel++)
|
|
{
|
|
if ((s_psram_channelmap & (0x1 << channel)) == 0)
|
|
{
|
|
s_psram_channelmap |= (0x1 << channel);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return channel;
|
|
}
|
|
|
|
bk_err_t bk_psram_free_write_through_channel(psram_write_through_area_t area)
|
|
{
|
|
if (area > PSRAM_WRITE_THROUGH_AREA_COUNT)
|
|
{
|
|
PSRAM_LOGE("%s over range failed\r\n", __func__);
|
|
return BK_OK;
|
|
}
|
|
|
|
if (s_psram_channelmap & (0x1 << area))
|
|
s_psram_channelmap &= ~(0x1 << area);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_psram_enable_write_through(psram_write_through_area_t area, uint32_t start, uint32_t end)
|
|
{
|
|
return psram_hal_set_write_through(area, 1, start, end);
|
|
}
|
|
|
|
bk_err_t bk_psram_disable_write_through(psram_write_through_area_t area)
|
|
{
|
|
return psram_hal_set_write_through(area, 0, 0, 0);
|
|
}
|
|
|
|
bk_err_t bk_psram_calibrate(void)
|
|
{
|
|
#if CONFIG_PSRAM_CALIBRATE
|
|
//TODO add calibrate strategy after get it from digital team
|
|
return BK_OK;
|
|
#else
|
|
return BK_OK;
|
|
#endif
|
|
}
|
|
|
|
#if (CONFIG_PSRAM_AUTO_DETECT)
|
|
static void psram_id_write(beken_thread_arg_t data)
|
|
{
|
|
rtos_get_semaphore(&s_psram_sem, BEKEN_WAIT_FOREVER);
|
|
|
|
if (s_psram_id_need_write)
|
|
{
|
|
bk_set_env_enhance(PSRAM_CHIP_ID, (const void *)&s_psram_id, sizeof(psram_flash_t));
|
|
}
|
|
|
|
PSRAM_LOGI("psram id write to flash success\r\n");
|
|
|
|
s_psram_id_need_write = false;
|
|
|
|
rtos_deinit_semaphore(&s_psram_sem);
|
|
s_psram_sem = NULL;
|
|
|
|
psram_task = NULL;
|
|
rtos_delete_thread(NULL);
|
|
}
|
|
#endif
|
|
|
|
bk_err_t bk_psram_id_auto_detect(void)
|
|
{
|
|
#if (CONFIG_PSRAM_AUTO_DETECT)
|
|
int ret = bk_get_env_enhance(PSRAM_CHIP_ID, (void *)&s_psram_id, sizeof(psram_flash_t));
|
|
|
|
if (ret != 8)
|
|
{
|
|
PSRAM_LOGW("%s, %d ret:%d read error\r\n", __func__, sizeof(psram_flash_t), ret);
|
|
}
|
|
|
|
if (s_psram_id.magic_code == PSRAM_CHECK_FLAG)
|
|
{
|
|
return BK_OK;
|
|
}
|
|
|
|
if (s_psram_sem == NULL)
|
|
{
|
|
ret = rtos_init_semaphore(&s_psram_sem, 1);
|
|
if (ret != BK_OK)
|
|
{
|
|
PSRAM_LOGE("%s, init s_psram_sem error\r\n", __func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
ret = rtos_create_thread(&psram_task,
|
|
4,
|
|
"psram_task",
|
|
(beken_thread_function_t)psram_id_write,
|
|
3072,
|
|
NULL);
|
|
|
|
if (BK_OK != ret)
|
|
{
|
|
PSRAM_LOGE("%s psram_task init failed\n");
|
|
rtos_deinit_semaphore(&s_psram_sem);
|
|
s_psram_sem = NULL;
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_psram_init(void)
|
|
{
|
|
#if (CONFIG_SYS_CPU0)
|
|
if (s_psram_server_is_init) {
|
|
return BK_OK;
|
|
}
|
|
|
|
uint32_t chip_id = 0, actual_id = 0;
|
|
|
|
// psram voltage sel
|
|
bk_psram_set_voltage(PSRAM_OUT_1_95V);
|
|
|
|
// power up and clk config
|
|
psram_hal_power_clk_enable(1);
|
|
|
|
if (s_psram_id.magic_code == PSRAM_CHECK_FLAG)
|
|
{
|
|
chip_id = s_psram_id.psram_id;
|
|
}
|
|
|
|
PSRAM_LOGI("%s, chip_id:%x\r\n", __func__, chip_id);
|
|
|
|
// psram config
|
|
actual_id = psram_hal_config_init(chip_id);
|
|
|
|
if (actual_id == 0)
|
|
{
|
|
PSRAM_LOGE("%s, fail!\r\n", __func__);
|
|
return BK_FAIL;
|
|
}
|
|
|
|
delay_us(1000);
|
|
// set psram clk
|
|
bk_psram_set_clk(PSRAM_120M);
|
|
|
|
PSRAM_LOGI("%s, %x-%x\r\n", __func__, actual_id, chip_id);
|
|
|
|
if (actual_id != chip_id)
|
|
{
|
|
s_psram_id.psram_id = actual_id;
|
|
s_psram_id.magic_code = PSRAM_CHECK_FLAG;
|
|
#if (CONFIG_PSRAM_AUTO_DETECT)
|
|
if (s_psram_sem)
|
|
{
|
|
s_psram_id_need_write = true;
|
|
|
|
rtos_set_semaphore(&s_psram_sem);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if (CONFIG_PSRAM_AUTO_DETECT)
|
|
if (s_psram_sem)
|
|
{
|
|
rtos_set_semaphore(&s_psram_sem);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
s_psram_server_is_init = true;
|
|
|
|
return BK_OK;
|
|
#else
|
|
return BK_FAIL;
|
|
#endif
|
|
}
|
|
|
|
bk_err_t bk_psram_deinit(void)
|
|
{
|
|
#if (CONFIG_SYS_CPU0)
|
|
if (!s_psram_server_is_init) {
|
|
return BK_OK;
|
|
}
|
|
|
|
psram_hal_power_clk_enable(0);
|
|
|
|
s_psram_server_is_init = false;
|
|
|
|
return BK_OK;
|
|
#else
|
|
return BK_FAIL;
|
|
#endif
|
|
}
|
|
|
|
bk_err_t bk_psram_memcpy(uint8_t *start_addr, uint8_t *data_buf, uint32_t len)
|
|
{
|
|
int i;
|
|
uint32_t val;
|
|
uint8_t *pb = NULL, *pd = NULL;
|
|
|
|
PSRAM_RETURN_ON_SERVER_NOT_INIT();
|
|
|
|
if (((uint32_t)start_addr & 0x3) != 0 || ((uint32_t)data_buf & 0x3) != 0)
|
|
{
|
|
PSRAM_LOGE("address not aligen 4 byte\r\n");
|
|
return BK_FAIL;
|
|
}
|
|
|
|
while (len) {
|
|
if (len < 4) {
|
|
val = *((uint32_t *)(start_addr));
|
|
pb = (uint8_t *)&val;
|
|
pd = (uint8_t *)data_buf;
|
|
for (i = 0; i < len; i++) {
|
|
*pb++ = *pd++;
|
|
}
|
|
*(uint32_t *)(start_addr) = val;
|
|
len = 0;
|
|
} else {
|
|
val = *data_buf++;
|
|
*(uint32_t *)(start_addr) = val;
|
|
start_addr += 4;
|
|
len -= 4;
|
|
}
|
|
}
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_psram_memread(uint8_t *start_addr, uint8_t *data_buf, uint32_t len)
|
|
{
|
|
int i;
|
|
uint32_t val;
|
|
uint8_t *pb, *pd;
|
|
|
|
PSRAM_RETURN_ON_SERVER_NOT_INIT();
|
|
|
|
if (((uint32_t)start_addr & 0x3) != 0 || ((uint32_t)data_buf & 0x3) != 0)
|
|
{
|
|
PSRAM_LOGE("address not aligen 4 byte\r\n");
|
|
return BK_FAIL;
|
|
}
|
|
|
|
while (len) {
|
|
if (len < 4) {
|
|
val = *((uint32_t *)(start_addr));
|
|
pb = (uint8_t *)&val;
|
|
pd = (uint8_t *)data_buf;
|
|
for (i = 0; i < len; i++) {
|
|
*pd++ = *pb++;
|
|
}
|
|
len = 0;
|
|
} else {
|
|
*(uint32_t *)(start_addr) = val;
|
|
*data_buf++ = val;
|
|
start_addr += 4;
|
|
len -= 4;
|
|
}
|
|
}
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
char *bk_psram_strcat(char *start_addr, const char *data_buf)
|
|
{
|
|
int i;
|
|
uint32_t val;
|
|
uint8_t *pb;
|
|
uint8_t *pd = (uint8_t *)data_buf;
|
|
|
|
if (!s_psram_server_is_init) {
|
|
return NULL;
|
|
}
|
|
|
|
if(*pd == '\0')
|
|
{
|
|
return start_addr;
|
|
}
|
|
do
|
|
{
|
|
val = *(uint32_t *)(start_addr);
|
|
pb = (uint8_t *)&val;
|
|
for (i = 0; i < 4; i++) {
|
|
if(*(pb+i) == '\0')
|
|
{
|
|
if(*pd == '\0')
|
|
{
|
|
*(pb+i) = *pd;
|
|
break;
|
|
}
|
|
*(pb+i) = *pd++;
|
|
}
|
|
}
|
|
*(uint32_t *)(start_addr) = val;
|
|
|
|
if(*pd == '\0')
|
|
{
|
|
break;
|
|
}
|
|
start_addr += 4;
|
|
} while(true);
|
|
|
|
return start_addr;
|
|
}
|
|
|
|
|
|
|