summaryrefslogtreecommitdiff
path: root/drivers/tty/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/68328serial.c2
-rw-r--r--drivers/tty/serial/8250/8250.c98
-rw-r--r--drivers/tty/serial/8250/8250.h36
-rw-r--r--drivers/tty/serial/8250/8250_acorn.c6
-rw-r--r--drivers/tty/serial/8250/8250_dw.c31
-rw-r--r--drivers/tty/serial/8250/8250_early.c46
-rw-r--r--drivers/tty/serial/8250/8250_em.c8
-rw-r--r--drivers/tty/serial/8250/8250_hp300.c10
-rw-r--r--drivers/tty/serial/8250/8250_pci.c352
-rw-r--r--drivers/tty/serial/8250/8250_pnp.c14
-rw-r--r--drivers/tty/serial/Kconfig48
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/altera_jtaguart.c6
-rw-r--r--drivers/tty/serial/altera_uart.c6
-rw-r--r--drivers/tty/serial/amba-pl011.c25
-rw-r--r--drivers/tty/serial/apbuart.c2
-rw-r--r--drivers/tty/serial/ar933x_uart.c96
-rw-r--r--drivers/tty/serial/arc_uart.c746
-rw-r--r--drivers/tty/serial/atmel_serial.c18
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c6
-rw-r--r--drivers/tty/serial/bfin_sport_uart.c6
-rw-r--r--drivers/tty/serial/bfin_uart.c20
-rw-r--r--drivers/tty/serial/clps711x.c595
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c4
-rw-r--r--drivers/tty/serial/efm32-uart.c6
-rw-r--r--drivers/tty/serial/icom.c14
-rw-r--r--drivers/tty/serial/ifx6x60.c168
-rw-r--r--drivers/tty/serial/ifx6x60.h2
-rw-r--r--drivers/tty/serial/ioc3_serial.c2
-rw-r--r--drivers/tty/serial/jsm/jsm.h8
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c9
-rw-r--r--drivers/tty/serial/jsm/jsm_neo.c116
-rw-r--r--drivers/tty/serial/jsm/jsm_tty.c104
-rw-r--r--drivers/tty/serial/kgdb_nmi.c2
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c6
-rw-r--r--drivers/tty/serial/max3100.c6
-rw-r--r--drivers/tty/serial/max310x.c12
-rw-r--r--drivers/tty/serial/mcf.c6
-rw-r--r--drivers/tty/serial/mfd.c7
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c2
-rw-r--r--drivers/tty/serial/mrst_max3110.c6
-rw-r--r--drivers/tty/serial/msm_serial.c2
-rw-r--r--drivers/tty/serial/msm_serial_hs.c8
-rw-r--r--drivers/tty/serial/mux.c6
-rw-r--r--drivers/tty/serial/mxs-auart.c376
-rw-r--r--drivers/tty/serial/of_serial.c38
-rw-r--r--drivers/tty/serial/omap-serial.c259
-rw-r--r--drivers/tty/serial/pch_uart.c4
-rw-r--r--drivers/tty/serial/pxa.c55
-rw-r--r--drivers/tty/serial/sa1100.c2
-rw-r--r--drivers/tty/serial/samsung.c46
-rw-r--r--drivers/tty/serial/sc26xx.c6
-rw-r--r--drivers/tty/serial/sccnxp.c6
-rw-r--r--drivers/tty/serial/serial_core.c257
-rw-r--r--drivers/tty/serial/serial_txx9.c16
-rw-r--r--drivers/tty/serial/sh-sci.c154
-rw-r--r--drivers/tty/serial/sirfsoc_uart.c4
-rw-r--r--drivers/tty/serial/sunhv.c6
-rw-r--r--drivers/tty/serial/sunsab.c8
-rw-r--r--drivers/tty/serial/sunsu.c10
-rw-r--r--drivers/tty/serial/sunzilog.c14
-rw-r--r--drivers/tty/serial/timbuart.c6
-rw-r--r--drivers/tty/serial/uartlite.c14
-rw-r--r--drivers/tty/serial/vr41xx_siu.c8
-rw-r--r--drivers/tty/serial/vt8500_serial.c14
-rw-r--r--drivers/tty/serial/xilinx_uartps.c15
66 files changed, 3006 insertions, 986 deletions
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index 66c38a3f74ce..f99a84526f82 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -1225,6 +1225,8 @@ rs68328_init(void)
if (tty_register_driver(serial_driver)) {
put_tty_driver(serial_driver);
+ for (i = 0; i < NR_PORTS; i++)
+ tty_port_destroy(&m68k_soft[i].tport);
printk(KERN_ERR "Couldn't register serial driver\n");
return -ENOMEM;
}
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 3ba4234592bc..d085e3a8ec06 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -280,7 +280,17 @@ static const struct serial8250_config uart_config[] = {
.fifo_size = 64,
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP,
+ },
+ [PORT_XR17V35X] = {
+ .name = "XR17V35X",
+ .fifo_size = 256,
+ .tx_loadsz = 256,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
+ UART_FCR_T_TRIG_11,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP,
},
[PORT_LPC3220] = {
.name = "LPC3220",
@@ -455,6 +465,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
}
static int serial8250_default_handle_irq(struct uart_port *port);
+static int exar_handle_irq(struct uart_port *port);
static void set_io_from_upio(struct uart_port *p)
{
@@ -574,6 +585,19 @@ EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
*/
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
+ /*
+ * Exar UARTs have a SLEEP register that enables or disables
+ * each UART to enter sleep mode separately. On the XR17V35x the
+ * register is accessible to each UART at the UART_EXAR_SLEEP
+ * offset but the UART channel may only write to the corresponding
+ * bit.
+ */
+ if ((p->port.type == PORT_XR17V35X) ||
+ (p->port.type == PORT_XR17D15X)) {
+ serial_out(p, UART_EXAR_SLEEP, 0xff);
+ return;
+ }
+
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -882,6 +906,27 @@ static void autoconfig_16550a(struct uart_8250_port *up)
up->capabilities |= UART_CAP_FIFO;
/*
+ * XR17V35x UARTs have an extra divisor register, DLD
+ * that gets enabled with when DLAB is set which will
+ * cause the device to incorrectly match and assign
+ * port type to PORT_16650. The EFR for this UART is
+ * found at offset 0x09. Instead check the Deice ID (DVID)
+ * register for a 2, 4 or 8 port UART.
+ */
+ if (up->port.flags & UPF_EXAR_EFR) {
+ status1 = serial_in(up, UART_EXAR_DVID);
+ if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
+ DEBUG_AUTOCONF("Exar XR17V35x ");
+ up->port.type = PORT_XR17V35X;
+ up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP;
+
+ return;
+ }
+
+ }
+
+ /*
* Check for presence of the EFR when DLAB is set.
* Only ST16C650V1 UARTs pass this test.
*/
@@ -1013,8 +1058,12 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* Exar uarts have EFR in a weird location
*/
if (up->port.flags & UPF_EXAR_EFR) {
+ DEBUG_AUTOCONF("Exar XR17D15x ");
up->port.type = PORT_XR17D15X;
- up->capabilities |= UART_CAP_AFE | UART_CAP_EFR;
+ up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP;
+
+ return;
}
/*
@@ -1516,6 +1565,31 @@ static int serial8250_default_handle_irq(struct uart_port *port)
}
/*
+ * These Exar UARTs have an extra interrupt indicator that could
+ * fire for a few unimplemented interrupts. One of which is a
+ * wakeup event when coming out of sleep. Put this here just
+ * to be on the safe side that these interrupts don't go unhandled.
+ */
+static int exar_handle_irq(struct uart_port *port)
+{
+ unsigned char int0, int1, int2, int3;
+ unsigned int iir = serial_port_in(port, UART_IIR);
+ int ret;
+
+ ret = serial8250_handle_irq(port, iir);
+
+ if ((port->type == PORT_XR17V35X) ||
+ (port->type == PORT_XR17D15X)) {
+ int0 = serial_port_in(port, 0x80);
+ int1 = serial_port_in(port, 0x81);
+ int2 = serial_port_in(port, 0x82);
+ int3 = serial_port_in(port, 0x83);
+ }
+
+ return ret;
+}
+
+/*
* This is the serial driver's interrupt routine.
*
* Arjan thinks the old way was overly complex, so it got simplified.
@@ -2349,16 +2423,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
serial_port_out(port, UART_EFR, efr);
}
-#ifdef CONFIG_ARCH_OMAP1
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
- if (cpu_is_omap1510() && is_omap_port(up)) {
+ if (is_omap1510_8250(up)) {
if (baud == 115200) {
quot = 1;
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
} else
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
}
-#endif
/*
* For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
@@ -2439,10 +2511,9 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
{
if (pt->port.iotype == UPIO_AU)
return 0x1000;
-#ifdef CONFIG_ARCH_OMAP1
- if (is_omap_port(pt))
+ if (is_omap1_8250(pt))
return 0x16 << pt->port.regshift;
-#endif
+
return 8 << pt->port.regshift;
}
@@ -2617,6 +2688,11 @@ static void serial8250_config_port(struct uart_port *port, int flags)
serial8250_release_rsa_resource(up);
if (port->type == PORT_UNKNOWN)
serial8250_release_std_resource(up);
+
+ /* Fixme: probably not the best place for this */
+ if ((port->type == PORT_XR17V35X) ||
+ (port->type == PORT_XR17D15X))
+ port->handle_irq = exar_handle_irq;
}
static int
@@ -2992,7 +3068,7 @@ void serial8250_resume_port(int line)
* list is terminated with a zero flags entry, which means we expect
* all entries to have at least UPF_BOOT_AUTOCONF set.
*/
-static int __devinit serial8250_probe(struct platform_device *dev)
+static int serial8250_probe(struct platform_device *dev)
{
struct plat_serial8250_port *p = dev->dev.platform_data;
struct uart_8250_port uart;
@@ -3038,7 +3114,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
/*
* Remove serial ports registered against a platform device.
*/
-static int __devexit serial8250_remove(struct platform_device *dev)
+static int serial8250_remove(struct platform_device *dev)
{
int i;
@@ -3081,7 +3157,7 @@ static int serial8250_resume(struct platform_device *dev)
static struct platform_driver serial8250_isa_driver = {
.probe = serial8250_probe,
- .remove = __devexit_p(serial8250_remove),
+ .remove = serial8250_remove,
.suspend = serial8250_suspend,
.resume = serial8250_resume,
.driver = {
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 5a76f9c8d36b..3b4ea84898c2 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -106,3 +106,39 @@ static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { }
#endif
+#ifdef CONFIG_ARCH_OMAP1
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+ int res;
+
+ switch (pt->port.mapbase) {
+ case OMAP1_UART1_BASE:
+ case OMAP1_UART2_BASE:
+ case OMAP1_UART3_BASE:
+ res = 1;
+ break;
+ default:
+ res = 0;
+ break;
+ }
+
+ return res;
+}
+
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+ if (!cpu_is_omap1510())
+ return 0;
+
+ return is_omap1_8250(pt);
+}
+#else
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+ return 0;
+}
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+ return 0;
+}
+#endif
diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
index 857498312a9a..549aa07c0d27 100644
--- a/drivers/tty/serial/8250/8250_acorn.c
+++ b/drivers/tty/serial/8250/8250_acorn.c
@@ -38,7 +38,7 @@ struct serial_card_info {
void __iomem *vaddr;
};
-static int __devinit
+static int
serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct serial_card_info *info;
@@ -80,7 +80,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
return 0;
}
-static void __devexit serial_card_remove(struct expansion_card *ec)
+static void serial_card_remove(struct expansion_card *ec)
{
struct serial_card_info *info = ecard_get_drvdata(ec);
int i;
@@ -116,7 +116,7 @@ static const struct ecard_id serial_cids[] = {
static struct ecard_driver serial_card_driver = {
.probe = serial_card_probe,
- .remove = __devexit_p(serial_card_remove),
+ .remove = serial_card_remove,
.id_table = serial_cids,
.drv = {
.name = "8250_acorn",
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index c3b2ec0c8c0b..1d0dba2d562d 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -87,7 +87,7 @@ static int dw8250_handle_irq(struct uart_port *p)
return 0;
}
-static int __devinit dw8250_probe(struct platform_device *pdev)
+static int dw8250_probe(struct platform_device *pdev)
{
struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -152,7 +152,7 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit dw8250_remove(struct platform_device *pdev)
+static int dw8250_remove(struct platform_device *pdev)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
@@ -161,6 +161,29 @@ static int __devexit dw8250_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct dw8250_data *data = platform_get_drvdata(pdev);
+
+ serial8250_suspend_port(data->line);
+
+ return 0;
+}
+
+static int dw8250_resume(struct platform_device *pdev)
+{
+ struct dw8250_data *data = platform_get_drvdata(pdev);
+
+ serial8250_resume_port(data->line);
+
+ return 0;
+}
+#else
+#define dw8250_suspend NULL
+#define dw8250_resume NULL
+#endif /* CONFIG_PM */
+
static const struct of_device_id dw8250_match[] = {
{ .compatible = "snps,dw-apb-uart" },
{ /* Sentinel */ }
@@ -174,7 +197,9 @@ static struct platform_driver dw8250_platform_driver = {
.of_match_table = dw8250_match,
},
.probe = dw8250_probe,
- .remove = __devexit_p(dw8250_remove),
+ .remove = dw8250_remove,
+ .suspend = dw8250_suspend,
+ .resume = dw8250_resume,
};
module_platform_driver(dw8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index eaafb98debed..f53a7db4350d 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -48,7 +48,7 @@ struct early_serial8250_device {
static struct early_serial8250_device early_device;
-static unsigned int __init serial_in(struct uart_port *port, int offset)
+unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
{
switch (port->iotype) {
case UPIO_MEM:
@@ -62,7 +62,7 @@ static unsigned int __init serial_in(struct uart_port *port, int offset)
}
}
-static void __init serial_out(struct uart_port *port, int offset, int value)
+void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
{
switch (port->iotype) {
case UPIO_MEM:
@@ -84,7 +84,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
unsigned int status;
for (;;) {
- status = serial_in(port, UART_LSR);
+ status = serial8250_early_in(port, UART_LSR);
if ((status & BOTH_EMPTY) == BOTH_EMPTY)
return;
cpu_relax();
@@ -94,7 +94,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
static void __init serial_putc(struct uart_port *port, int c)
{
wait_for_xmitr(port);
- serial_out(port, UART_TX, c);
+ serial8250_early_out(port, UART_TX, c);
}
static void __init early_serial8250_write(struct console *console,
@@ -104,14 +104,14 @@ static void __init early_serial8250_write(struct console *console,
unsigned int ier;
/* Save the IER and disable interrupts */
- ier = serial_in(port, UART_IER);
- serial_out(port, UART_IER, 0);
+ ier = serial8250_early_in(port, UART_IER);
+ serial8250_early_out(port, UART_IER, 0);
uart_console_write(port, s, count, serial_putc);
/* Wait for transmitter to become empty and restore the IER */
wait_for_xmitr(port);
- serial_out(port, UART_IER, ier);
+ serial8250_early_out(port, UART_IER, ier);
}
static unsigned int __init probe_baud(struct uart_port *port)
@@ -119,11 +119,11 @@ static unsigned int __init probe_baud(struct uart_port *port)
unsigned char lcr, dll, dlm;
unsigned int quot;
- lcr = serial_in(port, UART_LCR);
- serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
- dll = serial_in(port, UART_DLL);
- dlm = serial_in(port, UART_DLM);
- serial_out(port, UART_LCR, lcr);
+ lcr = serial8250_early_in(port, UART_LCR);
+ serial8250_early_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+ dll = serial8250_early_in(port, UART_DLL);
+ dlm = serial8250_early_in(port, UART_DLM);
+ serial8250_early_out(port, UART_LCR, lcr);
quot = (dlm << 8) | dll;
return (port->uartclk / 16) / quot;
@@ -135,17 +135,17 @@ static void __init init_port(struct early_serial8250_device *device)
unsigned int divisor;
unsigned char c;
- serial_out(port, UART_LCR, 0x3); /* 8n1 */
- serial_out(port, UART_IER, 0); /* no interrupt */
- serial_out(port, UART_FCR, 0); /* no fifo */
- serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
-
- divisor = port->uartclk / (16 * device->baud);
- c = serial_in(port, UART_LCR);
- serial_out(port, UART_LCR, c | UART_LCR_DLAB);
- serial_out(port, UART_DLL, divisor & 0xff);
- serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
- serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
+ serial8250_early_out(port, UART_LCR, 0x3); /* 8n1 */
+ serial8250_early_out(port, UART_IER, 0); /* no interrupt */
+ serial8250_early_out(port, UART_FCR, 0); /* no fifo */
+ serial8250_early_out(port, UART_MCR, 0x3); /* DTR + RTS */
+
+ divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
+ c = serial8250_early_in(port, UART_LCR);
+ serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
+ serial8250_early_out(port, UART_DLL, divisor & 0xff);
+ serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff);
+ serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
}
static int __init parse_options(struct early_serial8250_device *device,
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index 3a0363e7f3a7..916cc19fbbda 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -89,7 +89,7 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
}
-static int __devinit serial8250_em_probe(struct platform_device *pdev)
+static int serial8250_em_probe(struct platform_device *pdev)
{
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -152,7 +152,7 @@ static int __devinit serial8250_em_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit serial8250_em_remove(struct platform_device *pdev)
+static int serial8250_em_remove(struct platform_device *pdev)
{
struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
@@ -163,7 +163,7 @@ static int __devexit serial8250_em_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = {
+static const struct of_device_id serial8250_em_dt_ids[] = {
{ .compatible = "renesas,em-uart", },
{},
};
@@ -176,7 +176,7 @@ static struct platform_driver serial8250_em_platform_driver = {
.owner = THIS_MODULE,
},
.probe = serial8250_em_probe,
- .remove = __devexit_p(serial8250_em_remove),
+ .remove = serial8250_em_remove,
};
module_platform_driver(serial8250_em_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
index f3d0edf46644..5bdaf271d395 100644
--- a/drivers/tty/serial/8250/8250_hp300.c
+++ b/drivers/tty/serial/8250/8250_hp300.c
@@ -36,9 +36,9 @@ static struct hp300_port *hp300_ports;
#ifdef CONFIG_HPDCA
-static int __devinit hpdca_init_one(struct dio_dev *d,
+static int hpdca_init_one(struct dio_dev *d,
const struct dio_device_id *ent);
-static void __devexit hpdca_remove_one(struct dio_dev *d);
+static void hpdca_remove_one(struct dio_dev *d);
static struct dio_device_id hpdca_dio_tbl[] = {
{ DIO_ID_DCA0 },
@@ -52,7 +52,7 @@ static struct dio_driver hpdca_driver = {
.name = "hpdca",
.id_table = hpdca_dio_tbl,
.probe = hpdca_init_one,
- .remove = __devexit_p(hpdca_remove_one),
+ .remove = hpdca_remove_one,
};
#endif
@@ -159,7 +159,7 @@ int __init hp300_setup_serial_console(void)
#endif /* CONFIG_SERIAL_8250_CONSOLE */
#ifdef CONFIG_HPDCA
-static int __devinit hpdca_init_one(struct dio_dev *d,
+static int hpdca_init_one(struct dio_dev *d,
const struct dio_device_id *ent)
{
struct uart_8250_port uart;
@@ -288,7 +288,7 @@ static int __init hp300_8250_init(void)
}
#ifdef CONFIG_HPDCA
-static void __devexit hpdca_remove_one(struct dio_dev *d)
+static void hpdca_remove_one(struct dio_dev *d)
{
int line;
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 17b7d26abf41..26b9dc012ed0 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -288,7 +288,7 @@ static int pci_plx9050_init(struct pci_dev *dev)
return 0;
}
-static void __devexit pci_plx9050_exit(struct pci_dev *dev)
+static void pci_plx9050_exit(struct pci_dev *dev)
{
u8 __iomem *p;
@@ -313,7 +313,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
#define NI8420_INT_ENABLE_REG 0x38
#define NI8420_INT_ENABLE_BIT 0x2000
-static void __devexit pci_ni8420_exit(struct pci_dev *dev)
+static void pci_ni8420_exit(struct pci_dev *dev)
{
void __iomem *p;
unsigned long base, len;
@@ -345,7 +345,7 @@ static void __devexit pci_ni8420_exit(struct pci_dev *dev)
#define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
-static void __devexit pci_ni8430_exit(struct pci_dev *dev)
+static void pci_ni8430_exit(struct pci_dev *dev)
{
void __iomem *p;
unsigned long base, len;
@@ -422,7 +422,7 @@ static int sbs_init(struct pci_dev *dev)
* Disables the global interrupt of PMC-OctalPro
*/
-static void __devexit sbs_exit(struct pci_dev *dev)
+static void sbs_exit(struct pci_dev *dev)
{
u8 __iomem *p;
@@ -991,7 +991,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
return ret;
}
-static void __devexit pci_ite887x_exit(struct pci_dev *dev)
+static void pci_ite887x_exit(struct pci_dev *dev)
{
u32 ioport;
/* the ioport is bit 0-15 in POSIO0R */
@@ -1068,7 +1068,7 @@ ce4100_serial_setup(struct serial_private *priv,
{
int ret;
- ret = setup_port(priv, port, 0, 0, board->reg_shift);
+ ret = setup_port(priv, port, idx, 0, board->reg_shift);
port->port.iotype = UPIO_MEM32;
port->port.type = PORT_XSCALE;
port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
@@ -1165,6 +1165,94 @@ pci_xr17c154_setup(struct serial_private *priv,
}
static int
+pci_xr17v35x_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+{
+ u8 __iomem *p;
+
+ p = pci_ioremap_bar(priv->dev, 0);
+ if (p == NULL)
+ return -ENOMEM;
+
+ port->port.flags |= UPF_EXAR_EFR;
+
+ /*
+ * Setup Multipurpose Input/Output pins.
+ */
+ if (idx == 0) {
+ writeb(0x00, p + 0x8f); /*MPIOINT[7:0]*/
+ writeb(0x00, p + 0x90); /*MPIOLVL[7:0]*/
+ writeb(0x00, p + 0x91); /*MPIO3T[7:0]*/
+ writeb(0x00, p + 0x92); /*MPIOINV[7:0]*/
+ writeb(0x00, p + 0x93); /*MPIOSEL[7:0]*/
+ writeb(0x00, p + 0x94); /*MPIOOD[7:0]*/
+ writeb(0x00, p + 0x95); /*MPIOINT[15:8]*/
+ writeb(0x00, p + 0x96); /*MPIOLVL[15:8]*/
+ writeb(0x00, p + 0x97); /*MPIO3T[15:8]*/
+ writeb(0x00, p + 0x98); /*MPIOINV[15:8]*/
+ writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/
+ writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/
+ }
+ writeb(0x00, p + UART_EXAR_8XMODE);
+ writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
+ writeb(128, p + UART_EXAR_TXTRG);
+ writeb(128, p + UART_EXAR_RXTRG);
+ iounmap(p);
+
+ return pci_default_setup(priv, board, port, idx);
+}
+
+#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004
+#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002
+#define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a
+#define PCI_DEVICE_ID_COMMTECH_2328PCI335 0x000b
+
+static int
+pci_fastcom335_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+{
+ u8 __iomem *p;
+
+ p = pci_ioremap_bar(priv->dev, 0);
+ if (p == NULL)
+ return -ENOMEM;
+
+ port->port.flags |= UPF_EXAR_EFR;
+
+ /*
+ * Setup Multipurpose Input/Output pins.
+ */
+ if (idx == 0) {
+ switch (priv->dev->device) {
+ case PCI_DEVICE_ID_COMMTECH_4222PCI335:
+ case PCI_DEVICE_ID_COMMTECH_4224PCI335:
+ writeb(0x78, p + 0x90); /* MPIOLVL[7:0] */
+ writeb(0x00, p + 0x92); /* MPIOINV[7:0] */
+ writeb(0x00, p + 0x93); /* MPIOSEL[7:0] */
+ break;
+ case PCI_DEVICE_ID_COMMTECH_2324PCI335:
+ case PCI_DEVICE_ID_COMMTECH_2328PCI335:
+ writeb(0x00, p + 0x90); /* MPIOLVL[7:0] */
+ writeb(0xc0, p + 0x92); /* MPIOINV[7:0] */
+ writeb(0xc0, p + 0x93); /* MPIOSEL[7:0] */
+ break;
+ }
+ writeb(0x00, p + 0x8f); /* MPIOINT[7:0] */
+ writeb(0x00, p + 0x91); /* MPIO3T[7:0] */
+ writeb(0x00, p + 0x94); /* MPIOOD[7:0] */
+ }
+ writeb(0x00, p + UART_EXAR_8XMODE);
+ writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
+ writeb(32, p + UART_EXAR_TXTRG);
+ writeb(32, p + UART_EXAR_RXTRG);
+ iounmap(p);
+
+ return pci_default_setup(priv, board, port, idx);
+}
+
+static int
pci_wch_ch353_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
@@ -1213,6 +1301,10 @@ pci_wch_ch353_setup(struct serial_private *priv,
#define PCI_VENDOR_ID_AGESTAR 0x5372
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872
#define PCI_VENDOR_ID_ASIX 0x9710
+#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
+#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020
+#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
+
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1314,7 +1406,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ite887x_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ite887x_exit),
+ .exit = pci_ite887x_exit,
},
/*
* National Instruments
@@ -1326,7 +1418,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1335,7 +1427,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1344,7 +1436,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1353,7 +1445,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1362,7 +1454,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1371,7 +1463,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1380,7 +1472,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1389,7 +1481,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1398,7 +1490,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1407,7 +1499,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1416,7 +1508,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1425,7 +1517,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8420_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_ni8420_exit),
+ .exit = pci_ni8420_exit,
},
{
.vendor = PCI_VENDOR_ID_NI,
@@ -1434,7 +1526,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_ni8430_init,
.setup = pci_ni8430_setup,
- .exit = __devexit_p(pci_ni8430_exit),
+ .exit = pci_ni8430_exit,
},
/*
* Panacom
@@ -1446,7 +1538,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_plx9050_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
+ .exit = pci_plx9050_exit,
},
{
.vendor = PCI_VENDOR_ID_PANACOM,
@@ -1455,7 +1547,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.init = pci_plx9050_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
+ .exit = pci_plx9050_exit,
},
/*
* PLX
@@ -1474,7 +1566,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
.init = pci_plx9050_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
+ .exit = pci_plx9050_exit,
},
{
.vendor = PCI_VENDOR_ID_PLX,
@@ -1483,7 +1575,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
.init = pci_plx9050_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
+ .exit = pci_plx9050_exit,
},
{
.vendor = PCI_VENDOR_ID_PLX,
@@ -1492,7 +1584,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
.init = pci_plx9050_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
+ .exit = pci_plx9050_exit,
},
{
.vendor = PCI_VENDOR_ID_PLX,
@@ -1501,7 +1593,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
.init = pci_plx9050_init,
.setup = pci_default_setup,
- .exit = __devexit_p(pci_plx9050_exit),
+ .exit = pci_plx9050_exit,
},
/*
* SBS Technologies, Inc., PMC-OCTALPRO 232
@@ -1513,7 +1605,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_OCTPRO232,
.init = sbs_init,
.setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
+ .exit = sbs_exit,
},
/*
* SBS Technologies, Inc., PMC-OCTALPRO 422
@@ -1525,7 +1617,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_OCTPRO422,
.init = sbs_init,
.setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
+ .exit = sbs_exit,
},
/*
* SBS Technologies, Inc., P-Octal 232
@@ -1537,7 +1629,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_POCTAL232,
.init = sbs_init,
.setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
+ .exit = sbs_exit,
},
/*
* SBS Technologies, Inc., P-Octal 422
@@ -1549,7 +1641,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_POCTAL422,
.init = sbs_init,
.setup = sbs_setup,
- .exit = __devexit_p(sbs_exit),
+ .exit = sbs_exit,
},
/*
* SIIG cards - these may be called via parport_serial
@@ -1622,6 +1714,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.setup = pci_xr17c154_setup,
},
+ {
+ .vendor = PCI_VENDOR_ID_EXAR,
+ .device = PCI_DEVICE_ID_EXAR_XR17V352,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17v35x_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_EXAR,
+ .device = PCI_DEVICE_ID_EXAR_XR17V354,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17v35x_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_EXAR,
+ .device = PCI_DEVICE_ID_EXAR_XR17V358,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17v35x_setup,
+ },
/*
* Xircom cards
*/
@@ -1788,6 +1901,59 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_asix_setup,
},
/*
+ * Commtech, Inc. Fastcom adapters
+ *
+ */
+ {
+ .vendor = PCI_VENDOR_ID_COMMTECH,
+ .device = PCI_DEVICE_ID_COMMTECH_4222PCI335,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_fastcom335_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_COMMTECH,
+ .device = PCI_DEVICE_ID_COMMTECH_4224PCI335,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_fastcom335_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_COMMTECH,
+ .device = PCI_DEVICE_ID_COMMTECH_2324PCI335,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_fastcom335_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_COMMTECH,
+ .device = PCI_DEVICE_ID_COMMTECH_2328PCI335,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_fastcom335_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_COMMTECH,
+ .device = PCI_DEVICE_ID_COMMTECH_4222PCIE,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17v35x_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_COMMTECH,
+ .device = PCI_DEVICE_ID_COMMTECH_4224PCIE,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17v35x_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_COMMTECH,
+ .device = PCI_DEVICE_ID_COMMTECH_4228PCIE,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_xr17v35x_setup,
+ },
+ /*
* Default "match everything" terminator entry
*/
{
@@ -1863,6 +2029,10 @@ enum pci_board_num_t {
pbn_b0_4_1152000,
+ pbn_b0_2_1152000_200,
+ pbn_b0_4_1152000_200,
+ pbn_b0_8_1152000_200,
+
pbn_b0_2_1843200,
pbn_b0_4_1843200,
@@ -1962,6 +2132,9 @@ enum pci_board_num_t {
pbn_exar_XR17C152,
pbn_exar_XR17C154,
pbn_exar_XR17C158,
+ pbn_exar_XR17V352,
+ pbn_exar_XR17V354,
+ pbn_exar_XR17V358,
pbn_exar_ibm_saturn,
pbn_pasemi_1682M,
pbn_ni8430_2,
@@ -1987,7 +2160,7 @@ enum pci_board_num_t {
* see first lines of serial_in() and serial_out() in 8250.c
*/
-static struct pciserial_board pci_boards[] __devinitdata = {
+static struct pciserial_board pci_boards[] = {
[pbn_default] = {
.flags = FL_BASE0,
.num_ports = 1,
@@ -2057,6 +2230,27 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8,
},
+ [pbn_b0_2_1152000_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1152000,
+ .uart_offset = 0x200,
+ },
+
+ [pbn_b0_4_1152000_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1152000,
+ .uart_offset = 0x200,
+ },
+
+ [pbn_b0_8_1152000_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1152000,
+ .uart_offset = 0x200,
+ },
+
[pbn_b0_2_1843200] = {
.flags = FL_BASE0,
.num_ports = 2,
@@ -2580,6 +2774,30 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 0x200,
},
+ [pbn_exar_XR17V352] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 7812500,
+ .uart_offset = 0x400,
+ .reg_shift = 0,
+ .first_offset = 0,
+ },
+ [pbn_exar_XR17V354] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 7812500,
+ .uart_offset = 0x400,
+ .reg_shift = 0,
+ .first_offset = 0,
+ },
+ [pbn_exar_XR17V358] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 7812500,
+ .uart_offset = 0x400,
+ .reg_shift = 0,
+ .first_offset = 0,
+ },
[pbn_exar_ibm_saturn] = {
.flags = FL_BASE0,
.num_ports = 1,
@@ -2658,8 +2876,8 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.first_offset = 0x1000,
},
[pbn_ce4100_1_115200] = {
- .flags = FL_BASE0,
- .num_ports = 1,
+ .flags = FL_BASE_BARS,
+ .num_ports = 2,
.base_baud = 921600,
.reg_shift = 2,
},
@@ -2691,7 +2909,7 @@ static const struct pci_device_id blacklist[] = {
* guess what the configuration might be, based on the pitiful PCI
* serial specs. Returns 0 on success, 1 on failure.
*/
-static int __devinit
+static int
serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
{
const struct pci_device_id *bldev;
@@ -2917,7 +3135,7 @@ EXPORT_SYMBOL_GPL(pciserial_resume_ports);
* Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
*/
-static int __devinit
+static int
pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
{
struct pci_serial_quirk *quirk;
@@ -2988,7 +3206,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
return rc;
}
-static void __devexit pciserial_remove_one(struct pci_dev *dev)
+static void pciserial_remove_one(struct pci_dev *dev)
{
struct serial_private *priv = pci_get_drvdata(dev);
@@ -3826,6 +4044,21 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17C158 },
+ /*
+ * Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
+ */
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17V352 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17V354 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17V358 },
/*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
@@ -4257,6 +4490,38 @@ static struct pci_device_id serial_pci_tbl[] = {
0, 0, pbn_b0_bt_2_115200 },
/*
+ * Commtech, Inc. Fastcom adapters
+ */
+ { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCI335,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_b0_2_1152000_200 },
+ { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCI335,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_b0_4_1152000_200 },
+ { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2324PCI335,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_b0_4_1152000_200 },
+ { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2328PCI335,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_b0_8_1152000_200 },
+ { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCIE,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17V352 },
+ { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCIE,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17V354 },
+ { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4228PCIE,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_exar_XR17V358 },
+
+ /*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
*/
@@ -4323,7 +4588,7 @@ static const struct pci_error_handlers serial8250_err_handler = {
static struct pci_driver serial_pci_driver = {
.name = "serial",
.probe = pciserial_init_one,
- .remove = __devexit_p(pciserial_remove_one),
+ .remove = pciserial_remove_one,
#ifdef CONFIG_PM
.suspend = pciserial_suspend_one,
.resume = pciserial_resume_one,
@@ -4332,18 +4597,7 @@ static struct pci_driver serial_pci_driver = {
.err_handler = &serial8250_err_handler,
};
-static int __init serial8250_pci_init(void)
-{
- return pci_register_driver(&serial_pci_driver);
-}
-
-static void __exit serial8250_pci_exit(void)
-{
- pci_unregister_driver(&serial_pci_driver);
-}
-
-module_init(serial8250_pci_init);
-module_exit(serial8250_pci_exit);
+module_pci_driver(serial_pci_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index f8ee25001dd0..35d9ab95c5cb 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -370,14 +370,14 @@ static const struct pnp_device_id pnp_dev_table[] = {
MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-static char *modem_names[] __devinitdata = {
+static char *modem_names[] = {
"MODEM", "Modem", "modem", "FAX", "Fax", "fax",
"56K", "56k", "K56", "33.6", "28.8", "14.4",
"33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
"33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
};
-static int __devinit check_name(char *name)
+static int check_name(char *name)
{
char **tmp;
@@ -388,7 +388,7 @@ static int __devinit check_name(char *name)
return 0;
}
-static int __devinit check_resources(struct pnp_dev *dev)
+static int check_resources(struct pnp_dev *dev)
{
resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
int i;
@@ -412,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev)
* PnP modems, alternatively we must hardcode all modems in pnp_devices[]
* table.
*/
-static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
+static int serial_pnp_guess_board(struct pnp_dev *dev)
{
if (!(check_name(pnp_dev_name(dev)) ||
(dev->card && check_name(dev->card->name))))
@@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
return -ENODEV;
}
-static int __devinit
+static int
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
struct uart_8250_port uart;
@@ -476,7 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
return 0;
}
-static void __devexit serial_pnp_remove(struct pnp_dev *dev)
+static void serial_pnp_remove(struct pnp_dev *dev)
{
long line = (long)pnp_get_drvdata(dev);
if (line)
@@ -511,7 +511,7 @@ static int serial_pnp_resume(struct pnp_dev *dev)
static struct pnp_driver serial_pnp_driver = {
.name = "serial",
.probe = serial_pnp_probe,
- .remove = __devexit_p(serial_pnp_remove),
+ .remove = serial_pnp_remove,
.suspend = serial_pnp_suspend,
.resume = serial_pnp_resume,
.id_table = pnp_dev_table,
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2a53be5f010d..59c23d038106 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -93,7 +93,7 @@ config SERIAL_SB1250_DUART_CONSOLE
config SERIAL_ATMEL
bool "AT91 / AT32 on-chip serial port support"
- depends on (ARM && ARCH_AT91) || AVR32
+ depends on ARCH_AT91 || AVR32
select SERIAL_CORE
help
This enables the driver for the on-chip UARTs of the Atmel
@@ -198,7 +198,7 @@ config SERIAL_CLPS711X_CONSOLE
config SERIAL_SAMSUNG
tristate "Samsung SoC serial support"
- depends on ARM && PLAT_SAMSUNG
+ depends on PLAT_SAMSUNG
select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@@ -208,14 +208,14 @@ config SERIAL_SAMSUNG
config SERIAL_SAMSUNG_UARTS_4
bool
- depends on ARM && PLAT_SAMSUNG
+ depends on PLAT_SAMSUNG
default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
help
Internal node for the common case of 4 Samsung compatible UARTs
config SERIAL_SAMSUNG_UARTS
int
- depends on ARM && PLAT_SAMSUNG
+ depends on PLAT_SAMSUNG
default 6 if ARCH_S5P6450
default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
default 3
@@ -249,7 +249,7 @@ config SERIAL_SAMSUNG_CONSOLE
config SERIAL_SIRFSOC
tristate "SiRF SoC Platform Serial port support"
- depends on ARM && ARCH_PRIMA2
+ depends on ARCH_PRIMA2
select SERIAL_CORE
help
Support for the on-chip UART on the CSR SiRFprimaII series,
@@ -347,7 +347,7 @@ config SERIAL_ZS_CONSOLE
config SERIAL_21285
tristate "DC21285 serial port support"
- depends on ARM && FOOTBRIDGE
+ depends on FOOTBRIDGE
select SERIAL_CORE
help
If you have a machine based on a 21285 (Footbridge) StrongARM(R)/
@@ -371,7 +371,7 @@ config SERIAL_21285_CONSOLE
config SERIAL_MPSC
bool "Marvell MPSC serial port support"
- depends on PPC32 && MV64X60
+ depends on MV64X60
select SERIAL_CORE
help
Say Y here if you want to use the Marvell MPSC serial controller.
@@ -408,7 +408,7 @@ config SERIAL_PXA_CONSOLE
config SERIAL_SA1100
bool "SA1100 serial port support"
- depends on ARM && ARCH_SA1100
+ depends on ARCH_SA1100
select SERIAL_CORE
help
If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
@@ -716,7 +716,7 @@ config SERIAL_SH_SCI_DMA
config SERIAL_PNX8XXX
bool "Enable PNX8XXX SoCs' UART Support"
- depends on MIPS && (SOC_PNX8550 || SOC_PNX833X)
+ depends on SOC_PNX8550 || SOC_PNX833X
select SERIAL_CORE
help
If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
@@ -1013,7 +1013,7 @@ config SERIAL_SGI_IOC3
config SERIAL_MSM
bool "MSM on-chip serial port support"
- depends on ARM && ARCH_MSM
+ depends on ARCH_MSM
select SERIAL_CORE
config SERIAL_MSM_CONSOLE
@@ -1035,7 +1035,7 @@ config SERIAL_MSM_HS
config SERIAL_VT8500
bool "VIA VT8500 on-chip serial port support"
- depends on ARM && ARCH_VT8500
+ depends on ARCH_VT8500
select SERIAL_CORE
config SERIAL_VT8500_CONSOLE
@@ -1045,7 +1045,7 @@ config SERIAL_VT8500_CONSOLE
config SERIAL_NETX
tristate "NetX serial port support"
- depends on ARM && ARCH_NETX
+ depends on ARCH_NETX
select SERIAL_CORE
help
If you have a machine based on a Hilscher NetX SoC you
@@ -1376,6 +1376,7 @@ config SERIAL_MXS_AUART_CONSOLE
config SERIAL_XILINX_PS_UART
tristate "Xilinx PS UART support"
+ depends on OF
select SERIAL_CORE
help
This driver supports the Xilinx PS UART port.
@@ -1423,4 +1424,27 @@ config SERIAL_EFM32_UART_CONSOLE
depends on SERIAL_EFM32_UART=y
select SERIAL_CORE_CONSOLE
+config SERIAL_ARC
+ tristate "ARC UART driver support"
+ select SERIAL_CORE
+ help
+ Driver for on-chip UART for ARC(Synopsys) for the legacy
+ FPGA Boards (ML50x/ARCAngel4)
+
+config SERIAL_ARC_CONSOLE
+ bool "Console on ARC UART"
+ depends on SERIAL_ARC=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Enable system Console on ARC UART
+
+config SERIAL_ARC_NR_PORTS
+ int "Number of ARC UART ports"
+ depends on SERIAL_ARC
+ range 1 3
+ default "1"
+ help
+ Set this to the number of serial ports you want the driver
+ to support.
+
endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 4f694dafa719..df1b998c436b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -82,3 +82,4 @@ obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
+obj-$(CONFIG_SERIAL_ARC) += arc_uart.o
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index 530181e49f6b..872f14ae43d2 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -406,7 +406,7 @@ static struct uart_driver altera_jtaguart_driver = {
.cons = ALTERA_JTAGUART_CONSOLE,
};
-static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
+static int altera_jtaguart_probe(struct platform_device *pdev)
{
struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
struct uart_port *port;
@@ -453,7 +453,7 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
+static int altera_jtaguart_remove(struct platform_device *pdev)
{
struct uart_port *port;
int i = pdev->id;
@@ -477,7 +477,7 @@ MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
static struct platform_driver altera_jtaguart_platform_driver = {
.probe = altera_jtaguart_probe,
- .remove = __devexit_p(altera_jtaguart_remove),
+ .remove = altera_jtaguart_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 15d80b9fb303..684a0808e1c7 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -532,7 +532,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev,
}
#endif /* CONFIG_OF */
-static int __devinit altera_uart_probe(struct platform_device *pdev)
+static int altera_uart_probe(struct platform_device *pdev)
{
struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
struct uart_port *port;
@@ -598,7 +598,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit altera_uart_remove(struct platform_device *pdev)
+static int altera_uart_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
@@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, altera_uart_match);
static struct platform_driver altera_uart_platform_driver = {
.probe = altera_uart_probe,
- .remove = __devexit_p(altera_uart_remove),
+ .remove = altera_uart_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index d7e1edec50b5..7fca4022a8b2 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -56,8 +56,7 @@
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/sizes.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
#define UART_NR 14
@@ -1973,7 +1972,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
goto out;
}
- uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
+ uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
+ GFP_KERNEL);
if (uap == NULL) {
ret = -ENOMEM;
goto out;
@@ -1981,16 +1981,17 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
i = pl011_probe_dt_alias(i, &dev->dev);
- base = ioremap(dev->res.start, resource_size(&dev->res));
+ base = devm_ioremap(&dev->dev, dev->res.start,
+ resource_size(&dev->res));
if (!base) {
ret = -ENOMEM;
- goto free;
+ goto out;
}
uap->pinctrl = devm_pinctrl_get(&dev->dev);
if (IS_ERR(uap->pinctrl)) {
ret = PTR_ERR(uap->pinctrl);
- goto unmap;
+ goto out;
}
uap->pins_default = pinctrl_lookup_state(uap->pinctrl,
PINCTRL_STATE_DEFAULT);
@@ -2002,10 +2003,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
if (IS_ERR(uap->pins_sleep))
dev_dbg(&dev->dev, "could not get sleep pinstate\n");
- uap->clk = clk_get(&dev->dev, NULL);
+ uap->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
- goto unmap;
+ goto out;
}
uap->vendor = vendor;
@@ -2038,11 +2039,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
amba_set_drvdata(dev, NULL);
amba_ports[i] = NULL;
pl011_dma_remove(uap);
- clk_put(uap->clk);
- unmap:
- iounmap(base);
- free:
- kfree(uap);
}
out:
return ret;
@@ -2062,9 +2058,6 @@ static int pl011_remove(struct amba_device *dev)
amba_ports[i] = NULL;
pl011_dma_remove(uap);
- iounmap(uap->port.membase);
- clk_put(uap->clk);
- kfree(uap);
return 0;
}
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index 7162f70d9260..59ae2b53e765 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -554,7 +554,7 @@ static struct uart_driver grlib_apbuart_driver = {
/* OF Platform Driver */
/* ======================================================================== */
-static int __devinit apbuart_probe(struct platform_device *op)
+static int apbuart_probe(struct platform_device *op)
{
int i;
struct uart_port *port = NULL;
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index e4f60e2b87f3..505c490c0b44 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -25,11 +25,19 @@
#include <linux/io.h>
#include <linux/irq.h>
+#include <asm/div64.h>
+
#include <asm/mach-ath79/ar933x_uart.h>
#include <asm/mach-ath79/ar933x_uart_platform.h>
#define DRIVER_NAME "ar933x-uart"
+#define AR933X_UART_MAX_SCALE 0xff
+#define AR933X_UART_MAX_STEP 0xffff
+
+#define AR933X_UART_MIN_BAUD 300
+#define AR933X_UART_MAX_BAUD 3000000
+
#define AR933X_DUMMY_STATUS_RD 0x01
static struct uart_driver ar933x_uart_driver;
@@ -37,6 +45,8 @@ static struct uart_driver ar933x_uart_driver;
struct ar933x_uart_port {
struct uart_port port;
unsigned int ier; /* shadow Interrupt Enable Register */
+ unsigned int min_baud;
+ unsigned int max_baud;
};
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
@@ -162,6 +172,57 @@ static void ar933x_uart_enable_ms(struct uart_port *port)
{
}
+/*
+ * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
+ */
+static unsigned long ar933x_uart_get_baud(unsigned int clk,
+ unsigned int scale,
+ unsigned int step)
+{
+ u64 t;
+ u32 div;
+
+ div = (2 << 16) * (scale + 1);
+ t = clk;
+ t *= step;
+ t += (div / 2);
+ do_div(t, div);
+
+ return t;
+}
+
+static void ar933x_uart_get_scale_step(unsigned int clk,
+ unsigned int baud,
+ unsigned int *scale,
+ unsigned int *step)
+{
+ unsigned int tscale;
+ long min_diff;
+
+ *scale = 0;
+ *step = 0;
+
+ min_diff = baud;
+ for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
+ u64 tstep;
+ int diff;
+
+ tstep = baud * (tscale + 1);
+ tstep *= (2 << 16);
+ do_div(tstep, clk);
+
+ if (tstep > AR933X_UART_MAX_STEP)
+ break;
+
+ diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
+ if (diff < min_diff) {
+ min_diff = diff;
+ *scale = tscale;
+ *step = tstep;
+ }
+ }
+}
+
static void ar933x_uart_set_termios(struct uart_port *port,
struct ktermios *new,
struct ktermios *old)
@@ -169,7 +230,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
unsigned int cs;
unsigned long flags;
- unsigned int baud, scale;
+ unsigned int baud, scale, step;
/* Only CS8 is supported */
new->c_cflag &= ~CSIZE;
@@ -191,8 +252,8 @@ static void ar933x_uart_set_termios(struct uart_port *port,
/* Mark/space parity is not supported */
new->c_cflag &= ~CMSPAR;
- baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
- scale = (port->uartclk / (16 * baud)) - 1;
+ baud = uart_get_baud_rate(port, new, old, up->min_baud, up->max_baud);
+ ar933x_uart_get_scale_step(port->uartclk, baud, &scale, &step);
/*
* Ok, we're now changing the port state. Do it with
@@ -200,6 +261,10 @@ static void ar933x_uart_set_termios(struct uart_port *port,
*/
spin_lock_irqsave(&up->port.lock, flags);
+ /* disable the UART */
+ ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S);
+
/* Update the per-port timeout. */
uart_update_timeout(port, new->c_cflag, baud);
@@ -210,7 +275,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD;
ar933x_uart_write(up, AR933X_UART_CLOCK_REG,
- scale << AR933X_UART_CLOCK_SCALE_S | 8192);
+ scale << AR933X_UART_CLOCK_SCALE_S | step);
/* setup configuration register */
ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs);
@@ -219,6 +284,11 @@ static void ar933x_uart_set_termios(struct uart_port *port,
ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
AR933X_UART_CS_HOST_INT_EN);
+ /* reenable the UART */
+ ar933x_uart_rmw(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
+ AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S);
+
spin_unlock_irqrestore(&up->port.lock, flags);
if (tty_termios_baud_rate(new))
@@ -401,6 +471,8 @@ static void ar933x_uart_config_port(struct uart_port *port, int flags)
static int ar933x_uart_verify_port(struct uart_port *port,
struct serial_struct *ser)
{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
if (ser->type != PORT_UNKNOWN &&
ser->type != PORT_AR933X)
return -EINVAL;
@@ -408,7 +480,8 @@ static int ar933x_uart_verify_port(struct uart_port *port,
if (ser->irq < 0 || ser->irq >= NR_IRQS)
return -EINVAL;
- if (ser->baud_base < 28800)
+ if (ser->baud_base < up->min_baud ||
+ ser->baud_base > up->max_baud)
return -EINVAL;
return 0;
@@ -554,13 +627,14 @@ static struct uart_driver ar933x_uart_driver = {
.cons = AR933X_SERIAL_CONSOLE,
};
-static int __devinit ar933x_uart_probe(struct platform_device *pdev)
+static int ar933x_uart_probe(struct platform_device *pdev)
{
struct ar933x_uart_platform_data *pdata;
struct ar933x_uart_port *up;
struct uart_port *port;
struct resource *mem_res;
struct resource *irq_res;
+ unsigned int baud;
int id;
int ret;
@@ -611,6 +685,12 @@ static int __devinit ar933x_uart_probe(struct platform_device *pdev)
port->fifosize = AR933X_UART_FIFO_SIZE;
port->ops = &ar933x_uart_ops;
+ baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
+ up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
+
+ baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
+ up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
+
ar933x_uart_add_console_port(up);
ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
@@ -627,7 +707,7 @@ err_free_up:
return ret;
}
-static int __devexit ar933x_uart_remove(struct platform_device *pdev)
+static int ar933x_uart_remove(struct platform_device *pdev)
{
struct ar933x_uart_port *up;
@@ -645,7 +725,7 @@ static int __devexit ar933x_uart_remove(struct platform_device *pdev)
static struct platform_driver ar933x_uart_platform_driver = {
.probe = ar933x_uart_probe,
- .remove = __devexit_p(ar933x_uart_remove),
+ .remove = ar933x_uart_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
new file mode 100644
index 000000000000..3e0b3fac6a0e
--- /dev/null
+++ b/drivers/tty/serial/arc_uart.c
@@ -0,0 +1,746 @@
+/*
+ * ARC On-Chip(fpga) UART Driver
+ *
+ * Copyright (C) 2010-2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * vineetg: July 10th 2012
+ * -Decoupled the driver from arch/arc
+ * +Using platform_get_resource() for irq/membase (thx to bfin_uart.c)
+ * +Using early_platform_xxx() for early console (thx to mach-shmobile/xxx)
+ *
+ * Vineetg: Aug 21st 2010
+ * -Is uart_tx_stopped() not done in tty write path as it has already been
+ * taken care of, in serial core
+ *
+ * Vineetg: Aug 18th 2010
+ * -New Serial Core based ARC UART driver
+ * -Derived largely from blackfin driver albiet with some major tweaks
+ *
+ * TODO:
+ * -check if sysreq works
+ */
+
+#if defined(CONFIG_SERIAL_ARC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+/*************************************
+ * ARC UART Hardware Specs
+ ************************************/
+#define ARC_UART_TX_FIFO_SIZE 1
+
+/*
+ * UART Register set (this is not a Standards Compliant IP)
+ * Also each reg is Word aligned, but only 8 bits wide
+ */
+#define R_ID0 0
+#define R_ID1 4
+#define R_ID2 8
+#define R_ID3 12
+#define R_DATA 16
+#define R_STS 20
+#define R_BAUDL 24
+#define R_BAUDH 28
+
+/* Bits for UART Status Reg (R/W) */
+#define RXIENB 0x04 /* Receive Interrupt Enable */
+#define TXIENB 0x40 /* Transmit Interrupt Enable */
+
+#define RXEMPTY 0x20 /* Receive FIFO Empty: No char receivede */
+#define TXEMPTY 0x80 /* Transmit FIFO Empty, thus char can be written into */
+
+#define RXFULL 0x08 /* Receive FIFO full */
+#define RXFULL1 0x10 /* Receive FIFO has space for 1 char (tot space=4) */
+
+#define RXFERR 0x01 /* Frame Error: Stop Bit not detected */
+#define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */
+
+/* Uart bit fiddling helpers: lowest level */
+#define RBASE(uart, reg) (uart->port.membase + reg)
+#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
+#define UART_REG_GET(u, r) readb(RBASE(u, r))
+
+#define UART_REG_OR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) | (v))
+#define UART_REG_CLR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) & ~(v))
+
+/* Uart bit fiddling helpers: API level */
+#define UART_SET_DATA(uart, val) UART_REG_SET(uart, R_DATA, val)
+#define UART_GET_DATA(uart) UART_REG_GET(uart, R_DATA)
+
+#define UART_SET_BAUDH(uart, val) UART_REG_SET(uart, R_BAUDH, val)
+#define UART_SET_BAUDL(uart, val) UART_REG_SET(uart, R_BAUDL, val)
+
+#define UART_CLR_STATUS(uart, val) UART_REG_CLR(uart, R_STS, val)
+#define UART_GET_STATUS(uart) UART_REG_GET(uart, R_STS)
+
+#define UART_ALL_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB|TXIENB)
+#define UART_RX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB)
+#define UART_TX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, TXIENB)
+
+#define UART_ALL_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB|TXIENB)
+#define UART_RX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB)
+#define UART_TX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, TXIENB)
+
+#define ARC_SERIAL_DEV_NAME "ttyARC"
+
+struct arc_uart_port {
+ struct uart_port port;
+ unsigned long baud;
+ int is_emulated; /* H/w vs. Instruction Set Simulator */
+};
+
+#define to_arc_port(uport) container_of(uport, struct arc_uart_port, port)
+
+static struct arc_uart_port arc_uart_ports[CONFIG_SERIAL_ARC_NR_PORTS];
+
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+static struct console arc_console;
+#endif
+
+#define DRIVER_NAME "arc-uart"
+
+static struct uart_driver arc_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = DRIVER_NAME,
+ .dev_name = ARC_SERIAL_DEV_NAME,
+ .major = 0,
+ .minor = 0,
+ .nr = CONFIG_SERIAL_ARC_NR_PORTS,
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+ .cons = &arc_console,
+#endif
+};
+
+static void arc_serial_stop_rx(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+
+ UART_RX_IRQ_DISABLE(uart);
+}
+
+static void arc_serial_stop_tx(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+
+ while (!(UART_GET_STATUS(uart) & TXEMPTY))
+ cpu_relax();
+
+ UART_TX_IRQ_DISABLE(uart);
+}
+
+/*
+ * Return TIOCSER_TEMT when transmitter is not busy.
+ */
+static unsigned int arc_serial_tx_empty(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+ unsigned int stat;
+
+ stat = UART_GET_STATUS(uart);
+ if (stat & TXEMPTY)
+ return TIOCSER_TEMT;
+
+ return 0;
+}
+
+/*
+ * Driver internal routine, used by both tty(serial core) as well as tx-isr
+ * -Called under spinlock in either cases
+ * -also tty->stopped / tty->hw_stopped has already been checked
+ * = by uart_start( ) before calling us
+ * = tx_ist checks that too before calling
+ */
+static void arc_serial_tx_chars(struct arc_uart_port *uart)
+{
+ struct circ_buf *xmit = &uart->port.state->xmit;
+ int sent = 0;
+ unsigned char ch;
+
+ if (unlikely(uart->port.x_char)) {
+ UART_SET_DATA(uart, uart->port.x_char);
+ uart->port.icount.tx++;
+ uart->port.x_char = 0;
+ sent = 1;
+ } else if (xmit->tail != xmit->head) { /* TODO: uart_circ_empty */
+ ch = xmit->buf[xmit->tail];
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ uart->port.icount.tx++;
+ while (!(UART_GET_STATUS(uart) & TXEMPTY))
+ cpu_relax();
+ UART_SET_DATA(uart, ch);
+ sent = 1;
+ }
+
+ /*
+ * If num chars in xmit buffer are too few, ask tty layer for more.
+ * By Hard ISR to schedule processing in software interrupt part
+ */
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&uart->port);
+
+ if (sent)
+ UART_TX_IRQ_ENABLE(uart);
+}
+
+/*
+ * port is locked and interrupts are disabled
+ * uart_start( ) calls us under the port spinlock irqsave
+ */
+static void arc_serial_start_tx(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+
+ arc_serial_tx_chars(uart);
+}
+
+static void arc_serial_rx_chars(struct arc_uart_port *uart)
+{
+ struct tty_struct *tty = tty_port_tty_get(&uart->port.state->port);
+ unsigned int status, ch, flg = 0;
+
+ if (!tty)
+ return;
+
+ /*
+ * UART has 4 deep RX-FIFO. Driver's recongnition of this fact
+ * is very subtle. Here's how ...
+ * Upon getting a RX-Intr, such that RX-EMPTY=0, meaning data available,
+ * driver reads the DATA Reg and keeps doing that in a loop, until
+ * RX-EMPTY=1. Multiple chars being avail, with a single Interrupt,
+ * before RX-EMPTY=0, implies some sort of buffering going on in the
+ * controller, which is indeed the Rx-FIFO.
+ */
+ while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) {
+
+ ch = UART_GET_DATA(uart);
+ uart->port.icount.rx++;
+
+ if (unlikely(status & (RXOERR | RXFERR))) {
+ if (status & RXOERR) {
+ uart->port.icount.overrun++;
+ flg = TTY_OVERRUN;
+ UART_CLR_STATUS(uart, RXOERR);
+ }
+
+ if (status & RXFERR) {
+ uart->port.icount.frame++;
+ flg = TTY_FRAME;
+ UART_CLR_STATUS(uart, RXFERR);
+ }
+ } else
+ flg = TTY_NORMAL;
+
+ if (unlikely(uart_handle_sysrq_char(&uart->port, ch)))
+ goto done;
+
+ uart_insert_char(&uart->port, status, RXOERR, ch, flg);
+
+done:
+ tty_flip_buffer_push(tty);
+ }
+
+ tty_kref_put(tty);
+}
+
+/*
+ * A note on the Interrupt handling state machine of this driver
+ *
+ * kernel printk writes funnel thru the console driver framework and in order
+ * to keep things simple as well as efficient, it writes to UART in polled
+ * mode, in one shot, and exits.
+ *
+ * OTOH, Userland output (via tty layer), uses interrupt based writes as there
+ * can be undeterministic delay between char writes.
+ *
+ * Thus Rx-interrupts are always enabled, while tx-interrupts are by default
+ * disabled.
+ *
+ * When tty has some data to send out, serial core calls driver's start_tx
+ * which
+ * -checks-if-tty-buffer-has-char-to-send
+ * -writes-data-to-uart
+ * -enable-tx-intr
+ *
+ * Once data bits are pushed out, controller raises the Tx-room-avail-Interrupt.
+ * The first thing Tx ISR does is disable further Tx interrupts (as this could
+ * be the last char to send, before settling down into the quiet polled mode).
+ * It then calls the exact routine used by tty layer write to send out any
+ * more char in tty buffer. In case of sending, it re-enables Tx-intr. In case
+ * of no data, it remains disabled.
+ * This is how the transmit state machine is dynamically switched on/off
+ */
+
+static irqreturn_t arc_serial_isr(int irq, void *dev_id)
+{
+ struct arc_uart_port *uart = dev_id;
+ unsigned int status;
+
+ status = UART_GET_STATUS(uart);
+
+ /*
+ * Single IRQ for both Rx (data available) Tx (room available) Interrupt
+ * notifications from the UART Controller.
+ * To demultiplex between the two, we check the relevant bits
+ */
+ if ((status & RXIENB) && !(status & RXEMPTY)) {
+
+ /* already in ISR, no need of xx_irqsave */
+ spin_lock(&uart->port.lock);
+ arc_serial_rx_chars(uart);
+ spin_unlock(&uart->port.lock);
+ }
+
+ if ((status & TXIENB) && (status & TXEMPTY)) {
+
+ /* Unconditionally disable further Tx-Interrupts.
+ * will be enabled by tx_chars() if needed.
+ */
+ UART_TX_IRQ_DISABLE(uart);
+
+ spin_lock(&uart->port.lock);
+
+ if (!uart_tx_stopped(&uart->port))
+ arc_serial_tx_chars(uart);
+
+ spin_unlock(&uart->port.lock);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static unsigned int arc_serial_get_mctrl(struct uart_port *port)
+{
+ /*
+ * Pretend we have a Modem status reg and following bits are
+ * always set, to satify the serial core state machine
+ * (DSR) Data Set Ready
+ * (CTS) Clear To Send
+ * (CAR) Carrier Detect
+ */
+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* MCR not present */
+}
+
+/* Enable Modem Status Interrupts */
+
+static void arc_serial_enable_ms(struct uart_port *port)
+{
+ /* MSR not present */
+}
+
+static void arc_serial_break_ctl(struct uart_port *port, int break_state)
+{
+ /* ARC UART doesn't support sending Break signal */
+}
+
+static int arc_serial_startup(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+
+ /* Before we hook up the ISR, Disable all UART Interrupts */
+ UART_ALL_IRQ_DISABLE(uart);
+
+ if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
+ uart)) {
+ dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
+ return -EBUSY;
+ }
+
+ UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
+
+ return 0;
+}
+
+/* This is not really needed */
+static void arc_serial_shutdown(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+ free_irq(uart->port.irq, uart);
+}
+
+static void
+arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
+ struct ktermios *old)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+ unsigned int baud, uartl, uarth, hw_val;
+ unsigned long flags;
+
+ /*
+ * Use the generic handler so that any specially encoded baud rates
+ * such as SPD_xx flags or "%B0" can be handled
+ * Max Baud I suppose will not be more than current 115K * 4
+ * Formula for ARC UART is: hw-val = ((CLK/(BAUD*4)) -1)
+ * spread over two 8-bit registers
+ */
+ baud = uart_get_baud_rate(port, new, old, 0, 460800);
+
+ hw_val = port->uartclk / (uart->baud * 4) - 1;
+ uartl = hw_val & 0xFF;
+ uarth = (hw_val >> 8) & 0xFF;
+
+ /*
+ * UART ISS(Instruction Set simulator) emulation has a subtle bug:
+ * A existing value of Baudh = 0 is used as a indication to startup
+ * it's internal state machine.
+ * Thus if baudh is set to 0, 2 times, it chokes.
+ * This happens with BAUD=115200 and the formaula above
+ * Until that is fixed, when running on ISS, we will set baudh to !0
+ */
+ if (uart->is_emulated)
+ uarth = 1;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ UART_ALL_IRQ_DISABLE(uart);
+
+ UART_SET_BAUDL(uart, uartl);
+ UART_SET_BAUDH(uart, uarth);
+
+ UART_RX_IRQ_ENABLE(uart);
+
+ /*
+ * UART doesn't support Parity/Hardware Flow Control;
+ * Only supports 8N1 character size
+ */
+ new->c_cflag &= ~(CMSPAR|CRTSCTS|CSIZE);
+ new->c_cflag |= CS8;
+
+ if (old)
+ tty_termios_copy_hw(new, old);
+
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(new))
+ tty_termios_encode_baud_rate(new, baud, baud);
+
+ uart_update_timeout(port, new->c_cflag, baud);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *arc_serial_type(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+
+ return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
+}
+
+static void arc_serial_release_port(struct uart_port *port)
+{
+}
+
+static int arc_serial_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int
+arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if (port->type != PORT_UNKNOWN && ser->type != PORT_ARC)
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void arc_serial_config_port(struct uart_port *port, int flags)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+
+ if (flags & UART_CONFIG_TYPE)
+ uart->port.type = PORT_ARC;
+}
+
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)
+
+static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+
+ while (!(UART_GET_STATUS(uart) & TXEMPTY))
+ cpu_relax();
+
+ UART_SET_DATA(uart, chr);
+}
+#endif
+
+#ifdef CONFIG_CONSOLE_POLL
+static int arc_serial_poll_getchar(struct uart_port *port)
+{
+ struct arc_uart_port *uart = to_arc_port(port);
+ unsigned char chr;
+
+ while (!(UART_GET_STATUS(uart) & RXEMPTY))
+ cpu_relax();
+
+ chr = UART_GET_DATA(uart);
+ return chr;
+}
+#endif
+
+static struct uart_ops arc_serial_pops = {
+ .tx_empty = arc_serial_tx_empty,
+ .set_mctrl = arc_serial_set_mctrl,
+ .get_mctrl = arc_serial_get_mctrl,
+ .stop_tx = arc_serial_stop_tx,
+ .start_tx = arc_serial_start_tx,
+ .stop_rx = arc_serial_stop_rx,
+ .enable_ms = arc_serial_enable_ms,
+ .break_ctl = arc_serial_break_ctl,
+ .startup = arc_serial_startup,
+ .shutdown = arc_serial_shutdown,
+ .set_termios = arc_serial_set_termios,
+ .type = arc_serial_type,
+ .release_port = arc_serial_release_port,
+ .request_port = arc_serial_request_port,
+ .config_port = arc_serial_config_port,
+ .verify_port = arc_serial_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_put_char = arc_serial_poll_putchar,
+ .poll_get_char = arc_serial_poll_getchar,
+#endif
+};
+
+static int
+arc_uart_init_one(struct platform_device *pdev, struct arc_uart_port *uart)
+{
+ struct resource *res, *res2;
+ unsigned long *plat_data;
+
+ if (pdev->id < 0 || pdev->id >= CONFIG_SERIAL_ARC_NR_PORTS) {
+ dev_err(&pdev->dev, "Wrong uart platform device id.\n");
+ return -ENOENT;
+ }
+
+ plat_data = ((unsigned long *)(pdev->dev.platform_data));
+ uart->baud = plat_data[0];
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res2)
+ return -ENODEV;
+
+ uart->port.mapbase = res->start;
+ uart->port.membase = ioremap_nocache(res->start, resource_size(res));
+ if (!uart->port.membase)
+ /* No point of dev_err since UART itself is hosed here */
+ return -ENXIO;
+
+ uart->port.irq = res2->start;
+ uart->port.dev = &pdev->dev;
+ uart->port.iotype = UPIO_MEM;
+ uart->port.flags = UPF_BOOT_AUTOCONF;
+ uart->port.line = pdev->id;
+ uart->port.ops = &arc_serial_pops;
+
+ uart->port.uartclk = plat_data[1];
+ uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
+
+ /*
+ * uart_insert_char( ) uses it in decideding whether to ignore a
+ * char or not. Explicitly setting it here, removes the subtelty
+ */
+ uart->port.ignore_status_mask = 0;
+
+ /* Real Hardware vs. emulated to work around a bug */
+ uart->is_emulated = !!plat_data[2];
+
+ return 0;
+}
+
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+
+static int arc_serial_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index < 0 || co->index >= CONFIG_SERIAL_ARC_NR_PORTS)
+ return -ENODEV;
+
+ /*
+ * The uart port backing the console (e.g. ttyARC1) might not have been
+ * init yet. If so, defer the console setup to after the port.
+ */
+ port = &arc_uart_ports[co->index].port;
+ if (!port->membase)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ /*
+ * Serial core will call port->ops->set_termios( )
+ * which will set the baud reg
+ */
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static void arc_serial_console_putchar(struct uart_port *port, int ch)
+{
+ arc_serial_poll_putchar(port, (unsigned char)ch);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void arc_serial_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_port *port = &arc_uart_ports[co->index].port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ uart_console_write(port, s, count, arc_serial_console_putchar);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static struct console arc_console = {
+ .name = ARC_SERIAL_DEV_NAME,
+ .write = arc_serial_console_write,
+ .device = uart_console_device,
+ .setup = arc_serial_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &arc_uart_driver
+};
+
+static __init void early_serial_write(struct console *con, const char *s,
+ unsigned int n)
+{
+ struct uart_port *port = &arc_uart_ports[con->index].port;
+ unsigned int i;
+
+ for (i = 0; i < n; i++, s++) {
+ if (*s == '\n')
+ arc_serial_poll_putchar(port, '\r');
+ arc_serial_poll_putchar(port, *s);
+ }
+}
+
+static struct __initdata console arc_early_serial_console = {
+ .name = "early_ARCuart",
+ .write = early_serial_write,
+ .flags = CON_PRINTBUFFER | CON_BOOT,
+ .index = -1
+};
+
+static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
+{
+ arc_early_serial_console.index = pdev->id;
+
+ arc_uart_init_one(pdev, &arc_uart_ports[pdev->id]);
+
+ arc_serial_console_setup(&arc_early_serial_console, NULL);
+
+ register_console(&arc_early_serial_console);
+ return 0;
+}
+#else
+static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_SERIAL_ARC_CONSOLE */
+
+static int arc_serial_probe(struct platform_device *pdev)
+{
+ struct arc_uart_port *uart;
+ int rc;
+
+ if (is_early_platform_device(pdev))
+ return arc_serial_probe_earlyprintk(pdev);
+
+ uart = &arc_uart_ports[pdev->id];
+ rc = arc_uart_init_one(pdev, uart);
+ if (rc)
+ return rc;
+
+ return uart_add_one_port(&arc_uart_driver, &uart->port);
+}
+
+static int arc_serial_remove(struct platform_device *pdev)
+{
+ /* This will never be called */
+ return 0;
+}
+
+static struct platform_driver arc_platform_driver = {
+ .probe = arc_serial_probe,
+ .remove = arc_serial_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+#ifdef CONFIG_SERIAL_ARC_CONSOLE
+/*
+ * Register an early platform driver of "earlyprintk" class.
+ * ARCH platform code installs the driver and probes the early devices
+ * The installation could rely on user specifying earlyprintk=xyx in cmd line
+ * or it could be done independently, for all "earlyprintk" class drivers.
+ * [see arch/arc/plat-arcfpga/platform.c]
+ */
+early_platform_init("earlyprintk", &arc_platform_driver);
+
+#endif /* CONFIG_SERIAL_ARC_CONSOLE */
+
+static int __init arc_serial_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&arc_uart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&arc_platform_driver);
+ if (ret)
+ uart_unregister_driver(&arc_uart_driver);
+
+ return ret;
+}
+
+static void __exit arc_serial_exit(void)
+{
+ platform_driver_unregister(&arc_platform_driver);
+ uart_unregister_driver(&arc_uart_driver);
+}
+
+module_init(arc_serial_init);
+module_exit(arc_serial_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("plat-arcfpga/uart");
+MODULE_AUTHOR("Vineet Gupta");
+MODULE_DESCRIPTION("ARC(Synopsys) On-Chip(fpga) serial driver");
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 3d7e1ee2fa57..b95886c1198d 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -39,6 +39,7 @@
#include <linux/atmel_pdc.h>
#include <linux/atmel_serial.h>
#include <linux/uaccess.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/io.h>
#include <asm/ioctls.h>
@@ -1423,7 +1424,7 @@ static struct uart_ops atmel_pops = {
#endif
};
-static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
+static void atmel_of_init_port(struct atmel_uart_port *atmel_port,
struct device_node *np)
{
u32 rs485_delay[2];
@@ -1458,7 +1459,7 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
/*
* Configure the port from the platform device resource info.
*/
-static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
+static void atmel_init_port(struct atmel_uart_port *atmel_port,
struct platform_device *pdev)
{
struct uart_port *port = &atmel_port->uart;
@@ -1766,13 +1767,14 @@ static int atmel_serial_resume(struct platform_device *pdev)
#define atmel_serial_resume NULL
#endif
-static int __devinit atmel_serial_probe(struct platform_device *pdev)
+static int atmel_serial_probe(struct platform_device *pdev)
{
struct atmel_uart_port *port;
struct device_node *np = pdev->dev.of_node;
struct atmel_uart_data *pdata = pdev->dev.platform_data;
void *data;
int ret = -ENODEV;
+ struct pinctrl *pinctrl;
BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
@@ -1805,6 +1807,12 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
atmel_init_port(port, pdev);
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto err;
+ }
+
if (!atmel_use_dma_rx(&port->uart)) {
ret = -ENOMEM;
data = kmalloc(sizeof(struct atmel_uart_char)
@@ -1851,7 +1859,7 @@ err:
return ret;
}
-static int __devexit atmel_serial_remove(struct platform_device *pdev)
+static int atmel_serial_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
@@ -1876,7 +1884,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
static struct platform_driver atmel_serial_driver = {
.probe = atmel_serial_probe,
- .remove = __devexit_p(atmel_serial_remove),
+ .remove = atmel_serial_remove,
.suspend = atmel_serial_suspend,
.resume = atmel_serial_resume,
.driver = {
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index c0b68b9cad91..c76a226080f2 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -801,7 +801,7 @@ static struct uart_driver bcm_uart_driver = {
/*
* platform driver probe/remove callback
*/
-static int __devinit bcm_uart_probe(struct platform_device *pdev)
+static int bcm_uart_probe(struct platform_device *pdev)
{
struct resource *res_mem, *res_irq;
struct uart_port *port;
@@ -848,7 +848,7 @@ static int __devinit bcm_uart_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit bcm_uart_remove(struct platform_device *pdev)
+static int bcm_uart_remove(struct platform_device *pdev)
{
struct uart_port *port;
@@ -865,7 +865,7 @@ static int __devexit bcm_uart_remove(struct platform_device *pdev)
*/
static struct platform_driver bcm_uart_platform_driver = {
.probe = bcm_uart_probe,
- .remove = __devexit_p(bcm_uart_remove),
+ .remove = bcm_uart_remove,
.driver = {
.owner = THIS_MODULE,
.name = "bcm63xx_uart",
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index 7fbc3a08f10d..f5d117379b60 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -740,7 +740,7 @@ static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
};
#endif
-static int __devinit sport_uart_probe(struct platform_device *pdev)
+static int sport_uart_probe(struct platform_device *pdev)
{
struct resource *res;
struct sport_uart_port *sport;
@@ -850,7 +850,7 @@ out_error_free_mem:
return ret;
}
-static int __devexit sport_uart_remove(struct platform_device *pdev)
+static int sport_uart_remove(struct platform_device *pdev)
{
struct sport_uart_port *sport = platform_get_drvdata(pdev);
@@ -871,7 +871,7 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
static struct platform_driver sport_uart_driver = {
.probe = sport_uart_probe,
- .remove = __devexit_p(sport_uart_remove),
+ .remove = sport_uart_remove,
.driver = {
.name = DRV_NAME,
#ifdef CONFIG_PM
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 9242d56ba267..e6a008f4939f 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -477,9 +477,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
{
int x_pos, pos;
+ unsigned long flags;
- dma_disable_irq_nosync(uart->rx_dma_channel);
- spin_lock_bh(&uart->rx_lock);
+ spin_lock_irqsave(&uart->rx_lock, flags);
/* 2D DMA RX buffer ring is used. Because curr_y_count and
* curr_x_count can't be read as an atomic operation,
@@ -510,8 +510,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
}
- spin_unlock_bh(&uart->rx_lock);
- dma_enable_irq(uart->rx_dma_channel);
+ spin_unlock_irqrestore(&uart->rx_lock, flags);
mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
}
@@ -800,6 +799,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned long flags;
unsigned int baud, quot;
unsigned int ier, lcr = 0;
+ unsigned long timeout;
switch (termios->c_cflag & CSIZE) {
case CS8:
@@ -869,6 +869,14 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
+ /* Wait till the transfer buffer is empty */
+ timeout = jiffies + msecs_to_jiffies(10);
+ while (UART_GET_GCTL(uart) & UCEN && !(UART_GET_LSR(uart) & TEMT))
+ if (time_after(jiffies, timeout)) {
+ dev_warn(port->dev, "timeout waiting for TX buffer empty\n");
+ break;
+ }
+
/* Disable UART */
ier = UART_GET_IER(uart);
UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN);
@@ -1390,7 +1398,7 @@ out_error_free_mem:
return ret;
}
-static int __devexit bfin_serial_remove(struct platform_device *pdev)
+static int bfin_serial_remove(struct platform_device *pdev)
{
struct bfin_serial_port *uart = platform_get_drvdata(pdev);
@@ -1410,7 +1418,7 @@ static int __devexit bfin_serial_remove(struct platform_device *pdev)
static struct platform_driver bfin_serial_driver = {
.probe = bfin_serial_probe,
- .remove = __devexit_p(bfin_serial_remove),
+ .remove = bfin_serial_remove,
.suspend = bfin_serial_suspend,
.resume = bfin_serial_resume,
.driver = {
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index d0f719fafc84..3fd2526d121e 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -10,15 +10,6 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -26,172 +17,169 @@
#endif
#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/spinlock.h>
#include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
+#include <linux/console.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#define UART_NR 2
-
-#define SERIAL_CLPS711X_MAJOR 204
-#define SERIAL_CLPS711X_MINOR 40
-#define SERIAL_CLPS711X_NR UART_NR
-
-/*
- * We use the relevant SYSCON register as a base address for these ports.
- */
-#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
-#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
-#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
-#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
-
-#define TX_IRQ(port) ((port)->irq)
-#define RX_IRQ(port) ((port)->irq + 1)
-#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
-
-#define tx_enabled(port) ((port)->unused[0])
+#define UART_CLPS711X_NAME "uart-clps711x"
+#define UART_CLPS711X_NR 2
+#define UART_CLPS711X_MAJOR 204
+#define UART_CLPS711X_MINOR 40
+
+#define UBRLCR(port) ((port)->line ? UBRLCR2 : UBRLCR1)
+#define UARTDR(port) ((port)->line ? UARTDR2 : UARTDR1)
+#define SYSFLG(port) ((port)->line ? SYSFLG2 : SYSFLG1)
+#define SYSCON(port) ((port)->line ? SYSCON2 : SYSCON1)
+#define TX_IRQ(port) ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
+#define RX_IRQ(port) ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
+
+struct clps711x_port {
+ struct uart_driver uart;
+ struct clk *uart_clk;
+ struct uart_port port[UART_CLPS711X_NR];
+ int tx_enabled[UART_CLPS711X_NR];
+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+ struct console console;
+#endif
+};
-static void clps711xuart_stop_tx(struct uart_port *port)
+static void uart_clps711x_stop_tx(struct uart_port *port)
{
- if (tx_enabled(port)) {
+ struct clps711x_port *s = dev_get_drvdata(port->dev);
+
+ if (s->tx_enabled[port->line]) {
disable_irq(TX_IRQ(port));
- tx_enabled(port) = 0;
+ s->tx_enabled[port->line] = 0;
}
}
-static void clps711xuart_start_tx(struct uart_port *port)
+static void uart_clps711x_start_tx(struct uart_port *port)
{
- if (!tx_enabled(port)) {
+ struct clps711x_port *s = dev_get_drvdata(port->dev);
+
+ if (!s->tx_enabled[port->line]) {
enable_irq(TX_IRQ(port));
- tx_enabled(port) = 1;
+ s->tx_enabled[port->line] = 1;
}
}
-static void clps711xuart_stop_rx(struct uart_port *port)
+static void uart_clps711x_stop_rx(struct uart_port *port)
{
disable_irq(RX_IRQ(port));
}
-static void clps711xuart_enable_ms(struct uart_port *port)
+static void uart_clps711x_enable_ms(struct uart_port *port)
{
+ /* Do nothing */
}
-static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id)
+static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
- struct tty_struct *tty = port->state->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
unsigned int status, ch, flg;
- status = clps_readl(SYSFLG(port));
- while (!(status & SYSFLG_URXFE)) {
- ch = clps_readl(UARTDR(port));
+ if (!tty)
+ return IRQ_HANDLED;
- port->icount.rx++;
+ for (;;) {
+ status = clps_readl(SYSFLG(port));
+ if (status & SYSFLG_URXFE)
+ break;
+
+ ch = clps_readw(UARTDR(port));
+ status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR);
+ ch &= 0xff;
+ port->icount.rx++;
flg = TTY_NORMAL;
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- if (unlikely(ch & UART_ANY_ERR)) {
- if (ch & UARTDR_PARERR)
+ if (unlikely(status)) {
+ if (status & UARTDR_PARERR)
port->icount.parity++;
- else if (ch & UARTDR_FRMERR)
+ else if (status & UARTDR_FRMERR)
port->icount.frame++;
- if (ch & UARTDR_OVERR)
+ else if (status & UARTDR_OVERR)
port->icount.overrun++;
- ch &= port->read_status_mask;
+ status &= port->read_status_mask;
- if (ch & UARTDR_PARERR)
+ if (status & UARTDR_PARERR)
flg = TTY_PARITY;
- else if (ch & UARTDR_FRMERR)
+ else if (status & UARTDR_FRMERR)
flg = TTY_FRAME;
-
-#ifdef SUPPORT_SYSRQ
- port->sysrq = 0;
-#endif
+ else if (status & UARTDR_OVERR)
+ flg = TTY_OVERRUN;
}
if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
+ continue;
- /*
- * CHECK: does overrun affect the current character?
- * ASSUMPTION: it does not.
- */
- uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
+ if (status & port->ignore_status_mask)
+ continue;
- ignore_char:
- status = clps_readl(SYSFLG(port));
+ uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
}
+
tty_flip_buffer_push(tty);
+
+ tty_kref_put(tty);
+
return IRQ_HANDLED;
}
-static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
+static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
+ struct clps711x_port *s = dev_get_drvdata(port->dev);
struct circ_buf *xmit = &port->state->xmit;
- int count;
if (port->x_char) {
- clps_writel(port->x_char, UARTDR(port));
+ clps_writew(port->x_char, UARTDR(port));
port->icount.tx++;
port->x_char = 0;
return IRQ_HANDLED;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(port))
- goto disable_tx_irq;
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ disable_irq_nosync(TX_IRQ(port));
+ s->tx_enabled[port->line] = 0;
+ return IRQ_HANDLED;
+ }
- count = port->fifosize >> 1;
- do {
- clps_writel(xmit->buf[xmit->tail], UARTDR(port));
+ while (!uart_circ_empty(xmit)) {
+ clps_writew(xmit->buf[xmit->tail], UARTDR(port));
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
- if (uart_circ_empty(xmit))
+ if (clps_readl(SYSFLG(port) & SYSFLG_UTXFF))
break;
- } while (--count > 0);
+ }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
- if (uart_circ_empty(xmit)) {
- disable_tx_irq:
- disable_irq_nosync(TX_IRQ(port));
- tx_enabled(port) = 0;
- }
-
return IRQ_HANDLED;
}
-static unsigned int clps711xuart_tx_empty(struct uart_port *port)
+static unsigned int uart_clps711x_tx_empty(struct uart_port *port)
{
- unsigned int status = clps_readl(SYSFLG(port));
- return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
+ return (clps_readl(SYSFLG(port) & SYSFLG_UBUSY)) ? 0 : TIOCSER_TEMT;
}
-static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
+static unsigned int uart_clps711x_get_mctrl(struct uart_port *port)
{
- unsigned int port_addr;
- unsigned int result = 0;
- unsigned int status;
+ unsigned int status, result = 0;
- port_addr = SYSFLG(port);
- if (port_addr == SYSFLG1) {
+ if (port->line == 0) {
status = clps_readl(SYSFLG1);
if (status & SYSFLG1_DCD)
result |= TIOCM_CAR;
@@ -199,104 +187,86 @@ static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
result |= TIOCM_DSR;
if (status & SYSFLG1_CTS)
result |= TIOCM_CTS;
- }
+ } else
+ result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
return result;
}
-static void
-clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
+static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ /* Do nothing */
}
-static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
+static void uart_clps711x_break_ctl(struct uart_port *port, int break_state)
{
unsigned long flags;
unsigned int ubrlcr;
spin_lock_irqsave(&port->lock, flags);
+
ubrlcr = clps_readl(UBRLCR(port));
- if (break_state == -1)
+ if (break_state)
ubrlcr |= UBRLCR_BREAK;
else
ubrlcr &= ~UBRLCR_BREAK;
clps_writel(ubrlcr, UBRLCR(port));
+
spin_unlock_irqrestore(&port->lock, flags);
}
-static int clps711xuart_startup(struct uart_port *port)
+static int uart_clps711x_startup(struct uart_port *port)
{
- unsigned int syscon;
- int retval;
-
- tx_enabled(port) = 1;
-
- /*
- * Allocate the IRQs
- */
- retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
- "clps711xuart_tx", port);
- if (retval)
- return retval;
-
- retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
- "clps711xuart_rx", port);
- if (retval) {
- free_irq(TX_IRQ(port), port);
- return retval;
+ struct clps711x_port *s = dev_get_drvdata(port->dev);
+ int ret;
+
+ s->tx_enabled[port->line] = 1;
+ /* Allocate the IRQs */
+ ret = devm_request_irq(port->dev, TX_IRQ(port), uart_clps711x_int_tx,
+ 0, UART_CLPS711X_NAME " TX", port);
+ if (ret)
+ return ret;
+
+ ret = devm_request_irq(port->dev, RX_IRQ(port), uart_clps711x_int_rx,
+ 0, UART_CLPS711X_NAME " RX", port);
+ if (ret) {
+ devm_free_irq(port->dev, TX_IRQ(port), port);
+ return ret;
}
- /*
- * enable the port
- */
- syscon = clps_readl(SYSCON(port));
- syscon |= SYSCON_UARTEN;
- clps_writel(syscon, SYSCON(port));
+ /* Disable break */
+ clps_writel(clps_readl(UBRLCR(port)) & ~UBRLCR_BREAK, UBRLCR(port));
+
+ /* Enable the port */
+ clps_writel(clps_readl(SYSCON(port)) | SYSCON_UARTEN, SYSCON(port));
return 0;
}
-static void clps711xuart_shutdown(struct uart_port *port)
+static void uart_clps711x_shutdown(struct uart_port *port)
{
- unsigned int ubrlcr, syscon;
+ /* Free the interrupts */
+ devm_free_irq(port->dev, TX_IRQ(port), port);
+ devm_free_irq(port->dev, RX_IRQ(port), port);
- /*
- * Free the interrupt
- */
- free_irq(TX_IRQ(port), port); /* TX interrupt */
- free_irq(RX_IRQ(port), port); /* RX interrupt */
-
- /*
- * disable the port
- */
- syscon = clps_readl(SYSCON(port));
- syscon &= ~SYSCON_UARTEN;
- clps_writel(syscon, SYSCON(port));
-
- /*
- * disable break condition and fifos
- */
- ubrlcr = clps_readl(UBRLCR(port));
- ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
- clps_writel(ubrlcr, UBRLCR(port));
+ /* Disable the port */
+ clps_writel(clps_readl(SYSCON(port)) & ~SYSCON_UARTEN, SYSCON(port));
}
-static void
-clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+static void uart_clps711x_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
{
unsigned int ubrlcr, baud, quot;
unsigned long flags;
- /*
- * We don't implement CREAD.
- */
- termios->c_cflag |= CREAD;
+ /* Mask termios capabilities we don't support */
+ termios->c_cflag &= ~CMSPAR;
+ termios->c_iflag &= ~(BRKINT | IGNBRK);
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ /* Ask the core to calculate the divisor for us */
+ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 4096,
+ port->uartclk / 16);
quot = uart_get_divisor(port, baud);
switch (termios->c_cflag & CSIZE) {
@@ -309,160 +279,117 @@ clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
case CS7:
ubrlcr = UBRLCR_WRDLEN7;
break;
- default: // CS8
+ case CS8:
+ default:
ubrlcr = UBRLCR_WRDLEN8;
break;
}
+
if (termios->c_cflag & CSTOPB)
ubrlcr |= UBRLCR_XSTOP;
+
if (termios->c_cflag & PARENB) {
ubrlcr |= UBRLCR_PRTEN;
if (!(termios->c_cflag & PARODD))
ubrlcr |= UBRLCR_EVENPRT;
}
- if (port->fifosize > 1)
- ubrlcr |= UBRLCR_FIFOEN;
- spin_lock_irqsave(&port->lock, flags);
+ /* Enable FIFO */
+ ubrlcr |= UBRLCR_FIFOEN;
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
+ spin_lock_irqsave(&port->lock, flags);
+ /* Set read status mask */
port->read_status_mask = UARTDR_OVERR;
if (termios->c_iflag & INPCK)
port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
- /*
- * Characters to ignore
- */
+ /* Set status ignore mask */
port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
- if (termios->c_iflag & IGNBRK) {
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns to (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UARTDR_OVERR;
- }
+ if (!(termios->c_cflag & CREAD))
+ port->ignore_status_mask |= UARTDR_OVERR | UARTDR_PARERR |
+ UARTDR_FRMERR;
- quot -= 1;
+ uart_update_timeout(port, termios->c_cflag, baud);
- clps_writel(ubrlcr | quot, UBRLCR(port));
+ clps_writel(ubrlcr | (quot - 1), UBRLCR(port));
spin_unlock_irqrestore(&port->lock, flags);
}
-static const char *clps711xuart_type(struct uart_port *port)
+static const char *uart_clps711x_type(struct uart_port *port)
{
- return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
+ return (port->type == PORT_CLPS711X) ? "CLPS711X" : NULL;
}
-/*
- * Configure/autoconfigure the port.
- */
-static void clps711xuart_config_port(struct uart_port *port, int flags)
+static void uart_clps711x_config_port(struct uart_port *port, int flags)
{
if (flags & UART_CONFIG_TYPE)
port->type = PORT_CLPS711X;
}
-static void clps711xuart_release_port(struct uart_port *port)
+static void uart_clps711x_release_port(struct uart_port *port)
{
+ /* Do nothing */
}
-static int clps711xuart_request_port(struct uart_port *port)
+static int uart_clps711x_request_port(struct uart_port *port)
{
+ /* Do nothing */
return 0;
}
-static struct uart_ops clps711x_pops = {
- .tx_empty = clps711xuart_tx_empty,
- .set_mctrl = clps711xuart_set_mctrl_null,
- .get_mctrl = clps711xuart_get_mctrl,
- .stop_tx = clps711xuart_stop_tx,
- .start_tx = clps711xuart_start_tx,
- .stop_rx = clps711xuart_stop_rx,
- .enable_ms = clps711xuart_enable_ms,
- .break_ctl = clps711xuart_break_ctl,
- .startup = clps711xuart_startup,
- .shutdown = clps711xuart_shutdown,
- .set_termios = clps711xuart_set_termios,
- .type = clps711xuart_type,
- .config_port = clps711xuart_config_port,
- .release_port = clps711xuart_release_port,
- .request_port = clps711xuart_request_port,
-};
-
-static struct uart_port clps711x_ports[UART_NR] = {
- {
- .iobase = SYSCON1,
- .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
- .uartclk = 3686400,
- .fifosize = 16,
- .ops = &clps711x_pops,
- .line = 0,
- .flags = UPF_BOOT_AUTOCONF,
- },
- {
- .iobase = SYSCON2,
- .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
- .uartclk = 3686400,
- .fifosize = 16,
- .ops = &clps711x_pops,
- .line = 1,
- .flags = UPF_BOOT_AUTOCONF,
- }
+static const struct uart_ops uart_clps711x_ops = {
+ .tx_empty = uart_clps711x_tx_empty,
+ .set_mctrl = uart_clps711x_set_mctrl,
+ .get_mctrl = uart_clps711x_get_mctrl,
+ .stop_tx = uart_clps711x_stop_tx,
+ .start_tx = uart_clps711x_start_tx,
+ .stop_rx = uart_clps711x_stop_rx,
+ .enable_ms = uart_clps711x_enable_ms,
+ .break_ctl = uart_clps711x_break_ctl,
+ .startup = uart_clps711x_startup,
+ .shutdown = uart_clps711x_shutdown,
+ .set_termios = uart_clps711x_set_termios,
+ .type = uart_clps711x_type,
+ .config_port = uart_clps711x_config_port,
+ .release_port = uart_clps711x_release_port,
+ .request_port = uart_clps711x_request_port,
};
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-static void clps711xuart_console_putchar(struct uart_port *port, int ch)
+static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
{
while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
barrier();
- clps_writel(ch, UARTDR(port));
+
+ clps_writew(ch, UARTDR(port));
}
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- *
- * Note that this is called with interrupts already disabled
- */
-static void
-clps711xuart_console_write(struct console *co, const char *s,
- unsigned int count)
+static void uart_clps711x_console_write(struct console *co, const char *c,
+ unsigned n)
{
- struct uart_port *port = clps711x_ports + co->index;
- unsigned int status, syscon;
+ struct clps711x_port *s = (struct clps711x_port *)co->data;
+ struct uart_port *port = &s->port[co->index];
+ u32 syscon;
- /*
- * Ensure that the port is enabled.
- */
+ /* Ensure that the port is enabled */
syscon = clps_readl(SYSCON(port));
clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
- uart_console_write(port, s, count, clps711xuart_console_putchar);
+ uart_console_write(port, c, n, uart_clps711x_console_putchar);
- /*
- * Finally, wait for transmitter to become empty
- * and restore the uart state.
- */
- do {
- status = clps_readl(SYSFLG(port));
- } while (status & SYSFLG_UBUSY);
+ /* Wait for transmitter to become empty */
+ while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY)
+ barrier();
+ /* Restore the uart state */
clps_writel(syscon, SYSCON(port));
}
-static void __init
-clps711xuart_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
+static void uart_clps711x_console_get_options(struct uart_port *port,
+ int *baud, int *parity,
+ int *bits)
{
if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
unsigned int ubrlcr, quot;
@@ -487,92 +414,124 @@ clps711xuart_console_get_options(struct uart_port *port, int *baud,
}
}
-static int __init clps711xuart_console_setup(struct console *co, char *options)
+static int uart_clps711x_console_setup(struct console *co, char *options)
{
- struct uart_port *port;
- int baud = 38400;
- 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(clps711x_ports, UART_NR, co);
+ int baud = 38400, bits = 8, parity = 'n', flow = 'n';
+ struct clps711x_port *s = (struct clps711x_port *)co->data;
+ struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
- clps711xuart_console_get_options(port, &baud, &parity, &bits);
+ uart_clps711x_console_get_options(port, &baud, &parity, &bits);
return uart_set_options(port, co, baud, parity, bits, flow);
}
+#endif
-static struct uart_driver clps711x_reg;
-static struct console clps711x_console = {
- .name = "ttyCL",
- .write = clps711xuart_console_write,
- .device = uart_console_device,
- .setup = clps711xuart_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &clps711x_reg,
-};
-
-static int __init clps711xuart_console_init(void)
+static int uart_clps711x_probe(struct platform_device *pdev)
{
- register_console(&clps711x_console);
- return 0;
-}
-console_initcall(clps711xuart_console_init);
+ struct clps711x_port *s;
+ int ret, i;
+
+ s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL);
+ if (!s) {
+ dev_err(&pdev->dev, "Error allocating port structure\n");
+ return -ENOMEM;
+ }
+ platform_set_drvdata(pdev, s);
-#define CLPS711X_CONSOLE &clps711x_console
-#else
-#define CLPS711X_CONSOLE NULL
+ s->uart_clk = devm_clk_get(&pdev->dev, "uart");
+ if (IS_ERR(s->uart_clk)) {
+ dev_err(&pdev->dev, "Can't get UART clocks\n");
+ ret = PTR_ERR(s->uart_clk);
+ goto err_out;
+ }
+
+ s->uart.owner = THIS_MODULE;
+ s->uart.dev_name = "ttyCL";
+ s->uart.major = UART_CLPS711X_MAJOR;
+ s->uart.minor = UART_CLPS711X_MINOR;
+ s->uart.nr = UART_CLPS711X_NR;
+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
+ s->uart.cons = &s->console;
+ s->uart.cons->device = uart_console_device;
+ s->uart.cons->write = uart_clps711x_console_write;
+ s->uart.cons->setup = uart_clps711x_console_setup;
+ s->uart.cons->flags = CON_PRINTBUFFER;
+ s->uart.cons->index = -1;
+ s->uart.cons->data = s;
+ strcpy(s->uart.cons->name, "ttyCL");
#endif
+ ret = uart_register_driver(&s->uart);
+ if (ret) {
+ dev_err(&pdev->dev, "Registering UART driver failed\n");
+ devm_clk_put(&pdev->dev, s->uart_clk);
+ goto err_out;
+ }
-static struct uart_driver clps711x_reg = {
- .driver_name = "ttyCL",
- .dev_name = "ttyCL",
- .major = SERIAL_CLPS711X_MAJOR,
- .minor = SERIAL_CLPS711X_MINOR,
- .nr = UART_NR,
+ for (i = 0; i < UART_CLPS711X_NR; i++) {
+ s->port[i].line = i;
+ s->port[i].dev = &pdev->dev;
+ s->port[i].irq = TX_IRQ(&s->port[i]);
+ s->port[i].iobase = SYSCON(&s->port[i]);
+ s->port[i].type = PORT_CLPS711X;
+ s->port[i].fifosize = 16;
+ s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
+ s->port[i].uartclk = clk_get_rate(s->uart_clk);
+ s->port[i].ops = &uart_clps711x_ops;
+ WARN_ON(uart_add_one_port(&s->uart, &s->port[i]));
+ }
- .cons = CLPS711X_CONSOLE,
-};
+ return 0;
-static int __init clps711xuart_init(void)
-{
- int ret, i;
+err_out:
+ platform_set_drvdata(pdev, NULL);
- printk(KERN_INFO "Serial: CLPS711x driver\n");
+ return ret;
+}
- ret = uart_register_driver(&clps711x_reg);
- if (ret)
- return ret;
+static int uart_clps711x_remove(struct platform_device *pdev)
+{
+ struct clps711x_port *s = platform_get_drvdata(pdev);
+ int i;
- for (i = 0; i < UART_NR; i++)
- uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
+ for (i = 0; i < UART_CLPS711X_NR; i++)
+ uart_remove_one_port(&s->uart, &s->port[i]);
+
+ devm_clk_put(&pdev->dev, s->uart_clk);
+ uart_unregister_driver(&s->uart);
+ platform_set_drvdata(pdev, NULL);
return 0;
}
-static void __exit clps711xuart_exit(void)
-{
- int i;
+static struct platform_driver clps711x_uart_driver = {
+ .driver = {
+ .name = UART_CLPS711X_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = uart_clps711x_probe,
+ .remove = uart_clps711x_remove,
+};
+module_platform_driver(clps711x_uart_driver);
- for (i = 0; i < UART_NR; i++)
- uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
+static struct platform_device clps711x_uart_device = {
+ .name = UART_CLPS711X_NAME,
+};
- uart_unregister_driver(&clps711x_reg);
+static int __init uart_clps711x_init(void)
+{
+ return platform_device_register(&clps711x_uart_device);
}
+module_init(uart_clps711x_init);
-module_init(clps711xuart_init);
-module_exit(clps711xuart_exit);
+static void __exit uart_clps711x_exit(void)
+{
+ platform_device_unregister(&clps711x_uart_device);
+}
+module_exit(uart_clps711x_exit);
MODULE_AUTHOR("Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("CLPS-711x generic serial driver");
+MODULE_DESCRIPTION("CLPS711X serial driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index d0dd9194cecc..ad0caf176808 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1373,7 +1373,7 @@ static struct uart_driver cpm_reg = {
static int probe_index;
-static int __devinit cpm_uart_probe(struct platform_device *ofdev)
+static int cpm_uart_probe(struct platform_device *ofdev)
{
int index = probe_index++;
struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
@@ -1396,7 +1396,7 @@ static int __devinit cpm_uart_probe(struct platform_device *ofdev)
return uart_add_one_port(&cpm_reg, &pinfo->port);
}
-static int __devexit cpm_uart_remove(struct platform_device *ofdev)
+static int cpm_uart_remove(struct platform_device *ofdev)
{
struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
return uart_remove_one_port(&cpm_reg, &pinfo->port);
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
index 615e46470491..a8cbb2670521 100644
--- a/drivers/tty/serial/efm32-uart.c
+++ b/drivers/tty/serial/efm32-uart.c
@@ -690,7 +690,7 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
}
-static int __devinit efm32_uart_probe(struct platform_device *pdev)
+static int efm32_uart_probe(struct platform_device *pdev)
{
struct efm32_uart_port *efm_port;
struct resource *res;
@@ -764,7 +764,7 @@ err_get_base:
return ret;
}
-static int __devexit efm32_uart_remove(struct platform_device *pdev)
+static int efm32_uart_remove(struct platform_device *pdev)
{
struct efm32_uart_port *efm_port = platform_get_drvdata(pdev);
@@ -791,7 +791,7 @@ MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids);
static struct platform_driver efm32_uart_driver = {
.probe = efm32_uart_probe,
- .remove = __devexit_p(efm32_uart_remove),
+ .remove = efm32_uart_remove,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index defc4e3393a3..6197a69adb4d 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -175,7 +175,7 @@ static void free_port_memory(struct icom_port *icom_port)
}
}
-static int __devinit get_port_memory(struct icom_port *icom_port)
+static int get_port_memory(struct icom_port *icom_port)
{
int index;
unsigned long stgAddr;
@@ -1314,7 +1314,7 @@ static struct uart_driver icom_uart_driver = {
.cons = ICOM_CONSOLE,
};
-static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
+static int icom_init_ports(struct icom_adapter *icom_adapter)
{
u32 subsystem_id = icom_adapter->subsystem_id;
int i;
@@ -1381,7 +1381,7 @@ static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *i
0x8024 + 2 - 2 * (icom_port->port - 2);
}
}
-static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
+static int icom_load_ports(struct icom_adapter *icom_adapter)
{
struct icom_port *icom_port;
int port_num;
@@ -1407,7 +1407,7 @@ static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
return 0;
}
-static int __devinit icom_alloc_adapter(struct icom_adapter
+static int icom_alloc_adapter(struct icom_adapter
**icom_adapter_ref)
{
int adapter_count = 0;
@@ -1487,7 +1487,7 @@ static void icom_kref_release(struct kref *kref)
icom_remove_adapter(icom_adapter);
}
-static int __devinit icom_probe(struct pci_dev *dev,
+static int icom_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
int index;
@@ -1596,7 +1596,7 @@ probe_exit0:
return retval;
}
-static void __devexit icom_remove(struct pci_dev *dev)
+static void icom_remove(struct pci_dev *dev)
{
struct icom_adapter *icom_adapter;
struct list_head *tmp;
@@ -1617,7 +1617,7 @@ static struct pci_driver icom_pci_driver = {
.name = ICOM_DRIVER_NAME,
.id_table = icom_pci_table,
.probe = icom_probe,
- .remove = __devexit_p(icom_remove),
+ .remove = icom_remove,
};
static int __init icom_init(void)
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5b9bc19ed134..675d94ab0aff 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -60,20 +60,27 @@
#include <linux/pm_runtime.h>
#include <linux/spi/ifx_modem.h>
#include <linux/delay.h>
+#include <linux/reboot.h>
#include "ifx6x60.h"
#define IFX_SPI_MORE_MASK 0x10
-#define IFX_SPI_MORE_BIT 12 /* bit position in u16 */
-#define IFX_SPI_CTS_BIT 13 /* bit position in u16 */
+#define IFX_SPI_MORE_BIT 4 /* bit position in u8 */
+#define IFX_SPI_CTS_BIT 6 /* bit position in u8 */
#define IFX_SPI_MODE SPI_MODE_1
#define IFX_SPI_TTY_ID 0
#define IFX_SPI_TIMEOUT_SEC 2
#define IFX_SPI_HEADER_0 (-1)
#define IFX_SPI_HEADER_F (-2)
+#define PO_POST_DELAY 200
+#define IFX_MDM_RST_PMU 4
+
/* forward reference */
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
+static int ifx_modem_reboot_callback(struct notifier_block *nfb,
+ unsigned long event, void *data);
+static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev);
/* local variables */
static int spi_bpw = 16; /* 8, 16 or 32 bit word length */
@@ -81,6 +88,29 @@ static struct tty_driver *tty_drv;
static struct ifx_spi_device *saved_ifx_dev;
static struct lock_class_key ifx_spi_key;
+static struct notifier_block ifx_modem_reboot_notifier_block = {
+ .notifier_call = ifx_modem_reboot_callback,
+};
+
+static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev)
+{
+ gpio_set_value(IFX_MDM_RST_PMU, 1);
+ msleep(PO_POST_DELAY);
+
+ return 0;
+}
+
+static int ifx_modem_reboot_callback(struct notifier_block *nfb,
+ unsigned long event, void *data)
+{
+ if (saved_ifx_dev)
+ ifx_modem_power_off(saved_ifx_dev);
+ else
+ pr_warn("no ifx modem active;\n");
+
+ return NOTIFY_OK;
+}
+
/* GPIO/GPE settings */
/**
@@ -152,26 +182,67 @@ ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val)
}
/**
- * swap_buf
+ * swap_buf_8
* @buf: our buffer
* @len : number of bytes (not words) in the buffer
* @end: end of buffer
*
* Swap the contents of a buffer into big endian format
*/
-static inline void swap_buf(u16 *buf, int len, void *end)
+static inline void swap_buf_8(unsigned char *buf, int len, void *end)
+{
+ /* don't swap buffer if SPI word width is 8 bits */
+ return;
+}
+
+/**
+ * swap_buf_16
+ * @buf: our buffer
+ * @len : number of bytes (not words) in the buffer
+ * @end: end of buffer
+ *
+ * Swap the contents of a buffer into big endian format
+ */
+static inline void swap_buf_16(unsigned char *buf, int len, void *end)
{
int n;
+ u16 *buf_16 = (u16 *)buf;
len = ((len + 1) >> 1);
- if ((void *)&buf[len] > end) {
- pr_err("swap_buf: swap exceeds boundary (%p > %p)!",
- &buf[len], end);
+ if ((void *)&buf_16[len] > end) {
+ pr_err("swap_buf_16: swap exceeds boundary (%p > %p)!",
+ &buf_16[len], end);
+ return;
+ }
+ for (n = 0; n < len; n++) {
+ *buf_16 = cpu_to_be16(*buf_16);
+ buf_16++;
+ }
+}
+
+/**
+ * swap_buf_32
+ * @buf: our buffer
+ * @len : number of bytes (not words) in the buffer
+ * @end: end of buffer
+ *
+ * Swap the contents of a buffer into big endian format
+ */
+static inline void swap_buf_32(unsigned char *buf, int len, void *end)
+{
+ int n;
+
+ u32 *buf_32 = (u32 *)buf;
+ len = (len + 3) >> 2;
+
+ if ((void *)&buf_32[len] > end) {
+ pr_err("swap_buf_32: swap exceeds boundary (%p > %p)!\n",
+ &buf_32[len], end);
return;
}
for (n = 0; n < len; n++) {
- *buf = cpu_to_be16(*buf);
- buf++;
+ *buf_32 = cpu_to_be32(*buf_32);
+ buf_32++;
}
}
@@ -190,9 +261,7 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
if (!val) {
if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
&ifx_dev->flags)) {
- ifx_dev->spi_timer.expires =
- jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
- add_timer(&ifx_dev->spi_timer);
+ mod_timer(&ifx_dev->spi_timer,jiffies + IFX_SPI_TIMEOUT_SEC*HZ);
}
}
@@ -449,7 +518,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
tx_count-IFX_SPI_HEADER_OVERHEAD,
ifx_dev->spi_more);
/* swap actual data in the buffer */
- swap_buf((u16 *)(ifx_dev->tx_buffer), tx_count,
+ ifx_dev->swap_buf((ifx_dev->tx_buffer), tx_count,
&ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]);
return tx_count;
}
@@ -469,9 +538,17 @@ static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf,
{
struct ifx_spi_device *ifx_dev = tty->driver_data;
unsigned char *tmp_buf = (unsigned char *)buf;
- int tx_count = kfifo_in_locked(&ifx_dev->tx_fifo, tmp_buf, count,
- &ifx_dev->fifo_lock);
- mrdy_assert(ifx_dev);
+ unsigned long flags;
+ bool is_fifo_empty;
+ int tx_count;
+
+ spin_lock_irqsave(&ifx_dev->fifo_lock, flags);
+ is_fifo_empty = kfifo_is_empty(&ifx_dev->tx_fifo);
+ tx_count = kfifo_in(&ifx_dev->tx_fifo, tmp_buf, count);
+ spin_unlock_irqrestore(&ifx_dev->fifo_lock, flags);
+ if (is_fifo_empty)
+ mrdy_assert(ifx_dev);
+
return tx_count;
}
@@ -530,12 +607,19 @@ static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
/* clear any old data; can't do this in 'close' */
kfifo_reset(&ifx_dev->tx_fifo);
+ /* clear any flag which may be set in port shutdown procedure */
+ clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
+ clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
+
/* put port data into this tty */
tty->driver_data = ifx_dev;
/* allows flip string push from int context */
tty->low_latency = 1;
+ /* set flag to allows data transfer */
+ set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
+
return 0;
}
@@ -551,6 +635,7 @@ static void ifx_port_shutdown(struct tty_port *port)
struct ifx_spi_device *ifx_dev =
container_of(port, struct ifx_spi_device, tty_port);
+ clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
mrdy_set_low(ifx_dev);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
tasklet_kill(&ifx_dev->io_work_tasklet);
@@ -617,7 +702,7 @@ static void ifx_spi_complete(void *ctx)
if (!ifx_dev->spi_msg.status) {
/* check header validity, get comm flags */
- swap_buf((u16 *)ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
+ ifx_dev->swap_buf(ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
&ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]);
decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer,
&length, &more, &cts);
@@ -636,7 +721,8 @@ static void ifx_spi_complete(void *ctx)
actual_length = min((unsigned int)length,
ifx_dev->spi_msg.actual_length);
- swap_buf((u16 *)(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
+ ifx_dev->swap_buf(
+ (ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
actual_length,
&ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]);
ifx_spi_insert_flip_string(
@@ -705,7 +791,8 @@ static void ifx_spi_io(unsigned long data)
int retval;
struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
- if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) {
+ if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) &&
+ test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) {
if (ifx_dev->gpio.unack_srdy_int_nb > 0)
ifx_dev->gpio.unack_srdy_int_nb--;
@@ -773,6 +860,7 @@ static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev)
{
if (ifx_dev->tty_dev)
tty_unregister_device(tty_drv, ifx_dev->minor);
+ tty_port_destroy(&ifx_dev->tty_port);
kfifo_free(&ifx_dev->tx_fifo);
}
@@ -806,10 +894,12 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
dev_dbg(&ifx_dev->spi_dev->dev,
"%s: registering tty device failed", __func__);
ret = PTR_ERR(ifx_dev->tty_dev);
- goto error_ret;
+ goto error_port;
}
return 0;
+error_port:
+ tty_port_destroy(pport);
error_ret:
ifx_spi_free_port(ifx_dev);
return ret;
@@ -826,7 +916,7 @@ error_ret:
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev)
{
if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) {
- del_timer_sync(&ifx_dev->spi_timer);
+ del_timer(&ifx_dev->spi_timer);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
}
@@ -1001,6 +1091,14 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
return -ENODEV;
}
+ /* init swap_buf function according to word width configuration */
+ if (spi->bits_per_word == 32)
+ ifx_dev->swap_buf = swap_buf_32;
+ else if (spi->bits_per_word == 16)
+ ifx_dev->swap_buf = swap_buf_16;
+ else
+ ifx_dev->swap_buf = swap_buf_8;
+
/* ensure SPI protocol flags are initialized to enable transfer */
ifx_dev->spi_more = 0;
ifx_dev->spi_slave_cts = 0;
@@ -1219,6 +1317,9 @@ static int ifx_spi_spi_remove(struct spi_device *spi)
static void ifx_spi_spi_shutdown(struct spi_device *spi)
{
+ struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
+
+ ifx_modem_power_off(ifx_dev);
}
/*
@@ -1338,7 +1439,7 @@ static struct spi_driver ifx_spi_driver = {
.owner = THIS_MODULE},
.probe = ifx_spi_spi_probe,
.shutdown = ifx_spi_spi_shutdown,
- .remove = __devexit_p(ifx_spi_spi_remove),
+ .remove = ifx_spi_spi_remove,
.suspend = ifx_spi_spi_suspend,
.resume = ifx_spi_spi_resume,
.id_table = ifx_id_table
@@ -1354,7 +1455,9 @@ static void __exit ifx_spi_exit(void)
{
/* unregister */
tty_unregister_driver(tty_drv);
+ put_tty_driver(tty_drv);
spi_unregister_driver((void *)&ifx_spi_driver);
+ unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
}
/**
@@ -1389,16 +1492,31 @@ static int __init ifx_spi_init(void)
if (result) {
pr_err("%s: tty_register_driver failed(%d)",
DRVNAME, result);
- put_tty_driver(tty_drv);
- return result;
+ goto err_free_tty;
}
result = spi_register_driver((void *)&ifx_spi_driver);
if (result) {
pr_err("%s: spi_register_driver failed(%d)",
DRVNAME, result);
- tty_unregister_driver(tty_drv);
+ goto err_unreg_tty;
}
+
+ result = register_reboot_notifier(&ifx_modem_reboot_notifier_block);
+ if (result) {
+ pr_err("%s: register ifx modem reboot notifier failed(%d)",
+ DRVNAME, result);
+ goto err_unreg_spi;
+ }
+
+ return 0;
+err_unreg_spi:
+ spi_unregister_driver((void *)&ifx_spi_driver);
+err_unreg_tty:
+ tty_unregister_driver(tty_drv);
+err_free_tty:
+ put_tty_driver(tty_drv);
+
return result;
}
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464baf9e75..4fbddc297839 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -41,6 +41,7 @@
#define IFX_SPI_STATE_IO_IN_PROGRESS 1
#define IFX_SPI_STATE_IO_READY 2
#define IFX_SPI_STATE_TIMER_PENDING 3
+#define IFX_SPI_STATE_IO_AVAILABLE 4
/* flow control bitfields */
#define IFX_SPI_DCD 0
@@ -124,6 +125,7 @@ struct ifx_spi_device {
#define MR_INPROGRESS 1
#define MR_COMPLETE 2
wait_queue_head_t mdm_reset_wait;
+ void (*swap_buf)(unsigned char *buf, int len, void *end);
};
#endif /* _IFX6X60_H */
diff --git a/drivers/tty/serial/ioc3_serial.c b/drivers/tty/serial/ioc3_serial.c
index 5ac52898a0bb..d8f1d1d54471 100644
--- a/drivers/tty/serial/ioc3_serial.c
+++ b/drivers/tty/serial/ioc3_serial.c
@@ -2010,7 +2010,7 @@ static int ioc3uart_remove(struct ioc3_submodule *is,
* @idd: ioc3 driver data for this card
*/
-static int __devinit
+static int
ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
{
struct pci_dev *pdev = idd->pdev;
diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h
index 529bec6edaf8..844d5e4eb1aa 100644
--- a/drivers/tty/serial/jsm/jsm.h
+++ b/drivers/tty/serial/jsm/jsm.h
@@ -57,9 +57,11 @@ enum {
DBG_CARR = 0x10000,
};
-#define jsm_printk(nlevel, klevel, pdev, fmt, args...) \
- if ((DBG_##nlevel & jsm_debug)) \
- dev_printk(KERN_##klevel, pdev->dev, fmt, ## args)
+#define jsm_dbg(nlevel, pdev, fmt, ...) \
+do { \
+ if (DBG_##nlevel & jsm_debug) \
+ dev_dbg(pdev->dev, fmt, ##__VA_ARGS__); \
+} while (0)
#define MAXLINES 256
#define MAXPORTS 8
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index 5ab3c3b595e4..a47d882d6743 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -64,7 +64,7 @@ int jsm_debug;
module_param(jsm_debug, int, 0);
MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
-static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int rc = 0;
struct jsm_board *brd;
@@ -107,8 +107,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
brd->irq = pdev->irq;
- jsm_printk(INIT, INFO, &brd->pci_dev,
- "jsm_found_board - NEO adapter\n");
+ jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n");
/* get the PCI Base Address Registers */
brd->membase = pci_resource_start(pdev, 0);
@@ -179,7 +178,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
return rc;
}
-static void __devexit jsm_remove_one(struct pci_dev *pdev)
+static void jsm_remove_one(struct pci_dev *pdev)
{
struct jsm_board *brd = pci_get_drvdata(pdev);
int i = 0;
@@ -218,7 +217,7 @@ static struct pci_driver jsm_driver = {
.name = "jsm",
.id_table = jsm_pci_tbl,
.probe = jsm_probe_one,
- .remove = __devexit_p(jsm_remove_one),
+ .remove = jsm_remove_one,
.err_handler = &jsm_err_handler,
};
diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c
index 81dfafa11b0b..dfaf48826417 100644
--- a/drivers/tty/serial/jsm/jsm_neo.c
+++ b/drivers/tty/serial/jsm/jsm_neo.c
@@ -52,7 +52,7 @@ static void neo_set_cts_flow_control(struct jsm_channel *ch)
ier = readb(&ch->ch_neo_uart->ier);
efr = readb(&ch->ch_neo_uart->efr);
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
+ jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
/* Turn on auto CTS flow control */
ier |= (UART_17158_IER_CTSDSR);
@@ -83,7 +83,7 @@ static void neo_set_rts_flow_control(struct jsm_channel *ch)
ier = readb(&ch->ch_neo_uart->ier);
efr = readb(&ch->ch_neo_uart->efr);
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
+ jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
/* Turn on auto RTS flow control */
ier |= (UART_17158_IER_RTSDTR);
@@ -123,7 +123,7 @@ static void neo_set_ixon_flow_control(struct jsm_channel *ch)
ier = readb(&ch->ch_neo_uart->ier);
efr = readb(&ch->ch_neo_uart->efr);
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
+ jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
/* Turn off auto CTS flow control */
ier &= ~(UART_17158_IER_CTSDSR);
@@ -160,7 +160,7 @@ static void neo_set_ixoff_flow_control(struct jsm_channel *ch)
ier = readb(&ch->ch_neo_uart->ier);
efr = readb(&ch->ch_neo_uart->efr);
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
+ jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
/* Turn off auto RTS flow control */
ier &= ~(UART_17158_IER_RTSDTR);
@@ -198,7 +198,7 @@ static void neo_set_no_input_flow_control(struct jsm_channel *ch)
ier = readb(&ch->ch_neo_uart->ier);
efr = readb(&ch->ch_neo_uart->efr);
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
+ jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
/* Turn off auto RTS flow control */
ier &= ~(UART_17158_IER_RTSDTR);
@@ -237,7 +237,7 @@ static void neo_set_no_output_flow_control(struct jsm_channel *ch)
ier = readb(&ch->ch_neo_uart->ier);
efr = readb(&ch->ch_neo_uart->efr);
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
+ jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
/* Turn off auto CTS flow control */
ier &= ~(UART_17158_IER_CTSDSR);
@@ -276,7 +276,7 @@ static inline void neo_set_new_start_stop_chars(struct jsm_channel *ch)
if (ch->ch_c_cflag & CRTSCTS)
return;
- jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "start\n");
+ jsm_dbg(PARAM, &ch->ch_bd->pci_dev, "start\n");
/* Tell UART what start/stop chars it should be looking for */
writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
@@ -455,7 +455,7 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
* I hope thats okay with everyone? Yes? Good.
*/
while (qleft < 1) {
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ jsm_dbg(READ, &ch->ch_bd->pci_dev,
"Queue full, dropping DATA:%x LSR:%x\n",
ch->ch_rqueue[tail], ch->ch_equeue[tail]);
@@ -467,8 +467,8 @@ static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
ch->ch_equeue[head] = (u8) linestatus;
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]);
+ jsm_dbg(READ, &ch->ch_bd->pci_dev, "DATA/LSR pair: %x %x\n",
+ ch->ch_rqueue[head], ch->ch_equeue[head]);
/* Ditch any remaining linestatus value. */
linestatus = 0;
@@ -521,8 +521,8 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
ch->ch_cached_lsr &= ~(UART_LSR_THRE);
writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx);
- jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
- "Tx data: %x\n", circ->buf[circ->tail]);
+ jsm_dbg(WRITE, &ch->ch_bd->pci_dev,
+ "Tx data: %x\n", circ->buf[circ->tail]);
circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1);
ch->ch_txcount++;
}
@@ -575,8 +575,9 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
{
u8 msignals = signals;
- jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
- "neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
+ jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
+ "neo_parse_modem: port: %d msignals: %x\n",
+ ch->ch_portnum, msignals);
/* Scrub off lower bits. They signify delta's, which I don't care about */
/* Keep DDCD and DDSR though */
@@ -606,8 +607,8 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
else
ch->ch_mistat &= ~UART_MSR_CTS;
- jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
- "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
+ jsm_dbg(MSIGS, &ch->ch_bd->pci_dev,
+ "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
ch->ch_portnum,
!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
@@ -649,8 +650,8 @@ static void neo_flush_uart_write(struct jsm_channel *ch)
/* Check to see if the UART feels it completely flushed the FIFO. */
tmp = readb(&ch->ch_neo_uart->isr_fcr);
if (tmp & 4) {
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
- "Still flushing TX UART... i: %d\n", i);
+ jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
+ "Still flushing TX UART... i: %d\n", i);
udelay(10);
}
else
@@ -681,8 +682,8 @@ static void neo_flush_uart_read(struct jsm_channel *ch)
/* Check to see if the UART feels it completely flushed the FIFO. */
tmp = readb(&ch->ch_neo_uart->isr_fcr);
if (tmp & 2) {
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
- "Still flushing RX UART... i: %d\n", i);
+ jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
+ "Still flushing RX UART... i: %d\n", i);
udelay(10);
}
else
@@ -705,8 +706,9 @@ static void neo_clear_break(struct jsm_channel *ch, int force)
writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
ch->ch_flags &= ~(CH_BREAK_SENDING);
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
- "clear break Finishing UART_LCR_SBC! finished: %lx\n", jiffies);
+ jsm_dbg(IOCTL, &ch->ch_bd->pci_dev,
+ "clear break Finishing UART_LCR_SBC! finished: %lx\n",
+ jiffies);
/* flush write operation */
neo_pci_posting_flush(ch->ch_bd);
@@ -748,8 +750,8 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
*/
isr &= ~(UART_17158_IIR_FIFO_ENABLED);
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "%s:%d isr: %x\n", __FILE__, __LINE__, isr);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d isr: %x\n",
+ __FILE__, __LINE__, isr);
if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
/* Read data from uart -> queue */
@@ -772,8 +774,9 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
if (isr & UART_17158_IIR_XONXOFF) {
cause = readb(&ch->ch_neo_uart->xoffchar1);
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "Port %d. Got ISR_XONXOFF: cause:%x\n",
+ port, cause);
/*
* Since the UART detected either an XON or
@@ -786,17 +789,19 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
if (brd->channels[port]->ch_flags & CH_STOP) {
ch->ch_flags &= ~(CH_STOP);
}
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Port %d. XON detected in incoming data\n", port);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "Port %d. XON detected in incoming data\n",
+ port);
}
else if (cause == UART_17158_XOFF_DETECT) {
if (!(brd->channels[port]->ch_flags & CH_STOP)) {
ch->ch_flags |= CH_STOP;
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Setting CH_STOP\n");
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "Setting CH_STOP\n");
}
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "Port: %d. XOFF detected in incoming data\n", port);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "Port: %d. XOFF detected in incoming data\n",
+ port);
}
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
}
@@ -825,8 +830,8 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
}
/* Parse any modem signal changes */
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "MOD_STAT: sending to parse_modem_sigs\n");
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "MOD_STAT: sending to parse_modem_sigs\n");
neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
}
}
@@ -849,8 +854,8 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
linestatus = readb(&ch->ch_neo_uart->lsr);
- jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
- "%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d port: %d linestatus: %x\n",
+ __FILE__, __LINE__, port, linestatus);
ch->ch_cached_lsr |= linestatus;
@@ -869,7 +874,7 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
*to do the special RX+LSR read for this FIFO load.
*/
if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
"%s:%d Port: %d Got an RX error, need to parse LSR\n",
__FILE__, __LINE__, port);
@@ -880,20 +885,21 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
if (linestatus & UART_LSR_PE) {
ch->ch_err_parity++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d Port: %d. PAR ERR!\n",
+ __FILE__, __LINE__, port);
}
if (linestatus & UART_LSR_FE) {
ch->ch_err_frame++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev, "%s:%d Port: %d. FRM ERR!\n",
+ __FILE__, __LINE__, port);
}
if (linestatus & UART_LSR_BI) {
ch->ch_err_break++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "%s:%d Port: %d. BRK INTR!\n",
+ __FILE__, __LINE__, port);
}
if (linestatus & UART_LSR_OE) {
@@ -904,8 +910,9 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
* Probably we should eventually have an orun stat in our driver...
*/
ch->ch_err_overrun++;
- jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
- "%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port);
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "%s:%d Port: %d. Rx Overrun!\n",
+ __FILE__, __LINE__, port);
}
if (linestatus & UART_LSR_THRE) {
@@ -1128,11 +1135,11 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
*/
uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
- jsm_printk(INTR, INFO, &brd->pci_dev,
- "%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll);
+ jsm_dbg(INTR, &brd->pci_dev, "%s:%d uart_poll: %x\n",
+ __FILE__, __LINE__, uart_poll);
if (!uart_poll) {
- jsm_printk(INTR, INFO, &brd->pci_dev,
+ jsm_dbg(INTR, &brd->pci_dev,
"Kernel interrupted to me, but no pending interrupts...\n");
spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
return IRQ_NONE;
@@ -1158,15 +1165,15 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
continue;
}
- jsm_printk(INTR, INFO, &brd->pci_dev,
- "%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type);
+ jsm_dbg(INTR, &brd->pci_dev, "%s:%d port: %x type: %x\n",
+ __FILE__, __LINE__, port, type);
/* Remove this port + type from uart_poll */
uart_poll &= ~(jsm_offset_table[port]);
if (!type) {
/* If no type, just ignore it, and move onto next port */
- jsm_printk(INTR, ERR, &brd->pci_dev,
+ jsm_dbg(INTR, &brd->pci_dev,
"Interrupt with no type! port: %d\n", port);
continue;
}
@@ -1231,15 +1238,16 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
* these once and awhile.
* Its harmless, just ignore it and move on.
*/
- jsm_printk(INTR, ERR, &brd->pci_dev,
- "%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type);
+ jsm_dbg(INTR, &brd->pci_dev,
+ "%s:%d Unknown Interrupt type: %x\n",
+ __FILE__, __LINE__, type);
continue;
}
}
spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
- jsm_printk(INTR, INFO, &brd->pci_dev, "finish.\n");
+ jsm_dbg(INTR, &brd->pci_dev, "finish\n");
return IRQ_HANDLED;
}
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
index 71397961773c..4c00c5550b1a 100644
--- a/drivers/tty/serial/jsm/jsm_tty.c
+++ b/drivers/tty/serial/jsm/jsm_tty.c
@@ -43,7 +43,7 @@ static inline int jsm_get_mstat(struct jsm_channel *ch)
unsigned char mstat;
unsigned result;
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "start\n");
+ jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "start\n");
mstat = (ch->ch_mostat | ch->ch_mistat);
@@ -62,7 +62,7 @@ static inline int jsm_get_mstat(struct jsm_channel *ch)
if (mstat & UART_MSR_DCD)
result |= TIOCM_CD;
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n");
return result;
}
@@ -79,14 +79,14 @@ static unsigned int jsm_tty_get_mctrl(struct uart_port *port)
int result;
struct jsm_channel *channel = (struct jsm_channel *)port;
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
result = jsm_get_mstat(channel);
if (result < 0)
return -ENXIO;
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
return result;
}
@@ -100,7 +100,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct jsm_channel *channel = (struct jsm_channel *)port;
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
if (mctrl & TIOCM_RTS)
channel->ch_mostat |= UART_MCR_RTS;
@@ -114,7 +114,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
channel->ch_bd->bd_ops->assert_modem_signals(channel);
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
udelay(10);
}
@@ -135,23 +135,23 @@ static void jsm_tty_start_tx(struct uart_port *port)
{
struct jsm_channel *channel = (struct jsm_channel *)port;
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
channel->ch_flags &= ~(CH_STOP);
jsm_tty_write(port);
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
}
static void jsm_tty_stop_tx(struct uart_port *port)
{
struct jsm_channel *channel = (struct jsm_channel *)port;
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "start\n");
channel->ch_flags |= (CH_STOP);
- jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(IOCTL, &channel->ch_bd->pci_dev, "finish\n");
}
static void jsm_tty_send_xchar(struct uart_port *port, char ch)
@@ -216,16 +216,16 @@ static int jsm_tty_open(struct uart_port *port)
if (!channel->ch_rqueue) {
channel->ch_rqueue = kzalloc(RQUEUESIZE, GFP_KERNEL);
if (!channel->ch_rqueue) {
- jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
- "unable to allocate read queue buf");
+ jsm_dbg(INIT, &channel->ch_bd->pci_dev,
+ "unable to allocate read queue buf\n");
return -ENOMEM;
}
}
if (!channel->ch_equeue) {
channel->ch_equeue = kzalloc(EQUEUESIZE, GFP_KERNEL);
if (!channel->ch_equeue) {
- jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
- "unable to allocate error queue buf");
+ jsm_dbg(INIT, &channel->ch_bd->pci_dev,
+ "unable to allocate error queue buf\n");
return -ENOMEM;
}
}
@@ -234,7 +234,7 @@ static int jsm_tty_open(struct uart_port *port)
/*
* Initialize if neither terminal is open.
*/
- jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev,
+ jsm_dbg(OPEN, &channel->ch_bd->pci_dev,
"jsm_open: initializing channel in open...\n");
/*
@@ -270,7 +270,7 @@ static int jsm_tty_open(struct uart_port *port)
channel->ch_open_count++;
- jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n");
return 0;
}
@@ -280,7 +280,7 @@ static void jsm_tty_close(struct uart_port *port)
struct ktermios *ts;
struct jsm_channel *channel = (struct jsm_channel *)port;
- jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
+ jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "start\n");
bd = channel->ch_bd;
ts = &port->state->port.tty->termios;
@@ -293,7 +293,7 @@ static void jsm_tty_close(struct uart_port *port)
* If we have HUPCL set, lower DTR and RTS
*/
if (channel->ch_c_cflag & HUPCL) {
- jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev,
+ jsm_dbg(CLOSE, &channel->ch_bd->pci_dev,
"Close. HUPCL set, dropping DTR/RTS\n");
/* Drop RTS/DTR */
@@ -304,7 +304,7 @@ static void jsm_tty_close(struct uart_port *port)
/* Turn off UART interrupts for this port */
channel->ch_bd->bd_ops->uart_off(channel);
- jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(CLOSE, &channel->ch_bd->pci_dev, "finish\n");
}
static void jsm_tty_set_termios(struct uart_port *port,
@@ -371,7 +371,7 @@ static struct uart_ops jsm_ops = {
* Init the tty subsystem. Called once per board after board has been
* downloaded and init'ed.
*/
-int __devinit jsm_tty_init(struct jsm_board *brd)
+int jsm_tty_init(struct jsm_board *brd)
{
int i;
void __iomem *vaddr;
@@ -380,7 +380,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
if (!brd)
return -ENXIO;
- jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+ jsm_dbg(INIT, &brd->pci_dev, "start\n");
/*
* Initialize board structure elements.
@@ -401,9 +401,9 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
*/
brd->channels[i] = kzalloc(sizeof(struct jsm_channel), GFP_KERNEL);
if (!brd->channels[i]) {
- jsm_printk(CORE, ERR, &brd->pci_dev,
+ jsm_dbg(CORE, &brd->pci_dev,
"%s:%d Unable to allocate memory for channel struct\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
}
}
}
@@ -431,7 +431,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd)
init_waitqueue_head(&ch->ch_flags_wait);
}
- jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+ jsm_dbg(INIT, &brd->pci_dev, "finish\n");
return 0;
}
@@ -444,7 +444,7 @@ int jsm_uart_port_init(struct jsm_board *brd)
if (!brd)
return -ENXIO;
- jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+ jsm_dbg(INIT, &brd->pci_dev, "start\n");
/*
* Initialize board structure elements.
@@ -481,7 +481,7 @@ int jsm_uart_port_init(struct jsm_board *brd)
printk(KERN_INFO "jsm: Port %d added\n", i);
}
- jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+ jsm_dbg(INIT, &brd->pci_dev, "finish\n");
return 0;
}
@@ -493,7 +493,7 @@ int jsm_remove_uart_port(struct jsm_board *brd)
if (!brd)
return -ENXIO;
- jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+ jsm_dbg(INIT, &brd->pci_dev, "start\n");
/*
* Initialize board structure elements.
@@ -513,7 +513,7 @@ int jsm_remove_uart_port(struct jsm_board *brd)
uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port);
}
- jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+ jsm_dbg(INIT, &brd->pci_dev, "finish\n");
return 0;
}
@@ -531,7 +531,7 @@ void jsm_input(struct jsm_channel *ch)
int s = 0;
int i = 0;
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+ jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n");
if (!ch)
return;
@@ -560,7 +560,7 @@ void jsm_input(struct jsm_channel *ch)
return;
}
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+ jsm_dbg(READ, &ch->ch_bd->pci_dev, "start\n");
/*
*If the device is not open, or CREAD is off, flush
@@ -569,8 +569,9 @@ void jsm_input(struct jsm_channel *ch)
if (!tp ||
!(tp->termios.c_cflag & CREAD) ) {
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
+ jsm_dbg(READ, &ch->ch_bd->pci_dev,
+ "input. dropping %d bytes on port %d...\n",
+ data_len, ch->ch_portnum);
ch->ch_r_head = tail;
/* Force queue flow control to be released, if needed */
@@ -585,17 +586,17 @@ void jsm_input(struct jsm_channel *ch)
*/
if (ch->ch_flags & CH_STOPI) {
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ jsm_dbg(READ, &ch->ch_bd->pci_dev,
"Port %d throttled, not reading any data. head: %x tail: %x\n",
ch->ch_portnum, head, tail);
return;
}
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");
+ jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n");
if (data_len <= 0) {
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
+ jsm_dbg(READ, &ch->ch_bd->pci_dev, "jsm_input 1\n");
return;
}
@@ -653,7 +654,7 @@ void jsm_input(struct jsm_channel *ch)
/* Tell the tty layer its okay to "eat" the data now */
tty_flip_buffer_push(tp);
- jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+ jsm_dbg(IOCTL, &ch->ch_bd->pci_dev, "finish\n");
}
static void jsm_carrier(struct jsm_channel *ch)
@@ -663,7 +664,7 @@ static void jsm_carrier(struct jsm_channel *ch)
int virt_carrier = 0;
int phys_carrier = 0;
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev, "start\n");
+ jsm_dbg(CARR, &ch->ch_bd->pci_dev, "start\n");
if (!ch)
return;
@@ -673,16 +674,16 @@ static void jsm_carrier(struct jsm_channel *ch)
return;
if (ch->ch_mistat & UART_MSR_DCD) {
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
- "mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
+ jsm_dbg(CARR, &ch->ch_bd->pci_dev, "mistat: %x D_CD: %x\n",
+ ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
phys_carrier = 1;
}
if (ch->ch_c_cflag & CLOCAL)
virt_carrier = 1;
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
- "DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier);
+ jsm_dbg(CARR, &ch->ch_bd->pci_dev, "DCD: physical: %d virt: %d\n",
+ phys_carrier, virt_carrier);
/*
* Test for a VIRTUAL carrier transition to HIGH.
@@ -694,8 +695,7 @@ static void jsm_carrier(struct jsm_channel *ch)
* for carrier in the open routine.
*/
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
- "carrier: virt DCD rose\n");
+ jsm_dbg(CARR, &ch->ch_bd->pci_dev, "carrier: virt DCD rose\n");
if (waitqueue_active(&(ch->ch_flags_wait)))
wake_up_interruptible(&ch->ch_flags_wait);
@@ -711,7 +711,7 @@ static void jsm_carrier(struct jsm_channel *ch)
* for carrier in the open routine.
*/
- jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+ jsm_dbg(CARR, &ch->ch_bd->pci_dev,
"carrier: physical DCD rose\n");
if (waitqueue_active(&(ch->ch_flags_wait)))
@@ -790,8 +790,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
bd_ops->disable_receiver(ch);
ch->ch_flags |= (CH_RECEIVER_OFF);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
+ jsm_dbg(READ, &ch->ch_bd->pci_dev,
+ "Internal queue hit hilevel mark (%d)! Turning off interrupts\n",
qleft);
}
}
@@ -800,8 +800,9 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
bd_ops->send_stop_character(ch);
ch->ch_stops_sent++;
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
+ jsm_dbg(READ, &ch->ch_bd->pci_dev,
+ "Sending stop char! Times sent: %x\n",
+ ch->ch_stops_sent);
}
}
}
@@ -827,8 +828,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
if (ch->ch_flags & CH_RECEIVER_OFF) {
bd_ops->enable_receiver(ch);
ch->ch_flags &= ~(CH_RECEIVER_OFF);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
- "Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
+ jsm_dbg(READ, &ch->ch_bd->pci_dev,
+ "Internal queue hit lowlevel mark (%d)! Turning on interrupts\n",
qleft);
}
}
@@ -836,7 +837,8 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch)
else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
ch->ch_stops_sent = 0;
bd_ops->send_start_character(ch);
- jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
+ jsm_dbg(READ, &ch->ch_bd->pci_dev,
+ "Sending start char!\n");
}
}
}
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index d185247ba1aa..6ac2b797a764 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -266,6 +266,7 @@ static int kgdb_nmi_tty_install(struct tty_driver *drv, struct tty_struct *tty)
}
return 0;
err:
+ tty_port_destroy(&priv->port);
kfree(priv);
return ret;
}
@@ -275,6 +276,7 @@ static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
tty->driver_data = NULL;
+ tty_port_destroy(&priv->port);
kfree(priv);
}
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index ba3af3bf6d43..0e86bff3fe2a 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -686,7 +686,7 @@ static struct uart_ops serial_lpc32xx_pops = {
/*
* Register a set of serial devices attached to a platform device
*/
-static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
+static int serial_hs_lpc32xx_probe(struct platform_device *pdev)
{
struct lpc32xx_hsuart_port *p = &lpc32xx_hs_ports[uarts_registered];
int ret = 0;
@@ -740,7 +740,7 @@ static int __devinit serial_hs_lpc32xx_probe(struct platform_device *pdev)
/*
* Remove serial ports registered against a platform device.
*/
-static int __devexit serial_hs_lpc32xx_remove(struct platform_device *pdev)
+static int serial_hs_lpc32xx_remove(struct platform_device *pdev)
{
struct lpc32xx_hsuart_port *p = platform_get_drvdata(pdev);
@@ -783,7 +783,7 @@ MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
static struct platform_driver serial_hs_lpc32xx_driver = {
.probe = serial_hs_lpc32xx_probe,
- .remove = __devexit_p(serial_hs_lpc32xx_remove),
+ .remove = serial_hs_lpc32xx_remove,
.suspend = serial_hs_lpc32xx_suspend,
.resume = serial_hs_lpc32xx_resume,
.driver = {
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index 0f24486be532..7ce3197087bb 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -742,7 +742,7 @@ static struct uart_driver max3100_uart_driver = {
};
static int uart_driver_registered;
-static int __devinit max3100_probe(struct spi_device *spi)
+static int max3100_probe(struct spi_device *spi)
{
int i, retval;
struct plat_max3100 *pdata;
@@ -818,7 +818,7 @@ static int __devinit max3100_probe(struct spi_device *spi)
return 0;
}
-static int __devexit max3100_remove(struct spi_device *spi)
+static int max3100_remove(struct spi_device *spi)
{
struct max3100_port *s = dev_get_drvdata(&spi->dev);
int i;
@@ -907,7 +907,7 @@ static struct spi_driver max3100_driver = {
},
.probe = max3100_probe,
- .remove = __devexit_p(max3100_remove),
+ .remove = max3100_remove,
.suspend = max3100_suspend,
.resume = max3100_resume,
};
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 2bc28a59d385..a801f6872cad 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -378,7 +378,7 @@ static void max310x_wait_pll(struct max310x_port *s)
}
}
-static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
+static int max310x_update_best_err(unsigned long f, long *besterr)
{
/* Use baudrate 115200 for calculate error */
long err = f % (115200 * 16);
@@ -391,7 +391,7 @@ static int __devinit max310x_update_best_err(unsigned long f, long *besterr)
return 1;
}
-static int __devinit max310x_set_ref_clk(struct max310x_port *s)
+static int max310x_set_ref_clk(struct max310x_port *s)
{
unsigned int div, clksrc, pllcfg = 0;
long besterr = -1;
@@ -995,7 +995,7 @@ static struct max310x_pdata generic_plat_data = {
.frequency = 26000000,
};
-static int __devinit max310x_probe(struct spi_device *spi)
+static int max310x_probe(struct spi_device *spi)
{
struct max310x_port *s;
struct device *dev = &spi->dev;
@@ -1178,6 +1178,7 @@ static int __devinit max310x_probe(struct spi_device *spi)
s->gpio.set = max310x_gpio_set;
s->gpio.base = pdata->gpio_base;
s->gpio.ngpio = s->nr_gpio;
+ s->gpio.can_sleep = 1;
if (gpiochip_add(&s->gpio)) {
/* Indicate that we should not call gpiochip_remove */
s->gpio.base = 0;
@@ -1202,7 +1203,7 @@ err_out:
return ret;
}
-static int __devexit max310x_remove(struct spi_device *spi)
+static int max310x_remove(struct spi_device *spi)
{
struct device *dev = &spi->dev;
struct max310x_port *s = dev_get_drvdata(dev);
@@ -1239,6 +1240,7 @@ static int __devexit max310x_remove(struct spi_device *spi)
static const struct spi_device_id max310x_id_table[] = {
{ "max3107", MAX310X_TYPE_MAX3107 },
{ "max3108", MAX310X_TYPE_MAX3108 },
+ { }
};
MODULE_DEVICE_TABLE(spi, max310x_id_table);
@@ -1248,7 +1250,7 @@ static struct spi_driver max310x_driver = {
.owner = THIS_MODULE,
},
.probe = max310x_probe,
- .remove = __devexit_p(max310x_remove),
+ .remove = max310x_remove,
.suspend = max310x_suspend,
.resume = max310x_resume,
.id_table = max310x_id_table,
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index 9afca093d6ec..fcd56ab6053f 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -571,7 +571,7 @@ static struct uart_driver mcf_driver = {
/****************************************************************************/
-static int __devinit mcf_probe(struct platform_device *pdev)
+static int mcf_probe(struct platform_device *pdev)
{
struct mcf_platform_uart *platp = pdev->dev.platform_data;
struct uart_port *port;
@@ -599,7 +599,7 @@ static int __devinit mcf_probe(struct platform_device *pdev)
/****************************************************************************/
-static int __devexit mcf_remove(struct platform_device *pdev)
+static int mcf_remove(struct platform_device *pdev)
{
struct uart_port *port;
int i;
@@ -617,7 +617,7 @@ static int __devexit mcf_remove(struct platform_device *pdev)
static struct platform_driver mcf_platform_driver = {
.probe = mcf_probe,
- .remove = __devexit_p(mcf_remove),
+ .remove = mcf_remove,
.driver = {
.name = "mcfuart",
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index c4b50af46c44..2c01344dc332 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -36,6 +36,7 @@
#include <linux/serial_mfd.h>
#include <linux/dma-mapping.h>
#include <linux/pci.h>
+#include <linux/nmi.h>
#include <linux/io.h>
#include <linux/debugfs.h>
#include <linux/pm_runtime.h>
@@ -1113,6 +1114,8 @@ serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
unsigned int ier;
int locked = 1;
+ touch_nmi_watchdog();
+
local_irq_save(flags);
if (up->port.sysrq)
locked = 0;
@@ -1456,7 +1459,7 @@ static void serial_hsu_remove(struct pci_dev *pdev)
}
/* First 3 are UART ports, and the 4th is the DMA */
-static const struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
@@ -1468,7 +1471,7 @@ static struct pci_driver hsu_pci_driver = {
.name = "HSU serial",
.id_table = pci_ids,
.probe = serial_hsu_probe,
- .remove = __devexit_p(serial_hsu_remove),
+ .remove = serial_hsu_remove,
.suspend = serial_hsu_suspend,
.resume = serial_hsu_resume,
.driver = {
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 8cf577008ad7..7c23c4f4c58d 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1308,7 +1308,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
{},
};
-static int __devinit mpc52xx_uart_of_probe(struct platform_device *op)
+static int mpc52xx_uart_of_probe(struct platform_device *op)
{
int idx = -1;
unsigned int uartclk;
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
index df2a2240a3ae..58734d7e746d 100644
--- a/drivers/tty/serial/mrst_max3110.c
+++ b/drivers/tty/serial/mrst_max3110.c
@@ -773,7 +773,7 @@ static int serial_m3110_resume(struct spi_device *spi)
#define serial_m3110_resume NULL
#endif
-static int __devinit serial_m3110_probe(struct spi_device *spi)
+static int serial_m3110_probe(struct spi_device *spi)
{
struct uart_max3110 *max;
void *buffer;
@@ -855,7 +855,7 @@ err_get_page:
return ret;
}
-static int __devexit serial_m3110_remove(struct spi_device *dev)
+static int serial_m3110_remove(struct spi_device *dev)
{
struct uart_max3110 *max = spi_get_drvdata(dev);
@@ -879,7 +879,7 @@ static struct spi_driver uart_max3110_driver = {
.owner = THIS_MODULE,
},
.probe = serial_m3110_probe,
- .remove = __devexit_p(serial_m3110_remove),
+ .remove = serial_m3110_remove,
.suspend = serial_m3110_suspend,
.resume = serial_m3110_resume,
};
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 033e0bc9ebab..95fd39be2934 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -917,7 +917,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
return uart_add_one_port(&msm_uart_driver, port);
}
-static int __devexit msm_serial_remove(struct platform_device *pdev)
+static int msm_serial_remove(struct platform_device *pdev)
{
struct msm_port *msm_port = platform_get_drvdata(pdev);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index fca13dc73e23..1fa92284ade0 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -401,7 +401,7 @@ static int msm_hs_request_port(struct uart_port *port)
return 0;
}
-static int __devexit msm_hs_remove(struct platform_device *pdev)
+static int msm_hs_remove(struct platform_device *pdev)
{
struct msm_hs_port *msm_uport;
@@ -1521,7 +1521,7 @@ err_msm_hs_init_clk:
}
/* Initialize tx and rx data structures */
-static int __devinit uartdm_init_port(struct uart_port *uport)
+static int uartdm_init_port(struct uart_port *uport)
{
int ret = 0;
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
@@ -1614,7 +1614,7 @@ err_tx_command_ptr_ptr:
return ret;
}
-static int __devinit msm_hs_probe(struct platform_device *pdev)
+static int msm_hs_probe(struct platform_device *pdev)
{
int ret;
struct uart_port *uport;
@@ -1838,7 +1838,7 @@ static const struct dev_pm_ops msm_hs_dev_pm_ops = {
static struct platform_driver msm_serial_hs_platform_driver = {
.probe = msm_hs_probe,
- .remove = __devexit_p(msm_hs_remove),
+ .remove = msm_hs_remove,
.driver = {
.name = "msm_serial_hs",
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c
index 7ea8a263fd9e..e2775b6df5a5 100644
--- a/drivers/tty/serial/mux.c
+++ b/drivers/tty/serial/mux.c
@@ -520,7 +520,7 @@ static int __init mux_probe(struct parisc_device *dev)
return 0;
}
-static int __devexit mux_remove(struct parisc_device *dev)
+static int mux_remove(struct parisc_device *dev)
{
int i, j;
int port_count = (long)dev_get_drvdata(&dev->dev);
@@ -571,14 +571,14 @@ static struct parisc_driver builtin_serial_mux_driver = {
.name = "builtin_serial_mux",
.id_table = builtin_mux_tbl,
.probe = mux_probe,
- .remove = __devexit_p(mux_remove),
+ .remove = mux_remove,
};
static struct parisc_driver serial_mux_driver = {
.name = "serial_mux",
.id_table = mux_tbl,
.probe = mux_probe,
- .remove = __devexit_p(mux_remove),
+ .remove = mux_remove,
};
/**
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 6db3baa39a97..6db23b035efe 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -34,6 +34,8 @@
#include <linux/io.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl/mxs-dma.h>
#include <asm/cacheflush.h>
@@ -71,6 +73,15 @@
#define AUART_CTRL0_SFTRST (1 << 31)
#define AUART_CTRL0_CLKGATE (1 << 30)
+#define AUART_CTRL0_RXTO_ENABLE (1 << 27)
+#define AUART_CTRL0_RXTIMEOUT(v) (((v) & 0x7ff) << 16)
+#define AUART_CTRL0_XFER_COUNT(v) ((v) & 0xffff)
+
+#define AUART_CTRL1_XFER_COUNT(v) ((v) & 0xffff)
+
+#define AUART_CTRL2_DMAONERR (1 << 26)
+#define AUART_CTRL2_TXDMAE (1 << 25)
+#define AUART_CTRL2_RXDMAE (1 << 24)
#define AUART_CTRL2_CTSEN (1 << 15)
#define AUART_CTRL2_RTSEN (1 << 14)
@@ -111,29 +122,170 @@
#define AUART_STAT_BERR (1 << 18)
#define AUART_STAT_PERR (1 << 17)
#define AUART_STAT_FERR (1 << 16)
+#define AUART_STAT_RXCOUNT_MASK 0xffff
static struct uart_driver auart_driver;
+enum mxs_auart_type {
+ IMX23_AUART,
+ IMX28_AUART,
+};
+
struct mxs_auart_port {
struct uart_port port;
- unsigned int flags;
+#define MXS_AUART_DMA_CONFIG 0x1
+#define MXS_AUART_DMA_ENABLED 0x2
+#define MXS_AUART_DMA_TX_SYNC 2 /* bit 2 */
+#define MXS_AUART_DMA_RX_READY 3 /* bit 3 */
+ unsigned long flags;
unsigned int ctrl;
+ enum mxs_auart_type devtype;
unsigned int irq;
struct clk *clk;
struct device *dev;
+
+ /* for DMA */
+ struct mxs_dma_data dma_data;
+ int dma_channel_rx, dma_channel_tx;
+ int dma_irq_rx, dma_irq_tx;
+ int dma_channel;
+
+ struct scatterlist tx_sgl;
+ struct dma_chan *tx_dma_chan;
+ void *tx_dma_buf;
+
+ struct scatterlist rx_sgl;
+ struct dma_chan *rx_dma_chan;
+ void *rx_dma_buf;
+};
+
+static struct platform_device_id mxs_auart_devtype[] = {
+ { .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
+ { .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
+
+static struct of_device_id mxs_auart_dt_ids[] = {
+ {
+ .compatible = "fsl,imx28-auart",
+ .data = &mxs_auart_devtype[IMX28_AUART]
+ }, {
+ .compatible = "fsl,imx23-auart",
+ .data = &mxs_auart_devtype[IMX23_AUART]
+ }, { /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
+
+static inline int is_imx28_auart(struct mxs_auart_port *s)
+{
+ return s->devtype == IMX28_AUART;
+}
+
+static inline bool auart_dma_enabled(struct mxs_auart_port *s)
+{
+ return s->flags & MXS_AUART_DMA_ENABLED;
+}
static void mxs_auart_stop_tx(struct uart_port *u);
#define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
-static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
+static void mxs_auart_tx_chars(struct mxs_auart_port *s);
+
+static void dma_tx_callback(void *param)
{
+ struct mxs_auart_port *s = param;
struct circ_buf *xmit = &s->port.state->xmit;
+ dma_unmap_sg(s->dev, &s->tx_sgl, 1, DMA_TO_DEVICE);
+
+ /* clear the bit used to serialize the DMA tx. */
+ clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
+ smp_mb__after_clear_bit();
+
+ /* wake up the possible processes. */
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&s->port);
+
+ mxs_auart_tx_chars(s);
+}
+
+static int mxs_auart_dma_tx(struct mxs_auart_port *s, int size)
+{
+ struct dma_async_tx_descriptor *desc;
+ struct scatterlist *sgl = &s->tx_sgl;
+ struct dma_chan *channel = s->tx_dma_chan;
+ u32 pio;
+
+ /* [1] : send PIO. Note, the first pio word is CTRL1. */
+ pio = AUART_CTRL1_XFER_COUNT(size);
+ desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)&pio,
+ 1, DMA_TRANS_NONE, 0);
+ if (!desc) {
+ dev_err(s->dev, "step 1 error\n");
+ return -EINVAL;
+ }
+
+ /* [2] : set DMA buffer. */
+ sg_init_one(sgl, s->tx_dma_buf, size);
+ dma_map_sg(s->dev, sgl, 1, DMA_TO_DEVICE);
+ desc = dmaengine_prep_slave_sg(channel, sgl,
+ 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(s->dev, "step 2 error\n");
+ return -EINVAL;
+ }
+
+ /* [3] : submit the DMA */
+ desc->callback = dma_tx_callback;
+ desc->callback_param = s;
+ dmaengine_submit(desc);
+ dma_async_issue_pending(channel);
+ return 0;
+}
+
+static void mxs_auart_tx_chars(struct mxs_auart_port *s)
+{
+ struct circ_buf *xmit = &s->port.state->xmit;
+
+ if (auart_dma_enabled(s)) {
+ int i = 0;
+ int size;
+ void *buffer = s->tx_dma_buf;
+
+ if (test_and_set_bit(MXS_AUART_DMA_TX_SYNC, &s->flags))
+ return;
+
+ while (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
+ size = min_t(u32, UART_XMIT_SIZE - i,
+ CIRC_CNT_TO_END(xmit->head,
+ xmit->tail,
+ UART_XMIT_SIZE));
+ memcpy(buffer + i, xmit->buf + xmit->tail, size);
+ xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);
+
+ i += size;
+ if (i >= UART_XMIT_SIZE)
+ break;
+ }
+
+ if (uart_tx_stopped(&s->port))
+ mxs_auart_stop_tx(&s->port);
+
+ if (i) {
+ mxs_auart_dma_tx(s, i);
+ } else {
+ clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
+ smp_mb__after_clear_bit();
+ }
+ return;
+ }
+
+
while (!(readl(s->port.membase + AUART_STAT) &
AUART_STAT_TXFF)) {
if (s->port.x_char) {
@@ -287,10 +439,159 @@ static u32 mxs_auart_get_mctrl(struct uart_port *u)
return mctrl;
}
+static bool mxs_auart_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct mxs_auart_port *s = param;
+
+ if (!mxs_dma_is_apbx(chan))
+ return false;
+
+ if (s->dma_channel == chan->chan_id) {
+ chan->private = &s->dma_data;
+ return true;
+ }
+ return false;
+}
+
+static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s);
+static void dma_rx_callback(void *arg)
+{
+ struct mxs_auart_port *s = (struct mxs_auart_port *) arg;
+ struct tty_struct *tty = s->port.state->port.tty;
+ int count;
+ u32 stat;
+
+ dma_unmap_sg(s->dev, &s->rx_sgl, 1, DMA_FROM_DEVICE);
+
+ stat = readl(s->port.membase + AUART_STAT);
+ stat &= ~(AUART_STAT_OERR | AUART_STAT_BERR |
+ AUART_STAT_PERR | AUART_STAT_FERR);
+
+ count = stat & AUART_STAT_RXCOUNT_MASK;
+ tty_insert_flip_string(tty, s->rx_dma_buf, count);
+
+ writel(stat, s->port.membase + AUART_STAT);
+ tty_flip_buffer_push(tty);
+
+ /* start the next DMA for RX. */
+ mxs_auart_dma_prep_rx(s);
+}
+
+static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s)
+{
+ struct dma_async_tx_descriptor *desc;
+ struct scatterlist *sgl = &s->rx_sgl;
+ struct dma_chan *channel = s->rx_dma_chan;
+ u32 pio[1];
+
+ /* [1] : send PIO */
+ pio[0] = AUART_CTRL0_RXTO_ENABLE
+ | AUART_CTRL0_RXTIMEOUT(0x80)
+ | AUART_CTRL0_XFER_COUNT(UART_XMIT_SIZE);
+ desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
+ 1, DMA_TRANS_NONE, 0);
+ if (!desc) {
+ dev_err(s->dev, "step 1 error\n");
+ return -EINVAL;
+ }
+
+ /* [2] : send DMA request */
+ sg_init_one(sgl, s->rx_dma_buf, UART_XMIT_SIZE);
+ dma_map_sg(s->dev, sgl, 1, DMA_FROM_DEVICE);
+ desc = dmaengine_prep_slave_sg(channel, sgl, 1, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(s->dev, "step 2 error\n");
+ return -1;
+ }
+
+ /* [3] : submit the DMA, but do not issue it. */
+ desc->callback = dma_rx_callback;
+ desc->callback_param = s;
+ dmaengine_submit(desc);
+ dma_async_issue_pending(channel);
+ return 0;
+}
+
+static void mxs_auart_dma_exit_channel(struct mxs_auart_port *s)
+{
+ if (s->tx_dma_chan) {
+ dma_release_channel(s->tx_dma_chan);
+ s->tx_dma_chan = NULL;
+ }
+ if (s->rx_dma_chan) {
+ dma_release_channel(s->rx_dma_chan);
+ s->rx_dma_chan = NULL;
+ }
+
+ kfree(s->tx_dma_buf);
+ kfree(s->rx_dma_buf);
+ s->tx_dma_buf = NULL;
+ s->rx_dma_buf = NULL;
+}
+
+static void mxs_auart_dma_exit(struct mxs_auart_port *s)
+{
+
+ writel(AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE | AUART_CTRL2_DMAONERR,
+ s->port.membase + AUART_CTRL2_CLR);
+
+ mxs_auart_dma_exit_channel(s);
+ s->flags &= ~MXS_AUART_DMA_ENABLED;
+ clear_bit(MXS_AUART_DMA_TX_SYNC, &s->flags);
+ clear_bit(MXS_AUART_DMA_RX_READY, &s->flags);
+}
+
+static int mxs_auart_dma_init(struct mxs_auart_port *s)
+{
+ dma_cap_mask_t mask;
+
+ if (auart_dma_enabled(s))
+ return 0;
+
+ /* We do not get the right DMA channels. */
+ if (s->dma_channel_rx == -1 || s->dma_channel_rx == -1)
+ return -EINVAL;
+
+ /* init for RX */
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ s->dma_channel = s->dma_channel_rx;
+ s->dma_data.chan_irq = s->dma_irq_rx;
+ s->rx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
+ if (!s->rx_dma_chan)
+ goto err_out;
+ s->rx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
+ if (!s->rx_dma_buf)
+ goto err_out;
+
+ /* init for TX */
+ s->dma_channel = s->dma_channel_tx;
+ s->dma_data.chan_irq = s->dma_irq_tx;
+ s->tx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
+ if (!s->tx_dma_chan)
+ goto err_out;
+ s->tx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
+ if (!s->tx_dma_buf)
+ goto err_out;
+
+ /* set the flags */
+ s->flags |= MXS_AUART_DMA_ENABLED;
+ dev_dbg(s->dev, "enabled the DMA support.");
+
+ return 0;
+
+err_out:
+ mxs_auart_dma_exit_channel(s);
+ return -EINVAL;
+
+}
+
static void mxs_auart_settermios(struct uart_port *u,
struct ktermios *termios,
struct ktermios *old)
{
+ struct mxs_auart_port *s = to_auart_port(u);
u32 bm, ctrl, ctrl2, div;
unsigned int cflag, baud;
@@ -362,10 +663,23 @@ static void mxs_auart_settermios(struct uart_port *u,
ctrl |= AUART_LINECTRL_STP2;
/* figure out the hardware flow control settings */
- if (cflag & CRTSCTS)
+ if (cflag & CRTSCTS) {
+ /*
+ * The DMA has a bug(see errata:2836) in mx23.
+ * So we can not implement the DMA for auart in mx23,
+ * we can only implement the DMA support for auart
+ * in mx28.
+ */
+ if (is_imx28_auart(s) && (s->flags & MXS_AUART_DMA_CONFIG)) {
+ if (!mxs_auart_dma_init(s))
+ /* enable DMA tranfer */
+ ctrl2 |= AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE
+ | AUART_CTRL2_DMAONERR;
+ }
ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN;
- else
+ } else {
ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN);
+ }
/* set baud rate */
baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
@@ -377,6 +691,19 @@ static void mxs_auart_settermios(struct uart_port *u,
writel(ctrl2, u->membase + AUART_CTRL2);
uart_update_timeout(u, termios->c_cflag, baud);
+
+ /* prepare for the DMA RX. */
+ if (auart_dma_enabled(s) &&
+ !test_and_set_bit(MXS_AUART_DMA_RX_READY, &s->flags)) {
+ if (!mxs_auart_dma_prep_rx(s)) {
+ /* Disable the normal RX interrupt. */
+ writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN,
+ u->membase + AUART_INTR_CLR);
+ } else {
+ mxs_auart_dma_exit(s);
+ dev_err(s->dev, "We can not start up the DMA.\n");
+ }
+ }
}
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
@@ -395,7 +722,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
}
if (istat & (AUART_INTR_RTIS | AUART_INTR_RXIS)) {
- mxs_auart_rx_chars(s);
+ if (!auart_dma_enabled(s))
+ mxs_auart_rx_chars(s);
istat &= ~(AUART_INTR_RTIS | AUART_INTR_RXIS);
}
@@ -455,6 +783,9 @@ static void mxs_auart_shutdown(struct uart_port *u)
{
struct mxs_auart_port *s = to_auart_port(u);
+ if (auart_dma_enabled(s))
+ mxs_auart_dma_exit(s);
+
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
@@ -688,6 +1019,7 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ u32 dma_channel[2];
int ret;
if (!np)
@@ -701,11 +1033,27 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
}
s->port.line = ret;
+ s->dma_irq_rx = platform_get_irq(pdev, 1);
+ s->dma_irq_tx = platform_get_irq(pdev, 2);
+
+ ret = of_property_read_u32_array(np, "fsl,auart-dma-channel",
+ dma_channel, 2);
+ if (ret == 0) {
+ s->dma_channel_rx = dma_channel[0];
+ s->dma_channel_tx = dma_channel[1];
+
+ s->flags |= MXS_AUART_DMA_CONFIG;
+ } else {
+ s->dma_channel_rx = -1;
+ s->dma_channel_tx = -1;
+ }
return 0;
}
-static int __devinit mxs_auart_probe(struct platform_device *pdev)
+static int mxs_auart_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id =
+ of_match_device(mxs_auart_dt_ids, &pdev->dev);
struct mxs_auart_port *s;
u32 version;
int ret = 0;
@@ -730,6 +1078,11 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
goto out_free;
}
+ if (of_id) {
+ pdev->id_entry = of_id->data;
+ s->devtype = pdev->id_entry->driver_data;
+ }
+
s->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(s->clk)) {
ret = PTR_ERR(s->clk);
@@ -751,7 +1104,6 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
s->port.type = PORT_IMX;
s->port.dev = s->dev = get_device(&pdev->dev);
- s->flags = 0;
s->ctrl = 0;
s->irq = platform_get_irq(pdev, 0);
@@ -789,7 +1141,7 @@ out:
return ret;
}
-static int __devexit mxs_auart_remove(struct platform_device *pdev)
+static int mxs_auart_remove(struct platform_device *pdev)
{
struct mxs_auart_port *s = platform_get_drvdata(pdev);
@@ -805,15 +1157,9 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id mxs_auart_dt_ids[] = {
- { .compatible = "fsl,imx23-auart", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
-
static struct platform_driver mxs_auart_driver = {
.probe = mxs_auart_probe,
- .remove = __devexit_p(mxs_auart_remove),
+ .remove = mxs_auart_remove,
.driver = {
.name = "mxs-auart",
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index df443b908ca3..e7cae1c2d7d2 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -21,8 +21,10 @@
#include <linux/of_serial.h>
#include <linux/of_platform.h>
#include <linux/nwpserial.h>
+#include <linux/clk.h>
struct of_serial_info {
+ struct clk *clk;
int type;
int line;
};
@@ -50,8 +52,9 @@ EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
/*
* Fill a struct uart_port for a given device node
*/
-static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
- int type, struct uart_port *port)
+static int of_platform_serial_setup(struct platform_device *ofdev,
+ int type, struct uart_port *port,
+ struct of_serial_info *info)
{
struct resource resource;
struct device_node *np = ofdev->dev.of_node;
@@ -60,8 +63,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
memset(port, 0, sizeof *port);
if (of_property_read_u32(np, "clock-frequency", &clk)) {
- dev_warn(&ofdev->dev, "no clock-frequency property set\n");
- return -ENODEV;
+
+ /* Get clk rate through clk driver if present */
+ info->clk = clk_get(&ofdev->dev, NULL);
+ if (IS_ERR(info->clk)) {
+ dev_warn(&ofdev->dev,
+ "clk or clock-frequency not defined\n");
+ return PTR_ERR(info->clk);
+ }
+
+ clk_prepare_enable(info->clk);
+ clk = clk_get_rate(info->clk);
}
/* If current-speed was set, then try not to change it. */
if (of_property_read_u32(np, "current-speed", &spd) == 0)
@@ -70,7 +82,7 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
ret = of_address_to_resource(np, 0, &resource);
if (ret) {
dev_warn(&ofdev->dev, "invalid address\n");
- return ret;
+ goto out;
}
spin_lock_init(&port->lock);
@@ -97,7 +109,8 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
default:
dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
prop);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
}
@@ -115,13 +128,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
port->handle_break = tegra_serial_handle_break;
return 0;
+out:
+ if (info->clk)
+ clk_disable_unprepare(info->clk);
+ return ret;
}
/*
* Try to register a serial port
*/
static struct of_device_id of_platform_serial_table[];
-static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
+static int of_platform_serial_probe(struct platform_device *ofdev)
{
const struct of_device_id *match;
struct of_serial_info *info;
@@ -141,7 +158,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
return -ENOMEM;
port_type = (unsigned long)match->data;
- ret = of_platform_serial_setup(ofdev, port_type, &port);
+ ret = of_platform_serial_setup(ofdev, port_type, &port, info);
if (ret)
goto out;
@@ -204,6 +221,9 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
/* need to add code for these */
break;
}
+
+ if (info->clk)
+ clk_disable_unprepare(info->clk);
kfree(info);
return 0;
}
@@ -211,7 +231,7 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
/*
* A few common types, add more as needed.
*/
-static struct of_device_id __devinitdata of_platform_serial_table[] = {
+static struct of_device_id of_platform_serial_table[] = {
{ .compatible = "ns8250", .data = (void *)PORT_8250, },
{ .compatible = "ns16450", .data = (void *)PORT_16450, },
{ .compatible = "ns16550a", .data = (void *)PORT_16550A, },
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6d3d26a607b9..23f797eb7a28 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -44,6 +44,8 @@
#include <plat/omap-serial.h>
+#define OMAP_MAX_HSUART_PORTS 6
+
#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))
#define OMAP_UART_REV_42 0x0402
@@ -51,10 +53,14 @@
#define OMAP_UART_REV_52 0x0502
#define OMAP_UART_REV_63 0x0603
+#define UART_ERRATA_i202_MDR1_ACCESS BIT(0)
+#define UART_ERRATA_i291_DMA_FORCEIDLE BIT(1)
+
#define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
/* SCR register bitmasks */
#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
+#define OMAP_UART_SCR_TX_EMPTY (1 << 3)
/* FCR register bitmasks */
#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
@@ -71,6 +77,52 @@
#define OMAP_UART_MVR_MAJ_SHIFT 8
#define OMAP_UART_MVR_MIN_MASK 0x3f
+#define OMAP_UART_DMA_CH_FREE -1
+
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+#define OMAP_MODE13X_SPEED 230400
+
+/* WER = 0x7F
+ * Enable module level wakeup in WER reg
+ */
+#define OMAP_UART_WER_MOD_WKUP 0X7F
+
+/* Enable XON/XOFF flow control on output */
+#define OMAP_UART_SW_TX 0x08
+
+/* Enable XON/XOFF flow control on input */
+#define OMAP_UART_SW_RX 0x02
+
+#define OMAP_UART_SW_CLR 0xF0
+
+#define OMAP_UART_TCR_TRIG 0x0F
+
+struct uart_omap_dma {
+ u8 uart_dma_tx;
+ u8 uart_dma_rx;
+ int rx_dma_channel;
+ int tx_dma_channel;
+ dma_addr_t rx_buf_dma_phys;
+ dma_addr_t tx_buf_dma_phys;
+ unsigned int uart_base;
+ /*
+ * Buffer for rx dma.It is not required for tx because the buffer
+ * comes from port structure.
+ */
+ unsigned char *rx_buf;
+ unsigned int prev_rx_dma_pos;
+ int tx_buf_size;
+ int tx_dma_used;
+ int rx_dma_used;
+ spinlock_t tx_lock;
+ spinlock_t rx_lock;
+ /* timer to poll activity on rx dma */
+ struct timer_list rx_timer;
+ unsigned int rx_buf_size;
+ unsigned int rx_poll_rate;
+ unsigned int rx_timeout;
+};
+
struct uart_omap_port {
struct uart_port port;
struct uart_omap_dma uart_dma;
@@ -96,10 +148,9 @@ struct uart_omap_port {
unsigned char msr_saved_flags;
char name[20];
unsigned long port_activity;
- u32 context_loss_cnt;
+ int context_loss_cnt;
u32 errata;
u8 wakeups_enabled;
- unsigned int irq_pending:1;
int DTR_gpio;
int DTR_inverted;
@@ -303,6 +354,34 @@ static void serial_omap_start_tx(struct uart_port *port)
pm_runtime_put_autosuspend(up->dev);
}
+static void serial_omap_throttle(struct uart_port *port)
+{
+ struct uart_omap_port *up = to_uart_omap_port(port);
+ unsigned long flags;
+
+ pm_runtime_get_sync(up->dev);
+ spin_lock_irqsave(&up->port.lock, flags);
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+ serial_out(up, UART_IER, up->ier);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+}
+
+static void serial_omap_unthrottle(struct uart_port *port)
+{
+ struct uart_omap_port *up = to_uart_omap_port(port);
+ unsigned long flags;
+
+ pm_runtime_get_sync(up->dev);
+ spin_lock_irqsave(&up->port.lock, flags);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+}
+
static unsigned int check_modem_status(struct uart_omap_port *up)
{
unsigned int status;
@@ -504,7 +583,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_omap_port *up = to_uart_omap_port(port);
- unsigned char mcr = 0;
+ unsigned char mcr = 0, old_mcr;
dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
if (mctrl & TIOCM_RTS)
@@ -519,8 +598,10 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
mcr |= UART_MCR_LOOP;
pm_runtime_get_sync(up->dev);
- up->mcr = serial_in(up, UART_MCR);
- up->mcr |= mcr;
+ old_mcr = serial_in(up, UART_MCR);
+ old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
+ UART_MCR_DTR | UART_MCR_RTS);
+ up->mcr = old_mcr | mcr;
serial_out(up, UART_MCR, up->mcr);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
@@ -654,65 +735,6 @@ static void serial_omap_shutdown(struct uart_port *port)
free_irq(up->port.irq, up);
}
-static inline void
-serial_omap_configure_xonxoff
- (struct uart_omap_port *up, struct ktermios *termios)
-{
- up->lcr = serial_in(up, UART_LCR);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- up->efr = serial_in(up, UART_EFR);
- serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
-
- serial_out(up, UART_XON1, termios->c_cc[VSTART]);
- serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
-
- /* clear SW control mode bits */
- up->efr &= OMAP_UART_SW_CLR;
-
- /*
- * IXON Flag:
- * Enable XON/XOFF flow control on output.
- * Transmit XON1, XOFF1
- */
- if (termios->c_iflag & IXON)
- up->efr |= OMAP_UART_SW_TX;
-
- /*
- * IXOFF Flag:
- * Enable XON/XOFF flow control on input.
- * Receiver compares XON1, XOFF1.
- */
- if (termios->c_iflag & IXOFF)
- up->efr |= OMAP_UART_SW_RX;
-
- serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
- up->mcr = serial_in(up, UART_MCR);
-
- /*
- * IXANY Flag:
- * Enable any character to restart output.
- * Operation resumes after receiving any
- * character after recognition of the XOFF character
- */
- if (termios->c_iflag & IXANY)
- up->mcr |= UART_MCR_XONANY;
-
- serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
- /* Enable special char function UARTi.EFR_REG[5] and
- * load the new software flow control mode IXON or IXOFF
- * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
- */
- serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
- serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
- serial_out(up, UART_LCR, up->lcr);
-}
-
static void serial_omap_uart_qos_work(struct work_struct *work)
{
struct uart_omap_port *up = container_of(work, struct uart_omap_port,
@@ -730,7 +752,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char cval = 0;
- unsigned char efr = 0;
unsigned long flags = 0;
unsigned int baud, quot;
@@ -840,11 +861,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- up->efr = serial_in(up, UART_EFR);
+ up->efr = serial_in(up, UART_EFR) & ~UART_EFR_ECB;
+ up->efr &= ~UART_EFR_SCD;
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- up->mcr = serial_in(up, UART_MCR);
+ up->mcr = serial_in(up, UART_MCR) & ~UART_MCR_TCRTLR;
serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
/* FIFO ENABLE, DMA MODE */
@@ -863,9 +885,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_OMAP_SCR, up->scr);
- serial_out(up, UART_EFR, up->efr);
+ /* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_MCR, up->mcr);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, up->efr);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
/* Protocol, Baud Rate, and Interrupt Settings */
@@ -875,8 +900,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_OMAP_MDR1, up->mdr1);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- up->efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
serial_out(up, UART_LCR, 0);
@@ -903,29 +926,68 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
else
serial_out(up, UART_OMAP_MDR1, up->mdr1);
- /* Hardware Flow Control Configuration */
+ /* Configure flow control */
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+ /* XON1/XOFF1 accessible mode B, TCRTLR=0, ECB=0 */
+ serial_out(up, UART_XON1, termios->c_cc[VSTART]);
+ serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
+
+ /* Enable access to TCR/TLR */
+ serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
- if (termios->c_cflag & CRTSCTS) {
- efr |= (UART_EFR_CTS | UART_EFR_RTS);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
- up->mcr = serial_in(up, UART_MCR);
- serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+ if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
+ /* Enable AUTORTS and AUTOCTS */
+ up->efr |= UART_EFR_CTS | UART_EFR_RTS;
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- up->efr = serial_in(up, UART_EFR);
- serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+ /* Ensure MCR RTS is asserted */
+ up->mcr |= UART_MCR_RTS;
+ } else {
+ /* Disable AUTORTS and AUTOCTS */
+ up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS);
+ }
+
+ if (up->port.flags & UPF_SOFT_FLOW) {
+ /* clear SW control mode bits */
+ up->efr &= OMAP_UART_SW_CLR;
+
+ /*
+ * IXON Flag:
+ * Enable XON/XOFF flow control on input.
+ * Receiver compares XON1, XOFF1.
+ */
+ if (termios->c_iflag & IXON)
+ up->efr |= OMAP_UART_SW_RX;
- serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
- serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
- serial_out(up, UART_LCR, cval);
+ /*
+ * IXOFF Flag:
+ * Enable XON/XOFF flow control on output.
+ * Transmit XON1, XOFF1
+ */
+ if (termios->c_iflag & IXOFF)
+ up->efr |= OMAP_UART_SW_TX;
+
+ /*
+ * IXANY Flag:
+ * Enable any character to restart output.
+ * Operation resumes after receiving any
+ * character after recognition of the XOFF character
+ */
+ if (termios->c_iflag & IXANY)
+ up->mcr |= UART_MCR_XONANY;
+ else
+ up->mcr &= ~UART_MCR_XONANY;
}
+ serial_out(up, UART_MCR, up->mcr);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, up->efr);
+ serial_out(up, UART_LCR, up->lcr);
serial_omap_set_mctrl(&up->port, up->port.mctrl);
- /* Software Flow Control Configuration */
- serial_omap_configure_xonxoff(up, termios);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
@@ -991,6 +1053,7 @@ static void serial_omap_config_port(struct uart_port *port, int flags)
dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
up->port.line);
up->port.type = PORT_OMAP;
+ up->port.flags |= UPF_SOFT_FLOW | UPF_HARD_FLOW;
}
static int
@@ -1081,7 +1144,7 @@ out:
#ifdef CONFIG_SERIAL_OMAP_CONSOLE
-static struct uart_omap_port *serial_omap_console_ports[4];
+static struct uart_omap_port *serial_omap_console_ports[OMAP_MAX_HSUART_PORTS];
static struct uart_driver serial_omap_reg;
@@ -1194,6 +1257,8 @@ static struct uart_ops serial_omap_pops = {
.get_mctrl = serial_omap_get_mctrl,
.stop_tx = serial_omap_stop_tx,
.start_tx = serial_omap_start_tx,
+ .throttle = serial_omap_throttle,
+ .unthrottle = serial_omap_unthrottle,
.stop_rx = serial_omap_stop_rx,
.enable_ms = serial_omap_enable_ms,
.break_ctl = serial_omap_break_ctl,
@@ -1242,7 +1307,7 @@ static int serial_omap_resume(struct device *dev)
}
#endif
-static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *up)
+static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
{
u32 mvr, scheme;
u16 revision, major, minor;
@@ -1295,7 +1360,7 @@ static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *u
}
}
-static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
+static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
{
struct omap_uart_port_info *omap_up_info;
@@ -1308,7 +1373,7 @@ static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device
return omap_up_info;
}
-static int __devinit serial_omap_probe(struct platform_device *pdev)
+static int serial_omap_probe(struct platform_device *pdev)
{
struct uart_omap_port *up;
struct resource *mem, *irq;
@@ -1445,7 +1510,7 @@ err_port_line:
return ret;
}
-static int __devexit serial_omap_remove(struct platform_device *dev)
+static int serial_omap_remove(struct platform_device *dev)
{
struct uart_omap_port *up = platform_get_drvdata(dev);
@@ -1556,11 +1621,15 @@ static int serial_omap_runtime_resume(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
- u32 loss_cnt = serial_omap_get_context_loss_count(up);
+ int loss_cnt = serial_omap_get_context_loss_count(up);
- if (up->context_loss_cnt != loss_cnt)
+ if (loss_cnt < 0) {
+ dev_err(dev, "serial_omap_get_context_loss_count failed : %d\n",
+ loss_cnt);
serial_omap_restore_context(up);
-
+ } else if (up->context_loss_cnt != loss_cnt) {
+ serial_omap_restore_context(up);
+ }
up->latency = up->calc_latency;
schedule_work(&up->qos_work);
@@ -1586,7 +1655,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
static struct platform_driver serial_omap_driver = {
.probe = serial_omap_probe,
- .remove = __devexit_p(serial_omap_remove),
+ .remove = serial_omap_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &serial_omap_dev_pm_ops,
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 4cd6c2381528..8318925fbf6b 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -1839,7 +1839,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
{0,},
};
-static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
+static int pch_uart_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
@@ -1869,7 +1869,7 @@ static struct pci_driver pch_uart_pci_driver = {
.name = "pch_uart",
.id_table = pch_uart_pci_id,
.probe = pch_uart_pci_probe,
- .remove = __devexit_p(pch_uart_pci_remove),
+ .remove = pch_uart_pci_remove,
.suspend = pch_uart_pci_suspend,
.resume = pch_uart_pci_resume,
};
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 9033fc6e0e4e..2764828251f5 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -705,6 +705,57 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
clk_disable_unprepare(up->clk);
}
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial_pxa_get_poll_char(struct uart_port *port)
+{
+ struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+ unsigned char lsr = serial_in(up, UART_LSR);
+
+ while (!(lsr & UART_LSR_DR))
+ lsr = serial_in(up, UART_LSR);
+
+ return serial_in(up, UART_RX);
+}
+
+
+static void serial_pxa_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ unsigned int ier;
+ struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, UART_IER_UUE);
+
+ wait_for_xmitr(up);
+ /*
+ * Send the character out.
+ * If a LF, also do CR...
+ */
+ serial_out(up, UART_TX, c);
+ if (c == 10) {
+ wait_for_xmitr(up);
+ serial_out(up, UART_TX, 13);
+ }
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up);
+ serial_out(up, UART_IER, ier);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
static int __init
serial_pxa_console_setup(struct console *co, char *options)
{
@@ -759,6 +810,10 @@ struct uart_ops serial_pxa_pops = {
.request_port = serial_pxa_request_port,
.config_port = serial_pxa_config_port,
.verify_port = serial_pxa_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = serial_pxa_get_poll_char,
+ .poll_put_char = serial_pxa_put_poll_char,
+#endif
};
static struct uart_driver serial_pxa_reg = {
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index 2ca5959ec3fa..da56c8a0fdc9 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -637,7 +637,7 @@ static void __init sa1100_init_ports(void)
PPSR |= PPC_TXD1 | PPC_TXD3;
}
-void __devinit sa1100_register_uart_fns(struct sa1100_port_fns *fns)
+void sa1100_register_uart_fns(struct sa1100_port_fns *fns)
{
if (fns->get_mctrl)
sa1100_pops.get_mctrl = fns->get_mctrl;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 7f04717176aa..fb0e0f0bed0e 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -223,8 +223,11 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
struct uart_port *port = &ourport->port;
struct tty_struct *tty = port->state->port.tty;
unsigned int ufcon, ch, flag, ufstat, uerstat;
+ unsigned long flags;
int max_count = 64;
+ spin_lock_irqsave(&port->lock, flags);
+
while (max_count-- > 0) {
ufcon = rd_regl(port, S3C2410_UFCON);
ufstat = rd_regl(port, S3C2410_UFSTAT);
@@ -299,6 +302,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
tty_flip_buffer_push(tty);
out:
+ spin_unlock_irqrestore(&port->lock, flags);
return IRQ_HANDLED;
}
@@ -307,8 +311,11 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
+ unsigned long flags;
int count = 256;
+ spin_lock_irqsave(&port->lock, flags);
+
if (port->x_char) {
wr_regb(port, S3C2410_UTXH, port->x_char);
port->icount.tx++;
@@ -336,13 +343,17 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
port->icount.tx++;
}
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
+ spin_unlock(&port->lock);
uart_write_wakeup(port);
+ spin_lock(&port->lock);
+ }
if (uart_circ_empty(xmit))
s3c24xx_serial_stop_tx(port);
out:
+ spin_unlock_irqrestore(&port->lock, flags);
return IRQ_HANDLED;
}
@@ -352,10 +363,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
unsigned int pend = rd_regl(port, S3C64XX_UINTP);
- unsigned long flags;
irqreturn_t ret = IRQ_HANDLED;
- spin_lock_irqsave(&port->lock, flags);
if (pend & S3C64XX_UINTM_RXD_MSK) {
ret = s3c24xx_serial_rx_chars(irq, id);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
@@ -364,7 +373,6 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
ret = s3c24xx_serial_tx_chars(irq, id);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
}
- spin_unlock_irqrestore(&port->lock, flags);
return ret;
}
@@ -530,16 +538,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
switch (level) {
case 3:
if (!IS_ERR(ourport->baudclk))
- clk_disable(ourport->baudclk);
+ clk_disable_unprepare(ourport->baudclk);
- clk_disable(ourport->clk);
+ clk_disable_unprepare(ourport->clk);
break;
case 0:
- clk_enable(ourport->clk);
+ clk_prepare_enable(ourport->clk);
if (!IS_ERR(ourport->baudclk))
- clk_enable(ourport->baudclk);
+ clk_prepare_enable(ourport->baudclk);
break;
default:
@@ -713,11 +721,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
s3c24xx_serial_setsource(port, clk_sel);
if (!IS_ERR(ourport->baudclk)) {
- clk_disable(ourport->baudclk);
+ clk_disable_unprepare(ourport->baudclk);
ourport->baudclk = ERR_PTR(-EINVAL);
}
- clk_enable(clk);
+ clk_prepare_enable(clk);
ourport->baudclk = clk;
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
@@ -1256,7 +1264,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit s3c24xx_serial_remove(struct platform_device *dev)
+static int s3c24xx_serial_remove(struct platform_device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
@@ -1287,9 +1295,9 @@ static int s3c24xx_serial_resume(struct device *dev)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (port) {
- clk_enable(ourport->clk);
+ clk_prepare_enable(ourport->clk);
s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
- clk_disable(ourport->clk);
+ clk_disable_unprepare(ourport->clk);
uart_resume_port(&s3c24xx_uart_drv, port);
}
@@ -1701,6 +1709,16 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
#ifdef CONFIG_OF
static const struct of_device_id s3c24xx_uart_dt_match[] = {
+ { .compatible = "samsung,s3c2410-uart",
+ .data = (void *)S3C2410_SERIAL_DRV_DATA },
+ { .compatible = "samsung,s3c2412-uart",
+ .data = (void *)S3C2412_SERIAL_DRV_DATA },
+ { .compatible = "samsung,s3c2440-uart",
+ .data = (void *)S3C2440_SERIAL_DRV_DATA },
+ { .compatible = "samsung,s3c6400-uart",
+ .data = (void *)S3C6400_SERIAL_DRV_DATA },
+ { .compatible = "samsung,s5pv210-uart",
+ .data = (void *)S5PV210_SERIAL_DRV_DATA },
{ .compatible = "samsung,exynos4210-uart",
.data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
{},
@@ -1712,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
static struct platform_driver samsung_serial_driver = {
.probe = s3c24xx_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
+ .remove = s3c24xx_serial_remove,
.id_table = s3c24xx_serial_driver_ids,
.driver = {
.name = "samsung-uart",
diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c
index 9d664242b312..aced1dd923d8 100644
--- a/drivers/tty/serial/sc26xx.c
+++ b/drivers/tty/serial/sc26xx.c
@@ -621,7 +621,7 @@ static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos)
return bit ? (1 << (bit - 1)) : 0;
}
-static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
+static void sc26xx_init_masks(struct uart_sc26xx_port *up,
int line, unsigned int data)
{
up->dtr_mask[line] = sc26xx_flags2mask(data, 0);
@@ -632,7 +632,7 @@ static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
up->ri_mask[line] = sc26xx_flags2mask(data, 20);
}
-static int __devinit sc26xx_probe(struct platform_device *dev)
+static int sc26xx_probe(struct platform_device *dev)
{
struct resource *res;
struct uart_sc26xx_port *up;
@@ -733,7 +733,7 @@ static int __exit sc26xx_driver_remove(struct platform_device *dev)
static struct platform_driver sc26xx_driver = {
.probe = sc26xx_probe,
- .remove = __devexit_p(sc26xx_driver_remove),
+ .remove = sc26xx_driver_remove,
.driver = {
.name = "SC26xx",
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index e821068cd95b..418b495e3233 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -740,7 +740,7 @@ static int sccnxp_console_setup(struct console *co, char *options)
}
#endif
-static int __devinit sccnxp_probe(struct platform_device *pdev)
+static int sccnxp_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int chiptype = pdev->id_entry->driver_data;
@@ -943,7 +943,7 @@ err_out:
return ret;
}
-static int __devexit sccnxp_remove(struct platform_device *pdev)
+static int sccnxp_remove(struct platform_device *pdev)
{
int i;
struct sccnxp_port *s = platform_get_drvdata(pdev);
@@ -981,7 +981,7 @@ static struct platform_driver sccnxp_uart_driver = {
.owner = THIS_MODULE,
},
.probe = sccnxp_probe,
- .remove = __devexit_p(sccnxp_remove),
+ .remove = sccnxp_remove,
.id_table = sccnxp_id_table,
};
module_platform_driver(sccnxp_uart_driver);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0fcfd98a9566..2c7230aaefd4 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -610,34 +610,57 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)
static void uart_throttle(struct tty_struct *tty)
{
struct uart_state *state = tty->driver_data;
+ struct uart_port *port = state->uart_port;
+ uint32_t mask = 0;
if (I_IXOFF(tty))
+ mask |= UPF_SOFT_FLOW;
+ if (tty->termios.c_cflag & CRTSCTS)
+ mask |= UPF_HARD_FLOW;
+
+ if (port->flags & mask) {
+ port->ops->throttle(port);
+ mask &= ~port->flags;
+ }
+
+ if (mask & UPF_SOFT_FLOW)
uart_send_xchar(tty, STOP_CHAR(tty));
- if (tty->termios.c_cflag & CRTSCTS)
- uart_clear_mctrl(state->uart_port, TIOCM_RTS);
+ if (mask & UPF_HARD_FLOW)
+ uart_clear_mctrl(port, TIOCM_RTS);
}
static void uart_unthrottle(struct tty_struct *tty)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->uart_port;
+ uint32_t mask = 0;
+
+ if (I_IXOFF(tty))
+ mask |= UPF_SOFT_FLOW;
+ if (tty->termios.c_cflag & CRTSCTS)
+ mask |= UPF_HARD_FLOW;
- if (I_IXOFF(tty)) {
+ if (port->flags & mask) {
+ port->ops->unthrottle(port);
+ mask &= ~port->flags;
+ }
+
+ if (mask & UPF_SOFT_FLOW) {
if (port->x_char)
port->x_char = 0;
else
uart_send_xchar(tty, START_CHAR(tty));
}
- if (tty->termios.c_cflag & CRTSCTS)
+ if (mask & UPF_HARD_FLOW)
uart_set_mctrl(port, TIOCM_RTS);
}
-static void uart_get_info(struct tty_port *port,
- struct uart_state *state,
+static void do_uart_get_info(struct tty_port *port,
struct serial_struct *retinfo)
{
+ struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
memset(retinfo, 0, sizeof(*retinfo));
@@ -662,17 +685,21 @@ static void uart_get_info(struct tty_port *port,
retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
}
-static int uart_get_info_user(struct uart_state *state,
- struct serial_struct __user *retinfo)
+static void uart_get_info(struct tty_port *port,
+ struct serial_struct *retinfo)
{
- struct tty_port *port = &state->port;
- struct serial_struct tmp;
-
/* Ensure the state we copy is consistent and no hardware changes
occur as we go */
mutex_lock(&port->mutex);
- uart_get_info(port, state, &tmp);
+ do_uart_get_info(port, retinfo);
mutex_unlock(&port->mutex);
+}
+
+static int uart_get_info_user(struct tty_port *port,
+ struct serial_struct __user *retinfo)
+{
+ struct serial_struct tmp;
+ uart_get_info(port, &tmp);
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
@@ -1131,7 +1158,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd,
*/
switch (cmd) {
case TIOCGSERIAL:
- ret = uart_get_info_user(state, uarg);
+ ret = uart_get_info_user(port, uarg);
break;
case TIOCSSERIAL:
@@ -1210,9 +1237,22 @@ static void uart_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
struct uart_state *state = tty->driver_data;
+ struct uart_port *uport = state->uart_port;
unsigned long flags;
unsigned int cflag = tty->termios.c_cflag;
+ unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK;
+ bool sw_changed = false;
+ /*
+ * Drivers doing software flow control also need to know
+ * about changes to these input settings.
+ */
+ if (uport->flags & UPF_SOFT_FLOW) {
+ iflag_mask |= IXANY|IXON|IXOFF;
+ sw_changed =
+ tty->termios.c_cc[VSTART] != old_termios->c_cc[VSTART] ||
+ tty->termios.c_cc[VSTOP] != old_termios->c_cc[VSTOP];
+ }
/*
* These are the bits that are used to setup various
@@ -1220,11 +1260,11 @@ static void uart_set_termios(struct tty_struct *tty,
* bits in c_cflag; c_[io]speed will always be set
* appropriately by set_termios() in tty_ioctl.c
*/
-#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
if ((cflag ^ old_termios->c_cflag) == 0 &&
tty->termios.c_ospeed == old_termios->c_ospeed &&
tty->termios.c_ispeed == old_termios->c_ispeed &&
- RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) {
+ ((tty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 &&
+ !sw_changed) {
return;
}
@@ -1232,31 +1272,38 @@ static void uart_set_termios(struct tty_struct *tty,
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
- uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
+ uart_clear_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
/* Handle transition away from B0 status */
else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
unsigned int mask = TIOCM_DTR;
if (!(cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags))
mask |= TIOCM_RTS;
- uart_set_mctrl(state->uart_port, mask);
+ uart_set_mctrl(uport, mask);
}
+ /*
+ * If the port is doing h/w assisted flow control, do nothing.
+ * We assume that tty->hw_stopped has never been set.
+ */
+ if (uport->flags & UPF_HARD_FLOW)
+ return;
+
/* Handle turning off CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
- spin_lock_irqsave(&state->uart_port->lock, flags);
+ spin_lock_irqsave(&uport->lock, flags);
tty->hw_stopped = 0;
__uart_start(tty);
- spin_unlock_irqrestore(&state->uart_port->lock, flags);
+ spin_unlock_irqrestore(&uport->lock, flags);
}
/* Handle turning on CRTSCTS */
else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
- spin_lock_irqsave(&state->uart_port->lock, flags);
- if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
+ spin_lock_irqsave(&uport->lock, flags);
+ if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) {
tty->hw_stopped = 1;
- state->uart_port->ops->stop_tx(state->uart_port);
+ uport->ops->stop_tx(uport);
}
- spin_unlock_irqrestore(&state->uart_port->lock, flags);
+ spin_unlock_irqrestore(&uport->lock, flags);
}
}
@@ -2293,6 +2340,8 @@ int uart_register_driver(struct uart_driver *drv)
if (retval >= 0)
return retval;
+ for (i = 0; i < drv->nr; i++)
+ tty_port_destroy(&drv->state[i].port);
put_tty_driver(normal);
out_kfree:
kfree(drv->state);
@@ -2312,8 +2361,12 @@ out:
void uart_unregister_driver(struct uart_driver *drv)
{
struct tty_driver *p = drv->tty_driver;
+ unsigned int i;
+
tty_unregister_driver(p);
put_tty_driver(p);
+ for (i = 0; i < drv->nr; i++)
+ tty_port_destroy(&drv->state[i].port);
kfree(drv->state);
drv->state = NULL;
drv->tty_driver = NULL;
@@ -2329,21 +2382,166 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
static ssize_t uart_get_attr_uartclk(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret;
+ struct serial_struct tmp;
struct tty_port *port = dev_get_drvdata(dev);
- struct uart_state *state = container_of(port, struct uart_state, port);
- mutex_lock(&state->port.mutex);
- ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
- mutex_unlock(&state->port.mutex);
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.baud_base * 16);
+}
- return ret;
+static ssize_t uart_get_attr_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.type);
+}
+static ssize_t uart_get_attr_line(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.line);
+}
+
+static ssize_t uart_get_attr_port(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+ unsigned long ioaddr;
+
+ uart_get_info(port, &tmp);
+ ioaddr = tmp.port;
+ if (HIGH_BITS_OFFSET)
+ ioaddr |= (unsigned long)tmp.port_high << HIGH_BITS_OFFSET;
+ return snprintf(buf, PAGE_SIZE, "0x%lX\n", ioaddr);
}
+static ssize_t uart_get_attr_irq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.irq);
+}
+
+static ssize_t uart_get_attr_flags(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "0x%X\n", tmp.flags);
+}
+
+static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.xmit_fifo_size);
+}
+
+
+static ssize_t uart_get_attr_close_delay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.close_delay);
+}
+
+
+static ssize_t uart_get_attr_closing_wait(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.closing_wait);
+}
+
+static ssize_t uart_get_attr_custom_divisor(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.custom_divisor);
+}
+
+static ssize_t uart_get_attr_io_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.io_type);
+}
+
+static ssize_t uart_get_attr_iomem_base(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "0x%lX\n", (unsigned long)tmp.iomem_base);
+}
+
+static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct serial_struct tmp;
+ struct tty_port *port = dev_get_drvdata(dev);
+
+ uart_get_info(port, &tmp);
+ return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);
+}
+
+static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL);
+static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL);
+static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL);
+static DEVICE_ATTR(irq, S_IRUSR | S_IRGRP, uart_get_attr_irq, NULL);
+static DEVICE_ATTR(flags, S_IRUSR | S_IRGRP, uart_get_attr_flags, NULL);
+static DEVICE_ATTR(xmit_fifo_size, S_IRUSR | S_IRGRP, uart_get_attr_xmit_fifo_size, NULL);
static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
+static DEVICE_ATTR(close_delay, S_IRUSR | S_IRGRP, uart_get_attr_close_delay, NULL);
+static DEVICE_ATTR(closing_wait, S_IRUSR | S_IRGRP, uart_get_attr_closing_wait, NULL);
+static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divisor, NULL);
+static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL);
+static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL);
+static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL);
static struct attribute *tty_dev_attrs[] = {
+ &dev_attr_type.attr,
+ &dev_attr_line.attr,
+ &dev_attr_port.attr,
+ &dev_attr_irq.attr,
+ &dev_attr_flags.attr,
+ &dev_attr_xmit_fifo_size.attr,
&dev_attr_uartclk.attr,
+ &dev_attr_close_delay.attr,
+ &dev_attr_closing_wait.attr,
+ &dev_attr_custom_divisor.attr,
+ &dev_attr_io_type.attr,
+ &dev_attr_iomem_base.attr,
+ &dev_attr_iomem_reg_shift.attr,
NULL,
};
@@ -2356,6 +2554,7 @@ static const struct attribute_group *tty_dev_attr_groups[] = {
NULL
};
+
/**
* uart_add_one_port - attach a driver-defined port structure
* @drv: pointer to the uart low level driver structure for this port
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 6ae2a58d62f2..b52b21aeb250 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1030,7 +1030,7 @@ static DEFINE_MUTEX(serial_txx9_mutex);
*
* On success the port is ready to use and the line number is returned.
*/
-static int __devinit serial_txx9_register_port(struct uart_port *port)
+static int serial_txx9_register_port(struct uart_port *port)
{
int i;
struct uart_txx9_port *uart;
@@ -1078,7 +1078,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
* Remove one serial port. This may not be called from interrupt
* context. We hand the port back to the our control.
*/
-static void __devexit serial_txx9_unregister_port(int line)
+static void serial_txx9_unregister_port(int line)
{
struct uart_txx9_port *uart = &serial_txx9_ports[line];
@@ -1096,7 +1096,7 @@ static void __devexit serial_txx9_unregister_port(int line)
/*
* Register a set of serial devices attached to a platform device.
*/
-static int __devinit serial_txx9_probe(struct platform_device *dev)
+static int serial_txx9_probe(struct platform_device *dev)
{
struct uart_port *p = dev->dev.platform_data;
struct uart_port port;
@@ -1126,7 +1126,7 @@ static int __devinit serial_txx9_probe(struct platform_device *dev)
/*
* Remove serial ports registered against a platform device.
*/
-static int __devexit serial_txx9_remove(struct platform_device *dev)
+static int serial_txx9_remove(struct platform_device *dev)
{
int i;
@@ -1171,7 +1171,7 @@ static int serial_txx9_resume(struct platform_device *dev)
static struct platform_driver serial_txx9_plat_driver = {
.probe = serial_txx9_probe,
- .remove = __devexit_p(serial_txx9_remove),
+ .remove = serial_txx9_remove,
#ifdef CONFIG_PM
.suspend = serial_txx9_suspend,
.resume = serial_txx9_resume,
@@ -1187,7 +1187,7 @@ static struct platform_driver serial_txx9_plat_driver = {
* Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
*/
-static int __devinit
+static int
pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
{
struct uart_port port;
@@ -1217,7 +1217,7 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
return 0;
}
-static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
+static void pciserial_txx9_remove_one(struct pci_dev *dev)
{
struct uart_txx9_port *up = pci_get_drvdata(dev);
@@ -1261,7 +1261,7 @@ static const struct pci_device_id serial_txx9_pci_tbl[] = {
static struct pci_driver serial_txx9_pci_driver = {
.name = "serial_txx9",
.probe = pciserial_txx9_init_one,
- .remove = __devexit_p(pciserial_txx9_remove_one),
+ .remove = pciserial_txx9_remove_one,
#ifdef CONFIG_PM
.suspend = pciserial_txx9_suspend_one,
.resume = pciserial_txx9_resume_one,
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 6ee59001d61d..61477567423f 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -99,12 +99,6 @@ struct sci_port {
#endif
struct notifier_block freq_transition;
-
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
- unsigned short saved_smr;
- unsigned short saved_fcr;
- unsigned char saved_brr;
-#endif
};
/* Function prototypes */
@@ -202,9 +196,9 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCxSR] = { 0x14, 16 },
[SCxRDR] = { 0x60, 8 },
[SCFCR] = { 0x18, 16 },
- [SCFDR] = { 0x1c, 16 },
- [SCTFDR] = sci_reg_invalid,
- [SCRFDR] = sci_reg_invalid,
+ [SCFDR] = sci_reg_invalid,
+ [SCTFDR] = { 0x38, 16 },
+ [SCRFDR] = { 0x3c, 16 },
[SCSPTR] = sci_reg_invalid,
[SCLSR] = sci_reg_invalid,
},
@@ -491,7 +485,7 @@ static int sci_txfill(struct uart_port *port)
reg = sci_getreg(port, SCTFDR);
if (reg->size)
- return serial_port_in(port, SCTFDR) & 0xff;
+ return serial_port_in(port, SCTFDR) & ((port->fifosize << 1) - 1);
reg = sci_getreg(port, SCFDR);
if (reg->size)
@@ -511,7 +505,7 @@ static int sci_rxfill(struct uart_port *port)
reg = sci_getreg(port, SCRFDR);
if (reg->size)
- return serial_port_in(port, SCRFDR) & 0xff;
+ return serial_port_in(port, SCRFDR) & ((port->fifosize << 1) - 1);
reg = sci_getreg(port, SCFDR);
if (reg->size)
@@ -1132,7 +1126,7 @@ static const char *sci_gpio_str(unsigned int index)
return sci_gpio_names[index];
}
-static void __devinit sci_init_gpios(struct sci_port *port)
+static void sci_init_gpios(struct sci_port *port)
{
struct uart_port *up = &port->port;
int i;
@@ -1749,22 +1743,21 @@ static inline void sci_free_dma(struct uart_port *port)
static int sci_startup(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
+ unsigned long flags;
int ret;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
- pm_runtime_put_noidle(port->dev);
-
- sci_port_enable(s);
-
ret = sci_request_irq(s);
if (unlikely(ret < 0))
return ret;
sci_request_dma(port);
+ spin_lock_irqsave(&port->lock, flags);
sci_start_tx(port);
sci_start_rx(port);
+ spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
@@ -1772,18 +1765,17 @@ static int sci_startup(struct uart_port *port)
static void sci_shutdown(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
+ unsigned long flags;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+ spin_lock_irqsave(&port->lock, flags);
sci_stop_rx(port);
sci_stop_tx(port);
+ spin_unlock_irqrestore(&port->lock, flags);
sci_free_dma(port);
sci_free_irq(s);
-
- sci_port_disable(s);
-
- pm_runtime_get_noresume(port->dev);
}
static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
@@ -1829,7 +1821,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct sci_port *s = to_sci_port(port);
struct plat_sci_reg *reg;
- unsigned int baud, smr_val, max_baud;
+ unsigned int baud, smr_val, max_baud, cks;
int t = -1;
/*
@@ -1863,21 +1855,18 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
uart_update_timeout(port, termios->c_cflag, baud);
- serial_port_out(port, SCSMR, smr_val);
-
- dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
- s->cfg->scscr);
+ for (cks = 0; t >= 256 && cks <= 3; cks++)
+ t >>= 2;
- if (t > 0) {
- if (t >= 256) {
- serial_port_out(port, SCSMR, (serial_port_in(port, SCSMR) & ~3) | 1);
- t >>= 2;
- } else
- serial_port_out(port, SCSMR, serial_port_in(port, SCSMR) & ~3);
+ dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n",
+ __func__, smr_val, cks, t, s->cfg->scscr);
+ if (t >= 0) {
+ serial_port_out(port, SCSMR, (smr_val & ~3) | cks);
serial_port_out(port, SCBRR, t);
udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
- }
+ } else
+ serial_port_out(port, SCSMR, smr_val);
sci_init_pins(port, termios->c_cflag);
@@ -1932,6 +1921,21 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_port_disable(s);
}
+static void sci_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct sci_port *sci_port = to_sci_port(port);
+
+ switch (state) {
+ case 3:
+ sci_port_disable(sci_port);
+ break;
+ default:
+ sci_port_enable(sci_port);
+ break;
+ }
+}
+
static const char *sci_type(struct uart_port *port)
{
switch (port->type) {
@@ -2053,6 +2057,7 @@ static struct uart_ops sci_uart_ops = {
.startup = sci_startup,
.shutdown = sci_shutdown,
.set_termios = sci_set_termios,
+ .pm = sci_pm,
.type = sci_type,
.release_port = sci_release_port,
.request_port = sci_request_port,
@@ -2064,7 +2069,7 @@ static struct uart_ops sci_uart_ops = {
#endif
};
-static int __devinit sci_init_single(struct platform_device *dev,
+static int sci_init_single(struct platform_device *dev,
struct sci_port *sci_port,
unsigned int index,
struct plat_sci_port *p)
@@ -2121,8 +2126,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
sci_init_gpios(sci_port);
- pm_runtime_irq_safe(&dev->dev);
- pm_runtime_get_noresume(&dev->dev);
pm_runtime_enable(&dev->dev);
}
@@ -2206,9 +2209,21 @@ static void serial_console_write(struct console *co, const char *s,
{
struct sci_port *sci_port = &sci_ports[co->index];
struct uart_port *port = &sci_port->port;
- unsigned short bits;
+ unsigned short bits, ctrl;
+ unsigned long flags;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&port->lock);
+ else
+ spin_lock(&port->lock);
- sci_port_enable(sci_port);
+ /* first save the SCSCR then disable the interrupts */
+ ctrl = serial_port_in(port, SCSCR);
+ serial_port_out(port, SCSCR, sci_port->cfg->scscr);
uart_console_write(port, s, count, serial_console_putchar);
@@ -2217,10 +2232,15 @@ static void serial_console_write(struct console *co, const char *s,
while ((serial_port_in(port, SCxSR) & bits) != bits)
cpu_relax();
- sci_port_disable(sci_port);
+ /* restore the SCSCR */
+ serial_port_out(port, SCSCR, ctrl);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
}
-static int __devinit serial_console_setup(struct console *co, char *options)
+static int serial_console_setup(struct console *co, char *options)
{
struct sci_port *sci_port;
struct uart_port *port;
@@ -2249,13 +2269,9 @@ static int __devinit serial_console_setup(struct console *co, char *options)
if (unlikely(ret != 0))
return ret;
- sci_port_enable(sci_port);
-
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
- sci_port_disable(sci_port);
-
return uart_set_options(port, co, baud, parity, bits, flow);
}
@@ -2278,7 +2294,7 @@ static struct console early_serial_console = {
static char early_serial_buf[32];
-static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
+static int sci_probe_earlyprintk(struct platform_device *pdev)
{
struct plat_sci_port *cfg = pdev->dev.platform_data;
@@ -2298,57 +2314,15 @@ static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
return 0;
}
-#define uart_console(port) ((port)->cons->index == (port)->line)
-
-static int sci_runtime_suspend(struct device *dev)
-{
- struct sci_port *sci_port = dev_get_drvdata(dev);
- struct uart_port *port = &sci_port->port;
-
- if (uart_console(port)) {
- struct plat_sci_reg *reg;
-
- sci_port->saved_smr = serial_port_in(port, SCSMR);
- sci_port->saved_brr = serial_port_in(port, SCBRR);
-
- reg = sci_getreg(port, SCFCR);
- if (reg->size)
- sci_port->saved_fcr = serial_port_in(port, SCFCR);
- else
- sci_port->saved_fcr = 0;
- }
- return 0;
-}
-
-static int sci_runtime_resume(struct device *dev)
-{
- struct sci_port *sci_port = dev_get_drvdata(dev);
- struct uart_port *port = &sci_port->port;
-
- if (uart_console(port)) {
- sci_reset(port);
- serial_port_out(port, SCSMR, sci_port->saved_smr);
- serial_port_out(port, SCBRR, sci_port->saved_brr);
-
- if (sci_port->saved_fcr)
- serial_port_out(port, SCFCR, sci_port->saved_fcr);
-
- serial_port_out(port, SCSCR, sci_port->cfg->scscr);
- }
- return 0;
-}
-
#define SCI_CONSOLE (&serial_console)
#else
-static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
+static inline int sci_probe_earlyprintk(struct platform_device *pdev)
{
return -EINVAL;
}
#define SCI_CONSOLE NULL
-#define sci_runtime_suspend NULL
-#define sci_runtime_resume NULL
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
@@ -2379,7 +2353,7 @@ static int sci_remove(struct platform_device *dev)
return 0;
}
-static int __devinit sci_probe_single(struct platform_device *dev,
+static int sci_probe_single(struct platform_device *dev,
unsigned int index,
struct plat_sci_port *p,
struct sci_port *sciport)
@@ -2409,7 +2383,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
return 0;
}
-static int __devinit sci_probe(struct platform_device *dev)
+static int sci_probe(struct platform_device *dev)
{
struct plat_sci_port *p = dev->dev.platform_data;
struct sci_port *sp = &sci_ports[dev->id];
@@ -2466,8 +2440,6 @@ static int sci_resume(struct device *dev)
}
static const struct dev_pm_ops sci_dev_pm_ops = {
- .runtime_suspend = sci_runtime_suspend,
- .runtime_resume = sci_runtime_resume,
.suspend = sci_suspend,
.resume = sci_resume,
};
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index a9e2bd1ab534..5da5cb962769 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -727,7 +727,7 @@ static int sirfsoc_uart_resume(struct platform_device *pdev)
return 0;
}
-static struct of_device_id sirfsoc_uart_ids[] __devinitdata = {
+static struct of_device_id sirfsoc_uart_ids[] = {
{ .compatible = "sirf,prima2-uart", },
{}
};
@@ -735,7 +735,7 @@ MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match);
static struct platform_driver sirfsoc_uart_driver = {
.probe = sirfsoc_uart_probe,
- .remove = __devexit_p(sirfsoc_uart_remove),
+ .remove = sirfsoc_uart_remove,
.suspend = sirfsoc_uart_suspend,
.resume = sirfsoc_uart_resume,
.driver = {
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 505961cfd934..b9bf9c53f7fd 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -519,7 +519,7 @@ static struct console sunhv_console = {
.data = &sunhv_reg,
};
-static int __devinit hv_probe(struct platform_device *op)
+static int hv_probe(struct platform_device *op)
{
struct uart_port *port;
unsigned long minor;
@@ -598,7 +598,7 @@ out_free_port:
return err;
}
-static int __devexit hv_remove(struct platform_device *dev)
+static int hv_remove(struct platform_device *dev)
{
struct uart_port *port = dev_get_drvdata(&dev->dev);
@@ -636,7 +636,7 @@ static struct platform_driver hv_driver = {
.of_match_table = hv_match,
},
.probe = hv_probe,
- .remove = __devexit_p(hv_remove),
+ .remove = hv_remove,
};
static int __init sunhv_init(void)
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index f0d93eb7e6ec..bd8b3b634103 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void)
#define sunsab_console_init() do { } while (0)
#endif
-static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
+static int sunsab_init_one(struct uart_sunsab_port *up,
struct platform_device *op,
unsigned long offset,
int line)
@@ -1007,7 +1007,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
return 0;
}
-static int __devinit sab_probe(struct platform_device *op)
+static int sab_probe(struct platform_device *op)
{
static int inst;
struct uart_sunsab_port *up;
@@ -1063,7 +1063,7 @@ out:
return err;
}
-static int __devexit sab_remove(struct platform_device *op)
+static int sab_remove(struct platform_device *op)
{
struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
@@ -1100,7 +1100,7 @@ static struct platform_driver sab_driver = {
.of_match_table = sab_match,
},
.probe = sab_probe,
- .remove = __devexit_p(sab_remove),
+ .remove = sab_remove,
};
static int __init sunsab_init(void)
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index b97913dcdbff..220da3f9724f 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1185,7 +1185,7 @@ static struct uart_driver sunsu_reg = {
.major = TTY_MAJOR,
};
-static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
+static int sunsu_kbd_ms_init(struct uart_sunsu_port *up)
{
int quot, baud;
#ifdef CONFIG_SERIO
@@ -1391,7 +1391,7 @@ static inline struct console *SUNSU_CONSOLE(void)
#define sunsu_serial_console_init() do { } while (0)
#endif
-static enum su_type __devinit su_get_type(struct device_node *dp)
+static enum su_type su_get_type(struct device_node *dp)
{
struct device_node *ap = of_find_node_by_path("/aliases");
@@ -1412,7 +1412,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
return SU_PORT_PORT;
}
-static int __devinit su_probe(struct platform_device *op)
+static int su_probe(struct platform_device *op)
{
static int inst;
struct device_node *dp = op->dev.of_node;
@@ -1503,7 +1503,7 @@ out_unmap:
return err;
}
-static int __devexit su_remove(struct platform_device *op)
+static int su_remove(struct platform_device *op)
{
struct uart_sunsu_port *up = dev_get_drvdata(&op->dev);
bool kbdms = false;
@@ -1556,7 +1556,7 @@ static struct platform_driver su_driver = {
.of_match_table = su_match,
},
.probe = su_probe,
- .remove = __devexit_p(su_remove),
+ .remove = su_remove,
};
static int __init sunsu_init(void)
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index babd9470982b..aef4fab957c3 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -1282,7 +1282,7 @@ static inline struct console *SUNZILOG_CONSOLE(void)
#define SUNZILOG_CONSOLE() (NULL)
#endif
-static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
+static void sunzilog_init_kbdms(struct uart_sunzilog_port *up)
{
int baud, brg;
@@ -1302,7 +1302,7 @@ static void __devinit sunzilog_init_kbdms(struct uart_sunzilog_port *up)
}
#ifdef CONFIG_SERIO
-static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
+static void sunzilog_register_serio(struct uart_sunzilog_port *up)
{
struct serio *serio = &up->serio;
@@ -1331,7 +1331,7 @@ static void __devinit sunzilog_register_serio(struct uart_sunzilog_port *up)
}
#endif
-static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
+static void sunzilog_init_hw(struct uart_sunzilog_port *up)
{
struct zilog_channel __iomem *channel;
unsigned long flags;
@@ -1400,7 +1400,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
static int zilog_irq;
-static int __devinit zs_probe(struct platform_device *op)
+static int zs_probe(struct platform_device *op)
{
static int kbm_inst, uart_inst;
int inst;
@@ -1507,7 +1507,7 @@ static int __devinit zs_probe(struct platform_device *op)
return 0;
}
-static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
+static void zs_remove_one(struct uart_sunzilog_port *up)
{
if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
#ifdef CONFIG_SERIO
@@ -1517,7 +1517,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
uart_remove_one_port(&sunzilog_reg, &up->port);
}
-static int __devexit zs_remove(struct platform_device *op)
+static int zs_remove(struct platform_device *op)
{
struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev);
struct zilog_layout __iomem *regs;
@@ -1548,7 +1548,7 @@ static struct platform_driver zs_driver = {
.of_match_table = zs_match,
},
.probe = zs_probe,
- .remove = __devexit_p(zs_remove),
+ .remove = zs_remove,
};
static int __init sunzilog_init(void)
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
index 70f97491d8f2..5be0d68feceb 100644
--- a/drivers/tty/serial/timbuart.c
+++ b/drivers/tty/serial/timbuart.c
@@ -426,7 +426,7 @@ static struct uart_driver timbuart_driver = {
.nr = 1
};
-static int __devinit timbuart_probe(struct platform_device *dev)
+static int timbuart_probe(struct platform_device *dev)
{
int err, irq;
struct timbuart_port *uart;
@@ -492,7 +492,7 @@ err_mem:
return err;
}
-static int __devexit timbuart_remove(struct platform_device *dev)
+static int timbuart_remove(struct platform_device *dev)
{
struct timbuart_port *uart = platform_get_drvdata(dev);
@@ -510,7 +510,7 @@ static struct platform_driver timbuart_platform_driver = {
.owner = THIS_MODULE,
},
.probe = timbuart_probe,
- .remove = __devexit_p(timbuart_remove),
+ .remove = timbuart_remove,
};
module_platform_driver(timbuart_platform_driver);
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 6579ffdd8e9b..89eee43c4e2d 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -408,7 +408,7 @@ static void ulite_console_write(struct console *co, const char *s,
spin_unlock_irqrestore(&port->lock, flags);
}
-static int __devinit ulite_console_setup(struct console *co, char *options)
+static int ulite_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = 9600;
@@ -486,7 +486,7 @@ static struct uart_driver ulite_uart_driver = {
*
* Returns: 0 on success, <0 otherwise
*/
-static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
+static int ulite_assign(struct device *dev, int id, u32 base, int irq)
{
struct uart_port *port;
int rc;
@@ -542,7 +542,7 @@ static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
*
* @dev: pointer to device structure
*/
-static int __devexit ulite_release(struct device *dev)
+static int ulite_release(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
int rc = 0;
@@ -562,7 +562,7 @@ static int __devexit ulite_release(struct device *dev)
#if defined(CONFIG_OF)
/* Match table for of_platform binding */
-static struct of_device_id ulite_of_match[] __devinitdata = {
+static struct of_device_id ulite_of_match[] = {
{ .compatible = "xlnx,opb-uartlite-1.00.b", },
{ .compatible = "xlnx,xps-uartlite-1.00.a", },
{}
@@ -570,7 +570,7 @@ static struct of_device_id ulite_of_match[] __devinitdata = {
MODULE_DEVICE_TABLE(of, ulite_of_match);
#endif /* CONFIG_OF */
-static int __devinit ulite_probe(struct platform_device *pdev)
+static int ulite_probe(struct platform_device *pdev)
{
struct resource *res, *res2;
int id = pdev->id;
@@ -593,7 +593,7 @@ static int __devinit ulite_probe(struct platform_device *pdev)
return ulite_assign(&pdev->dev, id, res->start, res2->start);
}
-static int __devexit ulite_remove(struct platform_device *pdev)
+static int ulite_remove(struct platform_device *pdev)
{
return ulite_release(&pdev->dev);
}
@@ -603,7 +603,7 @@ MODULE_ALIAS("platform:uartlite");
static struct platform_driver ulite_platform_driver = {
.probe = ulite_probe,
- .remove = __devexit_p(ulite_remove),
+ .remove = ulite_remove,
.driver = {
.owner = THIS_MODULE,
.name = "uartlite",
diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
index cf0d9485ec08..62ee0166bc65 100644
--- a/drivers/tty/serial/vr41xx_siu.c
+++ b/drivers/tty/serial/vr41xx_siu.c
@@ -823,7 +823,7 @@ static struct console siu_console = {
.data = &siu_uart_driver,
};
-static int __devinit siu_console_init(void)
+static int siu_console_init(void)
{
struct uart_port *port;
int i;
@@ -867,7 +867,7 @@ static struct uart_driver siu_uart_driver = {
.cons = SERIAL_VR41XX_CONSOLE,
};
-static int __devinit siu_probe(struct platform_device *dev)
+static int siu_probe(struct platform_device *dev)
{
struct uart_port *port;
int num, i, retval;
@@ -901,7 +901,7 @@ static int __devinit siu_probe(struct platform_device *dev)
return 0;
}
-static int __devexit siu_remove(struct platform_device *dev)
+static int siu_remove(struct platform_device *dev)
{
struct uart_port *port;
int i;
@@ -952,7 +952,7 @@ static int siu_resume(struct platform_device *dev)
static struct platform_driver siu_device_driver = {
.probe = siu_probe,
- .remove = __devexit_p(siu_remove),
+ .remove = siu_remove,
.suspend = siu_suspend,
.resume = siu_resume,
.driver = {
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 205d4cf4a063..8fd181436a6b 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -554,7 +554,7 @@ static struct uart_driver vt8500_uart_driver = {
.cons = VT8500_CONSOLE,
};
-static int __devinit vt8500_serial_probe(struct platform_device *pdev)
+static int vt8500_serial_probe(struct platform_device *pdev)
{
struct vt8500_port *vt8500_port;
struct resource *mmres, *irqres;
@@ -567,10 +567,6 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
if (!mmres || !irqres)
return -ENODEV;
- vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
- if (!vt8500_port)
- return -ENOMEM;
-
if (np)
port = of_alias_get_id(np, "serial");
if (port > VT8500_MAX_PORTS)
@@ -593,6 +589,10 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
return -EBUSY;
}
+ vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
+ if (!vt8500_port)
+ return -ENOMEM;
+
vt8500_port->uart.type = PORT_VT8500;
vt8500_port->uart.iotype = UPIO_MEM;
vt8500_port->uart.mapbase = mmres->start;
@@ -634,7 +634,7 @@ err:
return ret;
}
-static int __devexit vt8500_serial_remove(struct platform_device *pdev)
+static int vt8500_serial_remove(struct platform_device *pdev)
{
struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
@@ -652,7 +652,7 @@ static const struct of_device_id wmt_dt_ids[] = {
static struct platform_driver vt8500_platform_driver = {
.probe = vt8500_serial_probe,
- .remove = __devexit_p(vt8500_serial_remove),
+ .remove = vt8500_serial_remove,
.driver = {
.name = "vt8500_serial",
.owner = THIS_MODULE,
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index b627363352e5..9ab910370c56 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -939,22 +939,18 @@ static struct uart_driver xuartps_uart_driver = {
*
* Returns 0 on success, negative error otherwise
**/
-static int __devinit xuartps_probe(struct platform_device *pdev)
+static int xuartps_probe(struct platform_device *pdev)
{
int rc;
struct uart_port *port;
struct resource *res, *res2;
int clk = 0;
-#ifdef CONFIG_OF
const unsigned int *prop;
prop = of_get_property(pdev->dev.of_node, "clock", NULL);
if (prop)
clk = be32_to_cpup(prop);
-#else
- clk = *((unsigned int *)(pdev->dev.platform_data));
-#endif
if (!clk) {
dev_err(&pdev->dev, "no clock specified\n");
return -ENODEV;
@@ -1001,7 +997,7 @@ static int __devinit xuartps_probe(struct platform_device *pdev)
*
* Returns 0 on success, negative error otherwise
**/
-static int __devexit xuartps_remove(struct platform_device *pdev)
+static int xuartps_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
int rc = 0;
@@ -1044,16 +1040,11 @@ static int xuartps_resume(struct platform_device *pdev)
}
/* Match table for of_platform binding */
-
-#ifdef CONFIG_OF
-static struct of_device_id xuartps_of_match[] __devinitdata = {
+static struct of_device_id xuartps_of_match[] = {
{ .compatible = "xlnx,xuartps", },
{}
};
MODULE_DEVICE_TABLE(of, xuartps_of_match);
-#else
-#define xuartps_of_match NULL
-#endif
static struct platform_driver xuartps_platform_driver = {
.probe = xuartps_probe, /* Probe method */