diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-06 22:17:06 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-06 22:17:06 -0500 |
commit | 56edff7529d0baa6d7b38b58f46631c7b9f4136e (patch) | |
tree | 37729cd0a56ad31601fb573ccf3f5a2d7bee52e8 /drivers/tty/serial/8250/8250_dw.c | |
parent | 0324e74534241f3f00910ec04ef67de1fe1542f4 (diff) | |
parent | 80d8611dd07603736d14e4a942546bdc84dd5477 (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.c | 76 |
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 | ||
58 | struct dw8250_data { | 58 | struct 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 | ||
66 | static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) | 66 | static 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 | ||
79 | static 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 | |||
79 | static void dw8250_serial_out(struct uart_port *p, int offset, int value) | 86 | static 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 | ||
92 | static unsigned int dw8250_serial_in(struct uart_port *p, int offset) | 108 | static 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 | ||
119 | static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) | 144 | static 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 | ||
180 | static 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 | |||
156 | static void dw8250_setup_port(struct uart_8250_port *up) | 188 | static 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 |
244 | static int dw8250_probe_acpi(struct uart_8250_port *up) | 276 | static 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 |
273 | static inline int dw8250_probe_acpi(struct uart_8250_port *up) | 304 | static 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 { |