Commit c2078402 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull tty/serial driver updates from Greg KH:
 "Here is the big tty/serial driver update for 4.3-rc1.

  Not many major things, a number of driver updates and changes, and the
  8250 driver got split up a bit to make it easier to work with by
  moving some functions to a new file.  Full details are in the
  shortlog.

  All have been in linux-next with no reported issues"

* tag 'tty-4.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits)
  serial: imx: save and restore context in the suspend path
  serial: imx: allow waking up on RTSD
  serial: imx: introduce serial_imx_enable_wakeup()
  serial: imx: remove unbalanced clk_prepare
  serial: 8250: move rx_running out of the bitfield
  tty: serial: 8250_omap: do not use RX DMA if pause is not supported
  serial:8250_dw: do not alter CTS and DCTS since AFE is enabled
  tty: serial: men_z135_uart.c: Don't initialize port->lock
  tty: serial: men_z135_uart.c: Fix race between IRQ and set_termios()
  serial: 8250: bind to ALi Fast Infrared Controller (ALI5123)
  serial: 8250: don't bind to SMSC IrCC IR port
  serial: mxs-auart: fix baud rate range
  serial: mxs-auart: keep the AUART unit in reset state when not in use
  serial: mxs-auart: use a function name to reflect what it really does
  serial: 8250_pci: fix mode after S3/S4 resume for F81504/508/512
  sc16is7xx: constify devtype
  sc16is7xx: support multiple devices
  sc16is7xx: save and use per-chip line number
  uart: pl011: Add support to ZTE ZX296702 uart
  uart: pl011: Improve LCRH register access decision
  ...
parents 2f37d65a c868cbb7
......@@ -22,6 +22,8 @@ Optional properties:
memory peripheral interface and USART DMA channel ID, FIFO configuration.
Refer to dma.txt and atmel-dma.txt for details.
- dma-names: "rx" for RX channel, "tx" for TX channel.
- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
capable USARTs.
<chip> compatible description:
- at91rm9200: legacy USART support
......@@ -57,4 +59,5 @@ Example:
dmas = <&dma0 2 0x3>,
<&dma0 2 0x204>;
dma-names = "tx", "rx";
atmel,fifo-size = <32>;
};
......@@ -6,7 +6,7 @@ Required properties:
- interrupts: device interrupt
Optional properties:
- {dtr,dsr,ri,cd}-gpios: specify a GPIO for DTR/DSR/RI/CD
- {dtr,dsr,rng,dcd}-gpios: specify a GPIO for DTR/DSR/RI/DCD
line respectively.
Example:
......@@ -16,4 +16,8 @@ serial@b00260000 {
reg = <0xb0026000 0x1000>;
interrupts = <68>;
status = "disabled";
dtr-gpios = <&sysgpio 0 GPIO_ACTIVE_LOW>;
dsr-gpios = <&sysgpio 1 GPIO_ACTIVE_LOW>;
rng-gpios = <&sysgpio 2 GPIO_ACTIVE_LOW>;
dcd-gpios = <&sysgpio 3 GPIO_ACTIVE_LOW>;
};
......@@ -4,6 +4,9 @@ Required properties:
- compatible : should be "ti,omap2-uart" for OMAP2 controllers
- compatible : should be "ti,omap3-uart" for OMAP3 controllers
- compatible : should be "ti,omap4-uart" for OMAP4 controllers
- compatible : should be "ti,am4372-uart" for AM437x controllers
- compatible : should be "ti,am3352-uart" for AM335x controllers
- compatible : should be "ti,dra742-uart" for DRA7x controllers
- reg : address and length of the register space
- interrupts or interrupts-extended : Should contain the uart interrupt
specifier or both the interrupt
......
......@@ -210,7 +210,7 @@
};
uart0: serial@44e09000 {
compatible = "ti,omap3-uart";
compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart1";
clock-frequency = <48000000>;
reg = <0x44e09000 0x2000>;
......@@ -221,7 +221,7 @@
};
uart1: serial@48022000 {
compatible = "ti,omap3-uart";
compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart2";
clock-frequency = <48000000>;
reg = <0x48022000 0x2000>;
......@@ -232,7 +232,7 @@
};
uart2: serial@48024000 {
compatible = "ti,omap3-uart";
compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart3";
clock-frequency = <48000000>;
reg = <0x48024000 0x2000>;
......@@ -243,7 +243,7 @@
};
uart3: serial@481a6000 {
compatible = "ti,omap3-uart";
compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart4";
clock-frequency = <48000000>;
reg = <0x481a6000 0x2000>;
......@@ -252,7 +252,7 @@
};
uart4: serial@481a8000 {
compatible = "ti,omap3-uart";
compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart5";
clock-frequency = <48000000>;
reg = <0x481a8000 0x2000>;
......@@ -261,7 +261,7 @@
};
uart5: serial@481aa000 {
compatible = "ti,omap3-uart";
compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart6";
clock-frequency = <48000000>;
reg = <0x481aa000 0x2000>;
......
......@@ -397,7 +397,7 @@
};
uart1: serial@4806a000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806a000 0x100>;
interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart1";
......@@ -408,7 +408,7 @@
};
uart2: serial@4806c000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806c000 0x100>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart2";
......@@ -419,7 +419,7 @@
};
uart3: serial@48020000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48020000 0x100>;
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart3";
......@@ -430,7 +430,7 @@
};
uart4: serial@4806e000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806e000 0x100>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart4";
......@@ -441,7 +441,7 @@
};
uart5: serial@48066000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48066000 0x100>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart5";
......@@ -452,7 +452,7 @@
};
uart6: serial@48068000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48068000 0x100>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart6";
......@@ -463,7 +463,7 @@
};
uart7: serial@48420000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48420000 0x100>;
interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart7";
......@@ -472,7 +472,7 @@
};
uart8: serial@48422000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48422000 0x100>;
interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart8";
......@@ -481,7 +481,7 @@
};
uart9: serial@48424000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48424000 0x100>;
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart9";
......@@ -490,7 +490,7 @@
};
uart10: serial@4ae2b000 {
compatible = "ti,omap4-uart";
compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4ae2b000 0x100>;
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart10";
......
......@@ -153,6 +153,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
{"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */
{"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
{"ALI5123"}, /* ALi Fast Infrared Controller */
{"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */
{"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */
{"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
......
......@@ -2712,7 +2712,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
memcpy(skb_put(skb, size), in_buf, size);
skb->dev = net;
skb->protocol = __constant_htons(ETH_P_IP);
skb->protocol = htons(ETH_P_IP);
/* Ship it off to the kernel */
netif_rx(skb);
......
......@@ -2147,6 +2147,8 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
static int job_control(struct tty_struct *tty, struct file *file)
{
struct pid *pgrp;
/* Job control check -- must be done at start and after
every sleep (POSIX.1 7.1.1.4). */
/* NOTE: not yet done after every sleep pending a thorough
......@@ -2156,18 +2158,25 @@ static int job_control(struct tty_struct *tty, struct file *file)
current->signal->tty != tty)
return 0;
rcu_read_lock();
pgrp = task_pgrp(current);
spin_lock_irq(&tty->ctrl_lock);
if (!tty->pgrp)
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
else if (task_pgrp(current) != tty->pgrp) {
else if (pgrp != tty->pgrp) {
spin_unlock_irq(&tty->ctrl_lock);
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
rcu_read_unlock();
return -EIO;
kill_pgrp(task_pgrp(current), SIGTTIN, 1);
}
kill_pgrp(pgrp, SIGTTIN, 1);
rcu_read_unlock();
set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
spin_unlock_irq(&tty->ctrl_lock);
rcu_read_unlock();
return 0;
}
......
......@@ -26,6 +26,12 @@
#include <linux/mutex.h>
#include <linux/poll.h>
#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
# define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args)
#else
# define tty_debug_hangup(tty, f, args...) do {} while (0)
#endif
#ifdef CONFIG_UNIX98_PTYS
static struct tty_driver *ptm_driver;
......@@ -779,6 +785,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
if (retval)
goto err_release;
tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
tty_unlock(tty);
return 0;
err_release:
......
......@@ -42,9 +42,9 @@ struct uart_8250_dma {
size_t rx_size;
size_t tx_size;
unsigned char tx_running:1;
unsigned char tx_err: 1;
unsigned char rx_running:1;
unsigned char tx_running;
unsigned char tx_err;
unsigned char rx_running;
};
struct old_serial_port {
......@@ -211,3 +211,14 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
}
return 1;
}
static inline int serial_index(struct uart_port *port)
{
return port->minor - 64;
}
#if 0
#define DEBUG_INTR(fmt...) printk(fmt)
#else
#define DEBUG_INTR(fmt...) do { } while (0)
#endif
This diff is collapsed.
......@@ -56,7 +56,6 @@
struct dw8250_data {
u8 usr_reg;
int last_mcr;
int line;
int msr_mask_on;
int msr_mask_off;
......@@ -76,12 +75,6 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
/* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */
if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) {
value |= UART_MSR_CTS;
value &= ~UART_MSR_DCTS;
}
/* Override any modem control signals if needed */
if (offset == UART_MSR) {
value |= d->msr_mask_on;
......@@ -101,11 +94,6 @@ static void dw8250_force_idle(struct uart_port *p)
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
if (offset == UART_MCR)
d->last_mcr = value;
writeb(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */
......@@ -144,11 +132,6 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset)
static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
if (offset == UART_MCR)
d->last_mcr = value;
value &= 0xff;
__raw_writeq(value, p->membase + (offset << p->regshift));
/* Read back to ensure register write ordering. */
......@@ -175,11 +158,6 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
if (offset == UART_MCR)
d->last_mcr = value;
writel(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */
......@@ -257,6 +235,11 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
if (!ret)
p->uartclk = rate;
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
out:
serial8250_do_set_termios(p, termios, old);
}
......
......@@ -35,7 +35,7 @@
#include <asm/io.h>
#include <asm/serial.h>
unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
{
switch (port->iotype) {
case UPIO_MEM:
......@@ -51,7 +51,7 @@ unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offse
}
}
void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
{
switch (port->iotype) {
case UPIO_MEM:
......
......@@ -17,18 +17,19 @@
#include <linux/serial_core.h>
#include "8250.h"
#define ADDR_PORT 0x4E
#define DATA_PORT 0x4F
#define ENTRY_KEY 0x77
#define ADDR_PORT 0
#define DATA_PORT 1
#define EXIT_KEY 0xAA
#define CHIP_ID1 0x20
#define CHIP_ID1_VAL 0x02
#define CHIP_ID2 0x21
#define CHIP_ID2_VAL 0x16
#define CHIP_ID_0 0x1602
#define CHIP_ID_1 0x0501
#define VENDOR_ID1 0x23
#define VENDOR_ID1_VAL 0x19
#define VENDOR_ID2 0x24
#define VENDOR_ID2_VAL 0x34
#define IO_ADDR1 0x61
#define IO_ADDR2 0x60
#define LDN 0x7
#define RS485 0xF0
......@@ -39,51 +40,49 @@
#define DRIVER_NAME "8250_fintek"
static int fintek_8250_enter_key(void){
struct fintek_8250 {
u16 base_port;
u8 index;
u8 key;
long line;
};
static int fintek_8250_enter_key(u16 base_port, u8 key)
{
if (!request_muxed_region(ADDR_PORT, 2, DRIVER_NAME))
if (!request_muxed_region(base_port, 2, DRIVER_NAME))
return -EBUSY;
outb(ENTRY_KEY, ADDR_PORT);
outb(ENTRY_KEY, ADDR_PORT);
outb(key, base_port + ADDR_PORT);
outb(key, base_port + ADDR_PORT);
return 0;
}
static void fintek_8250_exit_key(void){
outb(EXIT_KEY, ADDR_PORT);
release_region(ADDR_PORT, 2);
}
static int fintek_8250_get_index(resource_size_t base_addr)
static void fintek_8250_exit_key(u16 base_port)
{
resource_size_t base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
int i;
for (i = 0; i < ARRAY_SIZE(base); i++)
if (base_addr == base[i])
return i;
return -ENODEV;
outb(EXIT_KEY, base_port + ADDR_PORT);
release_region(base_port + ADDR_PORT, 2);
}
static int fintek_8250_check_id(void)
static int fintek_8250_check_id(u16 base_port)
{
u16 chip;
outb(CHIP_ID1, ADDR_PORT);
if (inb(DATA_PORT) != CHIP_ID1_VAL)
outb(VENDOR_ID1, base_port + ADDR_PORT);
if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL)
return -ENODEV;
outb(CHIP_ID2, ADDR_PORT);
if (inb(DATA_PORT) != CHIP_ID2_VAL)
outb(VENDOR_ID2, base_port + ADDR_PORT);
if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL)
return -ENODEV;
outb(VENDOR_ID1, ADDR_PORT);
if (inb(DATA_PORT) != VENDOR_ID1_VAL)
return -ENODEV;
outb(CHIP_ID1, base_port + ADDR_PORT);
chip = inb(base_port + DATA_PORT);
outb(CHIP_ID2, base_port + ADDR_PORT);
chip |= inb(base_port + DATA_PORT) << 8;
outb(VENDOR_ID2, ADDR_PORT);
if (inb(DATA_PORT) != VENDOR_ID2_VAL)
if (chip != CHIP_ID_0 && chip != CHIP_ID_1)
return -ENODEV;
return 0;
......@@ -93,9 +92,9 @@ static int fintek_8250_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
uint8_t config = 0;
int index = fintek_8250_get_index(port->iobase);
struct fintek_8250 *pdata = port->private_data;
if (index < 0)
if (!pdata)
return -EINVAL;
if (rs485->flags & SER_RS485_ENABLED)
......@@ -125,44 +124,84 @@ static int fintek_8250_rs485_config(struct uart_port *port,
if (rs485->flags & SER_RS485_RTS_ON_SEND)
config |= RTS_INVERT;
if (fintek_8250_enter_key())
if (fintek_8250_enter_key(pdata->base_port, pdata->key))
return -EBUSY;
outb(LDN, ADDR_PORT);
outb(index, DATA_PORT);
outb(RS485, ADDR_PORT);
outb(config, DATA_PORT);
fintek_8250_exit_key();
outb(LDN, pdata->base_port + ADDR_PORT);
outb(pdata->index, pdata->base_port + DATA_PORT);
outb(RS485, pdata->base_port + ADDR_PORT);
outb(config, pdata->base_port + DATA_PORT);
fintek_8250_exit_key(pdata->base_port);
port->rs485 = *rs485;
return 0;
}
static int fintek_8250_base_port(u16 io_address, u8 *key, u8 *index)
{
static const u16 addr[] = {0x4e, 0x2e};
static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
int i, j, k;
for (i = 0; i < ARRAY_SIZE(addr); i++) {
for (j = 0; j < ARRAY_SIZE(keys); j++) {
if (fintek_8250_enter_key(addr[i], keys[j]))
continue;
if (fintek_8250_check_id(addr[i])) {
fintek_8250_exit_key(addr[i]);
continue;
}
for (k = 0; k < 4; k++) {
u16 aux;
outb(LDN, addr[i] + ADDR_PORT);
outb(k, addr[i] + DATA_PORT);
outb(IO_ADDR1, addr[i] + ADDR_PORT);
aux = inb(addr[i] + DATA_PORT);
outb(IO_ADDR2, addr[i] + ADDR_PORT);
aux |= inb(addr[i] + DATA_PORT) << 8;
if (aux != io_address)
continue;
fintek_8250_exit_key(addr[i]);
*key = keys[j];
*index = k;
return addr[i];
}
fintek_8250_exit_key(addr[i]);
}
}
return -ENODEV;
}
static int
fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
int line;
struct uart_8250_port uart;
int ret;
struct fintek_8250 *pdata;
int base_port;
u8 key;
u8 index;
if (!pnp_port_valid(dev, 0))
return -ENODEV;
if (fintek_8250_get_index(pnp_port_start(dev, 0)) < 0)
base_port = fintek_8250_base_port(pnp_port_start(dev, 0), &key, &index);
if (base_port < 0)
return -ENODEV;
/* Enable configuration registers*/
if (fintek_8250_enter_key())
return -EBUSY;
memset(&uart, 0, sizeof(uart));
/*Check ID*/
ret = fintek_8250_check_id();
fintek_8250_exit_key();
if (ret)
return ret;
pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
uart.port.private_data = pdata;
memset(&uart, 0, sizeof(uart));
if (!pnp_irq_valid(dev, 0))
return -ENODEV;
uart.port.irq = pnp_irq(dev, 0);
......@@ -176,40 +215,43 @@ fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
uart.port.uartclk = 1843200;
uart.port.dev = &dev->dev;
line = serial8250_register_8250_port(&uart);
if (line < 0)
pdata->key = key;
pdata->base_port = base_port;
pdata->index = index;
pdata->line = serial8250_register_8250_port(&uart);
if (pdata->line < 0)
return -ENODEV;
pnp_set_drvdata(dev, (void *)((long)line + 1));
pnp_set_drvdata(dev, pdata);
return 0;
}
static void fintek_8250_remove(struct pnp_dev *dev)
{
long line = (long)pnp_get_drvdata(dev);
struct fintek_8250 *pdata = pnp_get_drvdata(dev);
if (line)
serial8250_unregister_port(line - 1);
if (pdata)
serial8250_unregister_port(pdata->line);
}
#ifdef CONFIG_PM
static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state)
{
long line = (long)pnp_get_drvdata(dev);
struct fintek_8250 *pdata = pnp_get_drvdata(dev);
if (!line)
if (!pdata)
return -ENODEV;
serial8250_suspend_port(line - 1);
serial8250_suspend_port(pdata->line);
return 0;
}
static int fintek_8250_resume(struct pnp_dev *dev)
{
long line = (long)pnp_get_drvdata(dev);
struct fintek_8250 *pdata = pnp_get_drvdata(dev);
if (!line)
if (!pdata)
return -ENODEV;
serial8250_resume_port(line - 1);
serial8250_resume_port(pdata->line);
return 0;
}
#else
......
......@@ -252,7 +252,6 @@ MODULE_DEVICE_TABLE(of, of_match);
static struct platform_driver ingenic_uart_platform_driver = {
.driver = {
.name = "ingenic-uart",
.owner = THIS_MODULE,
.of_match_table = of_match,
},
.probe = ingenic_uart_probe,
......
......@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/delay.h>
......@@ -32,6 +33,11 @@
#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0)
#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1)
#define OMAP_DMA_TX_KICK (1 << 2)
/*
* See Advisory 21 in AM437x errata SPRZ408B, updated April 2015.
* The same errata is applicable to AM335x and DRA7x processors too.
*/
#define UART_ERRATA_CLOCK_DISABLE (1 << 3)
#define OMAP_UART_FCR_RX_TRIG 6
#define OMAP_UART_FCR_TX_TRIG 4
......@@ -53,6 +59,12 @@
#define OMAP_UART_MVR_MAJ_SHIFT 8
#define OMAP_UART_MVR_MIN_MASK 0x3f
/* SYSC register bitmasks */
#define OMAP_UART_SYSC_SOFTRESET (1 << 1)
/* SYSS register bitmasks */
#define OMAP_UART_SYSS_RESETDONE (1 << 0)
#define UART_TI752_TLR_TX 0
#define UART_TI752_TLR_RX 4
......@@ -100,6 +112,7 @@ struct omap8250_priv {
struct work_struct qos_work;
struct uart_8250_dma omap8250_dma;
spinlock_t rx_dma_lock;
bool rx_dma_broken;
};
static u32 uart_read(struct uart_8250_port *up, u32 reg)
......@@ -232,6 +245,15 @@ static void omap8250_update_scr(struct uart_8250_port *up,
serial_out(up, UART_OMAP_SCR, priv->scr);
}
static void omap8250_update_mdr1(struct uart_8250_port *up,
struct omap8250_priv *priv)
{
if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
omap_8250_mdr1_errataset(up, priv);
else
serial_out(up, UART_OMAP_MDR1, priv->mdr1);
}
static void omap8250_restore_regs(struct uart_8250_port *up)
{
struct omap8250_priv *priv = up->port.private_data;
......@@ -282,11 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
serial_out(up, UART_XOFF1, priv->xoff);
serial_out(up, UART_LCR, up->lcr);
/* need mode A for FCR */
if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
omap_8250_mdr1_errataset(up, priv);
else
serial_out(up, UART_OMAP_MDR1, priv->mdr1);
omap8250_update_mdr1(up, priv);
up->port.ops->set_mctrl(&up->port, up->port.mctrl);
}
......@@ -428,12 +448,9 @@ static void omap_8250_set_termios(struct uart_port *port,
priv->efr |= UART_EFR_CTS;
} else if (up->port.flags & UPF_SOFT_FLOW) {
/*
* IXON Flag:
* Enable XON/XOFF flow control on input.
* Receiver compares XON1, XOFF1.
* OMAP rx s/w flow control is borked; the transmitter remains
* stuck off even if rx flow control is subsequently disabled
*/
if (termios->c_iflag & IXON)
priv->efr |= OMAP_UART_SW_RX;
/*
* IXOFF Flag:
......@@ -444,15 +461,6 @@ static void omap_8250_set_termios(struct uart_port *port,
up->port.status |= UPSTAT_AUTOXOFF;
priv->efr |= OMAP_UART_SW_TX;
}
/*
* IXANY Flag:
* Enable any character to restart output.
* Operation resumes after receiving any
* character after recognition of the XOFF character
*/
if (termios->c_iflag & IXANY)
up->mcr |= UART_MCR_XONANY;
}
omap8250_restore_regs(up);
......@@ -530,14 +538,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
switch (revision) {
case OMAP_UART_REV_46:
priv->habit = UART_ERRATA_i202_MDR1_ACCESS;
priv->habit |= UART_ERRATA_i202_MDR1_ACCESS;
break;
case OMAP_UART_REV_52:
priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
OMAP_UART_WER_HAS_TX_WAKEUP;
break;
case OMAP_UART_REV_63:
priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
OMAP_UART_WER_HAS_TX_WAKEUP;
break;
default:
......@@ -754,6 +762,7 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
struct omap8250_priv *priv = p->port.private_data;
struct uart_8250_dma *dma = p->dma;
unsigned long flags;
int ret;
spin_lock_irqsave(&priv->rx_dma_lock, flags);
......@@ -762,7 +771,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
return;
}
dmaengine_pause(dma->rxchan);
ret = dmaengine_pause(dma->rxchan);
if (WARN_ON_ONCE(ret))
priv->rx_dma_broken = true;
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
......@@ -806,6 +817,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
break;
}
if (priv->rx_dma_broken)
return -EINVAL;
spin_lock_irqsave(&priv->rx_dma_lock, flags);
if (dma->rx_running)
......@@ -1054,6 +1068,20 @@ static int omap8250_no_handle_irq(struct uart_port *port)
return 0;
}
static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
static const u8 am4372_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,am3352-uart", .data = &am3352_habit, },
{ .compatible = "ti,am4372-uart", .data = &am4372_habit, },
{ .compatible = "ti,dra742-uart", .data = &am4372_habit, },
{},
};
MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
static int omap8250_probe(struct platform_device *pdev)
{
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -1118,11 +1146,17 @@ static int omap8250_probe(struct platform_device *pdev)
up.port.unthrottle = omap_8250_unthrottle;
if (pdev->dev.of_node) {
const struct of_device_id *id;
ret = of_alias_get_id(pdev->dev.of_node, "serial");
of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&up.port.uartclk);
priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
if (id && id->data)
priv->habit |= *(u8 *)id->data;
} else {
ret = pdev->id;
}
......@@ -1180,6 +1214,11 @@ static int omap8250_probe(struct platform_device *pdev)
if (of_machine_is_compatible("ti,am33xx"))
priv->habit |= OMAP_DMA_TX_KICK;
/*
* pause is currently not supported atleast on omap-sdma
* and edma on most earlier kernels.
*/
priv->rx_dma_broken = true;
}
}
#endif
......@@ -1257,17 +1296,46 @@ static int omap8250_lost_context(struct uart_8250_port *up)
{
u32 val;
val = serial_in(up, UART_OMAP_MDR1);
val = serial_in(up, UART_OMAP_SCR);
/*
* If we lose context, then MDR1 is set to its reset value which is
* UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x
* or 16x but never to disable again.
* If we lose context, then SCR is set to its reset value of zero.
* After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1,
* among other bits, to never set the register back to zero again.
*/
if (val == UART_OMAP_MDR1_DISABLE)
if (!val)
return 1;
return 0;
}
/* TODO: in future, this should happen via API in drivers/reset/ */
static int omap8250_soft_reset(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(priv->line);
int timeout = 100;
int sysc;
int syss;
sysc = serial_in(up, UART_OMAP_SYSC);
/* softreset the UART */
sysc |= OMAP_UART_SYSC_SOFTRESET;
serial_out(up, UART_OMAP_SYSC, sysc);
/* By experiments, 1us enough for reset complete on AM335x */
do {
udelay(1);
syss = serial_in(up, UART_OMAP_SYSS);
} while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
if (!timeout) {
dev_err(dev, "timed out waiting for reset done\n");
return -ETIMEDOUT;
}
return 0;
}
static int omap8250_runtime_suspend(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
......@@ -1285,7 +1353,18 @@ static int omap8250_runtime_suspend(struct device *dev)
return -EBUSY;
}
if (up->dma)
if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
int ret;
ret = omap8250_soft_reset(dev);
if (ret)
return ret;
/* Restore to UART mode after reset (for wakeup) */
omap8250_update_mdr1(up, priv);
}
if (up->dma && up->dma->rxchan)
omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
......@@ -1310,7 +1389,7 @@ static int omap8250_runtime_resume(struct device *dev)
if (loss_cntx)
omap8250_restore_regs(up);
if (up->dma)
if (up->dma && up->dma->rxchan)
omap_8250_rx_dma(up, 0);
priv->latency = priv->calc_latency;
......@@ -1367,14 +1446,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = {
.complete = omap8250_complete,
};
static const struct of_device_id omap8250_dt_ids[] = {
{ .compatible = "ti,omap2-uart" },
{ .compatible = "ti,omap3-uart" },
{ .compatible = "ti,omap4-uart" },
{},
};
MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
static struct platform_driver omap8250_platform_driver = {
.driver = {
.name = "omap8250",
......
......@@ -1417,6 +1417,10 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK);
p->status &= ~UPSTAT_AUTOCTS;
if (termios->c_cflag & CRTSCTS)
p->status |= UPSTAT_AUTOCTS;
serial8250_do_set_termios(p, termios, old);
}
......@@ -1685,11 +1689,65 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
return ret;
}
/* RTS will control by MCR if this bit is 0 */
#define FINTEK_RTS_CONTROL_BY_HW BIT(4)
/* only worked with FINTEK_RTS_CONTROL_BY_HW on */
#define FINTEK_RTS_INVERT BIT(5)
/* We should do proper H/W transceiver setting before change to RS485 mode */
static int pci_fintek_rs485_config(struct uart_port *port,
struct serial_rs485 *rs485)
{
u8 setting;
u8 *index = (u8 *) port->private_data;
struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev,
dev);
pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting);
if (!rs485)
rs485 = &port->rs485;
else if (rs485->flags & SER_RS485_ENABLED)
memset(rs485->padding, 0, sizeof(rs485->padding));
else
memset(rs485, 0, sizeof(*rs485));
/* F81504/508/512 not support RTS delay before or after send */
rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
if (rs485->flags & SER_RS485_ENABLED) {
/* Enable RTS H/W control mode */
setting |= FINTEK_RTS_CONTROL_BY_HW;
if (rs485->flags & SER_RS485_RTS_ON_SEND) {
/* RTS driving high on TX */
setting &= ~FINTEK_RTS_INVERT;
} else {
/* RTS driving low on TX */
setting |= FINTEK_RTS_INVERT;
}
rs485->delay_rts_after_send = 0;
rs485->delay_rts_before_send = 0;
} else {
/* Disable RTS H/W control mode */
setting &= ~(FINTEK_RTS_CONTROL_BY_HW | FINTEK_RTS_INVERT);
}
pci_write_config_byte(pci_dev, 0x40 + 8 * *index + 7, setting);
if (rs485 != &port->rs485)
port->rs485 = *rs485;
return 0;
}
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;
u8 *data;
u8 config_base;
u16 iobase;
......@@ -1702,6 +1760,15 @@ static int pci_fintek_setup(struct serial_private *priv,
port->port.iotype = UPIO_PORT;
port->port.iobase = iobase;
port->port.rs485_config = pci_fintek_rs485_config;
data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL);
if (!data)
return -ENOMEM;
/* preserve index in PCI configuration space */
*data = idx;
port->port.private_data = data;
return 0;
}
......@@ -1712,6 +1779,8 @@ static int pci_fintek_init(struct pci_dev *dev)
u32 max_port, i;
u32 bar_data[3];
u8 config_base;
struct serial_private *priv = pci_get_drvdata(dev);
struct uart_8250_port *port;
switch (dev->device) {
case 0x1104: /* 4 ports */
......@@ -1752,6 +1821,19 @@ static int pci_fintek_init(struct pci_dev *dev)
(u8)((iobase & 0xff00) >> 8));
pci_write_config_byte(dev, config_base + 0x06, dev->irq);
if (priv) {
/* re-apply RS232/485 mode when
* pciserial_resume_ports()
*/
port = serial8250_get_port(priv->line[i]);
pci_fintek_rs485_config(&port->port, NULL);
} else {
/* First init without port data
* force init to RS232 Mode
*/
pci_write_config_byte(dev, config_base + 0x07, 0x01);
}
}
return max_port;
......@@ -2017,6 +2099,12 @@ pci_wch_ch38x_setup(struct serial_private *priv,
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
#define PCI_VENDOR_ID_PERICOM 0x12D8
#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954
#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
......@@ -2331,27 +2419,12 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
* 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,
.vendor = PCI_VENDOR_ID_PERICOM,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup,
},
/*
* PLX
*/
......@@ -3056,6 +3129,10 @@ enum pci_board_num_t {
pbn_fintek_8,
pbn_fintek_12,
pbn_wch384_4,
pbn_pericom_PI7C9X7951,
pbn_pericom_PI7C9X7952,
pbn_pericom_PI7C9X7954,
pbn_pericom_PI7C9X7958,
};
/*
......@@ -3881,7 +3958,6 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 115200,
.first_offset = 0x40,
},
[pbn_wch384_4] = {
.flags = FL_BASE0,
.num_ports = 4,
......@@ -3889,6 +3965,33 @@ static struct pciserial_board pci_boards[] = {
.uart_offset = 8,
.first_offset = 0xC0,
},
/*
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
*/
[pbn_pericom_PI7C9X7951] = {
.flags = FL_BASE0,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7952] = {
.flags = FL_BASE0,
.num_ports = 2,
.base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7954] = {
.flags = FL_BASE0,
.num_ports = 4,
.base_baud = 921600,
.uart_offset = 0x8,
},
[pbn_pericom_PI7C9X7958] = {
.flags = FL_BASE0,
.num_ports = 8,
.base_baud = 921600,
.uart_offset = 0x8,
},
};
static const struct pci_device_id blacklist[] = {
......@@ -5153,6 +5256,25 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V8358 },
/*
* Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
*/
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7951 },
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7952 },
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7954 },
{ PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_pericom_PI7C9X7958 },
/*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
*/
......
......@@ -41,6 +41,12 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "AEI1240", 0 },
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
{ "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
/*
* ALi Fast Infrared Controller
* Native driver (ali-ircc) is broken so at least
* it can be used with irtty-sir.
*/
{ "ALI5123", 0 },
/* AZT3005 PnP SOUND DEVICE */
{ "AZT4001", 0 },
/* Best Data Products Inc. Smart One 336F PnP Modem */
......@@ -364,6 +370,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
/* Winbond CIR port, should not be probed. We should keep track
of it to prevent the legacy serial driver from probing it */
{ "WEC1022", CIR_PORT },
/*
* SMSC IrCC SIR/FIR port, should not be probed by serial driver
* as well so its own driver can bind to it.
*/
{ "SMCF010", CIR_PORT },
{ "", 0 }
};
......
This diff is collapsed.
......@@ -218,6 +218,7 @@ static int uniphier_uart_probe(struct platform_device *pdev)
ret = serial8250_register_8250_port(&up);
if (ret < 0) {
dev_err(dev, "failed to register 8250 port\n");
clk_disable_unprepare(priv->clk);
return ret;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment