/*
 * linux/arch/arm/mach-davinci/serial_davinci.c
 *
 * TI DaVinci serial driver hookup file
 *
 * Copyright (C) 2004 Texas Instruments.
 *
 * ----------------------------------------------------------------------------
 *
 * 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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * ----------------------------------------------------------------------------
 Modifications:
 ver. 1.0: Oct 2005, Swaminathan S
 -
 *
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/serial_core.h>
#include <linux/serial.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/serial.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>

static struct uart_port davinci_serialport = {
	.membase    = (unsigned char __iomem *)IO_ADDRESS(DAVINCI_UART0_BASE),
	.irq        = IRQ_UARTINT0,
	.uartclk    = 27000000,
	.iotype     = UPIO_MEM,
	.regshift   = 2,
    .type       = PORT_DAVINCI,
	.fifosize   = 16,
    .flags      = 0,
    .line       = 0,
};

/*
 * Just setup the initial console rest is taken care by the
 * Linux 8250 serial driver
 */
void davinci_serial_init(void)
{
    printk("[davinci_serial_init]\n");
#ifdef CONFIG_SERIAL_8250
	early_serial_setup(&davinci_serialport);
#endif
}


/*-------------------------------------------------------------------------------------*\
\*-------------------------------------------------------------------------------------*/
#include <asm/arch/hw_uart.h>
#define UART_CLOCK 27000000

void sio_init (unsigned int baudrate) {
	int baud_divisor;
    struct _sio_ *const SIO = (struct _sio_ *)(IO_ADDRESS(DAVINCI_UART0_BASE));

    __REG(0x1c40004) |= 1;

	baud_divisor = ((UART_CLOCK / MODE_X_DIV + (baudrate>>1)) / baudrate);
	baud_divisor = (((UART_CLOCK >> 4) + (baudrate>>1)) / baudrate);

    /*--- SIO->PWREMU_MGMT = 0xE003; ---*/              /*--- bring UART out of reset ---*/

	SIO->IE = 0x00;
	SIO->LC = LCR_BKSE | LCR_WLS_8;         /*--- 8n1 mode ---*/
	SIO->DLL = baud_divisor & 0xff;
	SIO->DLH = (baud_divisor >> 8) & 0xff;
	SIO->LC = LCR_WLS_8;                    /*--- 8n1 mode ---*/
	SIO->MC = 0;                            
	SIO->IIR = FCR_FIFO_EN | FCR_RXCLR | FCR_TXCLR | DMA_MODE;
}

/*-------------------------------------------------------------------------------------*\
\*-------------------------------------------------------------------------------------*/
void sio_putc(const char c) {

    struct _sio_ *const SIO = (struct _sio_ *)(IO_ADDRESS(DAVINCI_UART0_BASE));

	while ((SIO->LS & LSR_THRE) == 0);
	if (c == '\n')
        SIO->DAT = '\r';
	while ((SIO->LS & LSR_THRE) == 0);
    SIO->DAT = c;
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
#include <stdarg.h>
#include <linux/kernel.h>

void prom_printf(char *fmt, ...) {

	va_list args;
	char ppbuf[1024];
	char *bptr;

	va_start(args, fmt);
	vsprintf(ppbuf, fmt, args);

	bptr = ppbuf;

	while (*bptr != 0) {
		if (*bptr == '\n')
			sio_putc('\r');

		sio_putc(*bptr++);
	}
	va_end(args);
}

