blob: c39332b30ac8976ca78559ee6c102a7bebb8ba95 [file] [log] [blame]
/*
* (C) Copyright 2006
* Mindspeed Technologies
*
* 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 <common.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/bsp.h>
#include <asm/byteorder.h>
#if !defined(CONFIG_UART0) && !defined(CONFIG_UART1)
#error must define one of CONFIG_UART0 or CONFIG_UART1
#endif
typedef struct tagUART16550REGS {
volatile u32 data; // Receive/Transmit data register
volatile u32 ier; // Interrupt Enable register
volatile u32 iir_fcr;// Interrupt Identity register / FIFO Control register
volatile u32 lcr; // Line Control register
volatile u32 mcr; // Modem Control register
volatile u32 lsr; // Line Status register
volatile u32 msr; // Modem Status register
volatile u32 sr; // Scratch register
} UART16550REGS, *PUART16550REGS;
typedef struct tagUART16550DLREGS {
volatile u32 dll; // Divisor Latch (Low)
volatile u32 dlh; // Divisor Latch (High)
} UART16550DLREGS, *PUART16550DLREGS;
#define LCR_CHAR_LEN_5 0x00 /* default */
#define LCR_CHAR_LEN_6 0x01
#define LCR_CHAR_LEN_7 0x02
#define LCR_CHAR_LEN_8 0x03
#define LCR_ONE_STOP 0x00 /* One stop bit! - default */
#define LCR_TWO_STOP 0x04 /* Two stop bit! */
#define LCR_PEN 0x08 /* Parity Enable */
#define LCR_PARITY_NONE 0x00
#define LCR_EPS 0x10 /* Even Parity Select */
#define LCR_PS 0x20 /* Enable Parity Stuff */
#define LCR_SBRK 0x40 /* Start Break */
#define LCR_PSB 0x80 /* Parity Stuff Bit */
#define LCR_DLAB 0x80 /* UART 16550 Divisor Latch Assess */
#define LSR_FIFOE (1 << 7) /* FIFO Error Status */
#define LSR_TEMT (1 << 6) /* Transmitter Empty */
#define LSR_TDRQ (1 << 5) /* Transmit Data Request */
#define LSR_BI (1 << 4) /* Break Interrupt */
#define LSR_FE (1 << 3) /* Framing Error */
#define LSR_PE (1 << 2) /* Parity Error */
#define LSR_OE (1 << 1) /* Overrun Error */
#define LSR_DR (1 << 0) /* Data Ready */
#define IER_DMAE (1 << 7) /* DMA Requests Enable */
#define IER_UUE (1 << 6) /* UART Unit Enable */
#define IER_NRZE (1 << 5) /* NRZ coding Enable */
#define IER_RTIOE (1 << 4) /* Receiver Time Out Interrupt Enable */
#define IER_MIE (1 << 3) /* Modem Interrupt Enable */
#define IER_RLSE (1 << 2) /* Receiver Line Status Interrupt Enable */
#define IER_TIE (1 << 1) /* Transmit Data request Interrupt Enable */
#define IER_RAVIE (1 << 0) /* Receiver Data Available Interrupt Enable */
#define IIR_FIFOES1 (1 << 7) /* FIFO Mode Enable Status */
#define IIR_FIFOES0 (1 << 6) /* FIFO Mode Enable Status */
#define IIR_TOD (1 << 3) /* Time Out Detected */
#define IIR_IID2 (1 << 2) /* Interrupt Source Encoded */
#define IIR_IID1 (1 << 1) /* Interrupt Source Encoded */
#define IIR_IP (1 << 0) /* Interrupt Pending (active low) */
/* UART 16550 FIFO Control Register */
#define FCR_FIFOEN 0x01
#define FCR_RCVRRES 0x02
#define FCR_XMITRES 0x04
/* Interrupt Enable Register */
// UART 16550
#define IER_RXTH 0x01 // Enable Received Data Available Interrupt
#define IER_TXTH 0x02 // Enable Transmitter Empty Interrupt
#ifdef CONFIG_UART0
#if defined(CONFIG_COMCERTO_100)
static void EnableUART0(void)
{
u32 temp;
do {
temp = *(volatile u32 *)GPIO_IOCTRL_REG | __cpu_to_le32(GPIO_IOCTRL_UART0); // enable UART0
*(volatile u32 *)GPIO_LOCK_REG = __cpu_to_le32(0x55555555); // remove lock
*(volatile u32 *)GPIO_IOCTRL_REG = temp; // write to ctrl reg
} while (*(volatile u32 *)GPIO_IOCTRL_REG != temp);
}
#endif
#else
#if defined(CONFIG_COMCERTO_100)
static void EnableUART1(void)
{
u32 temp;
do {
temp = *(volatile u32 *)GPIO_IOCTRL_REG | __cpu_to_le32(GPIO_IOCTRL_UART1); // enable UART1
*(volatile u32 *)GPIO_LOCK_REG = __cpu_to_le32(0x55555555); // remove lock
*(volatile u32 *)GPIO_IOCTRL_REG = temp; // write to ctrl reg
} while (*(volatile u32 *)GPIO_IOCTRL_REG != temp);
}
#else
static void EnableUART1(void)
{
*(volatile u32 *)GPIO_PIN_SELECT_REG |= __cpu_to_le32(GPIO_PIN_SELECT_UART1); // enable UART1
}
#endif
#endif
void serial_setbrg (void)
{
int baudrate = CONFIG_BAUDRATE;
unsigned int reg = 0;
unsigned int clk = HAL_get_amba_clk();
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
PUART16550DLREGS uart_dl = (PUART16550DLREGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
PUART16550DLREGS uart_dl = (PUART16550DLREGS) UART1_BASEADDR;
#endif
//if ((baudrate = gd->baudrate) <= 0)
// baudrate = CONFIG_BAUDRATE;
reg = clk / (baudrate * 16);
uart->lcr |= __cpu_to_le32(LCR_DLAB); // Enable Divisor Latch access
uart_dl->dll = __cpu_to_le32(reg & 0xFF); // Set Divisor Latch Low
uart_dl->dlh = __cpu_to_le32((reg >> 8) & 0xFF); // Set Divisor Latch high
uart->lcr &= __cpu_to_le32(~LCR_DLAB); // Disable Divisor Latch access
}
int serial_init (void)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
#ifdef CONFIG_UART1
EnableUART1();
#elif defined(CONFIG_COMCERTO_100)
EnableUART0();
#endif
serial_setbrg ();
uart->lcr = __cpu_to_le32(LCR_ONE_STOP | LCR_CHAR_LEN_8);
uart->iir_fcr = __cpu_to_le32(FCR_XMITRES | FCR_RCVRRES | FCR_FIFOEN); // Reset, FIFO
uart->ier = __cpu_to_le32(IER_UUE); /* Enable FFUART */
return (0);
}
void serial_putc (const char c)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
/* wait for room in the tx FIFO on FFUART */
while ((uart->lsr & __cpu_to_le32(LSR_TEMT))==0) ;
uart->data = __cpu_to_le32(c);
if (c == '\n')
serial_putc ('\r');
}
void serial_puts (const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
int serial_getc (void)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
while ((uart->lsr & __cpu_to_le32(LSR_DR)) == 0);
return (char)__le32_to_cpu(uart->data & __cpu_to_le32(0xff));
}
int serial_tstc (void)
{
#ifdef CONFIG_UART0
PUART16550REGS uart = (PUART16550REGS) UART0_BASEADDR;
#else
PUART16550REGS uart = (PUART16550REGS) UART1_BASEADDR;
#endif
return __le32_to_cpu(uart->lsr & __cpu_to_le32(LSR_DR));
}