aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/8250/8250_dw.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-06 22:17:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-06 22:17:06 -0500
commit56edff7529d0baa6d7b38b58f46631c7b9f4136e (patch)
tree37729cd0a56ad31601fb573ccf3f5a2d7bee52e8 /drivers/tty/serial/8250/8250_dw.c
parent0324e74534241f3f00910ec04ef67de1fe1542f4 (diff)
parent80d8611dd07603736d14e4a942546bdc84dd5477 (diff)
Merge tag 'tty-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here's the big tty/serial driver update for 3.13-rc1. There's some more minor n_tty work here, but nothing like previous kernel releases. Also some new driver ids, driver updates for new hardware, and other small things. All of this has been in linux-next for a while with no issues" * tag 'tty-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (84 commits) serial: omap: fix missing comma serial: sh-sci: Enable the driver on all ARM platforms serial: mfd: Staticize local symbols serial: omap: fix a few checkpatch warnings serial: omap: improve RS-485 performance mrst_max3110: fix unbalanced IRQ issue during resume serial: omap: Add support for optional wake-up serial: sirf: remove duplicate defines tty: xuartps: Fix build error when COMMON_CLK is not set tty: xuartps: Fix build error due to missing forward declaration tty: xuartps: Fix "may be used uninitialized" build warning serial: 8250_pci: add Pericom PCIe Serial board Support (12d8:7952/4/8) - Chip PI7C9X7952/4/8 tty: xuartps: Update copyright information tty: xuartps: Implement suspend/resume callbacks tty: xuartps: Dynamically adjust to input frequency changes tty: xuartps: Updating set_baud_rate() tty: xuartps: Force enable the UART in xuartps_console_write tty: xuartps: support 64 byte FIFO size tty: xuartps: Add polled mode support for xuartps tty: xuartps: Implement BREAK detection, add SYSRQ support ...
Diffstat (limited to 'drivers/tty/serial/8250/8250_dw.c')
-rw-r--r--drivers/tty/serial/8250/8250_dw.c76
1 files changed, 57 insertions, 19 deletions
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index daf710f5c3fc..4658e3e0ec42 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -56,11 +56,11 @@
56 56
57 57
58struct dw8250_data { 58struct dw8250_data {
59 int last_lcr; 59 u8 usr_reg;
60 int last_mcr; 60 int last_mcr;
61 int line; 61 int line;
62 struct clk *clk; 62 struct clk *clk;
63 u8 usr_reg; 63 struct uart_8250_dma dma;
64}; 64};
65 65
66static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) 66static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
@@ -76,17 +76,33 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
76 return value; 76 return value;
77} 77}
78 78
79static void dw8250_force_idle(struct uart_port *p)
80{
81 serial8250_clear_and_reinit_fifos(container_of
82 (p, struct uart_8250_port, port));
83 (void)p->serial_in(p, UART_RX);
84}
85
79static void dw8250_serial_out(struct uart_port *p, int offset, int value) 86static void dw8250_serial_out(struct uart_port *p, int offset, int value)
80{ 87{
81 struct dw8250_data *d = p->private_data; 88 struct dw8250_data *d = p->private_data;
82 89
83 if (offset == UART_LCR)
84 d->last_lcr = value;
85
86 if (offset == UART_MCR) 90 if (offset == UART_MCR)
87 d->last_mcr = value; 91 d->last_mcr = value;
88 92
89 writeb(value, p->membase + (offset << p->regshift)); 93 writeb(value, p->membase + (offset << p->regshift));
94
95 /* Make sure LCR write wasn't ignored */
96 if (offset == UART_LCR) {
97 int tries = 1000;
98 while (tries--) {
99 if (value == p->serial_in(p, UART_LCR))
100 return;
101 dw8250_force_idle(p);
102 writeb(value, p->membase + (UART_LCR << p->regshift));
103 }
104 dev_err(p->dev, "Couldn't set LCR to %d\n", value);
105 }
90} 106}
91 107
92static unsigned int dw8250_serial_in(struct uart_port *p, int offset) 108static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
@@ -107,13 +123,22 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
107{ 123{
108 struct dw8250_data *d = p->private_data; 124 struct dw8250_data *d = p->private_data;
109 125
110 if (offset == UART_LCR)
111 d->last_lcr = value;
112
113 if (offset == UART_MCR) 126 if (offset == UART_MCR)
114 d->last_mcr = value; 127 d->last_mcr = value;
115 128
116 writel(value, p->membase + (offset << p->regshift)); 129 writel(value, p->membase + (offset << p->regshift));
130
131 /* Make sure LCR write wasn't ignored */
132 if (offset == UART_LCR) {
133 int tries = 1000;
134 while (tries--) {
135 if (value == p->serial_in(p, UART_LCR))
136 return;
137 dw8250_force_idle(p);
138 writel(value, p->membase + (UART_LCR << p->regshift));
139 }
140 dev_err(p->dev, "Couldn't set LCR to %d\n", value);
141 }
117} 142}
118 143
119static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) 144static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
@@ -131,9 +156,8 @@ static int dw8250_handle_irq(struct uart_port *p)
131 if (serial8250_handle_irq(p, iir)) { 156 if (serial8250_handle_irq(p, iir)) {
132 return 1; 157 return 1;
133 } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { 158 } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
134 /* Clear the USR and write the LCR again. */ 159 /* Clear the USR */
135 (void)p->serial_in(p, d->usr_reg); 160 (void)p->serial_in(p, d->usr_reg);
136 p->serial_out(p, UART_LCR, d->last_lcr);
137 161
138 return 1; 162 return 1;
139 } 163 }
@@ -153,6 +177,14 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
153 pm_runtime_put_sync_suspend(port->dev); 177 pm_runtime_put_sync_suspend(port->dev);
154} 178}
155 179
180static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
181{
182 struct dw8250_data *data = param;
183
184 return chan->chan_id == data->dma.tx_chan_id ||
185 chan->chan_id == data->dma.rx_chan_id;
186}
187
156static void dw8250_setup_port(struct uart_8250_port *up) 188static void dw8250_setup_port(struct uart_8250_port *up)
157{ 189{
158 struct uart_port *p = &up->port; 190 struct uart_port *p = &up->port;
@@ -241,7 +273,8 @@ static int dw8250_probe_of(struct uart_port *p,
241} 273}
242 274
243#ifdef CONFIG_ACPI 275#ifdef CONFIG_ACPI
244static int dw8250_probe_acpi(struct uart_8250_port *up) 276static int dw8250_probe_acpi(struct uart_8250_port *up,
277 struct dw8250_data *data)
245{ 278{
246 const struct acpi_device_id *id; 279 const struct acpi_device_id *id;
247 struct uart_port *p = &up->port; 280 struct uart_port *p = &up->port;
@@ -260,9 +293,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up)
260 if (!p->uartclk) 293 if (!p->uartclk)
261 p->uartclk = (unsigned int)id->driver_data; 294 p->uartclk = (unsigned int)id->driver_data;
262 295
263 up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL); 296 up->dma = &data->dma;
264 if (!up->dma)
265 return -ENOMEM;
266 297
267 up->dma->rxconf.src_maxburst = p->fifosize / 4; 298 up->dma->rxconf.src_maxburst = p->fifosize / 4;
268 up->dma->txconf.dst_maxburst = p->fifosize / 4; 299 up->dma->txconf.dst_maxburst = p->fifosize / 4;
@@ -270,7 +301,8 @@ static int dw8250_probe_acpi(struct uart_8250_port *up)
270 return 0; 301 return 0;
271} 302}
272#else 303#else
273static inline int dw8250_probe_acpi(struct uart_8250_port *up) 304static inline int dw8250_probe_acpi(struct uart_8250_port *up,
305 struct dw8250_data *data)
274{ 306{
275 return -ENODEV; 307 return -ENODEV;
276} 308}
@@ -314,6 +346,12 @@ static int dw8250_probe(struct platform_device *pdev)
314 uart.port.uartclk = clk_get_rate(data->clk); 346 uart.port.uartclk = clk_get_rate(data->clk);
315 } 347 }
316 348
349 data->dma.rx_chan_id = -1;
350 data->dma.tx_chan_id = -1;
351 data->dma.rx_param = data;
352 data->dma.tx_param = data;
353 data->dma.fn = dw8250_dma_filter;
354
317 uart.port.iotype = UPIO_MEM; 355 uart.port.iotype = UPIO_MEM;
318 uart.port.serial_in = dw8250_serial_in; 356 uart.port.serial_in = dw8250_serial_in;
319 uart.port.serial_out = dw8250_serial_out; 357 uart.port.serial_out = dw8250_serial_out;
@@ -324,7 +362,7 @@ static int dw8250_probe(struct platform_device *pdev)
324 if (err) 362 if (err)
325 return err; 363 return err;
326 } else if (ACPI_HANDLE(&pdev->dev)) { 364 } else if (ACPI_HANDLE(&pdev->dev)) {
327 err = dw8250_probe_acpi(&uart); 365 err = dw8250_probe_acpi(&uart, data);
328 if (err) 366 if (err)
329 return err; 367 return err;
330 } else { 368 } else {