diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 11:18:24 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 11:18:24 -0800 |
| commit | 5266e70335dac35c35b5ca9cea4251c1389d4a68 (patch) | |
| tree | c8bfdcc37b922a0978ea7aab4a43685ee9f33c3e | |
| parent | 03f8d4cca352fd41f26b5c88dec1e4d3f507f5de (diff) | |
| parent | a9b01b5823f73dc741b623dfc52ccd68f8139b55 (diff) | |
| download | linux-5266e70335dac35c35b5ca9cea4251c1389d4a68.tar.gz linux-5266e70335dac35c35b5ca9cea4251c1389d4a68.tar.bz2 linux-5266e70335dac35c35b5ca9cea4251c1389d4a68.zip | |
Merge tag 'tty-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial updates from Greg KH:
"Here's the tty/serial patchset for 4.10-rc1.
It's been a quiet kernel cycle for this subsystem, just a small number
of changes. A few new serial drivers, and some cleanups to the old
vgacon logic, and other minor serial driver changes as well.
All of these have been in linux-next for a while with no reported
issues"
* tag 'tty-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (54 commits)
serial: 8250_mid fix calltrace when hotplug 8250 serial controller
console: Move userspace I/O out of console_lock to fix lockdep warning
tty: nozomi: avoid sprintf buffer overflow
serial: 8250_pci: Detach low-level driver during PCI error recovery
serial: core: don't check port twice in a row
mxs-auart: count FIFO overrun errors
serial: 8250_dw: Add support for IrDA SIR mode
serial: 8250: Expose set_ldisc function
serial: 8250: Add IrDA to UART capabilities
serial: 8250_dma: power off device after TX is done
serial: 8250_port: export serial8250_rpm_{get|put}_tx()
serial: sunsu: Free memory when probe fails
serial: sunhv: Free memory when remove() is called
vt: fix Scroll Lock LED trigger name
tty: typo in comments in drivers/tty/vt/keyboard.c
tty: amba-pl011: Add earlycon support for SBSA UART
tty: nozomi: use permission-specific DEVICE_ATTR variants
tty: serial: Make the STM32 serial port depend on it's arch
serial: ifx6x60: Free memory when probe fails
serial: ioc4_serial: Free memory when kzalloc fails during probe
...
46 files changed, 921 insertions, 429 deletions
diff --git a/Documentation/admin-guide/vga-softcursor.rst b/Documentation/admin-guide/vga-softcursor.rst index a663a745cff4..f52175457e60 100644 --- a/Documentation/admin-guide/vga-softcursor.rst +++ b/Documentation/admin-guide/vga-softcursor.rst @@ -4,15 +4,13 @@ Software cursor for VGA by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz> and Martin Mares <mj@atrey.karlin.mff.cuni.cz> -Linux now has some ability to manipulate cursor appearance. Normally, you -can set the size of hardware cursor (and also work around some ugly bugs in -those miserable Trident cards [#f1]_. You can now play a few new tricks: -you can make your cursor look - -like a non-blinking red block, make it inverse background of the character it's -over or to highlight that character and still choose whether the original -hardware cursor should remain visible or not. There may be other things I have -never thought of. +Linux now has some ability to manipulate cursor appearance. Normally, +you can set the size of hardware cursor. You can now play a few new +tricks: you can make your cursor look like a non-blinking red block, +make it inverse background of the character it's over or to highlight +that character and still choose whether the original hardware cursor +should remain visible or not. There may be other things I have never +thought of. The cursor appearance is controlled by a ``<ESC>[?1;2;3c`` escape sequence where 1, 2 and 3 are parameters described below. If you omit any of them, @@ -48,8 +46,6 @@ third parameter Bit setting takes place before bit toggling, so you can simply clear a bit by including it in both the set mask and the toggle mask. -.. [#f1] see ``#define TRIDENT_GLITCH`` in ``drivers/video/vgacon.c``. - Examples -------- diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c index b27bccd4390f..821cb41f00e6 100644 --- a/arch/x86/platform/ce4100/ce4100.c +++ b/arch/x86/platform/ce4100/ce4100.c @@ -89,7 +89,7 @@ static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value) } static void ce4100_serial_fixup(int port, struct uart_port *up, - unsigned short *capabilites) + u32 *capabilites) { #ifdef CONFIG_EARLY_PRINTK /* diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 208f573495dc..dfbb974927f2 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1012,8 +1012,6 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, { struct serial_struct tmp; - if (!retinfo) - return -EFAULT; memset(&tmp, 0, sizeof(tmp)); tty_lock(tty); tmp.line = tty->index; diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index d6fd0e802ef5..39b3723a32a6 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -63,44 +63,23 @@ #define VERSION_STRING DRIVER_DESC " 2.1d" -/* Macros definitions */ - /* Default debug printout level */ #define NOZOMI_DEBUG_LEVEL 0x00 - -#define P_BUF_SIZE 128 -#define NFO(_err_flag_, args...) \ -do { \ - char tmp[P_BUF_SIZE]; \ - snprintf(tmp, sizeof(tmp), ##args); \ - printk(_err_flag_ "[%d] %s(): %s\n", __LINE__, \ - __func__, tmp); \ -} while (0) - -#define DBG1(args...) D_(0x01, ##args) -#define DBG2(args...) D_(0x02, ##args) -#define DBG3(args...) D_(0x04, ##args) -#define DBG4(args...) D_(0x08, ##args) -#define DBG5(args...) D_(0x10, ##args) -#define DBG6(args...) D_(0x20, ##args) -#define DBG7(args...) D_(0x40, ##args) -#define DBG8(args...) D_(0x80, ##args) - -#ifdef DEBUG -/* Do we need this settable at runtime? */ static int debug = NOZOMI_DEBUG_LEVEL; +module_param(debug, int, S_IRUGO | S_IWUSR); -#define D(lvl, args...) do \ - {if (lvl & debug) NFO(KERN_DEBUG, ##args); } \ - while (0) -#define D_(lvl, args...) D(lvl, ##args) - -/* These printouts are always printed */ +/* Macros definitions */ +#define DBG_(lvl, fmt, args...) \ +do { \ + if (lvl & debug) \ + pr_debug("[%d] %s(): " fmt "\n", \ + __LINE__, __func__, ##args); \ +} while (0) -#else -static int debug; -#define D_(lvl, args...) -#endif +#define DBG1(args...) DBG_(0x01, ##args) +#define DBG2(args...) DBG_(0x02, ##args) +#define DBG3(args...) DBG_(0x04, ##args) +#define DBG4(args...) DBG_(0x08, ##args) /* TODO: rewrite to optimize macros... */ @@ -1320,7 +1299,7 @@ static ssize_t card_type_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", dc->card_type); } -static DEVICE_ATTR(card_type, S_IRUGO, card_type_show, NULL); +static DEVICE_ATTR_RO(card_type); static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1329,7 +1308,7 @@ static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", dc->open_ttys); } -static DEVICE_ATTR(open_ttys, S_IRUGO, open_ttys_show, NULL); +static DEVICE_ATTR_RO(open_ttys); static void make_sysfs_files(struct nozomi *dc) { @@ -1943,7 +1922,5 @@ static __exit void nozomi_exit(void) module_init(nozomi_init); module_exit(nozomi_exit); -module_param(debug, int, S_IRUGO | S_IWUSR); - MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index b0cc47c77b40..d66c1edd9892 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1189,8 +1189,6 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo) { struct rocket_config tmp; - if (!retinfo) - return -EFAULT; memset(&tmp, 0, sizeof (tmp)); mutex_lock(&info->port.mutex); tmp.line = info->line; @@ -1255,8 +1253,6 @@ static int get_ports(struct r_port *info, struct rocket_ports __user *retports) struct rocket_ports tmp; int board; - if (!retports) - return -EFAULT; memset(&tmp, 0, sizeof (tmp)); tmp.tty_major = rocket_driver->major; diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index a697a8585ddc..ce8d4ffcc425 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -80,6 +80,7 @@ struct serial8250_config { #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ #define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ #define UART_CAP_RPM (1 << 15) /* Runtime PM is active while idle */ +#define UART_CAP_IRDA (1 << 16) /* UART supports IrDA line discipline */ #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ @@ -129,8 +130,13 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) } struct uart_8250_port *serial8250_get_port(int line); + void serial8250_rpm_get(struct uart_8250_port *p); void serial8250_rpm_put(struct uart_8250_port *p); + +void serial8250_rpm_get_tx(struct uart_8250_port *p); +void serial8250_rpm_put_tx(struct uart_8250_port *p); + int serial8250_em485_init(struct uart_8250_port *p); void serial8250_em485_destroy(struct uart_8250_port *p); diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 240a361b674f..61569a765d9e 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -425,10 +425,10 @@ struct uart_8250_port *serial8250_get_port(int line) EXPORT_SYMBOL_GPL(serial8250_get_port); static void (*serial8250_isa_config)(int port, struct uart_port *up, - unsigned short *capabilities); + u32 *capabilities); void serial8250_set_isa_configurator( - void (*v)(int port, struct uart_port *up, unsigned short *capabilities)) + void (*v)(int port, struct uart_port *up, u32 *capabilities)) { serial8250_isa_config = v; } @@ -830,6 +830,7 @@ static int serial8250_probe(struct platform_device *dev) uart.port.handle_irq = p->handle_irq; uart.port.handle_break = p->handle_break; uart.port.set_termios = p->set_termios; + uart.port.set_ldisc = p->set_ldisc; uart.port.get_mctrl = p->get_mctrl; uart.port.pm = p->pm; uart.port.dev = &dev->dev; @@ -1023,6 +1024,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) /* Possibly override set_termios call */ if (up->port.set_termios) uart->port.set_termios = up->port.set_termios; + if (up->port.set_ldisc) + uart->port.set_ldisc = up->port.set_ldisc; if (up->port.get_mctrl) uart->port.get_mctrl = up->port.get_mctrl; if (up->port.set_mctrl) diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index fdbddbc6375d..26f17456b0d7 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -72,10 +72,15 @@ int serial8250_tx_dma(struct uart_8250_port *p) struct dma_async_tx_descriptor *desc; int ret; - if (uart_tx_stopped(&p->port) || dma->tx_running || - uart_circ_empty(xmit)) + if (dma->tx_running) return 0; + if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { + /* We have been called from __dma_tx_complete() */ + serial8250_rpm_put_tx(p); + return 0; + } + dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); desc = dmaengine_prep_slave_single(dma->txchan, diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 459d726f9d59..c89fafc972b6 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -53,6 +53,8 @@ /* Helper for fifo size calculation */ #define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) +/* DesignWare specific register fields */ +#define DW_UART_MCR_SIRE BIT(6) struct dw8250_data { u8 usr_reg; @@ -254,6 +256,22 @@ out: serial8250_do_set_termios(p, termios, old); } +static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios) +{ + struct uart_8250_port *up = up_to_u8250p(p); + unsigned int mcr = p->serial_in(p, UART_MCR); + + if (up->capabilities & UART_CAP_IRDA) { + if (termios->c_line == N_IRDA) + mcr |= DW_UART_MCR_SIRE; + else + mcr &= ~DW_UART_MCR_SIRE; + + p->serial_out(p, UART_MCR, mcr); + } + serial8250_do_set_ldisc(p, termios); +} + /* * dw8250_fallback_dma_filter will prevent the UART from getting just any free * channel on platforms that have DMA engines, but don't have any channels @@ -357,6 +375,9 @@ static void dw8250_setup_port(struct uart_port *p) if (reg & DW_UART_CPR_AFCE_MODE) up->capabilities |= UART_CAP_AFE; + + if (reg & DW_UART_CPR_SIR_MODE) + up->capabilities |= UART_CAP_IRDA; } static int dw8250_probe(struct platform_device *pdev) @@ -392,6 +413,7 @@ static int dw8250_probe(struct platform_device *pdev) p->iotype = UPIO_MEM; p->serial_in = dw8250_serial_in; p->serial_out = dw8250_serial_out; + p->set_ldisc = dw8250_set_ldisc; p->membase = devm_ioremap(dev, regs->start, resource_size(regs)); if (!p->membase) diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 0facc789fe7d..b67e7a544935 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -21,8 +21,11 @@ #define EXIT_KEY 0xAA #define CHIP_ID1 0x20 #define CHIP_ID2 0x21 -#define CHIP_ID_0 0x1602 -#define CHIP_ID_1 0x0501 +#define CHIP_ID_F81865 0x0407 +#define CHIP_ID_F81866 0x1010 +#define CHIP_ID_F81216AD 0x1602 +#define CHIP_ID_F81216H 0x0501 +#define CHIP_ID_F81216 0x0802 #define VENDOR_ID1 0x23 #define VENDOR_ID1_VAL 0x19 #define VENDOR_ID2 0x24 @@ -43,12 +46,60 @@ #define RXW4C_IRA BIT(3) #define TXW4C_IRA BIT(2) +#define FIFO_CTRL 0xF6 +#define FIFO_MODE_MASK (BIT(1) | BIT(0)) +#define FIFO_MODE_128 (BIT(1) | BIT(0)) +#define RXFTHR_MODE_MASK (BIT(5) | BIT(4)) +#define RXFTHR_MODE_4X BIT(5) + +#define F81216_LDN_LOW 0x0 +#define F81216_LDN_HIGH 0x4 + +/* + * F81866 registers + * + * The IRQ setting mode of F81866 is not the same with F81216 series. + * Level/Low: IRQ_MODE0:0, IRQ_MODE1:0 + * Edge/High: IRQ_MODE0:1, IRQ_MODE1:0 + */ +#define F81866_IRQ_MODE 0xf0 +#define F81866_IRQ_SHARE BIT(0) +#define F81866_IRQ_MODE0 BIT(1) + +#define F81866_FIFO_CTRL FIFO_CTRL +#define F81866_IRQ_MODE1 BIT(3) + +#define F81866_LDN_LOW 0x10 +#define F81866_LDN_HIGH 0x16 + struct fintek_8250 { + u16 pid; u16 base_port; u8 index; u8 key; }; +static u8 sio_read_reg(struct fintek_8250 *pdata, u8 reg) +{ + outb(reg, pdata->base_port + ADDR_PORT); + return inb(pdata->base_port + DATA_PORT); +} + +static void sio_write_reg(struct fintek_8250 *pdata, u8 reg, u8 data) +{ + outb(reg, pdata->base_port + ADDR_PORT); + outb(data, pdata->base_port + DATA_PORT); +} + +static void sio_write_mask_reg(struct fintek_8250 *pdata, u8 reg, u8 mask, + u8 data) +{ + u8 tmp; + + tmp = (sio_read_reg(pdata, reg) & ~mask) | (mask & data); + sio_write_reg(pdata, reg, tmp); +} + static int fintek_8250_enter_key(u16 base_port, u8 key) { if (!request_muxed_region(base_port, 2, "8250_fintek")) @@ -66,29 +117,55 @@ static void fintek_8250_exit_key(u16 base_port) release_region(base_port + ADDR_PORT, 2); } -static int fintek_8250_check_id(u16 base_port) +static int fintek_8250_check_id(struct fintek_8250 *pdata) { u16 chip; - outb(VENDOR_ID1, base_port + ADDR_PORT); - if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL) + if (sio_read_reg(pdata, VENDOR_ID1) != VENDOR_ID1_VAL) return -ENODEV; - outb(VENDOR_ID2, base_port + ADDR_PORT); - if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL) + if (sio_read_reg(pdata, VENDOR_ID2) != VENDOR_ID2_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; - - if (chip != CHIP_ID_0 && chip != CHIP_ID_1) + chip = sio_read_reg(pdata, CHIP_ID1); + chip |= sio_read_reg(pdata, CHIP_ID2) << 8; + + switch (chip) { + case CHIP_ID_F81865: + case CHIP_ID_F81866: + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + break; + default: return -ENODEV; + } + pdata->pid = chip; return 0; } +static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, + int *max) +{ + switch (pdata->pid) { + case CHIP_ID_F81865: + case CHIP_ID_F81866: + *min = F81866_LDN_LOW; + *max = F81866_LDN_HIGH; + return 0; + + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + *min = F81216_LDN_LOW; + *max = F81216_LDN_HIGH; + return 0; + } + + return -ENODEV; +} + static int fintek_8250_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { @@ -128,10 +205,8 @@ static int fintek_8250_rs485_config(struct uart_port *port, if (fintek_8250_enter_key(pdata->base_port, pdata->key)) return -EBUSY; - 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); + sio_write_reg(pdata, LDN, pdata->index); + sio_write_reg(pdata, RS485, config); fintek_8250_exit_key(pdata->base_port); port->rs485 = *rs485; @@ -139,40 +214,90 @@ static int fintek_8250_rs485_config(struct uart_port *port, return 0; } -static int find_base_port(struct fintek_8250 *pdata, u16 io_address) +static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) +{ + sio_write_reg(pdata, LDN, pdata->index); + + switch (pdata->pid) { + case CHIP_ID_F81866: + sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1, + 0); + /* fall through */ + case CHIP_ID_F81865: + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_SHARE, + F81866_IRQ_SHARE); + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_MODE0, + is_level ? 0 : F81866_IRQ_MODE0); + break; + + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, + IRQ_SHARE); + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, + is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); + break; + } +} + +static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) +{ + switch (pdata->pid) { + case CHIP_ID_F81216H: /* 128Bytes FIFO */ + case CHIP_ID_F81866: + sio_write_mask_reg(pdata, FIFO_CTRL, + FIFO_MODE_MASK | RXFTHR_MODE_MASK, + FIFO_MODE_128 | RXFTHR_MODE_4X); + break; + + default: /* Default 16Bytes FIFO */ + break; + } +} + +static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, + unsigned int irq) { static const u16 addr[] = {0x4e, 0x2e}; static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; - int i, j, k; + struct irq_data *irq_data; + bool level_mode = false; + int i, j, k, min, max; for (i = 0; i < ARRAY_SIZE(addr); i++) { for (j = 0; j < ARRAY_SIZE(keys); j++) { + pdata->base_port = addr[i]; + pdata->key = keys[j]; if (fintek_8250_enter_key(addr[i], keys[j])) continue; - if (fintek_8250_check_id(addr[i])) { + if (fintek_8250_check_id(pdata) || + fintek_8250_get_ldn_range(pdata, &min, &max)) { fintek_8250_exit_key(addr[i]); continue; } - for (k = 0; k < 4; k++) { + for (k = min; k < max; 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; + sio_write_reg(pdata, LDN, k); + aux = sio_read_reg(pdata, IO_ADDR1); + aux |= sio_read_reg(pdata, IO_ADDR2) << 8; if (aux != io_address) continue; - fintek_8250_exit_key(addr[i]); - pdata->key = keys[j]; - pdata->base_port = addr[i]; pdata->index = k; + irq_data = irq_get_irq_data(irq); + if (irq_data) + level_mode = + irqd_is_level_type(irq_data); + + fintek_8250_set_irq_mode(pdata, level_mode); + fintek_8250_set_max_fifo(pdata); + fintek_8250_exit_key(addr[i]); + return 0; } @@ -183,39 +308,29 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address) return -ENODEV; } -static int fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool level_mode) +static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) { - int status; - u8 tmp; - - status = fintek_8250_enter_key(pdata->base_port, pdata->key); - if (status) - return status; - - outb(LDN, pdata->base_port + ADDR_PORT); - outb(pdata->index, pdata->base_port + DATA_PORT); - - outb(FINTEK_IRQ_MODE, pdata->base_port + ADDR_PORT); - tmp = inb(pdata->base_port + DATA_PORT); - - tmp &= ~IRQ_MODE_MASK; - tmp |= IRQ_SHARE; - if (!level_mode) - tmp |= IRQ_EDGE_HIGH; - - outb(tmp, pdata->base_port + DATA_PORT); - fintek_8250_exit_key(pdata->base_port); - return 0; + struct fintek_8250 *pdata = uart->port.private_data; + + switch (pdata->pid) { + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81866: + case CHIP_ID_F81865: + uart->port.rs485_config = fintek_8250_rs485_config; + break; + + default: /* No RS485 Auto direction functional */ + break; + } } int fintek_8250_probe(struct uart_8250_port *uart) { struct fintek_8250 *pdata; struct fintek_8250 probe_data; - struct irq_data *irq_data = irq_get_irq_data(uart->port.irq); - bool level_mode = irqd_is_level_type(irq_data); - if (find_base_port(&probe_data, uart->port.iobase)) + if (probe_setup_port(&probe_data, uart->port.iobase, uart->port.irq)) return -ENODEV; pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL); @@ -223,8 +338,8 @@ int fintek_8250_probe(struct uart_8250_port *uart) return -ENOMEM; memcpy(pdata, &probe_data, sizeof(probe_data)); - uart->port.rs485_config = fintek_8250_rs485_config; uart->port.private_data = pdata; + fintek_8250_set_rs485_handler(uart); - return fintek_8250_set_irq_mode(pdata, level_mode); + return 0; } diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index b9923464599f..f607946fd996 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -174,7 +174,7 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) int ret; chip->dev = &pdev->dev; - chip->irq = pdev->irq; + chip->irq = pci_irq_vector(pdev, 0); chip->regs = pci_ioremap_bar(pdev, 1); ch |
