TTY/Serial driver updates for 3.13-rc1

Here's the big tty/serial driver update for 3.13-rc1.
 
 There's some more minor n_tty work here, but nothing like previous
 kernel releases.  Also some new driver ids, driver updates for new
 hardware, and other small things.
 
 All of this has been in linux-next for a while with no issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iEYEABECAAYFAlJ6xnEACgkQMUfUDdst+ylj1QCfaIzUNuFfzTmyB6K6iZrRNhCc
 WPgAnRLkkEpI/3rRo7jKwGQsuIuyybUu
 =r149
 -----END PGP SIGNATURE-----

Merge tag 'tty-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial driver updates from Greg KH:
 "Here's the big tty/serial driver update for 3.13-rc1.

  There's some more minor n_tty work here, but nothing like previous
  kernel releases.  Also some new driver ids, driver updates for new
  hardware, and other small things.

  All of this has been in linux-next for a while with no issues"

* tag 'tty-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (84 commits)
  serial: omap: fix missing comma
  serial: sh-sci: Enable the driver on all ARM platforms
  serial: mfd: Staticize local symbols
  serial: omap: fix a few checkpatch warnings
  serial: omap: improve RS-485 performance
  mrst_max3110: fix unbalanced IRQ issue during resume
  serial: omap: Add support for optional wake-up
  serial: sirf: remove duplicate defines
  tty: xuartps: Fix build error when COMMON_CLK is not set
  tty: xuartps: Fix build error due to missing forward declaration
  tty: xuartps: Fix "may be used uninitialized" build warning
  serial: 8250_pci: add Pericom PCIe Serial board Support (12d8:7952/4/8) - Chip PI7C9X7952/4/8
  tty: xuartps: Update copyright information
  tty: xuartps: Implement suspend/resume callbacks
  tty: xuartps: Dynamically adjust to input frequency changes
  tty: xuartps: Updating set_baud_rate()
  tty: xuartps: Force enable the UART in xuartps_console_write
  tty: xuartps: support 64 byte FIFO size
  tty: xuartps: Add polled mode support for xuartps
  tty: xuartps: Implement BREAK detection, add SYSRQ support
  ...
This commit is contained in:
Linus Torvalds 2013-11-07 12:17:06 +09:00
commit 56edff7529
53 changed files with 1200 additions and 364 deletions

View file

@ -264,10 +264,6 @@ hardware.
Locking: none. Locking: none.
Interrupts: caller dependent. Interrupts: caller dependent.
set_wake(port,state)
Enable/disable power management wakeup on serial activity. Not
currently implemented.
type(port) type(port)
Return a pointer to a string constant describing the specified Return a pointer to a string constant describing the specified
port, or return NULL, in which case the string 'unknown' is port, or return NULL, in which case the string 'unknown' is

View file

@ -11,27 +11,29 @@ regardless of whatever else it is doing, unless it is completely locked up.
You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
configuring the kernel. When running a kernel with SysRq compiled in, configuring the kernel. When running a kernel with SysRq compiled in,
/proc/sys/kernel/sysrq controls the functions allowed to be invoked via /proc/sys/kernel/sysrq controls the functions allowed to be invoked via
the SysRq key. By default the file contains 1 which means that every the SysRq key. The default value in this file is set by the
possible SysRq request is allowed (in older versions SysRq was disabled CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults
by default, and you were required to specifically enable it at run-time to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
but this is not the case any more). Here is the list of possible values
in /proc/sys/kernel/sysrq:
0 - disable sysrq completely 0 - disable sysrq completely
1 - enable all functions of sysrq 1 - enable all functions of sysrq
>1 - bitmask of allowed sysrq functions (see below for detailed function >1 - bitmask of allowed sysrq functions (see below for detailed function
description): description):
2 - enable control of console logging level 2 = 0x2 - enable control of console logging level
4 - enable control of keyboard (SAK, unraw) 4 = 0x4 - enable control of keyboard (SAK, unraw)
8 - enable debugging dumps of processes etc. 8 = 0x8 - enable debugging dumps of processes etc.
16 - enable sync command 16 = 0x10 - enable sync command
32 - enable remount read-only 32 = 0x20 - enable remount read-only
64 - enable signalling of processes (term, kill, oom-kill) 64 = 0x40 - enable signalling of processes (term, kill, oom-kill)
128 - allow reboot/poweroff 128 = 0x80 - allow reboot/poweroff
256 - allow nicing of all RT tasks 256 = 0x100 - allow nicing of all RT tasks
You can set the value in the file by the following command: You can set the value in the file by the following command:
echo "number" >/proc/sys/kernel/sysrq echo "number" >/proc/sys/kernel/sysrq
The number may be written here either as decimal or as hexadecimal
with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be
written in hexadecimal.
Note that the value of /proc/sys/kernel/sysrq influences only the invocation Note that the value of /proc/sys/kernel/sysrq influences only the invocation
via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
allowed (by a user with admin privileges). allowed (by a user with admin privileges).

View file

@ -349,7 +349,7 @@ bfin_jc_early_write(struct console *co, const char *buf, unsigned int count)
bfin_jc_straight_buffer_write(buf, count); bfin_jc_straight_buffer_write(buf, count);
} }
static struct __initdata console bfin_jc_early_console = { static struct console bfin_jc_early_console __initdata = {
.name = "early_BFJC", .name = "early_BFJC",
.write = bfin_jc_early_write, .write = bfin_jc_early_write,
.flags = CON_ANYTIME | CON_PRINTBUFFER, .flags = CON_ANYTIME | CON_PRINTBUFFER,

View file

@ -86,6 +86,21 @@ static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
return i; return i;
} }
static bool hvc_dcc_check(void)
{
unsigned long time = jiffies + (HZ / 10);
/* Write a test character to check if it is handled */
__dcc_putchar('\n');
while (time_is_after_jiffies(time)) {
if (!(__dcc_getstatus() & DCC_STATUS_TX))
return true;
}
return false;
}
static const struct hv_ops hvc_dcc_get_put_ops = { static const struct hv_ops hvc_dcc_get_put_ops = {
.get_chars = hvc_dcc_get_chars, .get_chars = hvc_dcc_get_chars,
.put_chars = hvc_dcc_put_chars, .put_chars = hvc_dcc_put_chars,
@ -93,6 +108,9 @@ static const struct hv_ops hvc_dcc_get_put_ops = {
static int __init hvc_dcc_console_init(void) static int __init hvc_dcc_console_init(void)
{ {
if (!hvc_dcc_check())
return -ENODEV;
hvc_instantiate(0, 0, &hvc_dcc_get_put_ops); hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
return 0; return 0;
} }
@ -100,6 +118,9 @@ console_initcall(hvc_dcc_console_init);
static int __init hvc_dcc_init(void) static int __init hvc_dcc_init(void)
{ {
if (!hvc_dcc_check())
return -ENODEV;
hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128); hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
return 0; return 0;
} }

View file

@ -48,6 +48,7 @@
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/hvsi.h> #include <asm/hvsi.h>
#include <asm/udbg.h> #include <asm/udbg.h>
#include <asm/machdep.h>
#include "hvc_console.h" #include "hvc_console.h"
@ -457,7 +458,9 @@ void __init hvc_vio_init_early(void)
if (hvterm_priv0.proto == HV_PROTOCOL_HVSI) if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
goto out; goto out;
#endif #endif
add_preferred_console("hvc", 0, NULL); /* Check whether the user has requested a different console. */
if (!strstr(cmd_line, "console="))
add_preferred_console("hvc", 0, NULL);
hvc_instantiate(0, 0, ops); hvc_instantiate(0, 0, ops);
out: out:
of_node_put(stdout_node); of_node_put(stdout_node);

View file

@ -767,7 +767,7 @@ static size_t __process_echoes(struct tty_struct *tty)
* of echo overrun before the next commit), then discard enough * of echo overrun before the next commit), then discard enough
* data at the tail to prevent a subsequent overrun */ * data at the tail to prevent a subsequent overrun */
while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) {
if (echo_buf(ldata, tail == ECHO_OP_START)) { if (echo_buf(ldata, tail) == ECHO_OP_START) {
if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB) if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB)
tail += 3; tail += 3;
else else
@ -1752,20 +1752,14 @@ int is_ignored(int sig)
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{ {
struct n_tty_data *ldata = tty->disc_data; struct n_tty_data *ldata = tty->disc_data;
int canon_change = 1;
if (old) if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) {
canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
if (canon_change) {
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
ldata->line_start = ldata->canon_head = ldata->read_tail; ldata->line_start = ldata->canon_head = ldata->read_tail;
ldata->erasing = 0; ldata->erasing = 0;
ldata->lnext = 0; ldata->lnext = 0;
} }
if (canon_change && !L_ICANON(tty) && read_cnt(ldata))
wake_up_interruptible(&tty->read_wait);
ldata->icanon = (L_ICANON(tty) != 0); ldata->icanon = (L_ICANON(tty) != 0);
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@ -1820,9 +1814,8 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
* Fix tty hang when I_IXON(tty) is cleared, but the tty * Fix tty hang when I_IXON(tty) is cleared, but the tty
* been stopped by STOP_CHAR(tty) before it. * been stopped by STOP_CHAR(tty) before it.
*/ */
if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped)
start_tty(tty); start_tty(tty);
}
/* The termios change make the tty ready for I/O */ /* The termios change make the tty ready for I/O */
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->write_wait);

View file

@ -959,7 +959,7 @@ static int receive_flow_control(struct nozomi *dc)
dev_err(&dc->pdev->dev, dev_err(&dc->pdev->dev,
"ERROR: flow control received for non-existing port\n"); "ERROR: flow control received for non-existing port\n");
return 0; return 0;
}; }
DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl), DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
*((u16 *)&ctrl_dl)); *((u16 *)&ctrl_dl));
@ -1025,7 +1025,7 @@ static enum ctrl_port_type port2ctrl(enum port_type port,
dev_err(&dc->pdev->dev, dev_err(&dc->pdev->dev,
"ERROR: send flow control " \ "ERROR: send flow control " \
"received for non-existing port\n"); "received for non-existing port\n");
}; }
return CTRL_ERROR; return CTRL_ERROR;
} }
@ -1805,7 +1805,7 @@ static int ntty_ioctl(struct tty_struct *tty,
default: default:
DBG1("ERR: 0x%08X, %d", cmd, cmd); DBG1("ERR: 0x%08X, %d", cmd, cmd);
break; break;
}; }
return rval; return rval;
} }

View file

@ -2322,7 +2322,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
fcr = uart_config[port->type].fcr; fcr = uart_config[port->type].fcr;
if (baud < 2400 || fifo_bug) { if ((baud < 2400 && !up->dma) || fifo_bug) {
fcr &= ~UART_FCR_TRIGGER_MASK; fcr &= ~UART_FCR_TRIGGER_MASK;
fcr |= UART_FCR_TRIGGER_1; fcr |= UART_FCR_TRIGGER_1;
} }

View file

@ -56,11 +56,11 @@
struct dw8250_data { struct dw8250_data {
int last_lcr; u8 usr_reg;
int last_mcr; int last_mcr;
int line; int line;
struct clk *clk; struct clk *clk;
u8 usr_reg; struct uart_8250_dma dma;
}; };
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
@ -76,17 +76,33 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
return value; return value;
} }
static void dw8250_force_idle(struct uart_port *p)
{
serial8250_clear_and_reinit_fifos(container_of
(p, struct uart_8250_port, port));
(void)p->serial_in(p, UART_RX);
}
static void dw8250_serial_out(struct uart_port *p, int offset, int value) static void dw8250_serial_out(struct uart_port *p, int offset, int value)
{ {
struct dw8250_data *d = p->private_data; struct dw8250_data *d = p->private_data;
if (offset == UART_LCR)
d->last_lcr = value;
if (offset == UART_MCR) if (offset == UART_MCR)
d->last_mcr = value; d->last_mcr = value;
writeb(value, p->membase + (offset << p->regshift)); writeb(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */
if (offset == UART_LCR) {
int tries = 1000;
while (tries--) {
if (value == p->serial_in(p, UART_LCR))
return;
dw8250_force_idle(p);
writeb(value, p->membase + (UART_LCR << p->regshift));
}
dev_err(p->dev, "Couldn't set LCR to %d\n", value);
}
} }
static unsigned int dw8250_serial_in(struct uart_port *p, int offset) static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
@ -107,13 +123,22 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
{ {
struct dw8250_data *d = p->private_data; struct dw8250_data *d = p->private_data;
if (offset == UART_LCR)
d->last_lcr = value;
if (offset == UART_MCR) if (offset == UART_MCR)
d->last_mcr = value; d->last_mcr = value;
writel(value, p->membase + (offset << p->regshift)); writel(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */
if (offset == UART_LCR) {
int tries = 1000;
while (tries--) {
if (value == p->serial_in(p, UART_LCR))
return;
dw8250_force_idle(p);
writel(value, p->membase + (UART_LCR << p->regshift));
}
dev_err(p->dev, "Couldn't set LCR to %d\n", value);
}
} }
static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
@ -131,9 +156,8 @@ static int dw8250_handle_irq(struct uart_port *p)
if (serial8250_handle_irq(p, iir)) { if (serial8250_handle_irq(p, iir)) {
return 1; return 1;
} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
/* Clear the USR and write the LCR again. */ /* Clear the USR */
(void)p->serial_in(p, d->usr_reg); (void)p->serial_in(p, d->usr_reg);
p->serial_out(p, UART_LCR, d->last_lcr);
return 1; return 1;
} }
@ -153,6 +177,14 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
pm_runtime_put_sync_suspend(port->dev); pm_runtime_put_sync_suspend(port->dev);
} }
static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
{
struct dw8250_data *data = param;
return chan->chan_id == data->dma.tx_chan_id ||
chan->chan_id == data->dma.rx_chan_id;
}
static void dw8250_setup_port(struct uart_8250_port *up) static void dw8250_setup_port(struct uart_8250_port *up)
{ {
struct uart_port *p = &up->port; struct uart_port *p = &up->port;
@ -241,7 +273,8 @@ static int dw8250_probe_of(struct uart_port *p,
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static int dw8250_probe_acpi(struct uart_8250_port *up) static int dw8250_probe_acpi(struct uart_8250_port *up,
struct dw8250_data *data)
{ {
const struct acpi_device_id *id; const struct acpi_device_id *id;
struct uart_port *p = &up->port; struct uart_port *p = &up->port;
@ -260,9 +293,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up)
if (!p->uartclk) if (!p->uartclk)
p->uartclk = (unsigned int)id->driver_data; p->uartclk = (unsigned int)id->driver_data;
up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL); up->dma = &data->dma;
if (!up->dma)
return -ENOMEM;
up->dma->rxconf.src_maxburst = p->fifosize / 4; up->dma->rxconf.src_maxburst = p->fifosize / 4;
up->dma->txconf.dst_maxburst = p->fifosize / 4; up->dma->txconf.dst_maxburst = p->fifosize / 4;
@ -270,7 +301,8 @@ static int dw8250_probe_acpi(struct uart_8250_port *up)
return 0; return 0;
} }
#else #else
static inline int dw8250_probe_acpi(struct uart_8250_port *up) static inline int dw8250_probe_acpi(struct uart_8250_port *up,
struct dw8250_data *data)
{ {
return -ENODEV; return -ENODEV;
} }
@ -314,6 +346,12 @@ static int dw8250_probe(struct platform_device *pdev)
uart.port.uartclk = clk_get_rate(data->clk); uart.port.uartclk = clk_get_rate(data->clk);
} }
data->dma.rx_chan_id = -1;
data->dma.tx_chan_id = -1;
data->dma.rx_param = data;
data->dma.tx_param = data;
data->dma.fn = dw8250_dma_filter;
uart.port.iotype = UPIO_MEM; uart.port.iotype = UPIO_MEM;
uart.port.serial_in = dw8250_serial_in; uart.port.serial_in = dw8250_serial_in;
uart.port.serial_out = dw8250_serial_out; uart.port.serial_out = dw8250_serial_out;
@ -324,7 +362,7 @@ static int dw8250_probe(struct platform_device *pdev)
if (err) if (err)
return err; return err;
} else if (ACPI_HANDLE(&pdev->dev)) { } else if (ACPI_HANDLE(&pdev->dev)) {
err = dw8250_probe_acpi(&uart); err = dw8250_probe_acpi(&uart, data);
if (err) if (err)
return err; return err;
} else { } else {

View file

@ -122,7 +122,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
up.port.dev = &pdev->dev; up.port.dev = &pdev->dev;
up.port.private_data = priv; up.port.private_data = priv;
clk_enable(priv->sclk); clk_prepare_enable(priv->sclk);
up.port.uartclk = clk_get_rate(priv->sclk); up.port.uartclk = clk_get_rate(priv->sclk);
up.port.iotype = UPIO_MEM32; up.port.iotype = UPIO_MEM32;
@ -134,7 +134,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
ret = serial8250_register_8250_port(&up); ret = serial8250_register_8250_port(&up);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "unable to register 8250 port\n"); dev_err(&pdev->dev, "unable to register 8250 port\n");
clk_disable(priv->sclk); clk_disable_unprepare(priv->sclk);
return ret; return ret;
} }
@ -148,7 +148,7 @@ static int serial8250_em_remove(struct platform_device *pdev)
struct serial8250_em_priv *priv = platform_get_drvdata(pdev); struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
serial8250_unregister_port(priv->line); serial8250_unregister_port(priv->line);
clk_disable(priv->sclk); clk_disable_unprepare(priv->sclk);
return 0; return 0;
} }

View file

@ -9,6 +9,7 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License. * the Free Software Foundation; either version 2 of the License.
*/ */
#undef DEBUG
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
@ -27,8 +28,6 @@
#include "8250.h" #include "8250.h"
#undef SERIAL_DEBUG_PCI
/* /*
* init function returns: * init function returns:
* > 0 - number of ports * > 0 - number of ports
@ -63,7 +62,7 @@ static int pci_default_setup(struct serial_private*,
static void moan_device(const char *str, struct pci_dev *dev) static void moan_device(const char *str, struct pci_dev *dev)
{ {
printk(KERN_WARNING dev_err(&dev->dev,
"%s: %s\n" "%s: %s\n"
"Please send the output of lspci -vv, this\n" "Please send the output of lspci -vv, this\n"
"message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
@ -233,7 +232,7 @@ static int pci_inteli960ni_init(struct pci_dev *dev)
/* is firmware started? */ /* is firmware started? */
pci_read_config_dword(dev, 0x44, (void *)&oldval); pci_read_config_dword(dev, 0x44, (void *)&oldval);
if (oldval == 0x00001000L) { /* RESET value */ if (oldval == 0x00001000L) { /* RESET value */
printk(KERN_DEBUG "Local i960 firmware missing"); dev_dbg(&dev->dev, "Local i960 firmware missing\n");
return -ENODEV; return -ENODEV;
} }
return 0; return 0;
@ -827,7 +826,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev)
if (sub_serports > 0) { if (sub_serports > 0) {
return sub_serports; return sub_serports;
} else { } else {
printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); dev_err(&dev->dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
return 0; return 0;
} }
} }
@ -931,7 +930,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
} }
if (!inta_addr[i]) { if (!inta_addr[i]) {
printk(KERN_ERR "ite887x: could not find iobase\n"); dev_err(&dev->dev, "ite887x: could not find iobase\n");
return -ENODEV; return -ENODEV;
} }
@ -1024,9 +1023,9 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
/* Tornado device */ /* Tornado device */
if (deviceID == 0x07000200) { if (deviceID == 0x07000200) {
number_uarts = ioread8(p + 4); number_uarts = ioread8(p + 4);
printk(KERN_DEBUG dev_dbg(&dev->dev,
"%d ports detected on Oxford PCI Express device\n", "%d ports detected on Oxford PCI Express device\n",
number_uarts); number_uarts);
} }
pci_iounmap(dev, p); pci_iounmap(dev, p);
return number_uarts; return number_uarts;
@ -1308,6 +1307,29 @@ static int pci_default_setup(struct serial_private *priv,
return setup_port(priv, port, bar, offset, board->reg_shift); return setup_port(priv, port, bar, offset, board->reg_shift);
} }
static int pci_pericom_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
unsigned int bar, offset = board->first_offset, maxnr;
bar = FL_GET_BASE(board->flags);
if (board->flags & FL_BASE_BARS)
bar += idx;
else
offset += idx * board->uart_offset;
maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
(board->reg_shift + 3);
if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
return 1;
port->port.uartclk = 14745600;
return setup_port(priv, port, bar, offset, board->reg_shift);
}
static int static int
ce4100_serial_setup(struct serial_private *priv, ce4100_serial_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
@ -1324,6 +1346,120 @@ ce4100_serial_setup(struct serial_private *priv,
return ret; return ret;
} }
#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a
#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c
#define BYT_PRV_CLK 0x800
#define BYT_PRV_CLK_EN (1 << 0)
#define BYT_PRV_CLK_M_VAL_SHIFT 1
#define BYT_PRV_CLK_N_VAL_SHIFT 16
#define BYT_PRV_CLK_UPDATE (1 << 31)
#define BYT_GENERAL_REG 0x808
#define BYT_GENERAL_DIS_RTS_N_OVERRIDE (1 << 3)
#define BYT_TX_OVF_INT 0x820
#define BYT_TX_OVF_INT_MASK (1 << 1)
static void
byt_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
unsigned int m = 6912;
unsigned int n = 15625;
u32 reg;
/* For baud rates 1M, 2M, 3M and 4M the dividers must be adjusted. */
if (baud == 1000000 || baud == 2000000 || baud == 4000000) {
m = 64;
n = 100;
p->uartclk = 64000000;
} else if (baud == 3000000) {
m = 48;
n = 100;
p->uartclk = 48000000;
} else {
p->uartclk = 44236800;
}
/* Reset the clock */
reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
writel(reg, p->membase + BYT_PRV_CLK);
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK);
/*
* If auto-handshake mechanism is not enabled,
* disable rts_n override
*/
reg = readl(p->membase + BYT_GENERAL_REG);
reg &= ~BYT_GENERAL_DIS_RTS_N_OVERRIDE;
if (termios->c_cflag & CRTSCTS)
reg |= BYT_GENERAL_DIS_RTS_N_OVERRIDE;
writel(reg, p->membase + BYT_GENERAL_REG);
serial8250_do_set_termios(p, termios, old);
}
static bool byt_dma_filter(struct dma_chan *chan, void *param)
{
return chan->chan_id == *(int *)param;
}
static int
byt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
struct uart_8250_dma *dma;
int ret;
dma = devm_kzalloc(port->port.dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
return -ENOMEM;
switch (priv->dev->device) {
case PCI_DEVICE_ID_INTEL_BYT_UART1:
dma->rx_chan_id = 3;
dma->tx_chan_id = 2;
break;
case PCI_DEVICE_ID_INTEL_BYT_UART2:
dma->rx_chan_id = 5;
dma->tx_chan_id = 4;
break;
default:
return -EINVAL;
}
dma->rxconf.slave_id = dma->rx_chan_id;
dma->rxconf.src_maxburst = 16;
dma->txconf.slave_id = dma->tx_chan_id;
dma->txconf.dst_maxburst = 16;
dma->fn = byt_dma_filter;
dma->rx_param = &dma->rx_chan_id;
dma->tx_param = &dma->tx_chan_id;
ret = pci_default_setup(priv, board, port, idx);
port->port.iotype = UPIO_MEM;
port->port.type = PORT_16550A;
port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
port->port.set_termios = byt_set_termios;
port->port.fifosize = 64;
port->tx_loadsz = 64;
port->dma = dma;
port->capabilities = UART_CAP_FIFO | UART_CAP_AFE;
/* Disable Tx counter interrupts */
writel(BYT_TX_OVF_INT_MASK, port->port.membase + BYT_TX_OVF_INT);
return ret;
}
static int static int
pci_omegapci_setup(struct serial_private *priv, pci_omegapci_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
@ -1344,17 +1480,80 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
return ret; return ret;
} }
static int pci_fintek_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
struct pci_dev *pdev = priv->dev;
unsigned long base;
unsigned long iobase;
unsigned long ciobase = 0;
u8 config_base;
/*
* We are supposed to be able to read these from the PCI config space,
* but the values there don't seem to match what we need to use, so
* just use these hard-coded values for now, as they are correct.
*/
switch (idx) {
case 0: iobase = 0xe000; config_base = 0x40; break;
case 1: iobase = 0xe008; config_base = 0x48; break;
case 2: iobase = 0xe010; config_base = 0x50; break;
case 3: iobase = 0xe018; config_base = 0x58; break;
case 4: iobase = 0xe020; config_base = 0x60; break;
case 5: iobase = 0xe028; config_base = 0x68; break;
case 6: iobase = 0xe030; config_base = 0x70; break;
case 7: iobase = 0xe038; config_base = 0x78; break;
case 8: iobase = 0xe040; config_base = 0x80; break;
case 9: iobase = 0xe048; config_base = 0x88; break;
case 10: iobase = 0xe050; config_base = 0x90; break;
case 11: iobase = 0xe058; config_base = 0x98; break;
default:
/* Unknown number of ports, get out of here */
return -EINVAL;
}
if (idx < 4) {
base = pci_resource_start(priv->dev, 3);
ciobase = (int)(base + (0x8 * idx));
}
dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n",
__func__, idx, iobase, ciobase, config_base);
/* Enable UART I/O port */
pci_write_config_byte(pdev, config_base + 0x00, 0x01);
/* Select 128-byte FIFO and 8x FIFO threshold */
pci_write_config_byte(pdev, config_base + 0x01, 0x33);
/* LSB UART */
pci_write_config_byte(pdev, config_base + 0x04, (u8)(iobase & 0xff));
/* MSB UART */
pci_write_config_byte(pdev, config_base + 0x05, (u8)((iobase & 0xff00) >> 8));
/* irq number, this usually fails, but the spec says to do it anyway. */
pci_write_config_byte(pdev, config_base + 0x06, pdev->irq);
port->port.iotype = UPIO_PORT;
port->port.iobase = iobase;
port->port.mapbase = 0;
port->port.membase = NULL;
port->port.regshift = 0;
return 0;
}
static int skip_tx_en_setup(struct serial_private *priv, static int skip_tx_en_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
struct uart_8250_port *port, int idx) struct uart_8250_port *port, int idx)
{ {
port->port.flags |= UPF_NO_TXEN_TEST; port->port.flags |= UPF_NO_TXEN_TEST;
printk(KERN_DEBUG "serial8250: skipping TxEn test for device " dev_dbg(&priv->dev->dev,
"[%04x:%04x] subsystem [%04x:%04x]\n", "serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n",
priv->dev->vendor, priv->dev->vendor, priv->dev->device,
priv->dev->device, priv->dev->subsystem_vendor, priv->dev->subsystem_device);
priv->dev->subsystem_vendor,
priv->dev->subsystem_device);
return pci_default_setup(priv, board, port, idx); return pci_default_setup(priv, board, port, idx);
} }
@ -1662,6 +1861,20 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = kt_serial_setup, .setup = kt_serial_setup,
}, },
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BYT_UART1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_BYT_UART2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = byt_serial_setup,
},
/* /*
* ITE * ITE
*/ */
@ -1825,6 +2038,31 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = pci_plx9050_exit, .exit = pci_plx9050_exit,
}, },
/*
* Pericom
*/
{
.vendor = 0x12d8,
.device = 0x7952,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup,
},
{
.vendor = 0x12d8,
.device = 0x7954,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup,
},
{
.vendor = 0x12d8,
.device = 0x7958,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup,
},
/* /*
* PLX * PLX
*/ */
@ -2255,6 +2493,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = pci_brcm_trumanage_setup, .setup = pci_brcm_trumanage_setup,
}, },
{
.vendor = 0x1c29,
.device = 0x1104,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fintek_setup,
},
{
.vendor = 0x1c29,
.device = 0x1108,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fintek_setup,
},
{
.vendor = 0x1c29,
.device = 0x1112,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fintek_setup,
},
/* /*
* Default "match everything" terminator entry * Default "match everything" terminator entry
@ -2449,9 +2708,13 @@ enum pci_board_num_t {
pbn_ADDIDATA_PCIe_4_3906250, pbn_ADDIDATA_PCIe_4_3906250,
pbn_ADDIDATA_PCIe_8_3906250, pbn_ADDIDATA_PCIe_8_3906250,
pbn_ce4100_1_115200, pbn_ce4100_1_115200,
pbn_byt,
pbn_omegapci, pbn_omegapci,
pbn_NETMOS9900_2s_115200, pbn_NETMOS9900_2s_115200,
pbn_brcm_trumanage, pbn_brcm_trumanage,
pbn_fintek_4,
pbn_fintek_8,
pbn_fintek_12,
}; };
/* /*
@ -3185,6 +3448,13 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 921600, .base_baud = 921600,
.reg_shift = 2, .reg_shift = 2,
}, },
[pbn_byt] = {
.flags = FL_BASE0,
.num_ports = 1,
.base_baud = 2764800,
.uart_offset = 0x80,
.reg_shift = 2,
},
[pbn_omegapci] = { [pbn_omegapci] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 8, .num_ports = 8,
@ -3202,6 +3472,24 @@ static struct pciserial_board pci_boards[] = {
.reg_shift = 2, .reg_shift = 2,
.base_baud = 115200, .base_baud = 115200,
}, },
[pbn_fintek_4] = {
.num_ports = 4,
.uart_offset = 8,
.base_baud = 115200,
.first_offset = 0x40,
},
[pbn_fintek_8] = {
.num_ports = 8,
.uart_offset = 8,
.base_baud = 115200,
.first_offset = 0x40,
},
[pbn_fintek_12] = {
.num_ports = 12,
.uart_offset = 8,
.base_baud = 115200,
.first_offset = 0x40,
},
}; };
static const struct pci_device_id blacklist[] = { static const struct pci_device_id blacklist[] = {
@ -3362,14 +3650,15 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
if (quirk->setup(priv, board, &uart, i)) if (quirk->setup(priv, board, &uart, i))
break; break;
#ifdef SERIAL_DEBUG_PCI dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n", uart.port.iobase, uart.port.irq, uart.port.iotype);
uart.port.iobase, uart.port.irq, uart.port.iotype);
#endif
priv->line[i] = serial8250_register_8250_port(&uart); priv->line[i] = serial8250_register_8250_port(&uart);
if (priv->line[i] < 0) { if (priv->line[i] < 0) {
printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]); dev_err(&dev->dev,
"Couldn't register serial port %lx, irq %d, type %d, error %d\n",
uart.port.iobase, uart.port.irq,
uart.port.iotype, priv->line[i]);
break; break;
} }
} }
@ -3462,7 +3751,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
} }
if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n", dev_err(&dev->dev, "invalid driver_data: %ld\n",
ent->driver_data); ent->driver_data);
return -EINVAL; return -EINVAL;
} }
@ -3520,8 +3809,6 @@ static void pciserial_remove_one(struct pci_dev *dev)
{ {
struct serial_private *priv = pci_get_drvdata(dev); struct serial_private *priv = pci_get_drvdata(dev);
pci_set_drvdata(dev, NULL);
pciserial_remove_ports(priv); pciserial_remove_ports(priv);
pci_disable_device(dev); pci_disable_device(dev);
@ -3555,7 +3842,7 @@ static int pciserial_resume_one(struct pci_dev *dev)
err = pci_enable_device(dev); err = pci_enable_device(dev);
/* FIXME: We cannot simply error out here */ /* FIXME: We cannot simply error out here */
if (err) if (err)
printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n"); dev_err(&dev->dev, "Unable to re-enable ports, trying to continue.\n");
pciserial_resume_ports(priv); pciserial_resume_ports(priv);
} }
return 0; return 0;
@ -4848,6 +5135,15 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_ce4100_1_115200 }, pbn_ce4100_1_115200 },
/* Intel BayTrail */
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART1,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART2,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
pbn_byt },
/* /*
* Cronyx Omega PCI * Cronyx Omega PCI
@ -4918,6 +5214,11 @@ static struct pci_device_id serial_pci_tbl[] = {
0, 0,
0, pbn_exar_XR17V358 }, 0, pbn_exar_XR17V358 },
/* Fintek PCI serial cards */
{ PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
/* /*
* These entries match devices with class COMMUNICATION_SERIAL, * These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL

View file

@ -709,7 +709,7 @@ config SERIAL_IP22_ZILOG_CONSOLE
config SERIAL_SH_SCI config SERIAL_SH_SCI
tristate "SuperH SCI(F) serial port support" tristate "SuperH SCI(F) serial port support"
depends on HAVE_CLK && (SUPERH || ARCH_SHMOBILE) depends on HAVE_CLK && (SUPERH || ARM || COMPILE_TEST)
select SERIAL_CORE select SERIAL_CORE
config SERIAL_SH_SCI_NR_UARTS config SERIAL_SH_SCI_NR_UARTS
@ -1512,6 +1512,7 @@ config SERIAL_FSL_LPUART_CONSOLE
config SERIAL_ST_ASC config SERIAL_ST_ASC
tristate "ST ASC serial port support" tristate "ST ASC serial port support"
select SERIAL_CORE select SERIAL_CORE
depends on ARM || COMPILE_TEST
help help
This driver is for the on-chip Asychronous Serial Controller on This driver is for the on-chip Asychronous Serial Controller on
STMicroelectronics STi SoCs. STMicroelectronics STi SoCs.

View file

@ -728,7 +728,6 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
amba_set_drvdata(dev, uap); amba_set_drvdata(dev, uap);
ret = uart_add_one_port(&amba_reg, &uap->port); ret = uart_add_one_port(&amba_reg, &uap->port);
if (ret) { if (ret) {
amba_set_drvdata(dev, NULL);
amba_ports[i] = NULL; amba_ports[i] = NULL;
clk_put(uap->clk); clk_put(uap->clk);
unmap: unmap:
@ -745,8 +744,6 @@ static int pl010_remove(struct amba_device *dev)
struct uart_amba_port *uap = amba_get_drvdata(dev); struct uart_amba_port *uap = amba_get_drvdata(dev);
int i; int i;
amba_set_drvdata(dev, NULL);
uart_remove_one_port(&amba_reg, &uap->port); uart_remove_one_port(&amba_reg, &uap->port);
for (i = 0; i < ARRAY_SIZE(amba_ports); i++) for (i = 0; i < ARRAY_SIZE(amba_ports); i++)

View file

@ -2147,7 +2147,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
amba_set_drvdata(dev, uap); amba_set_drvdata(dev, uap);
ret = uart_add_one_port(&amba_reg, &uap->port); ret = uart_add_one_port(&amba_reg, &uap->port);
if (ret) { if (ret) {
amba_set_drvdata(dev, NULL);
amba_ports[i] = NULL; amba_ports[i] = NULL;
pl011_dma_remove(uap); pl011_dma_remove(uap);
} }
@ -2160,8 +2159,6 @@ static int pl011_remove(struct amba_device *dev)
struct uart_amba_port *uap = amba_get_drvdata(dev); struct uart_amba_port *uap = amba_get_drvdata(dev);
int i; int i;
amba_set_drvdata(dev, NULL);
uart_remove_one_port(&amba_reg, &uap->port); uart_remove_one_port(&amba_reg, &uap->port);
for (i = 0; i < ARRAY_SIZE(amba_ports); i++) for (i = 0; i < ARRAY_SIZE(amba_ports); i++)

View file

@ -533,7 +533,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
unsigned long *plat_data; unsigned long *plat_data;
struct arc_uart_port *uart = &arc_uart_ports[dev_id]; struct arc_uart_port *uart = &arc_uart_ports[dev_id];
plat_data = (unsigned long *)dev_get_platdata(&pdev->dev); plat_data = dev_get_platdata(&pdev->dev);
if (!plat_data) if (!plat_data)
return -ENODEV; return -ENODEV;

View file

@ -99,6 +99,7 @@ static void atmel_stop_rx(struct uart_port *port);
#define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR)
#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR) #define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR)
#define UART_GET_IP_NAME(port) __raw_readl((port)->membase + ATMEL_US_NAME) #define UART_GET_IP_NAME(port) __raw_readl((port)->membase + ATMEL_US_NAME)
#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
/* PDC registers */ /* PDC registers */
#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
@ -1503,6 +1504,7 @@ static void atmel_get_ip_name(struct uart_port *port)
{ {
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
int name = UART_GET_IP_NAME(port); int name = UART_GET_IP_NAME(port);
u32 version;
int usart, uart; int usart, uart;
/* usart and uart ascii */ /* usart and uart ascii */
usart = 0x55534152; usart = 0x55534152;
@ -1517,7 +1519,22 @@ static void atmel_get_ip_name(struct uart_port *port)
dev_dbg(port->dev, "This is uart\n"); dev_dbg(port->dev, "This is uart\n");
atmel_port->is_usart = false; atmel_port->is_usart = false;
} else { } else {
dev_err(port->dev, "Not supported ip name, set to uart\n"); /* fallback for older SoCs: use version field */
version = UART_GET_IP_VERSION(port);
switch (version) {
case 0x302:
case 0x10213:
dev_dbg(port->dev, "This version is usart\n");
atmel_port->is_usart = true;
break;
case 0x203:
case 0x10202:
dev_dbg(port->dev, "This version is uart\n");
atmel_port->is_usart = false;
break;
default:
dev_err(port->dev, "Not supported ip name nor version, set to uart\n");
}
} }
} }

View file

@ -766,9 +766,8 @@ static int sport_uart_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
ret = peripheral_request_list( ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
(unsigned short *)dev_get_platdata(&pdev->dev), DRV_NAME);
DRV_NAME);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Fail to request SPORT peripherals\n"); "Fail to request SPORT peripherals\n");
@ -844,8 +843,7 @@ static int sport_uart_probe(struct platform_device *pdev)
out_error_unmap: out_error_unmap:
iounmap(sport->port.membase); iounmap(sport->port.membase);
out_error_free_peripherals: out_error_free_peripherals:
peripheral_free_list( peripheral_free_list(dev_get_platdata(&pdev->dev));
(unsigned short *)dev_get_platdata(&pdev->dev));
out_error_free_mem: out_error_free_mem:
kfree(sport); kfree(sport);
bfin_sport_uart_ports[pdev->id] = NULL; bfin_sport_uart_ports[pdev->id] = NULL;
@ -864,8 +862,7 @@ static int sport_uart_remove(struct platform_device *pdev)
if (sport) { if (sport) {
uart_remove_one_port(&sport_uart_reg, &sport->port); uart_remove_one_port(&sport_uart_reg, &sport->port);
iounmap(sport->port.membase); iounmap(sport->port.membase);
peripheral_free_list( peripheral_free_list(dev_get_platdata(&pdev->dev));
(unsigned short *)dev_get_platdata(&pdev->dev));
kfree(sport); kfree(sport);
bfin_sport_uart_ports[pdev->id] = NULL; bfin_sport_uart_ports[pdev->id] = NULL;
} }

View file

@ -680,7 +680,7 @@ static int bfin_serial_startup(struct uart_port *port)
default: default:
uart_dma_ch_rx = uart_dma_ch_tx = 0; uart_dma_ch_rx = uart_dma_ch_tx = 0;
break; break;
}; }
if (uart_dma_ch_rx && if (uart_dma_ch_rx &&
request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) { request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) {
@ -726,7 +726,7 @@ static int bfin_serial_startup(struct uart_port *port)
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
if (uart->cts_pin >= 0) { if (uart->cts_pin >= 0) {
if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int, if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int,
IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) { 0, "BFIN_UART_MODEM_STATUS", uart)) {
uart->cts_pin = -1; uart->cts_pin = -1;
dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n"); dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n");
} }
@ -765,7 +765,7 @@ static void bfin_serial_shutdown(struct uart_port *port)
break; break;
default: default:
break; break;
}; }
#endif #endif
free_irq(uart->rx_irq, uart); free_irq(uart->rx_irq, uart);
free_irq(uart->tx_irq, uart); free_irq(uart->tx_irq, uart);
@ -1240,7 +1240,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
*/ */
#endif #endif
ret = peripheral_request_list( ret = peripheral_request_list(
(unsigned short *)dev_get_platdata(&pdev->dev), dev_get_platdata(&pdev->dev),
DRIVER_NAME); DRIVER_NAME);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
@ -1358,8 +1358,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
out_error_unmap: out_error_unmap:
iounmap(uart->port.membase); iounmap(uart->port.membase);
out_error_free_peripherals: out_error_free_peripherals:
peripheral_free_list( peripheral_free_list(dev_get_platdata(&pdev->dev));
(unsigned short *)dev_get_platdata(&pdev->dev));
out_error_free_mem: out_error_free_mem:
kfree(uart); kfree(uart);
bfin_serial_ports[pdev->id] = NULL; bfin_serial_ports[pdev->id] = NULL;
@ -1377,8 +1376,7 @@ static int bfin_serial_remove(struct platform_device *pdev)
if (uart) { if (uart) {
uart_remove_one_port(&bfin_serial_reg, &uart->port); uart_remove_one_port(&bfin_serial_reg, &uart->port);
iounmap(uart->port.membase); iounmap(uart->port.membase);
peripheral_free_list( peripheral_free_list(dev_get_platdata(&pdev->dev));
(unsigned short *)dev_get_platdata(&pdev->dev));
kfree(uart); kfree(uart);
bfin_serial_ports[pdev->id] = NULL; bfin_serial_ports[pdev->id] = NULL;
} }
@ -1432,8 +1430,8 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
return -ENOENT; return -ENOENT;
} }
ret = peripheral_request_list( ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
(unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME); DRIVER_NAME);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"fail to request bfin serial peripherals\n"); "fail to request bfin serial peripherals\n");
@ -1463,8 +1461,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
return 0; return 0;
out_error_free_peripherals: out_error_free_peripherals:
peripheral_free_list( peripheral_free_list(dev_get_platdata(&pdev->dev));
(unsigned short *)dev_get_platdata(&pdev->dev));
return ret; return ret;
} }

View file

@ -459,7 +459,6 @@ static int uart_clps711x_probe(struct platform_device *pdev)
ret = uart_register_driver(&s->uart); ret = uart_register_driver(&s->uart);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Registering UART driver failed\n"); dev_err(&pdev->dev, "Registering UART driver failed\n");
devm_clk_put(&pdev->dev, s->uart_clk);
return ret; return ret;
} }
@ -487,7 +486,6 @@ static int uart_clps711x_remove(struct platform_device *pdev)
for (i = 0; i < UART_CLPS711X_NR; i++) for (i = 0; i < UART_CLPS711X_NR; i++)
uart_remove_one_port(&s->uart, &s->port[i]); uart_remove_one_port(&s->uart, &s->port[i]);
devm_clk_put(&pdev->dev, s->uart_clk);
uart_unregister_driver(&s->uart); uart_unregister_driver(&s->uart);
return 0; return 0;

View file

@ -1008,7 +1008,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
return -ENODEV; return -ENODEV;
} }
pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev); pl_data = dev_get_platdata(&spi->dev);
if (!pl_data) { if (!pl_data) {
dev_err(&spi->dev, "missing platform data!"); dev_err(&spi->dev, "missing platform data!");
return -ENODEV; return -ENODEV;

View file

@ -223,8 +223,7 @@ struct imx_port {
struct dma_chan *dma_chan_rx, *dma_chan_tx; struct dma_chan *dma_chan_rx, *dma_chan_tx;
struct scatterlist rx_sgl, tx_sgl[2]; struct scatterlist rx_sgl, tx_sgl[2];
void *rx_buf; void *rx_buf;
unsigned int rx_bytes, tx_bytes; unsigned int tx_bytes;
struct work_struct tsk_dma_rx, tsk_dma_tx;
unsigned int dma_tx_nents; unsigned int dma_tx_nents;
wait_queue_head_t dma_wait; wait_queue_head_t dma_wait;
}; };
@ -505,34 +504,25 @@ static void dma_tx_callback(void *data)
dev_dbg(sport->port.dev, "exit in %s.\n", __func__); dev_dbg(sport->port.dev, "exit in %s.\n", __func__);
return; return;
} }
schedule_work(&sport->tsk_dma_tx);
} }
static void dma_tx_work(struct work_struct *w) static void imx_dma_tx(struct imx_port *sport)
{ {
struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx);
struct circ_buf *xmit = &sport->port.state->xmit; struct circ_buf *xmit = &sport->port.state->xmit;
struct scatterlist *sgl = sport->tx_sgl; struct scatterlist *sgl = sport->tx_sgl;
struct dma_async_tx_descriptor *desc; struct dma_async_tx_descriptor *desc;
struct dma_chan *chan = sport->dma_chan_tx; struct dma_chan *chan = sport->dma_chan_tx;
struct device *dev = sport->port.dev; struct device *dev = sport->port.dev;
enum dma_status status; enum dma_status status;
unsigned long flags;
int ret; int ret;
status = chan->device->device_tx_status(chan, (dma_cookie_t)0, NULL); status = dmaengine_tx_status(chan, (dma_cookie_t)0, NULL);
if (DMA_IN_PROGRESS == status) if (DMA_IN_PROGRESS == status)
return; return;
spin_lock_irqsave(&sport->port.lock, flags);
sport->tx_bytes = uart_circ_chars_pending(xmit); sport->tx_bytes = uart_circ_chars_pending(xmit);
if (sport->tx_bytes == 0) {
spin_unlock_irqrestore(&sport->port.lock, flags);
return;
}
if (xmit->tail > xmit->head) { if (xmit->tail > xmit->head && xmit->head > 0) {
sport->dma_tx_nents = 2; sport->dma_tx_nents = 2;
sg_init_table(sgl, 2); sg_init_table(sgl, 2);
sg_set_buf(sgl, xmit->buf + xmit->tail, sg_set_buf(sgl, xmit->buf + xmit->tail,
@ -542,7 +532,6 @@ static void dma_tx_work(struct work_struct *w)
sport->dma_tx_nents = 1; sport->dma_tx_nents = 1;
sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes); sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
} }
spin_unlock_irqrestore(&sport->port.lock, flags);
ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
if (ret == 0) { if (ret == 0) {
@ -609,11 +598,7 @@ static void imx_start_tx(struct uart_port *port)
} }
if (sport->dma_is_enabled) { if (sport->dma_is_enabled) {
/* imx_dma_tx(sport);
* We may in the interrupt context, so arise a work_struct to
* do the real job.
*/
schedule_work(&sport->tsk_dma_tx);
return; return;
} }
@ -732,6 +717,7 @@ out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int start_rx_dma(struct imx_port *sport);
/* /*
* If the RXFIFO is filled with some data, and then we * If the RXFIFO is filled with some data, and then we
* arise a DMA operation to receive them. * arise a DMA operation to receive them.
@ -750,7 +736,7 @@ static void imx_dma_rxint(struct imx_port *sport)
writel(temp, sport->port.membase + UCR1); writel(temp, sport->port.membase + UCR1);
/* tell the DMA to receive the data. */ /* tell the DMA to receive the data. */
schedule_work(&sport->tsk_dma_rx); start_rx_dma(sport);
} }
} }
@ -795,8 +781,15 @@ static irqreturn_t imx_int(int irq, void *dev_id)
static unsigned int imx_tx_empty(struct uart_port *port) static unsigned int imx_tx_empty(struct uart_port *port)
{ {
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
unsigned int ret;
return (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0; ret = (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0;
/* If the TX DMA is working, return 0. */
if (sport->dma_is_enabled && sport->dma_is_txing)
ret = 0;
return ret;
} }
/* /*
@ -865,22 +858,6 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
} }
#define RX_BUF_SIZE (PAGE_SIZE) #define RX_BUF_SIZE (PAGE_SIZE)
static int start_rx_dma(struct imx_port *sport);
static void dma_rx_work(struct work_struct *w)
{
struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx);
struct tty_port *port = &sport->port.state->port;
if (sport->rx_bytes) {
tty_insert_flip_string(port, sport->rx_buf, sport->rx_bytes);
tty_flip_buffer_push(port);
sport->rx_bytes = 0;
}
if (sport->dma_is_rxing)
start_rx_dma(sport);
}
static void imx_rx_dma_done(struct imx_port *sport) static void imx_rx_dma_done(struct imx_port *sport)
{ {
unsigned long temp; unsigned long temp;
@ -912,6 +889,7 @@ static void dma_rx_callback(void *data)
struct imx_port *sport = data; struct imx_port *sport = data;
struct dma_chan *chan = sport->dma_chan_rx; struct dma_chan *chan = sport->dma_chan_rx;
struct scatterlist *sgl = &sport->rx_sgl; struct scatterlist *sgl = &sport->rx_sgl;
struct tty_port *port = &sport->port.state->port;
struct dma_tx_state state; struct dma_tx_state state;
enum dma_status status; enum dma_status status;
unsigned int count; unsigned int count;
@ -919,13 +897,15 @@ static void dma_rx_callback(void *data)
/* unmap it first */ /* unmap it first */
dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE); dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE);
status = chan->device->device_tx_status(chan, (dma_cookie_t)0, &state); status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
count = RX_BUF_SIZE - state.residue; count = RX_BUF_SIZE - state.residue;
dev_dbg(sport->port.dev, "We get %d bytes.\n", count); dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (count) { if (count) {
sport->rx_bytes = count; tty_insert_flip_string(port, sport->rx_buf, count);
schedule_work(&sport->tsk_dma_rx); tty_flip_buffer_push(port);
start_rx_dma(sport);
} else } else
imx_rx_dma_done(sport); imx_rx_dma_done(sport);
} }
@ -1007,7 +987,6 @@ static int imx_uart_dma_init(struct imx_port *sport)
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
sport->rx_bytes = 0;
/* Prepare for TX : */ /* Prepare for TX : */
sport->dma_chan_tx = dma_request_slave_channel(dev, "tx"); sport->dma_chan_tx = dma_request_slave_channel(dev, "tx");
@ -1038,11 +1017,7 @@ err:
static void imx_enable_dma(struct imx_port *sport) static void imx_enable_dma(struct imx_port *sport)
{ {
unsigned long temp; unsigned long temp;
struct tty_port *port = &sport->port.state->port;
port->low_latency = 1;
INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);
INIT_WORK(&sport->tsk_dma_rx, dma_rx_work);
init_waitqueue_head(&sport->dma_wait); init_waitqueue_head(&sport->dma_wait);
/* set UCR1 */ /* set UCR1 */
@ -1063,7 +1038,6 @@ static void imx_enable_dma(struct imx_port *sport)
static void imx_disable_dma(struct imx_port *sport) static void imx_disable_dma(struct imx_port *sport)
{ {
unsigned long temp; unsigned long temp;
struct tty_port *port = &sport->port.state->port;
/* clear UCR1 */ /* clear UCR1 */
temp = readl(sport->port.membase + UCR1); temp = readl(sport->port.membase + UCR1);
@ -1081,7 +1055,6 @@ static void imx_disable_dma(struct imx_port *sport)
writel(temp, sport->port.membase + UCR4); writel(temp, sport->port.membase + UCR4);
sport->dma_is_enabled = 0; sport->dma_is_enabled = 0;
port->low_latency = 0;
} }
/* half the RX buffer size */ /* half the RX buffer size */
@ -1303,6 +1276,16 @@ static void imx_shutdown(struct uart_port *port)
clk_disable_unprepare(sport->clk_ipg); clk_disable_unprepare(sport->clk_ipg);
} }
static void imx_flush_buffer(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
if (sport->dma_is_enabled) {
sport->tx_bytes = 0;
dmaengine_terminate_all(sport->dma_chan_tx);
}
}
static void static void
imx_set_termios(struct uart_port *port, struct ktermios *termios, imx_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
@ -1539,7 +1522,7 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL; ret = -EINVAL;
if (sport->port.uartclk / 16 != ser->baud_base) if (sport->port.uartclk / 16 != ser->baud_base)
ret = -EINVAL; ret = -EINVAL;
if ((void *)sport->port.mapbase != ser->iomem_base) if (sport->port.mapbase != (unsigned long)ser->iomem_base)
ret = -EINVAL; ret = -EINVAL;
if (sport->port.iobase != ser->port) if (sport->port.iobase != ser->port)
ret = -EINVAL; ret = -EINVAL;
@ -1623,6 +1606,7 @@ static struct uart_ops imx_pops = {
.break_ctl = imx_break_ctl, .break_ctl = imx_break_ctl,
.startup = imx_startup, .startup = imx_startup,
.shutdown = imx_shutdown, .shutdown = imx_shutdown,
.flush_buffer = imx_flush_buffer,
.set_termios = imx_set_termios, .set_termios = imx_set_termios,
.type = imx_type, .type = imx_type,
.release_port = imx_release_port, .release_port = imx_release_port,

View file

@ -832,7 +832,7 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,
up->curregs[5] |= Tx8; up->curregs[5] |= Tx8;
up->parity_mask = 0xff; up->parity_mask = 0xff;
break; break;
}; }
up->curregs[4] &= ~0x0c; up->curregs[4] &= ~0x0c;
if (cflag & CSTOPB) if (cflag & CSTOPB)
up->curregs[4] |= SB2; up->curregs[4] |= SB2;

View file

@ -690,7 +690,7 @@ static void max310x_handle_tx(struct uart_port *port)
max310x_port_write(port, MAX310X_THR_REG, max310x_port_write(port, MAX310X_THR_REG,
xmit->buf[xmit->tail]); xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
}; }
} }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)

View file

@ -293,7 +293,7 @@ static void serial_hsu_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier); serial_out(up, UART_IER, up->ier);
} }
void hsu_dma_tx(struct uart_hsu_port *up) static void hsu_dma_tx(struct uart_hsu_port *up)
{ {
struct circ_buf *xmit = &up->port.state->xmit; struct circ_buf *xmit = &up->port.state->xmit;
struct hsu_dma_buffer *dbuf = &up->txbuf; struct hsu_dma_buffer *dbuf = &up->txbuf;
@ -340,7 +340,8 @@ void hsu_dma_tx(struct uart_hsu_port *up)
} }
/* The buffer is already cache coherent */ /* The buffer is already cache coherent */
void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) static void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc,
struct hsu_dma_buffer *dbuf)
{ {
dbuf->ofs = 0; dbuf->ofs = 0;
@ -386,7 +387,8 @@ static void serial_hsu_stop_tx(struct uart_port *port)
/* This is always called in spinlock protected mode, so /* This is always called in spinlock protected mode, so
* modify timeout timer is safe here */ * modify timeout timer is safe here */
void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts, unsigned long *flags) static void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts,
unsigned long *flags)
{ {
struct hsu_dma_buffer *dbuf = &up->rxbuf; struct hsu_dma_buffer *dbuf = &up->rxbuf;
struct hsu_dma_chan *chan = up->rxc; struct hsu_dma_chan *chan = up->rxc;
@ -1183,7 +1185,7 @@ static struct console serial_hsu_console = {
#define SERIAL_HSU_CONSOLE NULL #define SERIAL_HSU_CONSOLE NULL
#endif #endif
struct uart_ops serial_hsu_pops = { static struct uart_ops serial_hsu_pops = {
.tx_empty = serial_hsu_tx_empty, .tx_empty = serial_hsu_tx_empty,
.set_mctrl = serial_hsu_set_mctrl, .set_mctrl = serial_hsu_set_mctrl,
.get_mctrl = serial_hsu_get_mctrl, .get_mctrl = serial_hsu_get_mctrl,
@ -1451,7 +1453,6 @@ static void serial_hsu_remove(struct pci_dev *pdev)
uart_remove_one_port(&serial_hsu_reg, &up->port); uart_remove_one_port(&serial_hsu_reg, &up->port);
} }
pci_set_drvdata(pdev, NULL);
free_irq(pdev->irq, priv); free_irq(pdev->irq, priv);
pci_disable_device(pdev); pci_disable_device(pdev);
} }
@ -1504,4 +1505,4 @@ module_init(hsu_pci_init);
module_exit(hsu_pci_exit); module_exit(hsu_pci_exit);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:medfield-hsu"); MODULE_DEVICE_TABLE(pci, pci_ids);

View file

@ -1301,7 +1301,6 @@ static struct uart_ops mpc52xx_uart_ops = {
.shutdown = mpc52xx_uart_shutdown, .shutdown = mpc52xx_uart_shutdown,
.set_termios = mpc52xx_uart_set_termios, .set_termios = mpc52xx_uart_set_termios,
/* .pm = mpc52xx_uart_pm, Not supported yet */ /* .pm = mpc52xx_uart_pm, Not supported yet */
/* .set_wake = mpc52xx_uart_set_wake, Not supported yet */
.type = mpc52xx_uart_type, .type = mpc52xx_uart_type,
.release_port = mpc52xx_uart_release_port, .release_port = mpc52xx_uart_release_port,
.request_port = mpc52xx_uart_request_port, .request_port = mpc52xx_uart_request_port,
@ -1766,7 +1765,7 @@ mpc52xx_uart_of_remove(struct platform_device *op)
static int static int
mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state)
{ {
struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); struct uart_port *port = platform_get_drvdata(op);
if (port) if (port)
uart_suspend_port(&mpc52xx_uart_driver, port); uart_suspend_port(&mpc52xx_uart_driver, port);
@ -1777,7 +1776,7 @@ mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state)
static int static int
mpc52xx_uart_of_resume(struct platform_device *op) mpc52xx_uart_of_resume(struct platform_device *op)
{ {
struct uart_port *port = (struct uart_port *) platform_get_drvdata(op); struct uart_port *port = platform_get_drvdata(op);
if (port) if (port)
uart_resume_port(&mpc52xx_uart_driver, port); uart_resume_port(&mpc52xx_uart_driver, port);

View file

@ -2030,7 +2030,7 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi,
{ {
struct mpsc_pdata *pdata; struct mpsc_pdata *pdata;
pdata = (struct mpsc_pdata *)dev_get_platdata(&pd->dev); pdata = dev_get_platdata(&pd->dev);
pi->port.uartclk = pdata->brg_clk_freq; pi->port.uartclk = pdata->brg_clk_freq;
pi->port.iotype = UPIO_MEM; pi->port.iotype = UPIO_MEM;

View file

@ -43,6 +43,7 @@
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/pm.h>
#include "mrst_max3110.h" #include "mrst_max3110.h"
@ -61,6 +62,7 @@ struct uart_max3110 {
struct task_struct *main_thread; struct task_struct *main_thread;
struct task_struct *read_thread; struct task_struct *read_thread;
struct mutex thread_mutex; struct mutex thread_mutex;
struct mutex io_mutex;
u32 baud; u32 baud;
u16 cur_conf; u16 cur_conf;
@ -90,6 +92,7 @@ static int max3110_write_then_read(struct uart_max3110 *max,
struct spi_transfer x; struct spi_transfer x;
int ret; int ret;
mutex_lock(&max->io_mutex);
spi_message_init(&message); spi_message_init(&message);
memset(&x, 0, sizeof x); memset(&x, 0, sizeof x);
x.len = len; x.len = len;
@ -104,6 +107,7 @@ static int max3110_write_then_read(struct uart_max3110 *max,
/* Do the i/o */ /* Do the i/o */
ret = spi_sync(spi, &message); ret = spi_sync(spi, &message);
mutex_unlock(&max->io_mutex);
return ret; return ret;
} }
@ -491,19 +495,9 @@ static int serial_m3110_startup(struct uart_port *port)
port->state->port.low_latency = 1; port->state->port.low_latency = 1;
if (max->irq) { if (max->irq) {
max->read_thread = NULL; /* Enable RX IRQ only */
ret = request_irq(max->irq, serial_m3110_irq, config |= WC_RXA_IRQ_ENABLE;
IRQ_TYPE_EDGE_FALLING, "max3110", max); } else {
if (ret) {
max->irq = 0;
pr_err(PR_FMT "unable to allocate IRQ, polling\n");
} else {
/* Enable RX IRQ only */
config |= WC_RXA_IRQ_ENABLE;
}
}
if (max->irq == 0) {
/* If IRQ is disabled, start a read thread for input data */ /* If IRQ is disabled, start a read thread for input data */
max->read_thread = max->read_thread =
kthread_run(max3110_read_thread, max, "max3110_read"); kthread_run(max3110_read_thread, max, "max3110_read");
@ -517,8 +511,6 @@ static int serial_m3110_startup(struct uart_port *port)
ret = max3110_out(max, config); ret = max3110_out(max, config);
if (ret) { if (ret) {
if (max->irq)
free_irq(max->irq, max);
if (max->read_thread) if (max->read_thread)
kthread_stop(max->read_thread); kthread_stop(max->read_thread);
max->read_thread = NULL; max->read_thread = NULL;
@ -540,9 +532,6 @@ static void serial_m3110_shutdown(struct uart_port *port)
max->read_thread = NULL; max->read_thread = NULL;
} }
if (max->irq)
free_irq(max->irq, max);
/* Disable interrupts from this port */ /* Disable interrupts from this port */
config = WC_TAG | WC_SW_SHDI; config = WC_TAG | WC_SW_SHDI;
max3110_out(max, config); max3110_out(max, config);
@ -749,7 +738,8 @@ static int serial_m3110_suspend(struct device *dev)
struct spi_device *spi = to_spi_device(dev); struct spi_device *spi = to_spi_device(dev);
struct uart_max3110 *max = spi_get_drvdata(spi); struct uart_max3110 *max = spi_get_drvdata(spi);
disable_irq(max->irq); if (max->irq > 0)
disable_irq(max->irq);
uart_suspend_port(&serial_m3110_reg, &max->port); uart_suspend_port(&serial_m3110_reg, &max->port);
max3110_out(max, max->cur_conf | WC_SW_SHDI); max3110_out(max, max->cur_conf | WC_SW_SHDI);
return 0; return 0;
@ -762,7 +752,8 @@ static int serial_m3110_resume(struct device *dev)
max3110_out(max, max->cur_conf); max3110_out(max, max->cur_conf);
uart_resume_port(&serial_m3110_reg, &max->port); uart_resume_port(&serial_m3110_reg, &max->port);
enable_irq(max->irq); if (max->irq > 0)
enable_irq(max->irq);
return 0; return 0;
} }
@ -803,6 +794,7 @@ static int serial_m3110_probe(struct spi_device *spi)
max->irq = (u16)spi->irq; max->irq = (u16)spi->irq;
mutex_init(&max->thread_mutex); mutex_init(&max->thread_mutex);
mutex_init(&max->io_mutex);
max->word_7bits = 0; max->word_7bits = 0;
max->parity = 0; max->parity = 0;
@ -840,6 +832,16 @@ static int serial_m3110_probe(struct spi_device *spi)
goto err_kthread; goto err_kthread;
} }
if (max->irq) {
ret = request_irq(max->irq, serial_m3110_irq,
IRQ_TYPE_EDGE_FALLING, "max3110", max);
if (ret) {
max->irq = 0;
dev_warn(&spi->dev,
"unable to allocate IRQ, will use polling method\n");
}
}
spi_set_drvdata(spi, max); spi_set_drvdata(spi, max);
pmax = max; pmax = max;
@ -867,6 +869,9 @@ static int serial_m3110_remove(struct spi_device *dev)
free_page((unsigned long)max->con_xmit.buf); free_page((unsigned long)max->con_xmit.buf);
if (max->irq)
free_irq(max->irq, max);
if (max->main_thread) if (max->main_thread)
kthread_stop(max->main_thread); kthread_stop(max->main_thread);

View file

@ -39,6 +39,7 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#define MXS_AUART_PORTS 5 #define MXS_AUART_PORTS 5
#define MXS_AUART_FIFO_SIZE 16
#define AUART_CTRL0 0x00000000 #define AUART_CTRL0 0x00000000
#define AUART_CTRL0_SET 0x00000004 #define AUART_CTRL0_SET 0x00000004
@ -548,6 +549,9 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s)
s->flags |= MXS_AUART_DMA_ENABLED; s->flags |= MXS_AUART_DMA_ENABLED;
dev_dbg(s->dev, "enabled the DMA support."); dev_dbg(s->dev, "enabled the DMA support.");
/* The DMA buffer is now the FIFO the TTY subsystem can use */
s->port.fifosize = UART_XMIT_SIZE;
return 0; return 0;
err_out: err_out:
@ -741,6 +745,9 @@ static int mxs_auart_startup(struct uart_port *u)
writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN, writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
u->membase + AUART_INTR); u->membase + AUART_INTR);
/* Reset FIFO size (it could have changed if DMA was enabled) */
u->fifosize = MXS_AUART_FIFO_SIZE;
/* /*
* Enable fifo so all four bytes of a DMA word are written to * Enable fifo so all four bytes of a DMA word are written to
* output (otherwise, only the LSB is written, ie. 1 in 4 bytes) * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
@ -1056,7 +1063,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
s->port.membase = ioremap(r->start, resource_size(r)); s->port.membase = ioremap(r->start, resource_size(r));
s->port.ops = &mxs_auart_ops; s->port.ops = &mxs_auart_ops;
s->port.iotype = UPIO_MEM; s->port.iotype = UPIO_MEM;
s->port.fifosize = 16; s->port.fifosize = MXS_AUART_FIFO_SIZE;
s->port.uartclk = clk_get_rate(s->clk); s->port.uartclk = clk_get_rate(s->clk);
s->port.type = PORT_IMX; s->port.type = PORT_IMX;
s->port.dev = s->dev = &pdev->dev; s->port.dev = s->dev = &pdev->dev;

View file

@ -39,6 +39,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/platform_data/serial-omap.h> #include <linux/platform_data/serial-omap.h>
@ -134,6 +135,7 @@ struct uart_omap_port {
struct uart_port port; struct uart_port port;
struct uart_omap_dma uart_dma; struct uart_omap_dma uart_dma;
struct device *dev; struct device *dev;
int wakeirq;
unsigned char ier; unsigned char ier;
unsigned char lcr; unsigned char lcr;
@ -175,7 +177,7 @@ struct uart_omap_port {
bool is_suspending; bool is_suspending;
}; };
#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
@ -214,10 +216,23 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
return pdata->get_context_loss_count(up->dev); return pdata->get_context_loss_count(up->dev);
} }
static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up,
bool enable)
{
if (!up->wakeirq)
return;
if (enable)
enable_irq(up->wakeirq);
else
disable_irq(up->wakeirq);
}
static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
{ {
struct omap_uart_port_info *pdata = dev_get_platdata(up->dev); struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
serial_omap_enable_wakeirq(up, enable);
if (!pdata || !pdata->enable_wakeup) if (!pdata || !pdata->enable_wakeup)
return; return;
@ -242,12 +257,12 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
unsigned int n16 = port->uartclk / (16 * baud); unsigned int n16 = port->uartclk / (16 * baud);
int baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
int baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
if(baudAbsDiff13 < 0) if (baudAbsDiff13 < 0)
baudAbsDiff13 = -baudAbsDiff13; baudAbsDiff13 = -baudAbsDiff13;
if(baudAbsDiff16 < 0) if (baudAbsDiff16 < 0)
baudAbsDiff16 = -baudAbsDiff16; baudAbsDiff16 = -baudAbsDiff16;
return (baudAbsDiff13 > baudAbsDiff16); return (baudAbsDiff13 >= baudAbsDiff16);
} }
/* /*
@ -258,13 +273,13 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
static unsigned int static unsigned int
serial_omap_get_divisor(struct uart_port *port, unsigned int baud) serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
{ {
unsigned int divisor; unsigned int mode;
if (!serial_omap_baud_is_mode16(port, baud)) if (!serial_omap_baud_is_mode16(port, baud))
divisor = 13; mode = 13;
else else
divisor = 16; mode = 16;
return port->uartclk/(baud * divisor); return port->uartclk/(mode * baud);
} }
static void serial_omap_enable_ms(struct uart_port *port) static void serial_omap_enable_ms(struct uart_port *port)
@ -283,28 +298,40 @@ static void serial_omap_enable_ms(struct uart_port *port)
static void serial_omap_stop_tx(struct uart_port *port) static void serial_omap_stop_tx(struct uart_port *port)
{ {
struct uart_omap_port *up = to_uart_omap_port(port); struct uart_omap_port *up = to_uart_omap_port(port);
struct circ_buf *xmit = &up->port.state->xmit;
int res; int res;
pm_runtime_get_sync(up->dev); pm_runtime_get_sync(up->dev);
/* handle rs485 */ /* Handle RS-485 */
if (up->rs485.flags & SER_RS485_ENABLED) { if (up->rs485.flags & SER_RS485_ENABLED) {
/* do nothing if current tx not yet completed */ if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
res = serial_in(up, UART_LSR) & UART_LSR_TEMT; /* THR interrupt is fired when both TX FIFO and TX
if (!res) * shift register are empty. This means there's nothing
return; * left to transmit now, so make sure the THR interrupt
* is fired when TX FIFO is below the trigger level,
/* if there's no more data to send, turn off rts */ * disable THR interrupts and toggle the RS-485 GPIO
if (uart_circ_empty(xmit)) { * data direction pin if needed.
/* if rts not already disabled */ */
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
serial_out(up, UART_OMAP_SCR, up->scr);
res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0; res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
if (gpio_get_value(up->rts_gpio) != res) { if (gpio_get_value(up->rts_gpio) != res) {
if (up->rs485.delay_rts_after_send > 0) { if (up->rs485.delay_rts_after_send > 0)
mdelay(up->rs485.delay_rts_after_send); mdelay(up->rs485.delay_rts_after_send);
}
gpio_set_value(up->rts_gpio, res); gpio_set_value(up->rts_gpio, res);
} }
} else {
/* We're asked to stop, but there's still stuff in the
* UART FIFO, so make sure the THR interrupt is fired
* when both TX FIFO and TX shift register are empty.
* The next THR interrupt (if no transmission is started
* in the meantime) will indicate the end of a
* transmission. Therefore we _don't_ disable THR
* interrupts in this situation.
*/
up->scr |= OMAP_UART_SCR_TX_EMPTY;
serial_out(up, UART_OMAP_SCR, up->scr);
return;
} }
} }
@ -384,15 +411,18 @@ static void serial_omap_start_tx(struct uart_port *port)
pm_runtime_get_sync(up->dev); pm_runtime_get_sync(up->dev);
/* handle rs485 */ /* Handle RS-485 */
if (up->rs485.flags & SER_RS485_ENABLED) { if (up->rs485.flags & SER_RS485_ENABLED) {
/* Fire THR interrupts when FIFO is below trigger level */
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
serial_out(up, UART_OMAP_SCR, up->scr);
/* if rts not already enabled */ /* if rts not already enabled */
res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
if (gpio_get_value(up->rts_gpio) != res) { if (gpio_get_value(up->rts_gpio) != res) {
gpio_set_value(up->rts_gpio, res); gpio_set_value(up->rts_gpio, res);
if (up->rs485.delay_rts_before_send > 0) { if (up->rs485.delay_rts_before_send > 0)
mdelay(up->rs485.delay_rts_before_send); mdelay(up->rs485.delay_rts_before_send);
}
} }
} }
@ -699,6 +729,20 @@ static int serial_omap_startup(struct uart_port *port)
if (retval) if (retval)
return retval; return retval;
/* Optional wake-up IRQ */
if (up->wakeirq) {
retval = request_irq(up->wakeirq, serial_omap_irq,
up->port.irqflags, up->name, up);
if (retval) {
free_irq(up->port.irq, up);
return retval;
}
disable_irq(up->wakeirq);
} else {
dev_info(up->port.dev, "no wakeirq for uart%d\n",
up->port.line);
}
dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line); dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
pm_runtime_get_sync(up->dev); pm_runtime_get_sync(up->dev);
@ -787,6 +831,8 @@ static void serial_omap_shutdown(struct uart_port *port)
pm_runtime_mark_last_busy(up->dev); pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev); pm_runtime_put_autosuspend(up->dev);
free_irq(up->port.irq, up); free_irq(up->port.irq, up);
if (up->wakeirq)
free_irq(up->wakeirq, up);
} }
static void serial_omap_uart_qos_work(struct work_struct *work) static void serial_omap_uart_qos_work(struct work_struct *work)
@ -938,7 +984,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
*/ */
/* Set receive FIFO threshold to 16 characters and /* Set receive FIFO threshold to 16 characters and
* transmit FIFO threshold to 16 spaces * transmit FIFO threshold to 32 spaces
*/ */
up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK; up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK;
@ -1060,15 +1106,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
} }
static int serial_omap_set_wake(struct uart_port *port, unsigned int state)
{
struct uart_omap_port *up = to_uart_omap_port(port);
serial_omap_enable_wakeup(up, state);
return 0;
}
static void static void
serial_omap_pm(struct uart_port *port, unsigned int state, serial_omap_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate) unsigned int oldstate)
@ -1353,6 +1390,15 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
up->ier = mode; up->ier = mode;
serial_out(up, UART_IER, up->ier); serial_out(up, UART_IER, up->ier);
/* If RS-485 is disabled, make sure the THR interrupt is fired when
* TX FIFO is below the trigger level.
*/
if (!(up->rs485.flags & SER_RS485_ENABLED) &&
(up->scr & OMAP_UART_SCR_TX_EMPTY)) {
up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
serial_out(up, UART_OMAP_SCR, up->scr);
}
spin_unlock_irqrestore(&up->port.lock, flags); spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev); pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev); pm_runtime_put_autosuspend(up->dev);
@ -1401,7 +1447,6 @@ static struct uart_ops serial_omap_pops = {
.shutdown = serial_omap_shutdown, .shutdown = serial_omap_shutdown,
.set_termios = serial_omap_set_termios, .set_termios = serial_omap_set_termios,
.pm = serial_omap_pm, .pm = serial_omap_pm,
.set_wake = serial_omap_set_wake,
.type = serial_omap_type, .type = serial_omap_type,
.release_port = serial_omap_release_port, .release_port = serial_omap_release_port,
.request_port = serial_omap_request_port, .request_port = serial_omap_request_port,
@ -1582,11 +1627,23 @@ static int serial_omap_probe(struct platform_device *pdev)
struct uart_omap_port *up; struct uart_omap_port *up;
struct resource *mem, *irq; struct resource *mem, *irq;
struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev); struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev);
int ret; int ret, uartirq = 0, wakeirq = 0;
/* The optional wakeirq may be specified in the board dts file */
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
uartirq = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (!uartirq)
return -EPROBE_DEFER;
wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
omap_up_info = of_get_uart_port_info(&pdev->dev); omap_up_info = of_get_uart_port_info(&pdev->dev);
pdev->dev.platform_data = omap_up_info; pdev->dev.platform_data = omap_up_info;
} else {
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "no irq resource?\n");
return -ENODEV;
}
uartirq = irq->start;
} }
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -1595,12 +1652,6 @@ static int serial_omap_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "no irq resource?\n");
return -ENODEV;
}
if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
pdev->dev.driver->name)) { pdev->dev.driver->name)) {
dev_err(&pdev->dev, "memory region already claimed\n"); dev_err(&pdev->dev, "memory region already claimed\n");
@ -1634,7 +1685,8 @@ static int serial_omap_probe(struct platform_device *pdev)
up->port.dev = &pdev->dev; up->port.dev = &pdev->dev;
up->port.type = PORT_OMAP; up->port.type = PORT_OMAP;
up->port.iotype = UPIO_MEM; up->port.iotype = UPIO_MEM;
up->port.irq = irq->start; up->port.irq = uartirq;
up->wakeirq = wakeirq;
up->port.regshift = 2; up->port.regshift = 2;
up->port.fifosize = 64; up->port.fifosize = 64;
@ -1670,8 +1722,9 @@ static int serial_omap_probe(struct platform_device *pdev)
up->port.uartclk = omap_up_info->uartclk; up->port.uartclk = omap_up_info->uartclk;
if (!up->port.uartclk) { if (!up->port.uartclk) {
up->port.uartclk = DEFAULT_CLK_SPEED; up->port.uartclk = DEFAULT_CLK_SPEED;
dev_warn(&pdev->dev, "No clock speed specified: using default:" dev_warn(&pdev->dev,
"%d\n", DEFAULT_CLK_SPEED); "No clock speed specified: using default: %d\n",
DEFAULT_CLK_SPEED);
} }
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;

View file

@ -1614,7 +1614,6 @@ static struct uart_ops pch_uart_ops = {
.shutdown = pch_uart_shutdown, .shutdown = pch_uart_shutdown,
.set_termios = pch_uart_set_termios, .set_termios = pch_uart_set_termios,
/* .pm = pch_uart_pm, Not supported yet */ /* .pm = pch_uart_pm, Not supported yet */
/* .set_wake = pch_uart_set_wake, Not supported yet */
.type = pch_uart_type, .type = pch_uart_type,
.release_port = pch_uart_release_port, .release_port = pch_uart_release_port,
.request_port = pch_uart_request_port, .request_port = pch_uart_request_port,
@ -1996,6 +1995,8 @@ module_exit(pch_uart_module_exit);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver"); MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver");
MODULE_DEVICE_TABLE(pci, pch_uart_pci_id);
module_param(default_baud, uint, S_IRUGO); module_param(default_baud, uint, S_IRUGO);
MODULE_PARM_DESC(default_baud, MODULE_PARM_DESC(default_baud,
"Default BAUD for initial driver state and console (default 9600)"); "Default BAUD for initial driver state and console (default 9600)");

View file

@ -1072,7 +1072,7 @@ static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag,
uap->curregs[5] |= Tx8; uap->curregs[5] |= Tx8;
uap->parity_mask = 0xff; uap->parity_mask = 0xff;
break; break;
}; }
uap->curregs[4] &= ~(SB_MASK); uap->curregs[4] &= ~(SB_MASK);
if (cflag & CSTOPB) if (cflag & CSTOPB)
uap->curregs[4] |= SB2; uap->curregs[4] |= SB2;

View file

@ -647,7 +647,10 @@ void sa1100_register_uart_fns(struct sa1100_port_fns *fns)
sa1100_pops.set_mctrl = fns->set_mctrl; sa1100_pops.set_mctrl = fns->set_mctrl;
sa1100_pops.pm = fns->pm; sa1100_pops.pm = fns->pm;
sa1100_pops.set_wake = fns->set_wake; /*
* FIXME: fns->set_wake is unused - this should be called from
* the suspend() callback if device_may_wakeup(dev)) is set.
*/
} }
void __init sa1100_register_uart(int idx, int port) void __init sa1100_register_uart(int idx, int port)

View file

@ -407,7 +407,14 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
{ {
/* todo - possibly remove AFC and do manual CTS */ unsigned int umcon = rd_regl(port, S3C2410_UMCON);
if (mctrl & TIOCM_RTS)
umcon |= S3C2410_UMCOM_RTS_LOW;
else
umcon &= ~S3C2410_UMCOM_RTS_LOW;
wr_regl(port, S3C2410_UMCON, umcon);
} }
static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
@ -774,8 +781,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
if (termios->c_cflag & CSTOPB) if (termios->c_cflag & CSTOPB)
ulcon |= S3C2410_LCON_STOPB; ulcon |= S3C2410_LCON_STOPB;
umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;
if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARENB) {
if (termios->c_cflag & PARODD) if (termios->c_cflag & PARODD)
ulcon |= S3C2410_LCON_PODD; ulcon |= S3C2410_LCON_PODD;
@ -792,6 +797,15 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
wr_regl(port, S3C2410_ULCON, ulcon); wr_regl(port, S3C2410_ULCON, ulcon);
wr_regl(port, S3C2410_UBRDIV, quot); wr_regl(port, S3C2410_UBRDIV, quot);
umcon = rd_regl(port, S3C2410_UMCON);
if (termios->c_cflag & CRTSCTS) {
umcon |= S3C2410_UMCOM_AFC;
/* Disable RTS when RX FIFO contains 63 bytes */
umcon &= ~S3C2412_UMCON_AFC_8;
} else {
umcon &= ~S3C2410_UMCOM_AFC;
}
wr_regl(port, S3C2410_UMCON, umcon); wr_regl(port, S3C2410_UMCON, umcon);
if (ourport->info->has_divslot) if (ourport->info->has_divslot)
@ -1254,7 +1268,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
ourport->baudclk = ERR_PTR(-EINVAL); ourport->baudclk = ERR_PTR(-EINVAL);
ourport->info = ourport->drv_data->info; ourport->info = ourport->drv_data->info;
ourport->cfg = (dev_get_platdata(&pdev->dev)) ? ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
(struct s3c2410_uartcfg *)dev_get_platdata(&pdev->dev) : dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg; ourport->drv_data->def_cfg;
ourport->port.fifosize = (ourport->info->fifosize) ? ourport->port.fifosize = (ourport->info->fifosize) ?

View file

@ -63,7 +63,7 @@ struct s3c24xx_uart_port {
/* conversion functions */ /* conversion functions */
#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) #define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
/* register access controls */ /* register access controls */

View file

@ -986,6 +986,7 @@ static int sccnxp_probe(struct platform_device *pdev)
return 0; return 0;
} }
uart_unregister_driver(&s->uart);
err_out: err_out:
if (!IS_ERR(s->regulator)) if (!IS_ERR(s->regulator))
return regulator_disable(s->regulator); return regulator_disable(s->regulator);

View file

@ -1018,7 +1018,7 @@ static int tegra_uart_startup(struct uart_port *u)
goto fail_hw_init; goto fail_hw_init;
} }
ret = request_irq(u->irq, tegra_uart_isr, IRQF_DISABLED, ret = request_irq(u->irq, tegra_uart_isr, 0,
dev_name(u->dev), tup); dev_name(u->dev), tup);
if (ret < 0) { if (ret < 0) {
dev_err(u->dev, "Failed to register ISR for IRQ %d\n", u->irq); dev_err(u->dev, "Failed to register ISR for IRQ %d\n", u->irq);

View file

@ -1220,8 +1220,6 @@ static void pciserial_txx9_remove_one(struct pci_dev *dev)
{ {
struct uart_txx9_port *up = pci_get_drvdata(dev); struct uart_txx9_port *up = pci_get_drvdata(dev);
pci_set_drvdata(dev, NULL);
if (up) { if (up) {
serial_txx9_unregister_port(up->port.line); serial_txx9_unregister_port(up->port.line);
pci_disable_device(dev); pci_disable_device(dev);

View file

@ -529,7 +529,7 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param)
while (sirfport->rx_completed != sirfport->rx_issued) { while (sirfport->rx_completed != sirfport->rx_issued) {
sirfsoc_uart_insert_rx_buf_to_tty(sirfport, sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
SIRFSOC_RX_DMA_BUF_SIZE); SIRFSOC_RX_DMA_BUF_SIZE);
sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++); sirfport->rx_completed++;
sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT; sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
} }
count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head, count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head,
@ -706,12 +706,19 @@ static void sirfsoc_uart_rx_dma_complete_tl(unsigned long param)
{ {
struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param; struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
struct uart_port *port = &sirfport->port; struct uart_port *port = &sirfport->port;
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&sirfport->rx_lock, flags); spin_lock_irqsave(&sirfport->rx_lock, flags);
while (sirfport->rx_completed != sirfport->rx_issued) { while (sirfport->rx_completed != sirfport->rx_issued) {
sirfsoc_uart_insert_rx_buf_to_tty(sirfport, sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
SIRFSOC_RX_DMA_BUF_SIZE); SIRFSOC_RX_DMA_BUF_SIZE);
sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++); if (rd_regl(port, ureg->sirfsoc_int_en_reg) &
uint_en->sirfsoc_rx_timeout_en)
sirfsoc_rx_submit_one_dma_desc(port,
sirfport->rx_completed++);
else
sirfport->rx_completed++;
sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT; sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
} }
spin_unlock_irqrestore(&sirfport->rx_lock, flags); spin_unlock_irqrestore(&sirfport->rx_lock, flags);

View file

@ -368,15 +368,6 @@ struct sirfsoc_uart_register sirfsoc_uart = {
#define SIRFSOC_UART_NR 6 #define SIRFSOC_UART_NR 6
#define SIRFSOC_PORT_TYPE 0xa5 #define SIRFSOC_PORT_TYPE 0xa5
/* Baud Rate Calculation */
#define SIRF_MIN_SAMPLE_DIV 0xf
#define SIRF_MAX_SAMPLE_DIV 0x3f
#define SIRF_IOCLK_DIV_MAX 0xffff
#define SIRF_SAMPLE_DIV_SHIFT 16
#define SIRF_IOCLK_DIV_MASK 0xffff
#define SIRF_SAMPLE_DIV_MASK 0x3f0000
#define SIRF_BAUD_RATE_SUPPORT_NR 18
/* Uart Common Use Macro*/ /* Uart Common Use Macro*/
#define SIRFSOC_RX_DMA_BUF_SIZE 256 #define SIRFSOC_RX_DMA_BUF_SIZE 256
#define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3) #define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3)
@ -453,9 +444,6 @@ struct sirfsoc_uart_port {
int rx_issued; int rx_issued;
}; };
/* Hardware Flow Control */
#define SIRFUART_AFC_CTRL_RX_THD 0x70
/* Register Access Control */ /* Register Access Control */
#define portaddr(port, reg) ((port)->membase + (reg)) #define portaddr(port, reg) ((port)->membase + (reg))
#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))

View file

@ -894,7 +894,7 @@ static int sunsab_console_setup(struct console *con, char *options)
case B115200: baud = 115200; break; case B115200: baud = 115200; break;
case B230400: baud = 230400; break; case B230400: baud = 230400; break;
case B460800: baud = 460800; break; case B460800: baud = 460800; break;
}; }
/* /*
* Temporary fix. * Temporary fix.

View file

@ -522,7 +522,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break)
serio_interrupt(&up->serio, ch, 0); serio_interrupt(&up->serio, ch, 0);
#endif #endif
break; break;
}; }
} }
} while (serial_in(up, UART_LSR) & UART_LSR_DR); } while (serial_in(up, UART_LSR) & UART_LSR_DR);
} }

View file

@ -319,7 +319,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
serio_interrupt(&up->serio, ch, 0); serio_interrupt(&up->serio, ch, 0);
#endif #endif
break; break;
}; }
} }
} }
@ -897,7 +897,7 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
up->curregs[R5] |= Tx8; up->curregs[R5] |= Tx8;
up->parity_mask = 0xff; up->parity_mask = 0xff;
break; break;
}; }
up->curregs[R4] &= ~0x0c; up->curregs[R4] &= ~0x0c;
if (cflag & CSTOPB) if (cflag & CSTOPB)
up->curregs[R4] |= SB2; up->curregs[R4] |= SB2;
@ -1239,7 +1239,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
default: case B9600: baud = 9600; break; default: case B9600: baud = 9600; break;
case B19200: baud = 19200; break; case B19200: baud = 19200; break;
case B38400: baud = 38400; break; case B38400: baud = 38400; break;
}; }
brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);

View file

@ -269,7 +269,7 @@ static unsigned int qe_uart_tx_empty(struct uart_port *port)
return 1; return 1;
bdp++; bdp++;
}; }
} }
/* /*

View file

@ -1,7 +1,7 @@
/* /*
* Xilinx PS UART driver * Xilinx PS UART driver
* *
* 2011 (c) Xilinx Inc. * 2011 - 2013 (C) Xilinx Inc.
* *
* This program is free software; you can redistribute it * This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public * and/or modify it under the terms of the GNU General Public
@ -11,13 +11,17 @@
* *
*/ */
#if defined(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/console.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
#include <linux/console.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/io.h> #include <linux/io.h>
@ -29,12 +33,22 @@
#define XUARTPS_MAJOR 0 /* use dynamic node allocation */ #define XUARTPS_MAJOR 0 /* use dynamic node allocation */
#define XUARTPS_MINOR 0 /* works best with devtmpfs */ #define XUARTPS_MINOR 0 /* works best with devtmpfs */
#define XUARTPS_NR_PORTS 2 #define XUARTPS_NR_PORTS 2
#define XUARTPS_FIFO_SIZE 16 /* FIFO size */ #define XUARTPS_FIFO_SIZE 64 /* FIFO size */
#define XUARTPS_REGISTER_SPACE 0xFFF #define XUARTPS_REGISTER_SPACE 0xFFF
#define xuartps_readl(offset) ioread32(port->membase + offset) #define xuartps_readl(offset) ioread32(port->membase + offset)
#define xuartps_writel(val, offset) iowrite32(val, port->membase + offset) #define xuartps_writel(val, offset) iowrite32(val, port->membase + offset)
/* Rx Trigger level */
static int rx_trigger_level = 56;
module_param(rx_trigger_level, uint, S_IRUGO);
MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes");
/* Rx Timeout */
static int rx_timeout = 10;
module_param(rx_timeout, uint, S_IRUGO);
MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");
/********************************Register Map********************************/ /********************************Register Map********************************/
/** UART /** UART
* *
@ -128,6 +142,9 @@
#define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ #define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */
#define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */ #define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */
/* Goes in read_status_mask for break detection as the HW doesn't do it*/
#define XUARTPS_IXR_BRK 0x80000000
/** Channel Status Register /** Channel Status Register
* *
* The channel status register (CSR) is provided to enable the control logic * The channel status register (CSR) is provided to enable the control logic
@ -139,15 +156,27 @@
#define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */ #define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */
#define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */
/* baud dividers min/max values */
#define XUARTPS_BDIV_MIN 4
#define XUARTPS_BDIV_MAX 255
#define XUARTPS_CD_MAX 65535
/** /**
* struct xuartps - device data * struct xuartps - device data
* @refclk Reference clock * @port Pointer to the UART port
* @aperclk APB clock * @refclk Reference clock
* @aperclk APB clock
* @baud Current baud rate
* @clk_rate_change_nb Notifier block for clock changes
*/ */
struct xuartps { struct xuartps {
struct uart_port *port;
struct clk *refclk; struct clk *refclk;
struct clk *aperclk; struct clk *aperclk;
unsigned int baud;
struct notifier_block clk_rate_change_nb;
}; };
#define to_xuartps(_nb) container_of(_nb, struct xuartps, clk_rate_change_nb);
/** /**
* xuartps_isr - Interrupt handler * xuartps_isr - Interrupt handler
@ -171,6 +200,23 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
*/ */
isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET); isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET);
/*
* There is no hardware break detection, so we interpret framing
* error with all-zeros data as a break sequence. Most of the time,
* there's another non-zero byte at the end of the sequence.
*/
if (isrstatus & XUARTPS_IXR_FRAMING) {
while (!(xuartps_readl(XUARTPS_SR_OFFSET) &
XUARTPS_SR_RXEMPTY)) {
if (!xuartps_readl(XUARTPS_FIFO_OFFSET)) {
port->read_status_mask |= XUARTPS_IXR_BRK;
isrstatus &= ~XUARTPS_IXR_FRAMING;
}
}
xuartps_writel(XUARTPS_IXR_FRAMING, XUARTPS_ISR_OFFSET);
}
/* drop byte with parity error if IGNPAR specified */ /* drop byte with parity error if IGNPAR specified */
if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY) if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY)
isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT); isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT);
@ -184,6 +230,30 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
while ((xuartps_readl(XUARTPS_SR_OFFSET) & while ((xuartps_readl(XUARTPS_SR_OFFSET) &
XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
data = xuartps_readl(XUARTPS_FIFO_OFFSET); data = xuartps_readl(XUARTPS_FIFO_OFFSET);
/* Non-NULL byte after BREAK is garbage (99%) */
if (data && (port->read_status_mask &
XUARTPS_IXR_BRK)) {
port->read_status_mask &= ~XUARTPS_IXR_BRK;
port->icount.brk++;
if (uart_handle_break(port))
continue;
}
/*
* uart_handle_sysrq_char() doesn't work if
* spinlocked, for some reason
*/
if (port->sysrq) {
spin_unlock(&port->lock);
if (uart_handle_sysrq_char(port,
(unsigned char)data)) {
spin_lock(&port->lock);
continue;
}
spin_lock(&port->lock);
}
port->icount.rx++; port->icount.rx++;
if (isrstatus & XUARTPS_IXR_PARITY) { if (isrstatus & XUARTPS_IXR_PARITY) {
@ -247,63 +317,196 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
} }
/** /**
* xuartps_set_baud_rate - Calculate and set the baud rate * xuartps_calc_baud_divs - Calculate baud rate divisors
* @port: Handle to the uart port structure * @clk: UART module input clock
* @baud: Baud rate to set * @baud: Desired baud rate
* * @rbdiv: BDIV value (return value)
* @rcd: CD value (return value)
* @div8: Value for clk_sel bit in mod (return value)
* Returns baud rate, requested baud when possible, or actual baud when there * Returns baud rate, requested baud when possible, or actual baud when there
* was too much error * was too much error, zero if no valid divisors are found.
**/ *
static unsigned int xuartps_set_baud_rate(struct uart_port *port, * Formula to obtain baud rate is
unsigned int baud) * baud_tx/rx rate = clk/CD * (BDIV + 1)
* input_clk = (Uart User Defined Clock or Apb Clock)
* depends on UCLKEN in MR Reg
* clk = input_clk or input_clk/8;
* depends on CLKS in MR reg
* CD and BDIV depends on values in
* baud rate generate register
* baud rate clock divisor register
*/
static unsigned int xuartps_calc_baud_divs(unsigned int clk, unsigned int baud,
u32 *rbdiv, u32 *rcd, int *div8)
{ {
unsigned int sel_clk; u32 cd, bdiv;
unsigned int calc_baud = 0; unsigned int calc_baud;
unsigned int brgr_val, brdiv_val; unsigned int bestbaud = 0;
unsigned int bauderror; unsigned int bauderror;
unsigned int besterror = ~0;
/* Formula to obtain baud rate is if (baud < clk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX)) {
* baud_tx/rx rate = sel_clk/CD * (BDIV + 1) *div8 = 1;
* input_clk = (Uart User Defined Clock or Apb Clock) clk /= 8;
* depends on UCLKEN in MR Reg } else {
* sel_clk = input_clk or input_clk/8; *div8 = 0;
* depends on CLKS in MR reg }
* CD and BDIV depends on values in
* baud rate generate register
* baud rate clock divisor register
*/
sel_clk = port->uartclk;
if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL)
sel_clk = sel_clk / 8;
/* Find the best values for baud generation */ for (bdiv = XUARTPS_BDIV_MIN; bdiv <= XUARTPS_BDIV_MAX; bdiv++) {
for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) { cd = DIV_ROUND_CLOSEST(clk, baud * (bdiv + 1));
if (cd < 1 || cd > XUARTPS_CD_MAX)
brgr_val = sel_clk / (baud * (brdiv_val + 1));
if (brgr_val < 2 || brgr_val > 65535)
continue; continue;
calc_baud = sel_clk / (brgr_val * (brdiv_val + 1)); calc_baud = clk / (cd * (bdiv + 1));
if (baud > calc_baud) if (baud > calc_baud)
bauderror = baud - calc_baud; bauderror = baud - calc_baud;
else else
bauderror = calc_baud - baud; bauderror = calc_baud - baud;
/* use the values when percent error is acceptable */ if (besterror > bauderror) {
if (((bauderror * 100) / baud) < 3) { *rbdiv = bdiv;
calc_baud = baud; *rcd = cd;
break; bestbaud = calc_baud;
besterror = bauderror;
} }
} }
/* use the values when percent error is acceptable */
if (((besterror * 100) / baud) < 3)
bestbaud = baud;
/* Set the values for the new baud rate */ return bestbaud;
xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET); }
xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET);
/**
* xuartps_set_baud_rate - Calculate and set the baud rate
* @port: Handle to the uart port structure
* @baud: Baud rate to set
* Returns baud rate, requested baud when possible, or actual baud when there
* was too much error, zero if no valid divisors are found.
*/
static unsigned int xuartps_set_baud_rate(struct uart_port *port,
unsigned int baud)
{
unsigned int calc_baud;
u32 cd = 0, bdiv = 0;
u32 mreg;
int div8;
struct xuartps *xuartps = port->private_data;
calc_baud = xuartps_calc_baud_divs(port->uartclk, baud, &bdiv, &cd,
&div8);
/* Write new divisors to hardware */
mreg = xuartps_readl(XUARTPS_MR_OFFSET);
if (div8)
mreg |= XUARTPS_MR_CLKSEL;
else
mreg &= ~XUARTPS_MR_CLKSEL;
xuartps_writel(mreg, XUARTPS_MR_OFFSET);
xuartps_writel(cd, XUARTPS_BAUDGEN_OFFSET);
xuartps_writel(bdiv, XUARTPS_BAUDDIV_OFFSET);
xuartps->baud = baud;
return calc_baud; return calc_baud;
} }
#ifdef CONFIG_COMMON_CLK
/**
* xuartps_clk_notitifer_cb - Clock notifier callback
* @nb: Notifier block
* @event: Notify event
* @data: Notifier data
* Returns NOTIFY_OK on success, NOTIFY_BAD on error.
*/
static int xuartps_clk_notifier_cb(struct notifier_block *nb,
unsigned long event, void *data)
{
u32 ctrl_reg;
struct uart_port *port;
int locked = 0;
struct clk_notifier_data *ndata = data;
unsigned long flags = 0;
struct xuartps *xuartps = to_xuartps(nb);
port = xuartps->port;
if (port->suspended)
return NOTIFY_OK;
switch (event) {
case PRE_RATE_CHANGE:
{
u32 bdiv;
u32 cd;
int div8;
/*
* Find out if current baud-rate can be achieved with new clock
* frequency.
*/
if (!xuartps_calc_baud_divs(ndata->new_rate, xuartps->baud,
&bdiv, &cd, &div8))
return NOTIFY_BAD;
spin_lock_irqsave(&xuartps->port->lock, flags);
/* Disable the TX and RX to set baud rate */
xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS),
XUARTPS_CR_OFFSET);
spin_unlock_irqrestore(&xuartps->port->lock, flags);
return NOTIFY_OK;
}
case POST_RATE_CHANGE:
/*
* Set clk dividers to generate correct baud with new clock
* frequency.
*/
spin_lock_irqsave(&xuartps->port->lock, flags);
locked = 1;
port->uartclk = ndata->new_rate;
xuartps->baud = xuartps_set_baud_rate(xuartps->port,
xuartps->baud);
/* fall through */
case ABORT_RATE_CHANGE:
if (!locked)
spin_lock_irqsave(&xuartps->port->lock, flags);
/* Set TX/RX Reset */
xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
XUARTPS_CR_OFFSET);
while (xuartps_readl(XUARTPS_CR_OFFSET) &
(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST))
cpu_relax();
/*
* Clear the RX disable and TX disable bits and then set the TX
* enable bit and RX enable bit to enable the transmitter and
* receiver.
*/
xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
xuartps_writel(
(ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) |
(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
XUARTPS_CR_OFFSET);
spin_unlock_irqrestore(&xuartps->port->lock, flags);
return NOTIFY_OK;
default:
return NOTIFY_DONE;
}
}
#endif
/*----------------------Uart Operations---------------------------*/ /*----------------------Uart Operations---------------------------*/
/** /**
@ -346,7 +549,7 @@ static void xuartps_start_tx(struct uart_port *port)
port->state->xmit.tail = (port->state->xmit.tail + 1) & port->state->xmit.tail = (port->state->xmit.tail + 1) &
(UART_XMIT_SIZE - 1); (UART_XMIT_SIZE - 1);
} }
xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_ISR_OFFSET);
/* Enable the TX Empty interrupt */ /* Enable the TX Empty interrupt */
xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET); xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET);
@ -437,7 +640,7 @@ static void xuartps_set_termios(struct uart_port *port,
struct ktermios *termios, struct ktermios *old) struct ktermios *termios, struct ktermios *old)
{ {
unsigned int cval = 0; unsigned int cval = 0;
unsigned int baud; unsigned int baud, minbaud, maxbaud;
unsigned long flags; unsigned long flags;
unsigned int ctrl_reg, mode_reg; unsigned int ctrl_reg, mode_reg;
@ -454,8 +657,14 @@ static void xuartps_set_termios(struct uart_port *port,
(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS),
XUARTPS_CR_OFFSET); XUARTPS_CR_OFFSET);
/* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */ /*
baud = uart_get_baud_rate(port, termios, old, 0, 10000000); * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk
* min and max baud should be calculated here based on port->uartclk.
* this way we get a valid baud and can safely call set_baud()
*/
minbaud = port->uartclk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX * 8);
maxbaud = port->uartclk / (XUARTPS_BDIV_MIN + 1);
baud = uart_get_baud_rate(port, termios, old, minbaud, maxbaud);
baud = xuartps_set_baud_rate(port, baud); baud = xuartps_set_baud_rate(port, baud);
if (tty_termios_baud_rate(termios)) if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud); tty_termios_encode_baud_rate(termios, baud, baud);
@ -480,7 +689,7 @@ static void xuartps_set_termios(struct uart_port *port,
| (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
XUARTPS_CR_OFFSET); XUARTPS_CR_OFFSET);
xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG | port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG |
XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT; XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT;
@ -531,13 +740,17 @@ static void xuartps_set_termios(struct uart_port *port,
cval |= XUARTPS_MR_PARITY_MARK; cval |= XUARTPS_MR_PARITY_MARK;
else else
cval |= XUARTPS_MR_PARITY_SPACE; cval |= XUARTPS_MR_PARITY_SPACE;
} else if (termios->c_cflag & PARODD) } else {
if (termios->c_cflag & PARODD)
cval |= XUARTPS_MR_PARITY_ODD; cval |= XUARTPS_MR_PARITY_ODD;
else else
cval |= XUARTPS_MR_PARITY_EVEN; cval |= XUARTPS_MR_PARITY_EVEN;
} else }
} else {
cval |= XUARTPS_MR_PARITY_NONE; cval |= XUARTPS_MR_PARITY_NONE;
xuartps_writel(cval , XUARTPS_MR_OFFSET); }
cval |= mode_reg & 1;
xuartps_writel(cval, XUARTPS_MR_OFFSET);
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
} }
@ -583,11 +796,17 @@ static int xuartps_startup(struct uart_port *port)
| XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT, | XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT,
XUARTPS_MR_OFFSET); XUARTPS_MR_OFFSET);
/* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */ /*
xuartps_writel(14, XUARTPS_RXWM_OFFSET); * Set the RX FIFO Trigger level to use most of the FIFO, but it
* can be tuned with a module parameter
*/
xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET);
/* Receive Timeout register is enabled with value of 10 */ /*
xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); * Receive Timeout register is enabled but it
* can be tuned with a module parameter
*/
xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
/* Clear out any pending interrupts before enabling them */ /* Clear out any pending interrupts before enabling them */
xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET); xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET);
@ -727,6 +946,54 @@ static void xuartps_enable_ms(struct uart_port *port)
/* N/A */ /* N/A */
} }
#ifdef CONFIG_CONSOLE_POLL
static int xuartps_poll_get_char(struct uart_port *port)
{
u32 imr;
int c;
/* Disable all interrupts */
imr = xuartps_readl(XUARTPS_IMR_OFFSET);
xuartps_writel(imr, XUARTPS_IDR_OFFSET);
/* Check if FIFO is empty */
if (xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY)
c = NO_POLL_CHAR;
else /* Read a character */
c = (unsigned char) xuartps_readl(XUARTPS_FIFO_OFFSET);
/* Enable interrupts */
xuartps_writel(imr, XUARTPS_IER_OFFSET);
return c;
}
static void xuartps_poll_put_char(struct uart_port *port, unsigned char c)
{
u32 imr;
/* Disable all interrupts */
imr = xuartps_readl(XUARTPS_IMR_OFFSET);
xuartps_writel(imr, XUARTPS_IDR_OFFSET);
/* Wait until FIFO is empty */
while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY))
cpu_relax();
/* Write a character */
xuartps_writel(c, XUARTPS_FIFO_OFFSET);
/* Wait until FIFO is empty */
while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY))
cpu_relax();
/* Enable interrupts */
xuartps_writel(imr, XUARTPS_IER_OFFSET);
return;
}
#endif
/** The UART operations structure /** The UART operations structure
*/ */
static struct uart_ops xuartps_ops = { static struct uart_ops xuartps_ops = {
@ -759,6 +1026,10 @@ static struct uart_ops xuartps_ops = {
.config_port = xuartps_config_port, /* Configure when driver .config_port = xuartps_config_port, /* Configure when driver
* adds a xuartps port * adds a xuartps port
*/ */
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = xuartps_poll_get_char,
.poll_put_char = xuartps_poll_put_char,
#endif
}; };
static struct uart_port xuartps_port[2]; static struct uart_port xuartps_port[2];
@ -837,7 +1108,7 @@ static void xuartps_console_write(struct console *co, const char *s,
{ {
struct uart_port *port = &xuartps_port[co->index]; struct uart_port *port = &xuartps_port[co->index];
unsigned long flags; unsigned long flags;
unsigned int imr; unsigned int imr, ctrl;
int locked = 1; int locked = 1;
if (oops_in_progress) if (oops_in_progress)
@ -849,9 +1120,19 @@ static void xuartps_console_write(struct console *co, const char *s,
imr = xuartps_readl(XUARTPS_IMR_OFFSET); imr = xuartps_readl(XUARTPS_IMR_OFFSET);
xuartps_writel(imr, XUARTPS_IDR_OFFSET); xuartps_writel(imr, XUARTPS_IDR_OFFSET);
/*
* Make sure that the tx part is enabled. Set the TX enable bit and
* clear the TX disable bit to enable the transmitter.
*/
ctrl = xuartps_readl(XUARTPS_CR_OFFSET);
xuartps_writel((ctrl & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN,
XUARTPS_CR_OFFSET);
uart_console_write(port, s, count, xuartps_console_putchar); uart_console_write(port, s, count, xuartps_console_putchar);
xuartps_console_wait_tx(port); xuartps_console_wait_tx(port);
xuartps_writel(ctrl, XUARTPS_CR_OFFSET);
/* restore interrupt state, it seems like there may be a h/w bug /* restore interrupt state, it seems like there may be a h/w bug
* in that the interrupt enable register should not need to be * in that the interrupt enable register should not need to be
* written based on the data sheet * written based on the data sheet
@ -933,6 +1214,119 @@ static struct uart_driver xuartps_uart_driver = {
#endif #endif
}; };
#ifdef CONFIG_PM_SLEEP
/**
* xuartps_suspend - suspend event
* @device: Pointer to the device structure
*
* Returns 0
*/
static int xuartps_suspend(struct device *device)
{
struct uart_port *port = dev_get_drvdata(device);
struct tty_struct *tty;
struct device *tty_dev;
int may_wake = 0;
/* Get the tty which could be NULL so don't assume it's valid */
tty = tty_port_tty_get(&port->state->port);
if (tty) {
tty_dev = tty->dev;
may_wake = device_may_wakeup(tty_dev);
tty_kref_put(tty);
}
/*
* Call the API provided in serial_core.c file which handles
* the suspend.
*/
uart_suspend_port(&xuartps_uart_driver, port);
if (console_suspend_enabled && !may_wake) {
struct xuartps *xuartps = port->private_data;
clk_disable(xuartps->refclk);
clk_disable(xuartps->aperclk);
} else {
unsigned long flags = 0;
spin_lock_irqsave(&port->lock, flags);
/* Empty the receive FIFO 1st before making changes */
while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY))
xuartps_readl(XUARTPS_FIFO_OFFSET);
/* set RX trigger level to 1 */
xuartps_writel(1, XUARTPS_RXWM_OFFSET);
/* disable RX timeout interrups */
xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IDR_OFFSET);
spin_unlock_irqrestore(&port->lock, flags);
}
return 0;
}
/**
* xuartps_resume - Resume after a previous suspend
* @device: Pointer to the device structure
*
* Returns 0
*/
static int xuartps_resume(struct device *device)
{
struct uart_port *port = dev_get_drvdata(device);
unsigned long flags = 0;
u32 ctrl_reg;
struct tty_struct *tty;
struct device *tty_dev;
int may_wake = 0;
/* Get the tty which could be NULL so don't assume it's valid */
tty = tty_port_tty_get(&port->state->port);
if (tty) {
tty_dev = tty->dev;
may_wake = device_may_wakeup(tty_dev);
tty_kref_put(tty);
}
if (console_suspend_enabled && !may_wake) {
struct xuartps *xuartps = port->private_data;
clk_enable(xuartps->aperclk);
clk_enable(xuartps->refclk);
spin_lock_irqsave(&port->lock, flags);
/* Set TX/RX Reset */
xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
XUARTPS_CR_OFFSET);
while (xuartps_readl(XUARTPS_CR_OFFSET) &
(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST))
cpu_relax();
/* restore rx timeout value */
xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
/* Enable Tx/Rx */
ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
xuartps_writel(
(ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) |
(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
XUARTPS_CR_OFFSET);
spin_unlock_irqrestore(&port->lock, flags);
} else {
spin_lock_irqsave(&port->lock, flags);
/* restore original rx trigger level */
xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET);
/* enable RX timeout interrupt */
xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
spin_unlock_irqrestore(&port->lock, flags);
}
return uart_resume_port(&xuartps_uart_driver, port);
}
#endif /* ! CONFIG_PM_SLEEP */
static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume);
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* Platform bus binding * Platform bus binding
*/ */
@ -949,27 +1343,26 @@ static int xuartps_probe(struct platform_device *pdev)
struct resource *res, *res2; struct resource *res, *res2;
struct xuartps *xuartps_data; struct xuartps *xuartps_data;
xuartps_data = kzalloc(sizeof(*xuartps_data), GFP_KERNEL); xuartps_data = devm_kzalloc(&pdev->dev, sizeof(*xuartps_data),
GFP_KERNEL);
if (!xuartps_data) if (!xuartps_data)
return -ENOMEM; return -ENOMEM;
xuartps_data->aperclk = clk_get(&pdev->dev, "aper_clk"); xuartps_data->aperclk = devm_clk_get(&pdev->dev, "aper_clk");
if (IS_ERR(xuartps_data->aperclk)) { if (IS_ERR(xuartps_data->aperclk)) {
dev_err(&pdev->dev, "aper_clk clock not found.\n"); dev_err(&pdev->dev, "aper_clk clock not found.\n");
rc = PTR_ERR(xuartps_data->aperclk); return PTR_ERR(xuartps_data->aperclk);
goto err_out_free;
} }
xuartps_data->refclk = clk_get(&pdev->dev, "ref_clk"); xuartps_data->refclk = devm_clk_get(&pdev->dev, "ref_clk");
if (IS_ERR(xuartps_data->refclk)) { if (IS_ERR(xuartps_data->refclk)) {
dev_err(&pdev->dev, "ref_clk clock not found.\n"); dev_err(&pdev->dev, "ref_clk clock not found.\n");
rc = PTR_ERR(xuartps_data->refclk); return PTR_ERR(xuartps_data->refclk);
goto err_out_clk_put_aper;
} }
rc = clk_prepare_enable(xuartps_data->aperclk); rc = clk_prepare_enable(xuartps_data->aperclk);
if (rc) { if (rc) {
dev_err(&pdev->dev, "Unable to enable APER clock.\n"); dev_err(&pdev->dev, "Unable to enable APER clock.\n");
goto err_out_clk_put; return rc;
} }
rc = clk_prepare_enable(xuartps_data->refclk); rc = clk_prepare_enable(xuartps_data->refclk);
if (rc) { if (rc) {
@ -989,13 +1382,21 @@ static int xuartps_probe(struct platform_device *pdev)
goto err_out_clk_disable; goto err_out_clk_disable;
} }
#ifdef CONFIG_COMMON_CLK
xuartps_data->clk_rate_change_nb.notifier_call =
xuartps_clk_notifier_cb;
if (clk_notifier_register(xuartps_data->refclk,
&xuartps_data->clk_rate_change_nb))
dev_warn(&pdev->dev, "Unable to register clock notifier.\n");
#endif
/* Initialize the port structure */ /* Initialize the port structure */
port = xuartps_get_port(); port = xuartps_get_port();
if (!port) { if (!port) {
dev_err(&pdev->dev, "Cannot get uart_port structure\n"); dev_err(&pdev->dev, "Cannot get uart_port structure\n");
rc = -ENODEV; rc = -ENODEV;
goto err_out_clk_disable; goto err_out_notif_unreg;
} else { } else {
/* Register the port. /* Register the port.
* This function also registers this device with the tty layer * This function also registers this device with the tty layer
@ -1006,26 +1407,26 @@ static int xuartps_probe(struct platform_device *pdev)
port->dev = &pdev->dev; port->dev = &pdev->dev;
port->uartclk = clk_get_rate(xuartps_data->refclk); port->uartclk = clk_get_rate(xuartps_data->refclk);
port->private_data = xuartps_data; port->private_data = xuartps_data;
xuartps_data->port = port;
platform_set_drvdata(pdev, port); platform_set_drvdata(pdev, port);
rc = uart_add_one_port(&xuartps_uart_driver, port); rc = uart_add_one_port(&xuartps_uart_driver, port);
if (rc) { if (rc) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"uart_add_one_port() failed; err=%i\n", rc); "uart_add_one_port() failed; err=%i\n", rc);
goto err_out_clk_disable; goto err_out_notif_unreg;
} }
return 0; return 0;
} }
err_out_notif_unreg:
#ifdef CONFIG_COMMON_CLK
clk_notifier_unregister(xuartps_data->refclk,
&xuartps_data->clk_rate_change_nb);
#endif
err_out_clk_disable: err_out_clk_disable:
clk_disable_unprepare(xuartps_data->refclk); clk_disable_unprepare(xuartps_data->refclk);
err_out_clk_dis_aper: err_out_clk_dis_aper:
clk_disable_unprepare(xuartps_data->aperclk); clk_disable_unprepare(xuartps_data->aperclk);
err_out_clk_put:
clk_put(xuartps_data->refclk);
err_out_clk_put_aper:
clk_put(xuartps_data->aperclk);
err_out_free:
kfree(xuartps_data);
return rc; return rc;
} }
@ -1043,13 +1444,14 @@ static int xuartps_remove(struct platform_device *pdev)
int rc; int rc;
/* Remove the xuartps port from the serial core */ /* Remove the xuartps port from the serial core */
#ifdef CONFIG_COMMON_CLK
clk_notifier_unregister(xuartps_data->refclk,
&xuartps_data->clk_rate_change_nb);
#endif
rc = uart_remove_one_port(&xuartps_uart_driver, port); rc = uart_remove_one_port(&xuartps_uart_driver, port);
port->mapbase = 0; port->mapbase = 0;
clk_disable_unprepare(xuartps_data->refclk); clk_disable_unprepare(xuartps_data->refclk);
clk_disable_unprepare(xuartps_data->aperclk); clk_disable_unprepare(xuartps_data->aperclk);
clk_put(xuartps_data->refclk);
clk_put(xuartps_data->aperclk);
kfree(xuartps_data);
return rc; return rc;
} }
@ -1067,6 +1469,7 @@ static struct platform_driver xuartps_platform_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = XUARTPS_NAME, /* Driver name */ .name = XUARTPS_NAME, /* Driver name */
.of_match_table = xuartps_of_match, .of_match_table = xuartps_of_match,
.pm = &xuartps_dev_pm_ops,
}, },
}; };

View file

@ -51,7 +51,7 @@
#include <asm/irq_regs.h> #include <asm/irq_regs.h>
/* Whether we react on sysrq keys or just ignore them */ /* Whether we react on sysrq keys or just ignore them */
static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE; static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
static bool __read_mostly sysrq_always_enabled; static bool __read_mostly sysrq_always_enabled;
unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED };

View file

@ -140,6 +140,10 @@ EXPORT_SYMBOL(tty_port_destroy);
static void tty_port_destructor(struct kref *kref) static void tty_port_destructor(struct kref *kref)
{ {
struct tty_port *port = container_of(kref, struct tty_port, kref); struct tty_port *port = container_of(kref, struct tty_port, kref);
/* check if last port ref was dropped before tty release */
if (WARN_ON(port->itty))
return;
if (port->xmit_buf) if (port->xmit_buf)
free_page((unsigned long)port->xmit_buf); free_page((unsigned long)port->xmit_buf);
tty_port_destroy(port); tty_port_destroy(port);
@ -480,8 +484,6 @@ int tty_port_close_start(struct tty_port *port,
if (port->count) { if (port->count) {
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
if (port->ops->drop)
port->ops->drop(port);
return 0; return 0;
} }
set_bit(ASYNCB_CLOSING, &port->flags); set_bit(ASYNCB_CLOSING, &port->flags);
@ -500,9 +502,7 @@ int tty_port_close_start(struct tty_port *port,
/* Flush the ldisc buffering */ /* Flush the ldisc buffering */
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
/* Don't call port->drop for the last reference. Callers will want /* Report to caller this is the last port reference */
to drop the last active reference in ->shutdown() or the tty
shutdown path */
return 1; return 1;
} }
EXPORT_SYMBOL(tty_port_close_start); EXPORT_SYMBOL(tty_port_close_start);

View file

@ -1300,21 +1300,30 @@ static void csi_m(struct vc_data *vc)
case 27: case 27:
vc->vc_reverse = 0; vc->vc_reverse = 0;
break; break;
case 38: /* ANSI X3.64-1979 (SCO-ish?) case 38:
* Enables underscore, white foreground case 48: /* ITU T.416
* with white underscore (Linux - use * Higher colour modes.
* default foreground). * They break the usual properties of SGR codes
* and thus need to be detected and ignored by
* hand. Strictly speaking, that standard also
* wants : rather than ; as separators, contrary
* to ECMA-48, but no one produces such codes
* and almost no one accepts them.
*/ */
vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0); i++;
vc->vc_underline = 1; if (i > vc->vc_npar)
break;
if (vc->vc_par[i] == 5) /* 256 colours */
i++; /* ubiquitous */
else if (vc->vc_par[i] == 2) /* 24 bit colours */
i += 3; /* extremely rare */
/* Subcommands 3 (CMY) and 4 (CMYK) are so insane
* that detecting them is not worth the few extra
* bytes of kernel's size.
*/
break; break;
case 39: /* ANSI X3.64-1979 (SCO-ish?) case 39:
* Disable underline option.
* Reset colour to default? It did this
* before...
*/
vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0); vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
vc->vc_underline = 0;
break; break;
case 49: case 49:
vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f); vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);

View file

@ -125,5 +125,6 @@
#define ATMEL_US_IF 0x4c /* IrDA Filter Register */ #define ATMEL_US_IF 0x4c /* IrDA Filter Register */
#define ATMEL_US_NAME 0xf0 /* Ip Name */ #define ATMEL_US_NAME 0xf0 /* Ip Name */
#define ATMEL_US_VERSION 0xfc /* Ip Version */
#endif #endif

View file

@ -66,7 +66,6 @@ struct uart_ops {
void (*set_ldisc)(struct uart_port *, int new); void (*set_ldisc)(struct uart_port *, int new);
void (*pm)(struct uart_port *, unsigned int state, void (*pm)(struct uart_port *, unsigned int state,
unsigned int oldstate); unsigned int oldstate);
int (*set_wake)(struct uart_port *, unsigned int state);
/* /*
* Return a string describing the type of the port * Return a string describing the type of the port

View file

@ -17,9 +17,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
/* Enable/disable SYSRQ support by default (0==no, 1==yes). */
#define SYSRQ_DEFAULT_ENABLE 1
/* Possible values of bitmask for enabling sysrq functions */ /* Possible values of bitmask for enabling sysrq functions */
/* 0x0001 is reserved for enable everything */ /* 0x0001 is reserved for enable everything */
#define SYSRQ_ENABLE_LOG 0x0002 #define SYSRQ_ENABLE_LOG 0x0002

View file

@ -180,7 +180,6 @@ struct tty_port_operations {
IFF the port was initialized. Do not use to free resources. Called IFF the port was initialized. Do not use to free resources. Called
under the port mutex to serialize against activate/shutdowns */ under the port mutex to serialize against activate/shutdowns */
void (*shutdown)(struct tty_port *port); void (*shutdown)(struct tty_port *port);
void (*drop)(struct tty_port *port);
/* Called under the port mutex from tty_port_open, serialized using /* Called under the port mutex from tty_port_open, serialized using
the port mutex */ the port mutex */
/* FIXME: long term getting the tty argument *out* of this would be /* FIXME: long term getting the tty argument *out* of this would be

View file

@ -190,7 +190,7 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
/* Note: sysrq code uses it's own private copy */ /* Note: sysrq code uses it's own private copy */
static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
static int sysrq_sysctl_handler(ctl_table *table, int write, static int sysrq_sysctl_handler(ctl_table *table, int write,
void __user *buffer, size_t *lenp, void __user *buffer, size_t *lenp,

View file

@ -312,6 +312,15 @@ config MAGIC_SYSRQ
keys are documented in <file:Documentation/sysrq.txt>. Don't say Y keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
unless you really know what this hack does. unless you really know what this hack does.
config MAGIC_SYSRQ_DEFAULT_ENABLE
hex "Enable magic SysRq key functions by default"
depends on MAGIC_SYSRQ
default 0x1
help
Specifies which SysRq key functions are enabled by default.
This may be set to 1 or 0 to enable or disable them all, or
to a bitmask as described in Documentation/sysrq.txt.
config DEBUG_KERNEL config DEBUG_KERNEL
bool "Kernel debugging" bool "Kernel debugging"
help help