Merge remote branch 'origin' into secretlab/next-spi

This commit is contained in:
Grant Likely 2010-05-25 00:38:26 -06:00
commit b1e50ebcf2
6890 changed files with 470191 additions and 215018 deletions

View file

@ -1891,8 +1891,8 @@ static int serial8250_get_poll_char(struct uart_port *port)
struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned char lsr = serial_inp(up, UART_LSR);
while (!(lsr & UART_LSR_DR))
lsr = serial_inp(up, UART_LSR);
if (!(lsr & UART_LSR_DR))
return NO_POLL_CHAR;
return serial_inp(up, UART_RX);
}

View file

@ -518,12 +518,13 @@ config SERIAL_S3C2412
Serial port support for the Samsung S3C2412 and S3C2413 SoC
config SERIAL_S3C2440
tristate "Samsung S3C2440/S3C2442 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442)
tristate "Samsung S3C2440/S3C2442/S3C2416 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442 || CPU_S3C2416)
default y if CPU_S3C2440
default y if CPU_S3C2442
select SERIAL_SAMSUNG_UARTS_4 if CPU_S3C2416
help
Serial port support for the Samsung S3C2440 and S3C2442 SoC
Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC
config SERIAL_S3C24A0
tristate "Samsung S3C24A0 Serial port support"
@ -533,21 +534,13 @@ config SERIAL_S3C24A0
Serial port support for the Samsung S3C24A0 SoC
config SERIAL_S3C6400
tristate "Samsung S3C6400/S3C6410/S5P6440 Seria port support"
depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440)
tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100)
select SERIAL_SAMSUNG_UARTS_4
default y
help
Serial port support for the Samsung S3C6400, S3C6410 and S5P6440
SoCs
config SERIAL_S5PC100
tristate "Samsung S5PC100 Serial port support"
depends on SERIAL_SAMSUNG && CPU_S5PC100
select SERIAL_SAMSUNG_UARTS_4
default y
help
Serial port support for the Samsung S5PC100 SoCs
Serial port support for the Samsung S3C6400, S3C6410, S5P6440
and S5PC100 SoCs
config SERIAL_S5PV210
tristate "Samsung S5PV210 Serial port support"
@ -1430,8 +1423,8 @@ config SERIAL_SC26XX_CONSOLE
Support for Console on SC2681/SC2692 serial ports.
config SERIAL_BFIN_SPORT
tristate "Blackfin SPORT emulate UART (EXPERIMENTAL)"
depends on BLACKFIN && EXPERIMENTAL
tristate "Blackfin SPORT emulate UART"
depends on BLACKFIN
select SERIAL_CORE
help
Enable SPORT emulate UART on Blackfin series.
@ -1446,28 +1439,52 @@ config SERIAL_BFIN_SPORT_CONSOLE
config SERIAL_BFIN_SPORT0_UART
bool "Enable UART over SPORT0"
depends on SERIAL_BFIN_SPORT && !(BF542 || BF542M || BF544 || BF544M)
depends on SERIAL_BFIN_SPORT && !(BF542 || BF544)
help
Enable UART over SPORT0
config SERIAL_BFIN_SPORT0_UART_CTSRTS
bool "Enable UART over SPORT0 hardware flow control"
depends on SERIAL_BFIN_SPORT0_UART
help
Enable hardware flow control in the driver.
config SERIAL_BFIN_SPORT1_UART
bool "Enable UART over SPORT1"
depends on SERIAL_BFIN_SPORT
help
Enable UART over SPORT1
config SERIAL_BFIN_SPORT1_UART_CTSRTS
bool "Enable UART over SPORT1 hardware flow control"
depends on SERIAL_BFIN_SPORT1_UART
help
Enable hardware flow control in the driver.
config SERIAL_BFIN_SPORT2_UART
bool "Enable UART over SPORT2"
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
help
Enable UART over SPORT2
config SERIAL_BFIN_SPORT2_UART_CTSRTS
bool "Enable UART over SPORT2 hardware flow control"
depends on SERIAL_BFIN_SPORT2_UART
help
Enable hardware flow control in the driver.
config SERIAL_BFIN_SPORT3_UART
bool "Enable UART over SPORT3"
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
help
Enable UART over SPORT3
config SERIAL_BFIN_SPORT3_UART_CTSRTS
bool "Enable UART over SPORT3 hardware flow control"
depends on SERIAL_BFIN_SPORT3_UART
help
Enable hardware flow control in the driver.
config SERIAL_TIMBERDALE
tristate "Support for timberdale UART"
select SERIAL_CORE
@ -1506,4 +1523,56 @@ config SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
help
Support for running a console on the GRLIB APBUART
config SERIAL_ALTERA_JTAGUART
tristate "Altera JTAG UART support"
select SERIAL_CORE
help
This driver supports the Altera JTAG UART port.
config SERIAL_ALTERA_JTAGUART_CONSOLE
bool "Altera JTAG UART console support"
depends on SERIAL_ALTERA_JTAGUART=y
select SERIAL_CORE_CONSOLE
help
Enable a Altera JTAG UART port to be the system console.
config SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS
bool "Bypass output when no connection"
depends on SERIAL_ALTERA_JTAGUART_CONSOLE
select SERIAL_CORE_CONSOLE
help
Bypass console output and keep going even if there is no
JTAG terminal connection with the host.
config SERIAL_ALTERA_UART
tristate "Altera UART support"
select SERIAL_CORE
help
This driver supports the Altera softcore UART port.
config SERIAL_ALTERA_UART_MAXPORTS
int "Maximum number of Altera UART ports"
depends on SERIAL_ALTERA_UART
default 4
help
This setting lets you define the maximum number of the Altera
UART ports. The usual default varies from board to board, and
this setting is a way of catering for that.
config SERIAL_ALTERA_UART_BAUDRATE
int "Default baudrate for Altera UART ports"
depends on SERIAL_ALTERA_UART
default 115200
help
This setting lets you define what the default baudrate is for the
Altera UART ports. The usual default varies from board to board,
and this setting is a way of catering for that.
config SERIAL_ALTERA_UART_CONSOLE
bool "Altera UART console support"
depends on SERIAL_ALTERA_UART=y
select SERIAL_CORE_CONSOLE
help
Enable a Altera UART port to be the system console.
endmenu

View file

@ -44,7 +44,6 @@ obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o
obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
@ -83,3 +82,5 @@ obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o

View file

@ -0,0 +1,504 @@
/*
* altera_jtaguart.c -- Altera JTAG UART driver
*
* Based on mcf.c -- Freescale ColdFire UART driver
*
* (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
* (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
* (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/altera_jtaguart.h>
#define DRV_NAME "altera_jtaguart"
/*
* Altera JTAG UART register definitions according to the Altera JTAG UART
* datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
*/
#define ALTERA_JTAGUART_SIZE 8
#define ALTERA_JTAGUART_DATA_REG 0
#define ALTERA_JTAGUART_DATA_DATA_MSK 0x000000FF
#define ALTERA_JTAGUART_DATA_RVALID_MSK 0x00008000
#define ALTERA_JTAGUART_DATA_RAVAIL_MSK 0xFFFF0000
#define ALTERA_JTAGUART_DATA_RAVAIL_OFF 16
#define ALTERA_JTAGUART_CONTROL_REG 4
#define ALTERA_JTAGUART_CONTROL_RE_MSK 0x00000001
#define ALTERA_JTAGUART_CONTROL_WE_MSK 0x00000002
#define ALTERA_JTAGUART_CONTROL_RI_MSK 0x00000100
#define ALTERA_JTAGUART_CONTROL_RI_OFF 8
#define ALTERA_JTAGUART_CONTROL_WI_MSK 0x00000200
#define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400
#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000
#define ALTERA_JTAGUART_CONTROL_WSPACE_OFF 16
/*
* Local per-uart structure.
*/
struct altera_jtaguart {
struct uart_port port;
unsigned int sigs; /* Local copy of line sigs */
unsigned long imr; /* Local IMR mirror */
};
static unsigned int altera_jtaguart_tx_empty(struct uart_port *port)
{
return (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) ? TIOCSER_TEMT : 0;
}
static unsigned int altera_jtaguart_get_mctrl(struct uart_port *port)
{
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
}
static void altera_jtaguart_set_mctrl(struct uart_port *port, unsigned int sigs)
{
}
static void altera_jtaguart_start_tx(struct uart_port *port)
{
struct altera_jtaguart *pp =
container_of(port, struct altera_jtaguart, port);
pp->imr |= ALTERA_JTAGUART_CONTROL_WE_MSK;
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
}
static void altera_jtaguart_stop_tx(struct uart_port *port)
{
struct altera_jtaguart *pp =
container_of(port, struct altera_jtaguart, port);
pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
}
static void altera_jtaguart_stop_rx(struct uart_port *port)
{
struct altera_jtaguart *pp =
container_of(port, struct altera_jtaguart, port);
pp->imr &= ~ALTERA_JTAGUART_CONTROL_RE_MSK;
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
}
static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
{
}
static void altera_jtaguart_enable_ms(struct uart_port *port)
{
}
static void altera_jtaguart_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
{
/* Just copy the old termios settings back */
if (old)
tty_termios_copy_hw(termios, old);
}
static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
{
struct uart_port *port = &pp->port;
unsigned char ch, flag;
unsigned long status;
while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) &
ALTERA_JTAGUART_DATA_RVALID_MSK) {
ch = status & ALTERA_JTAGUART_DATA_DATA_MSK;
flag = TTY_NORMAL;
port->icount.rx++;
if (uart_handle_sysrq_char(port, ch))
continue;
uart_insert_char(port, 0, 0, ch, flag);
}
tty_flip_buffer_push(port->state->port.tty);
}
static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
{
struct uart_port *port = &pp->port;
struct circ_buf *xmit = &port->state->xmit;
unsigned int pending, count;
if (port->x_char) {
/* Send special char - probably flow control */
writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG);
port->x_char = 0;
port->icount.tx++;
return;
}
pending = uart_circ_chars_pending(xmit);
if (pending > 0) {
count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) >>
ALTERA_JTAGUART_CONTROL_WSPACE_OFF;
if (count > pending)
count = pending;
if (count > 0) {
pending -= count;
while (count--) {
writel(xmit->buf[xmit->tail],
port->membase + ALTERA_JTAGUART_DATA_REG);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}
if (pending < WAKEUP_CHARS)
uart_write_wakeup(port);
}
}
if (pending == 0) {
pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
}
}
static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
{
struct uart_port *port = data;
struct altera_jtaguart *pp =
container_of(port, struct altera_jtaguart, port);
unsigned int isr;
isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >>
ALTERA_JTAGUART_CONTROL_RI_OFF) & pp->imr;
spin_lock(&port->lock);
if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK)
altera_jtaguart_rx_chars(pp);
if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK)
altera_jtaguart_tx_chars(pp);
spin_unlock(&port->lock);
return IRQ_RETVAL(isr);
}
static void altera_jtaguart_config_port(struct uart_port *port, int flags)
{
port->type = PORT_ALTERA_JTAGUART;
/* Clear mask, so no surprise interrupts. */
writel(0, port->membase + ALTERA_JTAGUART_CONTROL_REG);
}
static int altera_jtaguart_startup(struct uart_port *port)
{
struct altera_jtaguart *pp =
container_of(port, struct altera_jtaguart, port);
unsigned long flags;
int ret;
ret = request_irq(port->irq, altera_jtaguart_interrupt, IRQF_DISABLED,
DRV_NAME, port);
if (ret) {
pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
"interrupt vector=%d\n", port->line, port->irq);
return ret;
}
spin_lock_irqsave(&port->lock, flags);
/* Enable RX interrupts now */
pp->imr = ALTERA_JTAGUART_CONTROL_RE_MSK;
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
static void altera_jtaguart_shutdown(struct uart_port *port)
{
struct altera_jtaguart *pp =
container_of(port, struct altera_jtaguart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
/* Disable all interrupts now */
pp->imr = 0;
writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
free_irq(port->irq, port);
}
static const char *altera_jtaguart_type(struct uart_port *port)
{
return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL;
}
static int altera_jtaguart_request_port(struct uart_port *port)
{
/* UARTs always present */
return 0;
}
static void altera_jtaguart_release_port(struct uart_port *port)
{
/* Nothing to release... */
}
static int altera_jtaguart_verify_port(struct uart_port *port,
struct serial_struct *ser)
{
if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART)
return -EINVAL;
return 0;
}
/*
* Define the basic serial functions we support.
*/
static struct uart_ops altera_jtaguart_ops = {
.tx_empty = altera_jtaguart_tx_empty,
.get_mctrl = altera_jtaguart_get_mctrl,
.set_mctrl = altera_jtaguart_set_mctrl,
.start_tx = altera_jtaguart_start_tx,
.stop_tx = altera_jtaguart_stop_tx,
.stop_rx = altera_jtaguart_stop_rx,
.enable_ms = altera_jtaguart_enable_ms,
.break_ctl = altera_jtaguart_break_ctl,
.startup = altera_jtaguart_startup,
.shutdown = altera_jtaguart_shutdown,
.set_termios = altera_jtaguart_set_termios,
.type = altera_jtaguart_type,
.request_port = altera_jtaguart_request_port,
.release_port = altera_jtaguart_release_port,
.config_port = altera_jtaguart_config_port,
.verify_port = altera_jtaguart_verify_port,
};
#define ALTERA_JTAGUART_MAXPORTS 1
static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
int __init early_altera_jtaguart_setup(struct altera_jtaguart_platform_uart
*platp)
{
struct uart_port *port;
int i;
for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
port = &altera_jtaguart_ports[i].port;
port->line = i;
port->type = PORT_ALTERA_JTAGUART;
port->mapbase = platp[i].mapbase;
port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
port->iotype = SERIAL_IO_MEM;
port->irq = platp[i].irq;
port->flags = ASYNC_BOOT_AUTOCONF;
port->ops = &altera_jtaguart_ops;
}
return 0;
}
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
static void altera_jtaguart_console_putc(struct console *co, const char c)
{
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
unsigned long status;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
spin_unlock_irqrestore(&port->lock, flags);
return; /* no connection activity */
}
spin_unlock_irqrestore(&port->lock, flags);
cpu_relax();
spin_lock_irqsave(&port->lock, flags);
}
writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
#else
static void altera_jtaguart_console_putc(struct console *co, const char c)
{
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
spin_unlock_irqrestore(&port->lock, flags);
cpu_relax();
spin_lock_irqsave(&port->lock, flags);
}
writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
#endif
static void altera_jtaguart_console_write(struct console *co, const char *s,
unsigned int count)
{
for (; count; count--, s++) {
altera_jtaguart_console_putc(co, *s);
if (*s == '\n')
altera_jtaguart_console_putc(co, '\r');
}
}
static int __init altera_jtaguart_console_setup(struct console *co,
char *options)
{
struct uart_port *port;
if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS)
return -EINVAL;
port = &altera_jtaguart_ports[co->index].port;
if (port->membase == 0)
return -ENODEV;
return 0;
}
static struct uart_driver altera_jtaguart_driver;
static struct console altera_jtaguart_console = {
.name = "ttyJ",
.write = altera_jtaguart_console_write,
.device = uart_console_device,
.setup = altera_jtaguart_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &altera_jtaguart_driver,
};
static int __init altera_jtaguart_console_init(void)
{
register_console(&altera_jtaguart_console);
return 0;
}
console_initcall(altera_jtaguart_console_init);
#define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
#else
#define ALTERA_JTAGUART_CONSOLE NULL
#endif /* CONFIG_ALTERA_JTAGUART_CONSOLE */
static struct uart_driver altera_jtaguart_driver = {
.owner = THIS_MODULE,
.driver_name = "altera_jtaguart",
.dev_name = "ttyJ",
.major = ALTERA_JTAGUART_MAJOR,
.minor = ALTERA_JTAGUART_MINOR,
.nr = ALTERA_JTAGUART_MAXPORTS,
.cons = ALTERA_JTAGUART_CONSOLE,
};
static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
{
struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
struct uart_port *port;
int i;
for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
port = &altera_jtaguart_ports[i].port;
port->line = i;
port->type = PORT_ALTERA_JTAGUART;
port->mapbase = platp[i].mapbase;
port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
port->iotype = SERIAL_IO_MEM;
port->irq = platp[i].irq;
port->ops = &altera_jtaguart_ops;
port->flags = ASYNC_BOOT_AUTOCONF;
uart_add_one_port(&altera_jtaguart_driver, port);
}
return 0;
}
static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
{
struct uart_port *port;
int i;
for (i = 0; i < ALTERA_JTAGUART_MAXPORTS; i++) {
port = &altera_jtaguart_ports[i].port;
if (port)
uart_remove_one_port(&altera_jtaguart_driver, port);
}
return 0;
}
static struct platform_driver altera_jtaguart_platform_driver = {
.probe = altera_jtaguart_probe,
.remove = __devexit_p(altera_jtaguart_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
static int __init altera_jtaguart_init(void)
{
int rc;
rc = uart_register_driver(&altera_jtaguart_driver);
if (rc)
return rc;
rc = platform_driver_register(&altera_jtaguart_platform_driver);
if (rc) {
uart_unregister_driver(&altera_jtaguart_driver);
return rc;
}
return 0;
}
static void __exit altera_jtaguart_exit(void)
{
platform_driver_unregister(&altera_jtaguart_platform_driver);
uart_unregister_driver(&altera_jtaguart_driver);
}
module_init(altera_jtaguart_init);
module_exit(altera_jtaguart_exit);
MODULE_DESCRIPTION("Altera JTAG UART driver");
MODULE_AUTHOR("Thomas Chou <[email protected]>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);

View file

@ -0,0 +1,570 @@
/*
* altera_uart.c -- Altera UART driver
*
* Based on mcf.c -- Freescale ColdFire UART driver
*
* (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
* (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
* (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/altera_uart.h>
#define DRV_NAME "altera_uart"
/*
* Altera UART register definitions according to the Nios UART datasheet:
* http://www.altera.com/literature/ds/ds_nios_uart.pdf
*/
#define ALTERA_UART_SIZE 32
#define ALTERA_UART_RXDATA_REG 0
#define ALTERA_UART_TXDATA_REG 4
#define ALTERA_UART_STATUS_REG 8
#define ALTERA_UART_CONTROL_REG 12
#define ALTERA_UART_DIVISOR_REG 16
#define ALTERA_UART_EOP_REG 20
#define ALTERA_UART_STATUS_PE_MSK 0x0001 /* parity error */
#define ALTERA_UART_STATUS_FE_MSK 0x0002 /* framing error */
#define ALTERA_UART_STATUS_BRK_MSK 0x0004 /* break */
#define ALTERA_UART_STATUS_ROE_MSK 0x0008 /* RX overrun error */
#define ALTERA_UART_STATUS_TOE_MSK 0x0010 /* TX overrun error */
#define ALTERA_UART_STATUS_TMT_MSK 0x0020 /* TX shift register state */
#define ALTERA_UART_STATUS_TRDY_MSK 0x0040 /* TX ready */
#define ALTERA_UART_STATUS_RRDY_MSK 0x0080 /* RX ready */
#define ALTERA_UART_STATUS_E_MSK 0x0100 /* exception condition */
#define ALTERA_UART_STATUS_DCTS_MSK 0x0400 /* CTS logic-level change */
#define ALTERA_UART_STATUS_CTS_MSK 0x0800 /* CTS logic state */
#define ALTERA_UART_STATUS_EOP_MSK 0x1000 /* EOP written/read */
/* Enable interrupt on... */
#define ALTERA_UART_CONTROL_PE_MSK 0x0001 /* ...parity error */
#define ALTERA_UART_CONTROL_FE_MSK 0x0002 /* ...framing error */
#define ALTERA_UART_CONTROL_BRK_MSK 0x0004 /* ...break */
#define ALTERA_UART_CONTROL_ROE_MSK 0x0008 /* ...RX overrun */
#define ALTERA_UART_CONTROL_TOE_MSK 0x0010 /* ...TX overrun */
#define ALTERA_UART_CONTROL_TMT_MSK 0x0020 /* ...TX shift register empty */
#define ALTERA_UART_CONTROL_TRDY_MSK 0x0040 /* ...TX ready */
#define ALTERA_UART_CONTROL_RRDY_MSK 0x0080 /* ...RX ready */
#define ALTERA_UART_CONTROL_E_MSK 0x0100 /* ...exception*/
#define ALTERA_UART_CONTROL_TRBK_MSK 0x0200 /* TX break */
#define ALTERA_UART_CONTROL_DCTS_MSK 0x0400 /* Interrupt on CTS change */
#define ALTERA_UART_CONTROL_RTS_MSK 0x0800 /* RTS signal */
#define ALTERA_UART_CONTROL_EOP_MSK 0x1000 /* Interrupt on EOP */
/*
* Local per-uart structure.
*/
struct altera_uart {
struct uart_port port;
unsigned int sigs; /* Local copy of line sigs */
unsigned short imr; /* Local IMR mirror */
};
static unsigned int altera_uart_tx_empty(struct uart_port *port)
{
return (readl(port->membase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
}
static unsigned int altera_uart_get_mctrl(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
unsigned int sigs;
spin_lock_irqsave(&port->lock, flags);
sigs =
(readl(port->membase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
sigs |= (pp->sigs & TIOCM_RTS);
spin_unlock_irqrestore(&port->lock, flags);
return sigs;
}
static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->sigs = sigs;
if (sigs & TIOCM_RTS)
pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
else
pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_start_tx(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_stop_tx(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_stop_rx(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_break_ctl(struct uart_port *port, int break_state)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
if (break_state == -1)
pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
else
pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_enable_ms(struct uart_port *port)
{
}
static void altera_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
{
unsigned long flags;
unsigned int baud, baudclk;
baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
baudclk = port->uartclk / baud;
if (old)
tty_termios_copy_hw(termios, old);
tty_termios_encode_baud_rate(termios, baud, baud);
spin_lock_irqsave(&port->lock, flags);
writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_rx_chars(struct altera_uart *pp)
{
struct uart_port *port = &pp->port;
unsigned char ch, flag;
unsigned short status;
while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) &
ALTERA_UART_STATUS_RRDY_MSK) {
ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
flag = TTY_NORMAL;
port->icount.rx++;
if (status & ALTERA_UART_STATUS_E_MSK) {
writel(status, port->membase + ALTERA_UART_STATUS_REG);
if (status & ALTERA_UART_STATUS_BRK_MSK) {
port->icount.brk++;
if (uart_handle_break(port))
continue;
} else if (status & ALTERA_UART_STATUS_PE_MSK) {
port->icount.parity++;
} else if (status & ALTERA_UART_STATUS_ROE_MSK) {
port->icount.overrun++;
} else if (status & ALTERA_UART_STATUS_FE_MSK) {
port->icount.frame++;
}
status &= port->read_status_mask;
if (status & ALTERA_UART_STATUS_BRK_MSK)
flag = TTY_BREAK;
else if (status & ALTERA_UART_STATUS_PE_MSK)
flag = TTY_PARITY;
else if (status & ALTERA_UART_STATUS_FE_MSK)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(port, ch))
continue;
uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch,
flag);
}
tty_flip_buffer_push(port->state->port.tty);
}
static void altera_uart_tx_chars(struct altera_uart *pp)
{
struct uart_port *port = &pp->port;
struct circ_buf *xmit = &port->state->xmit;
if (port->x_char) {
/* Send special char - probably flow control */
writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG);
port->x_char = 0;
port->icount.tx++;
return;
}
while (readl(port->membase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK) {
if (xmit->head == xmit->tail)
break;
writel(xmit->buf[xmit->tail],
port->membase + ALTERA_UART_TXDATA_REG);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (xmit->head == xmit->tail) {
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
}
}
static irqreturn_t altera_uart_interrupt(int irq, void *data)
{
struct uart_port *port = data;
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned int isr;
isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
if (isr & ALTERA_UART_STATUS_RRDY_MSK)
altera_uart_rx_chars(pp);
if (isr & ALTERA_UART_STATUS_TRDY_MSK)
altera_uart_tx_chars(pp);
return IRQ_RETVAL(isr);
}
static void altera_uart_config_port(struct uart_port *port, int flags)
{
port->type = PORT_ALTERA_UART;
/* Clear mask, so no surprise interrupts. */
writel(0, port->membase + ALTERA_UART_CONTROL_REG);
/* Clear status register */
writel(0, port->membase + ALTERA_UART_STATUS_REG);
}
static int altera_uart_startup(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
int ret;
ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
DRV_NAME, port);
if (ret) {
pr_err(DRV_NAME ": unable to attach Altera UART %d "
"interrupt vector=%d\n", port->line, port->irq);
return ret;
}
spin_lock_irqsave(&port->lock, flags);
/* Enable RX interrupts now */
pp->imr = ALTERA_UART_CONTROL_RRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
static void altera_uart_shutdown(struct uart_port *port)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
/* Disable all interrupts now */
pp->imr = 0;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
spin_unlock_irqrestore(&port->lock, flags);
free_irq(port->irq, port);
}
static const char *altera_uart_type(struct uart_port *port)
{
return (port->type == PORT_ALTERA_UART) ? "Altera UART" : NULL;
}
static int altera_uart_request_port(struct uart_port *port)
{
/* UARTs always present */
return 0;
}
static void altera_uart_release_port(struct uart_port *port)
{
/* Nothing to release... */
}
static int altera_uart_verify_port(struct uart_port *port,
struct serial_struct *ser)
{
if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_ALTERA_UART))
return -EINVAL;
return 0;
}
/*
* Define the basic serial functions we support.
*/
static struct uart_ops altera_uart_ops = {
.tx_empty = altera_uart_tx_empty,
.get_mctrl = altera_uart_get_mctrl,
.set_mctrl = altera_uart_set_mctrl,
.start_tx = altera_uart_start_tx,
.stop_tx = altera_uart_stop_tx,
.stop_rx = altera_uart_stop_rx,
.enable_ms = altera_uart_enable_ms,
.break_ctl = altera_uart_break_ctl,
.startup = altera_uart_startup,
.shutdown = altera_uart_shutdown,
.set_termios = altera_uart_set_termios,
.type = altera_uart_type,
.request_port = altera_uart_request_port,
.release_port = altera_uart_release_port,
.config_port = altera_uart_config_port,
.verify_port = altera_uart_verify_port,
};
static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
{
struct uart_port *port;
int i;
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
port = &altera_uart_ports[i].port;
port->line = i;
port->type = PORT_ALTERA_UART;
port->mapbase = platp[i].mapbase;
port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
port->iotype = SERIAL_IO_MEM;
port->irq = platp[i].irq;
port->uartclk = platp[i].uartclk;
port->flags = ASYNC_BOOT_AUTOCONF;
port->ops = &altera_uart_ops;
}
return 0;
}
static void altera_uart_console_putc(struct console *co, const char c)
{
struct uart_port *port = &(altera_uart_ports + co->index)->port;
int i;
for (i = 0; i < 0x10000; i++) {
if (readl(port->membase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK)
break;
}
writel(c, port->membase + ALTERA_UART_TXDATA_REG);
for (i = 0; i < 0x10000; i++) {
if (readl(port->membase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK)
break;
}
}
static void altera_uart_console_write(struct console *co, const char *s,
unsigned int count)
{
for (; count; count--, s++) {
altera_uart_console_putc(co, *s);
if (*s == '\n')
altera_uart_console_putc(co, '\r');
}
}
static int __init altera_uart_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
int bits = 8;
int parity = 'n';
int flow = 'n';
if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
return -EINVAL;
port = &altera_uart_ports[co->index].port;
if (port->membase == 0)
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 altera_uart_driver;
static struct console altera_uart_console = {
.name = "ttyS",
.write = altera_uart_console_write,
.device = uart_console_device,
.setup = altera_uart_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &altera_uart_driver,
};
static int __init altera_uart_console_init(void)
{
register_console(&altera_uart_console);
return 0;
}
console_initcall(altera_uart_console_init);
#define ALTERA_UART_CONSOLE (&altera_uart_console)
#else
#define ALTERA_UART_CONSOLE NULL
#endif /* CONFIG_ALTERA_UART_CONSOLE */
/*
* Define the altera_uart UART driver structure.
*/
static struct uart_driver altera_uart_driver = {
.owner = THIS_MODULE,
.driver_name = DRV_NAME,
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
.nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
.cons = ALTERA_UART_CONSOLE,
};
static int __devinit altera_uart_probe(struct platform_device *pdev)
{
struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
struct uart_port *port;
int i;
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
port = &altera_uart_ports[i].port;
port->line = i;
port->type = PORT_ALTERA_UART;
port->mapbase = platp[i].mapbase;
port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
port->iotype = SERIAL_IO_MEM;
port->irq = platp[i].irq;
port->uartclk = platp[i].uartclk;
port->ops = &altera_uart_ops;
port->flags = ASYNC_BOOT_AUTOCONF;
uart_add_one_port(&altera_uart_driver, port);
}
return 0;
}
static int altera_uart_remove(struct platform_device *pdev)
{
struct uart_port *port;
int i;
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) {
port = &altera_uart_ports[i].port;
if (port)
uart_remove_one_port(&altera_uart_driver, port);
}
return 0;
}
static struct platform_driver altera_uart_platform_driver = {
.probe = altera_uart_probe,
.remove = __devexit_p(altera_uart_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = NULL,
},
};
static int __init altera_uart_init(void)
{
int rc;
rc = uart_register_driver(&altera_uart_driver);
if (rc)
return rc;
rc = platform_driver_register(&altera_uart_platform_driver);
if (rc) {
uart_unregister_driver(&altera_uart_driver);
return rc;
}
return 0;
}
static void __exit altera_uart_exit(void)
{
platform_driver_unregister(&altera_uart_platform_driver);
uart_unregister_driver(&altera_uart_driver);
}
module_init(altera_uart_init);
module_exit(altera_uart_exit);
MODULE_DESCRIPTION("Altera UART driver");
MODULE_AUTHOR("Thomas Chou <[email protected]>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);

View file

@ -342,9 +342,9 @@ static int pl010_get_poll_char(struct uart_port *port)
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status;
do {
status = readw(uap->port.membase + UART01x_FR);
} while (status & UART01x_FR_RXFE);
status = readw(uap->port.membase + UART01x_FR);
if (status & UART01x_FR_RXFE)
return NO_POLL_CHAR;
return readw(uap->port.membase + UART01x_DR);
}

View file

@ -559,7 +559,7 @@ static int __devinit apbuart_probe(struct of_device *op,
i = 0;
for (i = 0; i < grlib_apbuart_port_nr; i++) {
if (op->node == grlib_apbuart_nodes[i])
if (op->dev.of_node == grlib_apbuart_nodes[i])
break;
}
@ -584,12 +584,12 @@ static struct of_device_id __initdata apbuart_match[] = {
};
static struct of_platform_driver grlib_apbuart_of_driver = {
.match_table = apbuart_match,
.probe = apbuart_probe,
.driver = {
.owner = THIS_MODULE,
.name = "grlib-apbuart",
},
.owner = THIS_MODULE,
.name = "grlib-apbuart",
.of_match_table = apbuart_match,
},
};

View file

@ -38,6 +38,7 @@
#include <linux/dma-mapping.h>
#include <linux/atmel_pdc.h>
#include <linux/atmel_serial.h>
#include <linux/uaccess.h>
#include <asm/io.h>
@ -59,6 +60,9 @@
#include <linux/serial_core.h>
static void atmel_start_rx(struct uart_port *port);
static void atmel_stop_rx(struct uart_port *port);
#ifdef CONFIG_SERIAL_ATMEL_TTYAT
/* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we
@ -93,6 +97,7 @@
#define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR)
#define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR)
#define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR)
#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR)
/* PDC registers */
#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
@ -147,6 +152,9 @@ struct atmel_uart_port {
unsigned int irq_status_prev;
struct circ_buf rx_ring;
struct serial_rs485 rs485; /* rs485 settings */
unsigned int tx_done_mask;
};
static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
@ -187,6 +195,46 @@ static bool atmel_use_dma_tx(struct uart_port *port)
}
#endif
/* Enable or disable the rs485 support */
void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int mode;
spin_lock(&port->lock);
/* Disable interrupts */
UART_PUT_IDR(port, atmel_port->tx_done_mask);
mode = UART_GET_MR(port);
/* Resetting serial mode to RS232 (0x0) */
mode &= ~ATMEL_US_USMODE;
atmel_port->rs485 = *rs485conf;
if (rs485conf->flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
UART_PUT_TTGR(port, rs485conf->delay_rts_before_send);
mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");
if (atmel_use_dma_tx(port))
atmel_port->tx_done_mask = ATMEL_US_ENDTX |
ATMEL_US_TXBUFE;
else
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
}
UART_PUT_MR(port, mode);
/* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask);
spin_unlock(&port->lock);
}
/*
* Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
*/
@ -202,6 +250,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
{
unsigned int control = 0;
unsigned int mode;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
#ifdef CONFIG_ARCH_AT91RM9200
if (cpu_is_at91rm9200()) {
@ -236,6 +285,17 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
mode |= ATMEL_US_CHMODE_LOC_LOOP;
else
mode |= ATMEL_US_CHMODE_NORMAL;
/* Resetting serial mode to RS232 (0x0) */
mode &= ~ATMEL_US_USMODE;
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");
}
UART_PUT_MR(port, mode);
}
@ -268,12 +328,17 @@ static u_int atmel_get_mctrl(struct uart_port *port)
*/
static void atmel_stop_tx(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_dma_tx(port)) {
/* disable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
} else
UART_PUT_IDR(port, ATMEL_US_TXRDY);
}
/* Disable interrupts */
UART_PUT_IDR(port, atmel_port->tx_done_mask);
if (atmel_port->rs485.flags & SER_RS485_ENABLED)
atmel_start_rx(port);
}
/*
@ -281,17 +346,39 @@ static void atmel_stop_tx(struct uart_port *port)
*/
static void atmel_start_tx(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_dma_tx(port)) {
if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
/* The transmitter is already running. Yes, we
really need this.*/
return;
UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
if (atmel_port->rs485.flags & SER_RS485_ENABLED)
atmel_stop_rx(port);
/* re-enable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
} else
UART_PUT_IER(port, ATMEL_US_TXRDY);
}
/* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask);
}
/*
* start receiving - port is in process of being opened.
*/
static void atmel_start_rx(struct uart_port *port)
{
UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */
if (atmel_use_dma_rx(port)) {
/* enable PDC controller */
UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
port->read_status_mask);
UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
} else {
UART_PUT_IER(port, ATMEL_US_RXRDY);
}
}
/*
@ -302,9 +389,11 @@ static void atmel_stop_rx(struct uart_port *port)
if (atmel_use_dma_rx(port)) {
/* disable PDC receive */
UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
} else
UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
port->read_status_mask);
} else {
UART_PUT_IDR(port, ATMEL_US_RXRDY);
}
}
/*
@ -428,8 +517,9 @@ static void atmel_rx_chars(struct uart_port *port)
static void atmel_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) {
if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
UART_PUT_CHAR(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
@ -437,7 +527,7 @@ static void atmel_tx_chars(struct uart_port *port)
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return;
while (UART_GET_CSR(port) & ATMEL_US_TXRDY) {
while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
@ -449,7 +539,8 @@ static void atmel_tx_chars(struct uart_port *port)
uart_write_wakeup(port);
if (!uart_circ_empty(xmit))
UART_PUT_IER(port, ATMEL_US_TXRDY);
/* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask);
}
/*
@ -501,18 +592,10 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_dma_tx(port)) {
/* PDC transmit */
if (pending & (ATMEL_US_ENDTX | ATMEL_US_TXBUFE)) {
UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
tasklet_schedule(&atmel_port->tasklet);
}
} else {
/* Interrupt transmit */
if (pending & ATMEL_US_TXRDY) {
UART_PUT_IDR(port, ATMEL_US_TXRDY);
tasklet_schedule(&atmel_port->tasklet);
}
if (pending & atmel_port->tx_done_mask) {
/* Either PDC or interrupt transmission */
UART_PUT_IDR(port, atmel_port->tx_done_mask);
tasklet_schedule(&atmel_port->tasklet);
}
}
@ -590,9 +673,15 @@ static void atmel_tx_dma(struct uart_port *port)
UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
UART_PUT_TCR(port, count);
/* re-enable PDC transmit and interrupts */
/* re-enable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
/* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask);
} else {
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
/* DMA done, stop TX, start RX for RS485 */
atmel_start_rx(port);
}
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@ -1017,6 +1106,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
{
unsigned long flags;
unsigned int mode, imr, quot, baud;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
/* Get current mode register */
mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
@ -1115,6 +1205,17 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
/* disable receiver and transmitter */
UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
/* Resetting serial mode to RS232 (0x0) */
mode &= ~ATMEL_US_USMODE;
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");
}
/* set the parity, stop bits and data size */
UART_PUT_MR(port, mode);
@ -1231,6 +1332,35 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
}
#endif
static int
atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
{
struct serial_rs485 rs485conf;
switch (cmd) {
case TIOCSRS485:
if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
sizeof(rs485conf)))
return -EFAULT;
atmel_config_rs485(port, &rs485conf);
break;
case TIOCGRS485:
if (copy_to_user((struct serial_rs485 *) arg,
&(to_atmel_uart_port(port)->rs485),
sizeof(rs485conf)))
return -EFAULT;
break;
default:
return -ENOIOCTLCMD;
}
return 0;
}
static struct uart_ops atmel_pops = {
.tx_empty = atmel_tx_empty,
.set_mctrl = atmel_set_mctrl,
@ -1250,6 +1380,7 @@ static struct uart_ops atmel_pops = {
.config_port = atmel_config_port,
.verify_port = atmel_verify_port,
.pm = atmel_serial_pm,
.ioctl = atmel_ioctl,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = atmel_poll_get_char,
.poll_put_char = atmel_poll_put_char,
@ -1265,13 +1396,12 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
struct uart_port *port = &atmel_port->uart;
struct atmel_uart_data *data = pdev->dev.platform_data;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &atmel_pops;
port->fifosize = 1;
port->line = pdev->id;
port->dev = &pdev->dev;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &atmel_pops;
port->fifosize = 1;
port->line = pdev->id;
port->dev = &pdev->dev;
port->mapbase = pdev->resource[0].start;
port->irq = pdev->resource[1].start;
@ -1299,8 +1429,16 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
atmel_port->use_dma_rx = data->use_dma_rx;
atmel_port->use_dma_tx = data->use_dma_tx;
if (atmel_use_dma_tx(port))
atmel_port->rs485 = data->rs485;
/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
if (atmel_port->rs485.flags & SER_RS485_ENABLED)
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
else if (atmel_use_dma_tx(port)) {
port->fifosize = PDC_BUFFER_SIZE;
atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;
} else {
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
}
}
/*
@ -1334,6 +1472,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
static void atmel_console_write(struct console *co, const char *s, u_int count)
{
struct uart_port *port = &atmel_ports[co->index].uart;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status, imr;
unsigned int pdc_tx;
@ -1341,7 +1480,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
* First, save IMR and then disable interrupts
*/
imr = UART_GET_IMR(port);
UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY);
UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
/* Store PDC transmit status and disable it */
pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;

View file

@ -34,32 +34,12 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <asm/bfin_sport.h>
#include <asm/delay.h>
#include <asm/portmux.h>
#include "bfin_sport_uart.h"
#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
unsigned short bfin_uart_pin_req_sport0[] =
{P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0};
#endif
#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
unsigned short bfin_uart_pin_req_sport1[] =
{P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0};
#endif
#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
unsigned short bfin_uart_pin_req_sport2[] =
{P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, \
P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0};
#endif
#ifdef CONFIG_SERIAL_BFIN_SPORT3_UART
unsigned short bfin_uart_pin_req_sport3[] =
{P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, \
P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0};
#endif
struct sport_uart_port {
struct uart_port port;
int err_irq;
@ -69,9 +49,13 @@ struct sport_uart_port {
unsigned short txmask2;
unsigned char stopb;
/* unsigned char parib; */
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
int cts_pin;
int rts_pin;
#endif
};
static void sport_uart_tx_chars(struct sport_uart_port *up);
static int sport_uart_tx_chars(struct sport_uart_port *up);
static void sport_stop_tx(struct uart_port *port);
static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
@ -219,6 +203,59 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
static unsigned int sport_get_mctrl(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
if (up->cts_pin < 0)
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
/* CTS PIN is negative assertive. */
if (SPORT_UART_GET_CTS(up))
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
else
return TIOCM_DSR | TIOCM_CAR;
}
static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
if (up->rts_pin < 0)
return;
/* RTS PIN is negative assertive. */
if (mctrl & TIOCM_RTS)
SPORT_UART_ENABLE_RTS(up);
else
SPORT_UART_DISABLE_RTS(up);
}
/*
* Handle any change of modem status signal.
*/
static irqreturn_t sport_mctrl_cts_int(int irq, void *dev_id)
{
struct sport_uart_port *up = (struct sport_uart_port *)dev_id;
unsigned int status;
status = sport_get_mctrl(&up->port);
uart_handle_cts_change(&up->port, status & TIOCM_CTS);
return IRQ_HANDLED;
}
#else
static unsigned int sport_get_mctrl(struct uart_port *port)
{
pr_debug("%s enter\n", __func__);
return TIOCM_CTS | TIOCM_CD | TIOCM_DSR;
}
static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
pr_debug("%s enter\n", __func__);
}
#endif
/* Reqeust IRQ, Setup clock */
static int sport_startup(struct uart_port *port)
{
@ -247,6 +284,21 @@ static int sport_startup(struct uart_port *port)
goto fail2;
}
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
if (up->cts_pin >= 0) {
if (request_irq(gpio_to_irq(up->cts_pin),
sport_mctrl_cts_int,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) {
up->cts_pin = -1;
dev_info(port->dev, "Unable to attach BlackFin UART \
over SPORT CTS interrupt. So, disable it.\n");
}
}
if (up->rts_pin >= 0)
gpio_direction_output(up->rts_pin, 0);
#endif
return 0;
fail2:
free_irq(up->port.irq+1, up);
@ -256,23 +308,35 @@ static int sport_startup(struct uart_port *port)
return ret;
}
static void sport_uart_tx_chars(struct sport_uart_port *up)
/*
* sport_uart_tx_chars
*
* ret 1 means need to enable sport.
* ret 0 means do nothing.
*/
static int sport_uart_tx_chars(struct sport_uart_port *up)
{
struct circ_buf *xmit = &up->port.state->xmit;
if (SPORT_GET_STAT(up) & TXF)
return;
return 0;
if (up->port.x_char) {
tx_one_byte(up, up->port.x_char);
up->port.icount.tx++;
up->port.x_char = 0;
return;
return 1;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
sport_stop_tx(&up->port);
return;
/* The waiting loop to stop SPORT TX from TX interrupt is
* too long. This may block SPORT RX interrupts and cause
* RX FIFO overflow. So, do stop sport TX only after the last
* char in TX FIFO is moved into the shift register.
*/
if (SPORT_GET_STAT(up) & TXHRE)
sport_stop_tx(&up->port);
return 0;
}
while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) {
@ -283,6 +347,8 @@ static void sport_uart_tx_chars(struct sport_uart_port *up)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port);
return 1;
}
static unsigned int sport_tx_empty(struct uart_port *port)
@ -298,23 +364,15 @@ static unsigned int sport_tx_empty(struct uart_port *port)
return 0;
}
static unsigned int sport_get_mctrl(struct uart_port *port)
{
pr_debug("%s enter\n", __func__);
return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR);
}
static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
pr_debug("%s enter\n", __func__);
}
static void sport_stop_tx(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
pr_debug("%s enter\n", __func__);
if (!(SPORT_GET_TCR1(up) & TSPEN))
return;
/* Although the hold register is empty, last byte is still in shift
* register and not sent out yet. So, put a dummy data into TX FIFO.
* Then, sport tx stops when last byte is shift out and the dummy
@ -337,11 +395,12 @@ static void sport_start_tx(struct uart_port *port)
pr_debug("%s enter\n", __func__);
/* Write data into SPORT FIFO before enable SPROT to transmit */
sport_uart_tx_chars(up);
if (sport_uart_tx_chars(up)) {
/* Enable transmit, then an interrupt will generated */
SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
SSYNC();
}
/* Enable transmit, then an interrupt will generated */
SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
SSYNC();
pr_debug("%s exit\n", __func__);
}
@ -379,6 +438,10 @@ static void sport_shutdown(struct uart_port *port)
free_irq(up->port.irq, up);
free_irq(up->port.irq+1, up);
free_irq(up->err_irq, up);
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
if (up->cts_pin >= 0)
free_irq(gpio_to_irq(up->cts_pin), up);
#endif
}
static const char *sport_type(struct uart_port *port)
@ -448,27 +511,14 @@ static void sport_set_termios(struct uart_port *port,
/* up->parib = 1; */
}
port->read_status_mask = OE;
if (termios->c_iflag & INPCK)
port->read_status_mask |= (FE | PE);
if (termios->c_iflag & (BRKINT | PARMRK))
port->read_status_mask |= BI;
spin_lock_irqsave(&up->port.lock, flags);
port->read_status_mask = 0;
/*
* Characters to ignore
*/
port->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= FE | PE;
if (termios->c_iflag & IGNBRK) {
port->ignore_status_mask |= BI;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= OE;
}
/* RX extract mask */
up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8);
@ -488,8 +538,6 @@ static void sport_set_termios(struct uart_port *port,
/* uart baud rate */
port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16);
spin_lock_irqsave(&up->port.lock, flags);
/* Disable UART */
SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
@ -542,6 +590,8 @@ struct uart_ops sport_uart_ops = {
static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS];
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
#define CLASS_BFIN_SPORT_CONSOLE "bfin-sport-console"
static int __init
sport_uart_console_setup(struct console *co, char *options)
{
@ -549,7 +599,11 @@ sport_uart_console_setup(struct console *co, char *options)
int baud = 57600;
int bits = 8;
int parity = 'n';
# ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
int flow = 'r';
# else
int flow = 'n';
# endif
/* Check whether an invalid uart number has been specified */
if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS)
@ -690,11 +744,11 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
if (bfin_sport_uart_ports[pdev->id] == NULL) {
bfin_sport_uart_ports[pdev->id] =
kmalloc(sizeof(struct sport_uart_port), GFP_KERNEL);
kzalloc(sizeof(struct sport_uart_port), GFP_KERNEL);
sport = bfin_sport_uart_ports[pdev->id];
if (!sport) {
dev_err(&pdev->dev,
"Fail to kmalloc sport_uart_port\n");
"Fail to malloc sport_uart_port\n");
return -ENOMEM;
}
@ -720,13 +774,13 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
goto out_error_free_peripherals;
}
sport->port.membase = ioremap(res->start,
res->end - res->start);
sport->port.membase = ioremap(res->start, resource_size(res));
if (!sport->port.membase) {
dev_err(&pdev->dev, "Cannot map sport IO\n");
ret = -ENXIO;
goto out_error_free_peripherals;
}
sport->port.mapbase = res->start;
sport->port.irq = platform_get_irq(pdev, 0);
if (sport->port.irq < 0) {
@ -741,6 +795,22 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
ret = -ENOENT;
goto out_error_unmap;
}
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (res == NULL)
sport->cts_pin = -1;
else
sport->cts_pin = res->start;
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
if (res == NULL)
sport->rts_pin = -1;
else
sport->rts_pin = res->start;
if (sport->rts_pin >= 0)
gpio_request(sport->rts_pin, DRV_NAME);
#endif
}
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
@ -779,6 +849,10 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
if (sport) {
uart_remove_one_port(&sport_uart_reg, &sport->port);
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
if (sport->rts_pin >= 0)
gpio_free(sport->rts_pin);
#endif
iounmap(sport->port.membase);
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
@ -802,7 +876,7 @@ static struct platform_driver sport_uart_driver = {
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
static __initdata struct early_platform_driver early_sport_uart_driver = {
.class_str = DRV_NAME,
.class_str = CLASS_BFIN_SPORT_CONSOLE,
.pdrv = &sport_uart_driver,
.requested_id = EARLY_PLATFORM_ID_UNSET,
};
@ -811,7 +885,8 @@ static int __init sport_uart_rs_console_init(void)
{
early_platform_driver_register(&early_sport_uart_driver, DRV_NAME);
early_platform_driver_probe(DRV_NAME, BFIN_SPORT_UART_MAX_PORTS, 0);
early_platform_driver_probe(CLASS_BFIN_SPORT_CONSOLE,
BFIN_SPORT_UART_MAX_PORTS, 0);
register_console(&sport_uart_console);
@ -824,7 +899,7 @@ static int __init sport_uart_init(void)
{
int ret;
pr_info("Serial: Blackfin uart over sport driver\n");
pr_info("Blackfin uart over sport driver\n");
ret = uart_register_driver(&sport_uart_reg);
if (ret) {

View file

@ -37,7 +37,21 @@
#define SPORT_GET_TFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TFSDIV))
#define SPORT_GET_TX(sport) bfin_read16(((sport)->port.membase + OFFSET_TX))
#define SPORT_GET_RX(sport) bfin_read16(((sport)->port.membase + OFFSET_RX))
#define SPORT_GET_RX32(sport) bfin_read32(((sport)->port.membase + OFFSET_RX))
/*
* If another interrupt fires while doing a 32-bit read from RX FIFO,
* a fake RX underflow error will be generated. So disable interrupts
* to prevent interruption while reading the FIFO.
*/
#define SPORT_GET_RX32(sport) \
({ \
unsigned int __ret; \
if (ANOMALY_05000473) \
local_irq_disable(); \
__ret = bfin_read32((sport)->port.membase + OFFSET_RX); \
if (ANOMALY_05000473) \
local_irq_enable(); \
__ret; \
})
#define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1))
#define SPORT_GET_RCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR2))
#define SPORT_GET_RCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RCLKDIV))
@ -58,4 +72,15 @@
#define SPORT_TX_FIFO_SIZE 8
#define SPORT_UART_GET_CTS(x) gpio_get_value(x->cts_pin)
#define SPORT_UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
#define SPORT_UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
#if defined(CONFIG_SERIAL_BFIN_SPORT0_UART_CTSRTS) \
|| defined(CONFIG_SERIAL_BFIN_SPORT1_UART_CTSRTS) \
|| defined(CONFIG_SERIAL_BFIN_SPORT2_UART_CTSRTS) \
|| defined(CONFIG_SERIAL_BFIN_SPORT3_UART_CTSRTS)
# define CONFIG_SERIAL_BFIN_SPORT_CTSRTS
#endif
#endif /* _BFIN_SPORT_UART_H */

View file

@ -1342,7 +1342,7 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev,
/* initialize the device pointer for the port */
pinfo->port.dev = &ofdev->dev;
ret = cpm_uart_init_port(ofdev->node, pinfo);
ret = cpm_uart_init_port(ofdev->dev.of_node, pinfo);
if (ret)
return ret;
@ -1372,8 +1372,11 @@ static struct of_device_id cpm_uart_match[] = {
};
static struct of_platform_driver cpm_uart_driver = {
.name = "cpm_uart",
.match_table = cpm_uart_match,
.driver = {
.name = "cpm_uart",
.owner = THIS_MODULE,
.of_match_table = cpm_uart_match,
},
.probe = cpm_uart_probe,
.remove = cpm_uart_remove,
};

View file

@ -14,7 +14,9 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
#include <linux/tty.h>
#include <linux/console.h>
#define MAX_CONFIG_LEN 40
@ -32,6 +34,40 @@ static struct kparam_string kps = {
static struct tty_driver *kgdb_tty_driver;
static int kgdb_tty_line;
#ifdef CONFIG_KDB_KEYBOARD
static int kgdboc_register_kbd(char **cptr)
{
if (strncmp(*cptr, "kbd", 3) == 0) {
if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
kdb_poll_idx++;
if (cptr[0][3] == ',')
*cptr += 4;
else
return 1;
}
}
return 0;
}
static void kgdboc_unregister_kbd(void)
{
int i;
for (i = 0; i < kdb_poll_idx; i++) {
if (kdb_poll_funcs[i] == kdb_get_kbd_char) {
kdb_poll_idx--;
kdb_poll_funcs[i] = kdb_poll_funcs[kdb_poll_idx];
kdb_poll_funcs[kdb_poll_idx] = NULL;
i--;
}
}
}
#else /* ! CONFIG_KDB_KEYBOARD */
#define kgdboc_register_kbd(x) 0
#define kgdboc_unregister_kbd()
#endif /* ! CONFIG_KDB_KEYBOARD */
static int kgdboc_option_setup(char *opt)
{
if (strlen(opt) > MAX_CONFIG_LEN) {
@ -45,25 +81,51 @@ static int kgdboc_option_setup(char *opt)
__setup("kgdboc=", kgdboc_option_setup);
static void cleanup_kgdboc(void)
{
kgdboc_unregister_kbd();
if (configured == 1)
kgdb_unregister_io_module(&kgdboc_io_ops);
}
static int configure_kgdboc(void)
{
struct tty_driver *p;
int tty_line = 0;
int err;
char *cptr = config;
struct console *cons;
err = kgdboc_option_setup(config);
if (err || !strlen(config) || isspace(config[0]))
goto noconfig;
err = -ENODEV;
kgdboc_io_ops.is_console = 0;
kgdb_tty_driver = NULL;
p = tty_find_polling_driver(config, &tty_line);
if (kgdboc_register_kbd(&cptr))
goto do_register;
p = tty_find_polling_driver(cptr, &tty_line);
if (!p)
goto noconfig;
cons = console_drivers;
while (cons) {
int idx;
if (cons->device && cons->device(cons, &idx) == p &&
idx == tty_line) {
kgdboc_io_ops.is_console = 1;
break;
}
cons = cons->next;
}
kgdb_tty_driver = p;
kgdb_tty_line = tty_line;
do_register:
err = kgdb_register_io_module(&kgdboc_io_ops);
if (err)
goto noconfig;
@ -75,6 +137,7 @@ static int configure_kgdboc(void)
noconfig:
config[0] = 0;
configured = 0;
cleanup_kgdboc();
return err;
}
@ -88,20 +151,18 @@ static int __init init_kgdboc(void)
return configure_kgdboc();
}
static void cleanup_kgdboc(void)
{
if (configured == 1)
kgdb_unregister_io_module(&kgdboc_io_ops);
}
static int kgdboc_get_char(void)
{
if (!kgdb_tty_driver)
return -1;
return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
kgdb_tty_line);
}
static void kgdboc_put_char(u8 chr)
{
if (!kgdb_tty_driver)
return;
kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
kgdb_tty_line, chr);
}
@ -162,6 +223,25 @@ static struct kgdb_io kgdboc_io_ops = {
.post_exception = kgdboc_post_exp_handler,
};
#ifdef CONFIG_KGDB_SERIAL_CONSOLE
/* This is only available if kgdboc is a built in for early debugging */
int __init kgdboc_early_init(char *opt)
{
/* save the first character of the config string because the
* init routine can destroy it.
*/
char save_ch;
kgdboc_option_setup(opt);
save_ch = config[0];
init_kgdboc();
config[0] = save_ch;
return 0;
}
early_param("ekgdboc", kgdboc_early_init);
#endif /* CONFIG_KGDB_SERIAL_CONSOLE */
module_init(init_kgdboc);
module_exit(cleanup_kgdboc);
module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);

View file

@ -1226,14 +1226,14 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
/* Check validity & presence */
for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++)
if (mpc52xx_uart_nodes[idx] == op->node)
if (mpc52xx_uart_nodes[idx] == op->dev.of_node)
break;
if (idx >= MPC52xx_PSC_MAXNUM)
return -EINVAL;
pr_debug("Found %s assigned to ttyPSC%x\n",
mpc52xx_uart_nodes[idx]->full_name, idx);
uartclk = psc_ops->getuartclk(op->node);
uartclk = psc_ops->getuartclk(op->dev.of_node);
if (uartclk == 0) {
dev_dbg(&op->dev, "Could not find uart clock frequency!\n");
return -EINVAL;
@ -1253,7 +1253,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
port->dev = &op->dev;
/* Search for IRQ and mapbase */
ret = of_address_to_resource(op->node, 0, &res);
ret = of_address_to_resource(op->dev.of_node, 0, &res);
if (ret)
return ret;
@ -1263,7 +1263,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
return -EINVAL;
}
psc_ops->get_irq(port, op->node);
psc_ops->get_irq(port, op->dev.of_node);
if (port->irq == NO_IRQ) {
dev_dbg(&op->dev, "Could not get irq\n");
return -EINVAL;
@ -1362,15 +1362,16 @@ mpc52xx_uart_of_enumerate(void)
MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match);
static struct of_platform_driver mpc52xx_uart_of_driver = {
.match_table = mpc52xx_uart_of_match,
.probe = mpc52xx_uart_of_probe,
.remove = mpc52xx_uart_of_remove,
#ifdef CONFIG_PM
.suspend = mpc52xx_uart_of_suspend,
.resume = mpc52xx_uart_of_resume,
#endif
.driver = {
.name = "mpc52xx-psc-uart",
.driver = {
.name = "mpc52xx-psc-uart",
.owner = THIS_MODULE,
.of_match_table = mpc52xx_uart_of_match,
},
};

View file

@ -2071,6 +2071,7 @@ static int mpsc_drv_probe(struct platform_device *dev)
if (!(rc = mpsc_drv_map_regs(pi, dev))) {
mpsc_drv_get_platform_data(pi, dev, dev->id);
pi->port.dev = &dev->dev;
if (!(rc = mpsc_make_ready(pi))) {
spin_lock_init(&pi->tx_lock);

View file

@ -344,7 +344,7 @@ int nwpserial_register_port(struct uart_port *port)
mutex_lock(&nwpserial_mutex);
dn = to_of_device(port->dev)->node;
dn = to_of_device(port->dev)->dev.of_node;
if (dn == NULL)
goto out;

View file

@ -31,7 +31,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
int type, struct uart_port *port)
{
struct resource resource;
struct device_node *np = ofdev->node;
struct device_node *np = ofdev->dev.of_node;
const unsigned int *clk, *spd;
const u32 *prop;
int ret, prop_size;
@ -88,7 +88,7 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev,
int port_type;
int ret;
if (of_find_property(ofdev->node, "used-by-rtas", NULL))
if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
return -EBUSY;
info = kmalloc(sizeof(*info), GFP_KERNEL);
@ -175,11 +175,13 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
};
static struct of_platform_driver of_platform_serial_driver = {
.owner = THIS_MODULE,
.name = "of_serial",
.driver = {
.name = "of_serial",
.owner = THIS_MODULE,
.of_match_table = of_platform_serial_table,
},
.probe = of_platform_serial_probe,
.remove = of_platform_serial_remove,
.match_table = of_platform_serial_table,
};
static int __init of_platform_serial_init(void)

View file

@ -1611,7 +1611,7 @@ static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match)
/* Iterate the pmz_ports array to find a matching entry
*/
for (i = 0; i < MAX_ZS_PORTS; i++)
if (pmz_ports[i].node == mdev->ofdev.node) {
if (pmz_ports[i].node == mdev->ofdev.dev.of_node) {
struct uart_pmac_port *uap = &pmz_ports[i];
uap->dev = mdev;

View file

@ -89,7 +89,6 @@ struct serial_info {
int manfid;
int prodid;
int c950ctrl;
dev_node_t node[4];
int line[4];
const struct serial_quirk *quirk;
};
@ -289,8 +288,6 @@ static void serial_remove(struct pcmcia_device *link)
for (i = 0; i < info->ndev; i++)
serial8250_unregister_port(info->line[i]);
info->p_dev->dev_node = NULL;
if (!info->slave)
pcmcia_disable_device(link);
}
@ -343,7 +340,6 @@ static int serial_probe(struct pcmcia_device *link)
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts1 = 8;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->conf.Attributes = CONF_ENABLE_IRQ;
if (do_sound) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
@ -411,11 +407,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
}
info->line[info->ndev] = line;
sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
info->node[info->ndev].major = TTY_MAJOR;
info->node[info->ndev].minor = 0x40 + line;
if (info->ndev > 0)
info->node[info->ndev - 1].next = &info->node[info->ndev];
info->ndev++;
return 0;
@ -486,7 +477,7 @@ static int simple_config(struct pcmcia_device *link)
}
if (info->slave) {
return setup_serial(link, info, port,
link->irq.AssignedIRQ);
link->irq);
}
}
@ -507,10 +498,6 @@ static int simple_config(struct pcmcia_device *link)
return -1;
found_port:
i = pcmcia_request_irq(link, &link->irq);
if (i != 0)
link->irq.AssignedIRQ = 0;
if (info->multi && (info->manfid == MANFID_3COM))
link->conf.ConfigIndex &= ~(0x08);
@ -523,7 +510,7 @@ found_port:
i = pcmcia_request_configuration(link, &link->conf);
if (i != 0)
return -1;
return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
return setup_serial(link, info, link->io.BasePort1, link->irq);
}
static int multi_config_check(struct pcmcia_device *p_dev,
@ -586,13 +573,9 @@ static int multi_config(struct pcmcia_device *link)
}
}
i = pcmcia_request_irq(link, &link->irq);
if (i != 0) {
/* FIXME: comment does not fit, error handling does not fit */
printk(KERN_NOTICE
"serial_cs: no usable port range found, giving up\n");
link->irq.AssignedIRQ = 0;
}
if (!link->irq)
dev_warn(&link->dev,
"serial_cs: no usable IRQ found, continuing...\n");
/*
* Apply any configuration quirks.
@ -615,11 +598,11 @@ static int multi_config(struct pcmcia_device *link)
if (link->conf.ConfigIndex == 1 ||
link->conf.ConfigIndex == 3) {
err = setup_serial(link, info, base2,
link->irq.AssignedIRQ);
link->irq);
base2 = link->io.BasePort1;
} else {
err = setup_serial(link, info, link->io.BasePort1,
link->irq.AssignedIRQ);
link->irq);
}
info->c950ctrl = base2;
@ -633,10 +616,10 @@ static int multi_config(struct pcmcia_device *link)
return 0;
}
setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
setup_serial(link, info, link->io.BasePort1, link->irq);
for (i = 0; i < info->multi - 1; i++)
setup_serial(link, info, base2 + (8 * i),
link->irq.AssignedIRQ);
link->irq);
return 0;
}
@ -720,7 +703,6 @@ static int serial_config(struct pcmcia_device * link)
if (info->quirk->post(link))
goto failed;
link->dev_node = &info->node[0];
return 0;
failed:

View file

@ -83,16 +83,16 @@ struct sci_port {
/* Interface clock */
struct clk *iclk;
/* Data clock */
struct clk *dclk;
/* Function clock */
struct clk *fclk;
struct list_head node;
struct dma_chan *chan_tx;
struct dma_chan *chan_rx;
#ifdef CONFIG_SERIAL_SH_SCI_DMA
struct device *dma_dev;
enum sh_dmae_slave_chan_id slave_tx;
enum sh_dmae_slave_chan_id slave_rx;
unsigned int slave_tx;
unsigned int slave_rx;
struct dma_async_tx_descriptor *desc_tx;
struct dma_async_tx_descriptor *desc_rx[2];
dma_cookie_t cookie_tx;
@ -107,6 +107,7 @@ struct sci_port {
struct work_struct work_tx;
struct work_struct work_rx;
struct timer_list rx_timer;
unsigned int rx_timeout;
#endif
};
@ -150,7 +151,11 @@ static int sci_poll_get_char(struct uart_port *port)
handle_error(port);
continue;
}
} while (!(status & SCxSR_RDxF(port)));
break;
} while (1);
if (!(status & SCxSR_RDxF(port)))
return NO_POLL_CHAR;
c = sci_in(port, SCxRDR);
@ -674,22 +679,22 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
struct sci_port *s = to_sci_port(port);
if (s->chan_rx) {
unsigned long tout;
u16 scr = sci_in(port, SCSCR);
u16 ssr = sci_in(port, SCxSR);
/* Disable future Rx interrupts */
sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE);
if (port->type == PORT_SCIFA) {
disable_irq_nosync(irq);
scr |= 0x4000;
} else {
scr &= ~SCI_CTRL_FLAGS_RIE;
}
sci_out(port, SCSCR, scr);
/* Clear current interrupt */
sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
/* Calculate delay for 1.5 DMA buffers */
tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
port->fifosize / 2;
dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n",
tout * 1000 / HZ);
if (tout < 2)
tout = 2;
mod_timer(&s->rx_timer, jiffies + tout);
dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
jiffies, s->rx_timeout);
mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
return IRQ_HANDLED;
}
@ -799,7 +804,7 @@ static int sci_notifier(struct notifier_block *self,
(phase == CPUFREQ_RESUMECHANGE)) {
spin_lock_irqsave(&priv->lock, flags);
list_for_each_entry(sci_port, &priv->ports, node)
sci_port->port.uartclk = clk_get_rate(sci_port->dclk);
sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
spin_unlock_irqrestore(&priv->lock, flags);
}
@ -810,21 +815,17 @@ static void sci_clk_enable(struct uart_port *port)
{
struct sci_port *sci_port = to_sci_port(port);
clk_enable(sci_port->dclk);
sci_port->port.uartclk = clk_get_rate(sci_port->dclk);
if (sci_port->iclk)
clk_enable(sci_port->iclk);
clk_enable(sci_port->iclk);
sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
clk_enable(sci_port->fclk);
}
static void sci_clk_disable(struct uart_port *port)
{
struct sci_port *sci_port = to_sci_port(port);
if (sci_port->iclk)
clk_disable(sci_port->iclk);
clk_disable(sci_port->dclk);
clk_disable(sci_port->fclk);
clk_disable(sci_port->iclk);
}
static int sci_request_irq(struct sci_port *port)
@ -913,22 +914,26 @@ static void sci_dma_tx_complete(void *arg)
spin_lock_irqsave(&port->lock, flags);
xmit->tail += s->sg_tx.length;
xmit->tail += sg_dma_len(&s->sg_tx);
xmit->tail &= UART_XMIT_SIZE - 1;
port->icount.tx += s->sg_tx.length;
port->icount.tx += sg_dma_len(&s->sg_tx);
async_tx_ack(s->desc_tx);
s->cookie_tx = -EINVAL;
s->desc_tx = NULL;
spin_unlock_irqrestore(&port->lock, flags);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_chars_pending(xmit))
if (!uart_circ_empty(xmit)) {
schedule_work(&s->work_tx);
} else if (port->type == PORT_SCIFA) {
u16 ctrl = sci_in(port, SCSCR);
sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE);
}
spin_unlock_irqrestore(&port->lock, flags);
}
/* Locking: called with port lock held */
@ -972,13 +977,13 @@ static void sci_dma_rx_complete(void *arg)
unsigned long flags;
int count;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx);
spin_lock_irqsave(&port->lock, flags);
count = sci_dma_rx_push(s, tty, s->buf_len_rx);
mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5));
mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
spin_unlock_irqrestore(&port->lock, flags);
@ -999,8 +1004,9 @@ static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
s->chan_rx = NULL;
s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
dma_release_channel(chan);
dma_free_coherent(port->dev, s->buf_len_rx * 2,
sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
if (sg_dma_address(&s->sg_rx[0]))
dma_free_coherent(port->dev, s->buf_len_rx * 2,
sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
if (enable_pio)
sci_start_rx(port);
}
@ -1050,6 +1056,8 @@ static void sci_submit_rx(struct sci_port *s)
sci_rx_dma_release(s, true);
return;
}
dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
s->cookie_rx[i], i);
}
s->active_rx = s->cookie_rx[0];
@ -1084,7 +1092,7 @@ static void work_fn_rx(struct work_struct *work)
unsigned long flags;
int count;
chan->device->device_terminate_all(chan);
chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
dev_dbg(port->dev, "Read %u bytes with cookie %d\n",
sh_desc->partial, sh_desc->cookie);
@ -1107,10 +1115,10 @@ static void work_fn_rx(struct work_struct *work)
return;
}
dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__,
s->cookie_rx[new], new);
s->active_rx = s->cookie_rx[!new];
dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__,
s->cookie_rx[new], new, s->active_rx);
}
static void work_fn_tx(struct work_struct *work)
@ -1131,14 +1139,13 @@ static void work_fn_tx(struct work_struct *work)
*/
spin_lock_irq(&port->lock);
sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
sg->offset;
sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
sg->dma_length = sg->length;
spin_unlock_irq(&port->lock);
BUG_ON(!sg->length);
BUG_ON(!sg_dma_len(sg));
desc = chan->device->device_prep_slave_sg(chan,
sg, s->sg_len_tx, DMA_TO_DEVICE,
@ -1173,23 +1180,28 @@ static void work_fn_tx(struct work_struct *work)
static void sci_start_tx(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
unsigned short ctrl;
#ifdef CONFIG_SERIAL_SH_SCI_DMA
struct sci_port *s = to_sci_port(port);
if (s->chan_tx) {
if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0)
schedule_work(&s->work_tx);
return;
if (port->type == PORT_SCIFA) {
u16 new, scr = sci_in(port, SCSCR);
if (s->chan_tx)
new = scr | 0x8000;
else
new = scr & ~0x8000;
if (new != scr)
sci_out(port, SCSCR, new);
}
if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
s->cookie_tx < 0)
schedule_work(&s->work_tx);
#endif
/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR);
ctrl |= SCI_CTRL_FLAGS_TIE;
sci_out(port, SCSCR, ctrl);
if (!s->chan_tx || port->type == PORT_SCIFA) {
/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR);
sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE);
}
}
static void sci_stop_tx(struct uart_port *port)
@ -1198,6 +1210,8 @@ static void sci_stop_tx(struct uart_port *port)
/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR);
if (port->type == PORT_SCIFA)
ctrl &= ~0x8000;
ctrl &= ~SCI_CTRL_FLAGS_TIE;
sci_out(port, SCSCR, ctrl);
}
@ -1208,6 +1222,8 @@ static void sci_start_rx(struct uart_port *port)
/* Set RIE (Receive Interrupt Enable) bit in SCSCR */
ctrl |= sci_in(port, SCSCR);
if (port->type == PORT_SCIFA)
ctrl &= ~0x4000;
sci_out(port, SCSCR, ctrl);
}
@ -1217,6 +1233,8 @@ static void sci_stop_rx(struct uart_port *port)
/* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR);
if (port->type == PORT_SCIFA)
ctrl &= ~0x4000;
ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
sci_out(port, SCSCR, ctrl);
}
@ -1251,8 +1269,12 @@ static void rx_timer_fn(unsigned long arg)
{
struct sci_port *s = (struct sci_port *)arg;
struct uart_port *port = &s->port;
u16 scr = sci_in(port, SCSCR);
if (port->type == PORT_SCIFA) {
scr &= ~0x4000;
enable_irq(s->irqs[1]);
}
sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE);
dev_dbg(port->dev, "DMA Rx timed out\n");
schedule_work(&s->work_rx);
@ -1339,8 +1361,7 @@ static void sci_request_dma(struct uart_port *port)
sg_init_table(sg, 1);
sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
(int)buf[i] & ~PAGE_MASK);
sg->dma_address = dma[i];
sg->dma_length = sg->length;
sg_dma_address(sg) = dma[i];
}
INIT_WORK(&s->work_rx, work_fn_rx);
@ -1403,8 +1424,12 @@ static void sci_shutdown(struct uart_port *port)
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
#ifdef CONFIG_SERIAL_SH_SCI_DMA
struct sci_port *s = to_sci_port(port);
#endif
unsigned int status, baud, smr_val, max_baud;
int t = -1;
u16 scfcr = 0;
/*
* earlyprintk comes here early on with port->uartclk set to zero.
@ -1427,7 +1452,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
if (port->type != PORT_SCI)
sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
smr_val = sci_in(port, SCSMR) & 3;
if ((termios->c_cflag & CSIZE) == CS7)
@ -1458,10 +1483,32 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
}
sci_init_pins(port, termios->c_cflag);
sci_out(port, SCFCR, (termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0);
sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
sci_out(port, SCSCR, SCSCR_INIT(port));
#ifdef CONFIG_SERIAL_SH_SCI_DMA
/*
* Calculate delay for 1.5 DMA buffers: see
* drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits
* (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
* calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)."
* Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO
* sizes), but it has been found out experimentally, that this is not
* enough: the driver too often needlessly runs on a DMA timeout. 20ms
* as a minimum seem to work perfectly.
*/
if (s->chan_rx) {
s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
port->fifosize / 2;
dev_dbg(port->dev,
"DMA Rx t-out %ums, tty t-out %u jiffies\n",
s->rx_timeout * 1000 / HZ, port->timeout);
if (s->rx_timeout < msecs_to_jiffies(20))
s->rx_timeout = msecs_to_jiffies(20);
}
#endif
if ((termios->c_cflag & CREAD) != 0)
sci_start_rx(port);
}
@ -1553,10 +1600,10 @@ static struct uart_ops sci_uart_ops = {
#endif
};
static void __devinit sci_init_single(struct platform_device *dev,
struct sci_port *sci_port,
unsigned int index,
struct plat_sci_port *p)
static int __devinit sci_init_single(struct platform_device *dev,
struct sci_port *sci_port,
unsigned int index,
struct plat_sci_port *p)
{
struct uart_port *port = &sci_port->port;
@ -1577,8 +1624,23 @@ static void __devinit sci_init_single(struct platform_device *dev,
}
if (dev) {
sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
sci_port->dclk = clk_get(&dev->dev, "peripheral_clk");
sci_port->iclk = clk_get(&dev->dev, "sci_ick");
if (IS_ERR(sci_port->iclk)) {
sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
if (IS_ERR(sci_port->iclk)) {
dev_err(&dev->dev, "can't get iclk\n");
return PTR_ERR(sci_port->iclk);
}
}
/*
* The function clock is optional, ignore it if we can't
* find it.
*/
sci_port->fclk = clk_get(&dev->dev, "sci_fck");
if (IS_ERR(sci_port->fclk))
sci_port->fclk = NULL;
sci_port->enable = sci_clk_enable;
sci_port->disable = sci_clk_disable;
port->dev = &dev->dev;
@ -1605,6 +1667,7 @@ static void __devinit sci_init_single(struct platform_device *dev,
#endif
memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
return 0;
}
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
@ -1754,8 +1817,11 @@ static int sci_remove(struct platform_device *dev)
cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
spin_lock_irqsave(&priv->lock, flags);
list_for_each_entry(p, &priv->ports, node)
list_for_each_entry(p, &priv->ports, node) {
uart_remove_one_port(&sci_uart_driver, &p->port);
clk_put(p->iclk);
clk_put(p->fclk);
}
spin_unlock_irqrestore(&priv->lock, flags);
kfree(priv);
@ -1781,7 +1847,9 @@ static int __devinit sci_probe_single(struct platform_device *dev,
return 0;
}
sci_init_single(dev, sciport, index, p);
ret = sci_init_single(dev, sciport, index, p);
if (ret)
return ret;
ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
if (ret)

View file

@ -565,7 +565,7 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
if (err)
goto out_free_con_read_page;
sunserial_console_match(&sunhv_console, op->node,
sunserial_console_match(&sunhv_console, op->dev.of_node,
&sunhv_reg, port->line, false);
err = uart_add_one_port(&sunhv_reg, port);
@ -630,8 +630,11 @@ static const struct of_device_id hv_match[] = {
MODULE_DEVICE_TABLE(of, hv_match);
static struct of_platform_driver hv_driver = {
.name = "hv",
.match_table = hv_match,
.driver = {
.name = "hv",
.owner = THIS_MODULE,
.of_match_table = hv_match,
},
.probe = hv_probe,
.remove = __devexit_p(hv_remove),
};

View file

@ -883,7 +883,7 @@ static int sunsab_console_setup(struct console *con, char *options)
printk("Console: ttyS%d (SAB82532)\n",
(sunsab_reg.minor - 64) + con->index);
sunserial_console_termios(con, to_of_device(up->port.dev)->node);
sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node);
switch (con->cflag & CBAUD) {
case B150: baud = 150; break;
@ -1026,11 +1026,11 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
if (err)
goto out1;
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
sunserial_console_match(SUNSAB_CONSOLE(), op->dev.of_node,
&sunsab_reg, up[0].port.line,
false);
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
sunserial_console_match(SUNSAB_CONSOLE(), op->dev.of_node,
&sunsab_reg, up[1].port.line,
false);
@ -1093,8 +1093,11 @@ static const struct of_device_id sab_match[] = {
MODULE_DEVICE_TABLE(of, sab_match);
static struct of_platform_driver sab_driver = {
.name = "sab",
.match_table = sab_match,
.driver = {
.name = "sab",
.owner = THIS_MODULE,
.of_match_table = sab_match,
},
.probe = sab_probe,
.remove = __devexit_p(sab_remove),
};

View file

@ -1200,7 +1200,7 @@ static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
return -ENODEV;
printk("%s: %s port at %llx, irq %u\n",
to_of_device(up->port.dev)->node->full_name,
to_of_device(up->port.dev)->dev.of_node->full_name,
(up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse",
(unsigned long long) up->port.mapbase,
up->port.irq);
@ -1352,7 +1352,7 @@ static int __init sunsu_console_setup(struct console *co, char *options)
spin_lock_init(&port->lock);
/* Get firmware console settings. */
sunserial_console_termios(co, to_of_device(port->dev)->node);
sunserial_console_termios(co, to_of_device(port->dev)->dev.of_node);
memset(&termios, 0, sizeof(struct ktermios));
termios.c_cflag = co->cflag;
@ -1409,7 +1409,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
static int __devinit su_probe(struct of_device *op, const struct of_device_id *match)
{
static int inst;
struct device_node *dp = op->node;
struct device_node *dp = op->dev.of_node;
struct uart_sunsu_port *up;
struct resource *rp;
enum su_type type;
@ -1539,8 +1539,11 @@ static const struct of_device_id su_match[] = {
MODULE_DEVICE_TABLE(of, su_match);
static struct of_platform_driver su_driver = {
.name = "su",
.match_table = su_match,
.driver = {
.name = "su",
.owner = THIS_MODULE,
.of_match_table = su_match,
},
.probe = su_probe,
.remove = __devexit_p(su_remove),
};

View file

@ -102,6 +102,8 @@ struct uart_sunzilog_port {
#endif
};
static void sunzilog_putchar(struct uart_port *port, int ch);
#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase))
#define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
@ -996,6 +998,50 @@ static int sunzilog_verify_port(struct uart_port *port, struct serial_struct *se
return -EINVAL;
}
#ifdef CONFIG_CONSOLE_POLL
static int sunzilog_get_poll_char(struct uart_port *port)
{
unsigned char ch, r1;
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port;
struct zilog_channel __iomem *channel
= ZILOG_CHANNEL_FROM_PORT(&up->port);
r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
ch = readb(&channel->control);
ZSDELAY();
/* This funny hack depends upon BRK_ABRT not interfering
* with the other bits we care about in R1.
*/
if (ch & BRK_ABRT)
r1 |= BRK_ABRT;
if (!(ch & Rx_CH_AV))
return NO_POLL_CHAR;
ch = readb(&channel->data);
ZSDELAY();
ch &= up->parity_mask;
return ch;
}
static void sunzilog_put_poll_char(struct uart_port *port,
unsigned char ch)
{
struct uart_sunzilog_port *up = (struct uart_sunzilog_port *)port;
sunzilog_putchar(&up->port, ch);
}
#endif /* CONFIG_CONSOLE_POLL */
static struct uart_ops sunzilog_pops = {
.tx_empty = sunzilog_tx_empty,
.set_mctrl = sunzilog_set_mctrl,
@ -1013,6 +1059,10 @@ static struct uart_ops sunzilog_pops = {
.request_port = sunzilog_request_port,
.config_port = sunzilog_config_port,
.verify_port = sunzilog_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = sunzilog_get_poll_char,
.poll_put_char = sunzilog_put_poll_char,
#endif
};
static int uart_chip_count;
@ -1180,7 +1230,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
(sunzilog_reg.minor - 64) + con->index, con->index);
/* Get firmware console settings. */
sunserial_console_termios(con, to_of_device(up->port.dev)->node);
sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node);
/* Firmware console speed is limited to 150-->38400 baud so
* this hackish cflag thing is OK.
@ -1358,7 +1408,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
int keyboard_mouse = 0;
int err;
if (of_find_property(op->node, "keyboard", NULL))
if (of_find_property(op->dev.of_node, "keyboard", NULL))
keyboard_mouse = 1;
/* uarts must come before keyboards/mice */
@ -1415,7 +1465,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
sunzilog_init_hw(&up[1]);
if (!keyboard_mouse) {
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->dev.of_node,
&sunzilog_reg, up[0].port.line,
false))
up->flags |= SUNZILOG_FLAG_IS_CONS;
@ -1425,7 +1475,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
rp, sizeof(struct zilog_layout));
return err;
}
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node,
if (sunserial_console_match(SUNZILOG_CONSOLE(), op->dev.of_node,
&sunzilog_reg, up[1].port.line,
false))
up->flags |= SUNZILOG_FLAG_IS_CONS;
@ -1491,8 +1541,11 @@ static const struct of_device_id zs_match[] = {
MODULE_DEVICE_TABLE(of, zs_match);
static struct of_platform_driver zs_driver = {
.name = "zs",
.match_table = zs_match,
.driver = {
.name = "zs",
.owner = THIS_MODULE,
.of_match_table = zs_match,
},
.probe = zs_probe,
.remove = __devexit_p(zs_remove),
};

View file

@ -68,12 +68,22 @@ static void timbuart_start_tx(struct uart_port *port)
tasklet_schedule(&uart->tasklet);
}
static unsigned int timbuart_tx_empty(struct uart_port *port)
{
u32 isr = ioread32(port->membase + TIMBUART_ISR);
return (isr & TXBE) ? TIOCSER_TEMT : 0;
}
static void timbuart_flush_buffer(struct uart_port *port)
{
u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | TIMBUART_CTRL_FLSHTX;
if (!timbuart_tx_empty(port)) {
u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
TIMBUART_CTRL_FLSHTX;
iowrite8(ctl, port->membase + TIMBUART_CTRL);
iowrite32(TXBF, port->membase + TIMBUART_ISR);
iowrite8(ctl, port->membase + TIMBUART_CTRL);
iowrite32(TXBF, port->membase + TIMBUART_ISR);
}
}
static void timbuart_rx_chars(struct uart_port *port)
@ -195,13 +205,6 @@ void timbuart_tasklet(unsigned long arg)
dev_dbg(uart->port.dev, "%s leaving\n", __func__);
}
static unsigned int timbuart_tx_empty(struct uart_port *port)
{
u32 isr = ioread32(port->membase + TIMBUART_ISR);
return (isr & TXBE) ? TIOCSER_TEMT : 0;
}
static unsigned int timbuart_get_mctrl(struct uart_port *port)
{
u8 cts = ioread8(port->membase + TIMBUART_CTRL);
@ -220,7 +223,7 @@ static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_RTS)
iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
else
iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
iowrite8(0, port->membase + TIMBUART_CTRL);
}
static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)

View file

@ -86,7 +86,7 @@ static int ulite_receive(struct uart_port *port, int stat)
/* stats */
if (stat & ULITE_STATUS_RXVALID) {
port->icount.rx++;
ch = readb(port->membase + ULITE_RX);
ch = ioread32be(port->membase + ULITE_RX);
if (stat & ULITE_STATUS_PARITY)
port->icount.parity++;
@ -131,7 +131,7 @@ static int ulite_transmit(struct uart_port *port, int stat)
return 0;
if (port->x_char) {
writeb(port->x_char, port->membase + ULITE_TX);
iowrite32be(port->x_char, port->membase + ULITE_TX);
port->x_char = 0;
port->icount.tx++;
return 1;
@ -140,7 +140,7 @@ static int ulite_transmit(struct uart_port *port, int stat)
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return 0;
writeb(xmit->buf[xmit->tail], port->membase + ULITE_TX);
iowrite32be(xmit->buf[xmit->tail], port->membase + ULITE_TX);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
port->icount.tx++;
@ -157,7 +157,7 @@ static irqreturn_t ulite_isr(int irq, void *dev_id)
int busy, n = 0;
do {
int stat = readb(port->membase + ULITE_STATUS);
int stat = ioread32be(port->membase + ULITE_STATUS);
busy = ulite_receive(port, stat);
busy |= ulite_transmit(port, stat);
n++;
@ -178,7 +178,7 @@ static unsigned int ulite_tx_empty(struct uart_port *port)
unsigned int ret;
spin_lock_irqsave(&port->lock, flags);
ret = readb(port->membase + ULITE_STATUS);
ret = ioread32be(port->membase + ULITE_STATUS);
spin_unlock_irqrestore(&port->lock, flags);
return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
@ -201,7 +201,7 @@ static void ulite_stop_tx(struct uart_port *port)
static void ulite_start_tx(struct uart_port *port)
{
ulite_transmit(port, readb(port->membase + ULITE_STATUS));
ulite_transmit(port, ioread32be(port->membase + ULITE_STATUS));
}
static void ulite_stop_rx(struct uart_port *port)
@ -230,17 +230,17 @@ static int ulite_startup(struct uart_port *port)
if (ret)
return ret;
writeb(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX,
iowrite32be(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX,
port->membase + ULITE_CONTROL);
writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
return 0;
}
static void ulite_shutdown(struct uart_port *port)
{
writeb(0, port->membase + ULITE_CONTROL);
readb(port->membase + ULITE_CONTROL); /* dummy */
iowrite32be(0, port->membase + ULITE_CONTROL);
ioread32be(port->membase + ULITE_CONTROL); /* dummy */
free_irq(port->irq, port);
}
@ -352,7 +352,7 @@ static void ulite_console_wait_tx(struct uart_port *port)
/* Spin waiting for TX fifo to have space available */
for (i = 0; i < 100000; i++) {
val = readb(port->membase + ULITE_STATUS);
val = ioread32be(port->membase + ULITE_STATUS);
if ((val & ULITE_STATUS_TXFULL) == 0)
break;
cpu_relax();
@ -362,7 +362,7 @@ static void ulite_console_wait_tx(struct uart_port *port)
static void ulite_console_putchar(struct uart_port *port, int ch)
{
ulite_console_wait_tx(port);
writeb(ch, port->membase + ULITE_TX);
iowrite32be(ch, port->membase + ULITE_TX);
}
static void ulite_console_write(struct console *co, const char *s,
@ -379,8 +379,8 @@ static void ulite_console_write(struct console *co, const char *s,
spin_lock_irqsave(&port->lock, flags);
/* save and disable interrupt */
ier = readb(port->membase + ULITE_STATUS) & ULITE_STATUS_IE;
writeb(0, port->membase + ULITE_CONTROL);
ier = ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_IE;
iowrite32be(0, port->membase + ULITE_CONTROL);
uart_console_write(port, s, count, ulite_console_putchar);
@ -388,7 +388,7 @@ static void ulite_console_write(struct console *co, const char *s,
/* restore interrupt state */
if (ier)
writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
iowrite32be(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL);
if (locked)
spin_unlock_irqrestore(&port->lock, flags);
@ -591,17 +591,17 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match)
dev_dbg(&op->dev, "%s(%p, %p)\n", __func__, op, match);
rc = of_address_to_resource(op->node, 0, &res);
rc = of_address_to_resource(op->dev.of_node, 0, &res);
if (rc) {
dev_err(&op->dev, "invalid address\n");
return rc;
}
irq = irq_of_parse_and_map(op->node, 0);
irq = irq_of_parse_and_map(op->dev.of_node, 0);
id = of_get_property(op->node, "port-number", NULL);
id = of_get_property(op->dev.of_node, "port-number", NULL);
return ulite_assign(&op->dev, id ? *id : -1, res.start+3, irq);
return ulite_assign(&op->dev, id ? *id : -1, res.start, irq);
}
static int __devexit ulite_of_remove(struct of_device *op)
@ -610,13 +610,12 @@ static int __devexit ulite_of_remove(struct of_device *op)
}
static struct of_platform_driver ulite_of_driver = {
.owner = THIS_MODULE,
.name = "uartlite",
.match_table = ulite_of_match,
.probe = ulite_of_probe,
.remove = __devexit_p(ulite_of_remove),
.driver = {
.name = "uartlite",
.owner = THIS_MODULE,
.of_match_table = ulite_of_match,
},
};

View file

@ -1197,7 +1197,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context)
static int ucc_uart_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
struct device_node *np = ofdev->node;
struct device_node *np = ofdev->dev.of_node;
const unsigned int *iprop; /* Integer OF properties */
const char *sprop; /* String OF properties */
struct uart_qe_port *qe_port = NULL;
@ -1486,9 +1486,11 @@ static struct of_device_id ucc_uart_match[] = {
MODULE_DEVICE_TABLE(of, ucc_uart_match);
static struct of_platform_driver ucc_uart_of_driver = {
.owner = THIS_MODULE,
.name = "ucc_uart",
.match_table = ucc_uart_match,
.driver = {
.name = "ucc_uart",
.owner = THIS_MODULE,
.of_match_table = ucc_uart_match,
},
.probe = ucc_uart_probe,
.remove = ucc_uart_remove,
};