mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 22:50:41 +00:00
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:
commit
56edff7529
@ -264,10 +264,6 @@ hardware.
|
||||
Locking: none.
|
||||
Interrupts: caller dependent.
|
||||
|
||||
set_wake(port,state)
|
||||
Enable/disable power management wakeup on serial activity. Not
|
||||
currently implemented.
|
||||
|
||||
type(port)
|
||||
Return a pointer to a string constant describing the specified
|
||||
port, or return NULL, in which case the string 'unknown' is
|
||||
|
@ -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
|
||||
configuring the kernel. When running a kernel with SysRq compiled in,
|
||||
/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
|
||||
possible SysRq request is allowed (in older versions SysRq was disabled
|
||||
by default, and you were required to specifically enable it at run-time
|
||||
but this is not the case any more). Here is the list of possible values
|
||||
in /proc/sys/kernel/sysrq:
|
||||
the SysRq key. The default value in this file is set by the
|
||||
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults
|
||||
to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
|
||||
0 - disable sysrq completely
|
||||
1 - enable all functions of sysrq
|
||||
>1 - bitmask of allowed sysrq functions (see below for detailed function
|
||||
description):
|
||||
2 - enable control of console logging level
|
||||
4 - enable control of keyboard (SAK, unraw)
|
||||
8 - enable debugging dumps of processes etc.
|
||||
16 - enable sync command
|
||||
32 - enable remount read-only
|
||||
64 - enable signalling of processes (term, kill, oom-kill)
|
||||
128 - allow reboot/poweroff
|
||||
256 - allow nicing of all RT tasks
|
||||
2 = 0x2 - enable control of console logging level
|
||||
4 = 0x4 - enable control of keyboard (SAK, unraw)
|
||||
8 = 0x8 - enable debugging dumps of processes etc.
|
||||
16 = 0x10 - enable sync command
|
||||
32 = 0x20 - enable remount read-only
|
||||
64 = 0x40 - enable signalling of processes (term, kill, oom-kill)
|
||||
128 = 0x80 - allow reboot/poweroff
|
||||
256 = 0x100 - allow nicing of all RT tasks
|
||||
|
||||
You can set the value in the file by the following command:
|
||||
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
|
||||
via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
|
||||
allowed (by a user with admin privileges).
|
||||
|
@ -349,7 +349,7 @@ bfin_jc_early_write(struct console *co, const char *buf, unsigned int 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",
|
||||
.write = bfin_jc_early_write,
|
||||
.flags = CON_ANYTIME | CON_PRINTBUFFER,
|
||||
|
@ -86,6 +86,21 @@ static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
|
||||
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 = {
|
||||
.get_chars = hvc_dcc_get_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)
|
||||
{
|
||||
if (!hvc_dcc_check())
|
||||
return -ENODEV;
|
||||
|
||||
hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
|
||||
return 0;
|
||||
}
|
||||
@ -100,6 +118,9 @@ console_initcall(hvc_dcc_console_init);
|
||||
|
||||
static int __init hvc_dcc_init(void)
|
||||
{
|
||||
if (!hvc_dcc_check())
|
||||
return -ENODEV;
|
||||
|
||||
hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
|
||||
return 0;
|
||||
}
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <asm/prom.h>
|
||||
#include <asm/hvsi.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/machdep.h>
|
||||
|
||||
#include "hvc_console.h"
|
||||
|
||||
@ -457,7 +458,9 @@ void __init hvc_vio_init_early(void)
|
||||
if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
|
||||
goto out;
|
||||
#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);
|
||||
out:
|
||||
of_node_put(stdout_node);
|
||||
|
@ -767,7 +767,7 @@ static size_t __process_echoes(struct tty_struct *tty)
|
||||
* of echo overrun before the next commit), then discard enough
|
||||
* data at the tail to prevent a subsequent overrun */
|
||||
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)
|
||||
tail += 3;
|
||||
else
|
||||
@ -1752,20 +1752,14 @@ int is_ignored(int sig)
|
||||
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
{
|
||||
struct n_tty_data *ldata = tty->disc_data;
|
||||
int canon_change = 1;
|
||||
|
||||
if (old)
|
||||
canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
|
||||
if (canon_change) {
|
||||
if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) {
|
||||
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
|
||||
ldata->line_start = ldata->canon_head = ldata->read_tail;
|
||||
ldata->erasing = 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);
|
||||
|
||||
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
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* The termios change make the tty ready for I/O */
|
||||
wake_up_interruptible(&tty->write_wait);
|
||||
|
@ -959,7 +959,7 @@ static int receive_flow_control(struct nozomi *dc)
|
||||
dev_err(&dc->pdev->dev,
|
||||
"ERROR: flow control received for non-existing port\n");
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
|
||||
*((u16 *)&ctrl_dl));
|
||||
@ -1025,7 +1025,7 @@ static enum ctrl_port_type port2ctrl(enum port_type port,
|
||||
dev_err(&dc->pdev->dev,
|
||||
"ERROR: send flow control " \
|
||||
"received for non-existing port\n");
|
||||
};
|
||||
}
|
||||
return CTRL_ERROR;
|
||||
}
|
||||
|
||||
@ -1805,7 +1805,7 @@ static int ntty_ioctl(struct tty_struct *tty,
|
||||
default:
|
||||
DBG1("ERR: 0x%08X, %d", cmd, cmd);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
@ -2322,7 +2322,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
|
||||
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
|
||||
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_1;
|
||||
}
|
||||
|
@ -56,11 +56,11 @@
|
||||
|
||||
|
||||
struct dw8250_data {
|
||||
int last_lcr;
|
||||
int last_mcr;
|
||||
int line;
|
||||
struct clk *clk;
|
||||
u8 usr_reg;
|
||||
u8 usr_reg;
|
||||
int last_mcr;
|
||||
int line;
|
||||
struct clk *clk;
|
||||
struct uart_8250_dma dma;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
||||
if (offset == UART_LCR)
|
||||
d->last_lcr = value;
|
||||
|
||||
if (offset == UART_MCR)
|
||||
d->last_mcr = value;
|
||||
|
||||
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)
|
||||
@ -107,13 +123,22 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
||||
if (offset == UART_LCR)
|
||||
d->last_lcr = value;
|
||||
|
||||
if (offset == UART_MCR)
|
||||
d->last_mcr = value;
|
||||
|
||||
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)
|
||||
@ -131,9 +156,8 @@ static int dw8250_handle_irq(struct uart_port *p)
|
||||
if (serial8250_handle_irq(p, iir)) {
|
||||
return 1;
|
||||
} 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);
|
||||
p->serial_out(p, UART_LCR, d->last_lcr);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct uart_port *p = &up->port;
|
||||
@ -241,7 +273,8 @@ static int dw8250_probe_of(struct uart_port *p,
|
||||
}
|
||||
|
||||
#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;
|
||||
struct uart_port *p = &up->port;
|
||||
@ -260,9 +293,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up)
|
||||
if (!p->uartclk)
|
||||
p->uartclk = (unsigned int)id->driver_data;
|
||||
|
||||
up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL);
|
||||
if (!up->dma)
|
||||
return -ENOMEM;
|
||||
up->dma = &data->dma;
|
||||
|
||||
up->dma->rxconf.src_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;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
@ -314,6 +346,12 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
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.serial_in = dw8250_serial_in;
|
||||
uart.port.serial_out = dw8250_serial_out;
|
||||
@ -324,7 +362,7 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
} else if (ACPI_HANDLE(&pdev->dev)) {
|
||||
err = dw8250_probe_acpi(&uart);
|
||||
err = dw8250_probe_acpi(&uart, data);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
|
@ -122,7 +122,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
|
||||
up.port.dev = &pdev->dev;
|
||||
up.port.private_data = priv;
|
||||
|
||||
clk_enable(priv->sclk);
|
||||
clk_prepare_enable(priv->sclk);
|
||||
up.port.uartclk = clk_get_rate(priv->sclk);
|
||||
|
||||
up.port.iotype = UPIO_MEM32;
|
||||
@ -134,7 +134,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
|
||||
ret = serial8250_register_8250_port(&up);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "unable to register 8250 port\n");
|
||||
clk_disable(priv->sclk);
|
||||
clk_disable_unprepare(priv->sclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ static int serial8250_em_remove(struct platform_device *pdev)
|
||||
struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
serial8250_unregister_port(priv->line);
|
||||
clk_disable(priv->sclk);
|
||||
clk_disable_unprepare(priv->sclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*/
|
||||
#undef DEBUG
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
@ -27,8 +28,6 @@
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
#undef SERIAL_DEBUG_PCI
|
||||
|
||||
/*
|
||||
* init function returns:
|
||||
* > 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)
|
||||
{
|
||||
printk(KERN_WARNING
|
||||
dev_err(&dev->dev,
|
||||
"%s: %s\n"
|
||||
"Please send the output of lspci -vv, this\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? */
|
||||
pci_read_config_dword(dev, 0x44, (void *)&oldval);
|
||||
if (oldval == 0x00001000L) { /* RESET value */
|
||||
printk(KERN_DEBUG "Local i960 firmware missing");
|
||||
dev_dbg(&dev->dev, "Local i960 firmware missing\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
@ -827,7 +826,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev)
|
||||
if (sub_serports > 0) {
|
||||
return sub_serports;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -931,7 +930,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1024,9 +1023,9 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
|
||||
/* Tornado device */
|
||||
if (deviceID == 0x07000200) {
|
||||
number_uarts = ioread8(p + 4);
|
||||
printk(KERN_DEBUG
|
||||
dev_dbg(&dev->dev,
|
||||
"%d ports detected on Oxford PCI Express device\n",
|
||||
number_uarts);
|
||||
number_uarts);
|
||||
}
|
||||
pci_iounmap(dev, p);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
ce4100_serial_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
@ -1324,6 +1346,120 @@ ce4100_serial_setup(struct serial_private *priv,
|
||||
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
|
||||
pci_omegapci_setup(struct serial_private *priv,
|
||||
const struct pciserial_board *board,
|
||||
@ -1344,17 +1480,80 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
|
||||
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,
|
||||
const struct pciserial_board *board,
|
||||
struct uart_8250_port *port, int idx)
|
||||
{
|
||||
port->port.flags |= UPF_NO_TXEN_TEST;
|
||||
printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
|
||||
"[%04x:%04x] subsystem [%04x:%04x]\n",
|
||||
priv->dev->vendor,
|
||||
priv->dev->device,
|
||||
priv->dev->subsystem_vendor,
|
||||
priv->dev->subsystem_device);
|
||||
dev_dbg(&priv->dev->dev,
|
||||
"serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n",
|
||||
priv->dev->vendor, priv->dev->device,
|
||||
priv->dev->subsystem_vendor, priv->dev->subsystem_device);
|
||||
|
||||
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,
|
||||
.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
|
||||
*/
|
||||
@ -1825,6 +2038,31 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.setup = pci_default_setup,
|
||||
.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
|
||||
*/
|
||||
@ -2255,6 +2493,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.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
|
||||
@ -2449,9 +2708,13 @@ enum pci_board_num_t {
|
||||
pbn_ADDIDATA_PCIe_4_3906250,
|
||||
pbn_ADDIDATA_PCIe_8_3906250,
|
||||
pbn_ce4100_1_115200,
|
||||
pbn_byt,
|
||||
pbn_omegapci,
|
||||
pbn_NETMOS9900_2s_115200,
|
||||
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,
|
||||
.reg_shift = 2,
|
||||
},
|
||||
[pbn_byt] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 1,
|
||||
.base_baud = 2764800,
|
||||
.uart_offset = 0x80,
|
||||
.reg_shift = 2,
|
||||
},
|
||||
[pbn_omegapci] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 8,
|
||||
@ -3202,6 +3472,24 @@ static struct pciserial_board pci_boards[] = {
|
||||
.reg_shift = 2,
|
||||
.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[] = {
|
||||
@ -3362,14 +3650,15 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
|
||||
if (quirk->setup(priv, board, &uart, i))
|
||||
break;
|
||||
|
||||
#ifdef SERIAL_DEBUG_PCI
|
||||
printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
|
||||
uart.port.iobase, uart.port.irq, uart.port.iotype);
|
||||
#endif
|
||||
dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
|
||||
uart.port.iobase, uart.port.irq, uart.port.iotype);
|
||||
|
||||
priv->line[i] = serial8250_register_8250_port(&uart);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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)) {
|
||||
printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
|
||||
dev_err(&dev->dev, "invalid driver_data: %ld\n",
|
||||
ent->driver_data);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -3520,8 +3809,6 @@ static void pciserial_remove_one(struct pci_dev *dev)
|
||||
{
|
||||
struct serial_private *priv = pci_get_drvdata(dev);
|
||||
|
||||
pci_set_drvdata(dev, NULL);
|
||||
|
||||
pciserial_remove_ports(priv);
|
||||
|
||||
pci_disable_device(dev);
|
||||
@ -3555,7 +3842,7 @@ static int pciserial_resume_one(struct pci_dev *dev)
|
||||
err = pci_enable_device(dev);
|
||||
/* FIXME: We cannot simply error out here */
|
||||
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);
|
||||
}
|
||||
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_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
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
|
||||
@ -4918,6 +5214,11 @@ static struct pci_device_id serial_pci_tbl[] = {
|
||||
0,
|
||||
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,
|
||||
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
|
||||
|
@ -709,7 +709,7 @@ config SERIAL_IP22_ZILOG_CONSOLE
|
||||
|
||||
config SERIAL_SH_SCI
|
||||
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
|
||||
|
||||
config SERIAL_SH_SCI_NR_UARTS
|
||||
@ -1512,6 +1512,7 @@ config SERIAL_FSL_LPUART_CONSOLE
|
||||
config SERIAL_ST_ASC
|
||||
tristate "ST ASC serial port support"
|
||||
select SERIAL_CORE
|
||||
depends on ARM || COMPILE_TEST
|
||||
help
|
||||
This driver is for the on-chip Asychronous Serial Controller on
|
||||
STMicroelectronics STi SoCs.
|
||||
|
@ -728,7 +728,6 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
amba_set_drvdata(dev, uap);
|
||||
ret = uart_add_one_port(&amba_reg, &uap->port);
|
||||
if (ret) {
|
||||
amba_set_drvdata(dev, NULL);
|
||||
amba_ports[i] = NULL;
|
||||
clk_put(uap->clk);
|
||||
unmap:
|
||||
@ -745,8 +744,6 @@ static int pl010_remove(struct amba_device *dev)
|
||||
struct uart_amba_port *uap = amba_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
amba_set_drvdata(dev, NULL);
|
||||
|
||||
uart_remove_one_port(&amba_reg, &uap->port);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
|
||||
|
@ -2147,7 +2147,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
amba_set_drvdata(dev, uap);
|
||||
ret = uart_add_one_port(&amba_reg, &uap->port);
|
||||
if (ret) {
|
||||
amba_set_drvdata(dev, NULL);
|
||||
amba_ports[i] = NULL;
|
||||
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);
|
||||
int i;
|
||||
|
||||
amba_set_drvdata(dev, NULL);
|
||||
|
||||
uart_remove_one_port(&amba_reg, &uap->port);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
|
||||
|
@ -533,7 +533,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
|
||||
unsigned long *plat_data;
|
||||
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)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -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_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_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
|
||||
|
||||
/* PDC registers */
|
||||
#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);
|
||||
int name = UART_GET_IP_NAME(port);
|
||||
u32 version;
|
||||
int usart, uart;
|
||||
/* usart and uart ascii */
|
||||
usart = 0x55534152;
|
||||
@ -1517,7 +1519,22 @@ static void atmel_get_ip_name(struct uart_port *port)
|
||||
dev_dbg(port->dev, "This is uart\n");
|
||||
atmel_port->is_usart = false;
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -766,9 +766,8 @@ static int sport_uart_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = peripheral_request_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev),
|
||||
DRV_NAME);
|
||||
ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
|
||||
DRV_NAME);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Fail to request SPORT peripherals\n");
|
||||
@ -844,8 +843,7 @@ static int sport_uart_probe(struct platform_device *pdev)
|
||||
out_error_unmap:
|
||||
iounmap(sport->port.membase);
|
||||
out_error_free_peripherals:
|
||||
peripheral_free_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev));
|
||||
peripheral_free_list(dev_get_platdata(&pdev->dev));
|
||||
out_error_free_mem:
|
||||
kfree(sport);
|
||||
bfin_sport_uart_ports[pdev->id] = NULL;
|
||||
@ -864,8 +862,7 @@ static int sport_uart_remove(struct platform_device *pdev)
|
||||
if (sport) {
|
||||
uart_remove_one_port(&sport_uart_reg, &sport->port);
|
||||
iounmap(sport->port.membase);
|
||||
peripheral_free_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev));
|
||||
peripheral_free_list(dev_get_platdata(&pdev->dev));
|
||||
kfree(sport);
|
||||
bfin_sport_uart_ports[pdev->id] = NULL;
|
||||
}
|
||||
|
@ -680,7 +680,7 @@ static int bfin_serial_startup(struct uart_port *port)
|
||||
default:
|
||||
uart_dma_ch_rx = uart_dma_ch_tx = 0;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if (uart_dma_ch_rx &&
|
||||
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
|
||||
if (uart->cts_pin >= 0) {
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
free_irq(uart->rx_irq, uart);
|
||||
free_irq(uart->tx_irq, uart);
|
||||
@ -1240,7 +1240,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
|
||||
*/
|
||||
#endif
|
||||
ret = peripheral_request_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev),
|
||||
dev_get_platdata(&pdev->dev),
|
||||
DRIVER_NAME);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
@ -1358,8 +1358,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
|
||||
out_error_unmap:
|
||||
iounmap(uart->port.membase);
|
||||
out_error_free_peripherals:
|
||||
peripheral_free_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev));
|
||||
peripheral_free_list(dev_get_platdata(&pdev->dev));
|
||||
out_error_free_mem:
|
||||
kfree(uart);
|
||||
bfin_serial_ports[pdev->id] = NULL;
|
||||
@ -1377,8 +1376,7 @@ static int bfin_serial_remove(struct platform_device *pdev)
|
||||
if (uart) {
|
||||
uart_remove_one_port(&bfin_serial_reg, &uart->port);
|
||||
iounmap(uart->port.membase);
|
||||
peripheral_free_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev));
|
||||
peripheral_free_list(dev_get_platdata(&pdev->dev));
|
||||
kfree(uart);
|
||||
bfin_serial_ports[pdev->id] = NULL;
|
||||
}
|
||||
@ -1432,8 +1430,8 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = peripheral_request_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME);
|
||||
ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
|
||||
DRIVER_NAME);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"fail to request bfin serial peripherals\n");
|
||||
@ -1463,8 +1461,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
out_error_free_peripherals:
|
||||
peripheral_free_list(
|
||||
(unsigned short *)dev_get_platdata(&pdev->dev));
|
||||
peripheral_free_list(dev_get_platdata(&pdev->dev));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -459,7 +459,6 @@ static int uart_clps711x_probe(struct platform_device *pdev)
|
||||
ret = uart_register_driver(&s->uart);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Registering UART driver failed\n");
|
||||
devm_clk_put(&pdev->dev, s->uart_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -487,7 +486,6 @@ static int uart_clps711x_remove(struct platform_device *pdev)
|
||||
for (i = 0; i < UART_CLPS711X_NR; i++)
|
||||
uart_remove_one_port(&s->uart, &s->port[i]);
|
||||
|
||||
devm_clk_put(&pdev->dev, s->uart_clk);
|
||||
uart_unregister_driver(&s->uart);
|
||||
|
||||
return 0;
|
||||
|
@ -1008,7 +1008,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev);
|
||||
pl_data = dev_get_platdata(&spi->dev);
|
||||
if (!pl_data) {
|
||||
dev_err(&spi->dev, "missing platform data!");
|
||||
return -ENODEV;
|
||||
|
@ -223,8 +223,7 @@ struct imx_port {
|
||||
struct dma_chan *dma_chan_rx, *dma_chan_tx;
|
||||
struct scatterlist rx_sgl, tx_sgl[2];
|
||||
void *rx_buf;
|
||||
unsigned int rx_bytes, tx_bytes;
|
||||
struct work_struct tsk_dma_rx, tsk_dma_tx;
|
||||
unsigned int tx_bytes;
|
||||
unsigned int dma_tx_nents;
|
||||
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__);
|
||||
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 scatterlist *sgl = sport->tx_sgl;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_chan *chan = sport->dma_chan_tx;
|
||||
struct device *dev = sport->port.dev;
|
||||
enum dma_status status;
|
||||
unsigned long flags;
|
||||
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)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
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;
|
||||
sg_init_table(sgl, 2);
|
||||
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;
|
||||
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);
|
||||
if (ret == 0) {
|
||||
@ -609,11 +598,7 @@ static void imx_start_tx(struct uart_port *port)
|
||||
}
|
||||
|
||||
if (sport->dma_is_enabled) {
|
||||
/*
|
||||
* We may in the interrupt context, so arise a work_struct to
|
||||
* do the real job.
|
||||
*/
|
||||
schedule_work(&sport->tsk_dma_tx);
|
||||
imx_dma_tx(sport);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -732,6 +717,7 @@ out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int start_rx_dma(struct imx_port *sport);
|
||||
/*
|
||||
* If the RXFIFO is filled with some data, and then we
|
||||
* 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);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
{
|
||||
unsigned long temp;
|
||||
@ -912,6 +889,7 @@ static void dma_rx_callback(void *data)
|
||||
struct imx_port *sport = data;
|
||||
struct dma_chan *chan = sport->dma_chan_rx;
|
||||
struct scatterlist *sgl = &sport->rx_sgl;
|
||||
struct tty_port *port = &sport->port.state->port;
|
||||
struct dma_tx_state state;
|
||||
enum dma_status status;
|
||||
unsigned int count;
|
||||
@ -919,13 +897,15 @@ static void dma_rx_callback(void *data)
|
||||
/* unmap it first */
|
||||
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;
|
||||
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
|
||||
|
||||
if (count) {
|
||||
sport->rx_bytes = count;
|
||||
schedule_work(&sport->tsk_dma_rx);
|
||||
tty_insert_flip_string(port, sport->rx_buf, count);
|
||||
tty_flip_buffer_push(port);
|
||||
|
||||
start_rx_dma(sport);
|
||||
} else
|
||||
imx_rx_dma_done(sport);
|
||||
}
|
||||
@ -1007,7 +987,6 @@ static int imx_uart_dma_init(struct imx_port *sport)
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
sport->rx_bytes = 0;
|
||||
|
||||
/* Prepare for 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)
|
||||
{
|
||||
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);
|
||||
|
||||
/* set UCR1 */
|
||||
@ -1063,7 +1038,6 @@ static void imx_enable_dma(struct imx_port *sport)
|
||||
static void imx_disable_dma(struct imx_port *sport)
|
||||
{
|
||||
unsigned long temp;
|
||||
struct tty_port *port = &sport->port.state->port;
|
||||
|
||||
/* clear 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);
|
||||
|
||||
sport->dma_is_enabled = 0;
|
||||
port->low_latency = 0;
|
||||
}
|
||||
|
||||
/* half the RX buffer size */
|
||||
@ -1303,6 +1276,16 @@ static void imx_shutdown(struct uart_port *port)
|
||||
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
|
||||
imx_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
@ -1539,7 +1522,7 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.uartclk / 16 != ser->baud_base)
|
||||
ret = -EINVAL;
|
||||
if ((void *)sport->port.mapbase != ser->iomem_base)
|
||||
if (sport->port.mapbase != (unsigned long)ser->iomem_base)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.iobase != ser->port)
|
||||
ret = -EINVAL;
|
||||
@ -1623,6 +1606,7 @@ static struct uart_ops imx_pops = {
|
||||
.break_ctl = imx_break_ctl,
|
||||
.startup = imx_startup,
|
||||
.shutdown = imx_shutdown,
|
||||
.flush_buffer = imx_flush_buffer,
|
||||
.set_termios = imx_set_termios,
|
||||
.type = imx_type,
|
||||
.release_port = imx_release_port,
|
||||
|
@ -832,7 +832,7 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag,
|
||||
up->curregs[5] |= Tx8;
|
||||
up->parity_mask = 0xff;
|
||||
break;
|
||||
};
|
||||
}
|
||||
up->curregs[4] &= ~0x0c;
|
||||
if (cflag & CSTOPB)
|
||||
up->curregs[4] |= SB2;
|
||||
|
@ -690,7 +690,7 @@ static void max310x_handle_tx(struct uart_port *port)
|
||||
max310x_port_write(port, MAX310X_THR_REG,
|
||||
xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
|
@ -293,7 +293,7 @@ static void serial_hsu_enable_ms(struct uart_port *port)
|
||||
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 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 */
|
||||
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;
|
||||
|
||||
@ -386,7 +387,8 @@ static void serial_hsu_stop_tx(struct uart_port *port)
|
||||
|
||||
/* This is always called in spinlock protected mode, so
|
||||
* 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_chan *chan = up->rxc;
|
||||
@ -1183,7 +1185,7 @@ static struct console serial_hsu_console = {
|
||||
#define SERIAL_HSU_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
struct uart_ops serial_hsu_pops = {
|
||||
static struct uart_ops serial_hsu_pops = {
|
||||
.tx_empty = serial_hsu_tx_empty,
|
||||
.set_mctrl = serial_hsu_set_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);
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
free_irq(pdev->irq, priv);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
@ -1504,4 +1505,4 @@ module_init(hsu_pci_init);
|
||||
module_exit(hsu_pci_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:medfield-hsu");
|
||||
MODULE_DEVICE_TABLE(pci, pci_ids);
|
||||
|
@ -1301,7 +1301,6 @@ static struct uart_ops mpc52xx_uart_ops = {
|
||||
.shutdown = mpc52xx_uart_shutdown,
|
||||
.set_termios = mpc52xx_uart_set_termios,
|
||||
/* .pm = mpc52xx_uart_pm, Not supported yet */
|
||||
/* .set_wake = mpc52xx_uart_set_wake, Not supported yet */
|
||||
.type = mpc52xx_uart_type,
|
||||
.release_port = mpc52xx_uart_release_port,
|
||||
.request_port = mpc52xx_uart_request_port,
|
||||
@ -1766,7 +1765,7 @@ mpc52xx_uart_of_remove(struct platform_device *op)
|
||||
static int
|
||||
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)
|
||||
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
|
||||
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)
|
||||
uart_resume_port(&mpc52xx_uart_driver, port);
|
||||
|
@ -2030,7 +2030,7 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi,
|
||||
{
|
||||
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.iotype = UPIO_MEM;
|
||||
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include "mrst_max3110.h"
|
||||
|
||||
@ -61,6 +62,7 @@ struct uart_max3110 {
|
||||
struct task_struct *main_thread;
|
||||
struct task_struct *read_thread;
|
||||
struct mutex thread_mutex;
|
||||
struct mutex io_mutex;
|
||||
|
||||
u32 baud;
|
||||
u16 cur_conf;
|
||||
@ -90,6 +92,7 @@ static int max3110_write_then_read(struct uart_max3110 *max,
|
||||
struct spi_transfer x;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&max->io_mutex);
|
||||
spi_message_init(&message);
|
||||
memset(&x, 0, sizeof x);
|
||||
x.len = len;
|
||||
@ -104,6 +107,7 @@ static int max3110_write_then_read(struct uart_max3110 *max,
|
||||
|
||||
/* Do the i/o */
|
||||
ret = spi_sync(spi, &message);
|
||||
mutex_unlock(&max->io_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -491,19 +495,9 @@ static int serial_m3110_startup(struct uart_port *port)
|
||||
port->state->port.low_latency = 1;
|
||||
|
||||
if (max->irq) {
|
||||
max->read_thread = NULL;
|
||||
ret = request_irq(max->irq, serial_m3110_irq,
|
||||
IRQ_TYPE_EDGE_FALLING, "max3110", max);
|
||||
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) {
|
||||
/* Enable RX IRQ only */
|
||||
config |= WC_RXA_IRQ_ENABLE;
|
||||
} else {
|
||||
/* If IRQ is disabled, start a read thread for input data */
|
||||
max->read_thread =
|
||||
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);
|
||||
if (ret) {
|
||||
if (max->irq)
|
||||
free_irq(max->irq, max);
|
||||
if (max->read_thread)
|
||||
kthread_stop(max->read_thread);
|
||||
max->read_thread = NULL;
|
||||
@ -540,9 +532,6 @@ static void serial_m3110_shutdown(struct uart_port *port)
|
||||
max->read_thread = NULL;
|
||||
}
|
||||
|
||||
if (max->irq)
|
||||
free_irq(max->irq, max);
|
||||
|
||||
/* Disable interrupts from this port */
|
||||
config = WC_TAG | WC_SW_SHDI;
|
||||
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 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);
|
||||
max3110_out(max, max->cur_conf | WC_SW_SHDI);
|
||||
return 0;
|
||||
@ -762,7 +752,8 @@ static int serial_m3110_resume(struct device *dev)
|
||||
|
||||
max3110_out(max, max->cur_conf);
|
||||
uart_resume_port(&serial_m3110_reg, &max->port);
|
||||
enable_irq(max->irq);
|
||||
if (max->irq > 0)
|
||||
enable_irq(max->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -803,6 +794,7 @@ static int serial_m3110_probe(struct spi_device *spi)
|
||||
max->irq = (u16)spi->irq;
|
||||
|
||||
mutex_init(&max->thread_mutex);
|
||||
mutex_init(&max->io_mutex);
|
||||
|
||||
max->word_7bits = 0;
|
||||
max->parity = 0;
|
||||
@ -840,6 +832,16 @@ static int serial_m3110_probe(struct spi_device *spi)
|
||||
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);
|
||||
pmax = max;
|
||||
|
||||
@ -867,6 +869,9 @@ static int serial_m3110_remove(struct spi_device *dev)
|
||||
|
||||
free_page((unsigned long)max->con_xmit.buf);
|
||||
|
||||
if (max->irq)
|
||||
free_irq(max->irq, max);
|
||||
|
||||
if (max->main_thread)
|
||||
kthread_stop(max->main_thread);
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#define MXS_AUART_PORTS 5
|
||||
#define MXS_AUART_FIFO_SIZE 16
|
||||
|
||||
#define AUART_CTRL0 0x00000000
|
||||
#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;
|
||||
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;
|
||||
|
||||
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,
|
||||
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
|
||||
* 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.ops = &mxs_auart_ops;
|
||||
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.type = PORT_IMX;
|
||||
s->port.dev = s->dev = &pdev->dev;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_data/serial-omap.h>
|
||||
@ -134,6 +135,7 @@ struct uart_omap_port {
|
||||
struct uart_port port;
|
||||
struct uart_omap_dma uart_dma;
|
||||
struct device *dev;
|
||||
int wakeirq;
|
||||
|
||||
unsigned char ier;
|
||||
unsigned char lcr;
|
||||
@ -175,7 +177,7 @@ struct uart_omap_port {
|
||||
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];
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
|
||||
|
||||
serial_omap_enable_wakeirq(up, enable);
|
||||
if (!pdata || !pdata->enable_wakeup)
|
||||
return;
|
||||
|
||||
@ -242,12 +257,12 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
|
||||
unsigned int n16 = port->uartclk / (16 * baud);
|
||||
int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
|
||||
int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
|
||||
if(baudAbsDiff13 < 0)
|
||||
if (baudAbsDiff13 < 0)
|
||||
baudAbsDiff13 = -baudAbsDiff13;
|
||||
if(baudAbsDiff16 < 0)
|
||||
if (baudAbsDiff16 < 0)
|
||||
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
|
||||
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))
|
||||
divisor = 13;
|
||||
mode = 13;
|
||||
else
|
||||
divisor = 16;
|
||||
return port->uartclk/(baud * divisor);
|
||||
mode = 16;
|
||||
return port->uartclk/(mode * baud);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct uart_omap_port *up = to_uart_omap_port(port);
|
||||
struct circ_buf *xmit = &up->port.state->xmit;
|
||||
int res;
|
||||
|
||||
pm_runtime_get_sync(up->dev);
|
||||
|
||||
/* handle rs485 */
|
||||
/* Handle RS-485 */
|
||||
if (up->rs485.flags & SER_RS485_ENABLED) {
|
||||
/* do nothing if current tx not yet completed */
|
||||
res = serial_in(up, UART_LSR) & UART_LSR_TEMT;
|
||||
if (!res)
|
||||
return;
|
||||
|
||||
/* if there's no more data to send, turn off rts */
|
||||
if (uart_circ_empty(xmit)) {
|
||||
/* if rts not already disabled */
|
||||
if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
|
||||
/* THR interrupt is fired when both TX FIFO and TX
|
||||
* shift register are empty. This means there's nothing
|
||||
* left to transmit now, so make sure the THR interrupt
|
||||
* is fired when TX FIFO is below the trigger level,
|
||||
* disable THR interrupts and toggle the RS-485 GPIO
|
||||
* data direction pin if needed.
|
||||
*/
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
/* handle rs485 */
|
||||
/* Handle RS-485 */
|
||||
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 */
|
||||
res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
|
||||
if (gpio_get_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -699,6 +729,20 @@ static int serial_omap_startup(struct uart_port *port)
|
||||
if (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);
|
||||
|
||||
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_put_autosuspend(up->dev);
|
||||
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)
|
||||
@ -938,7 +984,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
*/
|
||||
|
||||
/* 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_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);
|
||||
}
|
||||
|
||||
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
|
||||
serial_omap_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
@ -1353,6 +1390,15 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
|
||||
up->ier = mode;
|
||||
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);
|
||||
pm_runtime_mark_last_busy(up->dev);
|
||||
pm_runtime_put_autosuspend(up->dev);
|
||||
@ -1401,7 +1447,6 @@ static struct uart_ops serial_omap_pops = {
|
||||
.shutdown = serial_omap_shutdown,
|
||||
.set_termios = serial_omap_set_termios,
|
||||
.pm = serial_omap_pm,
|
||||
.set_wake = serial_omap_set_wake,
|
||||
.type = serial_omap_type,
|
||||
.release_port = serial_omap_release_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 resource *mem, *irq;
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
@ -1595,12 +1652,6 @@ static int serial_omap_probe(struct platform_device *pdev)
|
||||
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),
|
||||
pdev->dev.driver->name)) {
|
||||
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.type = PORT_OMAP;
|
||||
up->port.iotype = UPIO_MEM;
|
||||
up->port.irq = irq->start;
|
||||
up->port.irq = uartirq;
|
||||
up->wakeirq = wakeirq;
|
||||
|
||||
up->port.regshift = 2;
|
||||
up->port.fifosize = 64;
|
||||
@ -1670,8 +1722,9 @@ static int serial_omap_probe(struct platform_device *pdev)
|
||||
up->port.uartclk = omap_up_info->uartclk;
|
||||
if (!up->port.uartclk) {
|
||||
up->port.uartclk = DEFAULT_CLK_SPEED;
|
||||
dev_warn(&pdev->dev, "No clock speed specified: using default:"
|
||||
"%d\n", DEFAULT_CLK_SPEED);
|
||||
dev_warn(&pdev->dev,
|
||||
"No clock speed specified: using default: %d\n",
|
||||
DEFAULT_CLK_SPEED);
|
||||
}
|
||||
|
||||
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
|
||||
|
@ -1614,7 +1614,6 @@ static struct uart_ops pch_uart_ops = {
|
||||
.shutdown = pch_uart_shutdown,
|
||||
.set_termios = pch_uart_set_termios,
|
||||
/* .pm = pch_uart_pm, Not supported yet */
|
||||
/* .set_wake = pch_uart_set_wake, Not supported yet */
|
||||
.type = pch_uart_type,
|
||||
.release_port = pch_uart_release_port,
|
||||
.request_port = pch_uart_request_port,
|
||||
@ -1996,6 +1995,8 @@ module_exit(pch_uart_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver");
|
||||
MODULE_DEVICE_TABLE(pci, pch_uart_pci_id);
|
||||
|
||||
module_param(default_baud, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(default_baud,
|
||||
"Default BAUD for initial driver state and console (default 9600)");
|
||||
|
@ -1072,7 +1072,7 @@ static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag,
|
||||
uap->curregs[5] |= Tx8;
|
||||
uap->parity_mask = 0xff;
|
||||
break;
|
||||
};
|
||||
}
|
||||
uap->curregs[4] &= ~(SB_MASK);
|
||||
if (cflag & CSTOPB)
|
||||
uap->curregs[4] |= SB2;
|
||||
|
@ -647,7 +647,10 @@ void sa1100_register_uart_fns(struct sa1100_port_fns *fns)
|
||||
sa1100_pops.set_mctrl = fns->set_mctrl;
|
||||
|
||||
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)
|
||||
|
@ -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)
|
||||
{
|
||||
/* 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)
|
||||
@ -774,8 +781,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
ulcon |= S3C2410_LCON_STOPB;
|
||||
|
||||
umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;
|
||||
|
||||
if (termios->c_cflag & PARENB) {
|
||||
if (termios->c_cflag & PARODD)
|
||||
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_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);
|
||||
|
||||
if (ourport->info->has_divslot)
|
||||
@ -1254,7 +1268,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
||||
ourport->baudclk = ERR_PTR(-EINVAL);
|
||||
ourport->info = ourport->drv_data->info;
|
||||
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->port.fifosize = (ourport->info->fifosize) ?
|
||||
|
@ -63,7 +63,7 @@ struct s3c24xx_uart_port {
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
@ -986,6 +986,7 @@ static int sccnxp_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uart_unregister_driver(&s->uart);
|
||||
err_out:
|
||||
if (!IS_ERR(s->regulator))
|
||||
return regulator_disable(s->regulator);
|
||||
|
@ -1018,7 +1018,7 @@ static int tegra_uart_startup(struct uart_port *u)
|
||||
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);
|
||||
if (ret < 0) {
|
||||
dev_err(u->dev, "Failed to register ISR for IRQ %d\n", u->irq);
|
||||
|
@ -1220,8 +1220,6 @@ static void pciserial_txx9_remove_one(struct pci_dev *dev)
|
||||
{
|
||||
struct uart_txx9_port *up = pci_get_drvdata(dev);
|
||||
|
||||
pci_set_drvdata(dev, NULL);
|
||||
|
||||
if (up) {
|
||||
serial_txx9_unregister_port(up->port.line);
|
||||
pci_disable_device(dev);
|
||||
|
@ -529,7 +529,7 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param)
|
||||
while (sirfport->rx_completed != sirfport->rx_issued) {
|
||||
sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
|
||||
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;
|
||||
}
|
||||
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 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;
|
||||
spin_lock_irqsave(&sirfport->rx_lock, flags);
|
||||
while (sirfport->rx_completed != sirfport->rx_issued) {
|
||||
sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
|
||||
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;
|
||||
}
|
||||
spin_unlock_irqrestore(&sirfport->rx_lock, flags);
|
||||
|
@ -368,15 +368,6 @@ struct sirfsoc_uart_register sirfsoc_uart = {
|
||||
#define SIRFSOC_UART_NR 6
|
||||
#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*/
|
||||
#define SIRFSOC_RX_DMA_BUF_SIZE 256
|
||||
#define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3)
|
||||
@ -453,9 +444,6 @@ struct sirfsoc_uart_port {
|
||||
int rx_issued;
|
||||
};
|
||||
|
||||
/* Hardware Flow Control */
|
||||
#define SIRFUART_AFC_CTRL_RX_THD 0x70
|
||||
|
||||
/* Register Access Control */
|
||||
#define portaddr(port, reg) ((port)->membase + (reg))
|
||||
#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
|
||||
|
@ -894,7 +894,7 @@ static int sunsab_console_setup(struct console *con, char *options)
|
||||
case B115200: baud = 115200; break;
|
||||
case B230400: baud = 230400; break;
|
||||
case B460800: baud = 460800; break;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Temporary fix.
|
||||
|
@ -522,7 +522,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break)
|
||||
serio_interrupt(&up->serio, ch, 0);
|
||||
#endif
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
} while (serial_in(up, UART_LSR) & UART_LSR_DR);
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
|
||||
serio_interrupt(&up->serio, ch, 0);
|
||||
#endif
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -897,7 +897,7 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
|
||||
up->curregs[R5] |= Tx8;
|
||||
up->parity_mask = 0xff;
|
||||
break;
|
||||
};
|
||||
}
|
||||
up->curregs[R4] &= ~0x0c;
|
||||
if (cflag & CSTOPB)
|
||||
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;
|
||||
case B19200: baud = 19200; break;
|
||||
case B38400: baud = 38400; break;
|
||||
};
|
||||
}
|
||||
|
||||
brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
|
||||
|
||||
|
@ -269,7 +269,7 @@ static unsigned int qe_uart_tx_empty(struct uart_port *port)
|
||||
return 1;
|
||||
|
||||
bdp++;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Xilinx PS UART driver
|
||||
*
|
||||
* 2011 (c) Xilinx Inc.
|
||||
* 2011 - 2013 (C) Xilinx Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it
|
||||
* 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/serial.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
@ -29,12 +33,22 @@
|
||||
#define XUARTPS_MAJOR 0 /* use dynamic node allocation */
|
||||
#define XUARTPS_MINOR 0 /* works best with devtmpfs */
|
||||
#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_readl(offset) ioread32(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********************************/
|
||||
/** UART
|
||||
*
|
||||
@ -128,6 +142,9 @@
|
||||
#define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */
|
||||
#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
|
||||
*
|
||||
* 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_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
|
||||
* @refclk Reference clock
|
||||
* @aperclk APB clock
|
||||
* @port Pointer to the UART port
|
||||
* @refclk Reference clock
|
||||
* @aperclk APB clock
|
||||
* @baud Current baud rate
|
||||
* @clk_rate_change_nb Notifier block for clock changes
|
||||
*/
|
||||
struct xuartps {
|
||||
struct uart_port *port;
|
||||
struct clk *refclk;
|
||||
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
|
||||
@ -171,6 +200,23 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
|
||||
*/
|
||||
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 */
|
||||
if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY)
|
||||
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) &
|
||||
XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
|
||||
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++;
|
||||
|
||||
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
|
||||
* @port: Handle to the uart port structure
|
||||
* @baud: Baud rate to set
|
||||
*
|
||||
* xuartps_calc_baud_divs - Calculate baud rate divisors
|
||||
* @clk: UART module input clock
|
||||
* @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
|
||||
* was too much error
|
||||
**/
|
||||
static unsigned int xuartps_set_baud_rate(struct uart_port *port,
|
||||
unsigned int baud)
|
||||
* was too much error, zero if no valid divisors are found.
|
||||
*
|
||||
* Formula to obtain baud rate is
|
||||
* 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;
|
||||
unsigned int calc_baud = 0;
|
||||
unsigned int brgr_val, brdiv_val;
|
||||
u32 cd, bdiv;
|
||||
unsigned int calc_baud;
|
||||
unsigned int bestbaud = 0;
|
||||
unsigned int bauderror;
|
||||
unsigned int besterror = ~0;
|
||||
|
||||
/* Formula to obtain baud rate is
|
||||
* baud_tx/rx rate = sel_clk/CD * (BDIV + 1)
|
||||
* input_clk = (Uart User Defined Clock or Apb Clock)
|
||||
* depends on UCLKEN in MR Reg
|
||||
* sel_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
|
||||
*/
|
||||
sel_clk = port->uartclk;
|
||||
if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL)
|
||||
sel_clk = sel_clk / 8;
|
||||
if (baud < clk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX)) {
|
||||
*div8 = 1;
|
||||
clk /= 8;
|
||||
} else {
|
||||
*div8 = 0;
|
||||
}
|
||||
|
||||
/* Find the best values for baud generation */
|
||||
for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) {
|
||||
|
||||
brgr_val = sel_clk / (baud * (brdiv_val + 1));
|
||||
if (brgr_val < 2 || brgr_val > 65535)
|
||||
for (bdiv = XUARTPS_BDIV_MIN; bdiv <= XUARTPS_BDIV_MAX; bdiv++) {
|
||||
cd = DIV_ROUND_CLOSEST(clk, baud * (bdiv + 1));
|
||||
if (cd < 1 || cd > XUARTPS_CD_MAX)
|
||||
continue;
|
||||
|
||||
calc_baud = sel_clk / (brgr_val * (brdiv_val + 1));
|
||||
calc_baud = clk / (cd * (bdiv + 1));
|
||||
|
||||
if (baud > calc_baud)
|
||||
bauderror = baud - calc_baud;
|
||||
else
|
||||
bauderror = calc_baud - baud;
|
||||
|
||||
/* use the values when percent error is acceptable */
|
||||
if (((bauderror * 100) / baud) < 3) {
|
||||
calc_baud = baud;
|
||||
break;
|
||||
if (besterror > bauderror) {
|
||||
*rbdiv = bdiv;
|
||||
*rcd = cd;
|
||||
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 */
|
||||
xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET);
|
||||
xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET);
|
||||
return bestbaud;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
#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---------------------------*/
|
||||
|
||||
/**
|
||||
@ -346,7 +549,7 @@ static void xuartps_start_tx(struct uart_port *port)
|
||||
port->state->xmit.tail = (port->state->xmit.tail + 1) &
|
||||
(UART_XMIT_SIZE - 1);
|
||||
}
|
||||
|
||||
xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_ISR_OFFSET);
|
||||
/* Enable the TX Empty interrupt */
|
||||
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)
|
||||
{
|
||||
unsigned int cval = 0;
|
||||
unsigned int baud;
|
||||
unsigned int baud, minbaud, maxbaud;
|
||||
unsigned long flags;
|
||||
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_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);
|
||||
if (tty_termios_baud_rate(termios))
|
||||
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_OFFSET);
|
||||
|
||||
xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
|
||||
xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
|
||||
|
||||
port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG |
|
||||
XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT;
|
||||
@ -531,13 +740,17 @@ static void xuartps_set_termios(struct uart_port *port,
|
||||
cval |= XUARTPS_MR_PARITY_MARK;
|
||||
else
|
||||
cval |= XUARTPS_MR_PARITY_SPACE;
|
||||
} else if (termios->c_cflag & PARODD)
|
||||
} else {
|
||||
if (termios->c_cflag & PARODD)
|
||||
cval |= XUARTPS_MR_PARITY_ODD;
|
||||
else
|
||||
cval |= XUARTPS_MR_PARITY_EVEN;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
@ -583,11 +796,17 @@ static int xuartps_startup(struct uart_port *port)
|
||||
| XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT,
|
||||
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 */
|
||||
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 */
|
||||
}
|
||||
|
||||
#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
|
||||
*/
|
||||
static struct uart_ops xuartps_ops = {
|
||||
@ -759,6 +1026,10 @@ static struct uart_ops xuartps_ops = {
|
||||
.config_port = xuartps_config_port, /* Configure when driver
|
||||
* 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];
|
||||
@ -837,7 +1108,7 @@ static void xuartps_console_write(struct console *co, const char *s,
|
||||
{
|
||||
struct uart_port *port = &xuartps_port[co->index];
|
||||
unsigned long flags;
|
||||
unsigned int imr;
|
||||
unsigned int imr, ctrl;
|
||||
int locked = 1;
|
||||
|
||||
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);
|
||||
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);
|
||||
xuartps_console_wait_tx(port);
|
||||
|
||||
xuartps_writel(ctrl, XUARTPS_CR_OFFSET);
|
||||
|
||||
/* restore interrupt state, it seems like there may be a h/w bug
|
||||
* in that the interrupt enable register should not need to be
|
||||
* written based on the data sheet
|
||||
@ -933,6 +1214,119 @@ static struct uart_driver xuartps_uart_driver = {
|
||||
#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
|
||||
*/
|
||||
@ -949,27 +1343,26 @@ static int xuartps_probe(struct platform_device *pdev)
|
||||
struct resource *res, *res2;
|
||||
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)
|
||||
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)) {
|
||||
dev_err(&pdev->dev, "aper_clk clock not found.\n");
|
||||
rc = PTR_ERR(xuartps_data->aperclk);
|
||||
goto err_out_free;
|
||||
return PTR_ERR(xuartps_data->aperclk);
|
||||
}
|
||||
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)) {
|
||||
dev_err(&pdev->dev, "ref_clk clock not found.\n");
|
||||
rc = PTR_ERR(xuartps_data->refclk);
|
||||
goto err_out_clk_put_aper;
|
||||
return PTR_ERR(xuartps_data->refclk);
|
||||
}
|
||||
|
||||
rc = clk_prepare_enable(xuartps_data->aperclk);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Unable to enable APER clock.\n");
|
||||
goto err_out_clk_put;
|
||||
return rc;
|
||||
}
|
||||
rc = clk_prepare_enable(xuartps_data->refclk);
|
||||
if (rc) {
|
||||
@ -989,13 +1382,21 @@ static int xuartps_probe(struct platform_device *pdev)
|
||||
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 */
|
||||
port = xuartps_get_port();
|
||||
|
||||
if (!port) {
|
||||
dev_err(&pdev->dev, "Cannot get uart_port structure\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out_clk_disable;
|
||||
goto err_out_notif_unreg;
|
||||
} else {
|
||||
/* Register the port.
|
||||
* 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->uartclk = clk_get_rate(xuartps_data->refclk);
|
||||
port->private_data = xuartps_data;
|
||||
xuartps_data->port = port;
|
||||
platform_set_drvdata(pdev, port);
|
||||
rc = uart_add_one_port(&xuartps_uart_driver, port);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev,
|
||||
"uart_add_one_port() failed; err=%i\n", rc);
|
||||
goto err_out_clk_disable;
|
||||
goto err_out_notif_unreg;
|
||||
}
|
||||
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:
|
||||
clk_disable_unprepare(xuartps_data->refclk);
|
||||
err_out_clk_dis_aper:
|
||||
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;
|
||||
}
|
||||
@ -1043,13 +1444,14 @@ static int xuartps_remove(struct platform_device *pdev)
|
||||
int rc;
|
||||
|
||||
/* 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);
|
||||
port->mapbase = 0;
|
||||
clk_disable_unprepare(xuartps_data->refclk);
|
||||
clk_disable_unprepare(xuartps_data->aperclk);
|
||||
clk_put(xuartps_data->refclk);
|
||||
clk_put(xuartps_data->aperclk);
|
||||
kfree(xuartps_data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1067,6 +1469,7 @@ static struct platform_driver xuartps_platform_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = XUARTPS_NAME, /* Driver name */
|
||||
.of_match_table = xuartps_of_match,
|
||||
.pm = &xuartps_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -51,7 +51,7 @@
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
/* 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;
|
||||
|
||||
unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED };
|
||||
|
@ -140,6 +140,10 @@ EXPORT_SYMBOL(tty_port_destroy);
|
||||
static void tty_port_destructor(struct kref *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)
|
||||
free_page((unsigned long)port->xmit_buf);
|
||||
tty_port_destroy(port);
|
||||
@ -480,8 +484,6 @@ int tty_port_close_start(struct tty_port *port,
|
||||
|
||||
if (port->count) {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
if (port->ops->drop)
|
||||
port->ops->drop(port);
|
||||
return 0;
|
||||
}
|
||||
set_bit(ASYNCB_CLOSING, &port->flags);
|
||||
@ -500,9 +502,7 @@ int tty_port_close_start(struct tty_port *port,
|
||||
/* Flush the ldisc buffering */
|
||||
tty_ldisc_flush(tty);
|
||||
|
||||
/* Don't call port->drop for the last reference. Callers will want
|
||||
to drop the last active reference in ->shutdown() or the tty
|
||||
shutdown path */
|
||||
/* Report to caller this is the last port reference */
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_close_start);
|
||||
|
@ -1300,21 +1300,30 @@ static void csi_m(struct vc_data *vc)
|
||||
case 27:
|
||||
vc->vc_reverse = 0;
|
||||
break;
|
||||
case 38: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Enables underscore, white foreground
|
||||
* with white underscore (Linux - use
|
||||
* default foreground).
|
||||
case 38:
|
||||
case 48: /* ITU T.416
|
||||
* Higher colour modes.
|
||||
* 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);
|
||||
vc->vc_underline = 1;
|
||||
i++;
|
||||
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;
|
||||
case 39: /* ANSI X3.64-1979 (SCO-ish?)
|
||||
* Disable underline option.
|
||||
* Reset colour to default? It did this
|
||||
* before...
|
||||
*/
|
||||
case 39:
|
||||
vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
|
||||
vc->vc_underline = 0;
|
||||
break;
|
||||
case 49:
|
||||
vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
|
||||
|
@ -125,5 +125,6 @@
|
||||
#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
|
||||
|
||||
#define ATMEL_US_NAME 0xf0 /* Ip Name */
|
||||
#define ATMEL_US_VERSION 0xfc /* Ip Version */
|
||||
|
||||
#endif
|
||||
|
@ -66,7 +66,6 @@ struct uart_ops {
|
||||
void (*set_ldisc)(struct uart_port *, int new);
|
||||
void (*pm)(struct uart_port *, unsigned int state,
|
||||
unsigned int oldstate);
|
||||
int (*set_wake)(struct uart_port *, unsigned int state);
|
||||
|
||||
/*
|
||||
* Return a string describing the type of the port
|
||||
|
@ -17,9 +17,6 @@
|
||||
#include <linux/errno.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 */
|
||||
/* 0x0001 is reserved for enable everything */
|
||||
#define SYSRQ_ENABLE_LOG 0x0002
|
||||
|
@ -180,7 +180,6 @@ struct tty_port_operations {
|
||||
IFF the port was initialized. Do not use to free resources. Called
|
||||
under the port mutex to serialize against activate/shutdowns */
|
||||
void (*shutdown)(struct tty_port *port);
|
||||
void (*drop)(struct tty_port *port);
|
||||
/* Called under the port mutex from tty_port_open, serialized using
|
||||
the port mutex */
|
||||
/* FIXME: long term getting the tty argument *out* of this would be
|
||||
|
@ -190,7 +190,7 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
/* 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,
|
||||
void __user *buffer, size_t *lenp,
|
||||
|
@ -312,6 +312,15 @@ config MAGIC_SYSRQ
|
||||
keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
|
||||
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
|
||||
bool "Kernel debugging"
|
||||
help
|
||||
|
Loading…
x
Reference in New Issue
Block a user