blob: 2a31d143d430bcf5983a3949f559547ecf45dfd8 [file] [log] [blame]
/*
* (C) Copyright 2010 Quantenna Communications Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include "ruby.h"
/*****************************************************************************/
/* Ruby UART is compatible with NS16550, but provide extra functionality. */
/* Let's have our own implementation, not uboot's generic NS16550. */
/*****************************************************************************/
static int initialized = 0;
inline static int serial_tx_ready(void)
{
return (readb(RUBY_UART0_LSR) & RUBY_LSR_TX_Empty);
}
inline static int serial_rx_ready(void)
{
return (readb(RUBY_UART0_LSR) & RUBY_LSR_RX_Ready);
}
inline static void serial_wait_tx(void)
{
while (!serial_tx_ready());
}
inline static void serial_wait_rx(void)
{
while (!serial_rx_ready());
}
inline static void serial_putc_simple(const char c)
{
serial_wait_tx();
writeb(c, RUBY_UART0_RBR_THR_DLL);
}
void serial_putc(const char c)
{
if (initialized) {
if (c == '\n') {
serial_putc_simple('\r');
}
serial_putc_simple(c);
}
}
int serial_getc(void)
{
int ret = 'X';
if (initialized) {
serial_wait_rx();
ret = readb(RUBY_UART0_RBR_THR_DLL);
}
return ret;
}
int serial_tstc(void)
{
return initialized ? serial_rx_ready() : 0;
}
void serial_puts(const char *s)
{
while (*s) {
serial_putc(*s++);
}
}
int serial_tx_done(void)
{
return initialized ? (readb(RUBY_UART0_LSR) & RUBY_LSR_TX_Empty) : 1;
}
void serial_setbrg(void)
{
DECLARE_GLOBAL_DATA_PTR;
u32 baud_val = (gd->baudrate * 16);
u32 div_val = (gd->bus_clk + baud_val / 2) / baud_val;
u8 lcr_val =
RUBY_LCR_Data_Word_Length_8 |
RUBY_LCR_Stop_Bit_1 |
RUBY_LCR_No_Parity |
RUBY_LCR_Break_Disable;
if (!(readb(RUBY_UART0_USR) & RUBY_USR_Busy)) {
writeb(lcr_val | RUBY_LCR_DLAB, RUBY_UART0_LCR);
writeb((div_val & 0xff), RUBY_UART0_RBR_THR_DLL);
writeb((div_val >> 8) & 0xff, RUBY_UART0_DLH_IER);
writeb(lcr_val, RUBY_UART0_LCR);
}
}
int serial_init(void)
{
return 0;
}
void board_serial_init(void)
{
/* configure GPIOs */
gpio_config(RUBY_GPIO_UART0_SO, RUBY_GPIO_ALT_OUTPUT);
gpio_config(RUBY_GPIO_UART0_SI, RUBY_GPIO_ALT_INPUT);
/* configure baud-rate */
serial_setbrg();
/* done */
initialized = 1;
}