/*******************************************************************************
 * Copyright (c) 2018-2021 Renesas Electronics Corporation. All rights reserved.
 *
 *     RENESAS ELECTRONICS CONFIDENTIAL AND PROPRIETARY
 *
 * This software is provided as reference/sample code under the license
 * agreement between Renesas Electronics Corporation and licensee (the
 * "License Agreement") and shall be treated as specified in the License
 * Agreement.
 * These instructions, statements, and software are the confidential
 * information of Renesas Electronics Corporation. They must be used and
 * modified solely for the purpose for which it was furnished by Renesas
 * Electronics Corporation. All or part of these instructions, statements and
 * software must not be reproduced nor disclosed to any third party in any
 * form, unless permitted by the License Agreement.
 *
 * THIS SOFTWARE IS PROVIDED BY RENESAS ELEOCTRONICS CORPORATION "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 * SATISFACTORY QUALITY, ACCURACY, TITLE AND NON-INFRINGEMENT ARE DISCLAIMED.
 * IN NO EVENT SHALL RENESAS ELECTRONICS CORPORATION BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 ******************************************************************************/

/*******************************************************************************
 * DESCRIPTION   : RPC driver
 ******************************************************************************/
/******************************************************************************
 * @file          rpc.c
 * - Version      : 0.01
 * @brief         Initial setting process of RPC.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>
#include <cpg_register.h>
#include <rpc_register.h>
#include <rpc.h>
#include <mem_io.h>

#define RPC_PHYCNT_CAL                  ((uint32_t)1U << 31U)
#define RPC_PHYCNT_STRTIM               ((uint32_t)0x7U << 15U)
#define RPC_DRCR_RCF                    ((uint32_t)1U << 9U)
#define RPC_DRCMR_CMD_MASK              (0x00FF0000U)
#define RPC_DRCMR_READ_32BIT_ADDR       ((uint32_t)0x13U << 16U)
#define RPC_DRCMR_HW_INIT               (0x00030000U)
#define RPC_DREAR_EAC_EXT_ADDR_25BIT    ((uint32_t)0x1U << 0U)
#define RPC_DREAR_HW_INIT               (0x00000000U)
#define RPC_DRENR_CDE_ENABLE            ((uint32_t)0x1U << 14U)
#define RPC_DRENR_ADE_MASK              (0x00000F00U)
#define RPC_DRENR_ADE_32BIT_ADDR        ((uint32_t)0xFU << 8U)
#define RPC_DRENR_HW_INIT               (0x00004700U)
#define CMNSR_TEND                      (0x00000001U)

void rpc_init(void)
{
    uint32_t reg;

    /* check the transfer end flag */
    rpc_end_state_check();

    /* For the initial setting flow of RPC, see Figure 62.12 in     */
    /* "R-Car Series, 3rd Generation User's Manual".                */
    /* This RPC setting is for S25FS512S device                     */
    /* A register that does not set a value expects                 */
    /* the initial value of HW.                                     */

    /* PHY calibration */
    reg = mem_read32(RPC_PHYCNT);
    reg |= RPC_PHYCNT_STRTIM;
    mem_write32(RPC_PHYCNT, reg);
    reg |= RPC_PHYCNT_CAL;
    mem_write32(RPC_PHYCNT, reg);
    /* Read cache Flash */
    reg = mem_read32(RPC_DRCR);
    mem_write32(RPC_DRCR, (reg | RPC_DRCR_RCF));
    /* 32bit address read command*/
    mem_write32(RPC_DRCMR, RPC_DRCMR_READ_32BIT_ADDR);
    /* Extended external address valid range is [25:0]*/
    mem_write32(RPC_DREAR, RPC_DREAR_EAC_EXT_ADDR_25BIT);
    /* output command is 32bit width */
    mem_write32(RPC_DRENR,
        ( RPC_DRENR_CDE_ENABLE | RPC_DRENR_ADE_32BIT_ADDR));
}
/* End of function rpc_init(void) */

void rpc_release(void)
{
    uint32_t reg;

    /* RPC restore to initial value of HW. */
    reg = mem_read32(RPC_DRCR);
    mem_write32(RPC_DRCR, (reg | RPC_DRCR_RCF));
    mem_write32(RPC_DRCMR, RPC_DRCMR_HW_INIT);
    mem_write32(RPC_DREAR, RPC_DREAR_HW_INIT);
    mem_write32(RPC_DRENR, RPC_DRENR_HW_INIT);
}
/* 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) */
