/*******************************************************************************
 * 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   : SCIF driver
 ******************************************************************************/
/******************************************************************************
 * @file          scif.c
 * - Version      : 0.01
 * @brief         1. Initial setting of SCIF.
 *                2. Log output function.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 03.07.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>
#include <cpg.h>
#include <cpg_register.h>
#include <pfc.h>
#include <pfc_register.h>
#include <scif_register.h>
#include <rcar_def.h>
#include <scif.h>
#include <mem_io.h>
#include <micro_wait.h>


/* Define  */
#define SCIF_SCSCR_TE_EN        (uint16_t)((uint16_t)1U << 5U)
#define SCIF_SCSCR_RE_EN        (uint16_t)((uint16_t)1U << 4U)
#define SCIF_SCSCR_CKE_MASK     (uint16_t)((uint16_t)3U << 0U)
#define SCIF_SCSCR_INIT_DATA    (uint16_t)(SCIF_SCSCR_TE_EN | SCIF_SCSCR_RE_EN)
#define SCIF_SCSCR_HW_INIT      (uint16_t)(0x0000U)

#define SCIF_SCFCR_TFRST_EN     (uint16_t)((uint16_t)1U << 2U)
#define SCIF_SCFCR_RFRS_EN      (uint16_t)((uint16_t)1U << 1U)
#define SCIF_SCFCR_RESET_FIFO   (uint16_t)(SCIF_SCFCR_TFRST_EN | SCIF_SCFCR_RFRS_EN)
#define SCIF_SCFCR_INIT_DATA    (uint16_t)(0x0000U)

#define SCIF_SCFSR_TEND         (uint16_t)((uint16_t)1U << 6U)
#define SCIF_SCFSR_TDFE         (uint16_t)((uint16_t)1U << 5U)
#define TRANS_END_CHECK         (uint16_t)(SCIF_SCFSR_TEND | SCIF_SCFSR_TDFE)
#define SCIF_SCFSR_INIT_DATA    (uint16_t)(0x0000U)

#define SCIF_SCLSR_INIT_DATA    (uint16_t)(0x0000U)

#define SCIF_SCSMR_INIT_DATA    (uint16_t)(0x0000U)

#define SCIF_SCBRR_115200BPS    (uint8_t)(0x11U)
#define SCIF_SCBRR_INIT_DATA    (SCIF_SCBRR_115200BPS)
#define SCIF_SCBRR_HW_INIT      (uint8_t)(0xFFU)

#define CPG_MSTPSR2_SCIF0               (((uint32_t)1U) << 7U)
#define CPG_MSTPSR2_SCIF0_ENABLE        (((uint32_t)0U) << 7U)

#define GPSR4_SDA2          ((uint32_t)1U << 5U)
#define GPSR4_SCL2          ((uint32_t)1U << 4U)
#define IPSR_24             ((uint32_t)4U << 24U)
#define IPSR_20             ((uint32_t)4U << 20U)
#define PFC_GPSR_SCIF_MASK  (uint32_t)(0x00000030U)         /* SCIF0/HSCIF0_B RX/TX */
#define PFC_GPSR_SCIF_VAL   (uint32_t)(GPSR4_SDA2 | GPSR4_SCL2) /* SCIF0/HSCIF0_B RX/TX */
#define PFC_IPSR_SCIF_MASK  (uint32_t)(0x0FF00000U)         /* SCIF0 RX/TX */
#define PFC_IPSR_SCIF_VAL   (uint32_t)(IPSR_24 | IPSR_20)       /* SCIF0 RX/TX */

static void scif0_module_start(void);
static void scif0_pfc_init(void);
static void scif0_console_init(void);

static void scif0_module_start(void)
{
    uint32_t reg;

    reg = mem_read32(CPG_MSTPSR2);
    /* If supply of clock to SCIF0 is stopped */
    if ((CPG_MSTPSR2_SCIF0 & reg) != CPG_MSTPSR2_SCIF0_ENABLE) {
        /* Supply of clock to SCIF0 is start */
        mem_write32((uintptr_t)CPG_CPGWPR, CPG_MSTPSR2_SCIF0);  /* write protect */
        cpg_reg_write(CPG_SCMSTPCR2, CPG_MSTPSR2, ~(CPG_MSTPSR2_SCIF0));
    }
}
/* End of function scif0_module_start(void) */

static void scif0_pfc_init(void)
{
    uint32_t reg;

    /* Set RX / TX of SCIF 0. */
    reg = mem_read32(PFC_IPSR7);
    reg &= (~(PFC_IPSR_SCIF_MASK));
    reg |= PFC_IPSR_SCIF_VAL;
    pfc_reg_write(PFC_IPSR7, reg);

    reg = mem_read32(PFC_GPSR4);
    reg &= (~(PFC_GPSR_SCIF_MASK));
    reg |= PFC_GPSR_SCIF_VAL;
    pfc_reg_write(PFC_GPSR4, reg);
}
/* End of function scif0_pfc_init(void) */

static void scif0_console_init(void)
{
    volatile uint16_t reg;

    /* clear SCR.TE & SCR.RE*/
    mem_write16(SCIF_SCSCR, SCIF_SCSCR_HW_INIT);
    /* reset tx-fifo, reset rx-fifo. */
    mem_write16(SCIF_SCFCR, SCIF_SCFCR_RESET_FIFO);

    /* clear ORER bit */
    mem_write16(SCIF_SCLSR, SCIF_SCLSR_INIT_DATA);
    /* clear all error bit  */
    mem_write16(SCIF_SCFSR, SCIF_SCFSR_INIT_DATA);

    /* internal clock, SC_CLK pin unused for output pin */
    mem_write16(SCIF_SCSCR, SCIF_SCSCR_HW_INIT);
    /* 8bit data, no-parity, 1 stop, Po/1 */
    mem_write16(SCIF_SCSMR, SCIF_SCSMR_INIT_DATA);
    /* Pclk(66MHz)/1, 115.2kBps*/
    /* N = 66/(66/2*115200)*10^4-1 =17=> 0x11 */
    mem_write16(SCIF_SCBRR, SCIF_SCBRR_115200BPS);

    micro_wait(10U); /* 10us */

    /* reset-off tx-fifo, rx-fifo. */
    mem_write16(SCIF_SCFCR, SCIF_SCFCR_INIT_DATA);
    /* enable TE, RE; SC_CLK=no output */
    mem_write16(SCIF_SCSCR, SCIF_SCSCR_INIT_DATA);
}
/* End of function scif0_console_init(void) */

void scif_init(void)
{
    scif0_module_start();
    scif0_pfc_init();
    scif0_console_init();
}
/* End of function scif_init(void) */

void scif_release(void)
{
    /* set HW initial value */
    mem_write16(SCIF_SCFCR, SCIF_SCFCR_INIT_DATA);
    mem_write16(SCIF_SCBRR, SCIF_SCBRR_HW_INIT);
    mem_write16(SCIF_SCSCR, SCIF_SCSCR_HW_INIT);
}
/* End of function scif_release(void) */

void console_putc(uint8_t outchar)
{
    uint16_t reg;

    /* Check that transfer of SCIF0 is completed */
    while (!((TRANS_END_CHECK & mem_read16(SCIF_SCFSR)) == TRANS_END_CHECK))
    {
        ;
    }

    mem_write8(SCIF_SCFTDR, outchar);       /* Transfer one character */
    reg = mem_read16(SCIF_SCFSR);
    reg &= (uint16_t)(~(TRANS_END_CHECK)); /* TEND,TDFE clear */
    mem_write16(SCIF_SCFSR, reg);
}
/* End of function console_putc(uint8_t outchar) */
