MXC-A36_2024.04.17/MXC-Screen_display/components/drivers/bsp/psram/driver_psram.c

351 lines
11 KiB
C

/*
******************************************************************************
* @file driver_flash.c
* @author FreqChip Firmware Team
* @version V1.0.0
* @date 2021
* @brief Internal XIP Flash module driver.
* This file provides firmware functions to manage the internal
* stacked xip flash
******************************************************************************
* @attention
*
* Copyright (c) 2022 FreqChip.
* All rights reserved.
******************************************************************************
*/
#include "fr30xx.h"
#include "driver_psram.h"
#include "co_util.h"
#define PSRAM_ENABLE_Q_MODE 1
#define PSRAM_LATENCY_CFG 3
#define PSRAM_HIGH_SPEED 1
#define PSRAM_OSPI_IF OSPI
#define PSRAM_READ_IDENTIFICATION 0x9F
#define PSRAM_READ_OPCODE 0x03
#define PSRAM_FAST_READ_OPCODE 0x0B
#define PSRAM_FAST_QUAL_READ_OPCODE 0xEB
#define PSRAM_PAGE_PROGRAM_OPCODE 0x02
#define PSRAM_PAGE_QUAL_PROGRAM_OPCODE 0x38
#define PSRAM_ENTER_QUAD_MODE_OPCODE 0x35
#define PSRAM_EXIT_QUAD_MODE_OPCODE 0xF5
#define PSRAM_RESET_ENABLE_OPCODE 0x66
#define PSRAM_RESET_OPCODE 0x99
static const struct qspi_stig_reg_t psram_read_ctrl_cmd = {
.enable_bank = 0,
.dummy_cycles = PSRAM_LATENCY_CFG-1,
.write_bytes = 0,
.enable_write = 0,
.addr_bytes = QSPI_STIG_ADDR_BYTES_4,
.enable_mode = 0,
.enable_cmd_addr = 1,
.read_bytes = 2,
.enable_read = 1,
.opcode = 0x40,
};
static const struct qspi_stig_reg_t psram_write_ctrl_cmd = {
.enable_bank = 0,
.dummy_cycles = 0,
.write_bytes = 2,
.enable_write = 1,
.addr_bytes = QSPI_STIG_ADDR_BYTES_4,
.enable_mode = 0,
.enable_cmd_addr = 1,
.read_bytes = 0,
.enable_read = 0,
.opcode = 0xC0,
};
static const struct qspi_stig_reg_t psram_read_id_cmd = {
.enable_bank = 0,
.dummy_cycles = 0,
.write_bytes = 0,
.enable_write = 0,
.addr_bytes = 0,
.enable_mode = 0,
.enable_cmd_addr = 0,
.read_bytes = 3,
.enable_read = 1,
.opcode = PSRAM_READ_IDENTIFICATION,
};
static const struct qspi_stig_reg_t enter_quad_mode_cmd = {
.enable_bank = 0,
.dummy_cycles = 0,
.write_bytes = 0,
.enable_write = 0,
.addr_bytes = 0,
.enable_mode = 0,
.enable_cmd_addr = 0,
.read_bytes = 0,
.enable_read = 0,
.opcode = PSRAM_ENTER_QUAD_MODE_OPCODE,
};
static const struct qspi_stig_reg_t reset_enable_cmd = {
.enable_bank = 0,
.dummy_cycles = 0,
.write_bytes = 0,
.enable_write = 0,
.addr_bytes = 0,
.enable_mode = 0,
.enable_cmd_addr = 0,
.read_bytes = 0,
.enable_read = 0,
.opcode = PSRAM_RESET_ENABLE_OPCODE,
};
static const struct qspi_stig_reg_t reset_cmd = {
.enable_bank = 0,
.dummy_cycles = 0,
.write_bytes = 0,
.enable_write = 0,
.addr_bytes = 0,
.enable_mode = 0,
.enable_cmd_addr = 0,
.read_bytes = 0,
.enable_read = 0,
.opcode = PSRAM_RESET_OPCODE,
};
static uint8_t psram_read_mode(uint8_t mode)
{
uint8_t result[2];
__QSPI_CMD_ADDRESS_SET(PSRAM_OSPI_IF, mode);
qspi_stig_cmd(PSRAM_OSPI_IF, psram_read_ctrl_cmd, QSPI_STIG_CMD_READ, 2, result);
return result[0];
}
static void psram_write_mode(uint8_t mode, uint8_t data)
{
uint8_t buffer[2];
buffer[0] = data;
buffer[1] = data;
__QSPI_CMD_ADDRESS_SET(PSRAM_OSPI_IF, mode);
qspi_stig_cmd(PSRAM_OSPI_IF, psram_write_ctrl_cmd, QSPI_STIG_CMD_WRITE, 2, buffer);
}
#if 0
static void psram_controller_init(uint16_t page_boundary)
{
while(__QSPI_IS_BUSY(PSRAM_OSPI_IF));
__QSPI_READ_OPCODE_SET(PSRAM_OSPI_IF, 0x20);
__QSPI_READ_INSTRUCTION_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_OIO);
__QSPI_READ_ADDRESS_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_OIO);
__QSPI_READ_DATA_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_OIO);
__QSPI_READ_DUMMY_CYCLES_SET(PSRAM_OSPI_IF, (PSRAM_LATENCY_CFG<<1)-1);
__QSPI_READ_MODE_ENABLE_SET(PSRAM_OSPI_IF, 0);
__QSPI_MODE_BIT_SET(PSRAM_OSPI_IF, 0);
__QSPI_WRITE_OPCODE_SET(PSRAM_OSPI_IF, 0xA0);
__QSPI_WRITE_ADDRESS_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_OIO);
__QSPI_WRITE_DATA_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_OIO);
__QSPI_WRITE_DUMMY_CYCLES_SET(PSRAM_OSPI_IF, PSRAM_LATENCY_CFG-1);
__QSPI_WRITE_WEL_DISABLE(PSRAM_OSPI_IF);
__QSPI_POLL_DISABLE(PSRAM_OSPI_IF);
//init configuration register
__QSPI_CFG_CPOL_SET(PSRAM_OSPI_IF, 0);
__QSPI_CFG_CPHA_SET(PSRAM_OSPI_IF, 0);
__QSPI_CFG_DAC_ENABLE(PSRAM_OSPI_IF);
__QSPI_CFG_LEGACY_DISABLE(PSRAM_OSPI_IF);
__QSPI_CFG_REMAP_ENABLE(PSRAM_OSPI_IF);
#if PSRAM_HIGH_SPEED
__QSPI_CFG_BAUDRATE_SET(PSRAM_OSPI_IF, QSPI_BAUDRATE_DIV_6);
__QSPI_READ_CAPTURE_DELAY_SET(PSRAM_OSPI_IF, 0);
#else
__QSPI_CFG_BAUDRATE_SET(PSRAM_OSPI_IF, QSPI_BAUDRATE_DIV_16);
__QSPI_READ_CAPTURE_DELAY_SET(PSRAM_OSPI_IF, 0);
#endif
// __QSPI_CFG_AHB_DECODER_ENABLE(PSRAM_OSPI_IF);
__QSPI_READ_CAPTURE_LP_CLK_EN(PSRAM_OSPI_IF);
__QSPI_DELAY_CS_START_SET(PSRAM_OSPI_IF, 2);
__QSPI_DELAY_CS_END_SET(PSRAM_OSPI_IF, 2);
__QSPI_DELAY_CS_DESSERT_SET(PSRAM_OSPI_IF, 2);
__QSPI_DEVICE_PAGE_SIZE_SET(PSRAM_OSPI_IF, page_boundary);
// __QSPI_DEVICE_CS0_SIZE_SET(PSRAM_OSPI_IF, 3); // 4Gb space
__QSPI_CS_CTRL_RD_BRK_ENABLE(PSRAM_OSPI_IF);
__QSPI_CS_CTRL_DIS_CS_AFT_FIRST_BYTE_SET(PSRAM_OSPI_IF);
__QSPI_CS_PAGE_BOUNDARY_SET(PSRAM_OSPI_IF, page_boundary);
__QSPI_CS_PAGE_BOUNDARY_PROTECT_ENABLE(PSRAM_OSPI_IF);
// __QSPI_REMAP_ADDRESS_SET(PSRAM_OSPI_IF, PSRAM_DAC_BASE);
__QSPI_DEVICE_ADDR_BYTES_SET(PSRAM_OSPI_IF, QSPI_DEVICE_ADDR_BYTES_4);
__QSPI_CFG_DTR_ENABLE(PSRAM_OSPI_IF);
__QSPI_CFG_OCTAL_XCCELA_ENABLE(PSRAM_OSPI_IF);
__QSPI_ENABLE(PSRAM_OSPI_IF);
}
void psram_init(void)
{
// uint8_t mode[7];
uint8_t value;
#if PSRAM_HIGH_SPEED
psram_controller_init(0x0040);
#else
psram_controller_init(0x0008);
#endif
value = (1<<5) | ((PSRAM_LATENCY_CFG-3)<<2) | (0<<0);
psram_write_mode(0x00, value);
#if PSRAM_LATENCY_CFG == 3
value = (0<<5);
#elif PSRAM_LATENCY_CFG == 4
value = (4<<5);
#elif PSRAM_LATENCY_CFG == 5
value = (2<<5);
#elif PSRAM_LATENCY_CFG == 6
value = (6<<5);
#elif PSRAM_LATENCY_CFG == 7
value = (1<<5);
#else
#error "UNACCEPTABLE configure"
#endif
printf("write 0x%02x to mode reg4.\r\n", value);
psram_write_mode(0x04, value);
co_delay_100us(1);
// mode[0] = psram_read_mode(0x00);
// printf("mode 0: 0x%02x\r\n", mode[0]);
// mode[1] = psram_read_mode(0x01);
// printf("mode 1: 0x%02x\r\n", mode[1]);
// mode[2] = psram_read_mode(0x02);
// printf("mode 2: 0x%02x\r\n", mode[2]);
// mode[3] = psram_read_mode(0x03);
// printf("mode 3: 0x%02x\r\n", mode[3]);
// mode[4] = psram_read_mode(0x04);
// printf("mode 4: 0x%02x\r\n", mode[4]);
// mode[5] = psram_read_mode(0x06);
// printf("mode 6: 0x%02x\r\n", mode[5]);
// mode[6] = psram_read_mode(0x08);
// printf("mode 8: 0x%02x\r\n", mode[6]);
}
#else
static void psram_enter_quad(void)
{
qspi_stig_cmd(PSRAM_OSPI_IF, enter_quad_mode_cmd, QSPI_STIG_CMD_EXE, 0, NULL);
}
static void psram_controller_init(uint16_t page_boundary)
{
while(__QSPI_IS_BUSY(PSRAM_OSPI_IF));
#if PSRAM_ENABLE_Q_MODE == 1
__QSPI_READ_OPCODE_SET(PSRAM_OSPI_IF, PSRAM_FAST_READ_OPCODE);
__QSPI_READ_INSTRUCTION_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_READ_ADDRESS_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_READ_DATA_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_READ_DUMMY_CYCLES_SET(PSRAM_OSPI_IF, 4);
__QSPI_READ_MODE_ENABLE_SET(PSRAM_OSPI_IF, 0);
__QSPI_MODE_BIT_SET(PSRAM_OSPI_IF, 0);
__QSPI_WRITE_OPCODE_SET(PSRAM_OSPI_IF, PSRAM_PAGE_QUAL_PROGRAM_OPCODE);
__QSPI_WRITE_ADDRESS_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_WRITE_DATA_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_WRITE_DUMMY_CYCLES_SET(PSRAM_OSPI_IF, 0);
#else
__QSPI_READ_OPCODE_SET(PSRAM_OSPI_IF, PSRAM_FAST_QUAL_READ_OPCODE);
__QSPI_READ_INSTRUCTION_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_STAND);
__QSPI_READ_ADDRESS_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_READ_DATA_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_READ_DUMMY_CYCLES_SET(PSRAM_OSPI_IF, 6);
__QSPI_READ_MODE_ENABLE_SET(PSRAM_OSPI_IF, 0);
__QSPI_MODE_BIT_SET(PSRAM_OSPI_IF, 0);
__QSPI_WRITE_OPCODE_SET(PSRAM_OSPI_IF, PSRAM_PAGE_QUAL_PROGRAM_OPCODE);
__QSPI_WRITE_ADDRESS_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_WRITE_DATA_TYPE_SET(PSRAM_OSPI_IF, QSPI_WIRE_TYPE_QIO);
__QSPI_WRITE_DUMMY_CYCLES_SET(PSRAM_OSPI_IF, 0);
#endif
//init configuration register
__QSPI_CFG_CPOL_SET(PSRAM_OSPI_IF, 0);
__QSPI_CFG_CPHA_SET(PSRAM_OSPI_IF, 0);
__QSPI_CFG_DAC_ENABLE(PSRAM_OSPI_IF);
__QSPI_CFG_LEGACY_DISABLE(PSRAM_OSPI_IF);
__QSPI_CFG_REMAP_ENABLE(PSRAM_OSPI_IF);
#if PSRAM_HIGH_SPEED
__QSPI_CFG_BAUDRATE_SET(PSRAM_OSPI_IF, QSPI_BAUDRATE_DIV_2);
__QSPI_READ_CAPTURE_DELAY_SET(PSRAM_OSPI_IF, 4);
#else
__QSPI_CFG_BAUDRATE_SET(PSRAM_OSPI_IF, QSPI_BAUDRATE_DIV_8);
__QSPI_READ_CAPTURE_DELAY_SET(PSRAM_OSPI_IF, 0);
#endif
// __QSPI_CFG_AHB_DECODER_ENABLE(PSRAM_OSPI_IF);
__QSPI_WRITE_WEL_DISABLE(PSRAM_OSPI_IF);
__QSPI_POLL_DISABLE(PSRAM_OSPI_IF);
__QSPI_READ_CAPTURE_LP_CLK_EN(PSRAM_OSPI_IF);
__QSPI_DELAY_CS_START_SET(PSRAM_OSPI_IF, 2);
__QSPI_DELAY_CS_END_SET(PSRAM_OSPI_IF, 2);
__QSPI_DELAY_CS_DESSERT_SET(PSRAM_OSPI_IF, 2);
__QSPI_DEVICE_PAGE_SIZE_SET(PSRAM_OSPI_IF, page_boundary);
// __QSPI_DEVICE_CS0_SIZE_SET(PSRAM_OSPI_IF, 3); // 4Gb space
__QSPI_CS_CTRL_RD_BRK_ENABLE(PSRAM_OSPI_IF);
__QSPI_CS_CTRL_DIS_CS_AFT_FIRST_BYTE_SET(PSRAM_OSPI_IF);
__QSPI_CS_PAGE_BOUNDARY_SET(PSRAM_OSPI_IF, page_boundary);
__QSPI_CS_PAGE_BOUNDARY_PROTECT_ENABLE(PSRAM_OSPI_IF);
__QSPI_REMAP_ADDRESS_SET(PSRAM_OSPI_IF, PSRAM_DAC_BASE);
__QSPI_CFG_OCTAL_OPI_DISABLE(PSRAM_OSPI_IF);
__QSPI_CFG_OCTAL_XCCELA_DISABLE(PSRAM_OSPI_IF);
__QSPI_ENABLE(PSRAM_OSPI_IF);
}
void psram_init(bool reset)
{
if (reset) {
qspi_stig_cmd(PSRAM_OSPI_IF, reset_enable_cmd, QSPI_STIG_CMD_EXE, 0, NULL);
// co_delay_10us(1000);
qspi_stig_cmd(PSRAM_OSPI_IF, reset_cmd, QSPI_STIG_CMD_EXE, 0, NULL);
// co_delay_10us(1000);
#if PSRAM_ENABLE_Q_MODE == 1
psram_enter_quad();
// co_delay_10us(1000);
#endif // PSRAM_ENABLE_Q_MODE == 1
}
#if PSRAM_HIGH_SPEED
psram_controller_init(0x0040);
#else
psram_controller_init(0x0010);
#endif
}
uint32_t psram_read_id(void)
{
uint32_t psram_id;
qspi_stig_cmd(PSRAM_OSPI_IF, psram_read_id_cmd, QSPI_STIG_CMD_READ, 3, (uint8_t *)&psram_id);
return (psram_id&0xffffff);
}
#endif