/*

 * Copyright (c) 2021, 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 "scifdrv3.h"

#include "bit.h"

#include "reg_rcargen3.h"

#include "mem_io.h"



/* Pin function setting value */

#define	POC_TX				((uint32_t)1U << 3U)        /* TX3 */

#define	POC_RX				((uint32_t)1U << 2U)        /* RX3 */

#define	GPSR_TX				((uint32_t)1U << 3U)        /* TX3 */

#define	GPSR_RX				((uint32_t)1U << 2U)        /* RX3 */

#define POC_TX_33V          ((uint32_t)1U << 3U)        /* TX3 3.3V setting value */

#define POC_RX_33V          ((uint32_t)1U << 2U)        /* RX3 3.3V setting value */

#define POC_TX_18V          ((uint32_t)0U << 3U)        /* TX3 1.8V setting value */

#define POC_RX_18V          ((uint32_t)0U << 2U)        /* RX3 1.8V setting value */

#define	IPSR_RX_VAL			((uint32_t)1U << 8U)        /* RX3 */

#define	IPSR_TX_VAL			((uint32_t)1U << 12U)       /* TX3 */

#define	IPSR_RX_MASK		((uint32_t)0xFU << 8U)      /* IPSR bit[11:8] */

#define	IPSR_TX_MASK		((uint32_t)0xFU << 12U)     /* IPSR bit[15:12] */

#define	PFC_POC_SCIF_MASK	(uint32_t)(0x0000000CU)     /* SCIF3 RX/TX */

#define PFC_POC_SCIF_18V    (uint32_t)(POC_TX_18V | POC_RX_18V)     /* SCIF3 RX/TX */

#define PFC_POC_SCIF_33V    (uint32_t)(POC_TX_33V | POC_RX_33V)     /* SCIF3 RX/TX */

#define	PFC_GPSR_SCIF_MASK	(uint32_t)(0x0000000CU)     /* SCIF3 RX/TX */

#define	PFC_GPSR_SCIF_VAL	(uint32_t)(GPSR_TX | GPSR_RX)    /* SCIF3 RX/TX */

#define	PFC_IPSR_SCIF_MASK	(uint32_t)(IPSR_RX_MASK | IPSR_TX_MASK) /* Mask value of IPSR (SCIF3 RX/TX) */

#define	PFC_IPSR_SCIF_VAL	(uint32_t)(IPSR_RX_VAL | IPSR_TX_VAL)   /* SCIF3 RX/TX */



/********************************************************************************/

/*										*/

/*	Debug Seirial(SCIF3)							*/

/*										*/

/********************************************************************************/

int32_t PutCharSCIF3(char outChar)

{

	while(!(0x60U & *((volatile uint16_t*)SCIF3_SCFSR) ));

	*((volatile uint8_t*)SCIF3_SCFTDR) = outChar;

	*((volatile uint16_t*)SCIF3_SCFSR) &= ~0x60U;	/* TEND,TDFE clear */

	return(0);

}



int32_t GetCharSCIF3(char *inChar)

{

	do{

		if(0x91U & *((volatile uint16_t *)SCIF3_SCFSR))

			*((volatile uint16_t *)SCIF3_SCFSR) &= ~0x91U;

		if(0x01U & *((volatile uint16_t *)SCIF3_SCLSR))

		{

			PutStr("ORER",1U);

			*((volatile uint16_t *)SCIF3_SCLSR) &= ~0x01U;

		}

	}while( !(0x02U & *((volatile uint16_t *)SCIF3_SCFSR)) );

		*inChar = *((volatile char*)SCIF3_SCFRDR);

		*((volatile uint16_t*)SCIF3_SCFSR) &= ~0x02U;

	return(0);

}



void PowerOnSCIF3(void)

{

	uint32_t dataL;



	dataL = *((volatile uint32_t*)CPG_MSTPSR7);

	if(dataL & BIT4){

		dataL &= ~BIT4;

		*((volatile uint32_t*)CPG_CPGWPR)    = ~dataL;

		*((volatile uint32_t*)CPG_MSTPCR7)  =  dataL;

	}

}



void WaitPutScif3SendEnd(void)

{

	uint16_t dataW;

	uint32_t loop;



	loop=1U;

	while(loop){

		dataW = *((volatile uint16_t*)SCIF3_SCFSR);

		if(dataW & BIT6) {

			loop = 0U;

		}

	}

}



static void InitScif3PinFunction(void)

{

	uint32_t dataL;



	/* Set Voltage setting to 3.3V */

	dataL = mem_read32(PFC_POC0);

	dataL &= ~(PFC_POC_SCIF_MASK);

	dataL |= PFC_POC_SCIF_33V;

	pfc_reg_write(PFC_POC0, dataL);



	/* Set RX / TX of SCIF3 */

	dataL = mem_read32(PFC_IP0SR0);

	dataL &= ~(PFC_IPSR_SCIF_MASK);

	dataL |= PFC_IPSR_SCIF_VAL;

	pfc_reg_write(PFC_IP0SR0, dataL);



	dataL = mem_read32(PFC_GPSR0);

	dataL &= ~(PFC_GPSR_SCIF_MASK);

	dataL |= PFC_GPSR_SCIF_VAL;

	pfc_reg_write(PFC_GPSR0, dataL);

}



void InitScif3_SCIFCLK(void)

{

	PowerOnSCIF3();



	InitScif3PinFunction();



	(void)(*((volatile uint16_t*)SCIF3_SCLSR));	/* dummy read */

	*((volatile uint16_t*)SCIF3_SCLSR) = 0x0000U;	/* clear ORER bit */

	*((volatile uint16_t*)SCIF3_SCFSR) = 0x0000U;	/* clear all error bit */



	*((volatile uint16_t*)SCIF3_SCSCR) = 0x0000U;	/* clear SCR.TE & SCR.RE*/

	*((volatile uint16_t*)SCIF3_SCFCR) = 0x0006U;	/* reset tx-fifo, reset rx-fifo. */

	*((volatile uint16_t*)SCIF3_SCFSR) = 0x0000U;	/* clear ER, TEND, TDFE, BRK, RDF, DR */



	*((volatile uint16_t*)SCIF3_SCSCR) = 0x0002U;	/* external clock, SC_CLK pin used for input pin */

	*((volatile uint16_t*)SCIF3_SCSMR) = 0x0000U;	/* 8bit data, no-parity, 1 stop, S3D4/1 */

	SoftDelay(100U);

	*((volatile uint16_t*)SCIF3_DL)    = 0x0091U;	/* 266.66MHz / (115200*16) = 144.67 */

	*((volatile uint16_t*)SCIF3_CKS)   = 0x4000U;	/* select S3D1-Clock */

	SoftDelay(100U);

	*((volatile uint16_t*)SCIF3_SCFCR) = 0x0000U;	/* reset-off tx-fifo, rx-fifo. */

	*((volatile uint16_t*)SCIF3_SCSCR) = 0x0032U;	/* enable TE, RE; SCK SC_CLK=input */



	SoftDelay(100U);

}



void SetScif3_DL(uint16_t setData)

{

	*((volatile uint16_t*)SCIF3_DL) = setData;

}



uint32_t SCIF3_TerminalInputCheck(char* str)

{

	char result = 0;

	

	if(0x91U & *((volatile uint16_t *)SCIF3_SCFSR))

		*((volatile uint16_t *)SCIF3_SCFSR) &= ~0x91U;

	if(0x01U & *((volatile uint16_t *)SCIF3_SCLSR))

	{

		PutStr("ORER",1U);

		*((volatile uint16_t *)SCIF3_SCLSR) &= ~0x01U;

	}

	if(0x02 & *((volatile uint16_t *)SCIF3_SCFSR))

	{

		*str = *((volatile unsigned char*)SCIF3_SCFRDR);

		*((volatile uint16_t*)SCIF3_SCFSR) &= ~0x02U;

		result = 1U;

	}

	return result;

}



void pfc_reg_write(uintptr_t addr, uint32_t data)

{

    mem_write32(PFC_PMMR(addr), ~data);

    mem_write32(addr, data);

}



