/*******************************************************************************
 * 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 2015-2022 Renesas Electronics Corporation All rights reserved.
 *******************************************************************************/

/*******************************************************************************
 * DESCRIPTION   :  RPC driver for QSPI Flash
 ******************************************************************************/
/******************************************************************************
 * @file          rpcqspidrv.c
 * - Version      : 0.07
 * @brief         RPC driver for QSPI Flash.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 15.10.2021 0.01     First Release
 *         : 16.02.2022 0.02     Modify how to write to RPC_WRBUF register.
 *         : 15.03.2022 0.03     Modify to use inline function in mem_io.h
 *         :                     when access to register.
 *         : 18.03.2022 0.04     Modify to read modify write when write to
 *         :                     register.
 *         : 23.03.2022 0.05     Modify command for QSPI Flash to refer to
 *         :                     command table.
 *         : 01.04.2022 0.06     Modify magic number to definition.
 *         : 09.11.2022 0.07     License notation change.
 *****************************************************************************/

#include <stdint.h>
#include <stddef.h>
#include <remap.h>
#include <mem_io.h>
#include <micro_wait.h>
#include <cpg_register.h>
#include <rpc_register.h>
#include <rpcqspidrv.h>
#include <rpc.h>
#include <wdt.h>
#include <log.h>

#include "dma2.h"

static uint32_t read_register_qspi_flash(uint32_t cmd, uint32_t *readData);

void init_rpc_qspi_flash_4fastread_ext_mode(void)
{
	uint32_t reg;

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_WBUF2
			| RPC_PHYCNT_WBUF
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
	reg |= RPC_PHYCNT_CAL;
	mem_write32(RPC_PHYCNT, reg);

    reg =  mem_read32(RPC_CMNCR);
    reg &= ~(CMNCR_MD_MANUAL    /* External address space read mode */
            | CMNCR_BSZ_MASK);  /* Data Bus Size: Serial flash memory x 1*/
    reg |= (CMNCR_MOIIO3_HIZ
            | CMNCR_MOIIO2_HIZ
            | CMNCR_MOIIO1_HIZ
            | CMNCR_MOIIO0_HIZ
            | CMNCR_IO0FV_HIZ);
    mem_write32(RPC_CMNCR, reg);
        /* bit31  MD       =  0 : External address space read mode */
        /* bit1-0 BSZ[1:0] = 00 : QSPI Flash x 1 */

    reg =  mem_read32(RPC_DRCR);
    reg &= ~(DRCR_SSLN
            | DRCR_RCF
            | DRCR_SSLE);
    reg |= (DRCR_RBURST_32UNITS
            | DRCR_RBE_BURST);
    mem_write32(RPC_DRCR, reg);
		/* bit20-16 RBURST[4:0] = 11111 : 32 continuous data unit */
		/* bit8     RBE         =     1 : Burst read */

    reg =  mem_read32(RPC_DRCMR);
    reg &= ~(DRCMR_CMD_MASK
            | DRCMR_OCMD_MASK);
    reg |= ((gp_qspi_cmd_tbl -> read_fast) << DRCMR_SMCMR_CMD_SHIFT);
    mem_write32(RPC_DRCMR, reg);
		/* bit23-16 CMD[7:0] = 0x0C : 4FAST_READ 0Ch Command 4-byte address command */

    reg =  mem_read32(RPC_DREAR);
    reg &= ~(DREAR_EAV_MASK
            | DREAR_EAC_MASK);
    reg |= DREAR_EAC_26BITS;
    mem_write32(RPC_DREAR, reg);
		/* bit23-16 EAV[7:0]   = 0    : ADR[32:26] output set0 */
		/* bit2-0   EAC[2:0]   = 001  : ADR[25:0 ] Enable */

    reg =  mem_read32(RPC_DRENR);
    reg &= ~(DRENR_CDB_MASK
            | DRENR_OCDB_MASK
            | DRENR_ADB_MASK
            | DRENR_OPDB_MASK
            | DRENR_DRDB_MASK
            | DRENR_OCDE_EN
            | DRENR_ADE_MASK
            | DRENR_OPDE_MASK);
    reg |= (DRENR_DME_EN
            | DRENR_CDE_EN
            | DRENR_ADE_ONE_SERIAL);
	mem_write32(RPC_DRENR, reg);
		/* bit31-30 CDB[1:0]   =   00 : 1bit width command (QSPI0_MOSI) */
		/* bit25-24 ADB[1:0]   =   00 : 1bit width address (QSPI0_MOSI) */
		/* bit17-16 DRDB[1:0]  =   00 : 1bit width transfer data (QSPI0_IO0) */
		/* bit15    DME        =    1 : dummy cycle enable */
		/* bit14    CDE        =    1 : Command enable */
		/* bit11-8  ADE[3:0]   = 1111 : ADR[31:0] output (32 Bit Address) */

    reg =  mem_read32(RPC_DRDMCR);
    reg &= ~(DRDMCR_DMCYC_MASK);
    reg |= DRDMCR_DMCYC_8;
    mem_write32(RPC_DRDMCR, reg);
		/* bit2-0 DMCYC[2:0]   = 111 : 8 cycle dummy wait */

    reg =  mem_read32(RPC_DRDRENR);
    reg &= ~(DRDRENR_HYPE_MASK
            | DRDRENR_ADDRE
            | DRDRENR_OPDRE
            | DRDRENR_DRDRE);
    mem_write32(RPC_DRDRENR, reg);
		/* bit8 ADDRE  = 0 : Address SDR transfer */
		/* bit0 DRDRE  = 0 : DATA SDR transfer */
}
/* End of function init_rpc_qspi_flash_4fastread_ext_mode */

void init_rpc_qspi_flash(void)
{
    uint32_t reg;

	power_on_rpc();

	set_rpc_clock_mode(RPC_CLK_80M);
	reset_rpc();
	set_rpc_ssl_delay();

    reg =  mem_read32(RPC_OFFSET1);
    reg &= ~(PHYOFFSET1_MASK);
    reg |= PHYOFFSET1_DMA_QSPI;
    mem_write32(RPC_OFFSET1, reg);
}
/* End of function init_rpc_qspi_flash */

/* 4SE DCh 4-byte address */
void sector_erase_4byte_qspi_flash(uint32_t sector_addr)
{
	uint32_t reg;

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_CAL
			| RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_WBUF2
			| RPC_PHYCNT_WBUF
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
		/* bit31  CAL         =  1 : PHY calibration */
		/* bit1-0 PHYMEM[1:0] = 00 : QSPI-SDR */

    reg =  mem_read32(RPC_CMNCR);
    reg &= ~(CMNCR_BSZ_MASK);
    reg |= (CMNCR_MD_MANUAL
            | CMNCR_MOIIO3_HIZ
            | CMNCR_MOIIO2_HIZ
            | CMNCR_MOIIO1_HIZ
            | CMNCR_MOIIO0_HIZ
            | CMNCR_IO0FV_HIZ);
    mem_write32(RPC_CMNCR, reg);
		/* bit31  MD       =  1 : Manual mode */
		/* bit1-0 BSZ[1:0] = 00 : QSPI Flash x 1 */

    reg =  mem_read32(RPC_SMCMR);
    reg &= ~(SMCMR_CMD_MASK
            | SMCMR_OCMD_MASK);
    reg |= ((gp_qspi_cmd_tbl -> sector_erase_4byte_addr) << DRCMR_SMCMR_CMD_SHIFT);
    mem_write32(RPC_SMCMR, reg);
		/* bit23-16 CMD[7:0] = 0xDC : Sector Erase 4-byte address command */

	mem_write32(RPC_SMADR,   sector_addr);

    reg =  mem_read32(RPC_SMDRENR);
    reg &= ~(SMDRENR_HYPE_MASK
            | SMDRENR_ADDRE
            | SMDRENR_OPDRE
            | SMDRENR_SPIDRE);
    mem_write32(RPC_SMDRENR, reg);
		/* bit8 ADDRE  = 0 : Address SDR transfer */
		/* bit0 SPIDRE = 0 : DATA SDR transfer */

    reg =  mem_read32(RPC_SMENR);
    reg &= ~(SMENR_CDB_MASK
            | SMENR_OCDB_MASK
            | SMENR_ADB_MASK
            | SMENR_OPDB_MASK
            | SMENR_SPIDB_MASK
            | SMENR_DME_EN
            | SMENR_OCDE_EN
            | SMENR_ADE_MASK
            | SMENR_OPDE_MASK
            | SMENR_SPIDE_MASK);
    reg |= (SMENR_CDE_EN
            | SMENR_ADE_SERIAL_31);
    mem_write32(RPC_SMENR, reg);
		/* bit31-30 CDB[1:0]   =   00 : 1bit width command (QSPI0_MOSI) */
		/* bit25-24 ADB[1:0]   =   00 : 1bit width address (QSPI0_MOSI) */
		/* bit17-16 SPIDB[1:0] =   00 : 1bit width transfer data (QSPI0_MISO) */
		/* bit15    DME        =    0 : No dummy cycle */
		/* bit14    CDE        =    1 : Command enable */
		/* bit11-8  ADE[3:0]   = 1111 : ADR[31:0] output (32 Bit Address) */
		/* bit3-0   SPIDE[3:0] = 0000 : No transfer */

    reg =  mem_read32(RPC_SMCR);
    reg &= ~(SMCR_SSLKP
            | SMCR_SPIRE
            | SMCR_SPIWE);
    reg |= SMCR_SPIE;
    mem_write32(RPC_SMCR, reg);
		/* bit2     SPIRE      = 0 : Data read disable */
		/* bit1     SPIWE      = 0 : Data write disable */
		/* bit0     SPIE       = 1 : SPI transfer start */

	wait_rpc_tx_end();
}
/* End of function sector_erase_4byte_qspi_flash */

/* 4P4E 21h 4-byte address */
void parameter_sector_erase_4kb_qspi_flash(uint32_t sector_addr)
{
	uint32_t reg;

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_CAL
			| RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_WBUF2
			| RPC_PHYCNT_WBUF
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
		/* bit31  CAL         =  1 : PHY calibration */
		/* bit1-0 PHYMEM[1:0] = 00 : QSPI-SDR */

    reg =  mem_read32(RPC_CMNCR);
    reg &= ~(CMNCR_BSZ_MASK);
    reg |= (CMNCR_MD_MANUAL
            | CMNCR_MOIIO3_HIZ
            | CMNCR_MOIIO2_HIZ
            | CMNCR_MOIIO1_HIZ
            | CMNCR_MOIIO0_HIZ
            | CMNCR_IO0FV_HIZ);
    mem_write32(RPC_CMNCR, reg);
		/* bit31  MD       =  1 : Manual mode */
		/* bit1-0 BSZ[1:0] = 00 : QSPI Flash x 1 */

    reg =  mem_read32(RPC_SMCMR);
    reg &= ~(SMCMR_CMD_MASK
            | SMCMR_OCMD_MASK);
    reg |= ((gp_qspi_cmd_tbl -> parameter_4kbyte_erase) << DRCMR_SMCMR_CMD_SHIFT);
    mem_write32(RPC_SMCMR, reg);
		/* bit23-16 CMD[7:0] = 0x21 : Parameter 4-kB Sector Erasecommand */

	mem_write32(RPC_SMADR,   sector_addr);

    reg =  mem_read32(RPC_SMDRENR);
    reg &= ~(SMDRENR_HYPE_MASK
            | SMDRENR_ADDRE
            | SMDRENR_OPDRE
            | SMDRENR_SPIDRE);
    mem_write32(RPC_SMDRENR, reg);
		/* bit8 ADDRE  = 0 : Address SDR transfer */
		/* bit0 SPIDRE = 0 : DATA SDR transfer */

    reg =  mem_read32(RPC_SMENR);
    reg &= ~(SMENR_CDB_MASK
            | SMENR_OCDB_MASK
            | SMENR_ADB_MASK
            | SMENR_OPDB_MASK
            | SMENR_SPIDB_MASK
            | SMENR_DME_EN
            | SMENR_OCDE_EN
            | SMENR_ADE_MASK
            | SMENR_OPDE_MASK
            | SMENR_SPIDE_MASK);
    reg |= (SMENR_CDE_EN
            | SMENR_ADE_SERIAL_31);
    mem_write32(RPC_SMENR, reg);
		/* bit31-30 CDB[1:0]   =   00 : 1bit width command (QSPI0_MOSI) */
		/* bit25-24 ADB[1:0]   =   00 : 1bit width address (QSPI0_MOSI) */
		/* bit17-16 SPIDB[1:0] =   00 : 1bit width transfer data (QSPI0_MISO) */
		/* bit15    DME        =    0 : No dummy cycle */
		/* bit14    CDE        =    1 : Command enable */
		/* bit11-8  ADE[3:0]   = 1111 : ADR[31:0] output (32 Bit Address) */
		/* bit3-0   SPIDE[3:0] = 0000 : No transfer */

    reg =  mem_read32(RPC_SMCR);
    reg &= ~(SMCR_SSLKP
            | SMCR_SPIRE
            | SMCR_SPIWE);
    reg |= SMCR_SPIE;
    mem_write32(RPC_SMCR, reg);
		/* bit2     SPIRE      = 0 : Data read disable */
		/* bit1     SPIWE      = 0 : Data write disable */
		/* bit0     SPIE       = 1 : SPI transfer start */

	wait_rpc_tx_end();
}
/* End of function parameter_sector_erase_4kb_qspi_flash */

/* Page Program (4PP:12h)  4-byte address */
void write_data_4pp_with_buf_qspi_flash(uint32_t addr, uint32_t source_addr)
{
	uintptr_t i=0;
	uint32_t reg;

    reg =  mem_read32(RPC_DRCR);
    reg |= (DRCR_SSLN
            | DRCR_RBURST_32UNITS
            | DRCR_RCF
            | DRCR_RBE_BURST
            | DRCR_SSLE);
    mem_write32(RPC_DRCR, reg);
		/* bit9   RCF         =  1 : Read Cache Clear */

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_CAL
			| RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0
			| RPC_PHYCNT_WBUF2
			| RPC_PHYCNT_WBUF);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
		/* bit31  CAL         =  1 : PHY calibration */
		/* bit2   WBUF        =  1 : Write Buffer Enable */
		/* bit1-0 PHYMEM[1:0] = 00 : QSPI-SDR */

	for(i = 0; i < RPC_WRITE_BUF_SIZE; i = i + TRANS_SIZE_64BYTE)
	{
		dma2_start_xbyte(RPC_WRBUF_PHYS+i, source_addr+i, TRANS_SIZE_64BYTE, TRANS_UNIT_64BYTES);
		dma2_end();
		// dma_trans_start(RPC_WRBUF_PHYS+i, source_addr+i, TRANS_SIZE_64BYTE);
		// dma_trans_end_check();
	}

    reg =  mem_read32(RPC_CMNCR);
    reg &= ~(CMNCR_BSZ_MASK);
    reg |= (CMNCR_MD_MANUAL
            | CMNCR_MOIIO3_HIZ
            | CMNCR_MOIIO2_HIZ
            | CMNCR_MOIIO1_HIZ
            | CMNCR_MOIIO0_HIZ
            | CMNCR_IO0FV_HIZ);
    mem_write32(RPC_CMNCR, reg);
		/* bit31  MD       =  1 : Manual mode */
		/* bit1-0 BSZ[1:0] = 00 : QSPI Flash x 1 */

    reg =  mem_read32(RPC_SMCMR);
    reg &= ~(SMCMR_CMD_MASK
            | SMCMR_OCMD_MASK);
    reg |= ((gp_qspi_cmd_tbl -> pp_4byte_addr) << DRCMR_SMCMR_CMD_SHIFT);
    mem_write32(RPC_SMCMR, reg);
		/* bit23-16 CMD[7:0] = 0x12 : Page Program 4-byte address */

	mem_write32(RPC_SMADR,   addr);

    reg =  mem_read32(RPC_SMDRENR);
    reg &= ~(SMDRENR_HYPE_MASK
            | SMDRENR_ADDRE
            | SMDRENR_OPDRE
            | SMDRENR_SPIDRE);
    mem_write32(RPC_SMDRENR, reg);
		/* bit8 ADDRE  = 0 : Address SDR transfer */
		/* bit0 SPIDRE = 0 : DATA SDR transfer */

    reg =  mem_read32(RPC_SMENR);
    reg &= ~(SMENR_CDB_MASK
            | SMENR_OCDB_MASK
            | SMENR_ADB_MASK
            | SMENR_OPDB_MASK
            | SMENR_SPIDB_MASK
            | SMENR_DME_EN
            | SMENR_OCDE_EN
            | SMENR_ADE_MASK
            | SMENR_OPDE_MASK
            | SMENR_SPIDE_MASK);
    reg |= (SMENR_CDE_EN
            | SMENR_ADE_SERIAL_31
            | SMENR_SPIDE_SPI_32);
    mem_write32(RPC_SMENR, reg);
		/* bit31-30 CDB[1:0]   =   00 : 1bit width command (QSPI0_MOSI) */
		/* bit25-24 ADB[1:0]   =   00 : 1bit width address (QSPI0_MOSI) */
		/* bit17-16 SPIDB[1:0] =   00 : 1bit width transfer data (QSPI0_MISO) */
		/* bit15    DME        =    0 : No dummy cycle */
		/* bit14    CDE        =    1 : Command enable */
		/* bit11-8  ADE[3:0]   = 1111 : ADR[31:0] is output */
		/* bit3-0   SPIDE[3:0] = 1111 : 32bit transfer */

    reg =  mem_read32(RPC_SMCR);
    reg &= ~(SMCR_SSLKP
            | SMCR_SPIRE);
    reg |= (SMCR_SPIWE
            | SMCR_SPIE);
    mem_write32(RPC_SMCR, reg);
		/* bit2     SPIRE      = 0 : Data read disable */
		/* bit1     SPIWE      = 1 : Data write enable */
		/* bit0     SPIE       = 1 : SPI transfer start */

	wait_rpc_tx_end();

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0
			| RPC_PHYCNT_WBUF2);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_WBUF
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
		/* bit31  CAL         =  0 : No PHY calibration */
		/* bit2   WBUF        =  0 : Write Buffer Disable */
		/* bit1-0 PHYMEM[1:0] = 00 : QSPI-SDR */

    reg =  mem_read32(RPC_DRCR);
    reg |= (DRCR_SSLN
            | DRCR_RBURST_32UNITS
            | DRCR_RCF
            | DRCR_RBE_BURST
            | DRCR_SSLE);
    mem_write32(RPC_DRCR, reg);
		/* bit9   RCF         =  1 : Read Cache Clear */
}
/* End of function write_data_4pp_with_buf_qspi_flash */

/* OnBoard QspiFlash(MT25QU01GB) */
uint32_t read_wip_status_register(uint32_t *readData)	/* for QSPIx1ch */
{
        return read_register_qspi_flash(gp_qspi_cmd_tbl -> read_any_register, readData);
}

#define RDCR_cmd        0x15
uint32_t read_configuration_register(uint32_t *readData)	/* for QSPIx1ch */
{
        return read_register_qspi_flash(RDCR_cmd, readData);
}

#define WRSR_cmd        0x01
void write_status_register(uint16_t stat_conf)
{
	uint32_t reg;

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_CAL
			| RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_WBUF2
			| RPC_PHYCNT_WBUF
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
		/* bit31  CAL         =  1 : PHY calibration */
		/* bit1-0 PHYMEM[1:0] = 00 : QSPI-SDR */

    reg =  mem_read32(RPC_CMNCR);
    reg &= ~(CMNCR_BSZ_MASK);
    reg |= (CMNCR_MD_MANUAL
            | CMNCR_MOIIO3_HIZ
            | CMNCR_MOIIO2_HIZ
            | CMNCR_MOIIO1_HIZ
            | CMNCR_MOIIO0_HIZ
            | CMNCR_IO0FV_HIZ);
    mem_write32(RPC_CMNCR, reg);
		/* bit31  MD       =  1 : Manual mode */
		/* bit1-0 BSZ[1:0] = 00 : QSPI Flash x 1 */

    reg =  mem_read32(RPC_SMCMR);
    reg &= ~(SMCMR_CMD_MASK
            | SMCMR_OCMD_MASK);
    reg |= ((WRSR_cmd) << DRCMR_SMCMR_CMD_SHIFT);
    mem_write32(RPC_SMCMR, reg);
		/* bit23-16 CMD[7:0] = 0x01 : write status/configuration register command */

    reg =  mem_read32(RPC_SMENR);
    reg &= ~(SMENR_CDB_MASK
            | SMENR_OCDB_MASK
            | SMENR_ADB_MASK
            | SMENR_OPDB_MASK
            | SMENR_SPIDB_MASK
            | SMENR_DME_EN
            | SMENR_OCDE_EN
            | SMENR_ADE_MASK
            | SMENR_OPDE_MASK
            | SMENR_SPIDE_MASK);
    reg |= (SMENR_CDE_EN
            | SMENR_SPIDE_SPI_16);
    mem_write32(RPC_SMENR, reg);
		/* bit31-30 CDB[1:0]   =   00 : 1bit width command (QSPI0_MOSI) */
		/* bit25-24 ADB[1:0]   =   00 : 1bit width address (QSPI0_MOSI) */
		/* bit17-16 SPIDB[1:0] =   00 : 1bit width transfer data (QSPI0_MISO) */
		/* bit15    DME        =    0 : No dummy cycle */
		/* bit14    CDE        =    1 : Command enable */
		/* bit11-8  ADE[3:0]   = 0000 : Address output disable */
		/* bit3-0   SPIDE[3:0] = 1100 : 16bit transfer */

	mem_write16(RPC_SMWDR0, stat_conf);

    reg =  mem_read32(RPC_SMCR);
    reg &= ~(SMCR_SSLKP
            | SMCR_SPIRE);
    reg |= (SMCR_SPIWE
            | SMCR_SPIE);
    mem_write32(RPC_SMCR, reg);
		/* bit2     SPIRE      = 0 : Data read disable */
		/* bit1     SPIWE      = 1 : Data write enable */
		/* bit0     SPIE       = 1 : SPI transfer start */

	wait_rpc_tx_end();
}

void set_rpc_clock_mode(uint32_t mode)
{
	uint32_t dataL=0;
    uint32_t reg;

	if(mode == RPC_CLK_160M){
		dataL = RPCCKCR_RPCFC_160M;	/* RPC clock 160MHz */
	}else if(mode == RPC_CLK_80M){
		dataL = RPCCKCR_RPCFC_80M;	/* RPC clock 80MHz */
	}else{
		dataL = RPCCKCR_RPCFC_40M;	/* RPC clock 40MHz */
	}

    reg = mem_read32(CPG_RPCCKCR);
    reg &= ~(RPCCKCR_RPCFC_MASK);
    dataL |= reg;
	mem_write32(CPG_CPGWPR,  ~dataL);
	mem_write32(CPG_RPCCKCR, dataL);

	(void)mem_read32(CPG_RPCCKCR);  /* dummy read */
}
/* End of function set_rpc_clock_mode */

void wait_rpc_tx_end(void)
{
	uint32_t dataL=0;

	while(1)
	{
		wdt_restart();
		dataL = mem_read32(RPC_CMNSR);
		if(dataL & BIT0)	break;
		/*  Wait for TEND = 1 */
	}
}
/* End of function wait_rpc_tx_end */

void reset_rpc(void)
{
	mem_write32(CPG_CPGWPR, ~BIT29);
	mem_write32(CPG_SRCR6,  BIT29);
	/* wait: tRLRH Reset# low pulse width 10us */
	micro_wait(20);		/*  wait 20us */

	mem_write32(CPG_CPGWPR,   ~BIT29);
	mem_write32(CPG_SRSTCLR6, BIT29);
	/* wait: tREADY1(35us) - tRHSL(10us) = 25us */
	micro_wait(40);		/*  wait 40us */
}
/* End of function reset_rpc */

void set_rpc_ssl_delay(void)
{
    uint32_t reg;

    reg = mem_read32(RPC_SSLDR);
    reg |= SSLDR_SLNDL;
	mem_write32(RPC_SSLDR, reg);
		/* bit10-8  SLNDL[2:0] =  100 : 5.5 cycles of QSPIn_SPCLK  */
}
/* End of function set_rpc_ssl_delay */

void power_on_rpc(void)
{
	uint32_t dataL=0;
		dataL = mem_read32(CPG_MSTPSR6);
	if(dataL & BIT29){	/*  case RPC(QSPI) Standby */
		dataL &= ~BIT29;
		mem_write32(CPG_CPGWPR,  ~dataL);
		mem_write32(CPG_MSTPCR6, dataL);
		while( BIT29 & mem_read32(CPG_MSTPSR6) );  /*  wait bit=0 */
	}
}
/* End of function power_on_rpc */

uint32_t read_qspi_flash_id(uint32_t *readData)	/* for QSPIx1ch */
{
        return read_register_qspi_flash(FLASH_CMD_READ_ID, readData);
}

uint32_t read_status_qspi_flash(uint32_t *readData) {
        return read_register_qspi_flash(gp_qspi_cmd_tbl -> read_stts_register, readData);
}

static uint32_t read_register_qspi_flash(uint32_t cmd, uint32_t *readData)	/* for QSPIx1ch */
{
	uint32_t reg;

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_WBUF2
			| RPC_PHYCNT_WBUF
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
	reg |= RPC_PHYCNT_CAL;
	mem_write32(RPC_PHYCNT, reg);
		/* bit31  CAL         =  1 : PHY calibration */
		/* bit1-0 PHYMEM[1:0] = 00 : QSPI-SDR */

    reg =  mem_read32(RPC_CMNCR);
    reg &= ~(CMNCR_BSZ_MASK);
    reg |= (CMNCR_MD_MANUAL
            | CMNCR_MOIIO3_HIZ
            | CMNCR_MOIIO2_HIZ
            | CMNCR_MOIIO1_HIZ
            | CMNCR_MOIIO0_HIZ
            | CMNCR_IO0FV_HIZ);
    mem_write32(RPC_CMNCR, reg);
		/* bit31  MD       =  1 : Manual mode */
		/* bit1-0 BSZ[1:0] = 00 : QSPI Flash x 1 */

    reg =  mem_read32(RPC_SMCMR);
    reg &= ~(SMCMR_CMD_MASK
            | SMCMR_OCMD_MASK);
    reg |= ((cmd) << DRCMR_SMCMR_CMD_SHIFT);
    mem_write32(RPC_SMCMR, reg);
		/* bit23-16 CMD[7:0] = 0x05 : Status Read command (for Palladium QSPI model) */

    reg =  mem_read32(RPC_SMDRENR);
    reg &= ~(SMDRENR_HYPE_MASK
            | SMDRENR_ADDRE
            | SMDRENR_OPDRE
            | SMDRENR_SPIDRE);
    mem_write32(RPC_SMDRENR, reg);
		/* bit8 ADDRE  = 0 : Address SDR transfer */
		/* bit0 SPIDRE = 0 : DATA SDR transfer */

    reg =  mem_read32(RPC_SMENR);
    reg &= ~(SMENR_CDB_MASK
            | SMENR_OCDB_MASK
            | SMENR_ADB_MASK
            | SMENR_OPDB_MASK
            | SMENR_SPIDB_MASK
            | SMENR_DME_EN
            | SMENR_OCDE_EN
            | SMENR_ADE_MASK
            | SMENR_OPDE_MASK
            | SMENR_SPIDE_MASK);
    reg |= (SMENR_CDE_EN
            | SMENR_SPIDE_SPI_32);
    mem_write32(RPC_SMENR, reg);
		/* bit31-30 CDB[1:0]   =   00 : 1bit width command (QSPI0_MOSI) */
		/* bit25-24 ADB[1:0]   =   00 : 1bit width address (QSPI0_MOSI) */
		/* bit17-16 SPIDB[1:0] =   00 : 1bit width transfer data (QSPI0_MISO) */
		/* bit15    DME        =    0 : No dummy cycle */
		/* bit14    CDE        =    1 : Command enable */
		/* bit11-8  ADE[3:0]   = 0000 : Address output disable */
		/* bit3-0   SPIDE[3:0] = 1111 : 32bit transfer */

    reg =  mem_read32(RPC_SMCR);
    reg &= ~(SMCR_SSLKP
            | SMCR_SPIWE);
    reg |= (SMCR_SPIRE
            | SMCR_SPIE);
    mem_write32(RPC_SMCR, reg);
		/* bit2     SPIRE      = 1 : Data read enable */
		/* bit1     SPIWE      = 0 : Data write disable */
		/* bit0     SPIE       = 1 : SPI transfer start */

	wait_rpc_tx_end();

	readData[0] = mem_read32(RPC_SMRDR0);	/* read data[31:0] */

	return(readData[0]);
}
/* End of function read_register_qspi_flash */

void write_command_qspi_flash(uint32_t command)	/* for QSPIx1ch */
{
	uint32_t reg;

	reg = mem_read32(RPC_PHYCNT);
	reg |= (RPC_PHYCNT_CAL
			| RPC_PHYCNT_STRTIM3
			| RPC_PHYCNT_STRTIM2
			| RPC_PHYCNT_STRTIM1
			| RPC_PHYCNT_STRTIM0);
	reg &= ~(RPC_PHYCNT_HS
			| RPC_PHYCNT_WBUF2
			| RPC_PHYCNT_WBUF
			| RPC_PHYCNT_PHYMEM_HYP);
	mem_write32(RPC_PHYCNT, reg);
		/* bit31  CAL         =  1 : PHY calibration */
		/* bit1-0 PHYMEM[1:0] = 00 : QSPI-SDR */

    reg =  mem_read32(RPC_CMNCR);
    reg &= ~(CMNCR_BSZ_MASK);
    reg |= (CMNCR_MD_MANUAL
            | CMNCR_MOIIO3_HIZ
            | CMNCR_MOIIO2_HIZ
            | CMNCR_MOIIO1_HIZ
            | CMNCR_MOIIO0_HIZ
            | CMNCR_IO0FV_HIZ);
    mem_write32(RPC_CMNCR, reg);
		/* bit31  MD       =  1 : Manual mode */
		/* bit1-0 BSZ[1:0] = 00 : QSPI Flash x 1 */

    reg =  mem_read32(RPC_SMCMR);
    reg &= ~(SMCMR_CMD_MASK
            | SMCMR_OCMD_MASK);
    reg |= (command & (SMCMR_CMD_MASK | SMCMR_OCMD_MASK));
    mem_write32(RPC_SMCMR, reg);
		/* bit23-16 CMD[7:0] : command */

    reg =  mem_read32(RPC_SMDRENR);
    reg &= ~(SMDRENR_HYPE_MASK
            | SMDRENR_ADDRE
            | SMDRENR_OPDRE
            | SMDRENR_SPIDRE);
    mem_write32(RPC_SMDRENR, reg);
		/* bit8 ADDRE  = 0 : Address SDR transfer */
		/* bit0 SPIDRE = 0 : DATA SDR transfer */

    reg =  mem_read32(RPC_SMENR);
    reg &= ~(SMENR_CDB_MASK
            | SMENR_OCDB_MASK
            | SMENR_ADB_MASK
            | SMENR_OPDB_MASK
            | SMENR_SPIDB_MASK
            | SMENR_DME_EN
            | SMENR_OCDE_EN
            | SMENR_ADE_MASK
            | SMENR_ADE_MASK
            | SMENR_OPDE_MASK
            | SMENR_SPIDE_MASK);
    reg |= SMENR_CDE_EN;
    mem_write32(RPC_SMENR, reg);
		/* bit31-30 CDB[1:0]   =   00 : 1bit width command (QSPI0_MOSI) */
		/* bit25-24 ADB[1:0]   =   00 : 1bit width address (QSPI0_MOSI) */
		/* bit17-16 SPIDB[1:0] =   00 : 1bit width transfer data (QSPI0_MISO) */
		/* bit15    DME        =    0 : No dummy cycle */
		/* bit14    CDE        =    1 : Command enable */
		/* bit11-8  ADE[3:0]   = 0000 : Address output disable */
		/* bit3-0   SPIDE[3:0] = 0000 : No transfer */

    reg =  mem_read32(RPC_SMCR);
    reg &= ~(SMCR_SSLKP
            | SMCR_SPIRE
            | SMCR_SPIWE);
    reg |= SMCR_SPIE;
    mem_write32(RPC_SMCR, reg);
		/* bit2     SPIRE      = 0 : Data read disable */
		/* bit1     SPIWE      = 0 : Data write disable */
		/* bit0     SPIE       = 1 : SPI transfer start */

	wait_rpc_tx_end();

}
/* End of function write_command_qspi_flash */

