aboutsummaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/21285.c2
-rw-r--r--drivers/serial/68328serial.c103
-rw-r--r--drivers/serial/68328serial.h1
-rw-r--r--drivers/serial/68360serial.c1
-rw-r--r--drivers/serial/8250.c6
-rw-r--r--drivers/serial/8250.h1
-rw-r--r--drivers/serial/8250_mca.c1
-rw-r--r--drivers/serial/8250_pci.c4
-rw-r--r--drivers/serial/8250_pnp.c6
-rw-r--r--drivers/serial/Kconfig26
-rw-r--r--drivers/serial/amba-pl010.c1
-rw-r--r--drivers/serial/amba-pl011.c1
-rw-r--r--drivers/serial/at91_serial.c467
-rw-r--r--drivers/serial/clps711x.c1
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c1
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c1
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c1
-rw-r--r--drivers/serial/crisv10.c31
-rw-r--r--drivers/serial/crisv10.h1
-rw-r--r--drivers/serial/dz.c7
-rw-r--r--drivers/serial/icom.c3
-rw-r--r--drivers/serial/imx.c4
-rw-r--r--drivers/serial/ioc4_serial.c11
-rw-r--r--drivers/serial/ip22zilog.c2
-rw-r--r--drivers/serial/jsm/jsm_driver.c2
-rw-r--r--drivers/serial/jsm/jsm_tty.c7
-rw-r--r--drivers/serial/m32r_sio.c4
-rw-r--r--drivers/serial/m32r_sio.h1
-rw-r--r--drivers/serial/m32r_sio_reg.h1
-rw-r--r--drivers/serial/mcfserial.c31
-rw-r--r--drivers/serial/mcfserial.h1
-rw-r--r--drivers/serial/mpc52xx_uart.c4
-rw-r--r--drivers/serial/mpsc.c5
-rw-r--r--drivers/serial/mux.c1
-rw-r--r--drivers/serial/pmac_zilog.c10
-rw-r--r--drivers/serial/pxa.c5
-rw-r--r--drivers/serial/s3c2410.c148
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_core.c17
-rw-r--r--drivers/serial/serial_cs.c1
-rw-r--r--drivers/serial/serial_lh7a40x.c14
-rw-r--r--drivers/serial/serial_txx9.c6
-rw-r--r--drivers/serial/sh-sci.c8
-rw-r--r--drivers/serial/sh-sci.h1
-rw-r--r--drivers/serial/sn_console.c3
-rw-r--r--drivers/serial/suncore.c1
-rw-r--r--drivers/serial/sunhv.c166
-rw-r--r--drivers/serial/sunsab.c301
-rw-r--r--drivers/serial/sunsu.c503
-rw-r--r--drivers/serial/sunzilog.c795
-rw-r--r--drivers/serial/v850e_uart.c5
-rw-r--r--drivers/serial/vr41xx_siu.c2
52 files changed, 1230 insertions, 1498 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 7572665a885..57438326b07 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -7,7 +7,6 @@
*
* $Id: 21285.c,v 1.37 2002/07/28 10:03:27 rmk Exp $
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
@@ -479,7 +478,6 @@ static struct uart_driver serial21285_reg = {
.owner = THIS_MODULE,
.driver_name = "ttyFB",
.dev_name = "ttyFB",
- .devfs_name = "ttyFB",
.major = SERIAL_21285_MAJOR,
.minor = SERIAL_21285_MINOR,
.nr = 1,
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index b88a7c1158a..993a702422e 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -23,7 +23,6 @@
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
-#include <linux/config.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
@@ -131,17 +130,6 @@ static int m68328_console_baud = CONSOLE_BAUD_RATE;
static int m68328_console_cbaud = DEFAULT_CBAUD;
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */
-
static inline int serial_paranoia_check(struct m68k_serial *info,
char *name, const char *routine)
{
@@ -211,16 +199,16 @@ static void rs_stop(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "rs_stop"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
uart->ustcnt &= ~USTCNT_TXEN;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void rs_put_char(char ch)
{
int flags, loops = 0;
- save_flags(flags); cli();
+ local_irq_save(flags);
while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) {
loops++;
@@ -229,7 +217,7 @@ static void rs_put_char(char ch)
UTX_TXDATA = ch;
udelay(5);
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void rs_start(struct tty_struct *tty)
@@ -241,7 +229,7 @@ static void rs_start(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "rs_start"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) {
#ifdef USE_INTS
uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK;
@@ -249,7 +237,7 @@ static void rs_start(struct tty_struct *tty)
uart->ustcnt |= USTCNT_TXEN;
#endif
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
/* Drop into either the boot monitor or kadb upon receiving a break
@@ -327,14 +315,6 @@ static void receive_chars(struct m68k_serial *info, struct pt_regs *regs,
if(!tty)
goto clear_and_exit;
- /*
- * Make sure that we do not overflow the buffer
- */
- if (tty_request_buffer_room(tty, 1) == 0) {
- tty_schedule_flip(tty);
- return;
- }
-
flag = TTY_NORMAL;
if(rx & URX_PARITY_ERROR) {
@@ -473,7 +453,7 @@ static int startup(struct m68k_serial * info)
return -ENOMEM;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
/*
* Clear the FIFO buffers and disable them
@@ -506,7 +486,7 @@ static int startup(struct m68k_serial * info)
change_speed(info);
info->flags |= S_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -523,7 +503,7 @@ static void shutdown(struct m68k_serial * info)
if (!(info->flags & S_INITIALIZED))
return;
- save_flags(flags); cli(); /* Disable interrupts */
+ local_irq_save(flags);
if (info->xmit_buf) {
free_page((unsigned long) info->xmit_buf);
@@ -534,7 +514,7 @@ static void shutdown(struct m68k_serial * info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~S_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
}
struct {
@@ -655,24 +635,24 @@ static void rs_fair_output(void)
if (info == 0) return;
if (info->xmit_buf == 0) return;
- save_flags(flags); cli();
+ local_irq_save(flags);
left = info->xmit_cnt;
while (left != 0) {
c = info->xmit_buf[info->xmit_tail];
info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);
info->xmit_cnt--;
- restore_flags(flags);
+ local_irq_restore(flags);
rs_put_char(c);
- save_flags(flags); cli();
+ local_irq_save(flags);
left = min(info->xmit_cnt, left-1);
}
/* Last character is being transmitted now (hopefully). */
udelay(5);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -720,11 +700,11 @@ static void rs_flush_chars(struct tty_struct *tty)
#endif
/* Enable transmitter */
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
!info->xmit_buf) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -749,7 +729,7 @@ static void rs_flush_chars(struct tty_struct *tty)
while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5);
}
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
}
extern void console_printn(const char * b, int count);
@@ -768,18 +748,22 @@ static int rs_write(struct tty_struct * tty,
if (!tty || !info->xmit_buf)
return 0;
- save_flags(flags);
+ local_save_flags(flags);
while (1) {
- cli();
+ local_irq_disable();
c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
+ local_irq_restore(flags);
+
if (c <= 0)
break;
memcpy(info->xmit_buf + info->xmit_head, buf, c);
+
+ local_irq_disable();
info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
info->xmit_cnt += c;
- restore_flags(flags);
+ local_irq_restore(flags);
buf += c;
count -= c;
total += c;
@@ -787,7 +771,7 @@ static int rs_write(struct tty_struct * tty,
if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
/* Enable transmitter */
- cli();
+ local_irq_disable();
#ifndef USE_INTS
while(info->xmit_cnt) {
#endif
@@ -807,9 +791,9 @@ static int rs_write(struct tty_struct * tty,
#ifndef USE_INTS
}
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
}
- restore_flags(flags);
+
return total;
}
@@ -838,12 +822,13 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
static void rs_flush_buffer(struct tty_struct *tty)
{
struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
return;
- cli();
+ local_irq_save(flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- sti();
+ local_irq_restore(flags);
tty_wakeup(tty);
}
@@ -973,14 +958,15 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value)
m68328_uart *uart = &uart_addr[info->line];
#endif
unsigned char status;
+ unsigned long flags;
- cli();
+ local_irq_save(flags);
#ifdef CONFIG_SERIAL_68328_RTS_CTS
status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0;
#else
status = 0;
#endif
- sti();
+ local_irq_restore(flags);
put_user(status,value);
return 0;
}
@@ -994,14 +980,13 @@ static void send_break(struct m68k_serial * info, unsigned int duration)
unsigned long flags;
if (!info->port)
return;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
#ifdef USE_INTS
uart->utx.w |= UTX_SEND_BREAK;
msleep_interruptible(duration);
uart->utx.w &= ~UTX_SEND_BREAK;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
}
static int rs_ioctl(struct tty_struct *tty, struct file * file,
@@ -1060,7 +1045,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
(struct serial_struct *) arg);
case TIOCSERGETLSR: /* Get line status register */
if (access_ok(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int));
+ sizeof(unsigned int)))
return get_lsr_info(info, (unsigned int *) arg);
return -EFAULT;
case TIOCSERGSTRUCT:
@@ -1113,10 +1098,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (tty_hung_up_p(filp)) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -1138,7 +1123,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->count = 0;
}
if (info->count) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
info->flags |= S_CLOSING;
@@ -1186,7 +1171,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
}
info->flags &= ~(S_NORMAL_ACTIVE|S_CLOSING);
wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -1262,9 +1247,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
info->count--;
info->blocked_open++;
while (1) {
- cli();
+ local_irq_disable();
m68k_rtsdtr(info, 1);
- sti();
+ local_irq_enable();
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp) ||
!(info->flags & S_INITIALIZED)) {
@@ -1444,7 +1429,7 @@ rs68328_init(void)
return -ENOMEM;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
for(i=0;i<NR_PORTS;i++) {
@@ -1489,7 +1474,7 @@ rs68328_init(void)
serial_pm[i]->data = info;
#endif
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
diff --git a/drivers/serial/68328serial.h b/drivers/serial/68328serial.h
index 978f8a609f3..58aa2154655 100644
--- a/drivers/serial/68328serial.h
+++ b/drivers/serial/68328serial.h
@@ -11,7 +11,6 @@
#ifndef _MC683XX_SERIAL_H
#define _MC683XX_SERIAL_H
-#include <linux/config.h>
struct serial_struct {
int type;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 9843ae3d420..e80e70e9b12 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -20,7 +20,6 @@
* int rs_360_init(void);
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index bbf78aaf9e0..0995430e4cf 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -19,7 +19,6 @@
* mapbase is the physical address of the IO port.
* membase is an 'ioremapped' cookie.
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -49,7 +48,7 @@
/*
* Configuration:
- * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option
+ * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
* is unsafe when used on edge-triggered interrupts.
*/
static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
@@ -1401,7 +1400,7 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
static int serial_link_irq_chain(struct uart_8250_port *up)
{
struct irq_info *i = irq_lists + up->port.irq;
- int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
+ int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
spin_lock_irq(&i->lock);
@@ -2354,7 +2353,6 @@ int __init serial8250_start_console(struct uart_port *port, char *options)
static struct uart_driver serial8250_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 490606b8709..91bd28f2bb4 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -15,7 +15,6 @@
* $Id: 8250.h,v 1.8 2002/07/21 21:32:30 rmk Exp $
*/
-#include <linux/config.h>
#include <linux/serial_8250.h>
struct old_serial_port {
diff --git a/drivers/serial/8250_mca.c b/drivers/serial/8250_mca.c
index ac205256d5f..d10be944ad4 100644
--- a/drivers/serial/8250_mca.c
+++ b/drivers/serial/8250_mca.c
@@ -8,7 +8,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mca.h>
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 950560ff9b4..a1d322f8a16 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -594,8 +594,8 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
else
offset += idx * board->uart_offset;
- maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) /
- (8 << board->reg_shift);
+ maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
+ (board->reg_shift + 3);
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
return 1;
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index b79ed0665d5..632f62d6ec7 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -323,8 +323,10 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "USR9180", 0 },
/* U.S. Robotics 56K Voice INT PnP*/
{ "USR9190", 0 },
- /* HP Compaq Tablet PC tc1100 Wacom tablet */
+ /* Wacom tablets */
+ { "WACF004", 0 },
{ "WACF005", 0 },
+ { "WACF006", 0 },
/* Rockwell's (PORALiNK) 33600 INT PNP */
{ "WCI0003", 0 },
/* Unkown PnP modems */
@@ -429,6 +431,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
#endif
port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
+ port.flags |= UPF_SHARE_IRQ;
port.uartclk = 1843200;
port.dev = &dev->dev;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 5fff79e7127..5b48ac22c9c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -300,21 +300,22 @@ config SERIAL_AMBA_PL011_CONSOLE
kernel at boot time.)
config SERIAL_AT91
- bool "AT91RM9200 serial port support"
- depends on ARM && ARCH_AT91RM9200
+ bool "AT91RM9200 / AT91SAM9261 serial port support"
+ depends on ARM && (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
select SERIAL_CORE
help
- This enables the driver for the on-chip UARTs of the AT91RM9200
- processor.
+ This enables the driver for the on-chip UARTs of the Atmel
+ AT91RM9200 and AT91SAM926 processor.
config SERIAL_AT91_CONSOLE
- bool "Support for console on AT91RM9200 serial port"
+ bool "Support for console on AT91RM9200 / AT91SAM9261 serial port"
depends on SERIAL_AT91=y
select SERIAL_CORE_CONSOLE
help
- Say Y here if you wish to use a UART on the AT91RM9200 as the system
- console (the system console is the device which receives all kernel
- messages and warnings and which allows logins in single user mode).
+ Say Y here if you wish to use a UART on the Atmel AT91RM9200 or
+ AT91SAM9261 as the system console (the system console is the device
+ which receives all kernel messages and warnings and which allows
+ logins in single user mode).
config SERIAL_AT91_TTYAT
bool "Install as device ttyAT0-4 instead of ttyS0-4"
@@ -353,21 +354,24 @@ config SERIAL_CLPS711X_CONSOLE
kernel at boot time.)
config SERIAL_S3C2410
- tristate "Samsung S3C2410 Serial port support"
+ tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support"
depends on ARM && ARCH_S3C2410
select SERIAL_CORE
help
- Support for the on-chip UARTs on the Samsung S3C2410X CPU,
+ Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
providing /dev/ttySAC0, 1 and 2 (note, some machines may not
provide all of these ports, depending on how the serial port
pins are configured.
+ Currently this driver supports the UARTS on the S3C2410, S3C2440,
+ S3C2442, S3C2412 and S3C2413 CPUs.
+
config SERIAL_S3C2410_CONSOLE
bool "Support for console on S3C2410 serial port"
depends on SERIAL_S3C2410=y
select SERIAL_CORE_CONSOLE
help
- Allow selection of the S3C2410 on-board serial ports for use as
+ Allow selection of the S3C24XX on-board serial ports for use as
an virtual console.
Even if you say Y here, the currently visible virtual console
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index e920d196d0b..7311d8487c9 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -31,7 +31,6 @@
* required, these have to be supplied via some other means (eg, GPIO)
* and hooked into this driver.
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 3d966cfc9a3..a8d7124e84a 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -31,7 +31,6 @@
* required, these have to be supplied via some other means (eg, GPIO)
* and hooked into this driver.
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
index 6547fe0cef9..a7d664383da 100644
--- a/drivers/serial/at91_serial.c
+++ b/drivers/serial/at91_serial.c
@@ -2,7 +2,6 @@
* linux/drivers/char/at91_serial.c
*
* Driver for Atmel AT91RM9200 Serial ports
- *
* Copyright (C) 2003 Rick Bronson
*
* Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
@@ -23,24 +22,25 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/serial.h>
+#include <linux/clk.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/tty_flip.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/arch/at91rm9200_usart.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/at91rm9200_pdc.h>
+#include <asm/mach/serial_at91.h>
#include <asm/arch/board.h>
-#include <asm/arch/pio.h>
-
+#include <asm/arch/system.h>
#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -67,7 +67,6 @@
#endif
-#define AT91_VA_BASE_DBGU ((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU)
#define AT91_ISR_PASS_LIMIT 256
#define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR)
@@ -87,16 +86,33 @@
/* PDC registers */
#define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR)
+#define UART_GET_PTSR(port) readl((port)->membase + AT91_PDC_PTSR)
+
#define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR)
+#define UART_GET_RPR(port) readl((port)->membase + AT91_PDC_RPR)
#define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR)
-#define UART_GET_RCR(port) readl((port)->membase + AT91_PDC_RCR)
#define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR)
#define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR)
+#define UART_PUT_TPR(port,v) writel(v, (port)->membase + AT91_PDC_TPR)
+#define UART_PUT_TCR(port,v) writel(v, (port)->membase + AT91_PDC_TCR)
+//#define UART_PUT_TNPR(port,v) writel(v, (port)->membase + AT91_PDC_TNPR)
+//#define UART_PUT_TNCR(port,v) writel(v, (port)->membase + AT91_PDC_TNCR)
static int (*at91_open)(struct uart_port *);
static void (*at91_close)(struct uart_port *);
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct at91_uart_port {
+ struct uart_port uart; /* uart */
+ struct clk *clk; /* uart clock */
+ unsigned short suspended; /* is port suspended? */
+};
+
+static struct at91_uart_port at91_ports[AT91_NR_UART];
+
#ifdef SUPPORT_SYSRQ
static struct console at91_console;
#endif
@@ -115,16 +131,19 @@ static u_int at91_tx_empty(struct uart_port *port)
static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
{
unsigned int control = 0;
+ unsigned int mode;
- /*
- * Errata #39: RTS0 is not internally connected to PA21. We need to drive
- * the pin manually.
- */
- if (port->mapbase == AT91_VA_BASE_US0) {
- if (mctrl & TIOCM_RTS)
- at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0);
- else
- at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
+ if (arch_identify() == ARCH_ID_AT91RM9200) {
+ /*
+ * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21.
+ * We need to drive the pin manually.
+ */
+ if (port->mapbase == AT91_BASE_US0) {
+ if (mctrl & TIOCM_RTS)
+ at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0);
+ else
+ at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
+ }
}
if (mctrl & TIOCM_RTS)
@@ -137,7 +156,15 @@ static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
else
control |= AT91_US_DTRDIS;
- UART_PUT_CR(port,control);
+ UART_PUT_CR(port, control);
+
+ /* Local loopback mode? */
+ mode = UART_GET_MR(port) & ~AT91_US_CHMODE;
+ if (mctrl & TIOCM_LOOP)
+ mode |= AT91_US_CHMODE_LOC_LOOP;
+ else
+ mode |= AT91_US_CHMODE_NORMAL;
+ UART_PUT_MR(port, mode);
}
/*
@@ -169,8 +196,9 @@ static u_int at91_get_mctrl(struct uart_port *port)
*/
static void at91_stop_tx(struct uart_port *port)
{
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
UART_PUT_IDR(port, AT91_US_TXRDY);
- port->read_status_mask &= ~AT91_US_TXRDY;
}
/*
@@ -178,7 +206,8 @@ static void at91_stop_tx(struct uart_port *port)
*/
static void at91_start_tx(struct uart_port *port)
{
- port->read_status_mask |= AT91_US_TXRDY;
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
UART_PUT_IER(port, AT91_US_TXRDY);
}
@@ -187,6 +216,8 @@ static void at91_start_tx(struct uart_port *port)
*/
static void at91_stop_rx(struct uart_port *port)
{
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
UART_PUT_IDR(port, AT91_US_RXRDY);
}
@@ -195,7 +226,6 @@ static void at91_stop_rx(struct uart_port *port)
*/
static void at91_enable_ms(struct uart_port *port)
{
- port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
}
@@ -218,8 +248,8 @@ static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
struct tty_struct *tty = port->info->tty;
unsigned int status, ch, flg;
- status = UART_GET_CSR(port) & port->read_status_mask;
- while (status & (AT91_US_RXRDY)) {
+ status = UART_GET_CSR(port);
+ while (status & AT91_US_RXRDY) {
ch = UART_GET_CHAR(port);
port->icount.rx++;
@@ -230,40 +260,38 @@ static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
* note that the error handling code is
* out of the main execution path
*/
- if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) {
+ if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE | AT91_US_RXBRK))) {
UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */
- if (status & (AT91_US_PARE))
+ if (status & AT91_US_RXBRK) {
+ status &= ~(AT91_US_PARE | AT91_US_FRAME); /* ignore side-effect */
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ goto ignore_char;
+ }
+ if (status & AT91_US_PARE)
port->icount.parity++;
- if (status & (AT91_US_FRAME))
+ if (status & AT91_US_FRAME)
port->icount.frame++;
- if (status & (AT91_US_OVRE))
+ if (status & AT91_US_OVRE)
port->icount.overrun++;
- if (status & AT91_US_PARE)
+ status &= port->read_status_mask;
+
+ if (status & AT91_US_RXBRK)
+ flg = TTY_BREAK;
+ else if (status & AT91_US_PARE)
flg = TTY_PARITY;
else if (status & AT91_US_FRAME)
flg = TTY_FRAME;
- if (status & AT91_US_OVRE) {
- /*
- * overrun does *not* affect the character
- * we read from the FIFO
- */
- tty_insert_flip_char(tty, ch, flg);
- ch = 0;
- flg = TTY_OVERRUN;
- }
-#ifdef SUPPORT_SYSRQ
- port->sysrq = 0;
-#endif
}
if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char;
- tty_insert_flip_char(tty, ch, flg);
+ uart_insert_char(port, status, AT91_US_OVRE, ch, flg);
ignore_char:
- status = UART_GET_CSR(port) & port->read_status_mask;
+ status = UART_GET_CSR(port);
}
tty_flip_buffer_push(tty);
@@ -308,40 +336,35 @@ static void at91_tx_chars(struct uart_port *port)
static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct uart_port *port = dev_id;
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
unsigned int status, pending, pass_counter = 0;
status = UART_GET_CSR(port);
- pending = status & port->read_status_mask;
- if (pending) {
- do {
- if (pending & AT91_US_RXRDY)
- at91_rx_chars(port, regs);
-
- /* Clear the relevent break bits */
- if (pending & AT91_US_RXBRK) {
- UART_PUT_CR(port, AT91_US_RSTSTA);
- port->icount.brk++;
- uart_handle_break(port);
- }
+ pending = status & UART_GET_IMR(port);
+ while (pending) {
+ /* Interrupt receive */
+ if (pending & AT91_US_RXRDY)
+ at91_rx_chars(port, regs);
+
+ // TODO: All reads to CSR will clear these interrupts!
+ if (pending & AT91_US_RIIC) port->icount.rng++;
+ if (pending & AT91_US_DSRIC) port->icount.dsr++;
+ if (pending & AT91_US_DCDIC)
+ uart_handle_dcd_change(port, !(status & AT91_US_DCD));
+ if (pending & AT91_US_CTSIC)
+ uart_handle_cts_change(port, !(status & AT91_US_CTS));
+ if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC))
+ wake_up_interruptible(&port->info->delta_msr_wait);
+
+ /* Interrupt transmit */
+ if (pending & AT91_US_TXRDY)
+ at91_tx_chars(port);
+
+ if (pass_counter++ > AT91_ISR_PASS_LIMIT)
+ break;
- // TODO: All reads to CSR will clear these interrupts!
- if (pending & AT91_US_RIIC) port->icount.rng++;
- if (pending & AT91_US_DSRIC) port->icount.dsr++;
- if (pending & AT91_US_DCDIC)
- uart_handle_dcd_change(port, !(status & AT91_US_DCD));
- if (pending & AT91_US_CTSIC)
- uart_handle_cts_change(port, !(status & AT91_US_CTS));
- if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC))
- wake_up_interruptible(&port->info->delta_msr_wait);
-
- if (pending & AT91_US_TXRDY)
- at91_tx_chars(port);
- if (pass_counter++ > AT91_ISR_PASS_LIMIT)
- break;
-
- status = UART_GET_CSR(port);
- pending = status & port->read_status_mask;
- } while (pending);
+ status = UART_GET_CSR(port);
+ pending = status & UART_GET_IMR(port);
}
return IRQ_HANDLED;
}
@@ -351,6 +374,7 @@ static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
static int at91_startup(struct uart_port *port)
{
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
int retval;
/*
@@ -363,7 +387,7 @@ static int at91_startup(struct uart_port *port)
/*
* Allocate the IRQ
*/
- retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port);
+ retval = request_irq(port->irq, at91_interrupt, IRQF_SHARED, "at91_serial", port);
if (retval) {
printk("at91_serial: at91_startup - Can't get irq\n");
return retval;
@@ -381,14 +405,14 @@ static int at91_startup(struct uart_port *port)
}
}
- port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE
- | AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK;
/*
* Finally, enable the serial port
*/
UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */
- UART_PUT_IER(port, AT91_US_RXRDY); /* do receive only */
+
+ UART_PUT_IER(port, AT91_US_RXRDY); /* enable receive only */
+
return 0;
}
@@ -397,6 +421,8 @@ static int at91_startup(struct uart_port *port)
*/
static void at91_shutdown(struct uart_port *port)
{
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
/*
* Disable all interrupts, port and break condition.
*/
@@ -421,21 +447,22 @@ static void at91_shutdown(struct uart_port *port)
*/
static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
{
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
switch (state) {
case 0:
/*
* Enable the peripheral clock for this serial port.
* This is called on uart_open() or a resume event.
*/
- at91_sys_write(AT91_PMC_PCER, 1 << port->irq);
+ clk_enable(at91_port->clk);
break;
case 3:
/*
* Disable the peripheral clock for this serial port.
* This is called on uart_close() or a suspend event.
*/
- if (port->irq != AT91_ID_SYS) /* is this a shared clock? */
- at91_sys_write(AT91_PMC_PCDR, 1 << port->irq);
+ clk_disable(at91_port->clk);
break;
default:
printk(KERN_ERR "at91_serial: unknown pm %d\n", state);
@@ -494,9 +521,9 @@ static void at91_set_termios(struct uart_port *port, struct termios * termios, s
spin_lock_irqsave(&port->lock, flags);
- port->read_status_mask |= AT91_US_OVRE;
+ port->read_status_mask = AT91_US_OVRE;
if (termios->c_iflag & INPCK)
- port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE;
+ port->read_status_mask |= (AT91_US_FRAME | AT91_US_PARE);
if (termios->c_iflag & (BRKINT | PARMRK))
port->read_status_mask |= AT91_US_RXBRK;
@@ -552,7 +579,7 @@ static void at91_set_termios(struct uart_port *port, struct termios * termios, s
*/
static const char *at91_type(struct uart_port *port)
{
- return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL;
+ return (port->type == PORT_AT91) ? "AT91_SERIAL" : NULL;
}
/*
@@ -560,8 +587,15 @@ static const char *at91_type(struct uart_port *port)
*/
static void at91_release_port(struct uart_port *port)
{
- release_mem_region(port->mapbase,
- (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K);
+ struct platform_device *pdev = to_platform_device(port->dev);
+ int size = pdev->resource[0].end - pdev->resource[0].start + 1;
+
+ release_mem_region(port->mapbase, size);
+
+ if (port->flags & UPF_IOREMAP) {
+ iounmap(port->membase);
+ port->membase = NULL;
+ }
}
/*
@@ -569,10 +603,21 @@ static void at91_release_port(struct uart_port *port)
*/
static int at91_request_port(struct uart_port *port)
{
- return request_mem_region(port->mapbase,
- (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K,
- "at91_serial") != NULL ? 0 : -EBUSY;
+ struct platform_device *pdev = to_platform_device(port->dev);
+ int size = pdev->resource[0].end - pdev->resource[0].start + 1;
+
+ if (!request_mem_region(port->mapbase, size, "at91_serial"))
+ return -EBUSY;
+
+ if (port->flags & UPF_IOREMAP) {
+ port->membase = ioremap(port->mapbase, size);
+ if (port->membase == NULL) {
+ release_mem_region(port->mapbase, size);
+ return -ENOMEM;
+ }
+ }
+ return 0;
}
/*
@@ -581,7 +626,7 @@ static int at91_request_port(struct uart_port *port)
static void at91_config_port(struct uart_port *port, int flags)
{
if (flags & UART_CONFIG_TYPE) {
- port->type = PORT_AT91RM9200;
+ port->type = PORT_AT91;
at91_request_port(port);
}
}
@@ -592,7 +637,7 @@ static void at91_config_port(struct uart_port *port, int flags)
static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
{
int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91)
ret = -EINVAL;
if (port->irq != ser->irq)
ret = -EINVAL;
@@ -624,33 +669,47 @@ static struct uart_ops at91_pops = {
.type = at91_type,
.release_port = at91_release_port,
.request_port = at91_request_port,
- .config_port = at91_config_port,
- .verify_port = at91_verify_port,
+ .config_port = at91_config_port,
+ .verify_port = at91_verify_port,
.pm = at91_serial_pm,
};
-static struct uart_port at91_ports[AT91_NR_UART];
-
-void __init at91_init_ports(void)
+/*
+ * Configure the port from the platform device resource info.
+ */
+static void __devinit at91_init_port(struct at91_uart_port *at91_port, struct platform_device *pdev)
{
- static int first = 1;
- int i;
-
- if (!first)
- return;
- first = 0;
+ struct uart_port *port = &at91_port->uart;
+ struct at91_uart_data *data = pdev->dev.platform_data;
+
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->ops = &at91_pops;
+ port->fifosize = 1;
+ port->line = pdev->id;
+ port->dev = &pdev->dev;
+
+ port->mapbase = pdev->resource[0].start;
+ port->irq = pdev->resource[1].start;
+
+ if (port->mapbase == AT91_VA_BASE_SYS + AT91_DBGU) /* Part of system perpherals - already mapped */
+ port->membase = (void __iomem *) port->mapbase;
+ else {
+ port->flags |= UPF_IOREMAP;
+ port->membase = NULL;
+ }
- for (i = 0; i < AT91_NR_UART; i++) {
- at91_ports[i].iotype = UPIO_MEM;
- at91_ports[i].flags = UPF_BOOT_AUTOCONF;
- at91_ports[i].uartclk = at91_master_clock;
- at91_ports[i].ops = &at91_pops;
- at91_ports[i].fifosize = 1;
- at91_ports[i].line = i;
- }
+ if (!at91_port->clk) { /* for console, the clock could already be configured */
+ at91_port->clk = clk_get(&pdev->dev, "usart");
+ clk_enable(at91_port->clk);
+ port->uartclk = clk_get_rate(at91_port->clk);
+ }
}
-void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
+/*
+ * Register board-specific modem-control line handlers.
+ */
+void __init at91_register_uart_fns(struct at91_port_fns *fns)
{
if (fns->enable_ms)
at91_pops.enable_ms = fns->enable_ms;
@@ -664,51 +723,6 @@ void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
at91_pops.set_wake = fns->set_wake;
}
-/*
- * Setup ports.
- */
-void __init at91_register_uart(int idx, int port)
-{
- if ((idx < 0) || (idx >= AT91_NR_UART)) {
- printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
- return;
- }
-
- switch (port) {
- case 0:
- at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0;
- at91_ports[idx].mapbase = AT91_VA_BASE_US0;
- at91_ports[idx].irq = AT91_ID_US0;
- AT91_CfgPIO_USART0();
- break;
- case 1:
- at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1;
- at91_ports[idx].mapbase = AT91_VA_BASE_US1;
- at91_ports[idx].irq = AT91_ID_US1;
- AT91_CfgPIO_USART1();
- break;
- case 2:
- at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2;
- at91_ports[idx].mapbase = AT91_VA_BASE_US2;
- at91_ports[idx].irq = AT91_ID_US2;
- AT91_CfgPIO_USART2();
- break;
- case 3:
- at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3;
- at91_ports[idx].mapbase = AT91_VA_BASE_US3;
- at91_ports[idx].irq = AT91_ID_US3;
- AT91_CfgPIO_USART3();
- break;
- case 4:
- at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU;
- at91_ports[idx].mapbase = AT91_VA_BASE_DBGU;
- at91_ports[idx].irq = AT91_ID_SYS;
- AT91_CfgPIO_DBGU();
- break;
- default:
- printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port);
- }
-}
#ifdef CONFIG_SERIAL_AT91_CONSOLE
static void at91_console_putchar(struct uart_port *port, int ch)
@@ -723,7 +737,7 @@ static void at91_console_putchar(struct uart_port *port, int ch)
*/
static void at91_console_write(struct console *co, const char *s, u_int count)
{
- struct uart_port *port = at91_ports + co->index;
+ struct uart_port *port = &at91_ports[co->index].uart;
unsigned int status, imr;
/*
@@ -778,23 +792,15 @@ static void __init at91_console_get_options(struct uart_port *port, int *baud, i
static int __init at91_console_setup(struct console *co, char *options)
{
- struct uart_port *port;
+ struct uart_port *port = &at91_ports[co->index].uart;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- port = uart_get_console(at91_ports, AT91_NR_UART, co);
+ if (port->membase == 0) /* Port not initialized yet - delay setup */
+ return -ENODEV;
- /*
- * Enable the serial console, in-case bootloader did not do it.
- */
- at91_sys_write(AT91_PMC_PCER, 1 << port->irq); /* enable clock */
UART_PUT_IDR(port, -1); /* disable interrupts */
UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN);
@@ -821,58 +827,147 @@ static struct console at91_console = {
#define AT91_CONSOLE_DEVICE &at91_console
-static int __init at91_console_init(void)
+/*
+ * Early console initialization (before VM subsystem initialized).
+ */
+static int __init at91_console_init(void)
{
- at91_init_ports();
+ if (at91_default_console_device) {
+ add_preferred_console(AT91_DEVICENAME, at91_default_console_device->id, NULL);
+ at91_init_port(&(at91_ports[at91_default_console_device->id]), at91_default_console_device);
+ register_console(&at91_console);
+ }
- at91_console.index = at91_console_port;
- register_console(&at91_console);
return 0;
}
console_initcall(at91_console_init);
+/*
+ * Late console initialization.
+ */
+static int __init at91_late_console_init(void)
+{
+ if (at91_default_console_device && !(at91_console.flags & CON_ENABLED))
+ register_console(&at91_console);
+
+ return 0;
+}
+core_initcall(at91_late_console_init);
+
#else
#define AT91_CONSOLE_DEVICE NULL
#endif
static struct uart_driver at91_uart = {
.owner = THIS_MODULE,
- .driver_name = AT91_DEVICENAME,
+ .driver_name = "at91_serial",
.dev_name = AT91_DEVICENAME,
- .devfs_name = AT91_DEVICENAME,
.major = SERIAL_AT91_MAJOR,
.minor = MINOR_START,
.nr = AT91_NR_UART,
.cons = AT91_CONSOLE_DEVICE,
};
-static int __init at91_serial_init(void)
+#ifdef CONFIG_PM
+static int at91_serial_suspend(struct platform_device *pdev, pm_message_t state)
{
- int ret, i;
+ struct uart_port *port = platform_get_drvdata(pdev);
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
+ if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
+ enable_irq_wake(port->irq);
+ else {
+ disable_irq_wake(port->irq);
+ uart_suspend_port(&at91_uart, port);
+ at91_port->suspended = 1;
+ }
- at91_init_ports();
+ return 0;
+}
- ret = uart_register_driver(&at91_uart);
- if (ret)
- return ret;
+static int at91_serial_resume(struct platform_device *pdev)
+{
+ struct uart_port *port = platform_get_drvdata(pdev);
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
- for (i = 0; i < AT91_NR_UART; i++) {
- if (at91_serial_map[i] >= 0)
- uart_add_one_port(&at91_uart, &at91_ports[i]);
+ if (at91_port->suspended) {
+ uart_resume_port(&at91_uart, port);
+ at91_port->suspended = 0;
}
return 0;
}
+#else
+#define at91_serial_suspend NULL
+#define at91_serial_resume NULL
+#endif
-static void __exit at91_serial_exit(void)
+static int __devinit at91_serial_probe(struct platform_device *pdev)
{
- int i;
+ struct at91_uart_port *port;
+ int ret;
- for (i = 0; i < AT91_NR_UART; i++) {
- if (at91_serial_map[i] >= 0)
- uart_remove_one_port(&at91_uart, &at91_ports[i]);
- }
+ port = &at91_ports[pdev->id];
+ at91_init_port(port, pdev);
+ ret = uart_add_one_port(&at91_uart, &port->uart);
+ if (!ret) {
+ device_init_wakeup(&pdev->dev, 1);
+ platform_set_drvdata(pdev, port);
+ }
+
+ return ret;
+}
+
+static int __devexit at91_serial_remove(struct platform_device *pdev)
+{
+ struct uart_port *port = platform_get_drvdata(pdev);
+ struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+ int ret = 0;
+
+ clk_disable(at91_port->clk);
+ clk_put(at91_port->clk);
+
+ device_init_wakeup(&pdev->dev, 0);
+ platform_set_drvdata(pdev, NULL);
+
+ if (port) {
+ ret = uart_remove_one_port(&at91_uart, port);
+ kfree(port);
+ }
+
+ return ret;
+}
+
+static struct platform_driver at91_serial_driver = {
+ .probe = at91_serial_probe,
+ .remove = __devexit_p(at91_serial_remove),
+ .suspend = at91_serial_suspend,
+ .resume = at91_serial_resume,
+ .driver = {
+ .name = "at91_usart",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91_serial_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&at91_uart);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&at91_serial_driver);
+ if (ret)
+ uart_unregister_driver(&at91_uart);
+
+ return ret;
+}
+
+static void __exit at91_serial_exit(void)
+{
+ platform_driver_unregister(&at91_serial_driver);
uart_unregister_driver(&at91_uart);
}
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 2691112c84a..f27d852ce50 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -25,7 +25,6 @@
* $Id: clps711x.c,v 1.42 2002/07/28 10:03:28 rmk Exp $
*
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 5cba59ad7dc..90ff96e3339 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -31,7 +31,6 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 17406a05ce1..95afc37297a 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -27,7 +27,6 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index cdba128250a..ef3bb476c43 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -27,7 +27,6 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 89700141f87..cabd048c863 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -415,7 +415,7 @@
* Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when
* closing the last filehandle, NASTY!.
* Added break generation, not tested though!
- * Use SA_SHIRQ when request_irq() for ser2 and ser3 (shared with) par0 and par1.
+ * Use IRQF_SHARED when request_irq() for ser2 and ser3 (shared with) par0 and par1.
* You can't use them at the same time (yet..), but you can hopefully switch
* between ser2/par0, ser3/par1 with the same kernel config.
* Replaced some magic constants with defines
@@ -425,7 +425,6 @@
static char *serial_version = "$Revision: 1.25 $";
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -2573,12 +2572,6 @@ static void flush_to_flip_buffer(struct e100_serial *info)
DFLIP(
if (1) {
-
- if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
- DEBUG_LOG(info->line, "*** TTY_DONT_FLIP set flip.count %i ***\n", tty->flip.count);
- DEBUG_LOG(info->line, "*** recv_cnt %i\n", info->recv_cnt);
- } else {
- }
DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx);
DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty));
DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty));
@@ -4884,7 +4877,7 @@ rs_init(void)
driver->init_termios = tty_std_termios;
driver->init_termios.c_cflag =
B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
- driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+ driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
driver->termios = serial_termios;
driver->termios_locked = serial_termios_locked;
@@ -4949,55 +4942,55 @@ rs_init(void)
/* Not needed in simulator. May only complicate stuff. */
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
- if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial ", NULL))
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial ", NULL))
panic("irq8");
#ifdef CONFIG_ETRAX_SERIAL_PORT0
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
- if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 0 dma tr", NULL))
+ if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 0 dma tr", NULL))
panic("irq22");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
- if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 0 dma rec", NULL))
+ if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 0 dma rec", NULL))
panic("irq23");
#endif
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT1
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
- if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL))
+ if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 1 dma tr", NULL))
panic("irq24");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
- if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL))
+ if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 1 dma rec", NULL))
panic("irq25");
#endif
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT2
/* DMA Shared with par0 (and SCSI0 and ATA) */
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
- if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 2 dma tr", NULL))
+ if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma tr", NULL))
panic("irq18");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
- if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 2 dma rec", NULL))
+ if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma rec", NULL))
panic("irq19");
#endif
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT3
/* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
- if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 3 dma tr", NULL))
+ if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma tr", NULL))
panic("irq20");
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
- if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, SA_SHIRQ | SA_INTERRUPT, "serial 3 dma rec", NULL))
+ if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma rec", NULL))
panic("irq21");
#endif
#endif
#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ | SA_INTERRUPT,
+ if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, IRQF_SHARED | IRQF_DISABLED,
"fast serial dma timeout", NULL)) {
printk(KERN_CRIT "err: timer1 irq\n");
}
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h
index 1800c0e7531..f30b93d6ef7 100644
--- a/drivers/serial/crisv10.h
+++ b/drivers/serial/crisv10.h
@@ -7,7 +7,6 @@
#ifndef _ETRAX_SERIAL_H
#define _ETRAX_SERIAL_H
-#include <linux/config.h>
#include <linux/circ_buf.h>
#include <asm/termios.h>
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index bf71bad5c34..d119c8296a7 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -26,7 +26,6 @@
#undef DEBUG_DZ
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -768,11 +767,7 @@ void __init dz_serial_console_init(void)
static struct uart_driver dz_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
-#ifdef CONFIG_DEVFS
- .dev_name = "tts/%d",
-#else
.dev_name = "ttyS%d",
-#endif
.major = TTY_MAJOR,
.minor = 64,
.nr = DZ_NB_PORT,
@@ -802,7 +797,7 @@ int __init dz_init(void)
restore_flags(flags);
if (request_irq(dz_ports[0].port.irq, dz_interrupt,
- SA_INTERRUPT, "DZ", &dz_ports[0]))
+ IRQF_DISABLED, "DZ", &dz_ports[0]))
panic("Unable to register DZ interrupt");
ret = uart_register_driver(&dz_reg);
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 144a7a352b2..a3c00a25214 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -24,7 +24,6 @@
*/
#define SERIAL_DO_RESTART
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -1564,7 +1563,7 @@ static int __devinit icom_probe(struct pci_dev *dev,
/* save off irq and request irq line */
if ( (retval = request_irq(dev->irq, icom_interrupt,
- SA_INTERRUPT | SA_SHIRQ, ICOM_DRIVER_NAME,
+ IRQF_DISABLED | IRQF_SHARED, ICOM_DRIVER_NAME,
(void *) icom_adapter))) {
goto probe_exit2;
}
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index d202eb4f384..4a142d6b8f3 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -25,7 +25,6 @@
* [29-Mar-2005] Mike Lee
* Added hardware handshake
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -405,7 +404,7 @@ static int imx_startup(struct uart_port *port)
if (retval) goto error_out2;
retval = request_irq(sport->rtsirq, imx_rtsint,
- SA_TRIGGER_FALLING | SA_TRIGGER_RISING,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
DRIVER_NAME, sport);
if (retval) goto error_out3;
@@ -888,7 +887,6 @@ static struct uart_driver imx_reg = {
.owner = THIS_MODULE,
.driver_name = DRIVER_NAME,
.dev_name = "ttySMX",
- .devfs_name = "ttsmx/",
.major = SERIAL_IMX_MAJOR,
.minor = MINOR_START,
.nr = ARRAY_SIZE(imx_ports),
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index c620209d7b9..576ca1eaa2b 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -2646,7 +2646,10 @@ static int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
struct ioc4_port *port;
struct ioc4_soft *soft;
+ /* If serial driver did not attach, don't try to detach */
control = idd->idd_serial_data;
+ if (!control)
+ return 0;
for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
for (port_type = UART_PORT_MIN;
@@ -2778,6 +2781,12 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev,
idd->idd_pci_id));
+ /* PCI-RT does not bring out serial connections.
+ * Do not attach to this particular IOC4.
+ */
+ if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
+ return 0;
+
/* request serial registers */
tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
@@ -2846,7 +2855,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
control->ic_soft = soft;
/* Hook up interrupt handler */
- if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ,
+ if (!request_irq(idd->idd_pdev->irq, ioc4_intr, IRQF_SHARED,
"sgi-ioc4serial", soft)) {
control->ic_irq = idd->idd_pdev->irq;
} else {
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index 651772474ac..342042889f6 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -12,7 +12,6 @@
* Copyright (C) 2002 Ralf Baechle (ralf@linux-mips.org)
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -1085,7 +1084,6 @@ static struct console ip22zilog_console = {
static struct uart_driver ip22zilog_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index b3e1f71be4d..244f63be3a0 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -121,7 +121,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
rc = request_irq(brd->irq, brd->bd_ops->intr,
- SA_INTERRUPT|SA_SHIRQ, "JSM", brd);
+ IRQF_DISABLED|IRQF_SHARED, "JSM", brd);
if (rc) {
printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq);
goto out_iounmap;
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 7d823705193..f8262e6ad8d 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -589,13 +589,6 @@ void jsm_input(struct jsm_channel *ch)
ld = tty_ldisc_ref(tp);
/*
- * If the DONT_FLIP flag is on, don't flush our buffer, and act
- * like the ld doesn't have any space to put the data right now.
- */
- if (test_bit(TTY_DONT_FLIP, &tp->flags))
- len = 0;
-
- /*
* If we were unable to get a reference to the ld,
* don't flush our buffer, and act like the ld doesn't
* have any space to put the data right now.
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 321a40f33b5..e7fe4bb46ec 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -25,7 +25,6 @@
* membase is an 'ioremapped' cookie. This is compatible with the old
* serial.c driver, and is currently the preferred form.
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_M32R_SIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -543,7 +542,7 @@ static void serial_do_unlink(struct irq_info *i, struct uart_sio_port *up)
static int serial_link_irq_chain(struct uart_sio_port *up)
{
struct irq_info *i = irq_lists + up->port.irq;
- int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
+ int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
spin_lock_irq(&i->lock);
@@ -1131,7 +1130,6 @@ console_initcall(m32r_sio_console_init);
static struct uart_driver m32r_sio_reg = {
.owner = THIS_MODULE,
.driver_name = "sio",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h
index 7c3ec24f7e5..849f1b2c253 100644
--- a/drivers/serial/m32r_sio.h
+++ b/drivers/serial/m32r_sio.h
@@ -15,7 +15,6 @@
* (at your option) any later version.
*/
-#include <linux/config.h>
struct m32r_sio_probe {
struct module *owner;
diff --git a/drivers/serial/m32r_sio_reg.h b/drivers/serial/m32r_sio_reg.h
index 9c864529451..4671473793e 100644
--- a/drivers/serial/m32r_sio_reg.h
+++ b/drivers/serial/m32r_sio_reg.h
@@ -15,7 +15,6 @@
#ifndef _M32R_SIO_REG_H
#define _M32R_SIO_REG_H
-#include <linux/config.h>
#ifdef CONFIG_SERIAL_M32R_PLDSIO
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 8cbbb954df2..832abd3c470 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -60,11 +60,11 @@ struct timer_list mcfrs_timer_struct;
#if defined(CONFIG_HW_FEITH)
#define CONSOLE_BAUD_RATE 38400
#define DEFAULT_CBAUD B38400
-#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
+#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || defined(CONFIG_M5329EVB)
#define CONSOLE_BAUD_RATE 115200
#define DEFAULT_CBAUD B115200
#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
- defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
+ defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET)
#define CONSOLE_BAUD_RATE 19200
#define DEFAULT_CBAUD B19200
#endif
@@ -93,7 +93,7 @@ static struct tty_driver *mcfrs_serial_driver;
#undef SERIAL_DEBUG_FLOW
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x)
+ defined(CONFIG_M520x) || defined(CONFIG_M532x)
#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
#else
#define IRQBASE 73
@@ -1545,6 +1545,28 @@ static void mcfrs_irqinit(struct mcf_serial *info)
*feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2
| MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
}
+#elif defined(CONFIG_M532x)
+ volatile unsigned char *uartp;
+ uartp = info->addr;
+ switch (info->line) {
+ case 0:
+ MCF_INTC0_ICR26 = 0x3;
+ MCF_INTC0_CIMR = 26;
+ /* GPIO initialization */
+ MCF_GPIO_PAR_UART |= 0x000F;
+ break;
+ case 1:
+ MCF_INTC0_ICR27 = 0x3;
+ MCF_INTC0_CIMR = 27;
+ /* GPIO initialization */
+ MCF_GPIO_PAR_UART |= 0x0FF0;
+ break;
+ case 2:
+ MCF_INTC0_ICR28 = 0x3;
+ MCF_INTC0_CIMR = 28;
+ /* GPIOs also must be initalized, depends on board */
+ break;
+ }
#else
volatile unsigned char *icrp, *uartp;
@@ -1574,7 +1596,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
/* Clear mask, so no surprise interrupts. */
uartp[MCFUART_UIMR] = 0;
- if (request_irq(info->irq, mcfrs_interrupt, SA_INTERRUPT,
+ if (request_irq(info->irq, mcfrs_interrupt, IRQF_DISABLED,
"ColdFire UART", NULL)) {
printk("MCFRS: Unable to attach ColdFire UART %d interrupt "
"vector=%d\n", info->line, info->irq);
@@ -1691,7 +1713,6 @@ mcfrs_init(void)
/* Initialize the tty_driver structure */
mcfrs_serial_driver->owner = THIS_MODULE;
mcfrs_serial_driver->name = "ttyS";
- mcfrs_serial_driver->devfs_name = "ttys/";
mcfrs_serial_driver->driver_name = "serial";
mcfrs_serial_driver->major = TTY_MAJOR;
mcfrs_serial_driver->minor_start = 64;
diff --git a/drivers/serial/mcfserial.h b/drivers/serial/mcfserial.h
index a2b28e8629f..56420e2cb11 100644
--- a/drivers/serial/mcfserial.h
+++ b/drivers/serial/mcfserial.h
@@ -14,7 +14,6 @@
#ifndef _MCF_SERIAL_H
#define _MCF_SERIAL_H
-#include <linux/config.h>
#include <linux/serial.h>
#ifdef __KERNEL__
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 1b2cdc91c22..7708e5dd365 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -44,7 +44,6 @@
* will be mapped to.
*/
-#include <linux/config.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/tty.h>
@@ -191,7 +190,7 @@ mpc52xx_uart_startup(struct uart_port *port)
/* Request IRQ */
ret = request_irq(port->irq, mpc52xx_uart_int,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
if (ret)
return ret;
@@ -693,7 +692,6 @@ static struct uart_driver mpc52xx_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "mpc52xx_psc_uart",
.dev_name = "ttyPSC",
- .devfs_name = "ttyPSC",
.major = SERIAL_PSC_MAJOR,
.minor = SERIAL_PSC_MINOR,
.nr = MPC52xx_PSC_MAXNUM,
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 94681922ea0..63d2a66e563 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -50,7 +50,6 @@
* 4) AFAICT, hardware flow control isn't supported by the controller --MAG.
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -315,7 +314,6 @@ struct mpsc_port_info *mpsc_device_remove(int index);
#define MPSC_MAJOR 204
#define MPSC_MINOR_START 44
#define MPSC_DRIVER_NAME "MPSC"
-#define MPSC_DEVFS_NAME "ttymm/"
#define MPSC_DEV_NAME "ttyMM"
#define MPSC_VERSION "1.00"
@@ -1414,7 +1412,7 @@ mpsc_startup(struct uart_port *port)
/* If irq's are shared, need to set flag */
if (mpsc_ports[0].port.irq == mpsc_ports[1].port.irq)
- flag = SA_SHIRQ;
+ flag = IRQF_SHARED;
if (request_irq(pi->port.irq, mpsc_sdma_intr, flag,
"mpsc-sdma", pi))
@@ -1863,7 +1861,6 @@ static struct platform_driver mpsc_shared_driver = {
static struct uart_driver mpsc_reg = {
.owner = THIS_MODULE,
.driver_name = MPSC_DRIVER_NAME,
- .devfs_name = MPSC_DEVFS_NAME,
.dev_name = MPSC_DEV_NAME,
.major = MPSC_MAJOR,
.minor = MPSC_MINOR_START,
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 64c0e89124c..4a1c9983f38 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -16,7 +16,6 @@
**
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 513ff859770..bfd2a22759e 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -42,7 +42,6 @@
#undef DEBUG_HARD
#undef USE_CTRL_O_SYSRQ
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
@@ -101,7 +100,6 @@ static DEFINE_MUTEX(pmz_irq_mutex);
static struct uart_driver pmz_uart_reg = {
.owner = THIS_MODULE,
.driver_name = "ttyS",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
};
@@ -936,7 +934,7 @@ static int pmz_startup(struct uart_port *port)
}
pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
- if (request_irq(uap->port.irq, pmz_interrupt, SA_SHIRQ, "PowerMac Zilog", uap)) {
+ if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, "PowerMac Zilog", uap)) {
dev_err(&uap->dev->ofdev.dev,
"Unable to register zs interrupt handler.\n");
pmz_set_scc_power(uap, 0);
@@ -1445,8 +1443,8 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
goto no_dma;
}
- uap->tx_dma_irq = np->intrs[1].line;
- uap->rx_dma_irq = np->intrs[2].line;
+ uap->tx_dma_irq = irq_of_parse_and_map(np, 1);
+ uap->rx_dma_irq = irq_of_parse_and_map(np, 2);
}
no_dma:
@@ -1493,7 +1491,7 @@ no_dma:
* Init remaining bits of "port" structure
*/
uap->port.iotype = UPIO_MEM;
- uap->port.irq = np->intrs[0].line;
+ uap->port.irq = irq_of_parse_and_map(np, 0);
uap->port.uartclk = ZS_CLOCK;
uap->port.fifosize = 1;
uap->port.ops = &pmz_pops;
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 77d4568ccc3..a720953a404 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -24,7 +24,6 @@
* with the serial core maintainer satisfaction to appear soon.
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -269,7 +268,6 @@ static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
unsigned char status;
unsigned int ret;
-return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
status = serial_in(up, UART_MSR);
ret = 0;
@@ -391,7 +389,7 @@ static int serial_pxa_startup(struct uart_port *port)
/*
* Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occuring imminently
+ * are set via set_termios(), which will be occurring imminently
* anyway, so we don't enable them here.
*/
up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
@@ -781,7 +779,6 @@ static struct uart_pxa_port serial_pxa_ports[] = {
static struct uart_driver serial_pxa_reg = {
.owner = THIS_MODULE,
.driver_name = "PXA serial",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index f5aac92fb79..392bffcf96e 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -55,7 +55,6 @@
* BJD, 04-Nov-2004
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_S3C2410_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -149,7 +148,6 @@ s3c24xx_serial_dbg(const char *fmt, ...)
/* UART name and device definitions */
#define S3C24XX_SERIAL_NAME "ttySAC"
-#define S3C24XX_SERIAL_DEVFS "tts/"
#define S3C24XX_SERIAL_MAJOR 204
#define S3C24XX_SERIAL_MINOR 64
@@ -872,6 +870,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
return "S3C2410";
case PORT_S3C2440:
return "S3C2440";
+ case PORT_S3C2412:
+ return "S3C2412";
default:
return NULL;
}
@@ -950,7 +950,6 @@ static struct uart_driver s3c24xx_uart_drv = {
.nr = 3,
.cons = S3C24XX_SERIAL_CONSOLE,
.driver_name = S3C24XX_SERIAL_NAME,
- .devfs_name = S3C24XX_SERIAL_DEVFS,
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
};
@@ -1365,7 +1364,7 @@ static inline void s3c2410_serial_exit(void)
#endif /* CONFIG_CPU_S3C2410 */
-#ifdef CONFIG_CPU_S3C2440
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
static int s3c2440_serial_setsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
@@ -1528,6 +1527,141 @@ static inline void s3c2440_serial_exit(void)
#define s3c2440_uart_inf_at NULL
#endif /* CONFIG_CPU_S3C2440 */
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+
+static int s3c2412_serial_setsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+ ucon &= ~S3C2412_UCON_CLKMASK;
+
+ if (strcmp(clk->name, "uclk") == 0)
+ ucon |= S3C2440_UCON_UCLK;
+ else if (strcmp(clk->name, "pclk") == 0)
+ ucon |= S3C2440_UCON_PCLK;
+ else if (strcmp(clk->name, "usysclk") == 0)
+ ucon |= S3C2412_UCON_USYSCLK;
+ else {
+ printk(KERN_ERR "unknown clock source %s\n", clk->name);
+ return -EINVAL;
+ }
+
+ wr_regl(port, S3C2410_UCON, ucon);
+ return 0;
+}
+
+
+static int s3c2412_serial_getsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+ switch (ucon & S3C2412_UCON_CLKMASK) {
+ case S3C2412_UCON_UCLK:
+ clk->divisor = 1;
+ clk->name = "uclk";
+ break;
+
+ case S3C2412_UCON_PCLK:
+ case S3C2412_UCON_PCLK2:
+ clk->divisor = 1;
+ clk->name = "pclk";
+ break;
+
+ case S3C2412_UCON_USYSCLK:
+ clk->divisor = 1;
+ clk->name = "usysclk";
+ break;
+ }
+
+ return 0;
+}
+
+static int s3c2412_serial_resetport(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg)
+{
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+ dbg("%s: port=%p (%08lx), cfg=%p\n",
+ __FUNCTION__, port, port->mapbase, cfg);
+
+ /* ensure we don't change the clock settings... */
+
+ ucon &= S3C2412_UCON_CLKMASK;
+
+ wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+ /* reset both fifos */
+
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+ return 0;
+}
+
+static struct s3c24xx_uart_info s3c2412_uart_inf = {
+ .name = "Samsung S3C2412 UART",
+ .type = PORT_S3C2412,
+ .fifosize = 64,
+ .rx_fifomask = S3C2440_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2440_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2440_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2440_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
+ .get_clksrc = s3c2412_serial_getsource,
+ .set_clksrc = s3c2412_serial_setsource,
+ .reset_port = s3c2412_serial_resetport,
+};
+
+/* device management */
+
+static int s3c2412_serial_probe(struct platform_device *dev)
+{
+ dbg("s3c2440_serial_probe: dev=%p\n", dev);
+ return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
+}
+
+static struct platform_driver s3c2412_serial_drv = {
+ .probe = s3c2412_serial_probe,
+ .remove = s3c24xx_serial_remove,
+ .suspend = s3c24xx_serial_suspend,
+ .resume = s3c24xx_serial_resume,
+ .driver = {
+ .name = "s3c2412-uart",
+ .owner = THIS_MODULE,
+ },
+};
+
+
+static inline int s3c2412_serial_init(void)
+{
+ return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
+}
+
+static inline void s3c2412_serial_exit(void)
+{
+ platform_driver_unregister(&s3c2412_serial_drv);
+}
+
+#define s3c2412_uart_inf_at &s3c2412_uart_inf
+#else
+
+static inline int s3c2412_serial_init(void)
+{
+ return 0;
+}
+
+static inline void s3c2412_serial_exit(void)
+{
+}
+
+#define s3c2412_uart_inf_at NULL
+#endif /* CONFIG_CPU_S3C2440 */
+
+
/* module initialisation code */
static int __init s3c24xx_serial_modinit(void)
@@ -1542,6 +1676,7 @@ static int __init s3c24xx_serial_modinit(void)
s3c2400_serial_init();
s3c2410_serial_init();
+ s3c2412_serial_init();
s3c2440_serial_init();
return 0;
@@ -1551,6 +1686,7 @@ static void __exit s3c24xx_serial_modexit(void)
{
s3c2400_serial_exit();
s3c2410_serial_exit();
+ s3c2412_serial_exit();
s3c2440_serial_exit();
uart_unregister_driver(&s3c24xx_uart_drv);
@@ -1773,6 +1909,8 @@ static int s3c24xx_serial_initconsole(void)
info = s3c2410_uart_inf_at;
} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
info = s3c2440_uart_inf_at;
+ } else if (strcmp(dev->name, "s3c2412-uart") == 0) {
+ info = s3c2412_uart_inf_at;
} else {
printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
return 0;
@@ -1796,4 +1934,4 @@ console_initcall(s3c24xx_serial_initconsole);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver");
+MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver");
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index c2d9068b491..db3486d3387 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -24,7 +24,6 @@
* $Id: sa1100.c,v 1.50 2002/07/29 14:41:04 rmk Exp $
*
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -816,7 +815,6 @@ static struct uart_driver sa1100_reg = {
.owner = THIS_MODULE,
.driver_name = "ttySA",
.dev_name = "ttySA",
- .devfs_name = "ttySA",
.major = SERIAL_SA1100_MAJOR,
.minor = MINOR_START,
.nr = NR_PORTS,
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 3805f467b2f..d5f636fbf29 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -22,7 +22,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/slab.h>
@@ -50,6 +49,12 @@
*/
static DEFINE_MUTEX(port_mutex);
+/*
+ * lockdep: port->lock is initialized in two places, but we
+ * want only one lock-class:
+ */
+static struct lock_class_key port_lock_key;
+
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
@@ -1868,6 +1873,7 @@ uart_set_options(struct uart_port *port, struct console *co,
* early.
*/
spin_lock_init(&port->lock);
+ lockdep_set_class(&port->lock, &port_lock_key);
memset(&termios, 0, sizeof(struct termios));
@@ -2155,7 +2161,6 @@ int uart_register_driver(struct uart_driver *drv)
normal->owner = drv->owner;
normal->driver_name = drv->driver_name;
- normal->devfs_name = drv->devfs_name;
normal->name = drv->dev_name;
normal->major = drv->major;
normal->minor_start = drv->minor;
@@ -2163,7 +2168,7 @@ int uart_register_driver(struct uart_driver *drv)
normal->subtype = SERIAL_TYPE_NORMAL;
normal->init_termios = tty_std_termios;
normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+ normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
normal->driver_state = drv;
tty_set_operations(normal, &uart_ops);
@@ -2251,8 +2256,10 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
* If this port is a console, then the spinlock is already
* initialised.
*/
- if (!(uart_console(port) && (port->cons->flags & CON_ENABLED)))
+ if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) {
spin_lock_init(&port->lock);
+ lockdep_set_class(&port->lock, &port_lock_key);
+ }
uart_configure_port(drv, state, port);
@@ -2314,7 +2321,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
mutex_unlock(&state->mutex);
/*
- * Remove the devices from devfs
+ * Remove the devices from the tty layer
*/
tty_unregister_device(drv->tty_driver, port->line);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 2c70773543e..cbf260bc225 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -786,6 +786,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"),
/* too generic */
/* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */
/* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index aa521b8e0d4..23ddedbaec0 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -27,7 +27,6 @@
*
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -145,14 +144,15 @@ lh7a40xuart_rx_chars (struct uart_port* port)
{
struct tty_struct* tty = port->info->tty;
int cbRxMax = 256; /* (Gross) limit on receive */
- unsigned int data, flag;/* Received data and status */
+ unsigned int data; /* Received data and status */
+ unsigned int flag;
while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
data = UR (port, UART_R_DATA);
flag = TTY_NORMAL;
++port->icount.rx;
- if (unlikely(data & RxError)) { /* Quick check, short-circuit */
+ if (unlikely(data & RxError)) {
if (data & RxBreak) {
data &= ~(RxFramingError | RxParityError);
++port->icount.brk;
@@ -303,7 +303,7 @@ static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl)
/* Note, kernel appears to be setting DTR and RTS on console. */
/* *** FIXME: this deserves more work. There's some work in
- tracing all of the IO pins. */
+ tracing all of the IO pins. */
#if 0
if( port->mapbase == UART1_PHYS) {
gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
@@ -662,9 +662,13 @@ static int __init lh7a40xuart_init(void)
if (ret == 0) {
int i;
- for (i = 0; i < DEV_NR; i++)
+ for (i = 0; i < DEV_NR; i++) {
+ /* UART3, when used, requires GPIO pin reallocation */
+ if (lh7a40x_ports[i].port.mapbase == UART3_PHYS)
+ GPIO_PINMUX |= 1<<3;
uart_add_one_port (&lh7a40x_reg,
&lh7a40x_ports[i].port);
+ }
}
return ret;
}
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 3bdee64d1a9..b361669f85a 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -38,7 +38,6 @@
* Fix some spin_locks.
* Do not call uart_add_one_port for absent ports.
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -69,12 +68,10 @@ static char *serial_name = "TX39/49 Serial driver";
#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
/* "ttyS" is used for standard serial driver */
#define TXX9_TTY_NAME "ttyTX"
-#define TXX9_TTY_DEVFS_NAME "tttx/"
#define TXX9_TTY_MINOR_START (64 + 64) /* ttyTX0(128), ttyTX1(129) */
#else
/* acts like standard serial driver */
#define TXX9_TTY_NAME "ttyS"
-#define TXX9_TTY_DEVFS_NAME "tts/"
#define TXX9_TTY_MINOR_START 64
#endif
#define TXX9_TTY_MAJOR TTY_MAJOR
@@ -498,7 +495,7 @@ static int serial_txx9_startup(struct uart_port *port)
sio_out(up, TXX9_SIDISR, 0);
retval = request_irq(up->port.irq, serial_txx9_interrupt,
- SA_SHIRQ, "serial_txx9", up);
+ IRQF_SHARED, "serial_txx9", up);
if (retval)
return retval;
@@ -971,7 +968,6 @@ console_initcall(serial_txx9_console_init);
static struct uart_driver serial_txx9_reg = {
.owner = THIS_MODULE,
.driver_name = "serial_txx9",
- .devfs_name = TXX9_TTY_DEVFS_NAME,
.dev_name = TXX9_TTY_NAME,
.major = TXX9_TTY_MAJOR,
.minor = TXX9_TTY_MINOR_START,
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 44f6bf79bbe..301573373c3 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -20,7 +20,6 @@
#undef DEBUG
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -842,7 +841,7 @@ static int sci_request_irq(struct sci_port *port)
printk(KERN_ERR "sci: Cannot allocate irq.(IRQ=0)\n");
return -ENODEV;
}
- if (request_irq(port->irqs[0], sci_mpxed_interrupt, SA_INTERRUPT,
+ if (request_irq(port->irqs[0], sci_mpxed_interrupt, IRQF_DISABLED,
"sci", port)) {
printk(KERN_ERR "sci: Cannot allocate irq.\n");
return -ENODEV;
@@ -851,7 +850,7 @@ static int sci_request_irq(struct sci_port *port)
for (i = 0; i < ARRAY_SIZE(handlers); i++) {
if (!port->irqs[i])
continue;
- if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT,
+ if (request_irq(port->irqs[i], handlers[i], IRQF_DISABLED,
desc[i], port)) {
printk(KERN_ERR "sci: Cannot allocate irq.\n");
return -ENODEV;
@@ -1699,9 +1698,6 @@ static char banner[] __initdata =
static struct uart_driver sci_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "sci",
-#ifdef CONFIG_DEVFS_FS
- .devfs_name = "ttsc/",
-#endif
.dev_name = "ttySC",
.major = SCI_MAJOR,
.minor = SCI_MINOR_START,
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 1f14bb4382f..ab320fa3237 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -10,7 +10,6 @@
* Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
* Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
*/
-#include <linux/config.h>
#include <linux/serial_core.h>
#if defined(__H8300H__) || defined(__H8300S__)
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 60ea4a3f071..2f148e5b925 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -37,7 +37,6 @@
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
-#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/serial.h>
@@ -649,7 +648,7 @@ static irqreturn_t sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static int sn_sal_connect_interrupt(struct sn_cons_port *port)
{
if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
- SA_INTERRUPT | SA_SHIRQ,
+ IRQF_DISABLED | IRQF_SHARED,
"SAL console driver", port) >= 0) {
return SGI_UART_VECTOR;
}
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index fa4ae94243c..e35d9ab359f 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -10,7 +10,6 @@
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/console.h>
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index f137804b313..f851f0f44f9 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -20,8 +20,8 @@
#include <asm/hypervisor.h>
#include <asm/spitfire.h>
-#include <asm/vdev.h>
-#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#include <asm/irq.h>
#if defined(CONFIG_MAGIC_SYSRQ)
@@ -353,7 +353,6 @@ static struct uart_ops sunhv_pops = {
static struct uart_driver sunhv_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
};
@@ -408,143 +407,120 @@ static inline struct console *SUNHV_CONSOLE(void)
return &sunhv_console;
}
-static int __init hv_console_compatible(char *buf, int len)
-{
- while (len) {
- int this_len;
-
- if (!strcmp(buf, "qcn"))
- return 1;
-
- this_len = strlen(buf) + 1;
-
- buf += this_len;
- len -= this_len;
- }
-
- return 0;
-}
-
-static unsigned int __init get_interrupt(void)
-{
- const char *cons_str = "console";
- const char *compat_str = "compatible";
- int node = prom_getchild(sun4v_vdev_root);
- char buf[64];
- int err, len;
-
- node = prom_searchsiblings(node, cons_str);
- if (!node)
- return 0;
-
- len = prom_getproplen(node, compat_str);
- if (len == 0 || len == -1)
- return 0;
-
- err = prom_getproperty(node, compat_str, buf, 64);
- if (err == -1)
- return 0;
-
- if (!hv_console_compatible(buf, len))
- return 0;
-
- /* Ok, the this is the OBP node for the sun4v hypervisor
- * console device. Decode the interrupt.
- */
- return sun4v_vdev_device_interrupt(node);
-}
-
-static int __init sunhv_init(void)
+static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match)
{
struct uart_port *port;
- int ret;
+ int err;
- if (tlb_type != hypervisor)
+ if (op->irqs[0] == 0xffffffff)
return -ENODEV;
- port = kmalloc(sizeof(struct uart_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct uart_port), GFP_KERNEL);
if (unlikely(!port))
return -ENOMEM;
- memset(port, 0, sizeof(struct uart_port));
+ sunhv_port = port;
port->line = 0;
port->ops = &sunhv_pops;
port->type = PORT_SUNHV;
port->uartclk = ( 29491200 / 16 ); /* arbitrary */
- /* Set this just to make uart_configure_port() happy. */
port->membase = (unsigned char __iomem *) __pa(port);
- port->irq = get_interrupt();
- if (!port->irq) {
- kfree(port);
- return -ENODEV;
- }
+ port->irq = op->irqs[0];
+
+ port->dev = &op->dev;
sunhv_reg.minor = sunserial_current_minor;
sunhv_reg.nr = 1;
- ret = uart_register_driver(&sunhv_reg);
- if (ret < 0) {
- printk(KERN_ERR "SUNHV: uart_register_driver() failed %d\n",
- ret);
- kfree(port);
-
- return ret;
- }
+ err = uart_register_driver(&sunhv_reg);
+ if (err)
+ goto out_free_port;
sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
sunserial_current_minor += 1;
sunhv_reg.cons = SUNHV_CONSOLE();
- sunhv_port = port;
+ err = uart_add_one_port(&sunhv_reg, port);
+ if (err)
+ goto out_unregister_driver;
- ret = uart_add_one_port(&sunhv_reg, port);
- if (ret < 0) {
- printk(KERN_ERR "SUNHV: uart_add_one_port() failed %d\n", ret);
- sunserial_current_minor -= 1;
- uart_unregister_driver(&sunhv_reg);
- kfree(port);
- sunhv_port = NULL;
- return -ENODEV;
- }
+ err = request_irq(port->irq, sunhv_interrupt, 0, "hvcons", port);
+ if (err)
+ goto out_remove_port;
- if (request_irq(port->irq, sunhv_interrupt,
- SA_SHIRQ, "serial(sunhv)", port)) {
- printk(KERN_ERR "sunhv: Cannot register IRQ\n");
- uart_remove_one_port(&sunhv_reg, port);
- sunserial_current_minor -= 1;
- uart_unregister_driver(&sunhv_reg);
- kfree(port);
- sunhv_port = NULL;
- return -ENODEV;
- }
+ dev_set_drvdata(&op->dev, port);
return 0;
+
+out_remove_port:
+ uart_remove_one_port(&sunhv_reg, port);
+
+out_unregister_driver:
+ sunserial_current_minor -= 1;
+ uart_unregister_driver(&sunhv_reg);
+
+out_free_port:
+ kfree(port);
+ sunhv_port = NULL;
+ return err;
}
-static void __exit sunhv_exit(void)
+static int __devexit hv_remove(struct of_device *dev)
{
- struct uart_port *port = sunhv_port;
-
- BUG_ON(!port);
+ struct uart_port *port = dev_get_drvdata(&dev->dev);
free_irq(port->irq, port);
uart_remove_one_port(&sunhv_reg, port);
- sunserial_current_minor -= 1;
+ sunserial_current_minor -= 1;
uart_unregister_driver(&sunhv_reg);
- kfree(sunhv_port);
+ kfree(port);
sunhv_port = NULL;
+
+ dev_set_drvdata(&dev->dev, NULL);
+
+ return 0;
+}
+
+static struct of_device_id hv_match[] = {
+ {
+ .name = "console",
+ .compatible = "qcn",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, hv_match);
+
+static struct of_platform_driver hv_driver = {
+ .name = "hv",
+ .match_table = hv_match,
+ .probe = hv_probe,
+ .remove = __devexit_p(hv_remove),
+};
+
+static int __init sunhv_init(void)
+{
+ if (tlb_type != hypervisor)
+ return -ENODEV;
+
+ return of_register_driver(&hv_driver, &of_bus_type);
+}
+
+static void __exit sunhv_exit(void)
+{
+ of_unregister_driver(&hv_driver);
}
module_init(sunhv_init);
module_exit(sunhv_exit);
MODULE_AUTHOR("David S. Miller");
-MODULE_DESCRIPTION("SUN4V Hypervisor console driver")
+MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index bfbe9dc90cc..0dbd4df44c0 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -1,7 +1,7 @@
/* sunsab.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
*
* Rewrote buffer handling to use CIRC(Circular Buffer) macros.
* Maxim Krasnyanskiy <maxk@qualcomm.com>
@@ -12,10 +12,9 @@
* Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*
* Ported to new 2.5.x UART layer.
- * David S. Miller <davem@redhat.com>
+ * David S. Miller <davem@davemloft.net>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -37,8 +36,8 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/oplib.h>
-#include <asm/ebus.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -851,7 +850,6 @@ static struct uart_ops sunsab_pops = {
static struct uart_driver sunsab_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
};
@@ -977,199 +975,188 @@ static inline struct console *SUNSAB_CONSOLE(void)
#define sunsab_console_init() do { } while (0)
#endif
-static void __init for_each_sab_edev(void (*callback)(struct linux_ebus_device *, void *), void *arg)
+static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
+ struct of_device *op,
+ unsigned long offset,
+ int line)
{
- struct linux_ebus *ebus;
- struct linux_ebus_device *edev = NULL;
-
- for_each_ebus(ebus) {
- for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_name, "se")) {
- callback(edev, arg);
- continue;
- } else if (!strcmp(edev->prom_name, "serial")) {
- char compat[32];
- int clen;
-
- /* On RIO this can be an SE, check it. We could
- * just check ebus->is_rio, but this is more portable.
- */
- clen = prom_getproperty(edev->prom_node, "compatible",
- compat, sizeof(compat));
- if (clen > 0) {
- if (strncmp(compat, "sab82532", 8) == 0) {
- callback(edev, arg);
- continue;
- }
- }
- }
- }
- }
-}
+ up->port.line = line;
+ up->port.dev = &op->dev;
+
+ up->port.mapbase = op->resource[0].start + offset;
+ up->port.membase = of_ioremap(&op->resource[0], offset,
+ sizeof(union sab82532_async_regs),
+ "sab");
+ if (!up->port.membase)
+ return -ENOMEM;
+ up->regs = (union sab82532_async_regs __iomem *) up->port.membase;
-static void __init sab_count_callback(struct linux_ebus_device *edev, void *arg)
-{
- int *count_p = arg;
+ up->port.irq = op->irqs[0];
- (*count_p)++;
-}
+ up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
+ up->port.iotype = UPIO_MEM;
-static void __init sab_attach_callback(struct linux_ebus_device *edev, void *arg)
-{
- int *instance_p = arg;
- struct uart_sunsab_port *up;
- unsigned long regs, offset;
- int i;
+ writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
- /* Note: ports are located in reverse order */
- regs = edev->resource[0].start;
- offset = sizeof(union sab82532_async_regs);
- for (i = 0; i < 2; i++) {
- up = &sunsab_ports[(*instance_p * 2) + 1 - i];
+ up->port.ops = &sunsab_pops;
+ up->port.type = PORT_SUNSAB;
+ up->port.uartclk = SAB_BASE_BAUD;
- memset(up, 0, sizeof(*up));
- up->regs = ioremap(regs + offset, sizeof(union sab82532_async_regs));
- up->port.irq = edev->irqs[0];
- up->port.fifosize = SAB82532_XMIT_FIFO_SIZE;
- up->port.mapbase = (unsigned long)up->regs;
- up->port.iotype = UPIO_MEM;
+ up->type = readb(&up->regs->r.vstr) & 0x0f;
+ writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &up->regs->w.pcr);
+ writeb(0xff, &up->regs->w.pim);
+ if ((up->port.line & 0x1) == 0) {
+ up->pvr_dsr_bit = (1 << 0);
+ up->pvr_dtr_bit = (1 << 1);
+ } else {
+ up->pvr_dsr_bit = (1 << 3);
+ up->pvr_dtr_bit = (1 << 2);
+ }
+ up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
+ writeb(up->cached_pvr, &up->regs->w.pvr);
+ up->cached_mode = readb(&up->regs->rw.mode);
+ up->cached_mode |= SAB82532_MODE_FRTS;
+ writeb(up->cached_mode, &up->regs->rw.mode);
+ up->cached_mode |= SAB82532_MODE_RTS;
+ writeb(up->cached_mode, &up->regs->rw.mode);
- writeb(SAB82532_IPC_IC_ACT_LOW, &up->regs->w.ipc);
+ up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
+ up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
- offset -= sizeof(union sab82532_async_regs);
+ if (!(up->port.line & 0x01)) {
+ int err;
+
+ err = request_irq(up->port.irq, sunsab_interrupt,
+ IRQF_SHARED, "sab", up);
+ if (err) {
+ of_iounmap(up->port.membase,
+ sizeof(union sab82532_async_regs));
+ return err;
+ }
}
-
- (*instance_p)++;
+
+ return 0;
}
-static int __init probe_for_sabs(void)
+static int __devinit sab_probe(struct of_device *op, const struct of_device_id *match)
{
- int this_sab = 0;
+ static int inst;
+ struct uart_sunsab_port *up;
+ int err;
+
+ up = &sunsab_ports[inst * 2];
+
+ err = sunsab_init_one(&up[0], op,
+ sizeof(union sab82532_async_regs),
+ (inst * 2) + 0);
+ if (err)
+ return err;
+
+ err = sunsab_init_one(&up[0], op, 0,
+ (inst * 2) + 1);
+ if (err) {
+ of_iounmap(up[0].port.membase,
+ sizeof(union sab82532_async_regs));
+ free_irq(up[0].port.irq, &up[0]);
+ return err;
+ }
- /* Find device instances. */
- for_each_sab_edev(&sab_count_callback, &this_sab);
- if (!this_sab)
- return -ENODEV;
+ uart_add_one_port(&sunsab_reg, &up[0].port);
+ uart_add_one_port(&sunsab_reg, &up[1].port);
- /* Allocate tables. */
- sunsab_ports = kmalloc(sizeof(struct uart_sunsab_port) * this_sab * 2,
- GFP_KERNEL);
- if (!sunsab_ports)
- return -ENOMEM;
+ dev_set_drvdata(&op->dev, &up[0]);
- num_channels = this_sab * 2;
+ inst++;
- this_sab = 0;
- for_each_sab_edev(&sab_attach_callback, &this_sab);
return 0;
}
-static void __init sunsab_init_hw(void)
+static void __devexit sab_remove_one(struct uart_sunsab_port *up)
{
- int i;
-
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
-
- up->port.line = i;
- up->port.ops = &sunsab_pops;
- up->port.type = PORT_SUNSAB;
- up->port.uartclk = SAB_BASE_BAUD;
-
- up->type = readb(&up->regs->r.vstr) & 0x0f;
- writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &up->regs->w.pcr);
- writeb(0xff, &up->regs->w.pim);
- if (up->port.line == 0) {
- up->pvr_dsr_bit = (1 << 0);
- up->pvr_dtr_bit = (1 << 1);
- } else {
- up->pvr_dsr_bit = (1 << 3);
- up->pvr_dtr_bit = (1 << 2);
- }
- up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
- writeb(up->cached_pvr, &up->regs->w.pvr);
- up->cached_mode = readb(&up->regs->rw.mode);
- up->cached_mode |= SAB82532_MODE_FRTS;
- writeb(up->cached_mode, &up->regs->rw.mode);
- up->cached_mode |= SAB82532_MODE_RTS;
- writeb(up->cached_mode, &up->regs->rw.mode);
-
- up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
- up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
-
- if (!(up->port.line & 0x01)) {
- if (request_irq(up->port.irq, sunsab_interrupt,
- SA_SHIRQ, "serial(sab82532)", up)) {
- printk("sunsab%d: can't get IRQ %x\n",
- i, up->port.irq);
- continue;
- }
- }
- }
+ uart_remove_one_port(&sunsab_reg, &up->port);
+ if (!(up->port.line & 1))
+ free_irq(up->port.irq, up);
+ of_iounmap(up->port.membase,
+ sizeof(union sab82532_async_regs));
}
-static int __init sunsab_init(void)
+static int __devexit sab_remove(struct of_device *op)
{
- int ret = probe_for_sabs();
- int i;
-
- if (ret < 0)
- return ret;
+ struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
- sunsab_init_hw();
+ sab_remove_one(&up[0]);
+ sab_remove_one(&up[1]);
- sunsab_reg.minor = sunserial_current_minor;
- sunsab_reg.nr = num_channels;
+ dev_set_drvdata(&op->dev, NULL);
- ret = uart_register_driver(&sunsab_reg);
- if (ret < 0) {
- int i;
+ return 0;
+}
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
+static struct of_device_id sab_match[] = {
+ {
+ .name = "se",
+ },
+ {
+ .name = "serial",
+ .compatible = "sab82532",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sab_match);
- if (!(up->port.line & 0x01))
- free_irq(up->port.irq, up);
- iounmap(up->regs);
- }
- kfree(sunsab_ports);
- sunsab_ports = NULL;
+static struct of_platform_driver sab_driver = {
+ .name = "sab",
+ .match_table = sab_match,
+ .probe = sab_probe,
+ .remove = __devexit_p(sab_remove),
+};
- return ret;
+static int __init sunsab_init(void)
+{
+ struct device_node *dp;
+ int err;
+
+ num_channels = 0;
+ for_each_node_by_name(dp, "su")
+ num_channels += 2;
+ for_each_node_by_name(dp, "serial") {
+ if (of_device_is_compatible(dp, "sab82532"))
+ num_channels += 2;
}
- sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
+ if (num_channels) {
+ sunsab_ports = kzalloc(sizeof(struct uart_sunsab_port) *
+ num_channels, GFP_KERNEL);
+ if (!sunsab_ports)
+ return -ENOMEM;
- sunsab_reg.cons = SUNSAB_CONSOLE();
+ sunsab_reg.minor = sunserial_current_minor;
+ sunsab_reg.nr = num_channels;
- sunserial_current_minor += num_channels;
-
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
+ err = uart_register_driver(&sunsab_reg);
+ if (err) {
+ kfree(sunsab_ports);
+ sunsab_ports = NULL;
- uart_add_one_port(&sunsab_reg, &up->port);
+ return err;
+ }
+
+ sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
+ sunsab_reg.cons = SUNSAB_CONSOLE();
+ sunserial_current_minor += num_channels;
}
- return 0;
+ return of_register_driver(&sab_driver, &of_bus_type);
}
static void __exit sunsab_exit(void)
{
- int i;
-
- for (i = 0; i < num_channels; i++) {
- struct uart_sunsab_port *up = &sunsab_ports[i];
-
- uart_remove_one_port(&sunsab_reg, &up->port);
-
- if (!(up->port.line & 0x01))
- free_irq(up->port.irq, up);
- iounmap(up->regs);
+ of_unregister_driver(&sab_driver);
+ if (num_channels) {
+ sunserial_current_minor -= num_channels;
+ uart_unregister_driver(&sunsab_reg);
}
- sunserial_current_minor -= num_channels;
- uart_unregister_driver(&sunsab_reg);
-
kfree(sunsab_ports);
sunsab_ports = NULL;
}
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 2b4f96541b8..f9013baba05 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -12,10 +12,9 @@
* Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
*
* Converted to new 2.5.x UART layer.
- * David S. Miller (davem@redhat.com), 2002-Jul-29
+ * David S. Miller (davem@davemloft.net), 2002-Jul-29
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -40,11 +39,8 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/oplib.h>
-#include <asm/ebus.h>
-#ifdef CONFIG_SPARC64
-#include <asm/isa.h>
-#endif
+#include <asm/prom.h>
+#include <asm/of_device.h>
#if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -94,10 +90,10 @@ struct uart_sunsu_port {
/* Probing information. */
enum su_type su_type;
unsigned int type_probed; /* XXX Stupid */
- int port_node;
+ unsigned long reg_size;
#ifdef CONFIG_SERIO
- struct serio *serio;
+ struct serio serio;
int serio_open;
#endif
};
@@ -509,7 +505,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
/* Stop-A is handled by drivers/char/keyboard.c now. */
if (up->su_type == SU_PORT_KBD) {
#ifdef CONFIG_SERIO
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
} else if (up->su_type == SU_PORT_MS) {
int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -523,7 +519,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
case 0:
#ifdef CONFIG_SERIO
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
break;
};
@@ -671,10 +667,10 @@ static int sunsu_startup(struct uart_port *port)
if (up->su_type != SU_PORT_PORT) {
retval = request_irq(up->port.irq, sunsu_kbd_ms_interrupt,
- SA_SHIRQ, su_typev[up->su_type], up);
+ IRQF_SHARED, su_typev[up->su_type], up);
} else {
retval = request_irq(up->port.irq, sunsu_serial_interrupt,
- SA_SHIRQ, su_typev[up->su_type], up);
+ IRQF_SHARED, su_typev[up->su_type], up);
}
if (retval) {
printk("su: Cannot register IRQ %d\n", up->port.irq);
@@ -1031,99 +1027,14 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
{
unsigned char status1, status2, scratch, scratch2, scratch3;
unsigned char save_lcr, save_mcr;
- struct linux_ebus_device *dev = NULL;
- struct linux_ebus *ebus;
-#ifdef CONFIG_SPARC64
- struct sparc_isa_bridge *isa_br;
- struct sparc_isa_device *isa_dev;
-#endif
-#ifndef CONFIG_SPARC64
- struct linux_prom_registers reg0;
-#endif
unsigned long flags;
- if (!up->port_node || !up->su_type)
+ if (up->su_type == SU_PORT_NONE)
return;
up->type_probed = PORT_UNKNOWN;
up->port.iotype = UPIO_MEM;
- /*
- * First we look for Ebus-bases su's
- */
- for_each_ebus(ebus) {
- for_each_ebusdev(dev, ebus) {
- if (dev->prom_node == up->port_node) {
- /*
- * The EBus is broken on sparc; it delivers
- * virtual addresses in resources. Oh well...
- * This is correct on sparc64, though.
- */
- up->port.membase = (char *) dev->resource[0].start;
- /*
- * This is correct on both architectures.
- */
- up->port.mapbase = dev->resource[0].start;
- up->port.irq = dev->irqs[0];
- goto ebus_done;
- }
- }
- }
-
-#ifdef CONFIG_SPARC64
- for_each_isa(isa_br) {
- for_each_isadev(isa_dev, isa_br) {
- if (isa_dev->prom_node == up->port_node) {
- /* Same on sparc64. Cool architecure... */
- up->port.membase = (char *) isa_dev->resource.start;
- up->port.mapbase = isa_dev->resource.start;
- up->port.irq = isa_dev->irq;
- goto ebus_done;
- }
- }
- }
-#endif
-
-#ifdef CONFIG_SPARC64
- /*
- * Not on Ebus, bailing.
- */
- return;
-#else
- /*
- * Not on Ebus, must be OBIO.
- */
- if (prom_getproperty(up->port_node, "reg",
- (char *)&reg0, sizeof(reg0)) == -1) {
- prom_printf("sunsu: no \"reg\" property\n");
- return;
- }
- prom_apply_obio_ranges(&reg0, 1);
- if (reg0.which_io != 0) { /* Just in case... */
- prom_printf("sunsu: bus number nonzero: 0x%x:%x\n",
- reg0.which_io, reg0.phys_addr);
- return;
- }
- up->port.mapbase = reg0.phys_addr;
- if ((up->port.membase = ioremap(reg0.phys_addr, reg0.reg_size)) == 0) {
- prom_printf("sunsu: Cannot map registers.\n");
- return;
- }
-
- /*
- * 0x20 is sun4m thing, Dave Redman heritage.
- * See arch/sparc/kernel/irq.c.
- */
-#define IRQ_4M(n) ((n)|0x20)
-
- /*
- * There is no intr property on MrCoffee, so hardwire it.
- */
- up->port.irq = IRQ_4M(13);
-#endif
-
-ebus_done:
-
spin_lock_irqsave(&up->port.lock, flags);
if (!(up->port.flags & UPF_BUGGY_UART)) {
@@ -1265,23 +1176,17 @@ out:
static struct uart_driver sunsu_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
};
-static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
+static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up)
{
int quot, baud;
#ifdef CONFIG_SERIO
struct serio *serio;
#endif
- spin_lock_init(&up->port.lock);
- up->port.line = channel;
- up->port.type = PORT_UNKNOWN;
- up->port.uartclk = (SU_BASE_BAUD * 16);
-
if (up->su_type == SU_PORT_KBD) {
up->cflag = B1200 | CS8 | CLOCAL | CREAD;
baud = 1200;
@@ -1293,41 +1198,31 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
sunsu_autoconfig(up);
if (up->port.type == PORT_UNKNOWN)
- return -1;
-
- printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n",
- channel,
- up->port.membase, __irq_itoa(up->port.irq),
- sunsu_type(&up->port));
+ return -ENODEV;
#ifdef CONFIG_SERIO
- up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(*serio));
-
- serio->port_data = up;
-
- serio->id.type = SERIO_RS232;
- if (up->su_type == SU_PORT_KBD) {
- serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "sukbd", sizeof(serio->name));
- } else {
- serio->id.proto = SERIO_SUN;
- serio->id.extra = 1;
- strlcpy(serio->name, "sums", sizeof(serio->name));
- }
- strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"),
- sizeof(serio->phys));
-
- serio->write = sunsu_serio_write;
- serio->open = sunsu_serio_open;
- serio->close = sunsu_serio_close;
+ serio = &up->serio;
+ serio->port_data = up;
- serio_register_port(serio);
+ serio->id.type = SERIO_RS232;
+ if (up->su_type == SU_PORT_KBD) {
+ serio->id.proto = SERIO_SUNKBD;
+ strlcpy(serio->name, "sukbd", sizeof(serio->name));
} else {
- printk(KERN_WARNING "su%d: not enough memory for serio port\n",
- channel);
+ serio->id.proto = SERIO_SUN;
+ serio->id.extra = 1;
+ strlcpy(serio->name, "sums", sizeof(serio->name));
}
+ strlcpy(serio->phys,
+ (!(up->port.line & 1) ? "su/serio0" : "su/serio1"),
+ sizeof(serio->phys));
+
+ serio->write = sunsu_serio_write;
+ serio->open = sunsu_serio_open;
+ serio->close = sunsu_serio_close;
+ serio->dev.parent = up->port.dev;
+
+ serio_register_port(serio);
#endif
sunsu_change_speed(&up->port, up->cflag, 0, quot);
@@ -1459,22 +1354,20 @@ static struct console sunsu_cons = {
* Register console.
*/
-static inline struct console *SUNSU_CONSOLE(void)
+static inline struct console *SUNSU_CONSOLE(int num_uart)
{
int i;
if (con_is_present())
return NULL;
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < num_uart; i++) {
int this_minor = sunsu_reg.minor + i;
if ((this_minor - 64) == (serial_console - 1))
break;
}
- if (i == UART_NR)
- return NULL;
- if (sunsu_ports[i].port_node == 0)
+ if (i == num_uart)
return NULL;
sunsu_cons.index = i;
@@ -1482,252 +1375,186 @@ static inline struct console *SUNSU_CONSOLE(void)
return &sunsu_cons;
}
#else
-#define SUNSU_CONSOLE() (NULL)
+#define SUNSU_CONSOLE(num_uart) (NULL)
#define sunsu_serial_console_init() do { } while (0)
#endif
-static int __init sunsu_serial_init(void)
+static enum su_type __devinit su_get_type(struct device_node *dp)
{
- int instance, ret, i;
+ struct device_node *ap = of_find_node_by_path("/aliases");
- /* How many instances do we need? */
- instance = 0;
- for (i = 0; i < UART_NR; i++) {
- struct uart_sunsu_port *up = &sunsu_ports[i];
+ if (ap) {
+ char *keyb = of_get_property(ap, "keyboard", NULL);
+ char *ms = of_get_property(ap, "mouse", NULL);
- if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD)
- continue;
+ if (keyb) {
+ if (dp == of_find_node_by_path(keyb))
+ return SU_PORT_KBD;
+ }
+ if (ms) {
+ if (dp == of_find_node_by_path(ms))
+ return SU_PORT_MS;
+ }
+ }
- spin_lock_init(&up->port.lock);
- up->port.flags |= UPF_BOOT_AUTOCONF;
- up->port.type = PORT_UNKNOWN;
- up->port.uartclk = (SU_BASE_BAUD * 16);
+ return SU_PORT_PORT;
+}
- sunsu_autoconfig(up);
- if (up->port.type == PORT_UNKNOWN)
- continue;
+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 uart_sunsu_port *up;
+ struct resource *rp;
+ int err;
- up->port.line = instance++;
- up->port.ops = &sunsu_pops;
- }
+ if (inst >= UART_NR)
+ return -EINVAL;
- sunsu_reg.minor = sunserial_current_minor;
+ up = &sunsu_ports[inst];
+ up->port.line = inst;
- sunsu_reg.nr = instance;
+ spin_lock_init(&up->port.lock);
- ret = uart_register_driver(&sunsu_reg);
- if (ret < 0)
- return ret;
+ up->su_type = su_get_type(dp);
- sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
+ rp = &op->resource[0];
+ up->port.mapbase = op->resource[0].start;
- sunserial_current_minor += instance;
+ up->reg_size = (rp->end - rp->start) + 1;
+ up->port.membase = of_ioremap(rp, 0, up->reg_size, "su");
+ if (!up->port.membase)
+ return -ENOMEM;
- sunsu_reg.cons = SUNSU_CONSOLE();
+ up->port.irq = op->irqs[0];
- for (i = 0; i < UART_NR; i++) {
- struct uart_sunsu_port *up = &sunsu_ports[i];
+ up->port.dev = &op->dev;
- /* Do not register Keyboard/Mouse lines with UART
- * layer.
- */
- if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD)
- continue;
+ up->port.type = PORT_UNKNOWN;
+ up->port.uartclk = (SU_BASE_BAUD * 16);
- if (up->port.type == PORT_UNKNOWN)
- continue;
+ err = 0;
+ if (up->su_type == SU_PORT_KBD || up->su_type == SU_PORT_MS) {
+ err = sunsu_kbd_ms_init(up);
+ if (err)
+ goto out_unmap;
- uart_add_one_port(&sunsu_reg, &up->port);
+ return 0;
}
- return 0;
-}
+ up->port.flags |= UPF_BOOT_AUTOCONF;
-static int su_node_ok(int node, char *name, int namelen)
-{
- if (strncmp(name, "su", namelen) == 0 ||
- strncmp(name, "su_pnp", namelen) == 0)
- return 1;
-
- if (strncmp(name, "serial", namelen) == 0) {
- char compat[32];
- int clen;
-
- /* Is it _really_ a 'su' device? */
- clen = prom_getproperty(node, "compatible", compat, sizeof(compat));
- if (clen > 0) {
- if (strncmp(compat, "sab82532", 8) == 0) {
- /* Nope, Siemens serial, not for us. */
- return 0;
- }
- }
- return 1;
- }
+ sunsu_autoconfig(up);
- return 0;
-}
+ err = -ENODEV;
+ if (up->port.type == PORT_UNKNOWN)
+ goto out_unmap;
-#define SU_PROPSIZE 128
+ up->port.ops = &sunsu_pops;
-/*
- * Scan status structure.
- * "prop" is a local variable but it eats stack to keep it in each
- * stack frame of a recursive procedure.
- */
-struct su_probe_scan {
- int msnode, kbnode; /* PROM nodes for mouse and keyboard */
- int msx, kbx; /* minors for mouse and keyboard */
- int devices; /* scan index */
- char prop[SU_PROPSIZE];
-};
+ err = uart_add_one_port(&sunsu_reg, &up->port);
+ if (err)
+ goto out_unmap;
-/*
- * We have several platforms which present 'su' in different parts
- * of the device tree. 'su' may be found under obio, ebus, isa and pci.
- * We walk over the tree and find them wherever PROM hides them.
- */
-static void __init su_probe_any(struct su_probe_scan *t, int sunode)
-{
- struct uart_sunsu_port *up;
- int len;
+ dev_set_drvdata(&op->dev, up);
- if (t->devices >= UART_NR)
- return;
+ inst++;
- for (; sunode != 0; sunode = prom_getsibling(sunode)) {
- len = prom_getproperty(sunode, "name", t->prop, SU_PROPSIZE);
- if (len <= 1)
- continue; /* Broken PROM node */
-
- if (su_node_ok(sunode, t->prop, len)) {
- up = &sunsu_ports[t->devices];
- if (t->kbnode != 0 && sunode == t->kbnode) {
- t->kbx = t->devices;
- up->su_type = SU_PORT_KBD;
- } else if (t->msnode != 0 && sunode == t->msnode) {
- t->msx = t->devices;
- up->su_type = SU_PORT_MS;
- } else {
-#ifdef CONFIG_SPARC64
- /*
- * Do not attempt to use the truncated
- * keyboard/mouse ports as serial ports
- * on Ultras with PC keyboard attached.
- */
- if (prom_getbool(sunode, "mouse"))
- continue;
- if (prom_getbool(sunode, "keyboard"))
- continue;
-#endif
- up->su_type = SU_PORT_PORT;
- }
- up->port_node = sunode;
- ++t->devices;
- } else {
- su_probe_any(t, prom_getchild(sunode));
- }
- }
+ return 0;
+
+out_unmap:
+ of_iounmap(up->port.membase, up->reg_size);
+ return err;
}
-static int __init sunsu_probe(void)
+static int __devexit su_remove(struct of_device *dev)
{
- int node;
- int len;
- struct su_probe_scan scan;
+ struct uart_sunsu_port *up = dev_get_drvdata(&dev->dev);;
- /*
- * First, we scan the tree.
- */
- scan.devices = 0;
- scan.msx = -1;
- scan.kbx = -1;
- scan.kbnode = 0;
- scan.msnode = 0;
+ if (up->su_type == SU_PORT_MS ||
+ up->su_type == SU_PORT_KBD) {
+#ifdef CONFIG_SERIO
+ serio_unregister_port(&up->serio);
+#endif
+ } else if (up->port.type != PORT_UNKNOWN)
+ uart_remove_one_port(&sunsu_reg, &up->port);
- /*
- * Get the nodes for keyboard and mouse from 'aliases'...
- */
- node = prom_getchild(prom_root_node);
- node = prom_searchsiblings(node, "aliases");
- if (node != 0) {
- len = prom_getproperty(node, "keyboard", scan.prop, SU_PROPSIZE);
- if (len > 0) {
- scan.prop[len] = 0;
- scan.kbnode = prom_finddevice(scan.prop);
- }
+ return 0;
+}
- len = prom_getproperty(node, "mouse", scan.prop, SU_PROPSIZE);
- if (len > 0) {
- scan.prop[len] = 0;
- scan.msnode = prom_finddevice(scan.prop);
- }
- }
+static struct of_device_id su_match[] = {
+ {
+ .name = "su",
+ },
+ {
+ .name = "su_pnp",
+ },
+ {
+ .name = "serial",
+ .compatible = "su",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, su_match);
- su_probe_any(&scan, prom_getchild(prom_root_node));
+static struct of_platform_driver su_driver = {
+ .name = "su",
+ .match_table = su_match,
+ .probe = su_probe,
+ .remove = __devexit_p(su_remove),
+};
- /*
- * Second, we process the special case of keyboard and mouse.
- *
- * Currently if we got keyboard and mouse hooked to "su" ports
- * we do not use any possible remaining "su" as a serial port.
- * Thus, we ignore values of .msx and .kbx, then compact ports.
- */
- if (scan.msx != -1 && scan.kbx != -1) {
- sunsu_ports[0].su_type = SU_PORT_MS;
- sunsu_ports[0].port_node = scan.msnode;
- sunsu_kbd_ms_init(&sunsu_ports[0], 0);
+static int num_uart;
- sunsu_ports[1].su_type = SU_PORT_KBD;
- sunsu_ports[1].port_node = scan.kbnode;
- sunsu_kbd_ms_init(&sunsu_ports[1], 1);
+static int __init sunsu_init(void)
+{
+ struct device_node *dp;
+ int err;
- return 0;
+ num_uart = 0;
+ for_each_node_by_name(dp, "su") {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
}
-
- if (scan.msx != -1 || scan.kbx != -1) {
- printk("sunsu_probe: cannot match keyboard and mouse, confused\n");
- return -ENODEV;
+ for_each_node_by_name(dp, "su_pnp") {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
+ }
+ for_each_node_by_name(dp, "serial") {
+ if (of_device_is_compatible(dp, "su")) {
+ if (su_get_type(dp) == SU_PORT_PORT)
+ num_uart++;
+ }
}
- if (scan.devices == 0)
- return -ENODEV;
+ if (num_uart) {
+ sunsu_reg.minor = sunserial_current_minor;
+ sunsu_reg.nr = num_uart;
+ err = uart_register_driver(&sunsu_reg);
+ if (err)
+ return err;
+ sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
+ sunserial_current_minor += num_uart;
+ sunsu_reg.cons = SUNSU_CONSOLE(num_uart);
+ }
- /*
- * Console must be initiated after the generic initialization.
- */
- sunsu_serial_init();
+ err = of_register_driver(&su_driver, &of_bus_type);
+ if (err && num_uart)
+ uart_unregister_driver(&sunsu_reg);
- return 0;
+ return err;
}
static void __exit sunsu_exit(void)
{
- int i, saw_uart;
-
- saw_uart = 0;
- for (i = 0; i < UART_NR; i++) {
- struct uart_sunsu_port *up = &sunsu_ports[i];
-
- if (up->su_type == SU_PORT_MS ||
- up->su_type == SU_PORT_KBD) {
-#ifdef CONFIG_SERIO
- if (up->serio) {
- serio_unregister_port(up->serio);
- up->serio = NULL;
- }
-#endif
- } else if (up->port.type != PORT_UNKNOWN) {
- uart_remove_one_port(&sunsu_reg, &up->port);
- saw_uart++;
- }
- }
-
- if (saw_uart)
+ if (num_uart)
uart_unregister_driver(&sunsu_reg);
}
-module_init(sunsu_probe);
+module_init(sunsu_init);
module_exit(sunsu_exit);
+
+MODULE_AUTHOR("Eddie C. Dost, Peter Zaitcev, and David S. Miller");
+MODULE_DESCRIPTION("Sun SU serial port driver");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index cd49ebbf4a4..a1456d9352c 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1,5 +1,4 @@
-/*
- * sunzilog.c
+/* sunzilog.c: Zilog serial driver for Sparc systems.
*
* Driver for Zilog serial chips found on Sun workstations and
* servers. This driver could actually be made more generic.
@@ -10,10 +9,9 @@
* C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
* work there.
*
- * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -38,10 +36,8 @@
#include <asm/io.h>
#include <asm/irq.h>
-#ifdef CONFIG_SPARC64
-#include <asm/fhc.h>
-#endif
-#include <asm/sbus.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -65,7 +61,7 @@
#define ZSDELAY()
#define ZSDELAY_LONG()
#define ZS_WSYNC(__channel) \
- sbus_readb(&((__channel)->control))
+ readb(&((__channel)->control))
#endif
static int num_sunzilog;
@@ -107,7 +103,7 @@ struct uart_sunzilog_port {
unsigned char prev_status;
#ifdef CONFIG_SERIO
- struct serio *serio;
+ struct serio serio;
int serio_open;
#endif
};
@@ -138,9 +134,9 @@ static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
{
unsigned char retval;
- sbus_writeb(reg, &channel->control);
+ writeb(reg, &channel->control);
ZSDELAY();
- retval = sbus_readb(&channel->control);
+ retval = readb(&channel->control);
ZSDELAY();
return retval;
@@ -149,9 +145,9 @@ static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
static void write_zsreg(struct zilog_channel __iomem *channel,
unsigned char reg, unsigned char value)
{
- sbus_writeb(reg, &channel->control);
+ writeb(reg, &channel->control);
ZSDELAY();
- sbus_writeb(value, &channel->control);
+ writeb(value, &channel->control);
ZSDELAY();
}
@@ -162,17 +158,17 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
for (i = 0; i < 32; i++) {
unsigned char regval;
- regval = sbus_readb(&channel->control);
+ regval = readb(&channel->control);
ZSDELAY();
if (regval & Rx_CH_AV)
break;
regval = read_zsreg(channel, R1);
- sbus_readb(&channel->data);
+ readb(&channel->data);
ZSDELAY();
if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- sbus_writeb(ERR_RES, &channel->control);
+ writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
@@ -194,7 +190,7 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *
udelay(100);
}
- sbus_writeb(ERR_RES, &channel->control);
+ writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -291,7 +287,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
/* Stop-A is handled by drivers/char/keyboard.c now. */
#ifdef CONFIG_SERIO
if (up->serio_open)
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
} else if (ZS_IS_MOUSE(up)) {
int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -306,7 +302,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
case 0:
#ifdef CONFIG_SERIO
if (up->serio_open)
- serio_interrupt(up->serio, ch, 0, regs);
+ serio_interrupt(&up->serio, ch, 0, regs);
#endif
break;
};
@@ -330,12 +326,12 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
- sbus_writeb(ERR_RES, &channel->control);
+ writeb(ERR_RES, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
- ch = sbus_readb(&channel->control);
+ ch = readb(&channel->control);
ZSDELAY();
/* This funny hack depends upon BRK_ABRT not interfering
@@ -347,7 +343,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
if (!(ch & Rx_CH_AV))
break;
- ch = sbus_readb(&channel->data);
+ ch = readb(&channel->data);
ZSDELAY();
ch &= up->parity_mask;
@@ -406,10 +402,10 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
{
unsigned char status;
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
- sbus_writeb(RES_EXT_INT, &channel->control);
+ writeb(RES_EXT_INT, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -421,7 +417,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
* confusing the PROM.
*/
while (1) {
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
if (!(status & BRK_ABRT))
break;
@@ -458,7 +454,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
struct circ_buf *xmit;
if (ZS_IS_CONS(up)) {
- unsigned char status = sbus_readb(&channel->control);
+ unsigned char status = readb(&channel->control);
ZSDELAY();
/* TX still busy? Just wait for the next TX done interrupt.
@@ -487,7 +483,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
if (up->port.x_char) {
up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
- sbus_writeb(up->port.x_char, &channel->data);
+ writeb(up->port.x_char, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -506,7 +502,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
goto ack_tx_int;
up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
- sbus_writeb(xmit->buf[xmit->tail], &channel->data);
+ writeb(xmit->buf[xmit->tail], &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -519,7 +515,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
return;
ack_tx_int:
- sbus_writeb(RES_Tx_P, &channel->control);
+ writeb(RES_Tx_P, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
}
@@ -540,7 +536,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg
/* Channel A */
tty = NULL;
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
- sbus_writeb(RES_H_IUS, &channel->control);
+ writeb(RES_H_IUS, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -563,7 +559,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg
spin_lock(&up->port.lock);
tty = NULL;
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
- sbus_writeb(RES_H_IUS, &channel->control);
+ writeb(RES_H_IUS, &channel->control);
ZSDELAY();
ZS_WSYNC(channel);
@@ -594,7 +590,7 @@ static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *p
unsigned char status;
channel = ZILOG_CHANNEL_FROM_PORT(port);
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
return status;
@@ -682,7 +678,7 @@ static void sunzilog_start_tx(struct uart_port *port)
up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
- status = sbus_readb(&channel->control);
+ status = readb(&channel->control);
ZSDELAY();
/* TX busy? Just wait for the TX done interrupt. */
@@ -693,7 +689,7 @@ static void sunzilog_start_tx(struct uart_port *port)
* IRQ sending engine.
*/
if (port->x_char) {
- sbus_writeb(port->x_char, &channel->data);
+ writeb(port->x_char, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -702,7 +698,7 @@ static void sunzilog_start_tx(struct uart_port *port)
} else {
struct circ_buf *xmit = &port->info->xmit;
- sbus_writeb(xmit->buf[xmit->tail], &channel->data);
+ writeb(xmit->buf[xmit->tail], &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
@@ -779,7 +775,7 @@ static void __sunzilog_startup(struct uart_sunzilog_port *up)
struct zilog_channel __iomem *channel;
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- up->prev_status = sbus_readb(&channel->control);
+ up->prev_status = readb(&channel->control);
/* Enable receiver and transmitter. */
up->curregs[R3] |= RxENAB;
@@ -963,7 +959,7 @@ sunzilog_set_termios(struct uart_port *port, struct termios *termios,
static const char *sunzilog_type(struct uart_port *port)
{
- return "SunZilog";
+ return "zs";
}
/* We do not request/release mappings of the registers here, this
@@ -1012,242 +1008,55 @@ static struct uart_sunzilog_port *sunzilog_port_table;
static struct zilog_layout __iomem **sunzilog_chip_regs;
static struct uart_sunzilog_port *sunzilog_irq_chain;
-static int zilog_irq = -1;
static struct uart_driver sunzilog_reg = {
.owner = THIS_MODULE,
.driver_name = "ttyS",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
};
-static void * __init alloc_one_table(unsigned long size)
-{
- void *ret;
-
- ret = kmalloc(size, GFP_KERNEL);
- if (ret != NULL)
- memset(ret, 0, size);
-
- return ret;
-}
-
-static void __init sunzilog_alloc_tables(void)
-{
- sunzilog_port_table =
- alloc_one_table(NUM_CHANNELS * sizeof(struct uart_sunzilog_port));
- sunzilog_chip_regs =
- alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *));
-
- if (sunzilog_port_table == NULL || sunzilog_chip_regs == NULL) {
- prom_printf("SunZilog: Cannot allocate tables.\n");
- prom_halt();
- }
-}
-
-#ifdef CONFIG_SPARC64
-
-/* We used to attempt to use the address property of the Zilog device node
- * but that totally is not necessary on sparc64.
- */
-static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode)
+static int __init sunzilog_alloc_tables(void)
{
- void __iomem *mapped_addr;
- unsigned int sun4u_ino;
- struct sbus_bus *sbus = NULL;
- struct sbus_dev *sdev = NULL;
- int err;
-
- if (central_bus == NULL) {
- for_each_sbus(sbus) {
- for_each_sbusdev(sdev, sbus) {
- if (sdev->prom_node == zsnode)
- goto found;
- }
- }
- }
- found:
- if (sdev == NULL && central_bus == NULL) {
- prom_printf("SunZilog: sdev&&central == NULL for "
- "Zilog %d in get_zs_sun4u.\n", chip);
- prom_halt();
- }
- if (central_bus == NULL) {
- mapped_addr =
- sbus_ioremap(&sdev->resource[0], 0,
- PAGE_SIZE,
- "Zilog Registers");
- } else {
- struct linux_prom_registers zsregs[1];
-
- err = prom_getproperty(zsnode, "reg",
- (char *) &zsregs[0],
- sizeof(zsregs));
- if (err == -1) {
- prom_printf("SunZilog: Cannot map "
- "Zilog %d regs on "
- "central bus.\n", chip);
- prom_halt();
- }
- apply_fhc_ranges(central_bus->child,
- &zsregs[0], 1);
- apply_central_ranges(central_bus, &zsregs[0], 1);
- mapped_addr = (void __iomem *)
- ((((u64)zsregs[0].which_io)<<32UL) |
- ((u64)zsregs[0].phys_addr));
- }
-
- if (zilog_irq == -1) {
- if (central_bus) {
- unsigned long iclr, imap;
-
- iclr = central_bus->child->fhc_regs.uregs
- + FHC_UREGS_ICLR;
- imap = central_bus->child->fhc_regs.uregs
- + FHC_UREGS_IMAP;
- zilog_irq = build_irq(12, 0, iclr, imap);
- } else {
- err = prom_getproperty(zsnode, "interrupts",
- (char *) &sun4u_ino,
- sizeof(sun4u_ino));
- zilog_irq = sbus_build_irq(sbus_root, sun4u_ino);
- }
- }
-
- return (struct zilog_layout __iomem *) mapped_addr;
-}
-#else /* CONFIG_SPARC64 */
-
-/*
- * XXX The sun4d case is utterly screwed: it tries to re-walk the tree
- * (for the 3rd time) in order to find bootbus and cpu. Streamline it.
- */
-static struct zilog_layout __iomem * __init get_zs_sun4cmd(int chip, int node)
-{
- struct linux_prom_irqs irq_info[2];
- void __iomem *mapped_addr = NULL;
- int zsnode, cpunode, bbnode;
- struct linux_prom_registers zsreg[4];
- struct resource res;
-
- if (sparc_cpu_model == sun4d) {
- int walk;
-
- zsnode = 0;
- bbnode = 0;
- cpunode = 0;
- for (walk = prom_getchild(prom_root_node);
- (walk = prom_searchsiblings(walk, "cpu-unit")) != 0;
- walk = prom_getsibling(walk)) {
- bbnode = prom_getchild(walk);
- if (bbnode &&
- (bbnode = prom_searchsiblings(bbnode, "bootbus"))) {
- if ((zsnode = prom_getchild(bbnode)) == node) {
- cpunode = walk;
- break;
- }
- }
- }
- if (!walk) {
- prom_printf("SunZilog: Cannot find the %d'th bootbus on sun4d.\n",
- (chip / 2));
- prom_halt();
- }
+ struct uart_sunzilog_port *up;
+ unsigned long size;
+ int i;
- if (prom_getproperty(zsnode, "reg",
- (char *) zsreg, sizeof(zsreg)) == -1) {
- prom_printf("SunZilog: Cannot map Zilog %d\n", chip);
- prom_halt();
- }
- /* XXX Looks like an off by one? */
- prom_apply_generic_ranges(bbnode, cpunode, zsreg, 1);
- res.start = zsreg[0].phys_addr;
- res.end = res.start + (8 - 1);
- res.flags = zsreg[0].which_io | IORESOURCE_IO;
- mapped_addr = sbus_ioremap(&res, 0, 8, "Zilog Serial");
+ size = NUM_CHANNELS * sizeof(struct uart_sunzilog_port);
+ sunzilog_port_table = kzalloc(size, GFP_KERNEL);
+ if (!sunzilog_port_table)
+ return -ENOMEM;
- } else {
- zsnode = node;
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ up = &sunzilog_port_table[i];
-#if 0 /* XXX When was this used? */
- if (prom_getintdefault(zsnode, "slave", -1) != chipid) {
- zsnode = prom_getsibling(zsnode);
- continue;
- }
-#endif
+ spin_lock_init(&up->port.lock);
- /*
- * "address" is only present on ports that OBP opened
- * (from Mitch Bradley's "Hitchhiker's Guide to OBP").
- * We do not use it.
- */
+ if (i == 0)
+ sunzilog_irq_chain = up;
- if (prom_getproperty(zsnode, "reg",
- (char *) zsreg, sizeof(zsreg)) == -1) {
- prom_printf("SunZilog: Cannot map Zilog %d\n", chip);
- prom_halt();
- }
- if (sparc_cpu_model == sun4m) /* Crude. Pass parent. XXX */
- prom_apply_obio_ranges(zsreg, 1);
- res.start = zsreg[0].phys_addr;
- res.end = res.start + (8 - 1);
- res.flags = zsreg[0].which_io | IORESOURCE_IO;
- mapped_addr = sbus_ioremap(&res, 0, 8, "Zilog Serial");
+ if (i < NUM_CHANNELS - 1)
+ up->next = up + 1;
+ else
+ up->next = NULL;
}
- if (prom_getproperty(zsnode, "intr",
- (char *) irq_info, sizeof(irq_info))
- % sizeof(struct linux_prom_irqs)) {
- prom_printf("SunZilog: Cannot get IRQ property for Zilog %d.\n",
- chip);
- prom_halt();
- }
- if (zilog_irq == -1) {
- zilog_irq = irq_info[0].pri;
- } else if (zilog_irq != irq_info[0].pri) {
- /* XXX. Dumb. Should handle per-chip IRQ, for add-ons. */
- prom_printf("SunZilog: Inconsistent IRQ layout for Zilog %d.\n",
- chip);
- prom_halt();
+ size = NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *);
+ sunzilog_chip_regs = kzalloc(size, GFP_KERNEL);
+ if (!sunzilog_chip_regs) {
+ kfree(sunzilog_port_table);
+ sunzilog_irq_chain = NULL;
+ return -ENOMEM;
}
- return (struct zilog_layout __iomem *) mapped_addr;
+ return 0;
}
-#endif /* !(CONFIG_SPARC64) */
-/* Get the address of the registers for SunZilog instance CHIP. */
-static struct zilog_layout __iomem * __init get_zs(int chip, int node)
+static void sunzilog_free_tables(void)
{
- if (chip < 0 || chip >= NUM_SUNZILOG) {
- prom_printf("SunZilog: Illegal chip number %d in get_zs.\n", chip);
- prom_halt();
- }
-
-#ifdef CONFIG_SPARC64
- return get_zs_sun4u(chip, node);
-#else
-
- if (sparc_cpu_model == sun4) {
- struct resource res;
-
- /* Not probe-able, hard code it. */
- switch (chip) {
- case 0:
- res.start = 0xf1000000;
- break;
- case 1:
- res.start = 0xf0000000;
- break;
- };
- zilog_irq = 12;
- res.end = (res.start + (8 - 1));
- res.flags = IORESOURCE_IO;
- return sbus_ioremap(&res, 0, 8, "SunZilog");
- }
-
- return get_zs_sun4cmd(chip, node);
-#endif
+ kfree(sunzilog_port_table);
+ sunzilog_irq_chain = NULL;
+ kfree(sunzilog_chip_regs);
}
#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
@@ -1261,7 +1070,7 @@ static void sunzilog_putchar(struct uart_port *port, int ch)
* udelay with ZSDELAY as that is a NOP on some platforms. -DaveM
*/
do {
- unsigned char val = sbus_readb(&channel->control);
+ unsigned char val = readb(&channel->control);
if (val & Tx_BUF_EMP) {
ZSDELAY();
break;
@@ -1269,7 +1078,7 @@ static void sunzilog_putchar(struct uart_port *port, int ch)
udelay(5);
} while (--loops);
- sbus_writeb(ch, &channel->data);
+ writeb(ch, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
}
@@ -1386,28 +1195,6 @@ static struct console sunzilog_console = {
.data = &sunzilog_reg,
};
-static int __init sunzilog_console_init(void)
-{
- int i;
-
- if (con_is_present())
- return 0;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- int this_minor = sunzilog_reg.minor + i;
-
- if ((this_minor - 64) == (serial_console - 1))
- break;
- }
- if (i == NUM_CHANNELS)
- return 0;
-
- sunzilog_console.index = i;
- sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
- register_console(&sunzilog_console);
- return 0;
-}
-
static inline struct console *SUNZILOG_CONSOLE(void)
{
int i;
@@ -1432,101 +1219,8 @@ static inline struct console *SUNZILOG_CONSOLE(void)
#else
#define SUNZILOG_CONSOLE() (NULL)
-#define sunzilog_console_init() do { } while (0)
#endif
-/*
- * We scan the PROM tree recursively. This is the most reliable way
- * to find Zilog nodes on various platforms. However, we face an extreme
- * shortage of kernel stack, so we must be very careful. To that end,
- * we scan only to a certain depth, and we use a common property buffer
- * in the scan structure.
- */
-#define ZS_PROPSIZE 128
-#define ZS_SCAN_DEPTH 5
-
-struct zs_probe_scan {
- int depth;
- void (*scanner)(struct zs_probe_scan *t, int node);
-
- int devices;
- char prop[ZS_PROPSIZE];
-};
-
-static int __inline__ sunzilog_node_ok(int node, const char *name, int len)
-{
- if (strncmp(name, "zs", len) == 0)
- return 1;
- /* Don't fold this procedure just yet. Compare to su_node_ok(). */
- return 0;
-}
-
-static void __init sunzilog_scan(struct zs_probe_scan *t, int node)
-{
- int len;
-
- for (; node != 0; node = prom_getsibling(node)) {
- len = prom_getproperty(node, "name", t->prop, ZS_PROPSIZE);
- if (len <= 1)
- continue; /* Broken PROM node */
- if (sunzilog_node_ok(node, t->prop, len)) {
- (*t->scanner)(t, node);
- } else {
- if (t->depth < ZS_SCAN_DEPTH) {
- t->depth++;
- sunzilog_scan(t, prom_getchild(node));
- --t->depth;
- }
- }
- }
-}
-
-static void __init sunzilog_prepare(void)
-{
- struct uart_sunzilog_port *up;
- struct zilog_layout __iomem *rp;
- int channel, chip;
-
- /*
- * Temporary fix.
- */
- for (channel = 0; channel < NUM_CHANNELS; channel++)
- spin_lock_init(&sunzilog_port_table[channel].port.lock);
-
- sunzilog_irq_chain = up = &sunzilog_port_table[0];
- for (channel = 0; channel < NUM_CHANNELS - 1; channel++)
- up[channel].next = &up[channel + 1];
- up[channel].next = NULL;
-
- for (chip = 0; chip < NUM_SUNZILOG; chip++) {
- rp = sunzilog_chip_regs[chip];
- up[(chip * 2) + 0].port.membase = (void __iomem *)&rp->channelA;
- up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB;
-
- /* Channel A */
- up[(chip * 2) + 0].port.iotype = UPIO_MEM;
- up[(chip * 2) + 0].port.irq = zilog_irq;
- up[(chip * 2) + 0].port.uartclk = ZS_CLOCK;
- up[(chip * 2) + 0].port.fifosize = 1;
- up[(chip * 2) + 0].port.ops = &sunzilog_pops;
- up[(chip * 2) + 0].port.type = PORT_SUNZILOG;
- up[(chip * 2) + 0].port.flags = 0;
- up[(chip * 2) + 0].port.line = (chip * 2) + 0;
- up[(chip * 2) + 0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
-
- /* Channel B */
- up[(chip * 2) + 1].port.iotype = UPIO_MEM;
- up[(chip * 2) + 1].port.irq = zilog_irq;
- up[(chip * 2) + 1].port.uartclk = ZS_CLOCK;
- up[(chip * 2) + 1].port.fifosize = 1;
- up[(chip * 2) + 1].port.ops = &sunzilog_pops;
- up[(chip * 2) + 1].port.type = PORT_SUNZILOG;
- up[(chip * 2) + 1].port.flags = 0;
- up[(chip * 2) + 1].port.line = (chip * 2) + 1;
- up[(chip * 2) + 1].flags |= 0;
- }
-}
-
static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channel)
{
int baud, brg;
@@ -1540,8 +1234,6 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
up->cflag = B4800 | CS8 | CLOCAL | CREAD;
baud = 4800;
}
- printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a SunZilog\n",
- channel, up->port.membase, __irq_itoa(zilog_irq));
up->curregs[R15] = BRKIE;
brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
@@ -1553,216 +1245,268 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
#ifdef CONFIG_SERIO
static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel)
{
- struct serio *serio;
-
- up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(*serio));
-
- serio->port_data = up;
-
- serio->id.type = SERIO_RS232;
- if (channel == KEYBOARD_LINE) {
- serio->id.proto = SERIO_SUNKBD;
- strlcpy(serio->name, "zskbd", sizeof(serio->name));
- } else {
- serio->id.proto = SERIO_SUN;
- serio->id.extra = 1;
- strlcpy(serio->name, "zsms", sizeof(serio->name));
- }
- strlcpy(serio->phys,
- (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
- sizeof(serio->phys));
+ struct serio *serio = &up->serio;
- serio->write = sunzilog_serio_write;
- serio->open = sunzilog_serio_open;
- serio->close = sunzilog_serio_close;
+ serio->port_data = up;
- serio_register_port(serio);
+ serio->id.type = SERIO_RS232;
+ if (channel == KEYBOARD_LINE) {
+ serio->id.proto = SERIO_SUNKBD;
+ strlcpy(serio->name, "zskbd", sizeof(serio->name));
} else {
- printk(KERN_WARNING "zs%d: not enough memory for serio port\n",
- channel);
+ serio->id.proto = SERIO_SUN;
+ serio->id.extra = 1;
+ strlcpy(serio->name, "zsms", sizeof(serio->name));
}
+ strlcpy(serio->phys,
+ (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
+ sizeof(serio->phys));
+
+ serio->write = sunzilog_serio_write;
+ serio->open = sunzilog_serio_open;
+ serio->close = sunzilog_serio_close;
+ serio->dev.parent = up->port.dev;
+
+ serio_register_port(serio);
}
#endif
-static void __init sunzilog_init_hw(void)
+static void __init sunzilog_init_hw(struct uart_sunzilog_port *up)
{
- int i;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
- struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- unsigned long flags;
- int baud, brg;
+ struct zilog_channel __iomem *channel;
+ unsigned long flags;
+ int baud, brg;
- spin_lock_irqsave(&up->port.lock, flags);
+ channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
- if (ZS_IS_CHANNEL_A(up)) {
- write_zsreg(channel, R9, FHWRES);
- ZSDELAY_LONG();
- (void) read_zsreg(channel, R0);
- }
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (ZS_IS_CHANNEL_A(up)) {
+ write_zsreg(channel, R9, FHWRES);
+ ZSDELAY_LONG();
+ (void) read_zsreg(channel, R0);
+ }
- if (i == KEYBOARD_LINE || i == MOUSE_LINE) {
- sunzilog_init_kbdms(up, i);
- up->curregs[R9] |= (NV | MIE);
- write_zsreg(channel, R9, up->curregs[R9]);
- } else {
- /* Normal serial TTY. */
- up->parity_mask = 0xff;
- up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
- up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
- up->curregs[R3] = RxENAB | Rx8;
- up->curregs[R5] = TxENAB | Tx8;
- up->curregs[R9] = NV | MIE;
- up->curregs[R10] = NRZ;
- up->curregs[R11] = TCBR | RCBR;
- baud = 9600;
- brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
- up->curregs[R12] = (brg & 0xff);
- up->curregs[R13] = (brg >> 8) & 0xff;
- up->curregs[R14] = BRSRC | BRENAB;
- __load_zsregs(channel, up->curregs);
- write_zsreg(channel, R9, up->curregs[R9]);
- }
+ if (up->port.line == KEYBOARD_LINE ||
+ up->port.line == MOUSE_LINE) {
+ sunzilog_init_kbdms(up, up->port.line);
+ up->curregs[R9] |= (NV | MIE);
+ write_zsreg(channel, R9, up->curregs[R9]);
+ } else {
+ /* Normal serial TTY. */
+ up->parity_mask = 0xff;
+ up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
+ up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
+ up->curregs[R3] = RxENAB | Rx8;
+ up->curregs[R5] = TxENAB | Tx8;
+ up->curregs[R9] = NV | MIE;
+ up->curregs[R10] = NRZ;
+ up->curregs[R11] = TCBR | RCBR;
+ baud = 9600;
+ brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+ up->curregs[R12] = (brg & 0xff);
+ up->curregs[R13] = (brg >> 8) & 0xff;
+ up->curregs[R14] = BRSRC | BRENAB;
+ __load_zsregs(channel, up->curregs);
+ write_zsreg(channel, R9, up->curregs[R9]);
+ }
- spin_unlock_irqrestore(&up->port.lock, flags);
+ spin_unlock_irqrestore(&up->port.lock, flags);
#ifdef CONFIG_SERIO
- if (i == KEYBOARD_LINE || i == MOUSE_LINE)
- sunzilog_register_serio(up, i);
+ if (up->port.line == KEYBOARD_LINE || up->port.line == MOUSE_LINE)
+ sunzilog_register_serio(up, up->port.line);
#endif
- }
-}
-
-static struct zilog_layout __iomem * __init get_zs(int chip, int node);
-
-static void __init sunzilog_scan_probe(struct zs_probe_scan *t, int node)
-{
- sunzilog_chip_regs[t->devices] = get_zs(t->devices, node);
- t->devices++;
}
-static int __init sunzilog_ports_init(void)
+static int __devinit zs_get_instance(struct device_node *dp)
{
- struct zs_probe_scan scan;
int ret;
- int uart_count;
- int i;
-
- printk(KERN_DEBUG "SunZilog: %d chips.\n", NUM_SUNZILOG);
-
- scan.scanner = sunzilog_scan_probe;
- scan.depth = 0;
- scan.devices = 0;
- sunzilog_scan(&scan, prom_getchild(prom_root_node));
-
- sunzilog_prepare();
- if (request_irq(zilog_irq, sunzilog_interrupt, SA_SHIRQ,
- "SunZilog", sunzilog_irq_chain)) {
- prom_printf("SunZilog: Unable to register zs interrupt handler.\n");
- prom_halt();
- }
+ ret = of_getintprop_default(dp, "slave", -1);
+ if (ret != -1)
+ return ret;
- sunzilog_init_hw();
+ if (of_find_property(dp, "keyboard", NULL))
+ ret = 1;
+ else
+ ret = 0;
- /* We can only init this once we have probed the Zilogs
- * in the system. Do not count channels assigned to keyboards
- * or mice when we are deciding how many ports to register.
- */
- uart_count = 0;
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
+ return ret;
+}
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
- continue;
+static int zilog_irq = -1;
- uart_count++;
- }
-
- sunzilog_reg.nr = uart_count;
- sunzilog_reg.minor = sunserial_current_minor;
+static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match)
+{
+ struct of_device *op = to_of_device(&dev->dev);
+ struct uart_sunzilog_port *up;
+ struct zilog_layout __iomem *rp;
+ int inst = zs_get_instance(dev->node);
+ int err;
- ret = uart_register_driver(&sunzilog_reg);
- if (ret == 0) {
- sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
- sunzilog_reg.cons = SUNZILOG_CONSOLE();
+ sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
+ sizeof(struct zilog_layout),
+ "zs");
+ if (!sunzilog_chip_regs[inst])
+ return -ENOMEM;
- sunserial_current_minor += uart_count;
+ rp = sunzilog_chip_regs[inst];
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
+ if (zilog_irq == -1) {
+ zilog_irq = op->irqs[0];
+ err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
+ "zs", sunzilog_irq_chain);
+ if (err) {
+ of_iounmap(rp, sizeof(struct zilog_layout));
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
- continue;
+ return err;
+ }
+ }
- if (uart_add_one_port(&sunzilog_reg, &up->port)) {
- printk(KERN_ERR
- "SunZilog: failed to add port zs%d\n", i);
- }
+ up = &sunzilog_port_table[inst * 2];
+
+ /* Channel A */
+ up[0].port.mapbase = op->resource[0].start + 0x00;
+ up[0].port.membase = (void __iomem *) &rp->channelA;
+ up[0].port.iotype = UPIO_MEM;
+ up[0].port.irq = op->irqs[0];
+ up[0].port.uartclk = ZS_CLOCK;
+ up[0].port.fifosize = 1;
+ up[0].port.ops = &sunzilog_pops;
+ up[0].port.type = PORT_SUNZILOG;
+ up[0].port.flags = 0;
+ up[0].port.line = (inst * 2) + 0;
+ up[0].port.dev = &op->dev;
+ up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
+ if (inst == 1)
+ up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
+ sunzilog_init_hw(&up[0]);
+
+ /* Channel B */
+ up[1].port.mapbase = op->resource[0].start + 0x04;
+ up[1].port.membase = (void __iomem *) &rp->channelB;
+ up[1].port.iotype = UPIO_MEM;
+ up[1].port.irq = op->irqs[0];
+ up[1].port.uartclk = ZS_CLOCK;
+ up[1].port.fifosize = 1;
+ up[1].port.ops = &sunzilog_pops;
+ up[1].port.type = PORT_SUNZILOG;
+ up[1].port.flags = 0;
+ up[1].port.line = (inst * 2) + 1;
+ up[1].port.dev = &op->dev;
+ up[1].flags |= 0;
+ if (inst == 1)
+ up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
+ sunzilog_init_hw(&up[1]);
+
+ if (inst != 1) {
+ err = uart_add_one_port(&sunzilog_reg, &up[0].port);
+ if (err) {
+ of_iounmap(rp, sizeof(struct zilog_layout));
+ return err;
+ }
+ err = uart_add_one_port(&sunzilog_reg, &up[1].port);
+ if (err) {
+ uart_remove_one_port(&sunzilog_reg, &up[0].port);
+ of_iounmap(rp, sizeof(struct zilog_layout));
+ return err;
}
}
- return ret;
+ dev_set_drvdata(&dev->dev, &up[0]);
+
+ return 0;
}
-static void __init sunzilog_scan_count(struct zs_probe_scan *t, int node)
+static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
{
- t->devices++;
+ if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
+#ifdef CONFIG_SERIO
+ serio_unregister_port(&up->serio);
+#endif
+ } else
+ uart_remove_one_port(&sunzilog_reg, &up->port);
}
-static int __init sunzilog_ports_count(void)
+static int __devexit zs_remove(struct of_device *dev)
{
- struct zs_probe_scan scan;
+ struct uart_sunzilog_port *up = dev_get_drvdata(&dev->dev);
+ struct zilog_layout __iomem *regs;
- /* Sun4 Zilog setup is hard coded, no probing to do. */
- if (sparc_cpu_model == sun4)
- return 2;
+ zs_remove_one(&up[0]);
+ zs_remove_one(&up[1]);
- scan.scanner = sunzilog_scan_count;
- scan.depth = 0;
- scan.devices = 0;
+ regs = sunzilog_chip_regs[up[0].port.line / 2];
+ of_iounmap(regs, sizeof(struct zilog_layout));
- sunzilog_scan(&scan, prom_getchild(prom_root_node));
+ dev_set_drvdata(&dev->dev, NULL);
- return scan.devices;
+ return 0;
}
+static struct of_device_id zs_match[] = {
+ {
+ .name = "zs",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, zs_match);
+
+static struct of_platform_driver zs_driver = {
+ .name = "zs",
+ .match_table = zs_match,
+ .probe = zs_probe,
+ .remove = __devexit_p(zs_remove),
+};
+
static int __init sunzilog_init(void)
{
+ struct device_node *dp;
+ int err;
- NUM_SUNZILOG = sunzilog_ports_count();
- if (NUM_SUNZILOG == 0)
- return -ENODEV;
+ NUM_SUNZILOG = 0;
+ for_each_node_by_name(dp, "zs")
+ NUM_SUNZILOG++;
- sunzilog_alloc_tables();
+ if (NUM_SUNZILOG) {
+ int uart_count;
- sunzilog_ports_init();
+ err = sunzilog_alloc_tables();
+ if (err)
+ return err;
- return 0;
+ /* Subtract 1 for keyboard, 1 for mouse. */
+ uart_count = (NUM_SUNZILOG * 2) - 2;
+
+ sunzilog_reg.nr = uart_count;
+ sunzilog_reg.minor = sunserial_current_minor;
+ err = uart_register_driver(&sunzilog_reg);
+ if (err) {
+ sunzilog_free_tables();
+ return err;
+ }
+ sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
+ sunzilog_reg.cons = SUNZILOG_CONSOLE();
+
+ sunserial_current_minor += uart_count;
+ }
+
+ return of_register_driver(&zs_driver, &of_bus_type);
}
static void __exit sunzilog_exit(void)
{
- int i;
+ of_unregister_driver(&zs_driver);
- for (i = 0; i < NUM_CHANNELS; i++) {
- struct uart_sunzilog_port *up = &sunzilog_port_table[i];
-
- if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
-#ifdef CONFIG_SERIO
- if (up->serio) {
- serio_unregister_port(up->serio);
- up->serio = NULL;
- }
-#endif
- } else
- uart_remove_one_port(&sunzilog_reg, &up->port);
+ if (zilog_irq != -1) {
+ free_irq(zilog_irq, sunzilog_irq_chain);
+ zilog_irq = -1;
}
- uart_unregister_driver(&sunzilog_reg);
+ if (NUM_SUNZILOG) {
+ uart_unregister_driver(&sunzilog_reg);
+ sunzilog_free_tables();
+ }
}
module_init(sunzilog_init);
@@ -1770,4 +1514,5 @@ module_exit(sunzilog_exit);
MODULE_AUTHOR("David S. Miller");
MODULE_DESCRIPTION("Sun Zilog serial port driver");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
index df705fda424..f802867c95c 100644
--- a/drivers/serial/v850e_uart.c
+++ b/drivers/serial/v850e_uart.c
@@ -372,13 +372,13 @@ static int v850e_uart_startup (struct uart_port *port)
/* Alloc RX irq. */
err = request_irq (V850E_UART_RX_IRQ (port->line), v850e_uart_rx_irq,
- SA_INTERRUPT, "v850e_uart", port);
+ IRQF_DISABLED, "v850e_uart", port);
if (err)
return err;
/* Alloc TX irq. */
err = request_irq (V850E_UART_TX_IRQ (port->line), v850e_uart_tx_irq,
- SA_INTERRUPT, "v850e_uart", port);
+ IRQF_DISABLED, "v850e_uart", port);
if (err) {
free_irq (V850E_UART_RX_IRQ (port->line), port);
return err;
@@ -468,7 +468,6 @@ static struct uart_ops v850e_uart_ops = {
static struct uart_driver v850e_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "v850e_uart",
- .devfs_name = "tts/",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = V850E_UART_MINOR_BASE,
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index df5e8713fa3..e93d0edc2e0 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -19,7 +19,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#if defined(CONFIG_SERIAL_VR41XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -911,7 +910,6 @@ static struct uart_driver siu_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "SIU",
.dev_name = "ttyVR",
- .devfs_name = "ttvr/",
.major = SIU_MAJOR,
.minor = SIU_MINOR_BASE,
.cons = SERIAL_VR41XX_CONSOLE,