/*
 * Copyright (c) 2020, Renesas Electronics Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Renesas nor the names of its contributors may be
 *     used to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) 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.
 */

#include "common.h"
#include "hscifdrv0.h"
#include "bit.h"
#include "reg_rcargen3.h"


/********************************************************************************/
/*										*/
/*	Debug Seirial(HSCIF0)							*/
/*										*/
/********************************************************************************/
int32_t PutCharHSCIF0(char outChar)
{
	while(!(0x60U & *((volatile uint16_t*)HSCIF0_HSFSR) ));
	*((volatile uint8_t*)HSCIF0_HSFTDR) = outChar;
	*((volatile uint16_t*)HSCIF0_HSFSR) &= ~0x60U;	/* TEND,TDFE clear */
	return(0);
}

int32_t GetCharHSCIF0(char *inChar)
{
	do{
		if(0x91 & *((volatile uint16_t *)HSCIF0_HSFSR))
			*((volatile uint16_t *)HSCIF0_HSFSR) &= ~0x91;
		if(0x01 & *((volatile uint16_t *)HSCIF0_HSLSR))
		{
			PutStr("ORER",1);
			*((volatile uint16_t *)HSCIF0_HSLSR) &= ~0x01;
		}
	}while( !(0x02 & *((volatile uint16_t *)HSCIF0_HSFSR)) );
		*inChar = *((volatile unsigned char*)HSCIF0_HSFRDR);
		*((volatile uint16_t*)HSCIF0_HSFSR) &= ~0x02;
	return(0);
}

void PowerOnHscif0(void)
{
	uint32_t dataL;
#ifdef RCAR_GEN3_CONDOR
	dataL = *((volatile uint32_t*)CPG_MSTPSR5);
	if(dataL & BIT20){	/* case HSCIF0 */
		dataL &= ~BIT20;
		*((volatile uint32_t*)CPG_CPGWPR)    = ~dataL;
		*((volatile uint32_t*)CPG_SMSTPCR5)  =  dataL;
		while( BIT20 & *((volatile uint32_t*)CPG_MSTPSR5) );  /* wait bit=0 */
	}
#endif /* RCAR_GEN3_CONDOR */
#ifdef RCAR_GEN3_FALCON
	dataL = *((volatile uint32_t*)CPG_MSTPSR5);
	if(dataL & BIT14){	/* case HSCIF0 */
		dataL &= ~BIT14;
		*((volatile uint32_t*)CPG_CPGWPR)   = ~dataL;
		*((volatile uint32_t*)CPG_MSTPCR5)  =  dataL;
		while( BIT14 & *((volatile uint32_t*)CPG_MSTPSR5) );  /* wait bit=0 */
	}
#endif /* RCAR_GEN3_FALCON */
}

void WaitPutHscif0SendEnd(void)
{
	uint16_t dataW;
	uint32_t loop;

	loop=1U;
	while(loop){
		dataW = *((volatile uint16_t*)HSCIF0_HSFSR);
		if(dataW & BIT6) {
			loop = 0U;
		}
	}
}

void InitHscif0PinFunction(void)
{
	uint32_t dataL;
#ifdef RCAR_GEN3_CONDOR
	/* HSCIF0 */
	dataL = *((volatile uint32_t*)PFC_IPSR7);
	dataL &= ~(0x0FF00000U);
	dataL |= 0x05500000U;				/* IPSR7[27:24]=4'b0101, IPSR7[23:20]=4'b0101 */
	*((volatile uint32_t*)PFC_PMMR) = ~dataL;
	*((volatile uint32_t*)PFC_IPSR7) = dataL;

	dataL = *((volatile uint32_t*)PFC_GPSR4);
	dataL |= 0x00000030U;				/* GPSR4[5],GPSR4[4] */
	*((volatile uint32_t*)PFC_PMMR) = ~dataL;
	*((volatile uint32_t*)PFC_GPSR4) = dataL;
#endif /* RCAR_GEN3_CONDOR */
#ifdef RCAR_GEN3_FALCON
	/* HSCIF0 */
	dataL = *((volatile uint32_t*)PFC_IP0SR1);
	dataL &= ~(0x00F000F0U);
	dataL |= 0x00000000U;				/* IP0SR1[23:20]=4'b0000(HTX0), IP0SR1[4:7]=4'b0000(HRX0) */
	dataL &= 0x0;					/* bit0:SCIF_CLK=0 */
	*((volatile uint32_t*)PFC_PMMR1) = ~dataL;
	*((volatile uint32_t*)PFC_IP0SR1) = dataL;

	dataL = *((volatile uint32_t*)PFC_GPSR1);	/* SDA2/SCL2 is not found in V3U TS */
	dataL |= 0x00000022U;				/* GPSR4[5],GPSR4[4] */
	*((volatile uint32_t*)PFC_PMMR1) = ~dataL;
	*((volatile uint32_t*)PFC_GPSR1) = dataL;
	
#endif /* RCAR_GEN3_FALCON */
}

void InitHscif0_SCIFCLK(void)
{
	uint16_t dataW;
#if RCAR_GEN3_FALCON
	uint32_t modemr0;
	uint32_t modemr1;
#endif /* RCAR_GEN3_FALCON */

	PowerOnHscif0();

	InitHscif0PinFunction();

	dataW = *((volatile uint16_t*)HSCIF0_HSLSR);	/* dummy read */
	*((volatile uint16_t*)HSCIF0_HSLSR) = 0x0000U;	/* clear ORER bit */
	*((volatile uint16_t*)HSCIF0_HSFSR) = 0x0000U;	/* clear all error bit */
	*((volatile uint16_t*)HSCIF0_HSSCR) = 0x0000U;	/* clear SCR.TE & SCR.RE*/
	*((volatile uint16_t*)HSCIF0_HSFCR) = 0x0006U;	/* reset tx-fifo, reset rx-fifo. */
	*((volatile uint16_t*)HSCIF0_HSFSR) = 0x0000U;	/* clear ER, TEND, TDFE, BRK, RDF, DR */
	*((volatile uint16_t*)HSCIF0_HSSCR) = 0x0000U;	/* internal clock, SCK pin is not used */
	*((volatile uint16_t*)HSCIF0_HSSMR) = 0x0000U;	/* 8bit data, no-parity, 1 stop, Po/1 */

#if defined(RCAR_GEN3_CONDOR)
	*((volatile uint16_t*)HSCIF0_HSSRR) = 0x8007U;	/* SRE=1,SRCYC[4:0]=S(8)-1=7 */
	SoftDelay(100U);
	*((volatile uint8_t*)HSCIF0_HSBRR)  = 0x11U;	/* 921600bps@266.6MHz */

#elif defined(RCAR_GEN3_FALCON)
	modemr0 = *((volatile uint32_t*)RST_MODEMR0) & MODEMR0_MD31_V3U;	/* bit31 */
	modemr1 = *((volatile uint32_t*)RST_MODEMR1) & MODEMR1_MD32_V3U;	/* bit0  */

	switch(modemr0 | modemr1){
		case MODEMR_SCIF_921600_V3U:
			*((volatile uint16_t*)HSCIF0_HSSRR) = 0x8007U;	/* SRE=1,SRCYC[4:0]=S(8)-1=7 */
			SoftDelay(100U);
			*((volatile uint8_t*)HSCIF0_HSBRR)  = 0x11U;	/* 921600bps@266.6MHz */
			break;
		case MODEMR_SCIF_1843200_V3U:
			*((volatile uint16_t*)HSCIF0_HSSRR) = 0x8007U;	/* SRE=1,SRCYC[4:0]=S(8)-1=7 */
			SoftDelay(100U);
			*((volatile uint8_t*)HSCIF0_HSBRR)  = 0x08U;	/* 1843200bps@266.6MHz */
			break;
		case MODEMR_SCIF_3000000_V3U:
			*((volatile uint16_t*)HSCIF0_HSSRR) = 0x8007;	/* 3000000bps with SCIF_CLK */
			*((volatile uint16_t*)HSCIF0_HSSCR) = 0x0002;	/* external clock, SC_CLK pin used for input pin */
			*((volatile uint16_t*)HSCIF0_DL)    = 0x0001;	/* Frequency Division is 1 */
			*((volatile uint16_t*)HSCIF0_CKS)   = 0x0000;	/* select scif_clk */
			break;
		default:
			break;
	}

#endif /* defined(RCAR_GEN3_CONDOR) */

	SoftDelay(100U);
	*((volatile uint16_t*)HSCIF0_HSFCR) = 0x0000U;	/* reset-off tx-fifo, rx-fifo. */
	*((volatile uint16_t*)HSCIF0_HSSCR) = 0x0030U;	/* enable TE, RE; SCK pin is not used */
	SoftDelay(100U);
}


uint32_t HSCIF0_TerminalInputCheck(char* str)
{
	char result = 0;
	
	if(0x91 & *((volatile uint16_t *)HSCIF0_HSFSR))
		*((volatile uint16_t *)HSCIF0_HSFSR) &= ~0x91;
	if(0x01 & *((volatile uint16_t *)HSCIF0_HSLSR))
	{
		PutStr("ORER",1);
		*((volatile uint16_t *)HSCIF0_HSLSR) &= ~0x01;
	}
	if(0x02 & *((volatile uint16_t *)HSCIF0_HSFSR))
	{
		*str = *((volatile unsigned char*)HSCIF0_HSFRDR);
		*((volatile uint16_t*)HSCIF0_HSFSR) &= ~0x02;
		result = 1;
	}
	return result;
}
