/*
 * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 */

#include "serial.h"
#include "io.h"
#include "secure_apb.h"

void serial_set_pin_port(unsigned port_base)
{
    setbits_le32(AO_RTI_PIN_MUX_REG,3<<11);
}

#define UART_STP_BIT UART_CNTL_MASK_STP_1BIT
#define UART_PRTY_BIT 0
#define UART_CHAR_LEN   UART_CNTL_MASK_CHAR_8BIT

void serial_init(unsigned set)
{
    /* baud rate */
    writel(set| UART_STP_BIT
	        | UART_PRTY_BIT
	        | UART_CHAR_LEN
	        //please do not remove these setting , jerry.yu
	        | UART_CNTL_MASK_TX_EN
	        | UART_CNTL_MASK_RX_EN
	        | UART_CNTL_MASK_RST_TX
	        | UART_CNTL_MASK_RST_RX
	        | UART_CNTL_MASK_CLR_ERR
	,P_UART_CONTROL(UART_PORT_CONS));
    serial_set_pin_port(UART_PORT_CONS);
    clrbits_le32(P_UART_CONTROL(UART_PORT_CONS),
	    UART_CNTL_MASK_RST_TX | UART_CNTL_MASK_RST_RX | UART_CNTL_MASK_CLR_ERR);
}

int serial_putc(int c)
{
    if (c == '\n') {
        while ((readl(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_TFIFO_FULL));
        writel('\r', P_UART_WFIFO(UART_PORT_CONS));
    }
    /* Wait till dataTx register is not full */
    while ((readl(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_TFIFO_FULL));
    writel(c, P_UART_WFIFO(UART_PORT_CONS));
    /* Wait till dataTx register is empty */
    return c;
}

int serial_getc(void)
{
   unsigned char ch;
    /* Wait till character is placed in fifo */
	while ((readl(P_UART_STATUS(UART_PORT_CONS)) & UART_STAT_MASK_RFIFO_CNT) == 0) ;

    /* Also check for overflow errors */
    if (readl(P_UART_STATUS(UART_PORT_CONS)) & (UART_STAT_MASK_PRTY_ERR | UART_STAT_MASK_FRAM_ERR))
	{
	    setbits_le32(P_UART_CONTROL(UART_PORT_CONS),UART_CNTL_MASK_CLR_ERR);
	    clrbits_le32(P_UART_CONTROL(UART_PORT_CONS),UART_CNTL_MASK_CLR_ERR);
	}

    ch = readl(P_UART_RFIFO(UART_PORT_CONS)) & 0x00ff;
    return ((int)ch);
}

int serial_puts(const char *s){
	while (*s) {
		serial_putc(*s++);
	}
	return 0;
}

//support 64bit number, serial_put_hex(data, 64);
void serial_put_hex(unsigned long data,unsigned int bitlen)
{
	int i;
	for (i=bitlen-4;i>=0;i-=4) {
        if ((data>>i) == 0)
        {
            serial_putc(0x30);
            continue;
        }
        unsigned char s = (data>>i)&0xf;
        if (s<10)
            serial_putc(0x30+s);
        else
            serial_putc(0x61+s-10);
    }
}

void serial_put_dec(unsigned long data)
{
	char szTxt[10];
	szTxt[0] = 0x30;
	int i = 0;

	do {
		szTxt[i++] = (data % 10) + 0x30;
		data = data / 10;
	} while(data);

	for (--i;i >=0;--i)
		serial_putc(szTxt[i]);
}