#include <linux/console.h>
#include <linux/serial_core.h>
#include <asm/io.h>
#define USB_UART_PORTS 2 /* The cell phone has 2
USB_UART ports */
/* Each USB_UART has a 3-byte register set consisting of
UU_STATUS_REGISTER at offset 0, UU_READ_DATA_REGISTER at
offset 1, and UU_WRITE_DATA_REGISTER at offset 2, as shown
in Table One of Chapter 6, "Serial Drivers" */
#define USB_UART1_BASE 0xe8000000 /* Memory base for USB_UART1 */
#define USB_UART2_BASE 0xe9000000 /* Memory base for USB_UART1 */
#define USB_UART_REGISTER_SPACE 0x3
/* Semantics of bits in the status register */
#define USB_UART_TX_FULL 0x20
#define USB_UART_RX_EMPTY 0x10
#define USB_UART_STATUS 0x0F
#define USB_UART1_IRQ 3
#define USB_UART2_IRQ 4
#define USB_UART_CLK_FREQ 16000000
#define USB_UART_FIFO_SIZE 32
/* Parameters of each supported USB_UART port */
static struct uart_port usb_uart_port[] = {
{
.mapbase = (unsigned int)USB_UART1_BASE,
.iotype = UPIO_MEM, /* Memory mapped */
.irq = USB_UART1_IRQ, /* IRQ */
.uartclk = USB_UART_CLK_FREQ, /* Clock HZ */
.fifosize = USB_UART_FIFO_SIZE, /* Size of the FIFO */
.flags = UPF_BOOT_AUTOCONF, /* UART port flag */
.line = 0, /* UART Line number */
},
{
.mapbase = (unsigned int)USB_UART2_BASE,
.iotype = UPIO_MEM, /* Memory mapped */
.irq = USB_UART2_IRQ, /* IRQ */
.uartclk = USB_UART_CLK_FREQ, /* CLock HZ */
.fifosize = USB_UART_FIFO_SIZE, /* Size of the FIFO */
.flags = UPF_BOOT_AUTOCONF, /* UART port flag */
.line = 1, /* UART Line number */
}
};
/* Write a character to the USB_UART port */
static void
usb_uart_putc(struct uart_port *port, unsigned char c)
{
/* Wait until there is space in the TX FIFO of the USB_UART.
Sense this by looking at the USB_UART_TX_FULL
bit in the status register */
while (__raw_readb(port->membase) & USB_UART_TX_FULL);
/* Write the character to the data port*/
__raw_writeb(c, (port->membase+1));
}
/* Console write */
static void
usb_uart_console_write(struct console *co, const char *s,
u_int count)
{
int i;
/* Write each character */
for (i = 0; i < count; i++, s++) {
usb_uart_putc(&usb_uart_port[co->index], *s);
}
}
/* Get communication parameters */
static void __init
usb_uart_console_get_options(struct uart_port *port,
int *baud, int *parity, int *bits)
{
/* Read the current settings (possibly set by a bootloader)
or return default values for parity, number of data bits,
and baud rate */
*parity = 'n';
*bits = 8;
*baud = 115200;
}
/* Setup console communication parameters */
static int __init
usb_uart_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud, bits, parity, flow;
/* Validate port number and get a handle to the
appropriate structure */
if (co->index == -1 || co->index >= USB_UART_PORTS) {
co->index = 0;
}
port = &usb_uart_port[co->index];
/* Use functions offered by the serial layer to parse options */
if (options) {
uart_parse_options(options, &baud, &parity, &bits, &flow);
} else {
usb_uart_console_get_options(port, &baud, &parity, &bits);
}
return uart_set_options(port, co, baud, parity, bits, flow);
}
/* Populate the console structure */
static struct console usb_uart_console = {
.name = "ttyUU", /* Console name */
.write = usb_uart_console_write, /* How to printk to the
console */
.device = uart_console_device, /* Provided by the serial core */
.setup = usb_uart_console_setup, /* How to setup the console */
.flags = CON_PRINTBUFFER, /* Default flag */
.index = -1, /* Init to invalid value */
};
/* Console Initialization */
static int __init
usb_uart_console_init(void)
{
/* ... */
/* Register this console */
register_console(&usb_uart_console);
return 0;
}
console_initcall(usb_uart_console_init); /* Mark console init */
syntax highlighted by Code2HTML, v. 0.9.1