316 lines
9.7 KiB
C
316 lines
9.7 KiB
C
/*
|
||
* 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
|
||
* Description: This files is for the qspi specific functions implementations
|
||
*
|
||
* Modify History:
|
||
* Ver Who Date Changes
|
||
* ----- ------ -------- --------------------------------------
|
||
* 1.0 wangxiaodong 2022/3/29 first release
|
||
* 1.1 wangxiaodong 2022/9/9 improve functions
|
||
* 1.2 zhangyan 2022/12/7 improve functions
|
||
*/
|
||
|
||
#include <string.h>
|
||
#include "fkernel.h"
|
||
#include "fassert.h"
|
||
#include "fqspi.h"
|
||
#include "fqspi_hw.h"
|
||
#include "fsleep.h"
|
||
#include "fqspi_flash.h"
|
||
|
||
#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)
|
||
{
|
||
FQSPI_WARN("Device is already initialized!!!");
|
||
}
|
||
|
||
/*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)
|
||
{
|
||
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;
|
||
}
|
||
|
||
/* 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);
|
||
FQSPI_INFO("The flash chip size is %ld bytes.\n", pctrl->flash_size);
|
||
}
|
||
|
||
|
||
/**
|
||
* @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
|
||
* @param {u32} channel, cs number
|
||
* @return
|
||
*/
|
||
void FQspiChannelSet(FQspiCtrl *pctrl, u32 channel)
|
||
{
|
||
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);
|
||
|
||
}
|
||
|
||
|