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

/*******************************************************************************
 * DESCRIPTION   :  QSPI Flash driver for S25FS512S
 ******************************************************************************/
/******************************************************************************
 * @file          spiflash2drv.c
 * - Version      : 0.04
 * @brief         QSPI Flash driver for S25FS512S.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 15.10.2021 0.01     First Release
 *         : 23.03.2022 0.02     Modify command for QSPI Flash to refer to
 *         :                     command table.
 *         : 01.04.2022 0.03     Modify magic number to definition.
 *         : 09.11.2022 0.04     License notation change.
 *****************************************************************************/

#include <stdint.h>
#include <stddef.h>
#include <spiflash2drv.h>
#include <rpcqspidrv.h>
#include <rpc.h>
#include <log.h>

#include "dma2.h"

#define QSPI_PARAM_SEC_SIZE    (0x1000U)
#define QSPI_PARAM_SEC_MASK    (0xFFFFF000U)

void fast_rd_qspi_flash(uint32_t sourceSpiAdd, uint32_t destinationAdd, uint32_t byteCount)
{
	uint32_t sourceAdd;

	init_rpc_qspi_flash_4fastread_ext_mode();

	sourceAdd = SPI_IOADDRESS_TOP + sourceSpiAdd;

	// dma_trans_start(destinationAdd, sourceAdd, byteCount);
	// dma_trans_end_check();
	// dma2_init();
	dma2_start(destinationAdd, sourceAdd, byteCount, DMA_MODE_SRC_INC);
	dma2_end();
}
/* End of function fast_rd_qspi_flash */

/* Qspi:Sector Erase */
/* 4SE DCh */
void sector_erase_NNNkb_qspi_flash_s25s512s(uint32_t addr)
{
	uint32_t status;

	/* WRITE ENABLE */
	write_command_qspi_flash((gp_qspi_cmd_tbl -> write_enable) << DRCMR_SMCMR_CMD_SHIFT);

    sector_erase_4byte_qspi_flash(addr);

	while(1)
	{
		read_status_qspi_flash(&status);
		if( check_Erase_Fail(status) )
		{
			// put_str("Erase Error", CRLF_OFF);
			ERROR("Erase Error!!\n");
			break;
		}
		read_wip_status_register(&status);
		if( !(status & BIT0) )
		{
			break;
		}
	}
}
/* End of function sector_erase_NNNkb_qspi_flash_s25s512s */

/* Qspi:Parameter 4-kB Sector Erase */
/* 4P4E 21h */
void parameter_sector_erase_4kb_qspi_flash_s25s512s(uint32_t addr)
{
	uint32_t status;

    /* WRITE ENABLE */
	write_command_qspi_flash((gp_qspi_cmd_tbl -> write_enable) << DRCMR_SMCMR_CMD_SHIFT);

    parameter_sector_erase_4kb_qspi_flash(addr);

	while(1)
	{
		read_status_qspi_flash(&status);
		if( check_Erase_Fail(status) )
		{
			ERROR("Erase Error!!\n");
			break;
		}
		read_wip_status_register(&status);
		if( !(status & BIT0) )
		{
			break;
		}
	}
}
/* End of function parameter_sector_erase_4kb_qspi_flash_s25s512s */

/* Qspi:Page Program (4PP:12h) */
void page_program_with_buf_qspi_flash_s25s512s(uint32_t addr, uint32_t source_addr)
{
	uint32_t status;

    /* WRITE ENABLE */
	write_command_qspi_flash((gp_qspi_cmd_tbl -> write_enable) << DRCMR_SMCMR_CMD_SHIFT);

    write_data_4pp_with_buf_qspi_flash(addr,source_addr);	/* 4PP */

	/* Add */
	while(1)
	{
		read_wip_status_register(&status);
		if( !(status & BIT0) )
		{
			break;
		}
	}

}
/* End of function page_program_with_buf_qspi_flash_s25s512s */

/* Qspi:Clear Block Protection of SR1V */
void clear_bp_qspi_flash(void)
{
	uint32_t statusReg;
    while(1)
	{
		read_wip_status_register(&statusReg);
        if( !(statusReg & BIT0) )
    	{
    		break;
    	}
    }
}
/* End of function clear_bp_qspi_flash */

void save_data_with_buf_qspi_flash(uint32_t srcAdd,uint32_t svFlashAdd,uint32_t svSize)
{
	uint32_t flashAdd;
	uint32_t writeDataAdd;

    /* WRITE ENABLE */
	write_command_qspi_flash((gp_qspi_cmd_tbl -> write_enable) << DRCMR_SMCMR_CMD_SHIFT);

	writeDataAdd = srcAdd;

	for(flashAdd=svFlashAdd; flashAdd<(svFlashAdd+svSize); flashAdd += RPC_WRITE_BUF_SIZE)
	{	/* 256byte:RPC Write Buffer size */
		page_program_with_buf_qspi_flash_s25s512s(flashAdd, writeDataAdd);
		writeDataAdd = writeDataAdd + RPC_WRITE_BUF_SIZE;
	}
}
/* End of function save_data_with_buf_qspi_flash */

void sector_erase_qspi_flash(uint32_t EraseStatAdd,uint32_t EraseEndAdd)
{
	uint32_t	sectorAd;
	uint32_t	SectorStatTopAdd;
	uint32_t	SectorEndTopAdd;

	SectorStatTopAdd = EraseStatAdd & FLASH_SECTOR_MASK;
	SectorEndTopAdd  = EraseEndAdd  & FLASH_SECTOR_MASK;

	for(sectorAd = SectorStatTopAdd; sectorAd <= SectorEndTopAdd; sectorAd += FLASH_SECTOR_SIZE)
	{
		sector_erase_NNNkb_qspi_flash_s25s512s(sectorAd);
	}
}
/* End of function sector_erase_qspi_flash_s25s512s */

void parameter_sector_erase_qspi_flash(uint32_t EraseStatAdd,uint32_t EraseEndAdd)
{
	uint32_t	sectorAd;
	uint32_t	SectorStatTopAdd;
	uint32_t	SectorEndTopAdd;

	SectorStatTopAdd = EraseStatAdd & QSPI_PARAM_SEC_MASK;
	SectorEndTopAdd  = EraseEndAdd  & QSPI_PARAM_SEC_MASK;

	for(sectorAd = SectorStatTopAdd; sectorAd <= SectorEndTopAdd; sectorAd += QSPI_PARAM_SEC_SIZE)
	{
		parameter_sector_erase_4kb_qspi_flash_s25s512s(sectorAd);
	}
}
/* End of function parameter_sector_erase_qspi_flash */
