summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/goldfish.c59
-rw-r--r--drivers/tty/n_gsm.c17
-rw-r--r--drivers/tty/serial/8250/8250_omap.c4
-rw-r--r--drivers/tty/serial/8250/8250_pci.c11
-rw-r--r--drivers/tty/serial/atmel_serial.c1
-rw-r--r--drivers/tty/serial/sccnxp.c15
-rw-r--r--drivers/tty/serial/sh-sci.c18
-rw-r--r--drivers/tty/tty_io.c2
-rw-r--r--drivers/tty/vt/vt.c14
9 files changed, 100 insertions, 41 deletions
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index c6ec9e64451b..4686e93aaf94 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -26,20 +26,25 @@
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/serial_core.h>
+#include <linux/of.h>
/* Goldfish tty register's offsets */
-#define GOLDFISH_TTY_REG_BYTES_READY 0x04
-#define GOLDFISH_TTY_REG_CMD 0x08
-#define GOLDFISH_TTY_REG_DATA_PTR 0x10
-#define GOLDFISH_TTY_REG_DATA_LEN 0x14
-#define GOLDFISH_TTY_REG_DATA_PTR_HIGH 0x18
-#define GOLDFISH_TTY_REG_VERSION 0x20
+enum {
+ GOLDFISH_TTY_REG_BYTES_READY = 0x04,
+ GOLDFISH_TTY_REG_CMD = 0x08,
+ GOLDFISH_TTY_REG_DATA_PTR = 0x10,
+ GOLDFISH_TTY_REG_DATA_LEN = 0x14,
+ GOLDFISH_TTY_REG_DATA_PTR_HIGH = 0x18,
+ GOLDFISH_TTY_REG_VERSION = 0x20,
+};
/* Goldfish tty commands */
-#define GOLDFISH_TTY_CMD_INT_DISABLE 0
-#define GOLDFISH_TTY_CMD_INT_ENABLE 1
-#define GOLDFISH_TTY_CMD_WRITE_BUFFER 2
-#define GOLDFISH_TTY_CMD_READ_BUFFER 3
+enum {
+ GOLDFISH_TTY_CMD_INT_DISABLE = 0,
+ GOLDFISH_TTY_CMD_INT_ENABLE = 1,
+ GOLDFISH_TTY_CMD_WRITE_BUFFER = 2,
+ GOLDFISH_TTY_CMD_READ_BUFFER = 3,
+};
struct goldfish_tty {
struct tty_port port;
@@ -82,32 +87,35 @@ static void do_rw_io(struct goldfish_tty *qtty,
}
static void goldfish_tty_rw(struct goldfish_tty *qtty,
- unsigned long addr,
+ const void *address_ptr,
unsigned int count,
int is_write)
{
dma_addr_t dma_handle;
enum dma_data_direction dma_dir;
+ uintptr_t address;
+ address = (uintptr_t)address_ptr;
dma_dir = (is_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
if (qtty->version > 0) {
/*
* Goldfish TTY for Ranchu platform uses
* physical addresses and DMA for read/write operations
*/
- unsigned long addr_end = addr + count;
+ uintptr_t address_end = address + count;
- while (addr < addr_end) {
- unsigned long pg_end = (addr & PAGE_MASK) + PAGE_SIZE;
- unsigned long next =
- pg_end < addr_end ? pg_end : addr_end;
- unsigned long avail = next - addr;
+ while (address < address_end) {
+ uintptr_t page_end = (address & PAGE_MASK) + PAGE_SIZE;
+ uintptr_t next = page_end < address_end ?
+ page_end : address_end;
+ uintptr_t avail = next - address;
/*
* Map the buffer's virtual address to the DMA address
* so the buffer can be accessed by the device.
*/
- dma_handle = dma_map_single(qtty->dev, (void *)addr,
+ dma_handle = dma_map_single(qtty->dev, (void *)address,
avail, dma_dir);
if (dma_mapping_error(qtty->dev, dma_handle)) {
@@ -122,31 +130,30 @@ static void goldfish_tty_rw(struct goldfish_tty *qtty,
*/
dma_unmap_single(qtty->dev, dma_handle, avail, dma_dir);
- addr += avail;
+ address += avail;
}
} else {
/*
* Old style Goldfish TTY used on the Goldfish platform
* uses virtual addresses.
*/
- do_rw_io(qtty, addr, count, is_write);
+ do_rw_io(qtty, address, count, is_write);
}
+
}
static void goldfish_tty_do_write(int line, const char *buf,
unsigned int count)
{
struct goldfish_tty *qtty = &goldfish_ttys[line];
- unsigned long address = (unsigned long)(void *)buf;
- goldfish_tty_rw(qtty, address, count, 1);
+ goldfish_tty_rw(qtty, buf, count, 1);
}
static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
{
struct goldfish_tty *qtty = dev_id;
void __iomem *base = qtty->base;
- unsigned long address;
unsigned char *buf;
u32 count;
@@ -155,9 +162,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
return IRQ_NONE;
count = tty_prepare_flip_string(&qtty->port, &buf, count);
-
- address = (unsigned long)(void *)buf;
- goldfish_tty_rw(qtty, address, count, 0);
+ goldfish_tty_rw(qtty, buf, count, 0);
tty_schedule_flip(&qtty->port);
return IRQ_HANDLED;
@@ -181,6 +186,7 @@ static void goldfish_tty_shutdown(struct tty_port *port)
static int goldfish_tty_open(struct tty_struct *tty, struct file *filp)
{
struct goldfish_tty *qtty = &goldfish_ttys[tty->index];
+
return tty_port_open(&qtty->port, tty, filp);
}
@@ -210,6 +216,7 @@ static int goldfish_tty_chars_in_buffer(struct tty_struct *tty)
{
struct goldfish_tty *qtty = &goldfish_ttys[tty->index];
void __iomem *base = qtty->base;
+
return readl(base + GOLDFISH_TTY_REG_BYTES_READY);
}
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 9aff37186246..78bd121ecede 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -1467,6 +1467,10 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)
* in which case an opening port goes back to closed and a closing port
* is simply put into closed state (any further frames from the other
* end will get a DM response)
+ *
+ * Some control dlci can stay in ADM mode with other dlci working just
+ * fine. In that case we can just keep the control dlci open after the
+ * DLCI_OPENING retries time out.
*/
static void gsm_dlci_t1(unsigned long data)
@@ -1480,8 +1484,15 @@ static void gsm_dlci_t1(unsigned long data)
if (dlci->retries) {
gsm_command(dlci->gsm, dlci->addr, SABM|PF);
mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100);
- } else
+ } else if (!dlci->addr && gsm->control == (DM | PF)) {
+ if (debug & 8)
+ pr_info("DLCI %d opening in ADM mode.\n",
+ dlci->addr);
+ gsm_dlci_open(dlci);
+ } else {
gsm_dlci_close(dlci);
+ }
+
break;
case DLCI_CLOSING:
dlci->retries--;
@@ -1499,8 +1510,8 @@ static void gsm_dlci_t1(unsigned long data)
* @dlci: DLCI to open
*
* Commence opening a DLCI from the Linux side. We issue SABM messages
- * to the modem which should then reply with a UA, at which point we
- * will move into open state. Opening is done asynchronously with retry
+ * to the modem which should then reply with a UA or ADM, at which point
+ * we will move into open state. Opening is done asynchronously with retry
* running off timers and the responses.
*/
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index e8dd296fb25b..c4383573cf66 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -608,6 +608,10 @@ static int omap_8250_startup(struct uart_port *port)
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
+ /* Disable DMA for console UART */
+ if (uart_console(port))
+ up->dma = NULL;
+
if (up->dma) {
ret = serial8250_request_dma(up);
if (ret) {
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 7025f47fa284..746c76b358a0 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -5300,6 +5300,17 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */
pbn_b2_4_115200 },
/*
+ * BrainBoxes UC-260
+ */
+ { PCI_VENDOR_ID_INTASHIELD, 0x0D21,
+ PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00,
+ pbn_b2_4_115200 },
+ { PCI_VENDOR_ID_INTASHIELD, 0x0E34,
+ PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00,
+ pbn_b2_4_115200 },
+ /*
* Perle PCI-RAS cards
*/
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 53e4d5056db7..e0277cf0bf58 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1783,6 +1783,7 @@ static void atmel_get_ip_name(struct uart_port *port)
switch (version) {
case 0x302:
case 0x10213:
+ case 0x10302:
dev_dbg(port->dev, "This version is usart\n");
atmel_port->is_usart = true;
break;
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index fcf803ffad19..cdd2f942317c 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -884,14 +884,19 @@ static int sccnxp_probe(struct platform_device *pdev)
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
- if (PTR_ERR(clk) == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
+ ret = PTR_ERR(clk);
+ if (ret == -EPROBE_DEFER)
goto err_out;
- }
+ uartclk = 0;
+ } else {
+ clk_prepare_enable(clk);
+ uartclk = clk_get_rate(clk);
+ }
+
+ if (!uartclk) {
dev_notice(&pdev->dev, "Using default clock frequency\n");
uartclk = s->chip->freq_std;
- } else
- uartclk = clk_get_rate(clk);
+ }
/* Check input frequency */
if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) {
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 80d0ffe7abc1..8dd822feb972 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -847,6 +847,8 @@ static void sci_receive_chars(struct uart_port *port)
/* Tell the rest of the system the news. New characters! */
tty_flip_buffer_push(tport);
} else {
+ /* TTY buffers full; read from RX reg to prevent lockup */
+ serial_port_in(port, SCxRDR);
serial_port_in(port, SCxSR); /* dummy read */
sci_clear_SCxSR(port, SCxSR_RDxF_CLEAR(port));
}
@@ -1455,7 +1457,16 @@ static void sci_free_dma(struct uart_port *port)
if (s->chan_rx)
sci_rx_dma_release(s, false);
}
-#else
+
+static void sci_flush_buffer(struct uart_port *port)
+{
+ /*
+ * In uart_flush_buffer(), the xmit circular buffer has just been
+ * cleared, so we have to reset tx_dma_len accordingly.
+ */
+ to_sci_port(port)->tx_dma_len = 0;
+}
+#else /* !CONFIG_SERIAL_SH_SCI_DMA */
static inline void sci_request_dma(struct uart_port *port)
{
}
@@ -1463,7 +1474,9 @@ static inline void sci_request_dma(struct uart_port *port)
static inline void sci_free_dma(struct uart_port *port)
{
}
-#endif
+
+#define sci_flush_buffer NULL
+#endif /* !CONFIG_SERIAL_SH_SCI_DMA */
static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
{
@@ -2203,6 +2216,7 @@ static struct uart_ops sci_uart_ops = {
.break_ctl = sci_break_ctl,
.startup = sci_startup,
.shutdown = sci_shutdown,
+ .flush_buffer = sci_flush_buffer,
.set_termios = sci_set_termios,
.pm = sci_pm,
.type = sci_type,
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 1bb629ab8ecc..a638c1738547 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1694,6 +1694,8 @@ static void release_tty(struct tty_struct *tty, int idx)
if (tty->link)
tty->link->port->itty = NULL;
tty_buffer_cancel_work(tty->port);
+ if (tty->link)
+ tty_buffer_cancel_work(tty->link->port);
tty_kref_put(tty->link);
tty_kref_put(tty);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index e4f69bddcfb1..ff3286fc22d8 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1312,6 +1312,11 @@ static void csi_m(struct vc_data *vc)
case 3:
vc->vc_italic = 1;
break;
+ case 21:
+ /*
+ * No console drivers support double underline, so
+ * convert it to a single underline.
+ */
case 4:
vc->vc_underline = 1;
break;
@@ -1348,7 +1353,6 @@ static void csi_m(struct vc_data *vc)
vc->vc_disp_ctrl = 1;
vc->vc_toggle_meta = 1;
break;
- case 21:
case 22:
vc->vc_intensity = 1;
break;
@@ -1725,7 +1729,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
default_attr(vc);
update_attr(vc);
- vc->vc_tab_stop[0] = 0x01010100;
+ vc->vc_tab_stop[0] =
vc->vc_tab_stop[1] =
vc->vc_tab_stop[2] =
vc->vc_tab_stop[3] =
@@ -1769,7 +1773,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
vc->vc_pos -= (vc->vc_x << 1);
while (vc->vc_x < vc->vc_cols - 1) {
vc->vc_x++;
- if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31)))
+ if (vc->vc_tab_stop[7 & (vc->vc_x >> 5)] & (1 << (vc->vc_x & 31)))
break;
}
vc->vc_pos += (vc->vc_x << 1);
@@ -1829,7 +1833,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
lf(vc);
return;
case 'H':
- vc->vc_tab_stop[vc->vc_x >> 5] |= (1 << (vc->vc_x & 31));
+ vc->vc_tab_stop[7 & (vc->vc_x >> 5)] |= (1 << (vc->vc_x & 31));
return;
case 'Z':
respond_ID(tty);
@@ -2022,7 +2026,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
return;
case 'g':
if (!vc->vc_par[0])
- vc->vc_tab_stop[vc->vc_x >> 5] &= ~(1 << (vc->vc_x & 31));
+ vc->vc_tab_stop[7 & (vc->vc_x >> 5)] &= ~(1 << (vc->vc_x & 31));
else if (vc->vc_par[0] == 3) {
vc->vc_tab_stop[0] =
vc->vc_tab_stop[1] =