/*  ============================================================================
 *   Copyright (c) Texas Instruments Inc 2011
 *
 *   Use of this software is controlled by the terms and conditions found in the
 *   license agreement under which this software has been supplied.
 *   ===========================================================================
 */
/** ============================================================================
EMIF16 configuration and drv
 * =============================================================================
 *  Revision History
 *  ===============
 *  2011.12 Zhan Xiang  file created
 * =============================================================================
 */

#include <stdio.h>
#include <c6x.h> 
#include "KeyStone_UART_init_drv.h"
#include "KeyStone_common.h"


#define UART_REGS 	(0x02540000)



#pragma DATA_ALIGN(UART_Rx_Buf,16);
int UART_Rx_Buf[2][8];

UART_Config    gUARTCfg;
CSL_UartRegs   * UART_Regs = (CSL_UartRegs *)UART_REGS;


void KeyStone_UART_init(UART_Config *pUARTCfg, Uint32 uartNumber)
{
	// Following register writes follow the initialization procedure in the UART User Guide	
	// Setup the UART0 baud rate | Divisor = (UART_input_clock) / (UART_baud_rate * 16)	
	// Assume 1000MHz/6 UART clock and set for 115200 baud rate	
	// MDR.OSM_SEL = 0 -> 16x over-sampling,	
	float divder;
	Uint32 uartDll, uartDlh;

	Uint32 osmFactor;

	float corePll = (float)pUARTCfg->corePllInput;
	
	CSL_UartRegs * localUartRegs = (CSL_UartRegs *)((Uint32)UART_Regs + uartNumber * 0x1000);

	if(pUARTCfg->osmSel == OverSampling_13x)
	{
		osmFactor = 13;
	}
	else 
	{
		osmFactor = 16;
	}
	
	localUartRegs->MDR = pUARTCfg->osmSel;
	
	divder = (corePll * 1000000)/(pUARTCfg->baudRate * 6 * osmFactor);

	uartDll = ((Uint32)divder) & 0xFF;

	uartDlh = (((Uint32)divder) &0xFF00)>>8;

	/* Set LCR.DLAB = 1 to modify contents of the DLL register */
	localUartRegs->LCR &= (~CSL_UART_LCR_DLAB_MASK);
	localUartRegs->LCR |= CSL_UART_LCR_DLAB_ENABLE << CSL_UART_LCR_DLAB_SHIFT;
	localUartRegs->DLH = uartDlh;
	localUartRegs->DLL = uartDll;

	if(pUARTCfg->opMode == FIFO_MODE)
	{
		localUartRegs->IIR &= (~CSL_UART_FCR_FIFOEN_MASK);
		localUartRegs->IIR |= ((CSL_UART_FCR_FIFOEN_ENABLE << CSL_UART_FCR_FIFOEN_SHIFT)& CSL_UART_FCR_FIFOEN_MASK);

		localUartRegs->IIR &= (~CSL_UART_FCR_RXFIFTL_MASK);
		localUartRegs->IIR |= ((pUARTCfg->fifoRxTriBytes << CSL_UART_FCR_RXFIFTL_SHIFT)&CSL_UART_FCR_RXFIFTL_MASK);

		localUartRegs->IIR &= (~CSL_UART_FCR_DMAMODE1_MASK);
		localUartRegs->IIR |= ((CSL_UART_FCR_DMAMODE1_ENABLE << CSL_UART_FCR_DMAMODE1_SHIFT)&CSL_UART_FCR_DMAMODE1_MASK);
	}
	else
	{
		localUartRegs->IIR &= (~CSL_UART_FCR_FIFOEN_MASK);
	}

	localUartRegs->LCR &= (~(PARITY_SET_MASK | CSL_UART_LCR_STB_MASK | CSL_UART_LCR_WLS_MASK));
	localUartRegs->LCR |= (pUARTCfg->parityMode | pUARTCfg->stopMode | pUARTCfg->dataLen);

	localUartRegs->MCR &= (~AUTO_FLOW_CTRL_MASK);
	localUartRegs->MCR |= pUARTCfg->autoFlow;

	localUartRegs->PWREMU_MGMT &= (~(CSL_UART_PWREMU_MGMT_UTRST_MASK | CSL_UART_PWREMU_MGMT_URRST_MASK | CSL_UART_PWREMU_MGMT_FREE_MASK));
	localUartRegs->PWREMU_MGMT |= (((CSL_UART_PWREMU_MGMT_UTRST_ENABLE<<CSL_UART_PWREMU_MGMT_UTRST_SHIFT)&CSL_UART_PWREMU_MGMT_UTRST_MASK)
								 |((CSL_UART_PWREMU_MGMT_URRST_ENABLE<<CSL_UART_PWREMU_MGMT_URRST_SHIFT)&CSL_UART_PWREMU_MGMT_URRST_MASK)
								 |((CSL_UART_PWREMU_MGMT_FREE_RUN<<CSL_UART_PWREMU_MGMT_FREE_SHIFT)<<CSL_UART_PWREMU_MGMT_FREE_MASK));
	
	localUartRegs->LCR &= (~CSL_UART_LCR_DLAB_MASK);
	localUartRegs->LCR |= CSL_UART_LCR_DLAB_DISABLE << CSL_UART_LCR_DLAB_SHIFT;
	
	Keystone_uartInterrupt_Cfg(localUartRegs);

}

void KeyStone_UART_calc()
{
#ifdef UART_NON_FIFO_MODE
	gUARTCfg.autoFlow = AutoFlowDisable;
	gUARTCfg.baudRate = 115200;
	gUARTCfg.corePllInput = 1000;
	gUARTCfg.dataLen = DataLen_8bit;
	gUARTCfg.loopBackEnable = 0;
	gUARTCfg.parityMode = ParityDisable;
	gUARTCfg.stopMode = One_StopBit;
	gUARTCfg.osmSel = OverSampling_16x;
	gUARTCfg.opMode = NON_FIFO_MODE;
#else
	gUARTCfg.autoFlow = AutoFlowDisable;
	gUARTCfg.baudRate = 115200;
	gUARTCfg.corePllInput = 1000;
	gUARTCfg.dataLen = DataLen_8bit;
	gUARTCfg.loopBackEnable = 0;
	gUARTCfg.parityMode = ParityDisable;
	gUARTCfg.stopMode = One_StopBit;
	gUARTCfg.osmSel = OverSampling_16x;
	gUARTCfg.opMode = FIFO_MODE;
	gUARTCfg.fifoRxTriBytes = TriggerLevel_8Byte;
#endif
	return;
}

void Keystone_uartInterrupt_Cfg(CSL_UartRegs *pUART_Regs)
{
	pUART_Regs->IER = (CSL_UART_IER_ELSI_ENABLE << CSL_UART_IER_ELSI_SHIFT) & CSL_UART_IER_ELSI_MASK;
	return;
}

int Keystone_uartWrite_Busy(Uint32 uartNumber, char c)
{
	CSL_UartRegs * localUartRegs = (CSL_UartRegs *)((Uint32)UART_Regs + uartNumber * 0x1000);
	while(!((localUartRegs->LSR) & CSL_UART_LSR_TEMT_MASK));
	localUartRegs->RBR = c;

	return 1;
}

int Keystone_uartWrite_String(Uint32 uartNumber, char *s)
{

	int i = 0;
	int status = 0;

	while(s[i]!= '\0')
	{
		status = Keystone_uartWrite_Busy(uartNumber, s[i]);
		++i;
	}

	return status;
}
