mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-25 08:20:50 +07:00
TTY/Serial patches for 4.18-rc1
Here is the big tty/serial driver update for 4.18-rc1. There's nothing major here, just lots of serial driver updates. Full details are in the shortlog, nothing anything specific to call out here. All have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWxbZzQ8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ym2pQCggrWJsOeXLXgzhVDH6/qMFP9R/hEAoLTvmOWQ BlPIlvRDm/ud33VogJ8t =XS8u -----END PGP SIGNATURE----- Merge tag 'tty-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial updates from Greg KH: "Here is the big tty/serial driver update for 4.18-rc1. There's nothing major here, just lots of serial driver updates. Full details are in the shortlog, nothing anything specific to call out here. All have been in linux-next for a while with no reported issues" * tag 'tty-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (55 commits) vt: Perform safe console erase only once serial: imx: disable UCR4_OREN on shutdown serial: imx: drop CTS/RTS handling from shutdown tty: fix typo in ASYNCB_FOURPORT comment serial: samsung: check DMA engine capabilities before using DMA mode tty: Fix data race in tty_insert_flip_string_fixed_flag tty: serial: msm_geni_serial: Fix TX infinite loop serial: 8250_dw: Fix runtime PM handling serial: 8250: omap: Fix idling of clocks for unused uarts tty: serial: drop ATH79 specific SoC symbols serial: 8250: Add missing rxtrig_bytes on Altera 16550 UART serial/aspeed-vuart: fix a couple mod_timer() calls serial: sh-sci: Use spin_{try}lock_irqsave instead of open coding version serial: 8250_of: Add IO space support tty/serial: atmel: use port->name as name in request_irq() serial: imx: dma_unmap_sg buffers on shutdown serial: imx: cleanup imx_uart_disable_dma() tty: serial: qcom_geni_serial: Add early console support tty: serial: qcom_geni_serial: Return IRQ_NONE for spurious interrupts tty: serial: qcom_geni_serial: Use iowrite32_rep to write to FIFO ...
This commit is contained in:
commit
a22e48cf31
@ -1020,6 +1020,12 @@
|
||||
address. The serial port must already be setup
|
||||
and configured. Options are not yet supported.
|
||||
|
||||
qcom_geni,<addr>
|
||||
Start an early, polled-mode console on a Qualcomm
|
||||
Generic Interface (GENI) based serial port at the
|
||||
specified address. The serial port must already be
|
||||
setup and configured. Options are not yet supported.
|
||||
|
||||
earlyprintk= [X86,SH,ARM,M68k,S390]
|
||||
earlyprintk=vga
|
||||
earlyprintk=efi
|
||||
|
@ -163,7 +163,7 @@ i2c1: i2c@11100 {
|
||||
};
|
||||
|
||||
uart0: serial@12000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "marvell,armada-38x-uart";
|
||||
reg = <0x12000 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -173,7 +173,7 @@ uart0: serial@12000 {
|
||||
};
|
||||
|
||||
uart1: serial@12100 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "marvell,armada-38x-uart";
|
||||
reg = <0x12100 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
@ -416,7 +416,7 @@ void ipwireless_network_packet_received(struct ipw_network *network,
|
||||
struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
|
||||
{
|
||||
struct ipw_network *network =
|
||||
kzalloc(sizeof(struct ipw_network), GFP_ATOMIC);
|
||||
kzalloc(sizeof(struct ipw_network), GFP_KERNEL);
|
||||
|
||||
if (!network)
|
||||
return NULL;
|
||||
|
@ -2675,7 +2675,7 @@ static inline void muxnet_put(struct gsm_mux_net *mux_net)
|
||||
kref_put(&mux_net->ref, net_free);
|
||||
}
|
||||
|
||||
static int gsm_mux_net_start_xmit(struct sk_buff *skb,
|
||||
static netdev_tx_t gsm_mux_net_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *net)
|
||||
{
|
||||
struct gsm_mux_net *mux_net = netdev_priv(net);
|
||||
|
@ -72,19 +72,19 @@ do { \
|
||||
|
||||
#define TMP_BUF_MAX 256
|
||||
|
||||
#define DUMP(buf__,len__) \
|
||||
do { \
|
||||
char tbuf[TMP_BUF_MAX] = {0};\
|
||||
if (len__ > 1) {\
|
||||
snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\
|
||||
if (tbuf[len__-2] == '\r') {\
|
||||
tbuf[len__-2] = 'r';\
|
||||
} \
|
||||
DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\
|
||||
} else {\
|
||||
DBG1("SENDING: '%s' (%d)", tbuf, len__);\
|
||||
} \
|
||||
} while (0)
|
||||
#define DUMP(buf__, len__) \
|
||||
do { \
|
||||
char tbuf[TMP_BUF_MAX] = {0}; \
|
||||
if (len__ > 1) { \
|
||||
u32 data_len = min_t(u32, len__, TMP_BUF_MAX); \
|
||||
strscpy(tbuf, buf__, data_len); \
|
||||
if (tbuf[data_len - 2] == '\r') \
|
||||
tbuf[data_len - 2] = 'r'; \
|
||||
DBG1("SENDING: '%s' (%d+n)", tbuf, len__); \
|
||||
} else { \
|
||||
DBG1("SENDING: '%s' (%d)", tbuf, len__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Defines */
|
||||
#define NOZOMI_NAME "nozomi"
|
||||
@ -102,41 +102,41 @@ do { \
|
||||
#define RECEIVE_BUF_MAX 4
|
||||
|
||||
|
||||
#define R_IIR 0x0000 /* Interrupt Identity Register */
|
||||
#define R_FCR 0x0000 /* Flow Control Register */
|
||||
#define R_IER 0x0004 /* Interrupt Enable Register */
|
||||
#define R_IIR 0x0000 /* Interrupt Identity Register */
|
||||
#define R_FCR 0x0000 /* Flow Control Register */
|
||||
#define R_IER 0x0004 /* Interrupt Enable Register */
|
||||
|
||||
#define NOZOMI_CONFIG_MAGIC 0xEFEFFEFE
|
||||
#define TOGGLE_VALID 0x0000
|
||||
|
||||
/* Definition of interrupt tokens */
|
||||
#define MDM_DL1 0x0001
|
||||
#define MDM_UL1 0x0002
|
||||
#define MDM_DL2 0x0004
|
||||
#define MDM_UL2 0x0008
|
||||
#define DIAG_DL1 0x0010
|
||||
#define DIAG_DL2 0x0020
|
||||
#define DIAG_UL 0x0040
|
||||
#define APP1_DL 0x0080
|
||||
#define APP1_UL 0x0100
|
||||
#define APP2_DL 0x0200
|
||||
#define APP2_UL 0x0400
|
||||
#define CTRL_DL 0x0800
|
||||
#define CTRL_UL 0x1000
|
||||
#define RESET 0x8000
|
||||
#define MDM_DL1 0x0001
|
||||
#define MDM_UL1 0x0002
|
||||
#define MDM_DL2 0x0004
|
||||
#define MDM_UL2 0x0008
|
||||
#define DIAG_DL1 0x0010
|
||||
#define DIAG_DL2 0x0020
|
||||
#define DIAG_UL 0x0040
|
||||
#define APP1_DL 0x0080
|
||||
#define APP1_UL 0x0100
|
||||
#define APP2_DL 0x0200
|
||||
#define APP2_UL 0x0400
|
||||
#define CTRL_DL 0x0800
|
||||
#define CTRL_UL 0x1000
|
||||
#define RESET 0x8000
|
||||
|
||||
#define MDM_DL (MDM_DL1 | MDM_DL2)
|
||||
#define MDM_UL (MDM_UL1 | MDM_UL2)
|
||||
#define DIAG_DL (DIAG_DL1 | DIAG_DL2)
|
||||
#define MDM_DL (MDM_DL1 | MDM_DL2)
|
||||
#define MDM_UL (MDM_UL1 | MDM_UL2)
|
||||
#define DIAG_DL (DIAG_DL1 | DIAG_DL2)
|
||||
|
||||
/* modem signal definition */
|
||||
#define CTRL_DSR 0x0001
|
||||
#define CTRL_DCD 0x0002
|
||||
#define CTRL_RI 0x0004
|
||||
#define CTRL_CTS 0x0008
|
||||
#define CTRL_DSR 0x0001
|
||||
#define CTRL_DCD 0x0002
|
||||
#define CTRL_RI 0x0004
|
||||
#define CTRL_CTS 0x0008
|
||||
|
||||
#define CTRL_DTR 0x0001
|
||||
#define CTRL_RTS 0x0002
|
||||
#define CTRL_DTR 0x0001
|
||||
#define CTRL_RTS 0x0002
|
||||
|
||||
#define MAX_PORT 4
|
||||
#define NOZOMI_MAX_PORTS 5
|
||||
@ -155,7 +155,7 @@ enum card_type {
|
||||
|
||||
/* Initialization states a card can be in */
|
||||
enum card_state {
|
||||
NOZOMI_STATE_UKNOWN = 0,
|
||||
NOZOMI_STATE_UNKNOWN = 0,
|
||||
NOZOMI_STATE_ENABLED = 1, /* pci device enabled */
|
||||
NOZOMI_STATE_ALLOCATED = 2, /* config setup done */
|
||||
NOZOMI_STATE_READY = 3, /* flowcontrols received */
|
||||
@ -365,7 +365,7 @@ struct buffer {
|
||||
u8 *data;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Global variables */
|
||||
/* Global variables */
|
||||
static const struct pci_device_id nozomi_pci_tbl[] = {
|
||||
{PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */
|
||||
{},
|
||||
@ -1686,12 +1686,12 @@ static int ntty_tiocmget(struct tty_struct *tty)
|
||||
|
||||
/* Note: these could change under us but it is not clear this
|
||||
matters if so */
|
||||
return (ctrl_ul->RTS ? TIOCM_RTS : 0) |
|
||||
(ctrl_ul->DTR ? TIOCM_DTR : 0) |
|
||||
(ctrl_dl->DCD ? TIOCM_CAR : 0) |
|
||||
(ctrl_dl->RI ? TIOCM_RNG : 0) |
|
||||
(ctrl_dl->DSR ? TIOCM_DSR : 0) |
|
||||
(ctrl_dl->CTS ? TIOCM_CTS : 0);
|
||||
return (ctrl_ul->RTS ? TIOCM_RTS : 0)
|
||||
| (ctrl_ul->DTR ? TIOCM_DTR : 0)
|
||||
| (ctrl_dl->DCD ? TIOCM_CAR : 0)
|
||||
| (ctrl_dl->RI ? TIOCM_RNG : 0)
|
||||
| (ctrl_dl->DSR ? TIOCM_DSR : 0)
|
||||
| (ctrl_dl->CTS ? TIOCM_CTS : 0);
|
||||
}
|
||||
|
||||
/* Sets io controls parameters */
|
||||
@ -1722,10 +1722,10 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
|
||||
const struct async_icount cnow = port->tty_icount;
|
||||
int ret;
|
||||
|
||||
ret = ((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
|
||||
((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
|
||||
((flags & TIOCM_CD) && (cnow.dcd != cprev->dcd)) ||
|
||||
((flags & TIOCM_CTS) && (cnow.cts != cprev->cts));
|
||||
ret = ((flags & TIOCM_RNG) && (cnow.rng != cprev->rng))
|
||||
|| ((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr))
|
||||
|| ((flags & TIOCM_CD) && (cnow.dcd != cprev->dcd))
|
||||
|| ((flags & TIOCM_CTS) && (cnow.cts != cprev->cts));
|
||||
|
||||
*cprev = cnow;
|
||||
|
||||
|
@ -110,16 +110,19 @@ static void pty_unthrottle(struct tty_struct *tty)
|
||||
static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
|
||||
{
|
||||
struct tty_struct *to = tty->link;
|
||||
unsigned long flags;
|
||||
|
||||
if (tty->stopped)
|
||||
return 0;
|
||||
|
||||
if (c > 0) {
|
||||
spin_lock_irqsave(&to->port->lock, flags);
|
||||
/* Stuff the data into the input queue of the other end */
|
||||
c = tty_insert_flip_string(to->port, buf, c);
|
||||
/* And shovel */
|
||||
if (c)
|
||||
tty_flip_buffer_push(to->port);
|
||||
spin_unlock_irqrestore(&to->port->lock, flags);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "8250.h"
|
||||
@ -28,8 +30,17 @@ struct aspeed_vuart {
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
int line;
|
||||
struct timer_list unthrottle_timer;
|
||||
struct uart_8250_port *port;
|
||||
};
|
||||
|
||||
/*
|
||||
* If we fill the tty flip buffers, we throttle the data ready interrupt
|
||||
* to prevent dropped characters. This timeout defines how long we wait
|
||||
* to (conditionally, depending on buffer state) unthrottle.
|
||||
*/
|
||||
static const int unthrottle_timeout = HZ/10;
|
||||
|
||||
/*
|
||||
* The VUART is basically two UART 'front ends' connected by their FIFO
|
||||
* (no actual serial line in between). One is on the BMC side (management
|
||||
@ -179,6 +190,114 @@ static void aspeed_vuart_shutdown(struct uart_port *uart_port)
|
||||
serial8250_do_shutdown(uart_port);
|
||||
}
|
||||
|
||||
static void __aspeed_vuart_set_throttle(struct uart_8250_port *up,
|
||||
bool throttle)
|
||||
{
|
||||
unsigned char irqs = UART_IER_RLSI | UART_IER_RDI;
|
||||
|
||||
up->ier &= ~irqs;
|
||||
if (!throttle)
|
||||
up->ier |= irqs;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
}
|
||||
static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
__aspeed_vuart_set_throttle(up, throttle);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static void aspeed_vuart_throttle(struct uart_port *port)
|
||||
{
|
||||
aspeed_vuart_set_throttle(port, true);
|
||||
}
|
||||
|
||||
static void aspeed_vuart_unthrottle(struct uart_port *port)
|
||||
{
|
||||
aspeed_vuart_set_throttle(port, false);
|
||||
}
|
||||
|
||||
static void aspeed_vuart_unthrottle_exp(struct timer_list *timer)
|
||||
{
|
||||
struct aspeed_vuart *vuart = from_timer(vuart, timer, unthrottle_timer);
|
||||
struct uart_8250_port *up = vuart->port;
|
||||
|
||||
if (!tty_buffer_space_avail(&up->port.state->port)) {
|
||||
mod_timer(&vuart->unthrottle_timer,
|
||||
jiffies + unthrottle_timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
aspeed_vuart_unthrottle(&up->port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Custom interrupt handler to manage finer-grained flow control. Although we
|
||||
* have throttle/unthrottle callbacks, we've seen that the VUART device can
|
||||
* deliver characters faster than the ldisc has a chance to check buffer space
|
||||
* against the throttle threshold. This results in dropped characters before
|
||||
* the throttle.
|
||||
*
|
||||
* We do this by checking for flip buffer space before RX. If we have no space,
|
||||
* throttle now and schedule an unthrottle for later, once the ldisc has had
|
||||
* a chance to drain the buffers.
|
||||
*/
|
||||
static int aspeed_vuart_handle_irq(struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned int iir, lsr;
|
||||
unsigned long flags;
|
||||
int space, count;
|
||||
|
||||
iir = serial_port_in(port, UART_IIR);
|
||||
|
||||
if (iir & UART_IIR_NO_INT)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
lsr = serial_port_in(port, UART_LSR);
|
||||
|
||||
if (lsr & (UART_LSR_DR | UART_LSR_BI)) {
|
||||
space = tty_buffer_space_avail(&port->state->port);
|
||||
|
||||
if (!space) {
|
||||
/* throttle and schedule an unthrottle later */
|
||||
struct aspeed_vuart *vuart = port->private_data;
|
||||
__aspeed_vuart_set_throttle(up, true);
|
||||
|
||||
if (!timer_pending(&vuart->unthrottle_timer)) {
|
||||
vuart->port = up;
|
||||
mod_timer(&vuart->unthrottle_timer,
|
||||
jiffies + unthrottle_timeout);
|
||||
}
|
||||
|
||||
} else {
|
||||
count = min(space, 256);
|
||||
|
||||
do {
|
||||
serial8250_read_char(up, lsr);
|
||||
lsr = serial_in(up, UART_LSR);
|
||||
if (--count == 0)
|
||||
break;
|
||||
} while (lsr & (UART_LSR_DR | UART_LSR_BI));
|
||||
|
||||
tty_flip_buffer_push(&port->state->port);
|
||||
}
|
||||
}
|
||||
|
||||
serial8250_modem_status(up);
|
||||
if (lsr & UART_LSR_THRE)
|
||||
serial8250_tx_chars(up);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aspeed_vuart_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_8250_port port;
|
||||
@ -195,6 +314,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
vuart->dev = &pdev->dev;
|
||||
timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
vuart->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
@ -208,6 +328,9 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
||||
port.port.mapsize = resource_size(res);
|
||||
port.port.startup = aspeed_vuart_startup;
|
||||
port.port.shutdown = aspeed_vuart_shutdown;
|
||||
port.port.throttle = aspeed_vuart_throttle;
|
||||
port.port.unthrottle = aspeed_vuart_unthrottle;
|
||||
port.port.status = UPSTAT_SYNC_FIFO;
|
||||
port.port.dev = &pdev->dev;
|
||||
|
||||
rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
|
||||
@ -253,6 +376,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
|
||||
|
||||
port.port.irq = irq_of_parse_and_map(np, 0);
|
||||
port.port.irqflags = IRQF_SHARED;
|
||||
port.port.handle_irq = aspeed_vuart_handle_irq;
|
||||
port.port.iotype = UPIO_MEM;
|
||||
port.port.type = PORT_16550A;
|
||||
port.port.uartclk = clk;
|
||||
@ -292,6 +416,7 @@ static int aspeed_vuart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct aspeed_vuart *vuart = platform_get_drvdata(pdev);
|
||||
|
||||
del_timer_sync(&vuart->unthrottle_timer);
|
||||
aspeed_vuart_set_enabled(vuart, false);
|
||||
serial8250_unregister_port(vuart->line);
|
||||
sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
|
||||
|
@ -121,25 +121,44 @@ static void dw8250_check_lcr(struct uart_port *p, int value)
|
||||
}
|
||||
|
||||
/* Returns once the transmitter is empty or we run out of retries */
|
||||
static void dw8250_tx_wait_empty(struct uart_port *p, int tries)
|
||||
static void dw8250_tx_wait_empty(struct uart_port *p)
|
||||
{
|
||||
unsigned int tries = 20000;
|
||||
unsigned int delay_threshold = tries - 1000;
|
||||
unsigned int lsr;
|
||||
|
||||
while (tries--) {
|
||||
lsr = readb (p->membase + (UART_LSR << p->regshift));
|
||||
if (lsr & UART_LSR_TEMT)
|
||||
break;
|
||||
udelay (10);
|
||||
|
||||
/* The device is first given a chance to empty without delay,
|
||||
* to avoid slowdowns at high bitrates. If after 1000 tries
|
||||
* the buffer has still not emptied, allow more time for low-
|
||||
* speed links. */
|
||||
if (tries < delay_threshold)
|
||||
udelay (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
|
||||
static void dw8250_serial_out38x(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
||||
/* Allow the TX to drain before we reconfigure */
|
||||
if (offset == UART_LCR)
|
||||
dw8250_tx_wait_empty(p, 1000);
|
||||
dw8250_tx_wait_empty(p);
|
||||
|
||||
writeb(value, p->membase + (offset << p->regshift));
|
||||
|
||||
if (offset == UART_LCR && !d->uart_16550_compatible)
|
||||
dw8250_check_lcr(p, value);
|
||||
}
|
||||
|
||||
|
||||
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
|
||||
{
|
||||
struct dw8250_data *d = p->private_data;
|
||||
|
||||
writeb(value, p->membase + (offset << p->regshift));
|
||||
|
||||
@ -357,6 +376,9 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
|
||||
p->serial_in = dw8250_serial_in32be;
|
||||
p->serial_out = dw8250_serial_out32be;
|
||||
}
|
||||
if (of_device_is_compatible(np, "marvell,armada-38x-uart"))
|
||||
p->serial_out = dw8250_serial_out38x;
|
||||
|
||||
} else if (acpi_dev_present("APMC0D08", NULL, -1)) {
|
||||
p->iotype = UPIO_MEM32;
|
||||
p->regshift = 2;
|
||||
@ -554,6 +576,10 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
if (!data->skip_autocfg)
|
||||
dw8250_setup_port(p);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
uart.capabilities |= UART_CAP_RPM;
|
||||
#endif
|
||||
|
||||
/* If we have a valid fifosize, try hooking up DMA */
|
||||
if (p->fifosize) {
|
||||
data->dma.rxconf.src_maxburst = p->fifosize / 4;
|
||||
@ -666,6 +692,7 @@ static const struct dev_pm_ops dw8250_pm_ops = {
|
||||
static const struct of_device_id dw8250_of_match[] = {
|
||||
{ .compatible = "snps,dw-apb-uart" },
|
||||
{ .compatible = "cavium,octeon-3860-uart" },
|
||||
{ .compatible = "marvell,armada-38x-uart" },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
||||
|
@ -122,7 +122,7 @@ static void __init init_port(struct earlycon_device *device)
|
||||
serial8250_early_out(port, UART_FCR, 0); /* no fifo */
|
||||
serial8250_early_out(port, UART_MCR, 0x3); /* DTR + RTS */
|
||||
|
||||
if (port->uartclk && device->baud) {
|
||||
if (port->uartclk) {
|
||||
divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
|
||||
c = serial8250_early_in(port, UART_LCR);
|
||||
serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
|
||||
|
@ -92,13 +92,43 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||
goto err_unprepare;
|
||||
}
|
||||
|
||||
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
|
||||
UPF_FIXED_TYPE;
|
||||
spin_lock_init(&port->lock);
|
||||
port->mapbase = resource.start;
|
||||
port->mapsize = resource_size(&resource);
|
||||
|
||||
/* Check for shifted address mapping */
|
||||
if (of_property_read_u32(np, "reg-offset", &prop) == 0)
|
||||
port->mapbase += prop;
|
||||
if (resource_type(&resource) == IORESOURCE_IO) {
|
||||
port->iotype = UPIO_PORT;
|
||||
port->iobase = resource.start;
|
||||
} else {
|
||||
port->mapbase = resource.start;
|
||||
port->mapsize = resource_size(&resource);
|
||||
|
||||
/* Check for shifted address mapping */
|
||||
if (of_property_read_u32(np, "reg-offset", &prop) == 0)
|
||||
port->mapbase += prop;
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
|
||||
switch (prop) {
|
||||
case 1:
|
||||
port->iotype = UPIO_MEM;
|
||||
break;
|
||||
case 2:
|
||||
port->iotype = UPIO_MEM16;
|
||||
break;
|
||||
case 4:
|
||||
port->iotype = of_device_is_big_endian(np) ?
|
||||
UPIO_MEM32BE : UPIO_MEM32;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
|
||||
prop);
|
||||
ret = -EINVAL;
|
||||
goto err_dispose;
|
||||
}
|
||||
}
|
||||
port->flags |= UPF_IOREMAP;
|
||||
}
|
||||
|
||||
/* Check for registers offset within the devices address range */
|
||||
if (of_property_read_u32(np, "reg-shift", &prop) == 0)
|
||||
@ -114,26 +144,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||
port->line = ret;
|
||||
|
||||
port->irq = irq_of_parse_and_map(np, 0);
|
||||
port->iotype = UPIO_MEM;
|
||||
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
|
||||
switch (prop) {
|
||||
case 1:
|
||||
port->iotype = UPIO_MEM;
|
||||
break;
|
||||
case 2:
|
||||
port->iotype = UPIO_MEM16;
|
||||
break;
|
||||
case 4:
|
||||
port->iotype = of_device_is_big_endian(np) ?
|
||||
UPIO_MEM32BE : UPIO_MEM32;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
|
||||
prop);
|
||||
ret = -EINVAL;
|
||||
goto err_dispose;
|
||||
}
|
||||
}
|
||||
|
||||
info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL);
|
||||
if (IS_ERR(info->rst)) {
|
||||
@ -147,8 +157,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
|
||||
|
||||
port->type = type;
|
||||
port->uartclk = clk;
|
||||
port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
|
||||
| UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
||||
port->irqflags |= IRQF_SHARED;
|
||||
|
||||
if (of_property_read_bool(np, "no-loopback-test"))
|
||||
port->flags |= UPF_SKIP_TEST;
|
||||
|
@ -1110,13 +1110,14 @@ static int omap8250_no_handle_irq(struct uart_port *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE;
|
||||
static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
|
||||
static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE;
|
||||
|
||||
static const struct of_device_id omap8250_dt_ids[] = {
|
||||
{ .compatible = "ti,omap2-uart" },
|
||||
{ .compatible = "ti,omap3-uart" },
|
||||
{ .compatible = "ti,omap4-uart" },
|
||||
{ .compatible = "ti,omap4-uart", .data = &omap4_habit, },
|
||||
{ .compatible = "ti,am3352-uart", .data = &am3352_habit, },
|
||||
{ .compatible = "ti,am4372-uart", .data = &am3352_habit, },
|
||||
{ .compatible = "ti,dra742-uart", .data = &dra742_habit, },
|
||||
@ -1310,8 +1311,17 @@ static void omap8250_complete(struct device *dev)
|
||||
static int omap8250_suspend(struct device *dev)
|
||||
{
|
||||
struct omap8250_priv *priv = dev_get_drvdata(dev);
|
||||
struct uart_8250_port *up = serial8250_get_port(priv->line);
|
||||
|
||||
serial8250_suspend_port(priv->line);
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
if (!device_may_wakeup(dev))
|
||||
priv->wer = 0;
|
||||
serial_out(up, UART_OMAP_WER, priv->wer);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
flush_work(&priv->qos_work);
|
||||
return 0;
|
||||
}
|
||||
@ -1353,6 +1363,19 @@ static int omap8250_soft_reset(struct device *dev)
|
||||
int sysc;
|
||||
int syss;
|
||||
|
||||
/*
|
||||
* At least on omap4, unused uarts may not idle after reset without
|
||||
* a basic scr dma configuration even with no dma in use. The
|
||||
* module clkctrl status bits will be 1 instead of 3 blocking idle
|
||||
* for the whole clockdomain. The softreset below will clear scr,
|
||||
* and we restore it on resume so this is safe to do on all SoCs
|
||||
* needing omap8250_soft_reset() quirk. Do it in two writes as
|
||||
* recommended in the comment for omap8250_update_scr().
|
||||
*/
|
||||
serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1);
|
||||
serial_out(up, UART_OMAP_SCR,
|
||||
OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL);
|
||||
|
||||
sysc = serial_in(up, UART_OMAP_SYSC);
|
||||
|
||||
/* softreset the UART */
|
||||
@ -1403,6 +1426,8 @@ static int omap8250_runtime_suspend(struct device *dev)
|
||||
|
||||
/* Restore to UART mode after reset (for wakeup) */
|
||||
omap8250_update_mdr1(up, priv);
|
||||
/* Restore wakeup enable register */
|
||||
serial_out(up, UART_OMAP_WER, priv->wer);
|
||||
}
|
||||
|
||||
if (up->dma && up->dma->rxchan)
|
||||
|
@ -243,6 +243,7 @@ static const struct serial8250_config uart_config[] = {
|
||||
.fifo_size = 32,
|
||||
.tx_loadsz = 32,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
||||
.rxtrig_bytes = {1, 8, 16, 30},
|
||||
.flags = UART_CAP_FIFO | UART_CAP_AFE,
|
||||
},
|
||||
[PORT_ALTR_16550_F64] = {
|
||||
@ -250,6 +251,7 @@ static const struct serial8250_config uart_config[] = {
|
||||
.fifo_size = 64,
|
||||
.tx_loadsz = 64,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
||||
.rxtrig_bytes = {1, 16, 32, 62},
|
||||
.flags = UART_CAP_FIFO | UART_CAP_AFE,
|
||||
},
|
||||
[PORT_ALTR_16550_F128] = {
|
||||
@ -257,6 +259,7 @@ static const struct serial8250_config uart_config[] = {
|
||||
.fifo_size = 128,
|
||||
.tx_loadsz = 128,
|
||||
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
||||
.rxtrig_bytes = {1, 32, 64, 126},
|
||||
.flags = UART_CAP_FIFO | UART_CAP_AFE,
|
||||
},
|
||||
/*
|
||||
@ -1680,7 +1683,7 @@ static void serial8250_enable_ms(struct uart_port *port)
|
||||
serial8250_rpm_put(up);
|
||||
}
|
||||
|
||||
static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
|
||||
void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
|
||||
{
|
||||
struct uart_port *port = &up->port;
|
||||
unsigned char ch;
|
||||
@ -1740,6 +1743,7 @@ static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
|
||||
|
||||
uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_read_char);
|
||||
|
||||
/*
|
||||
* serial8250_rx_chars: processes according to the passed in LSR
|
||||
|
@ -115,7 +115,6 @@ config SERIAL_SB1250_DUART_CONSOLE
|
||||
|
||||
config SERIAL_ATMEL
|
||||
bool "AT91 on-chip serial port support"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_AT91 || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
@ -500,7 +499,6 @@ config SERIAL_SA1100_CONSOLE
|
||||
|
||||
config SERIAL_IMX
|
||||
tristate "IMX serial port support"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
select RATIONAL
|
||||
@ -676,6 +674,8 @@ config SERIAL_SH_SCI
|
||||
|
||||
config SERIAL_SH_SCI_NR_UARTS
|
||||
int "Maximum number of SCI(F) serial ports" if EXPERT
|
||||
range 1 64 if 64BIT
|
||||
range 1 32 if !64BIT
|
||||
depends on SERIAL_SH_SCI
|
||||
default "3" if H8300
|
||||
default "10" if SUPERH
|
||||
@ -1262,7 +1262,6 @@ config SERIAL_PCH_UART_CONSOLE
|
||||
|
||||
config SERIAL_MXS_AUART
|
||||
tristate "MXS AUART support"
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_MXS || MACH_ASM9260 || COMPILE_TEST
|
||||
select SERIAL_CORE
|
||||
select SERIAL_MCTRL_GPIO if GPIOLIB
|
||||
@ -1295,7 +1294,7 @@ config SERIAL_XILINX_PS_UART_CONSOLE
|
||||
|
||||
config SERIAL_AR933X
|
||||
tristate "AR933X serial port support"
|
||||
depends on HAVE_CLK && SOC_AR933X
|
||||
depends on HAVE_CLK && ATH79
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have an Atheros AR933X SOC based board and want to use the
|
||||
@ -1473,7 +1472,6 @@ config SERIAL_SPRD_CONSOLE
|
||||
config SERIAL_STM32
|
||||
tristate "STMicroelectronics STM32 serial port support"
|
||||
select SERIAL_CORE
|
||||
depends on HAS_DMA
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
help
|
||||
This driver is for the on-chip Serial Controller on
|
||||
|
@ -1727,10 +1727,26 @@ static int pl011_allocate_irq(struct uart_amba_port *uap)
|
||||
*/
|
||||
static void pl011_enable_interrupts(struct uart_amba_port *uap)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
|
||||
/* Clear out any spuriously appearing RX interrupts */
|
||||
pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
|
||||
|
||||
/*
|
||||
* RXIS is asserted only when the RX FIFO transitions from below
|
||||
* to above the trigger threshold. If the RX FIFO is already
|
||||
* full to the threshold this can't happen and RXIS will now be
|
||||
* stuck off. Drain the RX FIFO explicitly to fix this:
|
||||
*/
|
||||
for (i = 0; i < uap->fifosize * 2; ++i) {
|
||||
if (pl011_read(uap, REG_FR) & UART01x_FR_RXFE)
|
||||
break;
|
||||
|
||||
pl011_read(uap, REG_DR);
|
||||
}
|
||||
|
||||
uap->im = UART011_RTIM;
|
||||
if (!pl011_dma_rx_running(uap))
|
||||
uap->im |= UART011_RXIM;
|
||||
|
@ -1757,7 +1757,6 @@ static int atmel_startup(struct uart_port *port)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(port->dev);
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
struct tty_struct *tty = port->state->port.tty;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
@ -1772,8 +1771,8 @@ static int atmel_startup(struct uart_port *port)
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(port->irq, atmel_interrupt,
|
||||
IRQF_SHARED | IRQF_COND_SUSPEND,
|
||||
tty ? tty->name : "atmel_serial", port);
|
||||
IRQF_SHARED | IRQF_COND_SUSPEND,
|
||||
dev_name(&pdev->dev), port);
|
||||
if (retval) {
|
||||
dev_err(port->dev, "atmel_startup - Can't get irq\n");
|
||||
return retval;
|
||||
|
@ -246,7 +246,6 @@ int __init of_setup_earlycon(const struct earlycon_id *match,
|
||||
return -ENXIO;
|
||||
}
|
||||
port->mapbase = addr;
|
||||
port->uartclk = BASE_BAUD * 16;
|
||||
|
||||
val = of_get_flat_dt_prop(node, "reg-offset", NULL);
|
||||
if (val)
|
||||
@ -281,6 +280,10 @@ int __init of_setup_earlycon(const struct earlycon_id *match,
|
||||
if (val)
|
||||
early_console_dev.baud = be32_to_cpu(*val);
|
||||
|
||||
val = of_get_flat_dt_prop(node, "clock-frequency", NULL);
|
||||
if (val)
|
||||
port->uartclk = be32_to_cpu(*val);
|
||||
|
||||
if (options) {
|
||||
early_console_dev.baud = simple_strtoul(options, NULL, 0);
|
||||
strlcpy(early_console_dev.options, options,
|
||||
|
@ -1291,18 +1291,13 @@ static void imx_uart_enable_dma(struct imx_port *sport)
|
||||
|
||||
static void imx_uart_disable_dma(struct imx_port *sport)
|
||||
{
|
||||
u32 ucr1, ucr2;
|
||||
u32 ucr1;
|
||||
|
||||
/* clear UCR1 */
|
||||
ucr1 = imx_uart_readl(sport, UCR1);
|
||||
ucr1 &= ~(UCR1_RXDMAEN | UCR1_TXDMAEN | UCR1_ATDMAEN);
|
||||
imx_uart_writel(sport, ucr1, UCR1);
|
||||
|
||||
/* clear UCR2 */
|
||||
ucr2 = imx_uart_readl(sport, UCR2);
|
||||
ucr2 &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
|
||||
imx_uart_writel(sport, ucr2, UCR2);
|
||||
|
||||
imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
|
||||
|
||||
sport->dma_is_enabled = 0;
|
||||
@ -1427,13 +1422,21 @@ static void imx_uart_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long flags;
|
||||
u32 ucr1, ucr2;
|
||||
u32 ucr1, ucr2, ucr4;
|
||||
|
||||
if (sport->dma_is_enabled) {
|
||||
sport->dma_is_rxing = 0;
|
||||
sport->dma_is_txing = 0;
|
||||
dmaengine_terminate_sync(sport->dma_chan_tx);
|
||||
if (sport->dma_is_txing) {
|
||||
dma_unmap_sg(sport->port.dev, &sport->tx_sgl[0],
|
||||
sport->dma_tx_nents, DMA_TO_DEVICE);
|
||||
sport->dma_is_txing = 0;
|
||||
}
|
||||
dmaengine_terminate_sync(sport->dma_chan_rx);
|
||||
if (sport->dma_is_rxing) {
|
||||
dma_unmap_sg(sport->port.dev, &sport->rx_sgl,
|
||||
1, DMA_FROM_DEVICE);
|
||||
sport->dma_is_rxing = 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
imx_uart_stop_tx(port);
|
||||
@ -1449,6 +1452,10 @@ static void imx_uart_shutdown(struct uart_port *port)
|
||||
ucr2 = imx_uart_readl(sport, UCR2);
|
||||
ucr2 &= ~(UCR2_TXEN | UCR2_ATEN);
|
||||
imx_uart_writel(sport, ucr2, UCR2);
|
||||
|
||||
ucr4 = imx_uart_readl(sport, UCR4);
|
||||
ucr4 &= ~UCR4_OREN;
|
||||
imx_uart_writel(sport, ucr4, UCR4);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
/*
|
||||
@ -2425,8 +2432,7 @@ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
|
||||
|
||||
static int imx_uart_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
struct imx_port *sport = dev_get_drvdata(dev);
|
||||
|
||||
imx_uart_save_context(sport);
|
||||
|
||||
@ -2437,8 +2443,7 @@ static int imx_uart_suspend_noirq(struct device *dev)
|
||||
|
||||
static int imx_uart_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
struct imx_port *sport = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(sport->clk_ipg);
|
||||
@ -2452,8 +2457,7 @@ static int imx_uart_resume_noirq(struct device *dev)
|
||||
|
||||
static int imx_uart_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
struct imx_port *sport = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
uart_suspend_port(&imx_uart_uart_driver, &sport->port);
|
||||
@ -2471,8 +2475,7 @@ static int imx_uart_suspend(struct device *dev)
|
||||
|
||||
static int imx_uart_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
struct imx_port *sport = dev_get_drvdata(dev);
|
||||
|
||||
/* disable wakeup from i.MX UART */
|
||||
imx_uart_enable_wakeup(sport, false);
|
||||
@ -2487,8 +2490,7 @@ static int imx_uart_resume(struct device *dev)
|
||||
|
||||
static int imx_uart_freeze(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
struct imx_port *sport = dev_get_drvdata(dev);
|
||||
|
||||
uart_suspend_port(&imx_uart_uart_driver, &sport->port);
|
||||
|
||||
@ -2497,8 +2499,7 @@ static int imx_uart_freeze(struct device *dev)
|
||||
|
||||
static int imx_uart_thaw(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct imx_port *sport = platform_get_drvdata(pdev);
|
||||
struct imx_port *sport = dev_get_drvdata(dev);
|
||||
|
||||
uart_resume_port(&imx_uart_uart_driver, &sport->port);
|
||||
|
||||
|
@ -1812,11 +1812,34 @@ static const struct of_device_id msm_match_table[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, msm_match_table);
|
||||
|
||||
static int __maybe_unused msm_serial_suspend(struct device *dev)
|
||||
{
|
||||
struct msm_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_suspend_port(&msm_uart_driver, &port->uart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused msm_serial_resume(struct device *dev)
|
||||
{
|
||||
struct msm_port *port = dev_get_drvdata(dev);
|
||||
|
||||
uart_resume_port(&msm_uart_driver, &port->uart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops msm_serial_dev_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(msm_serial_suspend, msm_serial_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver msm_platform_driver = {
|
||||
.remove = msm_serial_remove,
|
||||
.probe = msm_serial_probe,
|
||||
.driver = {
|
||||
.name = "msm_serial",
|
||||
.pm = &msm_serial_dev_pm_ops,
|
||||
.of_match_table = msm_match_table,
|
||||
},
|
||||
};
|
||||
|
@ -71,6 +71,8 @@
|
||||
#define UART_BRDV 0x10
|
||||
#define BRDV_BAUD_MASK 0x3FF
|
||||
|
||||
#define UART_OSAMP 0x14
|
||||
|
||||
#define MVEBU_NR_UARTS 2
|
||||
|
||||
#define MVEBU_UART_TYPE "mvebu-uart"
|
||||
@ -108,6 +110,17 @@ struct mvebu_uart_driver_data {
|
||||
struct uart_flags flags;
|
||||
};
|
||||
|
||||
/* Saved registers during suspend */
|
||||
struct mvebu_uart_pm_regs {
|
||||
unsigned int rbr;
|
||||
unsigned int tsh;
|
||||
unsigned int ctrl;
|
||||
unsigned int intr;
|
||||
unsigned int stat;
|
||||
unsigned int brdv;
|
||||
unsigned int osamp;
|
||||
};
|
||||
|
||||
/* MVEBU UART driver structure */
|
||||
struct mvebu_uart {
|
||||
struct uart_port *port;
|
||||
@ -115,6 +128,9 @@ struct mvebu_uart {
|
||||
int irq[UART_IRQ_COUNT];
|
||||
unsigned char __iomem *nb;
|
||||
struct mvebu_uart_driver_data *data;
|
||||
#if defined(CONFIG_PM)
|
||||
struct mvebu_uart_pm_regs pm_regs;
|
||||
#endif /* CONFIG_PM */
|
||||
};
|
||||
|
||||
static struct mvebu_uart *to_mvuart(struct uart_port *port)
|
||||
@ -718,6 +734,51 @@ static struct uart_driver mvebu_uart_driver = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
static int mvebu_uart_suspend(struct device *dev)
|
||||
{
|
||||
struct mvebu_uart *mvuart = dev_get_drvdata(dev);
|
||||
struct uart_port *port = mvuart->port;
|
||||
|
||||
uart_suspend_port(&mvebu_uart_driver, port);
|
||||
|
||||
mvuart->pm_regs.rbr = readl(port->membase + UART_RBR(port));
|
||||
mvuart->pm_regs.tsh = readl(port->membase + UART_TSH(port));
|
||||
mvuart->pm_regs.ctrl = readl(port->membase + UART_CTRL(port));
|
||||
mvuart->pm_regs.intr = readl(port->membase + UART_INTR(port));
|
||||
mvuart->pm_regs.stat = readl(port->membase + UART_STAT);
|
||||
mvuart->pm_regs.brdv = readl(port->membase + UART_BRDV);
|
||||
mvuart->pm_regs.osamp = readl(port->membase + UART_OSAMP);
|
||||
|
||||
device_set_wakeup_enable(dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_uart_resume(struct device *dev)
|
||||
{
|
||||
struct mvebu_uart *mvuart = dev_get_drvdata(dev);
|
||||
struct uart_port *port = mvuart->port;
|
||||
|
||||
writel(mvuart->pm_regs.rbr, port->membase + UART_RBR(port));
|
||||
writel(mvuart->pm_regs.tsh, port->membase + UART_TSH(port));
|
||||
writel(mvuart->pm_regs.ctrl, port->membase + UART_CTRL(port));
|
||||
writel(mvuart->pm_regs.intr, port->membase + UART_INTR(port));
|
||||
writel(mvuart->pm_regs.stat, port->membase + UART_STAT);
|
||||
writel(mvuart->pm_regs.brdv, port->membase + UART_BRDV);
|
||||
writel(mvuart->pm_regs.osamp, port->membase + UART_OSAMP);
|
||||
|
||||
uart_resume_port(&mvebu_uart_driver, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops mvebu_uart_pm_ops = {
|
||||
.suspend = mvebu_uart_suspend,
|
||||
.resume = mvebu_uart_resume,
|
||||
};
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct of_device_id mvebu_uart_of_match[];
|
||||
|
||||
/* Counter to keep track of each UART port id when not using CONFIG_OF */
|
||||
@ -891,6 +952,9 @@ static struct platform_driver mvebu_uart_platform_driver = {
|
||||
.name = "mvebu-uart",
|
||||
.of_match_table = of_match_ptr(mvebu_uart_of_match),
|
||||
.suppress_bind_attrs = true,
|
||||
#if defined(CONFIG_PM)
|
||||
.pm = &mvebu_uart_pm_ops,
|
||||
#endif /* CONFIG_PM */
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -98,14 +98,13 @@ struct qcom_geni_serial_port {
|
||||
enum geni_se_xfer_mode xfer_mode;
|
||||
bool setup;
|
||||
int (*handle_rx)(struct uart_port *uport, u32 bytes, bool drop);
|
||||
unsigned int xmit_size;
|
||||
unsigned int baud;
|
||||
unsigned int tx_bytes_pw;
|
||||
unsigned int rx_bytes_pw;
|
||||
bool brk;
|
||||
};
|
||||
|
||||
static const struct uart_ops qcom_geni_serial_pops;
|
||||
static const struct uart_ops qcom_geni_console_pops;
|
||||
static struct uart_driver qcom_geni_console_driver;
|
||||
static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop);
|
||||
static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port);
|
||||
@ -118,7 +117,14 @@ static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
|
||||
#define to_dev_port(ptr, member) \
|
||||
container_of(ptr, struct qcom_geni_serial_port, member)
|
||||
|
||||
static struct qcom_geni_serial_port qcom_geni_console_port;
|
||||
static struct qcom_geni_serial_port qcom_geni_console_port = {
|
||||
.uport = {
|
||||
.iotype = UPIO_MEM,
|
||||
.ops = &qcom_geni_console_pops,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.line = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int qcom_geni_serial_request_port(struct uart_port *uport)
|
||||
{
|
||||
@ -189,8 +195,19 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
|
||||
timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500;
|
||||
}
|
||||
|
||||
return !readl_poll_timeout_atomic(uport->membase + offset, reg,
|
||||
(bool)(reg & field) == set, 10, timeout_us);
|
||||
/*
|
||||
* Use custom implementation instead of readl_poll_atomic since ktimer
|
||||
* is not ready at the time of early console.
|
||||
*/
|
||||
timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10;
|
||||
while (timeout_us) {
|
||||
reg = readl_relaxed(uport->membase + offset);
|
||||
if ((bool)(reg & field) == set)
|
||||
return true;
|
||||
udelay(10);
|
||||
timeout_us -= 10;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size)
|
||||
@ -286,6 +303,10 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s,
|
||||
u32 bytes_to_send = count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/*
|
||||
* uart_console_write() adds a carriage return for each newline.
|
||||
* Account for additional bytes to be written.
|
||||
*/
|
||||
if (s[i] == '\n')
|
||||
bytes_to_send++;
|
||||
}
|
||||
@ -305,7 +326,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s,
|
||||
if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
|
||||
M_TX_FIFO_WATERMARK_EN, true))
|
||||
break;
|
||||
chars_to_write = min_t(size_t, (size_t)(count - i), avail / 2);
|
||||
chars_to_write = min_t(size_t, count - i, avail / 2);
|
||||
uart_console_write(uport, s + i, chars_to_write,
|
||||
qcom_geni_serial_wr_char);
|
||||
writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase +
|
||||
@ -406,20 +427,18 @@ static void qcom_geni_serial_start_tx(struct uart_port *uport)
|
||||
u32 status;
|
||||
|
||||
if (port->xfer_mode == GENI_SE_FIFO) {
|
||||
status = readl_relaxed(uport->membase + SE_GENI_STATUS);
|
||||
/*
|
||||
* readl ensures reading & writing of IRQ_EN register
|
||||
* is not re-ordered before checking the status of the
|
||||
* Serial Engine.
|
||||
*/
|
||||
status = readl(uport->membase + SE_GENI_STATUS);
|
||||
if (status & M_GENI_CMD_ACTIVE)
|
||||
return;
|
||||
|
||||
if (!qcom_geni_serial_tx_empty(uport))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ensure writing to IRQ_EN & watermark registers are not
|
||||
* re-ordered before checking the status of the Serial
|
||||
* Engine and TX FIFO
|
||||
*/
|
||||
mb();
|
||||
|
||||
irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN);
|
||||
irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
|
||||
|
||||
@ -442,7 +461,6 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport)
|
||||
writel_relaxed(0, uport->membase +
|
||||
SE_GENI_TX_WATERMARK_REG);
|
||||
}
|
||||
port->xmit_size = 0;
|
||||
writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
|
||||
status = readl_relaxed(uport->membase + SE_GENI_STATUS);
|
||||
/* Possible stop tx is called multiple times. */
|
||||
@ -572,21 +590,14 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport)
|
||||
chunk = uart_circ_chars_pending(xmit);
|
||||
status = readl_relaxed(uport->membase + SE_GENI_TX_FIFO_STATUS);
|
||||
/* Both FIFO and framework buffer are drained */
|
||||
if (chunk == port->xmit_size && !status) {
|
||||
port->xmit_size = 0;
|
||||
uart_circ_clear(xmit);
|
||||
if (!chunk && !status) {
|
||||
qcom_geni_serial_stop_tx(uport);
|
||||
goto out_write_wakeup;
|
||||
}
|
||||
chunk -= port->xmit_size;
|
||||
|
||||
avail = (port->tx_fifo_depth - port->tx_wm) * port->tx_bytes_pw;
|
||||
tail = (xmit->tail + port->xmit_size) & (UART_XMIT_SIZE - 1);
|
||||
if (chunk > (UART_XMIT_SIZE - tail))
|
||||
chunk = UART_XMIT_SIZE - tail;
|
||||
if (chunk > avail)
|
||||
chunk = avail;
|
||||
|
||||
tail = xmit->tail;
|
||||
chunk = min3((size_t)chunk, (size_t)(UART_XMIT_SIZE - tail), avail);
|
||||
if (!chunk)
|
||||
goto out_write_wakeup;
|
||||
|
||||
@ -595,24 +606,27 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport)
|
||||
remaining = chunk;
|
||||
for (i = 0; i < chunk; ) {
|
||||
unsigned int tx_bytes;
|
||||
unsigned int buf = 0;
|
||||
u8 buf[sizeof(u32)];
|
||||
int c;
|
||||
|
||||
tx_bytes = min_t(size_t, remaining, (size_t)port->tx_bytes_pw);
|
||||
memset(buf, 0, ARRAY_SIZE(buf));
|
||||
tx_bytes = min_t(size_t, remaining, port->tx_bytes_pw);
|
||||
for (c = 0; c < tx_bytes ; c++)
|
||||
buf |= (xmit->buf[tail + c] << (c * BITS_PER_BYTE));
|
||||
buf[c] = xmit->buf[tail + c];
|
||||
|
||||
writel_relaxed(buf, uport->membase + SE_GENI_TX_FIFOn);
|
||||
iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);
|
||||
|
||||
i += tx_bytes;
|
||||
tail = (tail + tx_bytes) & (UART_XMIT_SIZE - 1);
|
||||
tail += tx_bytes;
|
||||
uport->icount.tx += tx_bytes;
|
||||
remaining -= tx_bytes;
|
||||
}
|
||||
|
||||
xmit->tail = tail & (UART_XMIT_SIZE - 1);
|
||||
qcom_geni_serial_poll_tx_done(uport);
|
||||
port->xmit_size += chunk;
|
||||
out_write_wakeup:
|
||||
uart_write_wakeup(uport);
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(uport);
|
||||
}
|
||||
|
||||
static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
|
||||
@ -627,7 +641,7 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
|
||||
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
|
||||
|
||||
if (uport->suspended)
|
||||
return IRQ_HANDLED;
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&uport->lock, flags);
|
||||
m_irq_status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS);
|
||||
@ -667,20 +681,16 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int get_tx_fifo_size(struct qcom_geni_serial_port *port)
|
||||
static void get_tx_fifo_size(struct qcom_geni_serial_port *port)
|
||||
{
|
||||
struct uart_port *uport;
|
||||
|
||||
if (!port)
|
||||
return -ENODEV;
|
||||
|
||||
uport = &port->uport;
|
||||
port->tx_fifo_depth = geni_se_get_tx_fifo_depth(&port->se);
|
||||
port->tx_fifo_width = geni_se_get_tx_fifo_width(&port->se);
|
||||
port->rx_fifo_depth = geni_se_get_rx_fifo_depth(&port->se);
|
||||
uport->fifosize =
|
||||
(port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_rfr_wm(struct qcom_geni_serial_port *port)
|
||||
@ -702,7 +712,6 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
|
||||
/* Stop the console before stopping the current tx */
|
||||
console_stop(uport->cons);
|
||||
|
||||
disable_irq(uport->irq);
|
||||
free_irq(uport->irq, uport);
|
||||
spin_lock_irqsave(&uport->lock, flags);
|
||||
qcom_geni_serial_stop_tx(uport);
|
||||
@ -892,7 +901,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
|
||||
|
||||
static unsigned int qcom_geni_serial_tx_empty(struct uart_port *uport)
|
||||
{
|
||||
return !readl_relaxed(uport->membase + SE_GENI_TX_FIFO_STATUS);
|
||||
return !readl(uport->membase + SE_GENI_TX_FIFO_STATUS);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
|
||||
@ -910,7 +919,7 @@ static int __init qcom_geni_console_setup(struct console *co, char *options)
|
||||
|
||||
port = get_port_from_line(co->index);
|
||||
if (IS_ERR(port)) {
|
||||
pr_err("Invalid line %d(%d)\n", co->index, (int)PTR_ERR(port));
|
||||
pr_err("Invalid line %d\n", co->index);
|
||||
return PTR_ERR(port);
|
||||
}
|
||||
|
||||
@ -942,6 +951,65 @@ static int __init qcom_geni_console_setup(struct console *co, char *options)
|
||||
return uart_set_options(uport, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static void qcom_geni_serial_earlycon_write(struct console *con,
|
||||
const char *s, unsigned int n)
|
||||
{
|
||||
struct earlycon_device *dev = con->data;
|
||||
|
||||
__qcom_geni_serial_console_write(&dev->port, s, n);
|
||||
}
|
||||
|
||||
static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev,
|
||||
const char *opt)
|
||||
{
|
||||
struct uart_port *uport = &dev->port;
|
||||
u32 tx_trans_cfg;
|
||||
u32 tx_parity_cfg = 0; /* Disable Tx Parity */
|
||||
u32 rx_trans_cfg = 0;
|
||||
u32 rx_parity_cfg = 0; /* Disable Rx Parity */
|
||||
u32 stop_bit_len = 0; /* Default stop bit length - 1 bit */
|
||||
u32 bits_per_char;
|
||||
struct geni_se se;
|
||||
|
||||
if (!uport->membase)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&se, 0, sizeof(se));
|
||||
se.base = uport->membase;
|
||||
if (geni_se_read_proto(&se) != GENI_SE_UART)
|
||||
return -ENXIO;
|
||||
/*
|
||||
* Ignore Flow control.
|
||||
* n = 8.
|
||||
*/
|
||||
tx_trans_cfg = UART_CTS_MASK;
|
||||
bits_per_char = BITS_PER_BYTE;
|
||||
|
||||
/*
|
||||
* Make an unconditional cancel on the main sequencer to reset
|
||||
* it else we could end up in data loss scenarios.
|
||||
*/
|
||||
qcom_geni_serial_poll_tx_done(uport);
|
||||
qcom_geni_serial_abort_rx(uport);
|
||||
geni_se_config_packing(&se, BITS_PER_BYTE, 1, false, true, false);
|
||||
geni_se_init(&se, DEF_FIFO_DEPTH_WORDS / 2, DEF_FIFO_DEPTH_WORDS - 2);
|
||||
geni_se_select_mode(&se, GENI_SE_FIFO);
|
||||
|
||||
writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG);
|
||||
writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG);
|
||||
writel_relaxed(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG);
|
||||
writel_relaxed(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG);
|
||||
writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN);
|
||||
writel_relaxed(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN);
|
||||
writel_relaxed(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
|
||||
|
||||
dev->con->write = qcom_geni_serial_earlycon_write;
|
||||
dev->con->setup = NULL;
|
||||
return 0;
|
||||
}
|
||||
OF_EARLYCON_DECLARE(qcom_geni, "qcom,geni-debug-uart",
|
||||
qcom_geni_serial_earlycon_setup);
|
||||
|
||||
static int __init console_register(struct uart_driver *drv)
|
||||
{
|
||||
return uart_register_driver(drv);
|
||||
@ -1026,16 +1094,13 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
line = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||
else
|
||||
line = pdev->id;
|
||||
|
||||
if (line < 0 || line >= GENI_UART_CONS_PORTS)
|
||||
return -ENXIO;
|
||||
port = get_port_from_line(line);
|
||||
if (IS_ERR(port)) {
|
||||
ret = PTR_ERR(port);
|
||||
dev_err(&pdev->dev, "Invalid line %d(%d)\n", line, ret);
|
||||
return ret;
|
||||
dev_err(&pdev->dev, "Invalid line %d\n", line);
|
||||
return PTR_ERR(port);
|
||||
}
|
||||
|
||||
uport = &port->uport;
|
||||
@ -1072,7 +1137,6 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
|
||||
uport->private_data = &qcom_geni_console_driver;
|
||||
platform_set_drvdata(pdev, port);
|
||||
port->handle_rx = handle_rx_console;
|
||||
port->setup = false;
|
||||
return uart_add_one_port(&qcom_geni_console_driver, uport);
|
||||
}
|
||||
|
||||
@ -1087,8 +1151,7 @@ static int qcom_geni_serial_remove(struct platform_device *pdev)
|
||||
|
||||
static int __maybe_unused qcom_geni_serial_sys_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct qcom_geni_serial_port *port = platform_get_drvdata(pdev);
|
||||
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
|
||||
struct uart_port *uport = &port->uport;
|
||||
|
||||
uart_suspend_port(uport->private_data, uport);
|
||||
@ -1097,12 +1160,19 @@ static int __maybe_unused qcom_geni_serial_sys_suspend_noirq(struct device *dev)
|
||||
|
||||
static int __maybe_unused qcom_geni_serial_sys_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct qcom_geni_serial_port *port = platform_get_drvdata(pdev);
|
||||
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
|
||||
struct uart_port *uport = &port->uport;
|
||||
|
||||
if (console_suspend_enabled && uport->suspended) {
|
||||
uart_resume_port(uport->private_data, uport);
|
||||
/*
|
||||
* uart_suspend_port() invokes port shutdown which in turn
|
||||
* frees the irq. uart_resume_port invokes port startup which
|
||||
* performs request_irq. The request_irq auto-enables the IRQ.
|
||||
* In addition, resume_noirq implicitly enables the IRQ and
|
||||
* leads to an unbalanced IRQ enable warning. Disable the IRQ
|
||||
* before returning so that the warning is suppressed.
|
||||
*/
|
||||
disable_irq(uport->irq);
|
||||
}
|
||||
return 0;
|
||||
@ -1133,11 +1203,6 @@ static int __init qcom_geni_serial_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
qcom_geni_console_port.uport.iotype = UPIO_MEM;
|
||||
qcom_geni_console_port.uport.ops = &qcom_geni_console_pops;
|
||||
qcom_geni_console_port.uport.flags = UPF_BOOT_AUTOCONF;
|
||||
qcom_geni_console_port.uport.line = 0;
|
||||
|
||||
ret = console_register(&qcom_geni_console_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -856,35 +856,54 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
|
||||
static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
|
||||
{
|
||||
struct s3c24xx_uart_dma *dma = p->dma;
|
||||
struct dma_slave_caps dma_caps;
|
||||
const char *reason = NULL;
|
||||
int ret;
|
||||
|
||||
/* Default slave configuration parameters */
|
||||
dma->rx_conf.direction = DMA_DEV_TO_MEM;
|
||||
dma->rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
dma->rx_conf.src_addr = p->port.mapbase + S3C2410_URXH;
|
||||
dma->rx_conf.src_maxburst = 16;
|
||||
dma->rx_conf.src_maxburst = 1;
|
||||
|
||||
dma->tx_conf.direction = DMA_MEM_TO_DEV;
|
||||
dma->tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
dma->tx_conf.dst_addr = p->port.mapbase + S3C2410_UTXH;
|
||||
if (dma_get_cache_alignment() >= 16)
|
||||
dma->tx_conf.dst_maxburst = 16;
|
||||
else
|
||||
dma->tx_conf.dst_maxburst = 1;
|
||||
dma->tx_conf.dst_maxburst = 1;
|
||||
|
||||
dma->rx_chan = dma_request_chan(p->port.dev, "rx");
|
||||
|
||||
if (IS_ERR(dma->rx_chan))
|
||||
return PTR_ERR(dma->rx_chan);
|
||||
if (IS_ERR(dma->rx_chan)) {
|
||||
reason = "DMA RX channel request failed";
|
||||
ret = PTR_ERR(dma->rx_chan);
|
||||
goto err_warn;
|
||||
}
|
||||
|
||||
ret = dma_get_slave_caps(dma->rx_chan, &dma_caps);
|
||||
if (ret < 0 ||
|
||||
dma_caps.residue_granularity < DMA_RESIDUE_GRANULARITY_BURST) {
|
||||
reason = "insufficient DMA RX engine capabilities";
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_release_rx;
|
||||
}
|
||||
|
||||
dmaengine_slave_config(dma->rx_chan, &dma->rx_conf);
|
||||
|
||||
dma->tx_chan = dma_request_chan(p->port.dev, "tx");
|
||||
if (IS_ERR(dma->tx_chan)) {
|
||||
reason = "DMA TX channel request failed";
|
||||
ret = PTR_ERR(dma->tx_chan);
|
||||
goto err_release_rx;
|
||||
}
|
||||
|
||||
ret = dma_get_slave_caps(dma->tx_chan, &dma_caps);
|
||||
if (ret < 0 ||
|
||||
dma_caps.residue_granularity < DMA_RESIDUE_GRANULARITY_BURST) {
|
||||
reason = "insufficient DMA TX engine capabilities";
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_release_tx;
|
||||
}
|
||||
|
||||
dmaengine_slave_config(dma->tx_chan, &dma->tx_conf);
|
||||
|
||||
/* RX buffer */
|
||||
@ -899,6 +918,7 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
|
||||
dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
|
||||
dma->rx_size, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(p->port.dev, dma->rx_addr)) {
|
||||
reason = "DMA mapping error for RX buffer";
|
||||
ret = -EIO;
|
||||
goto err_free_rx;
|
||||
}
|
||||
@ -907,6 +927,7 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
|
||||
dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
|
||||
UART_XMIT_SIZE, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(p->port.dev, dma->tx_addr)) {
|
||||
reason = "DMA mapping error for TX buffer";
|
||||
ret = -EIO;
|
||||
goto err_unmap_rx;
|
||||
}
|
||||
@ -922,6 +943,9 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
|
||||
dma_release_channel(dma->tx_chan);
|
||||
err_release_rx:
|
||||
dma_release_channel(dma->rx_chan);
|
||||
err_warn:
|
||||
if (reason)
|
||||
dev_warn(p->port.dev, "%s, DMA will not be used\n", reason);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1040,8 +1064,6 @@ static int s3c64xx_serial_startup(struct uart_port *port)
|
||||
if (ourport->dma) {
|
||||
ret = s3c24xx_serial_request_dma(ourport);
|
||||
if (ret < 0) {
|
||||
dev_warn(port->dev,
|
||||
"DMA request failed, DMA will not be used\n");
|
||||
devm_kfree(port->dev, ourport->dma);
|
||||
ourport->dma = NULL;
|
||||
}
|
||||
|
@ -1168,7 +1168,10 @@ static int sc16is7xx_probe(struct device *dev,
|
||||
else
|
||||
return PTR_ERR(s->clk);
|
||||
} else {
|
||||
clk_prepare_enable(s->clk);
|
||||
ret = clk_prepare_enable(s->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
freq = clk_get_rate(s->clk);
|
||||
}
|
||||
|
||||
|
@ -674,8 +674,8 @@ static void uart_send_xchar(struct tty_struct *tty, char ch)
|
||||
static void uart_throttle(struct tty_struct *tty)
|
||||
{
|
||||
struct uart_state *state = tty->driver_data;
|
||||
upstat_t mask = UPSTAT_SYNC_FIFO;
|
||||
struct uart_port *port;
|
||||
upstat_t mask = 0;
|
||||
|
||||
port = uart_port_ref(state);
|
||||
if (!port)
|
||||
@ -703,8 +703,8 @@ static void uart_throttle(struct tty_struct *tty)
|
||||
static void uart_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
struct uart_state *state = tty->driver_data;
|
||||
upstat_t mask = UPSTAT_SYNC_FIFO;
|
||||
struct uart_port *port;
|
||||
upstat_t mask = 0;
|
||||
|
||||
port = uart_port_ref(state);
|
||||
if (!port)
|
||||
|
@ -160,6 +160,7 @@ struct sci_port {
|
||||
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
|
||||
|
||||
static struct sci_port sci_ports[SCI_NPORTS];
|
||||
static unsigned long sci_ports_in_use;
|
||||
static struct uart_driver sci_uart_driver;
|
||||
|
||||
static inline struct sci_port *
|
||||
@ -2390,6 +2391,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
/* byte size and parity */
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
bits = 7;
|
||||
break;
|
||||
case CS6:
|
||||
bits = 8;
|
||||
break;
|
||||
case CS7:
|
||||
bits = 9;
|
||||
break;
|
||||
default:
|
||||
bits = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
bits++;
|
||||
if (termios->c_cflag & PARENB)
|
||||
bits++;
|
||||
|
||||
if (best_clk >= 0) {
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
|
||||
switch (srr + 1) {
|
||||
@ -2406,8 +2428,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
|
||||
serial_port_out(port, SCSMR, smr_val);
|
||||
serial_port_out(port, SCBRR, brr);
|
||||
if (sci_getreg(port, HSSRR)->size)
|
||||
serial_port_out(port, HSSRR, srr | HSCIF_SRE);
|
||||
if (sci_getreg(port, HSSRR)->size) {
|
||||
unsigned int hssrr = srr | HSCIF_SRE;
|
||||
/* Calculate deviation from intended rate at the
|
||||
* center of the last stop bit in sampling clocks.
|
||||
*/
|
||||
int last_stop = bits * 2 - 1;
|
||||
int deviation = min_err * srr * last_stop / 2 / baud;
|
||||
|
||||
if (abs(deviation) >= 2) {
|
||||
/* At least two sampling clocks off at the
|
||||
* last stop bit; we can increase the error
|
||||
* margin by shifting the sampling point.
|
||||
*/
|
||||
int shift = min(-8, max(7, deviation / 2));
|
||||
|
||||
hssrr |= (shift << HSCIF_SRHP_SHIFT) &
|
||||
HSCIF_SRHP_MASK;
|
||||
hssrr |= HSCIF_SRDE;
|
||||
}
|
||||
serial_port_out(port, HSSRR, hssrr);
|
||||
}
|
||||
|
||||
/* Wait one bit interval */
|
||||
udelay((1000000 + (baud - 1)) / baud);
|
||||
@ -2474,27 +2515,6 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
* value obtained by this formula is too small. Therefore, if the value
|
||||
* is smaller than 20ms, use 20ms as the timeout value for DMA.
|
||||
*/
|
||||
/* byte size and parity */
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
bits = 7;
|
||||
break;
|
||||
case CS6:
|
||||
bits = 8;
|
||||
break;
|
||||
case CS7:
|
||||
bits = 9;
|
||||
break;
|
||||
default:
|
||||
bits = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
bits++;
|
||||
if (termios->c_cflag & PARENB)
|
||||
bits++;
|
||||
|
||||
s->rx_frame = (10000 * bits) / (baud / 100);
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame;
|
||||
@ -2890,16 +2910,15 @@ static void serial_console_write(struct console *co, const char *s,
|
||||
unsigned long flags;
|
||||
int locked = 1;
|
||||
|
||||
local_irq_save(flags);
|
||||
#if defined(SUPPORT_SYSRQ)
|
||||
if (port->sysrq)
|
||||
locked = 0;
|
||||
else
|
||||
#endif
|
||||
if (oops_in_progress)
|
||||
locked = spin_trylock(&port->lock);
|
||||
locked = spin_trylock_irqsave(&port->lock, flags);
|
||||
else
|
||||
spin_lock(&port->lock);
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/* first save SCSCR then disable interrupts, keep clock source */
|
||||
ctrl = serial_port_in(port, SCSCR);
|
||||
@ -2919,8 +2938,7 @@ static void serial_console_write(struct console *co, const char *s,
|
||||
serial_port_out(port, SCSCR, ctrl);
|
||||
|
||||
if (locked)
|
||||
spin_unlock(&port->lock);
|
||||
local_irq_restore(flags);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int serial_console_setup(struct console *co, char *options)
|
||||
@ -3026,6 +3044,7 @@ static int sci_remove(struct platform_device *dev)
|
||||
{
|
||||
struct sci_port *port = platform_get_drvdata(dev);
|
||||
|
||||
sci_ports_in_use &= ~BIT(port->port.line);
|
||||
uart_remove_one_port(&sci_uart_driver, &port->port);
|
||||
|
||||
sci_cleanup_single(port);
|
||||
@ -3107,6 +3126,8 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
|
||||
|
||||
/* Get the line number from the aliases node. */
|
||||
id = of_alias_get_id(np, "serial");
|
||||
if (id < 0 && ~sci_ports_in_use)
|
||||
id = ffz(sci_ports_in_use);
|
||||
if (id < 0) {
|
||||
dev_err(&pdev->dev, "failed to get alias id (%d)\n", id);
|
||||
return NULL;
|
||||
@ -3141,6 +3162,9 @@ static int sci_probe_single(struct platform_device *dev,
|
||||
dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
BUILD_BUG_ON(SCI_NPORTS > sizeof(sci_ports_in_use) * 8);
|
||||
if (sci_ports_in_use & BIT(index))
|
||||
return -EBUSY;
|
||||
|
||||
mutex_lock(&sci_uart_registration_lock);
|
||||
if (!sci_uart_driver.state) {
|
||||
@ -3239,6 +3263,7 @@ static int sci_probe(struct platform_device *dev)
|
||||
sh_bios_gdb_detach();
|
||||
#endif
|
||||
|
||||
sci_ports_in_use |= BIT(dev_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,10 @@ enum {
|
||||
|
||||
/* HSSRR HSCIF */
|
||||
#define HSCIF_SRE BIT(15) /* Sampling Rate Register Enable */
|
||||
#define HSCIF_SRDE BIT(14) /* Sampling Point Register Enable */
|
||||
|
||||
#define HSCIF_SRHP_SHIFT 8
|
||||
#define HSCIF_SRHP_MASK 0x0f00
|
||||
|
||||
/* SCPCR (Serial Port Control Register), SCIFA/SCIFB only */
|
||||
#define SCPCR_RTSC BIT(4) /* Serial Port RTS# Pin / Output Pin */
|
||||
|
@ -842,16 +842,14 @@ static int asc_serial_remove(struct platform_device *pdev)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int asc_serial_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
|
||||
return uart_suspend_port(&asc_uart_driver, port);
|
||||
}
|
||||
|
||||
static int asc_serial_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
|
||||
return uart_resume_port(&asc_uart_driver, port);
|
||||
}
|
||||
|
@ -1097,45 +1097,6 @@ static const struct uart_ops cdns_uart_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct uart_port cdns_uart_port[CDNS_UART_NR_PORTS];
|
||||
|
||||
/**
|
||||
* cdns_uart_get_port - Configure the port from platform device resource info
|
||||
* @id: Port id
|
||||
*
|
||||
* Return: a pointer to a uart_port or NULL for failure
|
||||
*/
|
||||
static struct uart_port *cdns_uart_get_port(int id)
|
||||
{
|
||||
struct uart_port *port;
|
||||
|
||||
/* Try the given port id if failed use default method */
|
||||
if (id < CDNS_UART_NR_PORTS && cdns_uart_port[id].mapbase != 0) {
|
||||
/* Find the next unused port */
|
||||
for (id = 0; id < CDNS_UART_NR_PORTS; id++)
|
||||
if (cdns_uart_port[id].mapbase == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (id >= CDNS_UART_NR_PORTS)
|
||||
return NULL;
|
||||
|
||||
port = &cdns_uart_port[id];
|
||||
|
||||
/* At this point, we've got an empty uart_port struct, initialize it */
|
||||
spin_lock_init(&port->lock);
|
||||
port->membase = NULL;
|
||||
port->irq = 0;
|
||||
port->type = PORT_UNKNOWN;
|
||||
port->iotype = UPIO_MEM32;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->ops = &cdns_uart_ops;
|
||||
port->fifosize = CDNS_UART_FIFO_SIZE;
|
||||
port->line = id;
|
||||
port->dev = NULL;
|
||||
return port;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
|
||||
/**
|
||||
* cdns_uart_console_wait_tx - Wait for the TX to be full
|
||||
@ -1206,6 +1167,10 @@ OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p8", cdns_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p12", cdns_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup);
|
||||
|
||||
|
||||
/* Static pointer to console port */
|
||||
static struct uart_port *console_port;
|
||||
|
||||
/**
|
||||
* cdns_uart_console_write - perform write operation
|
||||
* @co: Console handle
|
||||
@ -1215,7 +1180,7 @@ OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup);
|
||||
static void cdns_uart_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &cdns_uart_port[co->index];
|
||||
struct uart_port *port = console_port;
|
||||
unsigned long flags;
|
||||
unsigned int imr, ctrl;
|
||||
int locked = 1;
|
||||
@ -1261,15 +1226,13 @@ static void cdns_uart_console_write(struct console *co, const char *s,
|
||||
*/
|
||||
static int __init cdns_uart_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port = &cdns_uart_port[co->index];
|
||||
struct uart_port *port = console_port;
|
||||
|
||||
int baud = 9600;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
if (co->index < 0 || co->index >= CDNS_UART_NR_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
if (!port->membase) {
|
||||
pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n",
|
||||
co->index);
|
||||
@ -1293,20 +1256,6 @@ static struct console cdns_uart_console = {
|
||||
.index = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */
|
||||
.data = &cdns_uart_uart_driver,
|
||||
};
|
||||
|
||||
/**
|
||||
* cdns_uart_console_init - Initialization call
|
||||
*
|
||||
* Return: 0 on success, negative errno otherwise
|
||||
*/
|
||||
static int __init cdns_uart_console_init(void)
|
||||
{
|
||||
register_console(&cdns_uart_console);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_initcall(cdns_uart_console_init);
|
||||
|
||||
#endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */
|
||||
|
||||
static struct uart_driver cdns_uart_uart_driver = {
|
||||
@ -1430,8 +1379,7 @@ static int cdns_uart_resume(struct device *device)
|
||||
#endif /* ! CONFIG_PM_SLEEP */
|
||||
static int __maybe_unused cdns_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
|
||||
clk_disable(cdns_uart->uartclk);
|
||||
@ -1441,8 +1389,7 @@ static int __maybe_unused cdns_runtime_suspend(struct device *dev)
|
||||
|
||||
static int __maybe_unused cdns_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
struct cdns_uart *cdns_uart = port->private_data;
|
||||
|
||||
clk_enable(cdns_uart->pclk);
|
||||
@ -1487,6 +1434,9 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||
GFP_KERNEL);
|
||||
if (!cdns_uart_data)
|
||||
return -ENOMEM;
|
||||
port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return -ENOMEM;
|
||||
|
||||
match = of_match_node(cdns_uart_of_match, pdev->dev.of_node);
|
||||
if (match && match->data) {
|
||||
@ -1552,15 +1502,24 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||
if (id < 0)
|
||||
id = 0;
|
||||
|
||||
/* Initialize the port structure */
|
||||
port = cdns_uart_get_port(id);
|
||||
|
||||
if (!port) {
|
||||
if (id >= CDNS_UART_NR_PORTS) {
|
||||
dev_err(&pdev->dev, "Cannot get uart_port structure\n");
|
||||
rc = -ENODEV;
|
||||
goto err_out_notif_unreg;
|
||||
}
|
||||
|
||||
/* At this point, we've got an empty uart_port struct, initialize it */
|
||||
spin_lock_init(&port->lock);
|
||||
port->membase = NULL;
|
||||
port->irq = 0;
|
||||
port->type = PORT_UNKNOWN;
|
||||
port->iotype = UPIO_MEM32;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->ops = &cdns_uart_ops;
|
||||
port->fifosize = CDNS_UART_FIFO_SIZE;
|
||||
port->line = id;
|
||||
port->dev = NULL;
|
||||
|
||||
/*
|
||||
* Register the port.
|
||||
* This function also registers this device with the tty layer
|
||||
@ -1579,6 +1538,17 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
|
||||
/*
|
||||
* If console hasn't been found yet try to assign this port
|
||||
* because it is required to be assigned for console setup function.
|
||||
* If register_console() don't assign value, then console_port pointer
|
||||
* is cleanup.
|
||||
*/
|
||||
if (cdns_uart_uart_driver.cons->index == -1)
|
||||
console_port = port;
|
||||
#endif
|
||||
|
||||
rc = uart_add_one_port(&cdns_uart_uart_driver, port);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev,
|
||||
@ -1586,6 +1556,12 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||
goto err_out_pm_disable;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
|
||||
/* This is not port which is used for console that's why clean it up */
|
||||
if (cdns_uart_uart_driver.cons->index == -1)
|
||||
console_port = NULL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_pm_disable:
|
||||
|
@ -1178,15 +1178,8 @@ static void csi_J(struct vc_data *vc, int vpar)
|
||||
count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
|
||||
start = (unsigned short *)vc->vc_origin;
|
||||
break;
|
||||
case 3: /* erase scroll-back buffer (and whole display) */
|
||||
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
|
||||
vc->vc_screenbuf_size);
|
||||
flush_scrollback(vc);
|
||||
set_origin(vc);
|
||||
if (con_is_visible(vc))
|
||||
update_screen(vc);
|
||||
/* fall through */
|
||||
case 2: /* erase whole display */
|
||||
case 3: /* (and scrollback buffer later) */
|
||||
count = vc->vc_cols * vc->vc_rows;
|
||||
start = (unsigned short *)vc->vc_origin;
|
||||
break;
|
||||
@ -1194,7 +1187,12 @@ static void csi_J(struct vc_data *vc, int vpar)
|
||||
return;
|
||||
}
|
||||
scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
|
||||
if (con_should_update(vc))
|
||||
if (vpar == 3) {
|
||||
set_origin(vc);
|
||||
flush_scrollback(vc);
|
||||
if (con_is_visible(vc))
|
||||
update_screen(vc);
|
||||
} else if (con_should_update(vc))
|
||||
do_update_region(vc, (unsigned long) start, count);
|
||||
vc->vc_need_wrap = 0;
|
||||
}
|
||||
|
@ -163,6 +163,7 @@ extern void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl);
|
||||
extern int fsl8250_handle_irq(struct uart_port *port);
|
||||
int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
|
||||
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
|
||||
void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr);
|
||||
void serial8250_tx_chars(struct uart_8250_port *up);
|
||||
unsigned int serial8250_modem_status(struct uart_8250_port *up);
|
||||
void serial8250_init_port(struct uart_8250_port *up);
|
||||
|
@ -233,6 +233,7 @@ struct uart_port {
|
||||
#define UPSTAT_AUTORTS ((__force upstat_t) (1 << 2))
|
||||
#define UPSTAT_AUTOCTS ((__force upstat_t) (1 << 3))
|
||||
#define UPSTAT_AUTOXOFF ((__force upstat_t) (1 << 4))
|
||||
#define UPSTAT_SYNC_FIFO ((__force upstat_t) (1 << 5))
|
||||
|
||||
int hw_stopped; /* sw-assisted CTS flow state */
|
||||
unsigned int mctrl; /* current modem ctrl settings */
|
||||
@ -348,7 +349,8 @@ struct earlycon_device {
|
||||
};
|
||||
|
||||
struct earlycon_id {
|
||||
char name[16];
|
||||
char name[15];
|
||||
char name_term; /* In case compiler didn't '\0' term name */
|
||||
char compatible[128];
|
||||
int (*setup)(struct earlycon_device *, const char *options);
|
||||
};
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
#define ASYNCB_HUP_NOTIFY 0 /* Notify getty on hangups and closes
|
||||
* on the callout port */
|
||||
#define ASYNCB_FOURPORT 1 /* Set OU1, OUT2 per AST Fourport settings */
|
||||
#define ASYNCB_FOURPORT 1 /* Set OUT1, OUT2 per AST Fourport settings */
|
||||
#define ASYNCB_SAK 2 /* Secure Attention Key (Orange book) */
|
||||
#define ASYNCB_SPLIT_TERMIOS 3 /* [x] Separate termios for dialin/callout */
|
||||
#define ASYNCB_SPD_HI 4 /* Use 57600 instead of 38400 bps */
|
||||
|
Loading…
Reference in New Issue
Block a user