/**
 * \file   plat_uart.c
 *
 * \brief  
 *
 * 
*/

/*
 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */
#include "plat_uart.h"
#include "hw_cm_per.h"
#include "plat_utils.h"		

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */
#define BAUD_RATE_115200          (115200)
#define UART_MODULE_INPUT_CLK     (48000000)
/* ========================================================================== */
/*                         Structures and Enums                               */
/* ========================================================================== */

/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */ 

/**
 * \brief   A wrapper function performing Interrupt configurations.
 *
 * \param   
 *
 *
 * \return  
 *
 **/ 
static void UARTInterruptEnable(unsigned int instanceNum);
/**
 * \brief   A wrapper function performing FIFO configurations.
 *
 * \param   
 *
 *
 * \return  
 *
 **/ 
static void UARTFIFOConfigure(unsigned int instanceNum);
/**
 * \brief   A wrapper function performing Baud Rate settings.
 *
 * \param   
 *
 *
 * \return  
 *
 **/ 
static void UARTBaudRateSet(unsigned int instanceNum);
/**
 * \brief   
 *
 * \param   
 *
 *
 * \return  
 *
 **/ 
void UARTPinmux(unsigned int instanceNum);
/**
 * \brief   
 *
 * \param   
 *
 *
 * \return  
 *
 **/ 
void UARTPowerup(unsigned int instanceNum); 
/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */
extern unsigned char am335x_board_type;
/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */
void UARTInit(unsigned int instanceNum)
{
	unsigned int baseAddr = 0;
	switch(instanceNum)
	{
	case 3:
		baseAddr = SOC_UART_3_REGS;
		break;
	case 5:
		baseAddr = SOC_UART_5_REGS;
		break;
	default:
		return;
	}

	/* Clock enable */
	UARTPowerup(instanceNum);

	/* Pinumx */
	UARTPinmux(instanceNum);

    /* Performing a module reset. */
    UARTModuleReset(baseAddr);

    /* Performing FIFO configurations. */
    UARTFIFOConfigure(instanceNum);

    /* Switching to Configuration Mode B. */
    UARTRegConfigModeEnable(baseAddr, UART_REG_CONFIG_MODE_B);

    UARTSetParams(instanceNum);

    /* Disabling write access to Divisor Latches. */
    UARTDivisorLatchDisable(baseAddr);

    /* Disabling Break Control. */
    UARTBreakCtl(baseAddr, UART_BREAK_COND_DISABLE);

    /* Switching to UART16x operating mode. */
    UARTOperatingModeSelect(baseAddr, UART16x_OPER_MODE);

    /* Performing Interrupt configurations. */
    UARTInterruptEnable(instanceNum);
}

void UARTSetParams(unsigned int instanceNum)
{
	unsigned int baseAddress = 0;
	switch(instanceNum)
	{
	case 3:
		baseAddress = SOC_UART_3_REGS;
		break;
	case 5:
		baseAddress = SOC_UART_5_REGS;
		break;		
	default:
		return;
	}
    /* Performing Baud Rate settings. */
    UARTBaudRateSet(baseAddress);

    /* Programming the Line Characteristics. */
    UARTLineCharacConfig(baseAddress,
                         (UART_FRAME_WORD_LENGTH_8 | UART_FRAME_NUM_STB_1),
                         UART_PARITY_NONE);

}

void UARTPowerup(unsigned int instanceNum)
{
	switch(instanceNum)
	{
	case 3:
		HWREG( SOC_PRCM_REGS + CM_PER_UART3_CLKCTRL )  |= CM_PER_UART3_CLKCTRL_MODULEMODE_ENABLE; 	    // UART3  
		break;
	case 5:		
		HWREG( SOC_PRCM_REGS + CM_PER_UART5_CLKCTRL )  |= CM_PER_UART5_CLKCTRL_MODULEMODE_ENABLE; 		// UART5  
	default:
		break;
	}
}



void UARTPinmux(unsigned int instanceNum)
{

	switch(instanceNum)
	{
	case 3:
    if( AM335X_BOARD_TYPE_IDK == am335x_board_type)
    {
		//uart3_rxd_mux1
		HWREG(SOC_CONTROL_REGS + CONTROL_CONF_SPI0_CS1) = 1 | CONTROL_CONF_SPI0_CS0_CONF_SPI0_CS0_PUDEN |
															CONTROL_CONF_SPI0_CS0_CONF_SPI0_CS0_RXACTIVE;
		//uart3_txd_mux1
		HWREG(SOC_CONTROL_REGS + CONTROL_CONF_ECAP0_IN_PWM0_OUT) = 1;
    }        
    else if( AM335X_BOARD_TYPE_ICE_V2 == am335x_board_type)
    {
    	//uart3_rxd_mux
	   HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MII1_RXD3) =
	        			(0x01  |
	        			CONTROL_CONF_MII1_RXD3_CONF_MII1_RXD3_PUDEN |
	        			CONTROL_CONF_MII1_RXD3_CONF_MII1_RXD3_RXACTIVE);
	   //uart3_txd_mux
	   HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MII1_RXD2) = 1;
    }
	break;
	case 5:
        //AM335X_BOARD_TYPE_ICE == am335x_board_type
		//uart5_txd_mux
		HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(8)) = 4 ;
		//uart5_rxd_mux
		HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(9)) = 4 | CONTROL_CONF_LCD_DATA9_CONF_LCD_DATA9_PUDEN |
															  CONTROL_CONF_LCD_DATA9_CONF_LCD_DATA9_RXACTIVE;
	default:
		break;
	}

}






/* -------------------------------------------------------------------------- */
/*                 Internal Function Definitions                              */
/* -------------------------------------------------------------------------- */

static void UARTFIFOConfigure(unsigned int instanceNum)
{
    unsigned int fifoConfig = 0;

    /* Setting the TX and RX FIFO Trigger levels as 1. No DMA enabled. */
    fifoConfig = UART_FIFO_CONFIG(UART_TRIG_LVL_GRANULARITY_1,
                                  UART_TRIG_LVL_GRANULARITY_1,
                                  1,
                                  1,
                                  1,
                                  1,
                                  UART_DMA_EN_PATH_SCR,
                                  UART_DMA_MODE_0_ENABLE);

    switch(instanceNum)
    {
    case 3:
        /* Configuring the FIFO settings. */
        UARTFIFOConfig(SOC_UART_3_REGS, fifoConfig);
        break;
    case 5:
        /* Configuring the FIFO settings. */
        UARTFIFOConfig(SOC_UART_5_REGS, fifoConfig);
        break;		
    default:
    	break;
    }
}



static void UARTBaudRateSet(unsigned int baseAddress)
{
    unsigned int divisorValue = 0;

    /* Computing the Divisor Value. */
    divisorValue = UARTDivisorValCompute(UART_MODULE_INPUT_CLK,
                                         BAUD_RATE_115200,
                                         UART16x_OPER_MODE,
                                         UART_MIR_OVERSAMPLING_RATE_42);
    /* Programming the Divisor Latches. */
    UARTDivisorLatchWrite(baseAddress, divisorValue);
}


static void UARTInterruptEnable(unsigned int instanceNum)
{
    switch(instanceNum)
    {
    case 3:
        /* Enabling the specified UART interrupts. */
        UARTIntEnable(SOC_UART_3_REGS, (UART_INT_LINE_STAT | UART_INT_THR |
                                        UART_INT_RHR_CTI));
        break;
    case 5:
        /* Enabling the specified UART interrupts. */
        UARTIntEnable(SOC_UART_5_REGS, (UART_INT_LINE_STAT | UART_INT_THR |
                                        UART_INT_RHR_CTI));
        break;		
    default:
    	break;
    }
}


