/*
 *  for MB9BF618T on FRK-FM3
 * 
 *   Copyright (C) by Y.Ishioka.
 */
#include <basic.h>
#include <tk/tkernel.h>
#include <libstr.h>
#include <drivers/uart.h>

#include <tk/sysdef.h>


#define  CORE_CLOCK   144000000
#define  PERI2_CLOCK  (CORE_CLOCK/4)

UW uart_port_base[2] = {
    UART_S3_BASE,
    UART_S4_BASE
};


/*
 * UART Send
 *   port==0 : port3
 *   port==1 : port4
 */
void  uart_send( int port, unsigned char data )
{
    /* check busy */
    while( (in_b(uart_port_base[port]+UART_SSR)&UART_SSR_TDRE) == 0 ) ;

    out_b( uart_port_base[port]+UART_TDR, data ) ;
}


/*
 *  UART Receive
 *   port==0 : port3
 *   port==1 : port4
 */
int  uart_recv( int port )
{
    unsigned char  data ;

    if( (in_b((UW)(uart_port_base[port]+UART_SSR))&UART_SSR_RDRF) == 0 ) { /* Rx empty */
        return( -1 ) ;
    }

    /* input data */
    data = in_b( (UW)(uart_port_base[port]+UART_RDR) ) ;

    return( (int)data ) ;
}


void  uart_putstring( int port, unsigned char *buf )
{
    int  size = strlen( (const char *)buf ) ;
    int  loop ;

    for( loop=0 ; loop<size ; loop++ ) {
        uart_send( port, *buf++ ) ;
    }
}


/*
 *
 */
static void  uart_init_sub( UW base, UW baud )
{
    UW  size32 ;

    out_b( (UW)(base+UART_SMR), UART_SMR_MD_UART|UART_SMR_MD_SOE ) ;
    out_b( (UW)base+UART_SCR, 0x00 ) ;

    size32 = PERI2_CLOCK /  baud - 1 ;

    out_h( (UW)base+UART_BGR, (UH)size32 ) ;

    out_b( (UW)base+UART_SCR, (UART_SCR_TXE|UART_SCR_RXE) ) ;
}


/*
 *
 */
void  uart_chg_baud( int port, unsigned int baud )
{
    if( port < 0 || 2 < port ) {
        return ;
    }

    uart_init_sub( uart_port_base[port], (UW)baud ) ;
}


/*
 *
 */
void  uart_init( void )
{
    UW  base ;

    /* init uart ch3 */
    base = uart_port_base[0] ;
    out_w( GPIO_PFR4, in_w(GPIO_PFR4)|(1<<8) ) ;   // SIN3_2
    out_w( GPIO_EPFR07, in_w(GPIO_EPFR07)|(0x3<<22) ) ;
    out_w( GPIO_PFR4, in_w(GPIO_PFR4)|(1<<9) ) ;   // SOT3_2
    out_w( GPIO_EPFR07, in_w(GPIO_EPFR07)|(0x3<<24) ) ;
    uart_init_sub( base, UART_DEF_BAUDRATE_P0 ) ;
    out_b( base+UART_ESCR, 0x00 ) ;

    /* init uart ch4 */
    base = uart_port_base[1] ;
    out_w( GPIO_PFR0, in_w(GPIO_PFR0)|(1<<5) ) ;   // SIN4_2
    out_w( GPIO_EPFR08, in_w(GPIO_EPFR08)|(0x3<<4) ) ;
    out_w( GPIO_PFR0, in_w(GPIO_PFR0)|(1<<6) ) ;   // SOT4_2
    out_w( GPIO_EPFR08, in_w(GPIO_EPFR08)|(0x3<<6) ) ;
    out_w( GPIO_PFR0, in_w(GPIO_PFR0)|(1<<8) ) ;   // CTS4_2
    out_w( GPIO_EPFR08, in_w(GPIO_EPFR08)|(0x3<<2) ) ;

    out_b( base+UART_ESCR, in_b(base+UART_ESCR) | 0x80 ) ;
    out_b( base+UART_FCR0, 0x00 ) ;
    out_b( base+UART_FCR1, 0x00 ) ;
    out_b( base+UART_FBYTE1, 0x00 ) ;
    out_b( base+UART_FBYTE2, 0x00 ) ;
    uart_init_sub( base, UART_DEF_BAUDRATE_P1 ) ;
}

