/*
 * Copyright (c) 2015-2021, Renesas Electronics Corporation
 * All rights reserved.
 */

/******************************************************************************
 * @file          rpc_driver.c
 * - Version      : 0.01
 * @brief         RPC driver.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 29.05.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>
#include <string.h>
#include <mmio.h>
#include "cpg_register.h"
#include "cpg_init.h"
#include "rpc_register.h"
#include "rpc_driver.h"
#include "debug.h"

#define RPC_PHYCNT_CAL          ((uint32_t)1U << 31U)
#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_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_DREAR_EAC_EXT_ADDR_25BIT    ((uint32_t)0x1U << 0U)
#define RPC_PHYCNT_STRTIM       ((uint32_t)0x7U << 15U)

static void enable_rpc(void);
static void setup_rpc(void);

static void enable_rpc(void)
{
    while((mmio_read_32(CPG_MSTPSR9) & 0x00020000U) != 0U)
    {
        cpg_write(CPG_SMSTPCR9,
            mmio_read_32(CPG_SMSTPCR9) & (~0x00020000U));
    }
}
/* End of function enable_rpc */

static void setup_rpc(void)
{
    uint32_t reg;

    /* manual mode */
    if ((mmio_read_32(RPC_CMNCR) & 0x80000000U) != 0U)
    {
        /* external address space read mode */
        mmio_write_32(RPC_CMNCR,
            mmio_read_32(RPC_CMNCR) & (~0x80000000U));
    }

    while((mmio_read_32(RPC_CMNSR) & 0x1U) != 1U)
    {
        /* check the transfer end flag */
    }

    /* PHY calibration */
    reg = mmio_read_32(RPC_PHYCNT);
    reg |=  RPC_PHYCNT_STRTIM;
    mmio_write_32(RPC_PHYCNT, reg);
    reg |=  RPC_PHYCNT_CAL;
    mmio_write_32(RPC_PHYCNT, reg);

    /* CMNCR is not set */
    /* SSLDR is not set */

    /* Read cache Flash */
    reg = mmio_read_32(RPC_DRCR);
    mmio_write_32(RPC_DRCR, (reg | RPC_DRCR_RCF));

    /* Read 32bit addr command */
    mmio_write_32(RPC_DRCMR, RPC_DRCMR_READ_32BIT_ADDR);

        /* Extended external address valid range is [25:0]*/
    mmio_write_32(RPC_DREAR, RPC_DREAR_EAC_EXT_ADDR_25BIT);

        /* DROPR is not set */

    /* output command is 32bit addr */
    mmio_write_32(RPC_DRENR, (RPC_DRENR_CDE_ENABLE
                | RPC_DRENR_ADE_32BIT_ADDR));
    /* DRDMCR is not set */
    /* DRDRENR is not set */
}
/* End of function setup_rpc */

void init_rpc(void)
{
    enable_rpc();
    setup_rpc();
}
/* End of function init_rpc */

