253 lines
6.9 KiB
C
253 lines
6.9 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
#include "hw_reg_api.h"
|
|
#include "smc_rf.h"
|
|
#include "smc_rf_s.h"
|
|
#include "smc.h"
|
|
|
|
/* SFC and SMC share the same buffer, but they cannot be used at the same time */
|
|
#define SMC_BUFFER_ADDR SFC_MEM_BASEADDR
|
|
|
|
/* smc transmit ena */
|
|
smc_sts_type_t hal_smc_qspi_start()
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD0_ADDR);
|
|
REG_FIELD_SET(SW_SMC_ENA, tmp, 1);
|
|
SMC_WRITE_REG(CFG_SMC_CMD0_ADDR, tmp);
|
|
|
|
return SMC_QSPI_ERROR;
|
|
}
|
|
|
|
smc_sts_type_t hal_smc_disable()
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD0_ADDR);
|
|
REG_FIELD_SET(SW_SMC_ENA, tmp, 0);
|
|
SMC_WRITE_REG(CFG_SMC_CMD0_ADDR, tmp);
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CLK0_ADDR);
|
|
REG_FIELD_SET(CLK_SPI_SMC_ENA, tmp, 0);
|
|
SMC_WRITE_REG((CFG_SMC_CLK0_ADDR), tmp);
|
|
|
|
return SMC_QSPI_OK;
|
|
}
|
|
|
|
/* smc quad cfg */
|
|
smc_sts_type_t hal_smc_qspi_quad_cfg(uint8_t clk)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
/* quad read mode, quad write mode, little endian, spi is quad mode */
|
|
tmp = SMC_READ_REG(CFG_SMC_CFG0_ADDR);
|
|
REG_FIELD_SET(SMC_CACHE_RD_MODE, tmp, 2);
|
|
REG_FIELD_SET(SMC_CACHE_WR_MODE, tmp, 1);
|
|
REG_FIELD_SET(SMC_DATA_LE, tmp, 1);
|
|
REG_FIELD_SET(SMC_SPI_QPI_MODE, tmp, 1);
|
|
REG_FIELD_SET(SOFT_SMC_MODE, tmp, 0);
|
|
SMC_WRITE_REG(CFG_SMC_CFG0_ADDR, tmp);
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CACHE_WCFG0_ADDR);
|
|
REG_FIELD_SET(CACHE_WR_DATA_QUAD_MODE, tmp, 1);
|
|
REG_FIELD_SET(CACHE_WR_ADDR_QUAD_MODE, tmp, 1);
|
|
SMC_WRITE_REG(CFG_SMC_CACHE_WCFG0_ADDR, tmp);
|
|
|
|
#if HW_PLATFORM == HW_PLATFORM_SILICON
|
|
tmp = SMC_READ_REG(CFG_SMC_CLK0_ADDR);
|
|
REG_FIELD_SET(CLK_SPI_SMC_ENA, tmp, 1);
|
|
REG_FIELD_SET(CLK_SPI_SMC_DIV, tmp, 0);
|
|
SMC_WRITE_REG(CFG_SMC_CLK0_ADDR, tmp);
|
|
#endif
|
|
|
|
return SMC_QSPI_OK;
|
|
}
|
|
|
|
bool_t is_smc_cmd_busy()
|
|
{
|
|
return REG_FIELD_GET(SW_SMC_ENA, SMC_READ_REG(CFG_SMC_CMD0_ADDR));
|
|
}
|
|
|
|
/* smc rst en */
|
|
smc_sts_type_t hal_smc_qspi_rst_en()
|
|
{
|
|
return SMC_QSPI_OK;
|
|
}
|
|
|
|
/* smc rst en */
|
|
smc_sts_type_t hal_smc_qspi_rst()
|
|
{
|
|
return SMC_QSPI_OK;
|
|
}
|
|
|
|
/* si:command + address */
|
|
smc_sts_type_t hal_smc_qspi_command(smc_op_t *cmd, uint32_t timeout)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
/* cmd and addr */
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD1_ADDR);
|
|
REG_FIELD_SET(SW_SMC_CMD, tmp, cmd->cmd);
|
|
REG_FIELD_SET(SW_SMC_ADDR, tmp, cmd->addr);
|
|
SMC_WRITE_REG(CFG_SMC_CMD1_ADDR, tmp);
|
|
|
|
/* operation and size */
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD0_ADDR);
|
|
REG_FIELD_SET(SW_SMC_MODE, tmp, cmd->smc_mode);
|
|
REG_FIELD_SET(SW_SMC_DLEN, tmp, cmd->smc_dlen);
|
|
SMC_WRITE_REG(CFG_SMC_CMD0_ADDR, tmp);
|
|
|
|
|
|
/* qpi mode */
|
|
tmp = SMC_READ_REG(CFG_SMC_CFG0_ADDR);
|
|
REG_FIELD_SET(SMC_SPI_QPI_MODE, tmp, cmd->qpi_mode);
|
|
SMC_WRITE_REG(CFG_SMC_CFG0_ADDR, tmp);
|
|
|
|
return SMC_QSPI_OK;
|
|
}
|
|
|
|
/* spi output:data */
|
|
smc_sts_type_t hal_smc_qspi_transmit(uint8_t *data, uint32_t len,
|
|
uint8_t is_buf, uint32_t timeout)
|
|
{
|
|
uint8_t *smc_data_buf;
|
|
(void)timeout;
|
|
|
|
if (is_buf) {
|
|
while(is_smc_cmd_busy());
|
|
|
|
smc_data_buf = (uint8_t *)(SMC_BUFFER_ADDR);
|
|
/* write data to buf ram */
|
|
while(len--)
|
|
{
|
|
*smc_data_buf = *data;
|
|
data++;
|
|
smc_data_buf++;
|
|
}
|
|
hal_smc_qspi_start();
|
|
} else {
|
|
#if 0 // Hardware not supported
|
|
uint32_t tmp;
|
|
uint32_t i, temp_addr, temp_len;
|
|
temp_addr = REG_FIELD_GET(SW_SMC_ADDR, SMC_READ_REG(CFG_SMC_CMD1_ADDR));
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD0_ADDR);
|
|
REG_FIELD_SET(SW_SMC_MODE, tmp, MOD_SMC_OP_REG_WR);
|
|
SMC_WRITE_REG(CFG_SMC_CMD0_ADDR, tmp);
|
|
|
|
for (i = 0; i < len; i += 4) {
|
|
while(is_smc_cmd_busy());
|
|
|
|
temp_len = (len - i >= 4) ? 4 : (len - i);
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD0_ADDR);
|
|
REG_FIELD_SET(SW_SMC_DLEN, tmp, temp_len);
|
|
SMC_WRITE_REG(CFG_SMC_CMD0_ADDR, tmp);
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD1_ADDR);
|
|
REG_FIELD_SET(SW_SMC_ADDR, tmp, temp_addr);
|
|
SMC_WRITE_REG(CFG_SMC_CMD1_ADDR, tmp);
|
|
|
|
SMC_WRITE_REG(CFG_SMC_WDATA_ADDR, *((uint32_t *)data));
|
|
|
|
hal_smc_qspi_start();
|
|
|
|
temp_addr += 4;
|
|
data += 4;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return SMC_QSPI_OK;
|
|
}
|
|
|
|
/* spi input:data */
|
|
smc_sts_type_t hal_smc_qspi_receive(uint8_t *data, uint32_t len,
|
|
uint8_t is_buf, uint32_t timeout)
|
|
{
|
|
uint8_t *smc_data_buf;
|
|
|
|
if (is_buf) {
|
|
while(is_smc_cmd_busy());
|
|
|
|
smc_data_buf = (uint8_t *)(SMC_BUFFER_ADDR);
|
|
while(len--)
|
|
{
|
|
*data = *smc_data_buf;
|
|
data++;
|
|
smc_data_buf++;
|
|
}
|
|
} else {
|
|
#if 0 // Hardware not supported
|
|
uint32_t tmp, i, temp_addr, temp_len;
|
|
temp_addr = REG_FIELD_GET(SW_SMC_ADDR, SMC_READ_REG(CFG_SMC_CMD1_ADDR));
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD0_ADDR);
|
|
REG_FIELD_SET(SW_SMC_MODE, tmp, MOD_SMC_OP_REG_WR);
|
|
SMC_WRITE_REG(CFG_SMC_CMD0_ADDR, tmp);
|
|
|
|
for (i = 0; i < len; i += 4) {
|
|
while(is_smc_cmd_busy());
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD0_ADDR);
|
|
REG_FIELD_SET(SW_SMC_DLEN, tmp, 4);
|
|
SMC_WRITE_REG(CFG_SMC_CMD0_ADDR, tmp);
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CMD1_ADDR);
|
|
REG_FIELD_SET(SW_SMC_ADDR, tmp, temp_addr);
|
|
SMC_WRITE_REG(CFG_SMC_CMD1_ADDR, tmp);
|
|
|
|
/* start read to buf */
|
|
hal_smc_qspi_start();
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_WDATA_ADDR);
|
|
|
|
temp_len = (len - i >= 4) ? 4 : (len - i);
|
|
for (uint8_t j = 0; j < temp_len; j++) {
|
|
data[i + temp_len] = (tmp >> (j * 4)) & 0xff;
|
|
}
|
|
temp_addr += 4;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return SMC_QSPI_OK;
|
|
}
|
|
|
|
/* 0, 1(def), 2, 3 */
|
|
void IRAM_ATTR hal_smc_clk_div_set(uint8_t div)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_CLK0_ADDR);
|
|
REG_FIELD_SET(CLK_SPI_SMC_DIV, tmp, div);
|
|
SMC_WRITE_REG(CFG_SMC_CLK0_ADDR, tmp);
|
|
}
|
|
|
|
void hal_smc_clk_out(int enable)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = SMC_READ_REG(CFG_SMC_DBG0_ADDR);
|
|
if (enable) {
|
|
REG_FIELD_SET(SMC_CLK_FORCE_OUT, tmp, 1);
|
|
} else {
|
|
REG_FIELD_SET(SMC_CLK_FORCE_OUT, tmp, 0);
|
|
}
|
|
SMC_WRITE_REG(CFG_SMC_DBG0_ADDR, tmp);
|
|
}
|
|
|