提交 cb159556 编写于 作者: L Linus Torvalds

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

Pull tty/serial driver update from Greg KH:
 "Here's the big tty/serial driver update for 3.15-rc1.

  Nothing major, a number of serial driver updates and a few tty core
  fixes as well.

  All have been in linux-next for a while"

* tag 'tty-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (71 commits)
  tty/serial: omap: empty the RX FIFO at the end of half-duplex TX
  tty/serial: omap: fix RX interrupt enable/disable in half-duplex TX
  serial: sh-sci: Neaten dev_<level> uses
  serial: sh-sci: Replace hardcoded 3 by UART_PM_STATE_OFF
  serial: sh-sci: Add more register documentation
  serial: sh-sci: Remove useless casts
  serial: sh-sci: Replace printk() by pr_*()
  serial_core: Avoid NULL pointer dereference in uart_close()
  serial_core: Get a reference for port->tty in uart_remove_one_port()
  serial: clps711x: Give a chance to perform useful tasks during wait loop
  serial_core: Grammar s/ports/port's/
  serial_core: Spelling s/contro/control/
  serial: efm32: properly namespace location property
  serial: max310x: Add missing #include <linux/uaccess.h>
  synclink: fix info leak in ioctl
  serial: 8250: Clean up the locking for -rt
  serial: 8250_pci: change BayTrail default uartclk
  serial: 8250_pci: more BayTrail error-free bauds
  serial: sh-sci: Add missing call to uart_remove_one_port() in failure path
  serial_core: Unregister console in uart_remove_one_port()
  ...
...@@ -6,7 +6,7 @@ Required properties: ...@@ -6,7 +6,7 @@ Required properties:
- interrupts : Should contain uart interrupt - interrupts : Should contain uart interrupt
Optional properties: Optional properties:
- location : Decides the location of the USART I/O pins. - efm32,location : Decides the location of the USART I/O pins.
Allowed range : [0 .. 5] Allowed range : [0 .. 5]
Default: 0 Default: 0
...@@ -16,5 +16,5 @@ uart@0x4000c400 { ...@@ -16,5 +16,5 @@ uart@0x4000c400 {
compatible = "efm32,uart"; compatible = "efm32,uart";
reg = <0x4000c400 0x400>; reg = <0x4000c400 0x400>;
interrupts = <15>; interrupts = <15>;
location = <0>; efm32,location = <0>;
}; };
...@@ -4,11 +4,24 @@ Required properties: ...@@ -4,11 +4,24 @@ Required properties:
- compatible : Should be "fsl,<soc>-lpuart" - compatible : Should be "fsl,<soc>-lpuart"
- reg : Address and length of the register set for the device - reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt - interrupts : Should contain uart interrupt
- clocks : phandle + clock specifier pairs, one for each entry in clock-names
- clock-names : should contain: "ipg" - the uart clock
Optional properties:
- dmas: A list of two dma specifiers, one for each entry in dma-names.
- dma-names: should contain "tx" and "rx".
Note: Optional properties for DMA support. Write them both or both not.
Example: Example:
uart0: serial@40027000 { uart0: serial@40027000 {
compatible = "fsl,vf610-lpuart"; compatible = "fsl,vf610-lpuart";
reg = <0x40027000 0x1000>; reg = <0x40027000 0x1000>;
interrupts = <0 61 0x00>; interrupts = <0 61 0x00>;
}; clocks = <&clks VF610_CLK_UART0>;
clock-names = "ipg";
dmas = <&edma0 0 2>,
<&edma0 0 3>;
dma-names = "rx","tx";
};
* Maxim MAX310X advanced Universal Asynchronous Receiver-Transmitter (UART)
Required properties:
- compatible: Should be one of the following:
- "maxim,max3107" for Maxim MAX3107,
- "maxim,max3108" for Maxim MAX3108,
- "maxim,max3109" for Maxim MAX3109,
- "maxim,max14830" for Maxim MAX14830.
- reg: SPI chip select number.
- interrupt-parent: The phandle for the interrupt controller that
services interrupts for this IC.
- interrupts: Specifies the interrupt source of the parent interrupt
controller. The format of the interrupt specifier depends on the
parent interrupt controller.
- clocks: phandle to the IC source clock.
- clock-names: Should be "xtal" if clock is an external crystal or
"osc" if an external clock source is used.
Optional properties:
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Should be two. The first cell is the GPIO number and
the second cell is used to specify the GPIO polarity:
0 = active high,
1 = active low.
Example:
max14830: max14830@0 {
compatible = "maxim,max14830";
reg = <0>;
clocks = <&clk20m>;
clock-names = "osc";
interrupt-parent = <&gpio3>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
gpio-controller;
#gpio-cells = <2>;
};
...@@ -37,7 +37,7 @@ Example: ...@@ -37,7 +37,7 @@ Example:
}; };
scifa0: serial@e6c40000 { scifa0: serial@e6c40000 {
compatible = "renesas,scifa-r8a7790", "renesas,scifa-generic"; compatible = "renesas,scifa-r8a7790", "renesas,scifa";
reg = <0 0xe6c40000 0 64>; reg = <0 0xe6c40000 0 64>;
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
......
...@@ -217,8 +217,8 @@ ...@@ -217,8 +217,8 @@
interrupts = <17>; interrupts = <17>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 13>; clocks = <&clks 13>;
sirf,uart-dma-rx-channel = <21>; dmas = <&dmac1 5>, <&dmac0 2>;
sirf,uart-dma-tx-channel = <2>; dma-names = "rx", "tx";
}; };
uart1: uart@b0060000 { uart1: uart@b0060000 {
...@@ -228,6 +228,7 @@ ...@@ -228,6 +228,7 @@
interrupts = <18>; interrupts = <18>;
fifosize = <32>; fifosize = <32>;
clocks = <&clks 14>; clocks = <&clks 14>;
dma-names = "no-rx", "no-tx";
}; };
uart2: uart@b0070000 { uart2: uart@b0070000 {
...@@ -237,8 +238,8 @@ ...@@ -237,8 +238,8 @@
interrupts = <19>; interrupts = <19>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 15>; clocks = <&clks 15>;
sirf,uart-dma-rx-channel = <6>; dmas = <&dmac0 6>, <&dmac0 7>;
sirf,uart-dma-tx-channel = <7>; dma-names = "rx", "tx";
}; };
usp0: usp@b0080000 { usp0: usp@b0080000 {
...@@ -248,8 +249,8 @@ ...@@ -248,8 +249,8 @@
interrupts = <20>; interrupts = <20>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 28>; clocks = <&clks 28>;
sirf,usp-dma-rx-channel = <17>; dmas = <&dmac1 1>, <&dmac1 2>;
sirf,usp-dma-tx-channel = <18>; dma-names = "rx", "tx";
}; };
usp1: usp@b0090000 { usp1: usp@b0090000 {
...@@ -259,8 +260,8 @@ ...@@ -259,8 +260,8 @@
interrupts = <21>; interrupts = <21>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 29>; clocks = <&clks 29>;
sirf,usp-dma-rx-channel = <14>; dmas = <&dmac0 14>, <&dmac0 15>;
sirf,usp-dma-tx-channel = <15>; dma-names = "rx", "tx";
}; };
dmac0: dma-controller@b00b0000 { dmac0: dma-controller@b00b0000 {
......
...@@ -223,8 +223,8 @@ ...@@ -223,8 +223,8 @@
interrupts = <17>; interrupts = <17>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 13>; clocks = <&clks 13>;
sirf,uart-dma-rx-channel = <21>; dmas = <&dmac1 5>, <&dmac0 2>;
sirf,uart-dma-tx-channel = <2>; dma-names = "rx", "tx";
}; };
uart1: uart@b0060000 { uart1: uart@b0060000 {
...@@ -243,8 +243,8 @@ ...@@ -243,8 +243,8 @@
interrupts = <19>; interrupts = <19>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 15>; clocks = <&clks 15>;
sirf,uart-dma-rx-channel = <6>; dmas = <&dmac0 6>, <&dmac0 7>;
sirf,uart-dma-tx-channel = <7>; dma-names = "rx", "tx";
}; };
usp0: usp@b0080000 { usp0: usp@b0080000 {
...@@ -254,8 +254,8 @@ ...@@ -254,8 +254,8 @@
interrupts = <20>; interrupts = <20>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 28>; clocks = <&clks 28>;
sirf,usp-dma-rx-channel = <17>; dmas = <&dmac1 1>, <&dmac1 2>;
sirf,usp-dma-tx-channel = <18>; dma-names = "rx", "tx";
}; };
usp1: usp@b0090000 { usp1: usp@b0090000 {
...@@ -265,8 +265,8 @@ ...@@ -265,8 +265,8 @@
interrupts = <21>; interrupts = <21>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 29>; clocks = <&clks 29>;
sirf,usp-dma-rx-channel = <14>; dmas = <&dmac0 14>, <&dmac0 15>;
sirf,usp-dma-tx-channel = <15>; dma-names = "rx", "tx";
}; };
usp2: usp@b00a0000 { usp2: usp@b00a0000 {
...@@ -276,8 +276,8 @@ ...@@ -276,8 +276,8 @@
interrupts = <22>; interrupts = <22>;
fifosize = <128>; fifosize = <128>;
clocks = <&clks 30>; clocks = <&clks 30>;
sirf,usp-dma-rx-channel = <10>; dmas = <&dmac0 10>, <&dmac0 11>;
sirf,usp-dma-tx-channel = <11>; dma-names = "rx", "tx";
}; };
dmac0: dma-controller@b00b0000 { dmac0: dma-controller@b00b0000 {
......
...@@ -128,27 +128,15 @@ static struct platform_device mx31moboard_flash = { ...@@ -128,27 +128,15 @@ static struct platform_device mx31moboard_flash = {
.num_resources = 1, .num_resources = 1,
}; };
static int moboard_uart0_init(struct platform_device *pdev) static void __init moboard_uart0_init(void)
{ {
int ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack"); if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack")) {
if (ret) gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
return ret;
ret = gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
if (ret)
gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1)); gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1));
}
return ret;
}
static void moboard_uart0_exit(struct platform_device *pdev)
{
gpio_free(IOMUX_TO_GPIO(MX31_PIN_CTS1));
} }
static const struct imxuart_platform_data uart0_pdata __initconst = { static const struct imxuart_platform_data uart0_pdata __initconst = {
.init = moboard_uart0_init,
.exit = moboard_uart0_exit,
}; };
static const struct imxuart_platform_data uart4_pdata __initconst = { static const struct imxuart_platform_data uart4_pdata __initconst = {
...@@ -543,6 +531,7 @@ static void __init mx31moboard_init(void) ...@@ -543,6 +531,7 @@ static void __init mx31moboard_init(void)
imx31_add_imx2_wdt(); imx31_add_imx2_wdt();
moboard_uart0_init();
imx31_add_imx_uart0(&uart0_pdata); imx31_add_imx_uart0(&uart0_pdata);
imx31_add_imx_uart4(&uart4_pdata); imx31_add_imx_uart4(&uart4_pdata);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/atomic.h>
#include <linux/sysrq.h> #include <linux/sysrq.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
...@@ -70,6 +71,9 @@ static struct task_struct *hvc_task; ...@@ -70,6 +71,9 @@ static struct task_struct *hvc_task;
/* Picks up late kicks after list walk but before schedule() */ /* Picks up late kicks after list walk but before schedule() */
static int hvc_kicked; static int hvc_kicked;
/* hvc_init is triggered from hvc_alloc, i.e. only when actually used */
static atomic_t hvc_needs_init __read_mostly = ATOMIC_INIT(-1);
static int hvc_init(void); static int hvc_init(void);
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
...@@ -851,7 +855,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, ...@@ -851,7 +855,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
int i; int i;
/* We wait until a driver actually comes along */ /* We wait until a driver actually comes along */
if (!hvc_driver) { if (atomic_inc_not_zero(&hvc_needs_init)) {
int err = hvc_init(); int err = hvc_init();
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
......
...@@ -176,9 +176,6 @@ void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, ...@@ -176,9 +176,6 @@ void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
": %d chars not inserted to flip buffer!\n", ": %d chars not inserted to flip buffer!\n",
length - work); length - work);
/*
* This may sleep if ->low_latency is set
*/
if (work) if (work)
tty_flip_buffer_push(&tty->port); tty_flip_buffer_push(&tty->port);
} }
......
...@@ -1900,13 +1900,10 @@ static inline int input_available_p(struct tty_struct *tty, int poll) ...@@ -1900,13 +1900,10 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
struct n_tty_data *ldata = tty->disc_data; struct n_tty_data *ldata = tty->disc_data;
int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1; int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
if (ldata->icanon && !L_EXTPROC(tty)) { if (ldata->icanon && !L_EXTPROC(tty))
if (ldata->canon_head != ldata->read_tail) return ldata->canon_head != ldata->read_tail;
return 1; else
} else if (read_cnt(ldata) >= amt) return read_cnt(ldata) >= amt;
return 1;
return 0;
} }
/** /**
......
...@@ -1694,6 +1694,10 @@ static int serial_link_irq_chain(struct uart_8250_port *up) ...@@ -1694,6 +1694,10 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
static void serial_unlink_irq_chain(struct uart_8250_port *up) static void serial_unlink_irq_chain(struct uart_8250_port *up)
{ {
/*
* yes, some broken gcc emit "warning: 'i' may be used uninitialized"
* but no, we are not going to take a patch that assigns NULL below.
*/
struct irq_info *i; struct irq_info *i;
struct hlist_node *n; struct hlist_node *n;
struct hlist_head *h; struct hlist_head *h;
...@@ -2882,14 +2886,10 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2882,14 +2886,10 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
touch_nmi_watchdog(); touch_nmi_watchdog();
local_irq_save(flags); if (port->sysrq || oops_in_progress)
if (port->sysrq) { locked = spin_trylock_irqsave(&port->lock, flags);
/* serial8250_handle_irq() already took the lock */ else
locked = 0; spin_lock_irqsave(&port->lock, flags);
} else if (oops_in_progress) {
locked = spin_trylock(&port->lock);
} else
spin_lock(&port->lock);
/* /*
* First save the IER then disable the interrupts * First save the IER then disable the interrupts
...@@ -2921,8 +2921,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2921,8 +2921,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
serial8250_modem_status(up); serial8250_modem_status(up);
if (locked) if (locked)
spin_unlock(&port->lock); spin_unlock_irqrestore(&port->lock, flags);
local_irq_restore(flags);
} }
static int __init serial8250_console_setup(struct console *co, char *options) static int __init serial8250_console_setup(struct console *co, char *options)
......
...@@ -1366,23 +1366,44 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios, ...@@ -1366,23 +1366,44 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
{ {
unsigned int baud = tty_termios_baud_rate(termios); unsigned int baud = tty_termios_baud_rate(termios);
unsigned int m = 6912; unsigned int m, n;
unsigned int n = 15625;
u32 reg; u32 reg;
/* For baud rates 1M, 2M, 3M and 4M the dividers must be adjusted. */ /*
if (baud == 1000000 || baud == 2000000 || baud == 4000000) { * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
* dividers must be adjusted.
*
* uartclk = (m / n) * 100 MHz, where m <= n
*/
switch (baud) {
case 500000:
case 1000000:
case 2000000:
case 4000000:
m = 64; m = 64;
n = 100; n = 100;
p->uartclk = 64000000; p->uartclk = 64000000;
} else if (baud == 3000000) { break;
case 3500000:
m = 56;
n = 100;
p->uartclk = 56000000;
break;
case 1500000:
case 3000000:
m = 48; m = 48;
n = 100; n = 100;
p->uartclk = 48000000; p->uartclk = 48000000;
} else { break;
p->uartclk = 44236800; case 2500000:
m = 40;
n = 100;
p->uartclk = 40000000;
break;
default:
m = 2304;
n = 3125;
p->uartclk = 73728000;
} }
/* Reset the clock */ /* Reset the clock */
...@@ -3449,6 +3470,10 @@ static struct pciserial_board pci_boards[] = { ...@@ -3449,6 +3470,10 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 921600, .base_baud = 921600,
.reg_shift = 2, .reg_shift = 2,
}, },
/*
* Intel BayTrail HSUART reference clock is 44.2368 MHz at power-on,
* but is overridden by byt_set_termios.
*/
[pbn_byt] = { [pbn_byt] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 1, .num_ports = 1,
......
...@@ -289,7 +289,7 @@ config SERIAL_MAX3100 ...@@ -289,7 +289,7 @@ config SERIAL_MAX3100
MAX3100 chip support MAX3100 chip support
config SERIAL_MAX310X config SERIAL_MAX310X
bool "MAX310X support" tristate "MAX310X support"
depends on SPI_MASTER depends on SPI_MASTER
select SERIAL_CORE select SERIAL_CORE
select REGMAP_SPI if SPI_MASTER select REGMAP_SPI if SPI_MASTER
...@@ -708,7 +708,7 @@ config SERIAL_IP22_ZILOG_CONSOLE ...@@ -708,7 +708,7 @@ config SERIAL_IP22_ZILOG_CONSOLE
config SERIAL_SH_SCI config SERIAL_SH_SCI
tristate "SuperH SCI(F) serial port support" tristate "SuperH SCI(F) serial port support"
depends on HAVE_CLK && (SUPERH || ARM || COMPILE_TEST) depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
select SERIAL_CORE select SERIAL_CORE
config SERIAL_SH_SCI_NR_UARTS config SERIAL_SH_SCI_NR_UARTS
......
...@@ -2154,9 +2154,19 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -2154,9 +2154,19 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
amba_ports[i] = uap; amba_ports[i] = uap;
amba_set_drvdata(dev, uap); amba_set_drvdata(dev, uap);
if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg);
if (ret < 0) {
pr_err("Failed to register AMBA-PL011 driver\n");
return ret;
}
}
ret = uart_add_one_port(&amba_reg, &uap->port); ret = uart_add_one_port(&amba_reg, &uap->port);
if (ret) { if (ret) {
amba_ports[i] = NULL; amba_ports[i] = NULL;
uart_unregister_driver(&amba_reg);
pl011_dma_remove(uap); pl011_dma_remove(uap);
} }
out: out:
...@@ -2175,6 +2185,7 @@ static int pl011_remove(struct amba_device *dev) ...@@ -2175,6 +2185,7 @@ static int pl011_remove(struct amba_device *dev)
amba_ports[i] = NULL; amba_ports[i] = NULL;
pl011_dma_remove(uap); pl011_dma_remove(uap);
uart_unregister_driver(&amba_reg);
return 0; return 0;
} }
...@@ -2230,22 +2241,14 @@ static struct amba_driver pl011_driver = { ...@@ -2230,22 +2241,14 @@ static struct amba_driver pl011_driver = {
static int __init pl011_init(void) static int __init pl011_init(void)
{ {
int ret;
printk(KERN_INFO "Serial: AMBA PL011 UART driver\n"); printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
ret = uart_register_driver(&amba_reg); return amba_driver_register(&pl011_driver);
if (ret == 0) {
ret = amba_driver_register(&pl011_driver);
if (ret)
uart_unregister_driver(&amba_reg);
}
return ret;
} }
static void __exit pl011_exit(void) static void __exit pl011_exit(void)
{ {
amba_driver_unregister(&pl011_driver); amba_driver_unregister(&pl011_driver);
uart_unregister_driver(&amba_reg);
} }
/* /*
......
...@@ -115,9 +115,6 @@ static void atmel_stop_rx(struct uart_port *port); ...@@ -115,9 +115,6 @@ static void atmel_stop_rx(struct uart_port *port);
#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR) #define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR) #define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
static int (*atmel_open_hook)(struct uart_port *);
static void (*atmel_close_hook)(struct uart_port *);
struct atmel_dma_buffer { struct atmel_dma_buffer {
unsigned char *buf; unsigned char *buf;
dma_addr_t dma_addr; dma_addr_t dma_addr;
...@@ -1555,7 +1552,7 @@ static int atmel_startup(struct uart_port *port) ...@@ -1555,7 +1552,7 @@ static int atmel_startup(struct uart_port *port)
retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED, retval = request_irq(port->irq, atmel_interrupt, IRQF_SHARED,
tty ? tty->name : "atmel_serial", port); tty ? tty->name : "atmel_serial", port);
if (retval) { if (retval) {
printk("atmel_serial: atmel_startup - Can't get irq\n"); dev_err(port->dev, "atmel_startup - Can't get irq\n");
return retval; return retval;
} }
...@@ -1575,17 +1572,6 @@ static int atmel_startup(struct uart_port *port) ...@@ -1575,17 +1572,6 @@ static int atmel_startup(struct uart_port *port)
if (retval < 0) if (retval < 0)
atmel_set_ops(port); atmel_set_ops(port);
} }
/*
* If there is a specific "open" function (to register
* control line interrupts)
*/
if (atmel_open_hook) {
retval = atmel_open_hook(port);
if (retval) {
free_irq(port->irq, port);
return retval;
}
}
/* Save current CSR for comparison in atmel_tasklet_func() */ /* Save current CSR for comparison in atmel_tasklet_func() */
atmel_port->irq_status_prev = UART_GET_CSR(port); atmel_port->irq_status_prev = UART_GET_CSR(port);
...@@ -1684,13 +1670,6 @@ static void atmel_shutdown(struct uart_port *port) ...@@ -1684,13 +1670,6 @@ static void atmel_shutdown(struct uart_port *port)
* Free the interrupt * Free the interrupt
*/ */
free_irq(port->irq, port); free_irq(port->irq, port);
/*
* If there is a specific "close" function (to unregister
* control line interrupts)
*/
if (atmel_close_hook)
atmel_close_hook(port);
} }
/* /*
...@@ -1738,7 +1717,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, ...@@ -1738,7 +1717,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
clk_disable_unprepare(atmel_port->clk); clk_disable_unprepare(atmel_port->clk);
break; break;
default: default:
printk(KERN_ERR "atmel_serial: unknown pm %d\n", state); dev_err(port->dev, "atmel_serial: unknown pm %d\n", state);
} }
} }
...@@ -1853,13 +1832,10 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1853,13 +1832,10 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
mode &= ~ATMEL_US_USMODE; mode &= ~ATMEL_US_USMODE;
if (atmel_port->rs485.flags & SER_RS485_ENABLED) { if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
if ((atmel_port->rs485.delay_rts_after_send) > 0) if ((atmel_port->rs485.delay_rts_after_send) > 0)
UART_PUT_TTGR(port, UART_PUT_TTGR(port,
atmel_port->rs485.delay_rts_after_send); atmel_port->rs485.delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485; mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");
} }
/* set the parity, stop bits and data size */ /* set the parity, stop bits and data size */
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_bcm63xx.h> #include <linux/serial_bcm63xx.h>
#include <linux/io.h>
#include <linux/of.h>
#define BCM63XX_NR_UARTS 2 #define BCM63XX_NR_UARTS 2
...@@ -588,7 +590,7 @@ static int bcm_uart_request_port(struct uart_port *port) ...@@ -588,7 +590,7 @@ static int bcm_uart_request_port(struct uart_port *port)
{ {
unsigned int size; unsigned int size;
size = RSET_UART_SIZE; size = UART_REG_SIZE;
if (!request_mem_region(port->mapbase, size, "bcm63xx")) { if (!request_mem_region(port->mapbase, size, "bcm63xx")) {
dev_err(port->dev, "Memory region busy\n"); dev_err(port->dev, "Memory region busy\n");
return -EBUSY; return -EBUSY;
...@@ -608,7 +610,7 @@ static int bcm_uart_request_port(struct uart_port *port) ...@@ -608,7 +610,7 @@ static int bcm_uart_request_port(struct uart_port *port)
*/ */
static void bcm_uart_release_port(struct uart_port *port) static void bcm_uart_release_port(struct uart_port *port)
{ {
release_mem_region(port->mapbase, RSET_UART_SIZE); release_mem_region(port->mapbase, UART_REG_SIZE);
iounmap(port->membase); iounmap(port->membase);
} }
...@@ -805,6 +807,9 @@ static int bcm_uart_probe(struct platform_device *pdev) ...@@ -805,6 +807,9 @@ static int bcm_uart_probe(struct platform_device *pdev)
struct clk *clk; struct clk *clk;
int ret; int ret;
if (pdev->dev.of_node)
pdev->id = of_alias_get_id(pdev->dev.of_node, "uart");
if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS) if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
return -EINVAL; return -EINVAL;
...@@ -856,6 +861,12 @@ static int bcm_uart_remove(struct platform_device *pdev) ...@@ -856,6 +861,12 @@ static int bcm_uart_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id bcm63xx_of_match[] = {
{ .compatible = "brcm,bcm6345-uart" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, bcm63xx_of_match);
/* /*
* platform driver stuff * platform driver stuff
*/ */
...@@ -865,6 +876,7 @@ static struct platform_driver bcm_uart_platform_driver = { ...@@ -865,6 +876,7 @@ static struct platform_driver bcm_uart_platform_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "bcm63xx_uart", .name = "bcm63xx_uart",
.of_match_table = bcm63xx_of_match,
}, },
}; };
......
...@@ -368,11 +368,16 @@ static const struct uart_ops uart_clps711x_ops = { ...@@ -368,11 +368,16 @@ static const struct uart_ops uart_clps711x_ops = {
static void uart_clps711x_console_putchar(struct uart_port *port, int ch) static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
{ {
struct clps711x_port *s = dev_get_drvdata(port->dev); struct clps711x_port *s = dev_get_drvdata(port->dev);
u32 sysflg = 0;
do { /* Wait for FIFO is not full */
while (1) {
u32 sysflg = 0;
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
} while (sysflg & SYSFLG_UTXFF); if (!(sysflg & SYSFLG_UTXFF))
break;
cond_resched();
}
writew(ch, port->membase + UARTDR_OFFSET); writew(ch, port->membase + UARTDR_OFFSET);
} }
...@@ -382,14 +387,18 @@ static void uart_clps711x_console_write(struct console *co, const char *c, ...@@ -382,14 +387,18 @@ static void uart_clps711x_console_write(struct console *co, const char *c,
{ {
struct uart_port *port = clps711x_uart.state[co->index].uart_port; struct uart_port *port = clps711x_uart.state[co->index].uart_port;
struct clps711x_port *s = dev_get_drvdata(port->dev); struct clps711x_port *s = dev_get_drvdata(port->dev);
u32 sysflg = 0;
uart_console_write(port, c, n, uart_clps711x_console_putchar); uart_console_write(port, c, n, uart_clps711x_console_putchar);
/* Wait for transmitter to become empty */ /* Wait for transmitter to become empty */
do { while (1) {
u32 sysflg = 0;
regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
} while (sysflg & SYSFLG_UBUSY); if (!(sysflg & SYSFLG_UBUSY))
break;
cond_resched();
}
} }
static int uart_clps711x_console_setup(struct console *co, char *options) static int uart_clps711x_console_setup(struct console *co, char *options)
......
...@@ -286,7 +286,6 @@ static struct e100_serial rs_table[] = { ...@@ -286,7 +286,6 @@ static struct e100_serial rs_table[] = {
#endif #endif
}, /* ttyS0 */ }, /* ttyS0 */
#ifndef CONFIG_SVINTO_SIM
{ .baud = DEF_BAUD, { .baud = DEF_BAUD,
.ioport = (unsigned char *)R_SERIAL1_CTRL, .ioport = (unsigned char *)R_SERIAL1_CTRL,
.irq = 1U << 16, /* uses DMA 8 and 9 */ .irq = 1U << 16, /* uses DMA 8 and 9 */
...@@ -447,7 +446,6 @@ static struct e100_serial rs_table[] = { ...@@ -447,7 +446,6 @@ static struct e100_serial rs_table[] = {
.dma_in_enabled = 0 .dma_in_enabled = 0
#endif #endif
} /* ttyS3 */ } /* ttyS3 */
#endif
}; };
...@@ -1035,7 +1033,6 @@ cflag_to_etrax_baud(unsigned int cflag) ...@@ -1035,7 +1033,6 @@ cflag_to_etrax_baud(unsigned int cflag)
static inline void static inline void
e100_dtr(struct e100_serial *info, int set) e100_dtr(struct e100_serial *info, int set)
{ {
#ifndef CONFIG_SVINTO_SIM
unsigned char mask = e100_modem_pins[info->line].dtr_mask; unsigned char mask = e100_modem_pins[info->line].dtr_mask;
#ifdef SERIAL_DEBUG_IO #ifdef SERIAL_DEBUG_IO
...@@ -1060,7 +1057,6 @@ e100_dtr(struct e100_serial *info, int set) ...@@ -1060,7 +1057,6 @@ e100_dtr(struct e100_serial *info, int set)
info->line, *e100_modem_pins[info->line].dtr_shadow, info->line, *e100_modem_pins[info->line].dtr_shadow,
E100_DTR_GET(info)); E100_DTR_GET(info));
#endif #endif
#endif
} }
/* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive /* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive
...@@ -1069,7 +1065,6 @@ e100_dtr(struct e100_serial *info, int set) ...@@ -1069,7 +1065,6 @@ e100_dtr(struct e100_serial *info, int set)
static inline void static inline void
e100_rts(struct e100_serial *info, int set) e100_rts(struct e100_serial *info, int set)
{ {
#ifndef CONFIG_SVINTO_SIM
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
info->rx_ctrl &= ~E100_RTS_MASK; info->rx_ctrl &= ~E100_RTS_MASK;
...@@ -1079,7 +1074,6 @@ e100_rts(struct e100_serial *info, int set) ...@@ -1079,7 +1074,6 @@ e100_rts(struct e100_serial *info, int set)
#ifdef SERIAL_DEBUG_IO #ifdef SERIAL_DEBUG_IO
printk("ser%i rts %i\n", info->line, set); printk("ser%i rts %i\n", info->line, set);
#endif #endif
#endif
} }
...@@ -1087,7 +1081,6 @@ e100_rts(struct e100_serial *info, int set) ...@@ -1087,7 +1081,6 @@ e100_rts(struct e100_serial *info, int set)
static inline void static inline void
e100_ri_out(struct e100_serial *info, int set) e100_ri_out(struct e100_serial *info, int set)
{ {
#ifndef CONFIG_SVINTO_SIM
/* RI is active low */ /* RI is active low */
{ {
unsigned char mask = e100_modem_pins[info->line].ri_mask; unsigned char mask = e100_modem_pins[info->line].ri_mask;
...@@ -1099,12 +1092,10 @@ e100_ri_out(struct e100_serial *info, int set) ...@@ -1099,12 +1092,10 @@ e100_ri_out(struct e100_serial *info, int set)
*e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow; *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
local_irq_restore(flags); local_irq_restore(flags);
} }
#endif
} }
static inline void static inline void
e100_cd_out(struct e100_serial *info, int set) e100_cd_out(struct e100_serial *info, int set)
{ {
#ifndef CONFIG_SVINTO_SIM
/* CD is active low */ /* CD is active low */
{ {
unsigned char mask = e100_modem_pins[info->line].cd_mask; unsigned char mask = e100_modem_pins[info->line].cd_mask;
...@@ -1116,27 +1107,22 @@ e100_cd_out(struct e100_serial *info, int set) ...@@ -1116,27 +1107,22 @@ e100_cd_out(struct e100_serial *info, int set)
*e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow; *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
local_irq_restore(flags); local_irq_restore(flags);
} }
#endif
} }
static inline void static inline void
e100_disable_rx(struct e100_serial *info) e100_disable_rx(struct e100_serial *info)
{ {
#ifndef CONFIG_SVINTO_SIM
/* disable the receiver */ /* disable the receiver */
info->ioport[REG_REC_CTRL] = info->ioport[REG_REC_CTRL] =
(info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); (info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
#endif
} }
static inline void static inline void
e100_enable_rx(struct e100_serial *info) e100_enable_rx(struct e100_serial *info)
{ {
#ifndef CONFIG_SVINTO_SIM
/* enable the receiver */ /* enable the receiver */
info->ioport[REG_REC_CTRL] = info->ioport[REG_REC_CTRL] =
(info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); (info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable));
#endif
} }
/* the rx DMA uses both the dma_descr and the dma_eop interrupts */ /* the rx DMA uses both the dma_descr and the dma_eop interrupts */
...@@ -1554,24 +1540,6 @@ transmit_chars_dma(struct e100_serial *info) ...@@ -1554,24 +1540,6 @@ transmit_chars_dma(struct e100_serial *info)
unsigned int c, sentl; unsigned int c, sentl;
struct etrax_dma_descr *descr; struct etrax_dma_descr *descr;
#ifdef CONFIG_SVINTO_SIM
/* This will output too little if tail is not 0 always since
* we don't reloop to send the other part. Anyway this SHOULD be a
* no-op - transmit_chars_dma would never really be called during sim
* since rs_write does not write into the xmit buffer then.
*/
if (info->xmit.tail)
printk("Error in serial.c:transmit_chars-dma(), tail!=0\n");
if (info->xmit.head != info->xmit.tail) {
SIMCOUT(info->xmit.buf + info->xmit.tail,
CIRC_CNT(info->xmit.head,
info->xmit.tail,
SERIAL_XMIT_SIZE));
info->xmit.head = info->xmit.tail; /* move back head */
info->tr_running = 0;
}
return;
#endif
/* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */ /* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
*info->oclrintradr = *info->oclrintradr =
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
...@@ -1842,13 +1810,6 @@ static void receive_chars_dma(struct e100_serial *info) ...@@ -1842,13 +1810,6 @@ static void receive_chars_dma(struct e100_serial *info)
struct tty_struct *tty; struct tty_struct *tty;
unsigned char rstat; unsigned char rstat;
#ifdef CONFIG_SVINTO_SIM
/* No receive in the simulator. Will probably be when the rest of
* the serial interface works, and this piece will just be removed.
*/
return;
#endif
/* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */ /* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */
*info->iclrintradr = *info->iclrintradr =
IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
...@@ -1934,12 +1895,6 @@ static int start_recv_dma(struct e100_serial *info) ...@@ -1934,12 +1895,6 @@ static int start_recv_dma(struct e100_serial *info)
static void static void
start_receive(struct e100_serial *info) start_receive(struct e100_serial *info)
{ {
#ifdef CONFIG_SVINTO_SIM
/* No receive in the simulator. Will probably be when the rest of
* the serial interface works, and this piece will just be removed.
*/
return;
#endif
if (info->uses_dma_in) { if (info->uses_dma_in) {
/* reset the input dma channel to be sure it works */ /* reset the input dma channel to be sure it works */
...@@ -1972,17 +1927,6 @@ tr_interrupt(int irq, void *dev_id) ...@@ -1972,17 +1927,6 @@ tr_interrupt(int irq, void *dev_id)
int i; int i;
int handled = 0; int handled = 0;
#ifdef CONFIG_SVINTO_SIM
/* No receive in the simulator. Will probably be when the rest of
* the serial interface works, and this piece will just be removed.
*/
{
const char *s = "What? tr_interrupt in simulator??\n";
SIMCOUT(s,strlen(s));
}
return IRQ_HANDLED;
#endif
/* find out the line that caused this irq and get it from rs_table */ /* find out the line that caused this irq and get it from rs_table */
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */ ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
...@@ -2021,17 +1965,6 @@ rec_interrupt(int irq, void *dev_id) ...@@ -2021,17 +1965,6 @@ rec_interrupt(int irq, void *dev_id)
int i; int i;
int handled = 0; int handled = 0;
#ifdef CONFIG_SVINTO_SIM
/* No receive in the simulator. Will probably be when the rest of
* the serial interface works, and this piece will just be removed.
*/
{
const char *s = "What? rec_interrupt in simulator??\n";
SIMCOUT(s,strlen(s));
}
return IRQ_HANDLED;
#endif
/* find out the line that caused this irq and get it from rs_table */ /* find out the line that caused this irq and get it from rs_table */
ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */ ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */
...@@ -2173,10 +2106,6 @@ timed_flush_handler(unsigned long ptr) ...@@ -2173,10 +2106,6 @@ timed_flush_handler(unsigned long ptr)
struct e100_serial *info; struct e100_serial *info;
int i; int i;
#ifdef CONFIG_SVINTO_SIM
return;
#endif
for (i = 0; i < NR_PORTS; i++) { for (i = 0; i < NR_PORTS; i++) {
info = rs_table + i; info = rs_table + i;
if (info->uses_dma_in) if (info->uses_dma_in)
...@@ -2729,25 +2658,6 @@ startup(struct e100_serial * info) ...@@ -2729,25 +2658,6 @@ startup(struct e100_serial * info)
printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf); printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf);
#endif #endif
#ifdef CONFIG_SVINTO_SIM
/* Bits and pieces collected from below. Better to have them
in one ifdef:ed clause than to mix in a lot of ifdefs,
right? */
if (info->port.tty)
clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
info->xmit.head = info->xmit.tail = 0;
info->first_recv_buffer = info->last_recv_buffer = NULL;
info->recv_cnt = info->max_recv_cnt = 0;
for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++)
info->rec_descr[i].buf = NULL;
/* No real action in the simulator, but may set info important
to ioctl. */
change_speed(info);
#else
/* /*
* Clear the FIFO buffers and disable them * Clear the FIFO buffers and disable them
* (they will be reenabled in change_speed()) * (they will be reenabled in change_speed())
...@@ -2837,8 +2747,6 @@ startup(struct e100_serial * info) ...@@ -2837,8 +2747,6 @@ startup(struct e100_serial * info)
e100_rts(info, 1); e100_rts(info, 1);
e100_dtr(info, 1); e100_dtr(info, 1);
#endif /* CONFIG_SVINTO_SIM */
info->port.flags |= ASYNC_INITIALIZED; info->port.flags |= ASYNC_INITIALIZED;
local_irq_restore(flags); local_irq_restore(flags);
...@@ -2857,7 +2765,6 @@ shutdown(struct e100_serial * info) ...@@ -2857,7 +2765,6 @@ shutdown(struct e100_serial * info)
struct etrax_recv_buffer *buffer; struct etrax_recv_buffer *buffer;
int i; int i;
#ifndef CONFIG_SVINTO_SIM
/* shut down the transmitter and receiver */ /* shut down the transmitter and receiver */
DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line)); DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line));
e100_disable_rx(info); e100_disable_rx(info);
...@@ -2882,8 +2789,6 @@ shutdown(struct e100_serial * info) ...@@ -2882,8 +2789,6 @@ shutdown(struct e100_serial * info)
info->tr_running = 0; info->tr_running = 0;
} }
#endif /* CONFIG_SVINTO_SIM */
if (!(info->port.flags & ASYNC_INITIALIZED)) if (!(info->port.flags & ASYNC_INITIALIZED))
return; return;
...@@ -2995,17 +2900,12 @@ change_speed(struct e100_serial *info) ...@@ -2995,17 +2900,12 @@ change_speed(struct e100_serial *info)
IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal); IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal);
r_alt_ser_baudrate_shadow &= ~mask; r_alt_ser_baudrate_shadow &= ~mask;
r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8)); r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8));
#ifndef CONFIG_SVINTO_SIM
*R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow; *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow;
#endif /* CONFIG_SVINTO_SIM */
info->baud = cflag_to_baud(cflag); info->baud = cflag_to_baud(cflag);
#ifndef CONFIG_SVINTO_SIM
info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag); info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag);
#endif /* CONFIG_SVINTO_SIM */
} }
#ifndef CONFIG_SVINTO_SIM
/* start with default settings and then fill in changes */ /* start with default settings and then fill in changes */
local_irq_save(flags); local_irq_save(flags);
/* 8 bit, no/even parity */ /* 8 bit, no/even parity */
...@@ -3073,7 +2973,6 @@ change_speed(struct e100_serial *info) ...@@ -3073,7 +2973,6 @@ change_speed(struct e100_serial *info)
*((unsigned long *)&info->ioport[REG_XOFF]) = xoff; *((unsigned long *)&info->ioport[REG_XOFF]) = xoff;
local_irq_restore(flags); local_irq_restore(flags);
#endif /* !CONFIG_SVINTO_SIM */
update_char_time(info); update_char_time(info);
...@@ -3122,11 +3021,6 @@ static int rs_raw_write(struct tty_struct *tty, ...@@ -3122,11 +3021,6 @@ static int rs_raw_write(struct tty_struct *tty,
count, info->ioport[REG_STATUS]); count, info->ioport[REG_STATUS]);
#endif #endif
#ifdef CONFIG_SVINTO_SIM
/* Really simple. The output is here and now. */
SIMCOUT(buf, count);
return count;
#endif
local_save_flags(flags); local_save_flags(flags);
DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
...@@ -3463,7 +3357,6 @@ static int ...@@ -3463,7 +3357,6 @@ static int
get_lsr_info(struct e100_serial * info, unsigned int *value) get_lsr_info(struct e100_serial * info, unsigned int *value)
{ {
unsigned int result = TIOCSER_TEMT; unsigned int result = TIOCSER_TEMT;
#ifndef CONFIG_SVINTO_SIM
unsigned long curr_time = jiffies; unsigned long curr_time = jiffies;
unsigned long curr_time_usec = GET_JIFFIES_USEC(); unsigned long curr_time_usec = GET_JIFFIES_USEC();
unsigned long elapsed_usec = unsigned long elapsed_usec =
...@@ -3474,7 +3367,6 @@ get_lsr_info(struct e100_serial * info, unsigned int *value) ...@@ -3474,7 +3367,6 @@ get_lsr_info(struct e100_serial * info, unsigned int *value)
elapsed_usec < 2*info->char_time_usec) { elapsed_usec < 2*info->char_time_usec) {
result = 0; result = 0;
} }
#endif
if (copy_to_user(value, &result, sizeof(int))) if (copy_to_user(value, &result, sizeof(int)))
return -EFAULT; return -EFAULT;
...@@ -3804,7 +3696,6 @@ rs_close(struct tty_struct *tty, struct file * filp) ...@@ -3804,7 +3696,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
e100_disable_serial_data_irq(info); e100_disable_serial_data_irq(info);
#endif #endif
#ifndef CONFIG_SVINTO_SIM
e100_disable_rx(info); e100_disable_rx(info);
e100_disable_rx_irq(info); e100_disable_rx_irq(info);
...@@ -3816,7 +3707,6 @@ rs_close(struct tty_struct *tty, struct file * filp) ...@@ -3816,7 +3707,6 @@ rs_close(struct tty_struct *tty, struct file * filp)
*/ */
rs_wait_until_sent(tty, HZ); rs_wait_until_sent(tty, HZ);
} }
#endif
shutdown(info); shutdown(info);
rs_flush_buffer(tty); rs_flush_buffer(tty);
...@@ -4479,7 +4369,6 @@ static int __init rs_init(void) ...@@ -4479,7 +4369,6 @@ static int __init rs_init(void)
fast_timer_init(); fast_timer_init();
#endif #endif
#ifndef CONFIG_SVINTO_SIM
#ifndef CONFIG_ETRAX_KGDB #ifndef CONFIG_ETRAX_KGDB
/* Not needed in simulator. May only complicate stuff. */ /* Not needed in simulator. May only complicate stuff. */
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
...@@ -4489,7 +4378,6 @@ static int __init rs_init(void) ...@@ -4489,7 +4378,6 @@ static int __init rs_init(void)
panic("%s: Failed to request irq8", __func__); panic("%s: Failed to request irq8", __func__);
#endif #endif
#endif /* CONFIG_SVINTO_SIM */
return 0; return 0;
} }
......
...@@ -671,7 +671,10 @@ static int efm32_uart_probe_dt(struct platform_device *pdev, ...@@ -671,7 +671,10 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
if (!np) if (!np)
return 1; return 1;
ret = of_property_read_u32(np, "location", &location); ret = of_property_read_u32(np, "efm32,location", &location);
if (ret)
/* fall back to old and (wrongly) generic property "location" */
ret = of_property_read_u32(np, "location", &location);
if (!ret) { if (!ret) {
if (location > 5) { if (location > 5) {
dev_err(&pdev->dev, "invalid location\n"); dev_err(&pdev->dev, "invalid location\n");
......
...@@ -13,14 +13,19 @@ ...@@ -13,14 +13,19 @@
#define SUPPORT_SYSRQ #define SUPPORT_SYSRQ
#endif #endif
#include <linux/module.h> #include <linux/clk.h>
#include <linux/console.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/clk.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/console.h> #include <linux/of_dma.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/slab.h>
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
/* All registers are 8-bit width */ /* All registers are 8-bit width */
...@@ -112,6 +117,10 @@ ...@@ -112,6 +117,10 @@
#define UARTSFIFO_TXOF 0x02 #define UARTSFIFO_TXOF 0x02
#define UARTSFIFO_RXUF 0x01 #define UARTSFIFO_RXUF 0x01
#define DMA_MAXBURST 16
#define DMA_MAXBURST_MASK (DMA_MAXBURST - 1)
#define FSL_UART_RX_DMA_BUFFER_SIZE 64
#define DRIVER_NAME "fsl-lpuart" #define DRIVER_NAME "fsl-lpuart"
#define DEV_NAME "ttyLP" #define DEV_NAME "ttyLP"
#define UART_NR 6 #define UART_NR 6
...@@ -121,6 +130,24 @@ struct lpuart_port { ...@@ -121,6 +130,24 @@ struct lpuart_port {
struct clk *clk; struct clk *clk;
unsigned int txfifo_size; unsigned int txfifo_size;
unsigned int rxfifo_size; unsigned int rxfifo_size;
bool lpuart_dma_use;
struct dma_chan *dma_tx_chan;
struct dma_chan *dma_rx_chan;
struct dma_async_tx_descriptor *dma_tx_desc;
struct dma_async_tx_descriptor *dma_rx_desc;
dma_addr_t dma_tx_buf_bus;
dma_addr_t dma_rx_buf_bus;
dma_cookie_t dma_tx_cookie;
dma_cookie_t dma_rx_cookie;
unsigned char *dma_tx_buf_virt;
unsigned char *dma_rx_buf_virt;
unsigned int dma_tx_bytes;
unsigned int dma_rx_bytes;
int dma_tx_in_progress;
int dma_rx_in_progress;
unsigned int dma_rx_timeout;
struct timer_list lpuart_timer;
}; };
static struct of_device_id lpuart_dt_ids[] = { static struct of_device_id lpuart_dt_ids[] = {
...@@ -131,6 +158,10 @@ static struct of_device_id lpuart_dt_ids[] = { ...@@ -131,6 +158,10 @@ static struct of_device_id lpuart_dt_ids[] = {
}; };
MODULE_DEVICE_TABLE(of, lpuart_dt_ids); MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
/* Forward declare this for the dma callbacks*/
static void lpuart_dma_tx_complete(void *arg);
static void lpuart_dma_rx_complete(void *arg);
static void lpuart_stop_tx(struct uart_port *port) static void lpuart_stop_tx(struct uart_port *port)
{ {
unsigned char temp; unsigned char temp;
...@@ -152,6 +183,210 @@ static void lpuart_enable_ms(struct uart_port *port) ...@@ -152,6 +183,210 @@ static void lpuart_enable_ms(struct uart_port *port)
{ {
} }
static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
struct tty_port *tty, int count)
{
int copied;
sport->port.icount.rx += count;
if (!tty) {
dev_err(sport->port.dev, "No tty port\n");
return;
}
dma_sync_single_for_cpu(sport->port.dev, sport->dma_rx_buf_bus,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
copied = tty_insert_flip_string(tty,
((unsigned char *)(sport->dma_rx_buf_virt)), count);
if (copied != count) {
WARN_ON(1);
dev_err(sport->port.dev, "RxData copy to tty layer failed\n");
}
dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
}
static void lpuart_pio_tx(struct lpuart_port *sport)
{
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
while (!uart_circ_empty(xmit) &&
readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size) {
writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
sport->port.icount.tx++;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port);
if (uart_circ_empty(xmit))
writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
sport->port.membase + UARTCR5);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static int lpuart_dma_tx(struct lpuart_port *sport, unsigned long count)
{
struct circ_buf *xmit = &sport->port.state->xmit;
dma_addr_t tx_bus_addr;
dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
UART_XMIT_SIZE, DMA_TO_DEVICE);
sport->dma_tx_bytes = count & ~(DMA_MAXBURST_MASK);
tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
tx_bus_addr, sport->dma_tx_bytes,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!sport->dma_tx_desc) {
dev_err(sport->port.dev, "Not able to get desc for tx\n");
return -EIO;
}
sport->dma_tx_desc->callback = lpuart_dma_tx_complete;
sport->dma_tx_desc->callback_param = sport;
sport->dma_tx_in_progress = 1;
sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
dma_async_issue_pending(sport->dma_tx_chan);
return 0;
}
static void lpuart_prepare_tx(struct lpuart_port *sport)
{
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long count = CIRC_CNT_TO_END(xmit->head,
xmit->tail, UART_XMIT_SIZE);
if (!count)
return;
if (count < DMA_MAXBURST)
writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
sport->port.membase + UARTCR5);
else {
writeb(readb(sport->port.membase + UARTCR5) | UARTCR5_TDMAS,
sport->port.membase + UARTCR5);
lpuart_dma_tx(sport, count);
}
}
static void lpuart_dma_tx_complete(void *arg)
{
struct lpuart_port *sport = arg;
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long flags;
async_tx_ack(sport->dma_tx_desc);
spin_lock_irqsave(&sport->port.lock, flags);
xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1);
sport->dma_tx_in_progress = 0;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port);
lpuart_prepare_tx(sport);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static int lpuart_dma_rx(struct lpuart_port *sport)
{
dma_sync_single_for_device(sport->port.dev, sport->dma_rx_buf_bus,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_TO_DEVICE);
sport->dma_rx_desc = dmaengine_prep_slave_single(sport->dma_rx_chan,
sport->dma_rx_buf_bus, FSL_UART_RX_DMA_BUFFER_SIZE,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (!sport->dma_rx_desc) {
dev_err(sport->port.dev, "Not able to get desc for rx\n");
return -EIO;
}
sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
sport->dma_rx_desc->callback_param = sport;
sport->dma_rx_in_progress = 1;
sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc);
dma_async_issue_pending(sport->dma_rx_chan);
return 0;
}
static void lpuart_dma_rx_complete(void *arg)
{
struct lpuart_port *sport = arg;
struct tty_port *port = &sport->port.state->port;
unsigned long flags;
async_tx_ack(sport->dma_rx_desc);
spin_lock_irqsave(&sport->port.lock, flags);
sport->dma_rx_in_progress = 0;
lpuart_copy_rx_to_tty(sport, port, FSL_UART_RX_DMA_BUFFER_SIZE);
tty_flip_buffer_push(port);
lpuart_dma_rx(sport);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static void lpuart_timer_func(unsigned long data)
{
struct lpuart_port *sport = (struct lpuart_port *)data;
struct tty_port *port = &sport->port.state->port;
struct dma_tx_state state;
unsigned long flags;
unsigned char temp;
int count;
del_timer(&sport->lpuart_timer);
dmaengine_pause(sport->dma_rx_chan);
dmaengine_tx_status(sport->dma_rx_chan, sport->dma_rx_cookie, &state);
dmaengine_terminate_all(sport->dma_rx_chan);
count = FSL_UART_RX_DMA_BUFFER_SIZE - state.residue;
async_tx_ack(sport->dma_rx_desc);
spin_lock_irqsave(&sport->port.lock, flags);
sport->dma_rx_in_progress = 0;
lpuart_copy_rx_to_tty(sport, port, count);
tty_flip_buffer_push(port);
temp = readb(sport->port.membase + UARTCR5);
writeb(temp & ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static inline void lpuart_prepare_rx(struct lpuart_port *sport)
{
unsigned long flags;
unsigned char temp;
spin_lock_irqsave(&sport->port.lock, flags);
init_timer(&sport->lpuart_timer);
sport->lpuart_timer.function = lpuart_timer_func;
sport->lpuart_timer.data = (unsigned long)sport;
sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
add_timer(&sport->lpuart_timer);
lpuart_dma_rx(sport);
temp = readb(sport->port.membase + UARTCR5);
writeb(temp | UARTCR5_RDMAS, sport->port.membase + UARTCR5);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static inline void lpuart_transmit_buffer(struct lpuart_port *sport) static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
{ {
struct circ_buf *xmit = &sport->port.state->xmit; struct circ_buf *xmit = &sport->port.state->xmit;
...@@ -172,14 +407,21 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport) ...@@ -172,14 +407,21 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
static void lpuart_start_tx(struct uart_port *port) static void lpuart_start_tx(struct uart_port *port)
{ {
struct lpuart_port *sport = container_of(port, struct lpuart_port, port); struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned char temp; unsigned char temp;
temp = readb(port->membase + UARTCR2); temp = readb(port->membase + UARTCR2);
writeb(temp | UARTCR2_TIE, port->membase + UARTCR2); writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
if (readb(port->membase + UARTSR1) & UARTSR1_TDRE) if (sport->lpuart_dma_use) {
lpuart_transmit_buffer(sport); if (!uart_circ_empty(xmit) && !sport->dma_tx_in_progress)
lpuart_prepare_tx(sport);
} else {
if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
lpuart_transmit_buffer(sport);
}
} }
static irqreturn_t lpuart_txint(int irq, void *dev_id) static irqreturn_t lpuart_txint(int irq, void *dev_id)
...@@ -279,12 +521,19 @@ static irqreturn_t lpuart_int(int irq, void *dev_id) ...@@ -279,12 +521,19 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
sts = readb(sport->port.membase + UARTSR1); sts = readb(sport->port.membase + UARTSR1);
if (sts & UARTSR1_RDRF) if (sts & UARTSR1_RDRF) {
lpuart_rxint(irq, dev_id); if (sport->lpuart_dma_use)
lpuart_prepare_rx(sport);
else
lpuart_rxint(irq, dev_id);
}
if (sts & UARTSR1_TDRE && if (sts & UARTSR1_TDRE &&
!(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS)) !(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS)) {
lpuart_txint(irq, dev_id); if (sport->lpuart_dma_use)
lpuart_pio_tx(sport);
else
lpuart_txint(irq, dev_id);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -366,13 +615,156 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) ...@@ -366,13 +615,156 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
sport->port.membase + UARTCFIFO); sport->port.membase + UARTCFIFO);
writeb(2, sport->port.membase + UARTTWFIFO); writeb(0, sport->port.membase + UARTTWFIFO);
writeb(1, sport->port.membase + UARTRWFIFO); writeb(1, sport->port.membase + UARTRWFIFO);
/* Restore cr2 */ /* Restore cr2 */
writeb(cr2_saved, sport->port.membase + UARTCR2); writeb(cr2_saved, sport->port.membase + UARTCR2);
} }
static int lpuart_dma_tx_request(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
struct dma_chan *tx_chan;
struct dma_slave_config dma_tx_sconfig;
dma_addr_t dma_bus;
unsigned char *dma_buf;
int ret;
tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
if (!tx_chan) {
dev_err(sport->port.dev, "Dma tx channel request failed!\n");
return -ENODEV;
}
dma_bus = dma_map_single(tx_chan->device->dev,
sport->port.state->xmit.buf,
UART_XMIT_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(tx_chan->device->dev, dma_bus)) {
dev_err(sport->port.dev, "dma_map_single tx failed\n");
dma_release_channel(tx_chan);
return -ENOMEM;
}
dma_buf = sport->port.state->xmit.buf;
dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_tx_sconfig.dst_maxburst = DMA_MAXBURST;
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
if (ret < 0) {
dev_err(sport->port.dev,
"Dma slave config failed, err = %d\n", ret);
dma_release_channel(tx_chan);
return ret;
}
sport->dma_tx_chan = tx_chan;
sport->dma_tx_buf_virt = dma_buf;
sport->dma_tx_buf_bus = dma_bus;
sport->dma_tx_in_progress = 0;
return 0;
}
static int lpuart_dma_rx_request(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
struct dma_chan *rx_chan;
struct dma_slave_config dma_rx_sconfig;
dma_addr_t dma_bus;
unsigned char *dma_buf;
int ret;
rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
if (!rx_chan) {
dev_err(sport->port.dev, "Dma rx channel request failed!\n");
return -ENODEV;
}
dma_buf = devm_kzalloc(sport->port.dev,
FSL_UART_RX_DMA_BUFFER_SIZE, GFP_KERNEL);
if (!dma_buf) {
dev_err(sport->port.dev, "Dma rx alloc failed\n");
dma_release_channel(rx_chan);
return -ENOMEM;
}
dma_bus = dma_map_single(rx_chan->device->dev, dma_buf,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
if (dma_mapping_error(rx_chan->device->dev, dma_bus)) {
dev_err(sport->port.dev, "dma_map_single rx failed\n");
dma_release_channel(rx_chan);
return -ENOMEM;
}
dma_rx_sconfig.src_addr = sport->port.mapbase + UARTDR;
dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_rx_sconfig.src_maxburst = 1;
dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
ret = dmaengine_slave_config(rx_chan, &dma_rx_sconfig);
if (ret < 0) {
dev_err(sport->port.dev,
"Dma slave config failed, err = %d\n", ret);
dma_release_channel(rx_chan);
return ret;
}
sport->dma_rx_chan = rx_chan;
sport->dma_rx_buf_virt = dma_buf;
sport->dma_rx_buf_bus = dma_bus;
sport->dma_rx_in_progress = 0;
sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
sport->rxfifo_size / 2;
if (sport->dma_rx_timeout < msecs_to_jiffies(20))
sport->dma_rx_timeout = msecs_to_jiffies(20);
return 0;
}
static void lpuart_dma_tx_free(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
struct dma_chan *dma_chan;
dma_unmap_single(sport->port.dev, sport->dma_tx_buf_bus,
UART_XMIT_SIZE, DMA_TO_DEVICE);
dma_chan = sport->dma_tx_chan;
sport->dma_tx_chan = NULL;
sport->dma_tx_buf_bus = 0;
sport->dma_tx_buf_virt = NULL;
dma_release_channel(dma_chan);
}
static void lpuart_dma_rx_free(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
struct dma_chan *dma_chan;
dma_unmap_single(sport->port.dev, sport->dma_rx_buf_bus,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
dma_chan = sport->dma_rx_chan;
sport->dma_rx_chan = NULL;
sport->dma_rx_buf_bus = 0;
sport->dma_rx_buf_virt = NULL;
dma_release_channel(dma_chan);
}
static int lpuart_startup(struct uart_port *port) static int lpuart_startup(struct uart_port *port)
{ {
struct lpuart_port *sport = container_of(port, struct lpuart_port, port); struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
...@@ -380,6 +772,15 @@ static int lpuart_startup(struct uart_port *port) ...@@ -380,6 +772,15 @@ static int lpuart_startup(struct uart_port *port)
unsigned long flags; unsigned long flags;
unsigned char temp; unsigned char temp;
/*whether use dma support by dma request results*/
if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
sport->lpuart_dma_use = false;
} else {
sport->lpuart_dma_use = true;
temp = readb(port->membase + UARTCR5);
writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
}
ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0, ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
DRIVER_NAME, sport); DRIVER_NAME, sport);
if (ret) if (ret)
...@@ -414,6 +815,11 @@ static void lpuart_shutdown(struct uart_port *port) ...@@ -414,6 +815,11 @@ static void lpuart_shutdown(struct uart_port *port)
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
devm_free_irq(port->dev, port->irq, sport); devm_free_irq(port->dev, port->irq, sport);
if (sport->lpuart_dma_use) {
lpuart_dma_tx_free(port);
lpuart_dma_rx_free(port);
}
} }
static void static void
......
...@@ -496,8 +496,7 @@ static void dma_tx_callback(void *data) ...@@ -496,8 +496,7 @@ static void dma_tx_callback(void *data)
dev_dbg(sport->port.dev, "we finish the TX DMA.\n"); dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&sport->port);
uart_write_wakeup(&sport->port);
if (waitqueue_active(&sport->dma_wait)) { if (waitqueue_active(&sport->dma_wait)) {
wake_up(&sport->dma_wait); wake_up(&sport->dma_wait);
...@@ -1117,25 +1116,25 @@ static int imx_startup(struct uart_port *port) ...@@ -1117,25 +1116,25 @@ static int imx_startup(struct uart_port *port)
*/ */
if (sport->txirq > 0) { if (sport->txirq > 0) {
retval = request_irq(sport->rxirq, imx_rxint, 0, retval = request_irq(sport->rxirq, imx_rxint, 0,
DRIVER_NAME, sport); dev_name(port->dev), sport);
if (retval) if (retval)
goto error_out1; goto error_out1;
retval = request_irq(sport->txirq, imx_txint, 0, retval = request_irq(sport->txirq, imx_txint, 0,
DRIVER_NAME, sport); dev_name(port->dev), sport);
if (retval) if (retval)
goto error_out2; goto error_out2;
/* do not use RTS IRQ on IrDA */ /* do not use RTS IRQ on IrDA */
if (!USE_IRDA(sport)) { if (!USE_IRDA(sport)) {
retval = request_irq(sport->rtsirq, imx_rtsint, 0, retval = request_irq(sport->rtsirq, imx_rtsint, 0,
DRIVER_NAME, sport); dev_name(port->dev), sport);
if (retval) if (retval)
goto error_out3; goto error_out3;
} }
} else { } else {
retval = request_irq(sport->port.irq, imx_int, 0, retval = request_irq(sport->port.irq, imx_int, 0,
DRIVER_NAME, sport); dev_name(port->dev), sport);
if (retval) { if (retval) {
free_irq(sport->port.irq, sport); free_irq(sport->port.irq, sport);
goto error_out1; goto error_out1;
...@@ -1469,36 +1468,6 @@ static const char *imx_type(struct uart_port *port) ...@@ -1469,36 +1468,6 @@ static const char *imx_type(struct uart_port *port)
return sport->port.type == PORT_IMX ? "IMX" : NULL; return sport->port.type == PORT_IMX ? "IMX" : NULL;
} }
/*
* Release the memory region(s) being used by 'port'.
*/
static void imx_release_port(struct uart_port *port)
{
struct platform_device *pdev = to_platform_device(port->dev);
struct resource *mmres;
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mmres->start, resource_size(mmres));
}
/*
* Request the memory region(s) being used by 'port'.
*/
static int imx_request_port(struct uart_port *port)
{
struct platform_device *pdev = to_platform_device(port->dev);
struct resource *mmres;
void *ret;
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mmres)
return -ENODEV;
ret = request_mem_region(mmres->start, resource_size(mmres), "imx-uart");
return ret ? 0 : -EBUSY;
}
/* /*
* Configure/autoconfigure the port. * Configure/autoconfigure the port.
*/ */
...@@ -1506,8 +1475,7 @@ static void imx_config_port(struct uart_port *port, int flags) ...@@ -1506,8 +1475,7 @@ static void imx_config_port(struct uart_port *port, int flags)
{ {
struct imx_port *sport = (struct imx_port *)port; struct imx_port *sport = (struct imx_port *)port;
if (flags & UART_CONFIG_TYPE && if (flags & UART_CONFIG_TYPE)
imx_request_port(&sport->port) == 0)
sport->port.type = PORT_IMX; sport->port.type = PORT_IMX;
} }
...@@ -1617,8 +1585,6 @@ static struct uart_ops imx_pops = { ...@@ -1617,8 +1585,6 @@ static struct uart_ops imx_pops = {
.flush_buffer = imx_flush_buffer, .flush_buffer = imx_flush_buffer,
.set_termios = imx_set_termios, .set_termios = imx_set_termios,
.type = imx_type, .type = imx_type,
.release_port = imx_release_port,
.request_port = imx_request_port,
.config_port = imx_config_port, .config_port = imx_config_port,
.verify_port = imx_verify_port, .verify_port = imx_verify_port,
#if defined(CONFIG_CONSOLE_POLL) #if defined(CONFIG_CONSOLE_POLL)
...@@ -1935,7 +1901,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport, ...@@ -1935,7 +1901,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
static int serial_imx_probe(struct platform_device *pdev) static int serial_imx_probe(struct platform_device *pdev)
{ {
struct imx_port *sport; struct imx_port *sport;
struct imxuart_platform_data *pdata;
void __iomem *base; void __iomem *base;
int ret = 0; int ret = 0;
struct resource *res; struct resource *res;
...@@ -1951,12 +1916,9 @@ static int serial_imx_probe(struct platform_device *pdev) ...@@ -1951,12 +1916,9 @@ static int serial_imx_probe(struct platform_device *pdev)
return ret; return ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) base = devm_ioremap_resource(&pdev->dev, res);
return -ENODEV; if (IS_ERR(base))
return PTR_ERR(base);
base = devm_ioremap(&pdev->dev, res->start, PAGE_SIZE);
if (!base)
return -ENOMEM;
sport->port.dev = &pdev->dev; sport->port.dev = &pdev->dev;
sport->port.mapbase = res->start; sport->port.mapbase = res->start;
...@@ -1992,38 +1954,16 @@ static int serial_imx_probe(struct platform_device *pdev) ...@@ -1992,38 +1954,16 @@ static int serial_imx_probe(struct platform_device *pdev)
imx_ports[sport->port.line] = sport; imx_ports[sport->port.line] = sport;
pdata = dev_get_platdata(&pdev->dev);
if (pdata && pdata->init) {
ret = pdata->init(pdev);
if (ret)
return ret;
}
ret = uart_add_one_port(&imx_reg, &sport->port);
if (ret)
goto deinit;
platform_set_drvdata(pdev, sport); platform_set_drvdata(pdev, sport);
return 0; return uart_add_one_port(&imx_reg, &sport->port);
deinit:
if (pdata && pdata->exit)
pdata->exit(pdev);
return ret;
} }
static int serial_imx_remove(struct platform_device *pdev) static int serial_imx_remove(struct platform_device *pdev)
{ {
struct imxuart_platform_data *pdata;
struct imx_port *sport = platform_get_drvdata(pdev); struct imx_port *sport = platform_get_drvdata(pdev);
pdata = dev_get_platdata(&pdev->dev); return uart_remove_one_port(&imx_reg, &sport->port);
uart_remove_one_port(&imx_reg, &sport->port);
if (pdata && pdata->exit)
pdata->exit(pdev);
return 0;
} }
static struct platform_driver serial_imx_driver = { static struct platform_driver serial_imx_driver = {
......
此差异已折叠。
...@@ -39,6 +39,13 @@ ...@@ -39,6 +39,13 @@
#include "msm_serial.h" #include "msm_serial.h"
enum {
UARTDM_1P1 = 1,
UARTDM_1P2,
UARTDM_1P3,
UARTDM_1P4,
};
struct msm_port { struct msm_port {
struct uart_port uart; struct uart_port uart;
char name[16]; char name[16];
...@@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct uart_port *port) ...@@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct uart_port *port)
static void msm_reset(struct uart_port *port) static void msm_reset(struct uart_port *port)
{ {
struct msm_port *msm_port = UART_TO_MSM(port);
/* reset everything */ /* reset everything */
msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
...@@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *port) ...@@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *port)
msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
msm_write(port, UART_CR_CMD_SET_RFR, UART_CR); msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
/* Disable DM modes */
if (msm_port->is_uartdm)
msm_write(port, 0, UARTDM_DMEN);
} }
static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
...@@ -711,6 +724,117 @@ static void msm_power(struct uart_port *port, unsigned int state, ...@@ -711,6 +724,117 @@ static void msm_power(struct uart_port *port, unsigned int state,
} }
} }
#ifdef CONFIG_CONSOLE_POLL
static int msm_poll_init(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
/* Enable single character mode on RX FIFO */
if (msm_port->is_uartdm >= UARTDM_1P4)
msm_write(port, UARTDM_DMEN_RX_SC_ENABLE, UARTDM_DMEN);
return 0;
}
static int msm_poll_get_char_single(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF;
if (!(msm_read(port, UART_SR) & UART_SR_RX_READY))
return NO_POLL_CHAR;
else
return msm_read(port, rf_reg) & 0xff;
}
static int msm_poll_get_char_dm_1p3(struct uart_port *port)
{
int c;
static u32 slop;
static int count;
unsigned char *sp = (unsigned char *)&slop;
/* Check if a previous read had more than one char */
if (count) {
c = sp[sizeof(slop) - count];
count--;
/* Or if FIFO is empty */
} else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) {
/*
* If RX packing buffer has less than a word, force stale to
* push contents into RX FIFO
*/
count = msm_read(port, UARTDM_RXFS);
count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK;
if (count) {
msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR);
slop = msm_read(port, UARTDM_RF);
c = sp[0];
count--;
} else {
c = NO_POLL_CHAR;
}
/* FIFO has a word */
} else {
slop = msm_read(port, UARTDM_RF);
c = sp[0];
count = sizeof(slop) - 1;
}
return c;
}
static int msm_poll_get_char(struct uart_port *port)
{
u32 imr;
int c;
struct msm_port *msm_port = UART_TO_MSM(port);
/* Disable all interrupts */
imr = msm_read(port, UART_IMR);
msm_write(port, 0, UART_IMR);
if (msm_port->is_uartdm == UARTDM_1P3)
c = msm_poll_get_char_dm_1p3(port);
else
c = msm_poll_get_char_single(port);
/* Enable interrupts */
msm_write(port, imr, UART_IMR);
return c;
}
static void msm_poll_put_char(struct uart_port *port, unsigned char c)
{
u32 imr;
struct msm_port *msm_port = UART_TO_MSM(port);
/* Disable all interrupts */
imr = msm_read(port, UART_IMR);
msm_write(port, 0, UART_IMR);
if (msm_port->is_uartdm)
reset_dm_count(port, 1);
/* Wait until FIFO is empty */
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
cpu_relax();
/* Write a character */
msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
/* Wait until FIFO is empty */
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
cpu_relax();
/* Enable interrupts */
msm_write(port, imr, UART_IMR);
return;
}
#endif
static struct uart_ops msm_uart_pops = { static struct uart_ops msm_uart_pops = {
.tx_empty = msm_tx_empty, .tx_empty = msm_tx_empty,
.set_mctrl = msm_set_mctrl, .set_mctrl = msm_set_mctrl,
...@@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = { ...@@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = {
.config_port = msm_config_port, .config_port = msm_config_port,
.verify_port = msm_verify_port, .verify_port = msm_verify_port,
.pm = msm_power, .pm = msm_power,
#ifdef CONFIG_CONSOLE_POLL
.poll_init = msm_poll_init,
.poll_get_char = msm_poll_get_char,
.poll_put_char = msm_poll_put_char,
#endif
}; };
static struct msm_port msm_uart_ports[] = { static struct msm_port msm_uart_ports[] = {
...@@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_driver = { ...@@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_driver = {
static atomic_t msm_uart_next_id = ATOMIC_INIT(0); static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
static const struct of_device_id msm_uartdm_table[] = { static const struct of_device_id msm_uartdm_table[] = {
{ .compatible = "qcom,msm-uartdm" }, { .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 },
{ .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 },
{ .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 },
{ .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 },
{ } { }
}; };
...@@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struct platform_device *pdev) ...@@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
struct msm_port *msm_port; struct msm_port *msm_port;
struct resource *resource; struct resource *resource;
struct uart_port *port; struct uart_port *port;
const struct of_device_id *id;
int irq; int irq;
if (pdev->id == -1) if (pdev->id == -1)
...@@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struct platform_device *pdev) ...@@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struct platform_device *pdev)
port->dev = &pdev->dev; port->dev = &pdev->dev;
msm_port = UART_TO_MSM(port); msm_port = UART_TO_MSM(port);
if (of_match_device(msm_uartdm_table, &pdev->dev)) id = of_match_device(msm_uartdm_table, &pdev->dev);
msm_port->is_uartdm = 1; if (id)
msm_port->is_uartdm = (unsigned long)id->data;
else else
msm_port->is_uartdm = 0; msm_port->is_uartdm = 0;
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#define UART_CR_CMD_RESET_RFR (14 << 4) #define UART_CR_CMD_RESET_RFR (14 << 4)
#define UART_CR_CMD_PROTECTION_EN (16 << 4) #define UART_CR_CMD_PROTECTION_EN (16 << 4)
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
#define UART_CR_CMD_FORCE_STALE (4 << 8)
#define UART_CR_CMD_RESET_TX_READY (3 << 8) #define UART_CR_CMD_RESET_TX_READY (3 << 8)
#define UART_CR_TX_DISABLE (1 << 3) #define UART_CR_TX_DISABLE (1 << 3)
#define UART_CR_TX_ENABLE (1 << 2) #define UART_CR_TX_ENABLE (1 << 2)
...@@ -113,6 +114,14 @@ ...@@ -113,6 +114,14 @@
#define GSBI_PROTOCOL_UART 0x40 #define GSBI_PROTOCOL_UART 0x40
#define GSBI_PROTOCOL_IDLE 0x0 #define GSBI_PROTOCOL_IDLE 0x0
#define UARTDM_RXFS 0x50
#define UARTDM_RXFS_BUF_SHIFT 0x7
#define UARTDM_RXFS_BUF_MASK 0x7
#define UARTDM_DMEN 0x3C
#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
#define UARTDM_DMRX 0x34 #define UARTDM_DMRX 0x34
#define UARTDM_NCF_TX 0x40 #define UARTDM_NCF_TX 0x40
#define UARTDM_RX_TOTAL_SNAP 0x38 #define UARTDM_RX_TOTAL_SNAP 0x38
......
...@@ -342,7 +342,14 @@ static void serial_omap_stop_tx(struct uart_port *port) ...@@ -342,7 +342,14 @@ static void serial_omap_stop_tx(struct uart_port *port)
if ((up->rs485.flags & SER_RS485_ENABLED) && if ((up->rs485.flags & SER_RS485_ENABLED) &&
!(up->rs485.flags & SER_RS485_RX_DURING_TX)) { !(up->rs485.flags & SER_RS485_RX_DURING_TX)) {
up->ier = UART_IER_RLSI | UART_IER_RDI; /*
* Empty the RX FIFO, we are not interested in anything
* received during the half-duplex transmission.
*/
serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_RCVR);
/* Re-enable RX interrupts */
up->ier |= UART_IER_RLSI | UART_IER_RDI;
up->port.read_status_mask |= UART_LSR_DR;
serial_out(up, UART_IER, up->ier); serial_out(up, UART_IER, up->ier);
} }
...@@ -355,7 +362,7 @@ static void serial_omap_stop_rx(struct uart_port *port) ...@@ -355,7 +362,7 @@ static void serial_omap_stop_rx(struct uart_port *port)
struct uart_omap_port *up = to_uart_omap_port(port); struct uart_omap_port *up = to_uart_omap_port(port);
pm_runtime_get_sync(up->dev); pm_runtime_get_sync(up->dev);
up->ier &= ~UART_IER_RLSI; up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR; up->port.read_status_mask &= ~UART_LSR_DR;
serial_out(up, UART_IER, up->ier); serial_out(up, UART_IER, up->ier);
pm_runtime_mark_last_busy(up->dev); pm_runtime_mark_last_busy(up->dev);
......
...@@ -1762,7 +1762,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, ...@@ -1762,7 +1762,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
int fifosize; int fifosize;
int port_type; int port_type;
struct pch_uart_driver_data *board; struct pch_uart_driver_data *board;
#ifdef CONFIG_DEBUG_FS
char name[32]; /* for debugfs file name */ char name[32]; /* for debugfs file name */
#endif
board = &drv_dat[id->driver_data]; board = &drv_dat[id->driver_data];
port_type = board->port_type; port_type = board->port_type;
......
...@@ -1282,6 +1282,14 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) ...@@ -1282,6 +1282,14 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto probe_err; goto probe_err;
if (!s3c24xx_uart_drv.state) {
ret = uart_register_driver(&s3c24xx_uart_drv);
if (ret < 0) {
pr_err("Failed to register Samsung UART driver\n");
return ret;
}
}
dbg("%s: adding port\n", __func__); dbg("%s: adding port\n", __func__);
uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
platform_set_drvdata(pdev, &ourport->port); platform_set_drvdata(pdev, &ourport->port);
...@@ -1321,6 +1329,8 @@ static int s3c24xx_serial_remove(struct platform_device *dev) ...@@ -1321,6 +1329,8 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
uart_remove_one_port(&s3c24xx_uart_drv, port); uart_remove_one_port(&s3c24xx_uart_drv, port);
} }
uart_unregister_driver(&s3c24xx_uart_drv);
return 0; return 0;
} }
...@@ -1820,35 +1830,7 @@ static struct platform_driver samsung_serial_driver = { ...@@ -1820,35 +1830,7 @@ static struct platform_driver samsung_serial_driver = {
}, },
}; };
/* module initialisation code */ module_platform_driver(samsung_serial_driver);
static int __init s3c24xx_serial_modinit(void)
{
int ret;
ret = uart_register_driver(&s3c24xx_uart_drv);
if (ret < 0) {
pr_err("Failed to register Samsung UART driver\n");
return ret;
}
ret = platform_driver_register(&samsung_serial_driver);
if (ret < 0) {
pr_err("Failed to register platform driver\n");
uart_unregister_driver(&s3c24xx_uart_drv);
}
return ret;
}
static void __exit s3c24xx_serial_modexit(void)
{
platform_driver_unregister(&samsung_serial_driver);
uart_unregister_driver(&s3c24xx_uart_drv);
}
module_init(s3c24xx_serial_modinit);
module_exit(s3c24xx_serial_modexit);
MODULE_ALIAS("platform:samsung-uart"); MODULE_ALIAS("platform:samsung-uart");
MODULE_DESCRIPTION("Samsung SoC Serial port driver"); MODULE_DESCRIPTION("Samsung SoC Serial port driver");
......
...@@ -1319,9 +1319,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) ...@@ -1319,9 +1319,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
uport = state->uart_port; uport = state->uart_port;
port = &state->port; port = &state->port;
pr_debug("uart_close(%d) called\n", uport->line); pr_debug("uart_close(%d) called\n", uport ? uport->line : -1);
if (tty_port_close_start(port, tty, filp) == 0) if (!port->count || tty_port_close_start(port, tty, filp) == 0)
return; return;
/* /*
...@@ -1762,7 +1762,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co) ...@@ -1762,7 +1762,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
} }
/** /**
* uart_parse_options - Parse serial port baud/parity/bits/flow contro. * uart_parse_options - Parse serial port baud/parity/bits/flow control.
* @options: pointer to option string * @options: pointer to option string
* @baud: pointer to an 'int' variable for the baud rate. * @baud: pointer to an 'int' variable for the baud rate.
* @parity: pointer to an 'int' variable for the parity. * @parity: pointer to an 'int' variable for the parity.
...@@ -2609,7 +2609,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2609,7 +2609,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
/* /*
* Register the port whether it's detected or not. This allows * Register the port whether it's detected or not. This allows
* setserial to be used to alter this ports parameters. * setserial to be used to alter this port's parameters.
*/ */
tty_dev = tty_port_register_device_attr(port, drv->tty_driver, tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
uport->line, uport->dev, port, tty_dev_attr_groups); uport->line, uport->dev, port, tty_dev_attr_groups);
...@@ -2645,6 +2645,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2645,6 +2645,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
{ {
struct uart_state *state = drv->state + uport->line; struct uart_state *state = drv->state + uport->line;
struct tty_port *port = &state->port; struct tty_port *port = &state->port;
struct tty_struct *tty;
int ret = 0; int ret = 0;
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
...@@ -2673,8 +2674,17 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) ...@@ -2673,8 +2674,17 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
*/ */
tty_unregister_device(drv->tty_driver, uport->line); tty_unregister_device(drv->tty_driver, uport->line);
if (port->tty) tty = tty_port_tty_get(port);
if (tty) {
tty_vhangup(port->tty); tty_vhangup(port->tty);
tty_kref_put(tty);
}
/*
* If the port is used as a console, unregister it
*/
if (uart_console(uport))
unregister_console(uport->cons);
/* /*
* Free the port IO and memory resources, if any. * Free the port IO and memory resources, if any.
......
...@@ -428,7 +428,7 @@ static int sci_probe_regmap(struct plat_sci_port *cfg) ...@@ -428,7 +428,7 @@ static int sci_probe_regmap(struct plat_sci_port *cfg)
cfg->regtype = SCIx_HSCIF_REGTYPE; cfg->regtype = SCIx_HSCIF_REGTYPE;
break; break;
default: default:
printk(KERN_ERR "Can't probe register map for given port\n"); pr_err("Can't probe register map for given port\n");
return -EINVAL; return -EINVAL;
} }
...@@ -788,7 +788,7 @@ static int sci_handle_errors(struct uart_port *port) ...@@ -788,7 +788,7 @@ static int sci_handle_errors(struct uart_port *port)
if (tty_insert_flip_char(tport, 0, TTY_OVERRUN)) if (tty_insert_flip_char(tport, 0, TTY_OVERRUN))
copied++; copied++;
dev_notice(port->dev, "overrun error"); dev_notice(port->dev, "overrun error\n");
} }
if (status & SCxSR_FER(port)) { if (status & SCxSR_FER(port)) {
...@@ -830,7 +830,7 @@ static int sci_handle_errors(struct uart_port *port) ...@@ -830,7 +830,7 @@ static int sci_handle_errors(struct uart_port *port)
if (tty_insert_flip_char(tport, 0, TTY_PARITY)) if (tty_insert_flip_char(tport, 0, TTY_PARITY))
copied++; copied++;
dev_notice(port->dev, "parity error"); dev_notice(port->dev, "parity error\n");
} }
if (copied) if (copied)
...@@ -911,7 +911,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) ...@@ -911,7 +911,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
/* Disable future Rx interrupts */ /* Disable future Rx interrupts */
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
disable_irq_nosync(irq); disable_irq_nosync(irq);
scr |= 0x4000; scr |= SCSCR_RDRQE;
} else { } else {
scr &= ~SCSCR_RIE; scr &= ~SCSCR_RIE;
} }
...@@ -1199,7 +1199,9 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) ...@@ -1199,7 +1199,9 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
*/ */
reg = sci_getreg(port, SCFCR); reg = sci_getreg(port, SCFCR);
if (reg->size) if (reg->size)
serial_port_out(port, SCFCR, serial_port_in(port, SCFCR) | 1); serial_port_out(port, SCFCR,
serial_port_in(port, SCFCR) |
SCFCR_LOOP);
} }
} }
...@@ -1289,7 +1291,8 @@ static void sci_dma_rx_complete(void *arg) ...@@ -1289,7 +1291,8 @@ static void sci_dma_rx_complete(void *arg)
unsigned long flags; unsigned long flags;
int count; int count;
dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx); dev_dbg(port->dev, "%s(%d) active #%d\n",
__func__, port->line, s->active_rx);
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
...@@ -1365,8 +1368,8 @@ static void sci_submit_rx(struct sci_port *s) ...@@ -1365,8 +1368,8 @@ static void sci_submit_rx(struct sci_port *s)
sci_rx_dma_release(s, true); sci_rx_dma_release(s, true);
return; return;
} }
dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__, dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n",
s->cookie_rx[i], i); __func__, s->cookie_rx[i], i);
} }
s->active_rx = s->cookie_rx[0]; s->active_rx = s->cookie_rx[0];
...@@ -1425,8 +1428,8 @@ static void work_fn_rx(struct work_struct *work) ...@@ -1425,8 +1428,8 @@ static void work_fn_rx(struct work_struct *work)
s->active_rx = s->cookie_rx[!new]; s->active_rx = s->cookie_rx[!new];
dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__, dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n",
s->cookie_rx[new], new, s->active_rx); __func__, s->cookie_rx[new], new, s->active_rx);
} }
static void work_fn_tx(struct work_struct *work) static void work_fn_tx(struct work_struct *work)
...@@ -1479,8 +1482,8 @@ static void work_fn_tx(struct work_struct *work) ...@@ -1479,8 +1482,8 @@ static void work_fn_tx(struct work_struct *work)
return; return;
} }
dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", __func__, dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
xmit->buf, xmit->tail, xmit->head, s->cookie_tx); __func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
} }
...@@ -1495,9 +1498,9 @@ static void sci_start_tx(struct uart_port *port) ...@@ -1495,9 +1498,9 @@ static void sci_start_tx(struct uart_port *port)
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
u16 new, scr = serial_port_in(port, SCSCR); u16 new, scr = serial_port_in(port, SCSCR);
if (s->chan_tx) if (s->chan_tx)
new = scr | 0x8000; new = scr | SCSCR_TDRQE;
else else
new = scr & ~0x8000; new = scr & ~SCSCR_TDRQE;
if (new != scr) if (new != scr)
serial_port_out(port, SCSCR, new); serial_port_out(port, SCSCR, new);
} }
...@@ -1524,7 +1527,7 @@ static void sci_stop_tx(struct uart_port *port) ...@@ -1524,7 +1527,7 @@ static void sci_stop_tx(struct uart_port *port)
ctrl = serial_port_in(port, SCSCR); ctrl = serial_port_in(port, SCSCR);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x8000; ctrl &= ~SCSCR_TDRQE;
ctrl &= ~SCSCR_TIE; ctrl &= ~SCSCR_TIE;
...@@ -1538,7 +1541,7 @@ static void sci_start_rx(struct uart_port *port) ...@@ -1538,7 +1541,7 @@ static void sci_start_rx(struct uart_port *port)
ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port); ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x4000; ctrl &= ~SCSCR_RDRQE;
serial_port_out(port, SCSCR, ctrl); serial_port_out(port, SCSCR, ctrl);
} }
...@@ -1550,7 +1553,7 @@ static void sci_stop_rx(struct uart_port *port) ...@@ -1550,7 +1553,7 @@ static void sci_stop_rx(struct uart_port *port)
ctrl = serial_port_in(port, SCSCR); ctrl = serial_port_in(port, SCSCR);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x4000; ctrl &= ~SCSCR_RDRQE;
ctrl &= ~port_rx_irq_mask(port); ctrl &= ~port_rx_irq_mask(port);
...@@ -1599,8 +1602,8 @@ static bool filter(struct dma_chan *chan, void *slave) ...@@ -1599,8 +1602,8 @@ static bool filter(struct dma_chan *chan, void *slave)
{ {
struct sh_dmae_slave *param = slave; struct sh_dmae_slave *param = slave;
dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__, dev_dbg(chan->device->dev, "%s: slave ID %d\n",
param->shdma_slave.slave_id); __func__, param->shdma_slave.slave_id);
chan->private = &param->shdma_slave; chan->private = &param->shdma_slave;
return true; return true;
...@@ -1613,7 +1616,7 @@ static void rx_timer_fn(unsigned long arg) ...@@ -1613,7 +1616,7 @@ static void rx_timer_fn(unsigned long arg)
u16 scr = serial_port_in(port, SCSCR); u16 scr = serial_port_in(port, SCSCR);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
scr &= ~0x4000; scr &= ~SCSCR_RDRQE;
enable_irq(s->irqs[SCIx_RXI_IRQ]); enable_irq(s->irqs[SCIx_RXI_IRQ]);
} }
serial_port_out(port, SCSCR, scr | SCSCR_RIE); serial_port_out(port, SCSCR, scr | SCSCR_RIE);
...@@ -1629,8 +1632,7 @@ static void sci_request_dma(struct uart_port *port) ...@@ -1629,8 +1632,7 @@ static void sci_request_dma(struct uart_port *port)
dma_cap_mask_t mask; dma_cap_mask_t mask;
int nent; int nent;
dev_dbg(port->dev, "%s: port %d\n", __func__, dev_dbg(port->dev, "%s: port %d\n", __func__, port->line);
port->line);
if (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0) if (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0)
return; return;
...@@ -1658,7 +1660,8 @@ static void sci_request_dma(struct uart_port *port) ...@@ -1658,7 +1660,8 @@ static void sci_request_dma(struct uart_port *port)
if (!nent) if (!nent)
sci_tx_dma_release(s, false); sci_tx_dma_release(s, false);
else else
dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__, dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n",
__func__,
sg_dma_len(&s->sg_tx), port->state->xmit.buf, sg_dma_len(&s->sg_tx), port->state->xmit.buf,
&sg_dma_address(&s->sg_tx)); &sg_dma_address(&s->sg_tx));
...@@ -1870,13 +1873,13 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1870,13 +1873,13 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
smr_val = serial_port_in(port, SCSMR) & 3; smr_val = serial_port_in(port, SCSMR) & 3;
if ((termios->c_cflag & CSIZE) == CS7) if ((termios->c_cflag & CSIZE) == CS7)
smr_val |= 0x40; smr_val |= SCSMR_CHR;
if (termios->c_cflag & PARENB) if (termios->c_cflag & PARENB)
smr_val |= 0x20; smr_val |= SCSMR_PE;
if (termios->c_cflag & PARODD) if (termios->c_cflag & PARODD)
smr_val |= 0x30; smr_val |= SCSMR_PE | SCSMR_ODD;
if (termios->c_cflag & CSTOPB) if (termios->c_cflag & CSTOPB)
smr_val |= 0x08; smr_val |= SCSMR_STOP;
uart_update_timeout(port, termios->c_cflag, baud); uart_update_timeout(port, termios->c_cflag, baud);
...@@ -1884,7 +1887,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1884,7 +1887,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
__func__, smr_val, cks, t, s->cfg->scscr); __func__, smr_val, cks, t, s->cfg->scscr);
if (t >= 0) { if (t >= 0) {
serial_port_out(port, SCSMR, (smr_val & ~3) | cks); serial_port_out(port, SCSMR, (smr_val & ~SCSMR_CKS) | cks);
serial_port_out(port, SCBRR, t); serial_port_out(port, SCBRR, t);
reg = sci_getreg(port, HSSRR); reg = sci_getreg(port, HSSRR);
if (reg->size) if (reg->size)
...@@ -1932,8 +1935,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1932,8 +1935,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
if (s->chan_rx) { if (s->chan_rx) {
s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
port->fifosize / 2; port->fifosize / 2;
dev_dbg(port->dev, dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
"DMA Rx t-out %ums, tty t-out %u jiffies\n",
s->rx_timeout * 1000 / HZ, port->timeout); s->rx_timeout * 1000 / HZ, port->timeout);
if (s->rx_timeout < msecs_to_jiffies(20)) if (s->rx_timeout < msecs_to_jiffies(20))
s->rx_timeout = msecs_to_jiffies(20); s->rx_timeout = msecs_to_jiffies(20);
...@@ -1952,7 +1954,7 @@ static void sci_pm(struct uart_port *port, unsigned int state, ...@@ -1952,7 +1954,7 @@ static void sci_pm(struct uart_port *port, unsigned int state,
struct sci_port *sci_port = to_sci_port(port); struct sci_port *sci_port = to_sci_port(port);
switch (state) { switch (state) {
case 3: case UART_PM_STATE_OFF:
sci_port_disable(sci_port); sci_port_disable(sci_port);
break; break;
default: default:
...@@ -2017,7 +2019,7 @@ static int sci_remap_port(struct uart_port *port) ...@@ -2017,7 +2019,7 @@ static int sci_remap_port(struct uart_port *port)
* need to do any remapping, just cast the cookie * need to do any remapping, just cast the cookie
* directly. * directly.
*/ */
port->membase = (void __iomem *)port->mapbase; port->membase = (void __iomem *)(uintptr_t)port->mapbase;
} }
return 0; return 0;
...@@ -2388,8 +2390,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev) ...@@ -2388,8 +2390,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev)
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
static char banner[] __initdata = static const char banner[] __initconst = "SuperH (H)SCI(F) driver initialized";
KERN_INFO "SuperH (H)SCI(F) driver initialized\n";
static struct uart_driver sci_uart_driver = { static struct uart_driver sci_uart_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -2423,25 +2424,25 @@ struct sci_port_info { ...@@ -2423,25 +2424,25 @@ struct sci_port_info {
static const struct of_device_id of_sci_match[] = { static const struct of_device_id of_sci_match[] = {
{ {
.compatible = "renesas,scif", .compatible = "renesas,scif",
.data = (void *)&(const struct sci_port_info) { .data = &(const struct sci_port_info) {
.type = PORT_SCIF, .type = PORT_SCIF,
.regtype = SCIx_SH4_SCIF_REGTYPE, .regtype = SCIx_SH4_SCIF_REGTYPE,
}, },
}, { }, {
.compatible = "renesas,scifa", .compatible = "renesas,scifa",
.data = (void *)&(const struct sci_port_info) { .data = &(const struct sci_port_info) {
.type = PORT_SCIFA, .type = PORT_SCIFA,
.regtype = SCIx_SCIFA_REGTYPE, .regtype = SCIx_SCIFA_REGTYPE,
}, },
}, { }, {
.compatible = "renesas,scifb", .compatible = "renesas,scifb",
.data = (void *)&(const struct sci_port_info) { .data = &(const struct sci_port_info) {
.type = PORT_SCIFB, .type = PORT_SCIFB,
.regtype = SCIx_SCIFB_REGTYPE, .regtype = SCIx_SCIFB_REGTYPE,
}, },
}, { }, {
.compatible = "renesas,hscif", .compatible = "renesas,hscif",
.data = (void *)&(const struct sci_port_info) { .data = &(const struct sci_port_info) {
.type = PORT_HSCIF, .type = PORT_HSCIF,
.regtype = SCIx_HSCIF_REGTYPE, .regtype = SCIx_HSCIF_REGTYPE,
}, },
...@@ -2501,11 +2502,9 @@ static int sci_probe_single(struct platform_device *dev, ...@@ -2501,11 +2502,9 @@ static int sci_probe_single(struct platform_device *dev,
/* Sanity check */ /* Sanity check */
if (unlikely(index >= SCI_NPORTS)) { if (unlikely(index >= SCI_NPORTS)) {
dev_notice(&dev->dev, "Attempting to register port " dev_notice(&dev->dev, "Attempting to register port %d when only %d are available\n",
"%d when only %d are available.\n",
index+1, SCI_NPORTS); index+1, SCI_NPORTS);
dev_notice(&dev->dev, "Consider bumping " dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
"CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
return -EINVAL; return -EINVAL;
} }
...@@ -2563,6 +2562,7 @@ static int sci_probe(struct platform_device *dev) ...@@ -2563,6 +2562,7 @@ static int sci_probe(struct platform_device *dev)
ret = cpufreq_register_notifier(&sp->freq_transition, ret = cpufreq_register_notifier(&sp->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER); CPUFREQ_TRANSITION_NOTIFIER);
if (unlikely(ret < 0)) { if (unlikely(ret < 0)) {
uart_remove_one_port(&sci_uart_driver, &sp->port);
sci_cleanup_single(sp); sci_cleanup_single(sp);
return ret; return ret;
} }
...@@ -2614,7 +2614,7 @@ static int __init sci_init(void) ...@@ -2614,7 +2614,7 @@ static int __init sci_init(void)
{ {
int ret; int ret;
printk(banner); pr_info("%s\n", banner);
ret = uart_register_driver(&sci_uart_driver); ret = uart_register_driver(&sci_uart_driver);
if (likely(ret == 0)) { if (likely(ret == 0)) {
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-direction.h> #include <linux/dma-direction.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/sirfsoc_dma.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
...@@ -173,7 +172,7 @@ static void sirfsoc_uart_stop_tx(struct uart_port *port) ...@@ -173,7 +172,7 @@ static void sirfsoc_uart_stop_tx(struct uart_port *port)
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) { if (sirfport->tx_dma_chan) {
if (sirfport->tx_dma_state == TX_DMA_RUNNING) { if (sirfport->tx_dma_state == TX_DMA_RUNNING) {
dmaengine_pause(sirfport->tx_dma_chan); dmaengine_pause(sirfport->tx_dma_chan);
sirfport->tx_dma_state = TX_DMA_PAUSE; sirfport->tx_dma_state = TX_DMA_PAUSE;
...@@ -288,7 +287,7 @@ static void sirfsoc_uart_start_tx(struct uart_port *port) ...@@ -288,7 +287,7 @@ static void sirfsoc_uart_start_tx(struct uart_port *port)
struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) if (sirfport->tx_dma_chan)
sirfsoc_uart_tx_with_dma(sirfport); sirfsoc_uart_tx_with_dma(sirfport);
else { else {
sirfsoc_uart_pio_tx_chars(sirfport, 1); sirfsoc_uart_pio_tx_chars(sirfport, 1);
...@@ -310,7 +309,7 @@ static void sirfsoc_uart_stop_rx(struct uart_port *port) ...@@ -310,7 +309,7 @@ static void sirfsoc_uart_stop_rx(struct uart_port *port)
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) { if (sirfport->rx_dma_chan) {
if (!sirfport->is_marco) if (!sirfport->is_marco)
wr_regl(port, ureg->sirfsoc_int_en_reg, wr_regl(port, ureg->sirfsoc_int_en_reg,
rd_regl(port, ureg->sirfsoc_int_en_reg) & rd_regl(port, ureg->sirfsoc_int_en_reg) &
...@@ -675,7 +674,7 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id) ...@@ -675,7 +674,7 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
uart_handle_cts_change(port, cts_status); uart_handle_cts_change(port, cts_status);
wake_up_interruptible(&state->port.delta_msr_wait); wake_up_interruptible(&state->port.delta_msr_wait);
} }
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) { if (sirfport->rx_dma_chan) {
if (intr_status & uint_st->sirfsoc_rx_timeout) if (intr_status & uint_st->sirfsoc_rx_timeout)
sirfsoc_uart_handle_rx_tmo(sirfport); sirfsoc_uart_handle_rx_tmo(sirfport);
if (intr_status & uint_st->sirfsoc_rx_done) if (intr_status & uint_st->sirfsoc_rx_done)
...@@ -686,7 +685,7 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id) ...@@ -686,7 +685,7 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
SIRFSOC_UART_IO_RX_MAX_CNT); SIRFSOC_UART_IO_RX_MAX_CNT);
} }
if (intr_status & uint_st->sirfsoc_txfifo_empty) { if (intr_status & uint_st->sirfsoc_txfifo_empty) {
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) if (sirfport->tx_dma_chan)
sirfsoc_uart_tx_with_dma(sirfport); sirfsoc_uart_tx_with_dma(sirfport);
else { else {
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
...@@ -778,7 +777,7 @@ static void sirfsoc_uart_start_rx(struct uart_port *port) ...@@ -778,7 +777,7 @@ static void sirfsoc_uart_start_rx(struct uart_port *port)
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET); wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START); wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) if (sirfport->rx_dma_chan)
sirfsoc_uart_start_next_rx_dma(port); sirfsoc_uart_start_next_rx_dma(port);
else { else {
if (!sirfport->is_marco) if (!sirfport->is_marco)
...@@ -1014,11 +1013,11 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, ...@@ -1014,11 +1013,11 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
(sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) << (sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) <<
SIRFSOC_USP_ASYNC_DIV2_OFFSET); SIRFSOC_USP_ASYNC_DIV2_OFFSET);
} }
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) if (sirfport->tx_dma_chan)
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE); wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE);
else else
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE); wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) if (sirfport->rx_dma_chan)
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE); wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE);
else else
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE); wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
...@@ -1049,93 +1048,6 @@ static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state, ...@@ -1049,93 +1048,6 @@ static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state,
clk_disable_unprepare(sirfport->clk); clk_disable_unprepare(sirfport->clk);
} }
static unsigned int sirfsoc_uart_init_tx_dma(struct uart_port *port)
{
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
dma_cap_mask_t dma_mask;
struct dma_slave_config tx_slv_cfg = {
.dst_maxburst = 2,
};
dma_cap_zero(dma_mask);
dma_cap_set(DMA_SLAVE, dma_mask);
sirfport->tx_dma_chan = dma_request_channel(dma_mask,
(dma_filter_fn)sirfsoc_dma_filter_id,
(void *)sirfport->tx_dma_no);
if (!sirfport->tx_dma_chan) {
dev_err(port->dev, "Uart Request Dma Channel Fail %d\n",
sirfport->tx_dma_no);
return -EPROBE_DEFER;
}
dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
return 0;
}
static unsigned int sirfsoc_uart_init_rx_dma(struct uart_port *port)
{
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
dma_cap_mask_t dma_mask;
int ret;
int i, j;
struct dma_slave_config slv_cfg = {
.src_maxburst = 2,
};
dma_cap_zero(dma_mask);
dma_cap_set(DMA_SLAVE, dma_mask);
sirfport->rx_dma_chan = dma_request_channel(dma_mask,
(dma_filter_fn)sirfsoc_dma_filter_id,
(void *)sirfport->rx_dma_no);
if (!sirfport->rx_dma_chan) {
dev_err(port->dev, "Uart Request Dma Channel Fail %d\n",
sirfport->rx_dma_no);
ret = -EPROBE_DEFER;
goto request_err;
}
for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++) {
sirfport->rx_dma_items[i].xmit.buf =
dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
&sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL);
if (!sirfport->rx_dma_items[i].xmit.buf) {
dev_err(port->dev, "Uart alloc bufa failed\n");
ret = -ENOMEM;
goto alloc_coherent_err;
}
sirfport->rx_dma_items[i].xmit.head =
sirfport->rx_dma_items[i].xmit.tail = 0;
}
dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
return 0;
alloc_coherent_err:
for (j = 0; j < i; j++)
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
sirfport->rx_dma_items[j].xmit.buf,
sirfport->rx_dma_items[j].dma_addr);
dma_release_channel(sirfport->rx_dma_chan);
request_err:
return ret;
}
static void sirfsoc_uart_uninit_tx_dma(struct sirfsoc_uart_port *sirfport)
{
dmaengine_terminate_all(sirfport->tx_dma_chan);
dma_release_channel(sirfport->tx_dma_chan);
}
static void sirfsoc_uart_uninit_rx_dma(struct sirfsoc_uart_port *sirfport)
{
int i;
struct uart_port *port = &sirfport->port;
dmaengine_terminate_all(sirfport->rx_dma_chan);
dma_release_channel(sirfport->rx_dma_chan);
for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
sirfport->rx_dma_items[i].xmit.buf,
sirfport->rx_dma_items[i].dma_addr);
}
static int sirfsoc_uart_startup(struct uart_port *port) static int sirfsoc_uart_startup(struct uart_port *port)
{ {
struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_uart_port *sirfport = to_sirfport(port);
...@@ -1174,18 +1086,12 @@ static int sirfsoc_uart_startup(struct uart_port *port) ...@@ -1174,18 +1086,12 @@ static int sirfsoc_uart_startup(struct uart_port *port)
wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port)); wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port));
wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port)); wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port));
if (sirfport->rx_dma_chan)
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) {
ret = sirfsoc_uart_init_rx_dma(port);
if (ret)
goto init_rx_err;
wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk, wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) | SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) |
SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) | SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b)); SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
} if (sirfport->tx_dma_chan) {
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
sirfsoc_uart_init_tx_dma(port);
sirfport->tx_dma_state = TX_DMA_IDLE; sirfport->tx_dma_state = TX_DMA_IDLE;
wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk, wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) | SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) |
...@@ -1232,12 +1138,8 @@ static void sirfsoc_uart_shutdown(struct uart_port *port) ...@@ -1232,12 +1138,8 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
gpio_set_value(sirfport->rts_gpio, 1); gpio_set_value(sirfport->rts_gpio, 1);
free_irq(gpio_to_irq(sirfport->cts_gpio), sirfport); free_irq(gpio_to_irq(sirfport->cts_gpio), sirfport);
} }
if (IS_DMA_CHAN_VALID(sirfport->rx_dma_no)) if (sirfport->tx_dma_chan)
sirfsoc_uart_uninit_rx_dma(sirfport);
if (IS_DMA_CHAN_VALID(sirfport->tx_dma_no)) {
sirfsoc_uart_uninit_tx_dma(sirfport);
sirfport->tx_dma_state = TX_DMA_IDLE; sirfport->tx_dma_state = TX_DMA_IDLE;
}
} }
static const char *sirfsoc_uart_type(struct uart_port *port) static const char *sirfsoc_uart_type(struct uart_port *port)
...@@ -1313,8 +1215,8 @@ sirfsoc_uart_console_setup(struct console *co, char *options) ...@@ -1313,8 +1215,8 @@ sirfsoc_uart_console_setup(struct console *co, char *options)
port->cons = co; port->cons = co;
/* default console tx/rx transfer using io mode */ /* default console tx/rx transfer using io mode */
sirfport->rx_dma_no = UNVALID_DMA_CHAN; sirfport->rx_dma_chan = NULL;
sirfport->tx_dma_no = UNVALID_DMA_CHAN; sirfport->tx_dma_chan = NULL;
return uart_set_options(port, co, baud, parity, bits, flow); return uart_set_options(port, co, baud, parity, bits, flow);
} }
...@@ -1382,6 +1284,13 @@ static int sirfsoc_uart_probe(struct platform_device *pdev) ...@@ -1382,6 +1284,13 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
struct uart_port *port; struct uart_port *port;
struct resource *res; struct resource *res;
int ret; int ret;
int i, j;
struct dma_slave_config slv_cfg = {
.src_maxburst = 2,
};
struct dma_slave_config tx_slv_cfg = {
.dst_maxburst = 2,
};
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node); match = of_match_node(sirfsoc_uart_ids, pdev->dev.of_node);
...@@ -1402,27 +1311,10 @@ static int sirfsoc_uart_probe(struct platform_device *pdev) ...@@ -1402,27 +1311,10 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node, sirfport->hw_flow_ctrl = of_property_read_bool(pdev->dev.of_node,
"sirf,uart-has-rtscts"); "sirf,uart-has-rtscts");
if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart")) { if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-uart"))
sirfport->uart_reg->uart_type = SIRF_REAL_UART; sirfport->uart_reg->uart_type = SIRF_REAL_UART;
if (of_property_read_u32(pdev->dev.of_node,
"sirf,uart-dma-rx-channel",
&sirfport->rx_dma_no))
sirfport->rx_dma_no = UNVALID_DMA_CHAN;
if (of_property_read_u32(pdev->dev.of_node,
"sirf,uart-dma-tx-channel",
&sirfport->tx_dma_no))
sirfport->tx_dma_no = UNVALID_DMA_CHAN;
}
if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart")) { if (of_device_is_compatible(pdev->dev.of_node, "sirf,prima2-usp-uart")) {
sirfport->uart_reg->uart_type = SIRF_USP_UART; sirfport->uart_reg->uart_type = SIRF_USP_UART;
if (of_property_read_u32(pdev->dev.of_node,
"sirf,usp-dma-rx-channel",
&sirfport->rx_dma_no))
sirfport->rx_dma_no = UNVALID_DMA_CHAN;
if (of_property_read_u32(pdev->dev.of_node,
"sirf,usp-dma-tx-channel",
&sirfport->tx_dma_no))
sirfport->tx_dma_no = UNVALID_DMA_CHAN;
if (!sirfport->hw_flow_ctrl) if (!sirfport->hw_flow_ctrl)
goto usp_no_flow_control; goto usp_no_flow_control;
if (of_find_property(pdev->dev.of_node, "cts-gpios", NULL)) if (of_find_property(pdev->dev.of_node, "cts-gpios", NULL))
...@@ -1515,8 +1407,32 @@ static int sirfsoc_uart_probe(struct platform_device *pdev) ...@@ -1515,8 +1407,32 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
goto port_err; goto port_err;
} }
return 0; sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx");
for (i = 0; sirfport->rx_dma_chan && i < SIRFSOC_RX_LOOP_BUF_CNT; i++) {
sirfport->rx_dma_items[i].xmit.buf =
dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
&sirfport->rx_dma_items[i].dma_addr, GFP_KERNEL);
if (!sirfport->rx_dma_items[i].xmit.buf) {
dev_err(port->dev, "Uart alloc bufa failed\n");
ret = -ENOMEM;
goto alloc_coherent_err;
}
sirfport->rx_dma_items[i].xmit.head =
sirfport->rx_dma_items[i].xmit.tail = 0;
}
if (sirfport->rx_dma_chan)
dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg);
sirfport->tx_dma_chan = dma_request_slave_channel(port->dev, "tx");
if (sirfport->tx_dma_chan)
dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg);
return 0;
alloc_coherent_err:
for (j = 0; j < i; j++)
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
sirfport->rx_dma_items[j].xmit.buf,
sirfport->rx_dma_items[j].dma_addr);
dma_release_channel(sirfport->rx_dma_chan);
port_err: port_err:
clk_put(sirfport->clk); clk_put(sirfport->clk);
err: err:
...@@ -1529,6 +1445,19 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) ...@@ -1529,6 +1445,19 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
struct uart_port *port = &sirfport->port; struct uart_port *port = &sirfport->port;
clk_put(sirfport->clk); clk_put(sirfport->clk);
uart_remove_one_port(&sirfsoc_uart_drv, port); uart_remove_one_port(&sirfsoc_uart_drv, port);
if (sirfport->rx_dma_chan) {
int i;
dmaengine_terminate_all(sirfport->rx_dma_chan);
dma_release_channel(sirfport->rx_dma_chan);
for (i = 0; i < SIRFSOC_RX_LOOP_BUF_CNT; i++)
dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE,
sirfport->rx_dma_items[i].xmit.buf,
sirfport->rx_dma_items[i].dma_addr);
}
if (sirfport->tx_dma_chan) {
dmaengine_terminate_all(sirfport->tx_dma_chan);
dma_release_channel(sirfport->tx_dma_chan);
}
return 0; return 0;
} }
......
...@@ -392,9 +392,6 @@ struct sirfsoc_uart_register sirfsoc_uart = { ...@@ -392,9 +392,6 @@ struct sirfsoc_uart_register sirfsoc_uart = {
/* Indicate how many buffers used */ /* Indicate how many buffers used */
#define SIRFSOC_RX_LOOP_BUF_CNT 2 #define SIRFSOC_RX_LOOP_BUF_CNT 2
/* Indicate if DMA channel valid */
#define IS_DMA_CHAN_VALID(x) ((x) != -1)
#define UNVALID_DMA_CHAN -1
/* For Fast Baud Rate Calculation */ /* For Fast Baud Rate Calculation */
struct sirfsoc_baudrate_to_regv { struct sirfsoc_baudrate_to_regv {
unsigned int baud_rate; unsigned int baud_rate;
...@@ -423,8 +420,6 @@ struct sirfsoc_uart_port { ...@@ -423,8 +420,6 @@ struct sirfsoc_uart_port {
/* for SiRFmarco, there are SET/CLR for UART_INT_EN */ /* for SiRFmarco, there are SET/CLR for UART_INT_EN */
bool is_marco; bool is_marco;
struct sirfsoc_uart_register *uart_reg; struct sirfsoc_uart_register *uart_reg;
int rx_dma_no;
int tx_dma_no;
struct dma_chan *rx_dma_chan; struct dma_chan *rx_dma_chan;
struct dma_chan *tx_dma_chan; struct dma_chan *tx_dma_chan;
dma_addr_t tx_dma_addr; dma_addr_t tx_dma_addr;
......
...@@ -7866,6 +7866,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -7866,6 +7866,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
memset(&new_line, 0, sizeof(new_line));
switch (flags){ switch (flags){
case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
......
...@@ -1766,6 +1766,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -1766,6 +1766,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
memset(&new_line, 0, sizeof(new_line));
switch (flags){ switch (flags){
case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
......
...@@ -351,14 +351,11 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags); ...@@ -351,14 +351,11 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
* Takes any pending buffers and transfers their ownership to the * Takes any pending buffers and transfers their ownership to the
* ldisc side of the queue. It then schedules those characters for * ldisc side of the queue. It then schedules those characters for
* processing by the line discipline. * processing by the line discipline.
* Note that this function can only be used when the low_latency flag
* is unset. Otherwise the workqueue won't be flushed.
*/ */
void tty_schedule_flip(struct tty_port *port) void tty_schedule_flip(struct tty_port *port)
{ {
struct tty_bufhead *buf = &port->buf; struct tty_bufhead *buf = &port->buf;
WARN_ON(port->low_latency);
buf->tail->commit = buf->tail->used; buf->tail->commit = buf->tail->used;
schedule_work(&buf->work); schedule_work(&buf->work);
...@@ -482,17 +479,15 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -482,17 +479,15 @@ static void flush_to_ldisc(struct work_struct *work)
*/ */
void tty_flush_to_ldisc(struct tty_struct *tty) void tty_flush_to_ldisc(struct tty_struct *tty)
{ {
if (!tty->port->low_latency) flush_work(&tty->port->buf.work);
flush_work(&tty->port->buf.work);
} }
/** /**
* tty_flip_buffer_push - terminal * tty_flip_buffer_push - terminal
* @port: tty port to push * @port: tty port to push
* *
* Queue a push of the terminal flip buffers to the line discipline. This * Queue a push of the terminal flip buffers to the line discipline.
* function must not be called from IRQ context if port->low_latency is * Can be called from IRQ/atomic context.
* set.
* *
* In the event of the queue being busy for flipping the work will be * In the event of the queue being busy for flipping the work will be
* held off and retried later. * held off and retried later.
...@@ -500,14 +495,7 @@ void tty_flush_to_ldisc(struct tty_struct *tty) ...@@ -500,14 +495,7 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
void tty_flip_buffer_push(struct tty_port *port) void tty_flip_buffer_push(struct tty_port *port)
{ {
struct tty_bufhead *buf = &port->buf; tty_schedule_flip(port);
buf->tail->commit = buf->tail->used;
if (port->low_latency)
flush_to_ldisc(&buf->work);
else
schedule_work(&buf->work);
} }
EXPORT_SYMBOL(tty_flip_buffer_push); EXPORT_SYMBOL(tty_flip_buffer_push);
......
...@@ -1271,12 +1271,13 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) ...@@ -1271,12 +1271,13 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
* *
* Locking: None * Locking: None
*/ */
static void tty_line_name(struct tty_driver *driver, int index, char *p) static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
{ {
if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE) if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
strcpy(p, driver->name); return sprintf(p, "%s", driver->name);
else else
sprintf(p, "%s%d", driver->name, index + driver->name_base); return sprintf(p, "%s%d", driver->name,
index + driver->name_base);
} }
/** /**
...@@ -3545,9 +3546,19 @@ static ssize_t show_cons_active(struct device *dev, ...@@ -3545,9 +3546,19 @@ static ssize_t show_cons_active(struct device *dev,
if (i >= ARRAY_SIZE(cs)) if (i >= ARRAY_SIZE(cs))
break; break;
} }
while (i--) while (i--) {
count += sprintf(buf + count, "%s%d%c", int index = cs[i]->index;
cs[i]->name, cs[i]->index, i ? ' ':'\n'); struct tty_driver *drv = cs[i]->device(cs[i], &index);
/* don't resolve tty0 as some programs depend on it */
if (drv && (cs[i]->index > 0 || drv->major != TTY_MAJOR))
count += tty_line_name(drv, index, buf + count);
else
count += sprintf(buf + count, "%s%d",
cs[i]->name, cs[i]->index);
count += sprintf(buf + count, "%c", i ? ' ':'\n');
}
console_unlock(); console_unlock();
return count; return count;
......
...@@ -1590,9 +1590,9 @@ static void restore_cur(struct vc_data *vc) ...@@ -1590,9 +1590,9 @@ static void restore_cur(struct vc_data *vc)
vc->vc_need_wrap = 0; vc->vc_need_wrap = 0;
} }
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd, EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
ESpalette }; ESpalette, ESosc };
/* console_lock is held (except via vc_init()) */ /* console_lock is held (except via vc_init()) */
static void reset_terminal(struct vc_data *vc, int do_clear) static void reset_terminal(struct vc_data *vc, int do_clear)
...@@ -1652,11 +1652,15 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) ...@@ -1652,11 +1652,15 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
* Control characters can be used in the _middle_ * Control characters can be used in the _middle_
* of an escape sequence. * of an escape sequence.
*/ */
if (vc->vc_state == ESosc && c>=8 && c<=13) /* ... except for OSC */
return;
switch (c) { switch (c) {
case 0: case 0:
return; return;
case 7: case 7:
if (vc->vc_bell_duration) if (vc->vc_state == ESosc)
vc->vc_state = ESnormal;
else if (vc->vc_bell_duration)
kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration); kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
return; return;
case 8: case 8:
...@@ -1767,7 +1771,9 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) ...@@ -1767,7 +1771,9 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
} else if (c=='R') { /* reset palette */ } else if (c=='R') { /* reset palette */
reset_palette(vc); reset_palette(vc);
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
} else } else if (c>='0' && c<='9')
vc->vc_state = ESosc;
else
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
return; return;
case ESpalette: case ESpalette:
...@@ -1807,9 +1813,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) ...@@ -1807,9 +1813,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
vc->vc_par[vc->vc_npar] *= 10; vc->vc_par[vc->vc_npar] *= 10;
vc->vc_par[vc->vc_npar] += c - '0'; vc->vc_par[vc->vc_npar] += c - '0';
return; return;
} else }
vc->vc_state = ESgotpars;
case ESgotpars:
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
switch(c) { switch(c) {
case 'h': case 'h':
...@@ -2023,6 +2027,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) ...@@ -2023,6 +2027,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
vc->vc_translate = set_translate(vc->vc_G1_charset, vc); vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
return; return;
case ESosc:
return;
default: default:
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
} }
......
...@@ -549,8 +549,8 @@ static void gs_rx_push(unsigned long _port) ...@@ -549,8 +549,8 @@ static void gs_rx_push(unsigned long _port)
port->read_started--; port->read_started--;
} }
/* Push from tty to ldisc; without low_latency set this is handled by /* Push from tty to ldisc; this is handled by a workqueue,
* a workqueue, so we won't get callbacks and can hold port_lock * so we won't get callbacks and can hold port_lock
*/ */
if (do_push) if (do_push)
tty_flip_buffer_push(&port->port); tty_flip_buffer_push(&port->port);
......
/*
* Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
*
* Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
*
* Based on max3100.c, by Christian Pellegrin <chripell@evolware.org>
* Based on max3110.c, by Feng Tang <feng.tang@intel.com>
* Based on max3107.c, by Aavamobile
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _MAX310X_H_
#define _MAX310X_H_
/*
* Example board initialization data:
*
* static struct max310x_pdata max3107_pdata = {
* .driver_flags = MAX310X_EXT_CLK,
* .uart_flags[0] = MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL,
* .frequency = 3686400,
* .gpio_base = -1,
* };
*
* static struct spi_board_info spi_device_max3107[] = {
* {
* .modalias = "max3107",
* .irq = IRQ_EINT3,
* .bus_num = 1,
* .chip_select = 1,
* .platform_data = &max3107_pdata,
* },
* };
*/
#define MAX310X_MAX_UARTS 4
/* MAX310X platform data structure */
struct max310x_pdata {
/* Flags global to driver */
const u8 driver_flags;
#define MAX310X_EXT_CLK (0x00000001) /* External clock enable */
/* Flags global to UART port */
const u8 uart_flags[MAX310X_MAX_UARTS];
#define MAX310X_LOOPBACK (0x00000001) /* Loopback mode enable */
#define MAX310X_ECHO_SUPRESS (0x00000002) /* Enable echo supress */
#define MAX310X_AUTO_DIR_CTRL (0x00000004) /* Enable Auto direction
* control (RS-485)
*/
/* Frequency (extrenal clock or crystal) */
const int frequency;
/* GPIO base number (can be negative) */
const int gpio_base;
/* Called during startup */
void (*init)(void);
/* Called before finish */
void (*exit)(void);
};
#endif
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
#define IMXUART_IRDA (1<<1) #define IMXUART_IRDA (1<<1)
struct imxuart_platform_data { struct imxuart_platform_data {
int (*init)(struct platform_device *pdev);
void (*exit)(struct platform_device *pdev);
unsigned int flags; unsigned int flags;
void (*irda_enable)(int enable); void (*irda_enable)(int enable);
unsigned int irda_inv_rx:1; unsigned int irda_inv_rx:1;
......
...@@ -116,4 +116,6 @@ ...@@ -116,4 +116,6 @@
UART_FIFO_PARERR_MASK | \ UART_FIFO_PARERR_MASK | \
UART_FIFO_BRKDET_MASK) UART_FIFO_BRKDET_MASK)
#define UART_REG_SIZE 24
#endif /* _LINUX_SERIAL_BCM63XX_H */ #endif /* _LINUX_SERIAL_BCM63XX_H */
...@@ -10,45 +10,59 @@ ...@@ -10,45 +10,59 @@
#define SCIx_NOT_SUPPORTED (-1) #define SCIx_NOT_SUPPORTED (-1)
#define SCSCR_TIE (1 << 7) /* SCSMR (Serial Mode Register) */
#define SCSCR_RIE (1 << 6) #define SCSMR_CHR (1 << 6) /* 7-bit Character Length */
#define SCSCR_TE (1 << 5) #define SCSMR_PE (1 << 5) /* Parity Enable */
#define SCSCR_RE (1 << 4) #define SCSMR_ODD (1 << 4) /* Odd Parity */
#define SCSCR_REIE (1 << 3) /* not supported by all parts */ #define SCSMR_STOP (1 << 3) /* Stop Bit Length */
#define SCSCR_TOIE (1 << 2) /* not supported by all parts */ #define SCSMR_CKS 0x0003 /* Clock Select */
#define SCSCR_CKE1 (1 << 1)
#define SCSCR_CKE0 (1 << 0) /* Serial Control Register (@ = not supported by all parts) */
#define SCSCR_TIE (1 << 7) /* Transmit Interrupt Enable */
/* SCxSR SCI */ #define SCSCR_RIE (1 << 6) /* Receive Interrupt Enable */
#define SCI_TDRE 0x80 #define SCSCR_TE (1 << 5) /* Transmit Enable */
#define SCI_RDRF 0x40 #define SCSCR_RE (1 << 4) /* Receive Enable */
#define SCI_ORER 0x20 #define SCSCR_REIE (1 << 3) /* Receive Error Interrupt Enable @ */
#define SCI_FER 0x10 #define SCSCR_TOIE (1 << 2) /* Timeout Interrupt Enable @ */
#define SCI_PER 0x08 #define SCSCR_CKE1 (1 << 1) /* Clock Enable 1 */
#define SCI_TEND 0x04 #define SCSCR_CKE0 (1 << 0) /* Clock Enable 0 */
/* SCIFA/SCIFB only */
#define SCSCR_TDRQE (1 << 15) /* Tx Data Transfer Request Enable */
#define SCSCR_RDRQE (1 << 14) /* Rx Data Transfer Request Enable */
/* SCxSR (Serial Status Register) on SCI */
#define SCI_TDRE 0x80 /* Transmit Data Register Empty */
#define SCI_RDRF 0x40 /* Receive Data Register Full */
#define SCI_ORER 0x20 /* Overrun Error */
#define SCI_FER 0x10 /* Framing Error */
#define SCI_PER 0x08 /* Parity Error */
#define SCI_TEND 0x04 /* Transmit End */
#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER) #define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
/* SCxSR SCIF, HSCIF */ /* SCxSR (Serial Status Register) on SCIF, HSCIF */
#define SCIF_ER 0x0080 #define SCIF_ER 0x0080 /* Receive Error */
#define SCIF_TEND 0x0040 #define SCIF_TEND 0x0040 /* Transmission End */
#define SCIF_TDFE 0x0020 #define SCIF_TDFE 0x0020 /* Transmit FIFO Data Empty */
#define SCIF_BRK 0x0010 #define SCIF_BRK 0x0010 /* Break Detect */
#define SCIF_FER 0x0008 #define SCIF_FER 0x0008 /* Framing Error */
#define SCIF_PER 0x0004 #define SCIF_PER 0x0004 /* Parity Error */
#define SCIF_RDF 0x0002 #define SCIF_RDF 0x0002 /* Receive FIFO Data Full */
#define SCIF_DR 0x0001 #define SCIF_DR 0x0001 /* Receive Data Ready */
#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) #define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
/* SCSPTR, optional */ /* SCFCR (FIFO Control Register) */
#define SCSPTR_RTSIO (1 << 7) #define SCFCR_LOOP (1 << 0) /* Loopback Test */
#define SCSPTR_CTSIO (1 << 5)
#define SCSPTR_SPB2IO (1 << 1) /* SCSPTR (Serial Port Register), optional */
#define SCSPTR_SPB2DT (1 << 0) #define SCSPTR_RTSIO (1 << 7) /* Serial Port RTS Pin Input/Output */
#define SCSPTR_CTSIO (1 << 5) /* Serial Port CTS Pin Input/Output */
#define SCSPTR_SPB2IO (1 << 1) /* Serial Port Break Input/Output */
#define SCSPTR_SPB2DT (1 << 0) /* Serial Port Break Data */
/* HSSRR HSCIF */ /* HSSRR HSCIF */
#define HSCIF_SRE 0x8000 #define HSCIF_SRE 0x8000 /* Sampling Rate Register Enable */
enum { enum {
SCIx_PROBE_REGTYPE, SCIx_PROBE_REGTYPE,
...@@ -73,10 +87,19 @@ enum { ...@@ -73,10 +87,19 @@ enum {
* Not all registers will exist on all parts. * Not all registers will exist on all parts.
*/ */
enum { enum {
SCSMR, SCBRR, SCSCR, SCxSR, SCSMR, /* Serial Mode Register */
SCFCR, SCFDR, SCxTDR, SCxRDR, SCBRR, /* Bit Rate Register */
SCLSR, SCTFDR, SCRFDR, SCSPTR, SCSCR, /* Serial Control Register */
HSSRR, SCxSR, /* Serial Status Register */
SCFCR, /* FIFO Control Register */
SCFDR, /* FIFO Data Count Register */
SCxTDR, /* Transmit (FIFO) Data Register */
SCxRDR, /* Receive (FIFO) Data Register */
SCLSR, /* Line Status Register */
SCTFDR, /* Transmit FIFO Data Count Register */
SCRFDR, /* Receive FIFO Data Count Register */
SCSPTR, /* Serial Port Register */
HSSRR, /* Sampling Rate Register */
SCIx_NR_REGS, SCIx_NR_REGS,
}; };
......
...@@ -208,7 +208,7 @@ struct tty_port { ...@@ -208,7 +208,7 @@ struct tty_port {
wait_queue_head_t delta_msr_wait; /* Modem status change */ wait_queue_head_t delta_msr_wait; /* Modem status change */
unsigned long flags; /* TTY flags ASY_*/ unsigned long flags; /* TTY flags ASY_*/
unsigned char console:1, /* port is a console */ unsigned char console:1, /* port is a console */
low_latency:1; /* direct buffer flush */ low_latency:1; /* optional: tune for latency */
struct mutex mutex; /* Locking */ struct mutex mutex; /* Locking */
struct mutex buf_mutex; /* Buffer alloc lock */ struct mutex buf_mutex; /* Buffer alloc lock */
unsigned char *xmit_buf; /* Optional buffer */ unsigned char *xmit_buf; /* Optional buffer */
......
...@@ -126,7 +126,6 @@ ...@@ -126,7 +126,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/wait.h>
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册