Академический Документы
Профессиональный Документы
Культура Документы
<linux/platform_device.h>
<linux/module.h>
<linux/console.h>
<linux/serial.h>
<linux/serial_core.h>
<linux/tty.h>
<linux/tty_flip.h>
<linux/delay.h>
<linux/interrupt.h>
<linux/init.h>
<linux/io.h>
<linux/of.h>
<linux/of_address.h>
<linux/of_device.h>
<linux/of_platform.h>
ULITE_NAME
ULITE_MAJOR
ULITE_MINOR
ULITE_NR_UARTS
"ttyUL"
204
187
4
ULITE_RX
ULITE_TX
ULITE_STATUS
ULITE_CONTROL
0x00
0x04
0x08
0x0c
#define ULITE_REGION
16
#define
#define
#define
#define
#define
#define
#define
#define
ULITE_STATUS_RXVALID
ULITE_STATUS_RXFULL
ULITE_STATUS_TXEMPTY
ULITE_STATUS_TXFULL
ULITE_STATUS_IE
ULITE_STATUS_OVERRUN
ULITE_STATUS_FRAME
ULITE_STATUS_PARITY
0x01
#define ULITE_CONTROL_RST_TX
#define ULITE_CONTROL_RST_RX
#define ULITE_CONTROL_IE
0x01
0x02
0x10
struct uartlite_reg_ops {
0x02
0x04
0x08
0x10
0x20
0x40
0x80
*/
timeout = jiffies + msecs_to_jiffies(1000);
while (1) {
val = uart_in32(ULITE_STATUS, port);
if ((val & ULITE_STATUS_TXFULL) == 0)
break;
if (time_after(jiffies, timeout)) {
dev_warn(port->dev,
"timeout waiting for TX buffer empty\n");
break;
}
cpu_relax();
}
}
static void ulite_console_putchar(struct uart_port *port, int ch)
{
ulite_console_wait_tx(port);
uart_out32(ch, ULITE_TX, port);
}
static void ulite_console_write(struct console *co, const char *s,
unsigned int count)
{
struct uart_port *port = &ulite_ports[co->index];
unsigned long flags;
unsigned int ier;
int locked = 1;
if (oops_in_progress) {
locked = spin_trylock_irqsave(&port->lock, flags);
} else
spin_lock_irqsave(&port->lock, flags);
/* save and disable interrupt */
ier = uart_in32(ULITE_STATUS, port) & ULITE_STATUS_IE;
uart_out32(0, ULITE_CONTROL, port);
uart_console_write(port, s, count, ulite_console_putchar);
ulite_console_wait_tx(port);
/* restore interrupt state */
if (ier)
uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port);
if (locked)
spin_unlock_irqrestore(&port->lock, flags);
}
static int ulite_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';
if (co->index < 0 || co->index >= ULITE_NR_UARTS)
return -EINVAL;
port = &ulite_ports[co->index];
/* Has the device been initialized yet? */
if (!port->mapbase) {
pr_debug("console on ttyUL%i not present\n", co->index);
return -ENODEV;
}
/* not initialized yet? */
if (!port->membase) {
if (ulite_request_port(port))
return -ENODEV;
}
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(port, co, baud, parity, bits, flow);
}
static struct uart_driver ulite_uart_driver;
static struct console ulite_console = {
.name = ULITE_NAME,
.write = ulite_console_write,
.device = uart_console_device,
.setup = ulite_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */
.data = &ulite_uart_driver,
};
static int __init ulite_console_init(void)
{
register_console(&ulite_console);
return 0;
}
console_initcall(ulite_console_init);
#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
static struct uart_driver ulite_uart_driver = {
.owner
= THIS_MODULE,
.driver_name
= "uartlite",
.dev_name
= ULITE_NAME,
.major
= ULITE_MAJOR,
.minor
= ULITE_MINOR,
.nr
= ULITE_NR_UARTS,
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
.cons
= &ulite_console,
#endif
};
/* --------------------------------------------------------------------* Port assignment functions (mapping devices to uart_port structures)
*/
/** ulite_assign: register a uartlite device with the driver
*
* @dev: pointer to device structure
* @id: requested id number. Pass -1 for automatic port assignment
* @base: base address of uartlite registers
* @irq: irq number for uartlite
*
* Returns: 0 on success, <0 otherwise
*/
static int ulite_assign(struct device *dev, int id, u32 base, int irq)
{
struct uart_port *port;
int rc;
/* if id = -1; then scan for a free id and use that */
if (id < 0) {
for (id = 0; id < ULITE_NR_UARTS; id++)
if (ulite_ports[id].mapbase == 0)
break;
}
if (id < 0 || id >= ULITE_NR_UARTS) {
dev_err(dev, "%s%i too large\n", ULITE_NAME, id);
return -EINVAL;
}
if ((ulite_ports[id].mapbase) && (ulite_ports[id].mapbase != base)) {
dev_err(dev, "cannot assign to %s%i; it is already in use\n",
ULITE_NAME, id);
return -EBUSY;
}
port = &ulite_ports[id];
spin_lock_init(&port->lock);
port->fifosize = 16;
port->regshift = 2;
port->iotype = UPIO_MEM;
port->iobase = 1; /* mark port in use */
port->mapbase = base;
port->membase = NULL;
port->ops = &ulite_ops;
port->irq = irq;
port->flags = UPF_BOOT_AUTOCONF;
port->dev = dev;
port->type = PORT_UNKNOWN;
port->line = id;
dev_set_drvdata(dev, port);
/* Register the port */
rc = uart_add_one_port(&ulite_uart_driver, port);
if (rc) {
dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
port->mapbase = 0;
dev_set_drvdata(dev, NULL);
return rc;
}
return 0;
}