rt-thread/bsp/phytium/libraries/standalone/drivers/qspi/fqspi/fqspi.c

316 lines
9.7 KiB
C
Raw Normal View History

/*
* 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 successothers 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 successothers 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 successothers 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 successothers 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 successothers 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);
}