2022-11-10 22:22:48 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
|
|
|
|
* All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
|
|
|
|
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
|
|
|
|
* either version 1.0 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
* See the Phytium Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* FilePath: fqspi.c
|
|
|
|
|
* Date: 2022-02-10 14:53:42
|
|
|
|
|
* LastEditTime: 2022-03-28 09:00:41
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* Description: This files is for the qspi specific functions implementations
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*
|
|
|
|
|
* Modify History:
|
|
|
|
|
* Ver Who Date Changes
|
|
|
|
|
* ----- ------ -------- --------------------------------------
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* 1.0 wangxiaodong 2022/3/29 first release
|
|
|
|
|
* 1.1 wangxiaodong 2022/9/9 improve functions
|
|
|
|
|
* 1.2 zhangyan 2022/12/7 improve functions
|
2022-11-10 22:22:48 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "fkernel.h"
|
|
|
|
|
#include "fassert.h"
|
|
|
|
|
#include "fqspi.h"
|
|
|
|
|
#include "fqspi_hw.h"
|
|
|
|
|
#include "fsleep.h"
|
2023-05-11 10:25:21 +08:00
|
|
|
|
#include "fqspi_flash.h"
|
2022-11-10 22:22:48 +08:00
|
|
|
|
|
|
|
|
|
#define FQSPI_DEBUG_TAG "FQSPI"
|
|
|
|
|
#define FQSPI_ERROR(format, ...) FT_DEBUG_PRINT_E(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FQSPI_WARN(format, ...) FT_DEBUG_PRINT_W(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FQSPI_INFO(format, ...) FT_DEBUG_PRINT_I(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
#define FQSPI_DEBUG(format, ...) FT_DEBUG_PRINT_D(FQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiCfgInitialize
|
|
|
|
|
* @msg: Initializes a specific instance such that it is ready to be used.
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
|
|
|
|
* @param {FQspiConfig} *input_config_p, Configuration parameters of FQSPI
|
|
|
|
|
* @return err code information, FQSPI_SUCCESS indicates success,others indicates failed
|
|
|
|
|
*/
|
|
|
|
|
FError FQspiCfgInitialize(FQspiCtrl *pctrl, const FQspiConfig *input_config_p)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl && input_config_p);
|
|
|
|
|
|
|
|
|
|
FError ret = FQSPI_SUCCESS;
|
|
|
|
|
/*
|
|
|
|
|
* If the device is started, disallow the initialize and return a Status
|
|
|
|
|
* indicating it is started. This allows the user to de-initialize the device
|
|
|
|
|
* and reinitialize, but prevents a user from inadvertently
|
|
|
|
|
* initializing.
|
|
|
|
|
*/
|
|
|
|
|
if (FT_COMPONENT_IS_READY == pctrl->is_ready)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FQSPI_WARN("Device is already initialized!!!");
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*Set default values and configuration data */
|
|
|
|
|
FQspiDeInitialize(pctrl);
|
|
|
|
|
|
|
|
|
|
pctrl->config = *input_config_p;
|
|
|
|
|
|
|
|
|
|
pctrl->is_ready = FT_COMPONENT_IS_READY;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiDeInitialize
|
|
|
|
|
* @msg: DeInitialization function for the device instance
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
|
|
|
|
* @return {*}
|
|
|
|
|
*/
|
|
|
|
|
void FQspiDeInitialize(FQspiCtrl *pctrl)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl);
|
|
|
|
|
|
|
|
|
|
pctrl->is_ready = 0;
|
|
|
|
|
memset(pctrl, 0, sizeof(*pctrl));
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiSetCapacityAndNum
|
|
|
|
|
* @msg: Initializes the capacity and number of flash connect to specific instance.
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
void FQspiSetCapacityAndNum(FQspiCtrl *pctrl)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl);
|
|
|
|
|
u32 reg_val = 0;
|
|
|
|
|
FQspiConfig *config_p = &pctrl->config;
|
|
|
|
|
uintptr base_addr = pctrl->config.base_addr;
|
|
|
|
|
|
|
|
|
|
switch (config_p->capacity)
|
|
|
|
|
{
|
2023-05-11 10:25:21 +08:00
|
|
|
|
case FQSPI_FLASH_CAP_4MB:
|
|
|
|
|
pctrl->flash_size = SZ_4M;
|
|
|
|
|
break;
|
|
|
|
|
case FQSPI_FLASH_CAP_8MB:
|
|
|
|
|
pctrl->flash_size = SZ_8M;
|
|
|
|
|
break;
|
|
|
|
|
case FQSPI_FLASH_CAP_16MB:
|
|
|
|
|
pctrl->flash_size = SZ_16M;
|
|
|
|
|
break;
|
|
|
|
|
case FQSPI_FLASH_CAP_32MB:
|
|
|
|
|
pctrl->flash_size = SZ_32M;
|
|
|
|
|
break;
|
|
|
|
|
case FQSPI_FLASH_CAP_64MB:
|
|
|
|
|
pctrl->flash_size = SZ_64M;
|
|
|
|
|
break;
|
|
|
|
|
case FQSPI_FLASH_CAP_128MB:
|
|
|
|
|
pctrl->flash_size = SZ_128M;
|
|
|
|
|
break;
|
|
|
|
|
case FQSPI_FLASH_CAP_256MB:
|
|
|
|
|
pctrl->flash_size = SZ_256M;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pctrl->flash_size = SZ_4M;
|
|
|
|
|
break;
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write flash capacity and numbers information to qspi Capacity register */
|
|
|
|
|
reg_val = (FQSPI_CAP_FLASH_NUM_MASK & FQSPI_CAP_FLASH_NUM(config_p->dev_num)) |
|
|
|
|
|
(FQSPI_CAP_FLASH_CAP_MASK & FQSPI_CAP_FLASH_CAP(config_p->capacity));
|
|
|
|
|
|
|
|
|
|
/*write value to flash capacity register 0x00 */
|
|
|
|
|
FQSPI_WRITE_REG32(base_addr, FQSPI_REG_CAP_OFFSET, reg_val);
|
2023-05-11 10:25:21 +08:00
|
|
|
|
FQSPI_INFO("The flash chip size is %ld bytes.\n", pctrl->flash_size);
|
2022-11-10 22:22:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiRdCfgConfig
|
|
|
|
|
* @msg: config read config register
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
|
|
|
|
* @return err code information, FQSPI_SUCCESS indicates success,others indicates failed
|
|
|
|
|
*/
|
|
|
|
|
FError FQspiRdCfgConfig(FQspiCtrl *pctrl)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl);
|
|
|
|
|
FError ret = FQSPI_SUCCESS;
|
|
|
|
|
u32 cmd_reg = 0;
|
|
|
|
|
uintptr base_addr = pctrl->config.base_addr;
|
|
|
|
|
|
|
|
|
|
FQspiRdCfgDef rd_config = pctrl->rd_cfg;
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_CMD(rd_config.rd_cmd);
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_THROUGH(rd_config.rd_through);
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_TRANSFER(rd_config.rd_transfer);
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_ADDR_SEL(rd_config.rd_addr_sel);
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_LATENCY(rd_config.rd_latency);
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_MODE_BYTE(rd_config.mode_byte);
|
|
|
|
|
|
|
|
|
|
if ((rd_config.mode_byte) || (rd_config.cmd_sign == 0))
|
|
|
|
|
{
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_CMD_SIGN(rd_config.cmd_sign);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FQSPI_ERROR("rd_cfg mode_byte disable !!!");
|
|
|
|
|
return FQSPI_INVAL_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((rd_config.rd_latency == FQSPI_CMD_LATENCY_ENABLE) || (rd_config.dummy == 0))
|
|
|
|
|
{
|
|
|
|
|
rd_config.dummy = rd_config.dummy ? rd_config.dummy : 1;
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_DUMMY(rd_config.dummy);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FQSPI_ERROR("rd_cfg latency disable !!!");
|
|
|
|
|
return FQSPI_INVAL_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_D_BUFFER(rd_config.d_buffer);
|
|
|
|
|
cmd_reg |= FQSPI_RD_CFG_SCK_SEL(rd_config.rd_sck_sel);
|
|
|
|
|
|
|
|
|
|
FQSPI_WRITE_REG32(base_addr, FQSPI_REG_RD_CFG_OFFSET, cmd_reg);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiWrCfgConfig
|
|
|
|
|
* @msg: config write config register
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
|
|
|
|
* @return err code information, FQSPI_SUCCESS indicates success,others indicates failed
|
|
|
|
|
*/
|
|
|
|
|
FError FQspiWrCfgConfig(FQspiCtrl *pctrl)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl);
|
|
|
|
|
FError ret = FQSPI_SUCCESS;
|
|
|
|
|
u32 cmd_reg = 0;
|
|
|
|
|
uintptr base_addr = pctrl->config.base_addr;
|
|
|
|
|
|
|
|
|
|
FQspiWrCfgDef wr_config = pctrl->wr_cfg;
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_WR_CFG_CMD(wr_config.wr_cmd);
|
|
|
|
|
cmd_reg |= FQSPI_WR_CFG_WAIT(wr_config.wr_wait);
|
|
|
|
|
cmd_reg |= FQSPI_WR_CFG_THROUGH(wr_config.wr_through);
|
|
|
|
|
cmd_reg |= FQSPI_WR_CFG_TRANSFER(wr_config.wr_transfer);
|
|
|
|
|
cmd_reg |= FQSPI_WR_CFG_ADDRSEL(wr_config.wr_addr_sel);
|
|
|
|
|
cmd_reg |= FQSPI_WR_CFG_MODE(wr_config.wr_mode);
|
|
|
|
|
cmd_reg |= FQSPI_WR_CFG_SCK_SEL(wr_config.wr_sck_sel);
|
|
|
|
|
|
|
|
|
|
FQSPI_WRITE_REG32(base_addr, FQSPI_REG_WR_CFG_OFFSET, cmd_reg);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiCommandPortConfig
|
|
|
|
|
* @msg: config command port register
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
|
|
|
|
* @return err code information, FQSPI_SUCCESS indicates success,others indicates failed
|
|
|
|
|
*/
|
|
|
|
|
FError FQspiCommandPortConfig(FQspiCtrl *pctrl)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl);
|
|
|
|
|
FError ret = FQSPI_SUCCESS;
|
|
|
|
|
u32 cmd_reg = 0;
|
|
|
|
|
uintptr base_addr = pctrl->config.base_addr;
|
|
|
|
|
|
|
|
|
|
FQspiCommandPortDef cmd_port_config = pctrl->cmd_def;
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_CMD_MASK & FQSPI_CMD_PORT_CMD(cmd_port_config.cmd);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_WAIT(cmd_port_config.wait);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_THROUGH(cmd_port_config.through);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_CS_MASK & FQSPI_CMD_PORT_CS(cmd_port_config.cs);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_TRANSFER(cmd_port_config.transfer);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_CMD_ADDR(cmd_port_config.cmd_addr);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_LATENCY(cmd_port_config.latency);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_DATA_TRANS(cmd_port_config.data_transfer);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_ADDR_SEL(cmd_port_config.addr_sel);
|
|
|
|
|
|
|
|
|
|
if ((cmd_port_config.latency == FQSPI_CMD_LATENCY_ENABLE) || (cmd_port_config.dummy == 0))
|
|
|
|
|
{
|
|
|
|
|
cmd_port_config.dummy = cmd_port_config.dummy ? cmd_port_config.dummy : 1;
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_DUMMY(cmd_port_config.dummy);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FQSPI_ERROR("cmd_port latency disable !!!");
|
|
|
|
|
return FQSPI_INVAL_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_P_BUFFER(cmd_port_config.p_buffer);
|
|
|
|
|
|
|
|
|
|
/* read data num */
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_RW_NUM_MASK & FQSPI_CMD_PORT_RW_NUM(cmd_port_config.rw_num);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_CMD_PORT_CLK_SEL_MASK & FQSPI_CMD_PORT_CLK_SEL(cmd_port_config.sck_sel);
|
|
|
|
|
|
|
|
|
|
FQSPI_WRITE_REG32(base_addr, FQSPI_REG_CMD_PORT_OFFSET, cmd_reg);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiChannelSet
|
|
|
|
|
* @msg: config qspi cs num
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
2023-05-11 10:25:21 +08:00
|
|
|
|
* @param {u32} channel, cs number
|
2022-11-10 22:22:48 +08:00
|
|
|
|
* @return
|
|
|
|
|
*/
|
2023-05-11 10:25:21 +08:00
|
|
|
|
void FQspiChannelSet(FQspiCtrl *pctrl, u32 channel)
|
2022-11-10 22:22:48 +08:00
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl);
|
|
|
|
|
FASSERT(channel < FQSPI_CS_NUM);
|
|
|
|
|
pctrl->config.channel = channel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @name: FQspiCsTimingSet
|
|
|
|
|
* @msg: config qspi cs timing
|
|
|
|
|
* @param {FQspiCtrl} *pctrl, instance of FQSPI controller
|
|
|
|
|
* @param {FQspiCsTimingCfgDef} cs_timing_cfg, cs timing
|
|
|
|
|
* @return err code information, FQSPI_SUCCESS indicates success,others indicates failed
|
|
|
|
|
*/
|
|
|
|
|
void FQspiCsTimingSet(FQspiCtrl *pctrl, FQspiCsTimingCfgDef *cs_timing_cfg)
|
|
|
|
|
{
|
|
|
|
|
FASSERT(pctrl);
|
|
|
|
|
u32 cmd_reg = 0;
|
|
|
|
|
uintptr base_addr = pctrl->config.base_addr;
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_FUN_SET_CS_HOLD(cs_timing_cfg->cs_hold);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_FUN_SET_CS_SETUP(cs_timing_cfg->cs_setup);
|
|
|
|
|
|
|
|
|
|
cmd_reg |= FQSPI_FUN_SET_CS_DELAY(cs_timing_cfg->cs_delay);
|
|
|
|
|
|
|
|
|
|
FQSPI_WRITE_REG32(base_addr, FQSPI_REG_CS_TIMING_SET_OFFSET, cmd_reg);
|
|
|
|
|
|
|
|
|
|
}
|
2023-05-11 10:25:21 +08:00
|
|
|
|
|
|
|
|
|
|