281 lines
11 KiB
C
281 lines
11 KiB
C
/*******************************************************************************
|
|
* DISCLAIMER
|
|
* This software is supplied by Renesas Electronics Corporation and is only
|
|
* intended for use with Renesas products. No other uses are authorized. This
|
|
* software is owned by Renesas Electronics Corporation and is protected under
|
|
* all applicable laws, including copyright laws.
|
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
|
|
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
|
|
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
|
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
|
|
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
|
|
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
|
|
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
|
|
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
* Renesas reserves the right, without notice, to make changes to this software
|
|
* and to discontinue the availability of this software. By using this software,
|
|
* you agree to the additional terms and conditions found by accessing the
|
|
* following link:
|
|
* http://www.renesas.com/disclaimer
|
|
* Copyright 2021-2024 Renesas Electronics Corporation All rights reserved.
|
|
*******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* DESCRIPTION : RPC driver
|
|
******************************************************************************/
|
|
/******************************************************************************
|
|
* @file rpc.c
|
|
* - Version : 0.08
|
|
* @brief Initial setting process of RPC.
|
|
* .
|
|
*****************************************************************************/
|
|
/******************************************************************************
|
|
* History : DD.MM.YYYY Version Description
|
|
* : 28.07.2021 0.01 First Release
|
|
* : 03.09.2021 0.02 Add rpc_release function.
|
|
* : 27.07.2022 0.03 Add QSPI Flash vendor ID check and QSPI Flash
|
|
* : command initialization.
|
|
* : 22.08.2022 0.04 Add DDR mode for QSPI Flash.
|
|
* : 21.09.2022 0.05 Fix comparison of test data
|
|
* : in adjust_strobe_timing function.
|
|
* : 12.01.2023 0.06 Add PFC setting to qspi_ddr_transfer_mode()
|
|
* : function.
|
|
* : 04.04.2023 0.07 Removed stdio.h.
|
|
* : 17.06.2024 0.08 Fix PUEN register setting when QSPI DDR mode.
|
|
*****************************************************************************/
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <remap.h>
|
|
#include <mem_io.h>
|
|
#include <rst_register.h>
|
|
#include <cpg_register.h>
|
|
#include <cpg.h>
|
|
#include <rpc_register.h>
|
|
#include <rpcqspidrv.h>
|
|
#include <rpc.h>
|
|
#include <image_load_flash.h>
|
|
#include <pfc.h>
|
|
#include <log.h>
|
|
|
|
#define RST_MODEMR0_BOOTMODE (0xFU << 1U)
|
|
#define BOOTMODE_QSPI_SINGLE_40MHZ (0x4U)
|
|
#define BOOTMODE_QSPI_DMA (0x6U)
|
|
|
|
typedef struct{
|
|
uint32_t reg_addr; /* registers address. */
|
|
uint32_t value; /* setting value. */
|
|
} st_register_table_t;
|
|
|
|
#define RPC_TBL_MAX (13U)
|
|
|
|
static st_register_table_t g_rpc_reg_hwinit_val_tbl[RPC_TBL_MAX];
|
|
|
|
/* The number of Flash vendor */
|
|
#if USER_ADDED_QSPI == 0
|
|
#define VENDOR_NUM (1U)
|
|
#endif /* USER_ADDED_QSPI == 0 */
|
|
/* Command for S25FS512S */
|
|
#define MT25QU01GB_READ_FAST (0x0CU) /* 4FAST_READ, read_fast */
|
|
#define MT25QU01GB_SEC_ER_4BYTE_ADDR (0xDCU) /* 4SE, sector_erase_4byte_addr */
|
|
#define MT25QU01GB_PARA_4KBYTE_ER (0x21U) /* 4P4E, parameter_4kbyte_erase */
|
|
#define MT25QU01GB_PP_4BYTE_ADDR (0x12U) /* 4PP, pp_4byte_addr */
|
|
#define MT25QU01GB_READ_ANY_REG (0x05U) /* READ STATUS, read_any_register */
|
|
#define MT25QU01GB_READ_STATUS (0x70U) /* READ FLAG STATUS, read_stts_register */
|
|
#define MT25QU01GB_WRITE_ENABLE (0x06U) /* WREN, write_enable */
|
|
#define S25FS512S_READ_32BIT_ADDR (0x13U) /* read 32bit address */
|
|
#define S25FS512S_DDR_QUAD_IO_READ_32BIT_ADDR (0xEEU) /* DDR quad I/O read 32bit address */
|
|
|
|
#if USER_ADDED_QSPI == 1
|
|
/* User can customize for another vendor's QSPI Flash. */
|
|
#define VENDOR_NUM (2U)
|
|
/* Command for XXXXXXXXX */
|
|
#define XXXXXXXXX_READ_FAST (0x0CU) /* 4-byte read_fast */
|
|
#define XXXXXXXXX_SEC_ER_4BYTE_ADDR (0xDCU) /* sector_erase_4byte_addr */
|
|
#define XXXXXXXXX_PARA_4KBYTE_ER (0x21U) /* parameter_4kbyte_erase */
|
|
#define XXXXXXXXX_PP_4BYTE_ADDR (0x12U) /* page_program_4byte_addr */
|
|
#define XXXXXXXXX_READ_ANY_REG (0x05U) /* READ STATUS, read_any_register */
|
|
#define XXXXXXXXX_READ_STATUS (0x2BU) /* RDSCUR, read_stts_register */
|
|
#define XXXXXXXXX_WRITE_ENABLE (0x06U) /* WREN, write_enable */
|
|
#define XXXXXXXXX_READ_32BIT_ADDR (0x13U) /* read 32bit address */
|
|
#define XXXXXXXXX_DDR_QUAD_IO_READ_32BIT_ADDR (0xEEU) /* DDR quad I/O read 32bit address */
|
|
#endif /* USER_ADDED_QSPI == 1 */
|
|
|
|
static const st_qspi_cmd_tbl_t qspi_cmd_tbls[VENDOR_NUM] =
|
|
{
|
|
/* Command table for MT25QU01GB */
|
|
{
|
|
MT25QU01GB_READ_FAST, /* read_fast */
|
|
MT25QU01GB_SEC_ER_4BYTE_ADDR, /* sector_erase_4byte_addr */
|
|
MT25QU01GB_PARA_4KBYTE_ER, /* parameter_4kbyte_erase */
|
|
MT25QU01GB_PP_4BYTE_ADDR, /* pp_4byte_addr */
|
|
MT25QU01GB_READ_ANY_REG, /* read_any_register */
|
|
MT25QU01GB_READ_STATUS, /* read_status */
|
|
MT25QU01GB_WRITE_ENABLE, /* write_enable */
|
|
S25FS512S_READ_32BIT_ADDR, /* read 32bit address */
|
|
S25FS512S_DDR_QUAD_IO_READ_32BIT_ADDR /* DDR quad I/O read 32bit address */
|
|
},
|
|
#if USER_ADDED_QSPI == 1
|
|
/* Command table for XXXXXXXXX */
|
|
/* User can customize for another vendor's QSPI Flash. */
|
|
{
|
|
XXXXXXXXX_READ_FAST, /* read_fast */
|
|
XXXXXXXXX_SEC_ER_4BYTE_ADDR, /* sector_erase_4byte_addr */
|
|
XXXXXXXXX_PARA_4KBYTE_ER, /* parameter_4kbyte_erase */
|
|
XXXXXXXXX_PP_4BYTE_ADDR, /* pp_4byte_addr */
|
|
XXXXXXXXX_READ_ANY_REG, /* read_any_register */
|
|
XXXXXXXXX_READ_STATUS, /* read_status */
|
|
XXXXXXXXX_WRITE_ENABLE, /* write_enable */
|
|
XXXXXXXXX_READ_32BIT_ADDR, /* read 32bit address */
|
|
XXXXXXXXX_DDR_QUAD_IO_READ_32BIT_ADDR /* DDR quad I/O read 32bit address */
|
|
}
|
|
#endif /* USER_ADDED_QSPI == 1 */
|
|
};
|
|
|
|
static const uint32_t dev_id_index[VENDOR_NUM] =
|
|
{
|
|
/* QSPI Flash device ID */
|
|
DEVID_MT25QU01GB, /* MT25QU01GB */
|
|
#if USER_ADDED_QSPI == 1
|
|
/* User can customize for another vendor's QSPI Flash. */
|
|
DEVID_XXXXXXXXX
|
|
#endif /* USER_ADDED_QSPI == 1 */
|
|
};
|
|
|
|
const st_qspi_cmd_tbl_t* gp_qspi_cmd_tbl;
|
|
|
|
static void rpc_save_hw_init_val(void);
|
|
static uint32_t init_qspi_cmd(uint32_t device_id);
|
|
|
|
void rpc_init(void)
|
|
{
|
|
/* Save HW initial value of RPC registers */
|
|
rpc_save_hw_init_val();
|
|
}
|
|
|
|
void qspi_flash_rw_init(void)
|
|
{
|
|
uint32_t reg;
|
|
uint32_t qspi_flash_id;
|
|
uint32_t rtn_val;
|
|
static bool qspi_flash_id_checked = false;
|
|
|
|
if (qspi_flash_id_checked == true)
|
|
{
|
|
NOTICE("QSPI Flash ID has been checked.\n");
|
|
return;
|
|
}
|
|
qspi_flash_id_checked = true;
|
|
|
|
/* judge boot device */
|
|
reg = (mem_read32(RST_MODEMR0) & RST_MODEMR0_BOOTMODE) >> 1U;
|
|
|
|
if ((reg == BOOTMODE_QSPI_SINGLE_40MHZ) ||
|
|
(reg == BOOTMODE_QSPI_DMA))
|
|
{
|
|
/* check the transfer end flag */
|
|
rpc_end_state_check();
|
|
|
|
/* Initialize command for QSPI Flash. */
|
|
read_qspi_flash_id(&qspi_flash_id);
|
|
qspi_flash_id = (qspi_flash_id & DEVICE_ID_MASK);
|
|
NOTICE("QSPI Flash ID = 0x%08x\n", qspi_flash_id);
|
|
rtn_val = init_qspi_cmd(qspi_flash_id);
|
|
if(rtn_val != QSPI_CMD_INIT_SUCCESS)
|
|
{
|
|
/* unknown QSPI Flash ID */
|
|
ERROR("QSPI Flash command initialization error!!\n");
|
|
panic;
|
|
}
|
|
|
|
#if (QSPI_DDR_MODE==1)
|
|
/* Initialize for QSPI DDR transfer mode */
|
|
qspi_ddr_transfer_mode(gp_qspi_cmd_tbl->ddr_quad_io_read_32bit_addr);
|
|
#else
|
|
/* Initialize for QSPI SDR transfer mode */
|
|
qspi_sdr_transfer_mode(gp_qspi_cmd_tbl->read_32bit_addr);
|
|
#endif
|
|
}
|
|
}
|
|
/* End of function rpc_init(void) */
|
|
|
|
void rpc_release(void)
|
|
{
|
|
uint32_t loop;
|
|
|
|
/* Set HW initial value to RPC registers */
|
|
for(loop = 0; loop < RPC_TBL_MAX; loop++)
|
|
{
|
|
mem_write32(g_rpc_reg_hwinit_val_tbl[loop].reg_addr, g_rpc_reg_hwinit_val_tbl[loop].value);
|
|
}
|
|
}
|
|
/* End of function rpc_release(void) */
|
|
|
|
void rpc_end_state_check(void)
|
|
{
|
|
/* Wait until RPC data transfer is completed */
|
|
while ((mem_read32(RPC_CMNSR) & CMNSR_TEND) != 1U)
|
|
{
|
|
;
|
|
}
|
|
}
|
|
/* End of function rpc_end_state_check(void) */
|
|
|
|
|
|
static void rpc_save_hw_init_val(void)
|
|
{
|
|
uint32_t loop;
|
|
|
|
g_rpc_reg_hwinit_val_tbl[0].reg_addr = RPC_CMNCR;
|
|
g_rpc_reg_hwinit_val_tbl[1].reg_addr = RPC_DRCR;
|
|
g_rpc_reg_hwinit_val_tbl[2].reg_addr = RPC_DRCMR;
|
|
g_rpc_reg_hwinit_val_tbl[3].reg_addr = RPC_DREAR;
|
|
g_rpc_reg_hwinit_val_tbl[4].reg_addr = RPC_DRENR;
|
|
g_rpc_reg_hwinit_val_tbl[5].reg_addr = RPC_SMCR;
|
|
g_rpc_reg_hwinit_val_tbl[6].reg_addr = RPC_SMCMR;
|
|
g_rpc_reg_hwinit_val_tbl[7].reg_addr = RPC_SMENR;
|
|
/* RPC_SMRDR0 is Read only */
|
|
/* RPC_CMNSR is Read only */
|
|
g_rpc_reg_hwinit_val_tbl[8].reg_addr = RPC_DRDMCR;
|
|
g_rpc_reg_hwinit_val_tbl[9].reg_addr = RPC_DRDRENR;
|
|
g_rpc_reg_hwinit_val_tbl[10].reg_addr = RPC_SMDRENR;
|
|
g_rpc_reg_hwinit_val_tbl[11].reg_addr = RPC_PHYCNT;
|
|
g_rpc_reg_hwinit_val_tbl[12].reg_addr = RPC_PHYOFFSET1;
|
|
|
|
/* Save RPC register initial value */
|
|
for(loop = 0; loop < RPC_TBL_MAX; loop++)
|
|
{
|
|
g_rpc_reg_hwinit_val_tbl[loop].value = mem_read32(g_rpc_reg_hwinit_val_tbl[loop].reg_addr);
|
|
}
|
|
}
|
|
|
|
uint8_t prk3_rev = 3;
|
|
static uint32_t init_qspi_cmd(uint32_t device_id)
|
|
{
|
|
uint32_t i = 0U;
|
|
uint32_t rtn_val = QSPI_CMD_INIT_ERROR;
|
|
|
|
gp_qspi_cmd_tbl = NULL;
|
|
|
|
for (i = 0U; i < VENDOR_NUM; i++)
|
|
{
|
|
if (device_id == dev_id_index[i])
|
|
{
|
|
gp_qspi_cmd_tbl = &qspi_cmd_tbls[i];
|
|
if (device_id == DEVID_XXXXXXXXX)
|
|
prk3_rev = 4;
|
|
rtn_val = QSPI_CMD_INIT_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
return rtn_val;
|
|
}
|
|
|
|
int check_Erase_Fail(uint32_t status) {
|
|
if (prk3_rev <= 3)
|
|
return (status & BIT5);
|
|
return (status & BIT6);
|
|
}
|
|
/* End of function init_qspi_cmd(uint32_t device_id) */
|