blob: dd3971fe899f2aba71c5abb3c51754b7e64eda22 [file] [log] [blame]
Govindraj.Rb6126332010-09-27 20:20:49 +05301/*
2 * Driver for OMAP-UART controller.
3 * Based on drivers/serial/8250.c
4 *
5 * Copyright (C) 2010 Texas Instruments.
6 *
7 * Authors:
8 * Govindraj R <govindraj.raja@ti.com>
9 * Thara Gopinath <thara@ti.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -030016 * Note: This driver is made separate from 8250 driver as we cannot
Govindraj.Rb6126332010-09-27 20:20:49 +053017 * over load 8250 driver with omap platform specific configuration for
18 * features like DMA, it makes easier to implement features like DMA and
19 * hardware flow control and software flow control configuration with
20 * this driver as required for the omap-platform.
21 */
22
Thomas Weber364a6ec2011-02-01 08:30:41 +010023#if defined(CONFIG_SERIAL_OMAP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
24#define SUPPORT_SYSRQ
25#endif
26
Govindraj.Rb6126332010-09-27 20:20:49 +053027#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/console.h>
30#include <linux/serial_reg.h>
31#include <linux/delay.h>
32#include <linux/slab.h>
33#include <linux/tty.h>
34#include <linux/tty_flip.h>
35#include <linux/io.h>
Govindraj.Rb6126332010-09-27 20:20:49 +053036#include <linux/clk.h>
37#include <linux/serial_core.h>
38#include <linux/irq.h>
Govindraj.Rfcdca752011-02-28 18:12:23 +053039#include <linux/pm_runtime.h>
Rajendra Nayakd92b0df2011-12-14 17:25:45 +053040#include <linux/of.h>
NeilBrown9574f362012-07-30 10:30:26 +100041#include <linux/gpio.h>
Govindraj.Rb6126332010-09-27 20:20:49 +053042
Govindraj.Rb6126332010-09-27 20:20:49 +053043#include <plat/dmtimer.h>
44#include <plat/omap-serial.h>
45
Govindraj.R7c77c8d2012-04-03 19:12:34 +053046#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))
47
48#define OMAP_UART_REV_42 0x0402
49#define OMAP_UART_REV_46 0x0406
50#define OMAP_UART_REV_52 0x0502
51#define OMAP_UART_REV_63 0x0603
52
Rajendra Nayak8fe789d2011-12-14 17:25:44 +053053#define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
54
Paul Walmsley0ba5f662012-01-25 19:50:36 -070055/* SCR register bitmasks */
56#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
57
58/* FCR register bitmasks */
59#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6
60#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
61
Govindraj.R7c77c8d2012-04-03 19:12:34 +053062/* MVR register bitmasks */
63#define OMAP_UART_MVR_SCHEME_SHIFT 30
64
65#define OMAP_UART_LEGACY_MVR_MAJ_MASK 0xf0
66#define OMAP_UART_LEGACY_MVR_MAJ_SHIFT 4
67#define OMAP_UART_LEGACY_MVR_MIN_MASK 0x0f
68
69#define OMAP_UART_MVR_MAJ_MASK 0x700
70#define OMAP_UART_MVR_MAJ_SHIFT 8
71#define OMAP_UART_MVR_MIN_MASK 0x3f
72
Govindraj.Rb6126332010-09-27 20:20:49 +053073static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
74
75/* Forward declaration of functions */
Govindraj.R94734742011-11-07 19:00:33 +053076static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
Govindraj.Rb6126332010-09-27 20:20:49 +053077
Govindraj.R2fd14962011-11-09 17:41:21 +053078static struct workqueue_struct *serial_omap_uart_wq;
Govindraj.Rb6126332010-09-27 20:20:49 +053079
80static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
81{
82 offset <<= up->port.regshift;
83 return readw(up->port.membase + offset);
84}
85
86static inline void serial_out(struct uart_omap_port *up, int offset, int value)
87{
88 offset <<= up->port.regshift;
89 writew(value, up->port.membase + offset);
90}
91
92static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
93{
94 serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
95 serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
96 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
97 serial_out(up, UART_FCR, 0);
98}
99
Felipe Balbie5b57c02012-08-23 13:32:42 +0300100static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
101{
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300102 struct omap_uart_port_info *pdata = up->dev->platform_data;
Felipe Balbie5b57c02012-08-23 13:32:42 +0300103
104 if (!pdata->get_context_loss_count)
105 return 0;
106
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300107 return pdata->get_context_loss_count(up->dev);
Felipe Balbie5b57c02012-08-23 13:32:42 +0300108}
109
110static void serial_omap_set_forceidle(struct uart_omap_port *up)
111{
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300112 struct omap_uart_port_info *pdata = up->dev->platform_data;
Felipe Balbie5b57c02012-08-23 13:32:42 +0300113
114 if (pdata->set_forceidle)
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300115 pdata->set_forceidle(up->dev);
Felipe Balbie5b57c02012-08-23 13:32:42 +0300116}
117
118static void serial_omap_set_noidle(struct uart_omap_port *up)
119{
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300120 struct omap_uart_port_info *pdata = up->dev->platform_data;
Felipe Balbie5b57c02012-08-23 13:32:42 +0300121
122 if (pdata->set_noidle)
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300123 pdata->set_noidle(up->dev);
Felipe Balbie5b57c02012-08-23 13:32:42 +0300124}
125
126static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
127{
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300128 struct omap_uart_port_info *pdata = up->dev->platform_data;
Felipe Balbie5b57c02012-08-23 13:32:42 +0300129
130 if (pdata->enable_wakeup)
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300131 pdata->enable_wakeup(up->dev, enable);
Felipe Balbie5b57c02012-08-23 13:32:42 +0300132}
133
Govindraj.Rb6126332010-09-27 20:20:49 +0530134/*
135 * serial_omap_get_divisor - calculate divisor value
136 * @port: uart port info
137 * @baud: baudrate for which divisor needs to be calculated.
138 *
139 * We have written our own function to get the divisor so as to support
140 * 13x mode. 3Mbps Baudrate as an different divisor.
141 * Reference OMAP TRM Chapter 17:
142 * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
143 * referring to oversampling - divisor value
144 * baudrate 460,800 to 3,686,400 all have divisor 13
145 * except 3,000,000 which has divisor value 16
146 */
147static unsigned int
148serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
149{
150 unsigned int divisor;
151
152 if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
153 divisor = 13;
154 else
155 divisor = 16;
156 return port->uartclk/(baud * divisor);
157}
158
Govindraj.Rb6126332010-09-27 20:20:49 +0530159static void serial_omap_enable_ms(struct uart_port *port)
160{
Felipe Balbic990f352012-08-23 13:32:41 +0300161 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530162
Rajendra Nayakba774332011-12-14 17:25:43 +0530163 dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530164
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300165 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530166 up->ier |= UART_IER_MSI;
167 serial_out(up, UART_IER, up->ier);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300168 pm_runtime_put(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530169}
170
171static void serial_omap_stop_tx(struct uart_port *port)
172{
Felipe Balbic990f352012-08-23 13:32:41 +0300173 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530174
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300175 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530176 if (up->ier & UART_IER_THRI) {
177 up->ier &= ~UART_IER_THRI;
178 serial_out(up, UART_IER, up->ier);
179 }
Govindraj.Rfcdca752011-02-28 18:12:23 +0530180
Felipe Balbi49457432012-09-06 15:45:21 +0300181 serial_omap_set_forceidle(up);
Paul Walmsleybe4b0282012-01-25 19:50:52 -0700182
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300183 pm_runtime_mark_last_busy(up->dev);
184 pm_runtime_put_autosuspend(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530185}
186
187static void serial_omap_stop_rx(struct uart_port *port)
188{
Felipe Balbic990f352012-08-23 13:32:41 +0300189 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530190
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300191 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530192 up->ier &= ~UART_IER_RLSI;
193 up->port.read_status_mask &= ~UART_LSR_DR;
194 serial_out(up, UART_IER, up->ier);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300195 pm_runtime_mark_last_busy(up->dev);
196 pm_runtime_put_autosuspend(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530197}
198
Govindraj.Rda274682011-12-14 21:24:11 +0530199static inline void receive_chars(struct uart_omap_port *up,
200 unsigned int *status)
Govindraj.Rb6126332010-09-27 20:20:49 +0530201{
202 struct tty_struct *tty = up->port.state->port.tty;
Govindraj.Rda274682011-12-14 21:24:11 +0530203 unsigned int flag, lsr = *status;
204 unsigned char ch = 0;
Govindraj.Rb6126332010-09-27 20:20:49 +0530205 int max_count = 256;
206
207 do {
208 if (likely(lsr & UART_LSR_DR))
209 ch = serial_in(up, UART_RX);
210 flag = TTY_NORMAL;
211 up->port.icount.rx++;
212
213 if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
214 /*
215 * For statistics only
216 */
217 if (lsr & UART_LSR_BI) {
218 lsr &= ~(UART_LSR_FE | UART_LSR_PE);
219 up->port.icount.brk++;
220 /*
221 * We do the SysRQ and SAK checking
222 * here because otherwise the break
223 * may get masked by ignore_status_mask
224 * or read_status_mask.
225 */
226 if (uart_handle_break(&up->port))
227 goto ignore_char;
228 } else if (lsr & UART_LSR_PE) {
229 up->port.icount.parity++;
230 } else if (lsr & UART_LSR_FE) {
231 up->port.icount.frame++;
232 }
233
234 if (lsr & UART_LSR_OE)
235 up->port.icount.overrun++;
236
237 /*
238 * Mask off conditions which should be ignored.
239 */
240 lsr &= up->port.read_status_mask;
241
242#ifdef CONFIG_SERIAL_OMAP_CONSOLE
243 if (up->port.line == up->port.cons->index) {
244 /* Recover the break flag from console xmit */
245 lsr |= up->lsr_break_flag;
Govindraj.Rb6126332010-09-27 20:20:49 +0530246 }
247#endif
248 if (lsr & UART_LSR_BI)
249 flag = TTY_BREAK;
250 else if (lsr & UART_LSR_PE)
251 flag = TTY_PARITY;
252 else if (lsr & UART_LSR_FE)
253 flag = TTY_FRAME;
254 }
255
256 if (uart_handle_sysrq_char(&up->port, ch))
257 goto ignore_char;
258 uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
259ignore_char:
260 lsr = serial_in(up, UART_LSR);
261 } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
262 spin_unlock(&up->port.lock);
263 tty_flip_buffer_push(tty);
264 spin_lock(&up->port.lock);
265}
266
267static void transmit_chars(struct uart_omap_port *up)
268{
269 struct circ_buf *xmit = &up->port.state->xmit;
270 int count;
271
272 if (up->port.x_char) {
273 serial_out(up, UART_TX, up->port.x_char);
274 up->port.icount.tx++;
275 up->port.x_char = 0;
276 return;
277 }
278 if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
279 serial_omap_stop_tx(&up->port);
280 return;
281 }
Greg Kroah-Hartmanaf681ca2012-01-26 11:14:42 -0800282 count = up->port.fifosize / 4;
Govindraj.Rb6126332010-09-27 20:20:49 +0530283 do {
284 serial_out(up, UART_TX, xmit->buf[xmit->tail]);
285 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
286 up->port.icount.tx++;
287 if (uart_circ_empty(xmit))
288 break;
289 } while (--count > 0);
290
291 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
292 uart_write_wakeup(&up->port);
293
294 if (uart_circ_empty(xmit))
295 serial_omap_stop_tx(&up->port);
296}
297
298static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
299{
300 if (!(up->ier & UART_IER_THRI)) {
301 up->ier |= UART_IER_THRI;
302 serial_out(up, UART_IER, up->ier);
303 }
304}
305
306static void serial_omap_start_tx(struct uart_port *port)
307{
Felipe Balbic990f352012-08-23 13:32:41 +0300308 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530309
Felipe Balbi49457432012-09-06 15:45:21 +0300310 pm_runtime_get_sync(up->dev);
311 serial_omap_enable_ier_thri(up);
312 serial_omap_set_noidle(up);
313 pm_runtime_mark_last_busy(up->dev);
314 pm_runtime_put_autosuspend(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530315}
316
317static unsigned int check_modem_status(struct uart_omap_port *up)
318{
319 unsigned int status;
320
321 status = serial_in(up, UART_MSR);
322 status |= up->msr_saved_flags;
323 up->msr_saved_flags = 0;
324 if ((status & UART_MSR_ANY_DELTA) == 0)
325 return status;
326
327 if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
328 up->port.state != NULL) {
329 if (status & UART_MSR_TERI)
330 up->port.icount.rng++;
331 if (status & UART_MSR_DDSR)
332 up->port.icount.dsr++;
333 if (status & UART_MSR_DDCD)
334 uart_handle_dcd_change
335 (&up->port, status & UART_MSR_DCD);
336 if (status & UART_MSR_DCTS)
337 uart_handle_cts_change
338 (&up->port, status & UART_MSR_CTS);
339 wake_up_interruptible(&up->port.state->port.delta_msr_wait);
340 }
341
342 return status;
343}
344
345/**
346 * serial_omap_irq() - This handles the interrupt from one port
347 * @irq: uart port irq number
348 * @dev_id: uart port info
349 */
350static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
351{
352 struct uart_omap_port *up = dev_id;
353 unsigned int iir, lsr;
354 unsigned long flags;
355
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300356 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530357 iir = serial_in(up, UART_IIR);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530358 if (iir & UART_IIR_NO_INT) {
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300359 pm_runtime_mark_last_busy(up->dev);
360 pm_runtime_put_autosuspend(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530361 return IRQ_NONE;
Govindraj.Rfcdca752011-02-28 18:12:23 +0530362 }
Govindraj.Rb6126332010-09-27 20:20:49 +0530363
364 spin_lock_irqsave(&up->port.lock, flags);
365 lsr = serial_in(up, UART_LSR);
366 if (iir & UART_IIR_RLSI) {
Felipe Balbi49457432012-09-06 15:45:21 +0300367 if (lsr & UART_LSR_DR)
368 receive_chars(up, &lsr);
Govindraj.Rb6126332010-09-27 20:20:49 +0530369 }
370
371 check_modem_status(up);
372 if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
373 transmit_chars(up);
374
375 spin_unlock_irqrestore(&up->port.lock, flags);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300376 pm_runtime_mark_last_busy(up->dev);
377 pm_runtime_put_autosuspend(up->dev);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530378
Govindraj.Rb6126332010-09-27 20:20:49 +0530379 up->port_activity = jiffies;
380 return IRQ_HANDLED;
381}
382
383static unsigned int serial_omap_tx_empty(struct uart_port *port)
384{
Felipe Balbic990f352012-08-23 13:32:41 +0300385 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530386 unsigned long flags = 0;
387 unsigned int ret = 0;
388
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300389 pm_runtime_get_sync(up->dev);
Rajendra Nayakba774332011-12-14 17:25:43 +0530390 dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
Govindraj.Rb6126332010-09-27 20:20:49 +0530391 spin_lock_irqsave(&up->port.lock, flags);
392 ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
393 spin_unlock_irqrestore(&up->port.lock, flags);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300394 pm_runtime_put(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530395 return ret;
396}
397
398static unsigned int serial_omap_get_mctrl(struct uart_port *port)
399{
Felipe Balbic990f352012-08-23 13:32:41 +0300400 struct uart_omap_port *up = to_uart_omap_port(port);
Shubhrajyoti D514f31d2011-11-21 15:43:28 +0530401 unsigned int status;
Govindraj.Rb6126332010-09-27 20:20:49 +0530402 unsigned int ret = 0;
403
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300404 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530405 status = check_modem_status(up);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300406 pm_runtime_put(up->dev);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530407
Rajendra Nayakba774332011-12-14 17:25:43 +0530408 dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
Govindraj.Rb6126332010-09-27 20:20:49 +0530409
410 if (status & UART_MSR_DCD)
411 ret |= TIOCM_CAR;
412 if (status & UART_MSR_RI)
413 ret |= TIOCM_RNG;
414 if (status & UART_MSR_DSR)
415 ret |= TIOCM_DSR;
416 if (status & UART_MSR_CTS)
417 ret |= TIOCM_CTS;
418 return ret;
419}
420
421static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
422{
Felipe Balbic990f352012-08-23 13:32:41 +0300423 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530424 unsigned char mcr = 0;
425
Rajendra Nayakba774332011-12-14 17:25:43 +0530426 dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
Govindraj.Rb6126332010-09-27 20:20:49 +0530427 if (mctrl & TIOCM_RTS)
428 mcr |= UART_MCR_RTS;
429 if (mctrl & TIOCM_DTR)
430 mcr |= UART_MCR_DTR;
431 if (mctrl & TIOCM_OUT1)
432 mcr |= UART_MCR_OUT1;
433 if (mctrl & TIOCM_OUT2)
434 mcr |= UART_MCR_OUT2;
435 if (mctrl & TIOCM_LOOP)
436 mcr |= UART_MCR_LOOP;
437
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300438 pm_runtime_get_sync(up->dev);
Govindraj.Rc538d202011-11-07 18:57:03 +0530439 up->mcr = serial_in(up, UART_MCR);
440 up->mcr |= mcr;
441 serial_out(up, UART_MCR, up->mcr);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300442 pm_runtime_put(up->dev);
NeilBrown9574f362012-07-30 10:30:26 +1000443
444 if (gpio_is_valid(up->DTR_gpio) &&
445 !!(mctrl & TIOCM_DTR) != up->DTR_active) {
446 up->DTR_active = !up->DTR_active;
447 if (gpio_cansleep(up->DTR_gpio))
448 schedule_work(&up->qos_work);
449 else
450 gpio_set_value(up->DTR_gpio,
451 up->DTR_active != up->DTR_inverted);
452 }
Govindraj.Rb6126332010-09-27 20:20:49 +0530453}
454
455static void serial_omap_break_ctl(struct uart_port *port, int break_state)
456{
Felipe Balbic990f352012-08-23 13:32:41 +0300457 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530458 unsigned long flags = 0;
459
Rajendra Nayakba774332011-12-14 17:25:43 +0530460 dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300461 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530462 spin_lock_irqsave(&up->port.lock, flags);
463 if (break_state == -1)
464 up->lcr |= UART_LCR_SBC;
465 else
466 up->lcr &= ~UART_LCR_SBC;
467 serial_out(up, UART_LCR, up->lcr);
468 spin_unlock_irqrestore(&up->port.lock, flags);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300469 pm_runtime_put(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530470}
471
472static int serial_omap_startup(struct uart_port *port)
473{
Felipe Balbic990f352012-08-23 13:32:41 +0300474 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530475 unsigned long flags = 0;
476 int retval;
477
478 /*
479 * Allocate the IRQ
480 */
481 retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags,
482 up->name, up);
483 if (retval)
484 return retval;
485
Rajendra Nayakba774332011-12-14 17:25:43 +0530486 dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
Govindraj.Rb6126332010-09-27 20:20:49 +0530487
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300488 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530489 /*
490 * Clear the FIFO buffers and disable them.
491 * (they will be reenabled in set_termios())
492 */
493 serial_omap_clear_fifos(up);
494 /* For Hardware flow control */
495 serial_out(up, UART_MCR, UART_MCR_RTS);
496
497 /*
498 * Clear the interrupt registers.
499 */
500 (void) serial_in(up, UART_LSR);
501 if (serial_in(up, UART_LSR) & UART_LSR_DR)
502 (void) serial_in(up, UART_RX);
503 (void) serial_in(up, UART_IIR);
504 (void) serial_in(up, UART_MSR);
505
506 /*
507 * Now, initialize the UART
508 */
509 serial_out(up, UART_LCR, UART_LCR_WLEN8);
510 spin_lock_irqsave(&up->port.lock, flags);
511 /*
512 * Most PC uarts need OUT2 raised to enable interrupts.
513 */
514 up->port.mctrl |= TIOCM_OUT2;
515 serial_omap_set_mctrl(&up->port, up->port.mctrl);
516 spin_unlock_irqrestore(&up->port.lock, flags);
517
518 up->msr_saved_flags = 0;
Govindraj.Rb6126332010-09-27 20:20:49 +0530519 /*
520 * Finally, enable interrupts. Note: Modem status interrupts
521 * are set via set_termios(), which will be occurring imminently
522 * anyway, so we don't enable them here.
523 */
524 up->ier = UART_IER_RLSI | UART_IER_RDI;
525 serial_out(up, UART_IER, up->ier);
526
Jarkko Nikula78841462011-01-24 17:51:22 +0200527 /* Enable module level wake up */
528 serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
529
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300530 pm_runtime_mark_last_busy(up->dev);
531 pm_runtime_put_autosuspend(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530532 up->port_activity = jiffies;
533 return 0;
534}
535
536static void serial_omap_shutdown(struct uart_port *port)
537{
Felipe Balbic990f352012-08-23 13:32:41 +0300538 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530539 unsigned long flags = 0;
540
Rajendra Nayakba774332011-12-14 17:25:43 +0530541 dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530542
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300543 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530544 /*
545 * Disable interrupts from this port
546 */
547 up->ier = 0;
548 serial_out(up, UART_IER, 0);
549
550 spin_lock_irqsave(&up->port.lock, flags);
551 up->port.mctrl &= ~TIOCM_OUT2;
552 serial_omap_set_mctrl(&up->port, up->port.mctrl);
553 spin_unlock_irqrestore(&up->port.lock, flags);
554
555 /*
556 * Disable break condition and FIFOs
557 */
558 serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
559 serial_omap_clear_fifos(up);
560
561 /*
562 * Read data port to reset things, and then free the irq
563 */
564 if (serial_in(up, UART_LSR) & UART_LSR_DR)
565 (void) serial_in(up, UART_RX);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530566
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300567 pm_runtime_put(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530568 free_irq(up->port.irq, up);
569}
570
571static inline void
572serial_omap_configure_xonxoff
573 (struct uart_omap_port *up, struct ktermios *termios)
574{
Govindraj.Rb6126332010-09-27 20:20:49 +0530575 up->lcr = serial_in(up, UART_LCR);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800576 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530577 up->efr = serial_in(up, UART_EFR);
578 serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
579
580 serial_out(up, UART_XON1, termios->c_cc[VSTART]);
581 serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
582
583 /* clear SW control mode bits */
Govindraj.Rc538d202011-11-07 18:57:03 +0530584 up->efr &= OMAP_UART_SW_CLR;
Govindraj.Rb6126332010-09-27 20:20:49 +0530585
586 /*
587 * IXON Flag:
588 * Enable XON/XOFF flow control on output.
589 * Transmit XON1, XOFF1
590 */
591 if (termios->c_iflag & IXON)
Govindraj.Rc538d202011-11-07 18:57:03 +0530592 up->efr |= OMAP_UART_SW_TX;
Govindraj.Rb6126332010-09-27 20:20:49 +0530593
594 /*
595 * IXOFF Flag:
596 * Enable XON/XOFF flow control on input.
597 * Receiver compares XON1, XOFF1.
598 */
599 if (termios->c_iflag & IXOFF)
Govindraj.Rc538d202011-11-07 18:57:03 +0530600 up->efr |= OMAP_UART_SW_RX;
Govindraj.Rb6126332010-09-27 20:20:49 +0530601
602 serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800603 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
Govindraj.Rb6126332010-09-27 20:20:49 +0530604
605 up->mcr = serial_in(up, UART_MCR);
606
607 /*
608 * IXANY Flag:
609 * Enable any character to restart output.
610 * Operation resumes after receiving any
611 * character after recognition of the XOFF character
612 */
613 if (termios->c_iflag & IXANY)
614 up->mcr |= UART_MCR_XONANY;
615
616 serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800617 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530618 serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
619 /* Enable special char function UARTi.EFR_REG[5] and
620 * load the new software flow control mode IXON or IXOFF
621 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
622 */
Govindraj.Rc538d202011-11-07 18:57:03 +0530623 serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800624 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
Govindraj.Rb6126332010-09-27 20:20:49 +0530625
626 serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
627 serial_out(up, UART_LCR, up->lcr);
628}
629
Govindraj.R2fd14962011-11-09 17:41:21 +0530630static void serial_omap_uart_qos_work(struct work_struct *work)
631{
632 struct uart_omap_port *up = container_of(work, struct uart_omap_port,
633 qos_work);
634
635 pm_qos_update_request(&up->pm_qos_request, up->latency);
NeilBrown9574f362012-07-30 10:30:26 +1000636 if (gpio_is_valid(up->DTR_gpio))
637 gpio_set_value_cansleep(up->DTR_gpio,
638 up->DTR_active != up->DTR_inverted);
Govindraj.R2fd14962011-11-09 17:41:21 +0530639}
640
Govindraj.Rb6126332010-09-27 20:20:49 +0530641static void
642serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
643 struct ktermios *old)
644{
Felipe Balbic990f352012-08-23 13:32:41 +0300645 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530646 unsigned char cval = 0;
647 unsigned char efr = 0;
648 unsigned long flags = 0;
649 unsigned int baud, quot;
650
651 switch (termios->c_cflag & CSIZE) {
652 case CS5:
653 cval = UART_LCR_WLEN5;
654 break;
655 case CS6:
656 cval = UART_LCR_WLEN6;
657 break;
658 case CS7:
659 cval = UART_LCR_WLEN7;
660 break;
661 default:
662 case CS8:
663 cval = UART_LCR_WLEN8;
664 break;
665 }
666
667 if (termios->c_cflag & CSTOPB)
668 cval |= UART_LCR_STOP;
669 if (termios->c_cflag & PARENB)
670 cval |= UART_LCR_PARITY;
671 if (!(termios->c_cflag & PARODD))
672 cval |= UART_LCR_EPAR;
673
674 /*
675 * Ask the core to calculate the divisor for us.
676 */
677
678 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
679 quot = serial_omap_get_divisor(port, baud);
680
Govindraj.R2fd14962011-11-09 17:41:21 +0530681 /* calculate wakeup latency constraint */
Paul Walmsley19723452012-01-25 19:50:56 -0700682 up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8);
Govindraj.R2fd14962011-11-09 17:41:21 +0530683 up->latency = up->calc_latency;
684 schedule_work(&up->qos_work);
685
Govindraj.Rc538d202011-11-07 18:57:03 +0530686 up->dll = quot & 0xff;
687 up->dlh = quot >> 8;
688 up->mdr1 = UART_OMAP_MDR1_DISABLE;
689
Govindraj.Rb6126332010-09-27 20:20:49 +0530690 up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
691 UART_FCR_ENABLE_FIFO;
Govindraj.Rb6126332010-09-27 20:20:49 +0530692
693 /*
694 * Ok, we're now changing the port state. Do it with
695 * interrupts disabled.
696 */
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300697 pm_runtime_get_sync(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530698 spin_lock_irqsave(&up->port.lock, flags);
699
700 /*
701 * Update the per-port timeout.
702 */
703 uart_update_timeout(port, termios->c_cflag, baud);
704
705 up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
706 if (termios->c_iflag & INPCK)
707 up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
708 if (termios->c_iflag & (BRKINT | PARMRK))
709 up->port.read_status_mask |= UART_LSR_BI;
710
711 /*
712 * Characters to ignore
713 */
714 up->port.ignore_status_mask = 0;
715 if (termios->c_iflag & IGNPAR)
716 up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
717 if (termios->c_iflag & IGNBRK) {
718 up->port.ignore_status_mask |= UART_LSR_BI;
719 /*
720 * If we're ignoring parity and break indicators,
721 * ignore overruns too (for real raw support).
722 */
723 if (termios->c_iflag & IGNPAR)
724 up->port.ignore_status_mask |= UART_LSR_OE;
725 }
726
727 /*
728 * ignore all characters if CREAD is not set
729 */
730 if ((termios->c_cflag & CREAD) == 0)
731 up->port.ignore_status_mask |= UART_LSR_DR;
732
733 /*
734 * Modem status interrupts
735 */
736 up->ier &= ~UART_IER_MSI;
737 if (UART_ENABLE_MS(&up->port, termios->c_cflag))
738 up->ier |= UART_IER_MSI;
739 serial_out(up, UART_IER, up->ier);
740 serial_out(up, UART_LCR, cval); /* reset DLAB */
Govindraj.Rc538d202011-11-07 18:57:03 +0530741 up->lcr = cval;
Govindraj.R32212892011-11-07 18:58:55 +0530742 up->scr = OMAP_UART_SCR_TX_EMPTY;
Govindraj.Rb6126332010-09-27 20:20:49 +0530743
744 /* FIFOs and DMA Settings */
745
746 /* FCR can be changed only when the
747 * baud clock is not running
748 * DLL_REG and DLH_REG set to 0.
749 */
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800750 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
Govindraj.Rb6126332010-09-27 20:20:49 +0530751 serial_out(up, UART_DLL, 0);
752 serial_out(up, UART_DLM, 0);
753 serial_out(up, UART_LCR, 0);
754
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800755 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530756
757 up->efr = serial_in(up, UART_EFR);
758 serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
759
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800760 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
Govindraj.Rb6126332010-09-27 20:20:49 +0530761 up->mcr = serial_in(up, UART_MCR);
762 serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
763 /* FIFO ENABLE, DMA MODE */
Paul Walmsley0ba5f662012-01-25 19:50:36 -0700764
765 up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
Paul Walmsley0a697b22012-01-21 00:27:40 -0700766
Felipe Balbi49457432012-09-06 15:45:21 +0300767 /* Set receive FIFO threshold to 1 byte */
768 up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
769 up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);
Greg Kroah-Hartman8a74e9f2012-01-26 11:15:18 -0800770
Paul Walmsley0ba5f662012-01-25 19:50:36 -0700771 serial_out(up, UART_FCR, up->fcr);
772 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
773
Govindraj.Rc538d202011-11-07 18:57:03 +0530774 serial_out(up, UART_OMAP_SCR, up->scr);
775
Govindraj.Rb6126332010-09-27 20:20:49 +0530776 serial_out(up, UART_EFR, up->efr);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800777 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
Govindraj.Rb6126332010-09-27 20:20:49 +0530778 serial_out(up, UART_MCR, up->mcr);
779
780 /* Protocol, Baud Rate, and Interrupt Settings */
781
Govindraj.R94734742011-11-07 19:00:33 +0530782 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
783 serial_omap_mdr1_errataset(up, up->mdr1);
784 else
785 serial_out(up, UART_OMAP_MDR1, up->mdr1);
786
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800787 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530788
789 up->efr = serial_in(up, UART_EFR);
790 serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
791
792 serial_out(up, UART_LCR, 0);
793 serial_out(up, UART_IER, 0);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800794 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530795
Govindraj.Rc538d202011-11-07 18:57:03 +0530796 serial_out(up, UART_DLL, up->dll); /* LS of divisor */
797 serial_out(up, UART_DLM, up->dlh); /* MS of divisor */
Govindraj.Rb6126332010-09-27 20:20:49 +0530798
799 serial_out(up, UART_LCR, 0);
800 serial_out(up, UART_IER, up->ier);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800801 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530802
803 serial_out(up, UART_EFR, up->efr);
804 serial_out(up, UART_LCR, cval);
805
806 if (baud > 230400 && baud != 3000000)
Govindraj.Rc538d202011-11-07 18:57:03 +0530807 up->mdr1 = UART_OMAP_MDR1_13X_MODE;
Govindraj.Rb6126332010-09-27 20:20:49 +0530808 else
Govindraj.Rc538d202011-11-07 18:57:03 +0530809 up->mdr1 = UART_OMAP_MDR1_16X_MODE;
810
Govindraj.R94734742011-11-07 19:00:33 +0530811 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
812 serial_omap_mdr1_errataset(up, up->mdr1);
813 else
814 serial_out(up, UART_OMAP_MDR1, up->mdr1);
Govindraj.Rb6126332010-09-27 20:20:49 +0530815
816 /* Hardware Flow Control Configuration */
817
818 if (termios->c_cflag & CRTSCTS) {
819 efr |= (UART_EFR_CTS | UART_EFR_RTS);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800820 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
Govindraj.Rb6126332010-09-27 20:20:49 +0530821
822 up->mcr = serial_in(up, UART_MCR);
823 serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
824
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800825 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530826 up->efr = serial_in(up, UART_EFR);
827 serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
828
829 serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
830 serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800831 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
Govindraj.Rb6126332010-09-27 20:20:49 +0530832 serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
833 serial_out(up, UART_LCR, cval);
834 }
835
836 serial_omap_set_mctrl(&up->port, up->port.mctrl);
837 /* Software Flow Control Configuration */
Nick Pellyb280a972011-07-15 13:53:08 -0700838 serial_omap_configure_xonxoff(up, termios);
Govindraj.Rb6126332010-09-27 20:20:49 +0530839
840 spin_unlock_irqrestore(&up->port.lock, flags);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300841 pm_runtime_put(up->dev);
Rajendra Nayakba774332011-12-14 17:25:43 +0530842 dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
Govindraj.Rb6126332010-09-27 20:20:49 +0530843}
844
845static void
846serial_omap_pm(struct uart_port *port, unsigned int state,
847 unsigned int oldstate)
848{
Felipe Balbic990f352012-08-23 13:32:41 +0300849 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530850 unsigned char efr;
851
Rajendra Nayakba774332011-12-14 17:25:43 +0530852 dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530853
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300854 pm_runtime_get_sync(up->dev);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800855 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530856 efr = serial_in(up, UART_EFR);
857 serial_out(up, UART_EFR, efr | UART_EFR_ECB);
858 serial_out(up, UART_LCR, 0);
859
860 serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
Andrei Emeltchenko662b083a2010-11-30 14:11:49 -0800861 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
Govindraj.Rb6126332010-09-27 20:20:49 +0530862 serial_out(up, UART_EFR, efr);
863 serial_out(up, UART_LCR, 0);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530864
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300865 if (!device_may_wakeup(up->dev)) {
Govindraj.Rfcdca752011-02-28 18:12:23 +0530866 if (!state)
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300867 pm_runtime_forbid(up->dev);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530868 else
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300869 pm_runtime_allow(up->dev);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530870 }
871
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300872 pm_runtime_put(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +0530873}
874
875static void serial_omap_release_port(struct uart_port *port)
876{
877 dev_dbg(port->dev, "serial_omap_release_port+\n");
878}
879
880static int serial_omap_request_port(struct uart_port *port)
881{
882 dev_dbg(port->dev, "serial_omap_request_port+\n");
883 return 0;
884}
885
886static void serial_omap_config_port(struct uart_port *port, int flags)
887{
Felipe Balbic990f352012-08-23 13:32:41 +0300888 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530889
890 dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
Rajendra Nayakba774332011-12-14 17:25:43 +0530891 up->port.line);
Govindraj.Rb6126332010-09-27 20:20:49 +0530892 up->port.type = PORT_OMAP;
893}
894
895static int
896serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser)
897{
898 /* we don't want the core code to modify any port params */
899 dev_dbg(port->dev, "serial_omap_verify_port+\n");
900 return -EINVAL;
901}
902
903static const char *
904serial_omap_type(struct uart_port *port)
905{
Felipe Balbic990f352012-08-23 13:32:41 +0300906 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530907
Rajendra Nayakba774332011-12-14 17:25:43 +0530908 dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->port.line);
Govindraj.Rb6126332010-09-27 20:20:49 +0530909 return up->name;
910}
911
Govindraj.Rb6126332010-09-27 20:20:49 +0530912#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
913
914static inline void wait_for_xmitr(struct uart_omap_port *up)
915{
916 unsigned int status, tmout = 10000;
917
918 /* Wait up to 10ms for the character(s) to be sent. */
919 do {
920 status = serial_in(up, UART_LSR);
921
922 if (status & UART_LSR_BI)
923 up->lsr_break_flag = UART_LSR_BI;
924
925 if (--tmout == 0)
926 break;
927 udelay(1);
928 } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
929
930 /* Wait up to 1s for flow control if necessary */
931 if (up->port.flags & UPF_CONS_FLOW) {
932 tmout = 1000000;
933 for (tmout = 1000000; tmout; tmout--) {
934 unsigned int msr = serial_in(up, UART_MSR);
935
936 up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
937 if (msr & UART_MSR_CTS)
938 break;
939
940 udelay(1);
941 }
942 }
943}
944
Cosmin Cojocar1b41dbc2010-12-05 16:15:10 +0100945#ifdef CONFIG_CONSOLE_POLL
946
947static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
948{
Felipe Balbic990f352012-08-23 13:32:41 +0300949 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530950
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300951 pm_runtime_get_sync(up->dev);
Cosmin Cojocar1b41dbc2010-12-05 16:15:10 +0100952 wait_for_xmitr(up);
953 serial_out(up, UART_TX, ch);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300954 pm_runtime_put(up->dev);
Cosmin Cojocar1b41dbc2010-12-05 16:15:10 +0100955}
956
957static int serial_omap_poll_get_char(struct uart_port *port)
958{
Felipe Balbic990f352012-08-23 13:32:41 +0300959 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530960 unsigned int status;
Cosmin Cojocar1b41dbc2010-12-05 16:15:10 +0100961
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300962 pm_runtime_get_sync(up->dev);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530963 status = serial_in(up, UART_LSR);
Cosmin Cojocar1b41dbc2010-12-05 16:15:10 +0100964 if (!(status & UART_LSR_DR))
965 return NO_POLL_CHAR;
966
Govindraj.Rfcdca752011-02-28 18:12:23 +0530967 status = serial_in(up, UART_RX);
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300968 pm_runtime_put(up->dev);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530969 return status;
Cosmin Cojocar1b41dbc2010-12-05 16:15:10 +0100970}
971
972#endif /* CONFIG_CONSOLE_POLL */
973
974#ifdef CONFIG_SERIAL_OMAP_CONSOLE
975
976static struct uart_omap_port *serial_omap_console_ports[4];
977
978static struct uart_driver serial_omap_reg;
979
Govindraj.Rb6126332010-09-27 20:20:49 +0530980static void serial_omap_console_putchar(struct uart_port *port, int ch)
981{
Felipe Balbic990f352012-08-23 13:32:41 +0300982 struct uart_omap_port *up = to_uart_omap_port(port);
Govindraj.Rb6126332010-09-27 20:20:49 +0530983
984 wait_for_xmitr(up);
985 serial_out(up, UART_TX, ch);
986}
987
988static void
989serial_omap_console_write(struct console *co, const char *s,
990 unsigned int count)
991{
992 struct uart_omap_port *up = serial_omap_console_ports[co->index];
993 unsigned long flags;
994 unsigned int ier;
995 int locked = 1;
996
Felipe Balbid8ee4ea2012-09-06 15:45:20 +0300997 pm_runtime_get_sync(up->dev);
Govindraj.Rfcdca752011-02-28 18:12:23 +0530998
Govindraj.Rb6126332010-09-27 20:20:49 +0530999 local_irq_save(flags);
1000 if (up->port.sysrq)
1001 locked = 0;
1002 else if (oops_in_progress)
1003 locked = spin_trylock(&up->port.lock);
1004 else
1005 spin_lock(&up->port.lock);
1006
1007 /*
1008 * First save the IER then disable the interrupts
1009 */
1010 ier = serial_in(up, UART_IER);
1011 serial_out(up, UART_IER, 0);
1012
1013 uart_console_write(&up->port, s, count, serial_omap_console_putchar);
1014
1015 /*
1016 * Finally, wait for transmitter to become empty
1017 * and restore the IER
1018 */
1019 wait_for_xmitr(up);
1020 serial_out(up, UART_IER, ier);
1021 /*
1022 * The receive handling will happen properly because the
1023 * receive ready bit will still be set; it is not cleared
1024 * on read. However, modem control will not, we must
1025 * call it if we have saved something in the saved flags
1026 * while processing with interrupts off.
1027 */
1028 if (up->msr_saved_flags)
1029 check_modem_status(up);
1030
Felipe Balbid8ee4ea2012-09-06 15:45:20 +03001031 pm_runtime_mark_last_busy(up->dev);
1032 pm_runtime_put_autosuspend(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +05301033 if (locked)
1034 spin_unlock(&up->port.lock);
1035 local_irq_restore(flags);
1036}
1037
1038static int __init
1039serial_omap_console_setup(struct console *co, char *options)
1040{
1041 struct uart_omap_port *up;
1042 int baud = 115200;
1043 int bits = 8;
1044 int parity = 'n';
1045 int flow = 'n';
1046
1047 if (serial_omap_console_ports[co->index] == NULL)
1048 return -ENODEV;
1049 up = serial_omap_console_ports[co->index];
1050
1051 if (options)
1052 uart_parse_options(options, &baud, &parity, &bits, &flow);
1053
1054 return uart_set_options(&up->port, co, baud, parity, bits, flow);
1055}
1056
1057static struct console serial_omap_console = {
1058 .name = OMAP_SERIAL_NAME,
1059 .write = serial_omap_console_write,
1060 .device = uart_console_device,
1061 .setup = serial_omap_console_setup,
1062 .flags = CON_PRINTBUFFER,
1063 .index = -1,
1064 .data = &serial_omap_reg,
1065};
1066
1067static void serial_omap_add_console_port(struct uart_omap_port *up)
1068{
Rajendra Nayakba774332011-12-14 17:25:43 +05301069 serial_omap_console_ports[up->port.line] = up;
Govindraj.Rb6126332010-09-27 20:20:49 +05301070}
1071
1072#define OMAP_CONSOLE (&serial_omap_console)
1073
1074#else
1075
1076#define OMAP_CONSOLE NULL
1077
1078static inline void serial_omap_add_console_port(struct uart_omap_port *up)
1079{}
1080
1081#endif
1082
1083static struct uart_ops serial_omap_pops = {
1084 .tx_empty = serial_omap_tx_empty,
1085 .set_mctrl = serial_omap_set_mctrl,
1086 .get_mctrl = serial_omap_get_mctrl,
1087 .stop_tx = serial_omap_stop_tx,
1088 .start_tx = serial_omap_start_tx,
1089 .stop_rx = serial_omap_stop_rx,
1090 .enable_ms = serial_omap_enable_ms,
1091 .break_ctl = serial_omap_break_ctl,
1092 .startup = serial_omap_startup,
1093 .shutdown = serial_omap_shutdown,
1094 .set_termios = serial_omap_set_termios,
1095 .pm = serial_omap_pm,
1096 .type = serial_omap_type,
1097 .release_port = serial_omap_release_port,
1098 .request_port = serial_omap_request_port,
1099 .config_port = serial_omap_config_port,
1100 .verify_port = serial_omap_verify_port,
Cosmin Cojocar1b41dbc2010-12-05 16:15:10 +01001101#ifdef CONFIG_CONSOLE_POLL
1102 .poll_put_char = serial_omap_poll_put_char,
1103 .poll_get_char = serial_omap_poll_get_char,
1104#endif
Govindraj.Rb6126332010-09-27 20:20:49 +05301105};
1106
1107static struct uart_driver serial_omap_reg = {
1108 .owner = THIS_MODULE,
1109 .driver_name = "OMAP-SERIAL",
1110 .dev_name = OMAP_SERIAL_NAME,
1111 .nr = OMAP_MAX_HSUART_PORTS,
1112 .cons = OMAP_CONSOLE,
1113};
1114
Shubhrajyoti D3bc4f0d2012-01-16 15:52:36 +05301115#ifdef CONFIG_PM_SLEEP
Govindraj.Rfcdca752011-02-28 18:12:23 +05301116static int serial_omap_suspend(struct device *dev)
Govindraj.Rb6126332010-09-27 20:20:49 +05301117{
Govindraj.Rfcdca752011-02-28 18:12:23 +05301118 struct uart_omap_port *up = dev_get_drvdata(dev);
Govindraj.Rb6126332010-09-27 20:20:49 +05301119
Govindraj.R2fd14962011-11-09 17:41:21 +05301120 if (up) {
Govindraj.Rb6126332010-09-27 20:20:49 +05301121 uart_suspend_port(&serial_omap_reg, &up->port);
Govindraj.R2fd14962011-11-09 17:41:21 +05301122 flush_work_sync(&up->qos_work);
1123 }
1124
Govindraj.Rb6126332010-09-27 20:20:49 +05301125 return 0;
1126}
1127
Govindraj.Rfcdca752011-02-28 18:12:23 +05301128static int serial_omap_resume(struct device *dev)
Govindraj.Rb6126332010-09-27 20:20:49 +05301129{
Govindraj.Rfcdca752011-02-28 18:12:23 +05301130 struct uart_omap_port *up = dev_get_drvdata(dev);
Govindraj.Rb6126332010-09-27 20:20:49 +05301131
1132 if (up)
1133 uart_resume_port(&serial_omap_reg, &up->port);
1134 return 0;
1135}
Govindraj.Rfcdca752011-02-28 18:12:23 +05301136#endif
Govindraj.Rb6126332010-09-27 20:20:49 +05301137
Govindraj.R7c77c8d2012-04-03 19:12:34 +05301138static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
1139{
1140 u32 mvr, scheme;
1141 u16 revision, major, minor;
1142
1143 mvr = serial_in(up, UART_OMAP_MVER);
1144
1145 /* Check revision register scheme */
1146 scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT;
1147
1148 switch (scheme) {
1149 case 0: /* Legacy Scheme: OMAP2/3 */
1150 /* MINOR_REV[0:4], MAJOR_REV[4:7] */
1151 major = (mvr & OMAP_UART_LEGACY_MVR_MAJ_MASK) >>
1152 OMAP_UART_LEGACY_MVR_MAJ_SHIFT;
1153 minor = (mvr & OMAP_UART_LEGACY_MVR_MIN_MASK);
1154 break;
1155 case 1:
1156 /* New Scheme: OMAP4+ */
1157 /* MINOR_REV[0:5], MAJOR_REV[8:10] */
1158 major = (mvr & OMAP_UART_MVR_MAJ_MASK) >>
1159 OMAP_UART_MVR_MAJ_SHIFT;
1160 minor = (mvr & OMAP_UART_MVR_MIN_MASK);
1161 break;
1162 default:
Felipe Balbid8ee4ea2012-09-06 15:45:20 +03001163 dev_warn(up->dev,
Govindraj.R7c77c8d2012-04-03 19:12:34 +05301164 "Unknown %s revision, defaulting to highest\n",
1165 up->name);
1166 /* highest possible revision */
1167 major = 0xff;
1168 minor = 0xff;
1169 }
1170
1171 /* normalize revision for the driver */
1172 revision = UART_BUILD_REVISION(major, minor);
1173
1174 switch (revision) {
1175 case OMAP_UART_REV_46:
1176 up->errata |= (UART_ERRATA_i202_MDR1_ACCESS |
1177 UART_ERRATA_i291_DMA_FORCEIDLE);
1178 break;
1179 case OMAP_UART_REV_52:
1180 up->errata |= (UART_ERRATA_i202_MDR1_ACCESS |
1181 UART_ERRATA_i291_DMA_FORCEIDLE);
1182 break;
1183 case OMAP_UART_REV_63:
1184 up->errata |= UART_ERRATA_i202_MDR1_ACCESS;
1185 break;
1186 default:
1187 break;
1188 }
1189}
1190
Rajendra Nayakd92b0df2011-12-14 17:25:45 +05301191static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
1192{
1193 struct omap_uart_port_info *omap_up_info;
1194
1195 omap_up_info = devm_kzalloc(dev, sizeof(*omap_up_info), GFP_KERNEL);
1196 if (!omap_up_info)
1197 return NULL; /* out of memory */
1198
1199 of_property_read_u32(dev->of_node, "clock-frequency",
1200 &omap_up_info->uartclk);
1201 return omap_up_info;
1202}
1203
Govindraj.Rb6126332010-09-27 20:20:49 +05301204static int serial_omap_probe(struct platform_device *pdev)
1205{
1206 struct uart_omap_port *up;
Felipe Balbi49457432012-09-06 15:45:21 +03001207 struct resource *mem, *irq;
Govindraj.Rb6126332010-09-27 20:20:49 +05301208 struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
NeilBrown9574f362012-07-30 10:30:26 +10001209 int ret;
Govindraj.Rb6126332010-09-27 20:20:49 +05301210
Rajendra Nayakd92b0df2011-12-14 17:25:45 +05301211 if (pdev->dev.of_node)
1212 omap_up_info = of_get_uart_port_info(&pdev->dev);
1213
Govindraj.Rb6126332010-09-27 20:20:49 +05301214 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1215 if (!mem) {
1216 dev_err(&pdev->dev, "no mem resource?\n");
1217 return -ENODEV;
1218 }
1219
1220 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1221 if (!irq) {
1222 dev_err(&pdev->dev, "no irq resource?\n");
1223 return -ENODEV;
1224 }
1225
Shubhrajyoti D388bc262012-03-21 17:22:22 +05301226 if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
Joe Perches28f65c112011-06-09 09:13:32 -07001227 pdev->dev.driver->name)) {
Govindraj.Rb6126332010-09-27 20:20:49 +05301228 dev_err(&pdev->dev, "memory region already claimed\n");
1229 return -EBUSY;
1230 }
1231
NeilBrown9574f362012-07-30 10:30:26 +10001232 if (gpio_is_valid(omap_up_info->DTR_gpio) &&
1233 omap_up_info->DTR_present) {
1234 ret = gpio_request(omap_up_info->DTR_gpio, "omap-serial");
1235 if (ret < 0)
1236 return ret;
1237 ret = gpio_direction_output(omap_up_info->DTR_gpio,
1238 omap_up_info->DTR_inverted);
1239 if (ret < 0)
1240 return ret;
1241 }
1242
Shubhrajyoti D388bc262012-03-21 17:22:22 +05301243 up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);
1244 if (!up)
1245 return -ENOMEM;
1246
NeilBrown9574f362012-07-30 10:30:26 +10001247 if (gpio_is_valid(omap_up_info->DTR_gpio) &&
1248 omap_up_info->DTR_present) {
1249 up->DTR_gpio = omap_up_info->DTR_gpio;
1250 up->DTR_inverted = omap_up_info->DTR_inverted;
1251 } else
1252 up->DTR_gpio = -EINVAL;
1253 up->DTR_active = 0;
1254
Felipe Balbid8ee4ea2012-09-06 15:45:20 +03001255 up->dev = &pdev->dev;
Govindraj.Rb6126332010-09-27 20:20:49 +05301256 up->port.dev = &pdev->dev;
1257 up->port.type = PORT_OMAP;
1258 up->port.iotype = UPIO_MEM;
1259 up->port.irq = irq->start;
1260
1261 up->port.regshift = 2;
1262 up->port.fifosize = 64;
1263 up->port.ops = &serial_omap_pops;
Govindraj.Rb6126332010-09-27 20:20:49 +05301264
Rajendra Nayakd92b0df2011-12-14 17:25:45 +05301265 if (pdev->dev.of_node)
1266 up->port.line = of_alias_get_id(pdev->dev.of_node, "serial");
1267 else
1268 up->port.line = pdev->id;
1269
1270 if (up->port.line < 0) {
1271 dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n",
1272 up->port.line);
1273 ret = -ENODEV;
Shubhrajyoti D388bc262012-03-21 17:22:22 +05301274 goto err_port_line;
Rajendra Nayakd92b0df2011-12-14 17:25:45 +05301275 }
1276
1277 sprintf(up->name, "OMAP UART%d", up->port.line);
Govindraj.Redd70ad2011-10-11 14:55:41 +05301278 up->port.mapbase = mem->start;
Shubhrajyoti D388bc262012-03-21 17:22:22 +05301279 up->port.membase = devm_ioremap(&pdev->dev, mem->start,
1280 resource_size(mem));
Govindraj.Redd70ad2011-10-11 14:55:41 +05301281 if (!up->port.membase) {
1282 dev_err(&pdev->dev, "can't ioremap UART\n");
1283 ret = -ENOMEM;
Shubhrajyoti D388bc262012-03-21 17:22:22 +05301284 goto err_ioremap;
Govindraj.Redd70ad2011-10-11 14:55:41 +05301285 }
1286
Govindraj.Rb6126332010-09-27 20:20:49 +05301287 up->port.flags = omap_up_info->flags;
Govindraj.Rb6126332010-09-27 20:20:49 +05301288 up->port.uartclk = omap_up_info->uartclk;
Rajendra Nayak8fe789d2011-12-14 17:25:44 +05301289 if (!up->port.uartclk) {
1290 up->port.uartclk = DEFAULT_CLK_SPEED;
1291 dev_warn(&pdev->dev, "No clock speed specified: using default:"
1292 "%d\n", DEFAULT_CLK_SPEED);
1293 }
Govindraj.Rb6126332010-09-27 20:20:49 +05301294
Govindraj.R2fd14962011-11-09 17:41:21 +05301295 up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
1296 up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
1297 pm_qos_add_request(&up->pm_qos_request,
1298 PM_QOS_CPU_DMA_LATENCY, up->latency);
1299 serial_omap_uart_wq = create_singlethread_workqueue(up->name);
1300 INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
1301
Govindraj.Rfcdca752011-02-28 18:12:23 +05301302 pm_runtime_use_autosuspend(&pdev->dev);
1303 pm_runtime_set_autosuspend_delay(&pdev->dev,
Deepak Kc86845db2011-11-09 17:33:38 +05301304 omap_up_info->autosuspend_timeout);
Govindraj.Rfcdca752011-02-28 18:12:23 +05301305
1306 pm_runtime_irq_safe(&pdev->dev);
1307 pm_runtime_enable(&pdev->dev);
1308 pm_runtime_get_sync(&pdev->dev);
1309
Govindraj.R7c77c8d2012-04-03 19:12:34 +05301310 omap_serial_fill_features_erratas(up);
1311
Rajendra Nayakba774332011-12-14 17:25:43 +05301312 ui[up->port.line] = up;
Govindraj.Rb6126332010-09-27 20:20:49 +05301313 serial_omap_add_console_port(up);
1314
1315 ret = uart_add_one_port(&serial_omap_reg, &up->port);
1316 if (ret != 0)
Shubhrajyoti D388bc262012-03-21 17:22:22 +05301317 goto err_add_port;
Govindraj.Rb6126332010-09-27 20:20:49 +05301318
Govindraj.Rfcdca752011-02-28 18:12:23 +05301319 pm_runtime_put(&pdev->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +05301320 platform_set_drvdata(pdev, up);
1321 return 0;
Shubhrajyoti D388bc262012-03-21 17:22:22 +05301322
1323err_add_port:
1324 pm_runtime_put(&pdev->dev);
1325 pm_runtime_disable(&pdev->dev);
1326err_ioremap:
1327err_port_line:
Govindraj.Rb6126332010-09-27 20:20:49 +05301328 dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
1329 pdev->id, __func__, ret);
Govindraj.Rb6126332010-09-27 20:20:49 +05301330 return ret;
1331}
1332
1333static int serial_omap_remove(struct platform_device *dev)
1334{
1335 struct uart_omap_port *up = platform_get_drvdata(dev);
1336
Govindraj.Rb6126332010-09-27 20:20:49 +05301337 if (up) {
Felipe Balbid8ee4ea2012-09-06 15:45:20 +03001338 pm_runtime_disable(up->dev);
Govindraj.Rb6126332010-09-27 20:20:49 +05301339 uart_remove_one_port(&serial_omap_reg, &up->port);
Govindraj.R2fd14962011-11-09 17:41:21 +05301340 pm_qos_remove_request(&up->pm_qos_request);
Govindraj.Rb6126332010-09-27 20:20:49 +05301341 }
Govindraj.Rfcdca752011-02-28 18:12:23 +05301342
1343 platform_set_drvdata(dev, NULL);
Govindraj.Rb6126332010-09-27 20:20:49 +05301344 return 0;
1345}
1346
Govindraj.R94734742011-11-07 19:00:33 +05301347/*
1348 * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460)
1349 * The access to uart register after MDR1 Access
1350 * causes UART to corrupt data.
1351 *
1352 * Need a delay =
1353 * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
1354 * give 10 times as much
1355 */
1356static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1)
1357{
1358 u8 timeout = 255;
1359
1360 serial_out(up, UART_OMAP_MDR1, mdr1);
1361 udelay(2);
1362 serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
1363 UART_FCR_CLEAR_RCVR);
1364 /*
1365 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
1366 * TX_FIFO_E bit is 1.
1367 */
1368 while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
1369 (UART_LSR_THRE | UART_LSR_DR))) {
1370 timeout--;
1371 if (!timeout) {
1372 /* Should *never* happen. we warn and carry on */
Felipe Balbid8ee4ea2012-09-06 15:45:20 +03001373 dev_crit(up->dev, "Errata i202: timedout %x\n",
Govindraj.R94734742011-11-07 19:00:33 +05301374 serial_in(up, UART_LSR));
1375 break;
1376 }
1377 udelay(1);
1378 }
1379}
1380
Shubhrajyoti Db5148852012-01-16 15:52:37 +05301381#ifdef CONFIG_PM_RUNTIME
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301382static void serial_omap_restore_context(struct uart_omap_port *up)
1383{
Govindraj.R94734742011-11-07 19:00:33 +05301384 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
1385 serial_omap_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
1386 else
1387 serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
1388
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301389 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
1390 serial_out(up, UART_EFR, UART_EFR_ECB);
1391 serial_out(up, UART_LCR, 0x0); /* Operational mode */
1392 serial_out(up, UART_IER, 0x0);
1393 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
Govindraj.Rc538d202011-11-07 18:57:03 +05301394 serial_out(up, UART_DLL, up->dll);
1395 serial_out(up, UART_DLM, up->dlh);
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301396 serial_out(up, UART_LCR, 0x0); /* Operational mode */
1397 serial_out(up, UART_IER, up->ier);
1398 serial_out(up, UART_FCR, up->fcr);
1399 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
1400 serial_out(up, UART_MCR, up->mcr);
1401 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
Govindraj.Rc538d202011-11-07 18:57:03 +05301402 serial_out(up, UART_OMAP_SCR, up->scr);
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301403 serial_out(up, UART_EFR, up->efr);
1404 serial_out(up, UART_LCR, up->lcr);
Govindraj.R94734742011-11-07 19:00:33 +05301405 if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
1406 serial_omap_mdr1_errataset(up, up->mdr1);
1407 else
1408 serial_out(up, UART_OMAP_MDR1, up->mdr1);
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301409}
1410
Govindraj.Rfcdca752011-02-28 18:12:23 +05301411static int serial_omap_runtime_suspend(struct device *dev)
1412{
Govindraj.Rec3bebc2011-10-11 19:11:27 +05301413 struct uart_omap_port *up = dev_get_drvdata(dev);
1414 struct omap_uart_port_info *pdata = dev->platform_data;
1415
1416 if (!up)
1417 return -EINVAL;
1418
Felipe Balbie5b57c02012-08-23 13:32:42 +03001419 if (!pdata)
Govindraj.R62f3ec5f2011-10-13 14:11:09 +05301420 return 0;
1421
Felipe Balbie5b57c02012-08-23 13:32:42 +03001422 up->context_loss_cnt = serial_omap_get_context_loss_count(up);
Govindraj.Rec3bebc2011-10-11 19:11:27 +05301423
Govindraj.R62f3ec5f2011-10-13 14:11:09 +05301424 if (device_may_wakeup(dev)) {
1425 if (!up->wakeups_enabled) {
Felipe Balbie5b57c02012-08-23 13:32:42 +03001426 serial_omap_enable_wakeup(up, true);
Govindraj.R62f3ec5f2011-10-13 14:11:09 +05301427 up->wakeups_enabled = true;
1428 }
1429 } else {
1430 if (up->wakeups_enabled) {
Felipe Balbie5b57c02012-08-23 13:32:42 +03001431 serial_omap_enable_wakeup(up, false);
Govindraj.R62f3ec5f2011-10-13 14:11:09 +05301432 up->wakeups_enabled = false;
1433 }
1434 }
1435
Govindraj.R2fd14962011-11-09 17:41:21 +05301436 up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
1437 schedule_work(&up->qos_work);
1438
Govindraj.Rfcdca752011-02-28 18:12:23 +05301439 return 0;
1440}
1441
1442static int serial_omap_runtime_resume(struct device *dev)
1443{
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301444 struct uart_omap_port *up = dev_get_drvdata(dev);
Govindraj.Rec3bebc2011-10-11 19:11:27 +05301445 struct omap_uart_port_info *pdata = dev->platform_data;
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301446
Cousson, Benoita5f43132012-02-28 18:22:12 +01001447 if (up && pdata) {
Felipe Balbie5b57c02012-08-23 13:32:42 +03001448 u32 loss_cnt = serial_omap_get_context_loss_count(up);
Govindraj.Rec3bebc2011-10-11 19:11:27 +05301449
1450 if (up->context_loss_cnt != loss_cnt)
1451 serial_omap_restore_context(up);
Govindraj.R94734742011-11-07 19:00:33 +05301452
Govindraj.R2fd14962011-11-09 17:41:21 +05301453 up->latency = up->calc_latency;
1454 schedule_work(&up->qos_work);
Govindraj.Rec3bebc2011-10-11 19:11:27 +05301455 }
Govindraj.R9f9ac1e2011-11-07 18:56:12 +05301456
Govindraj.Rfcdca752011-02-28 18:12:23 +05301457 return 0;
1458}
1459#endif
1460
1461static const struct dev_pm_ops serial_omap_dev_pm_ops = {
1462 SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume)
1463 SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend,
1464 serial_omap_runtime_resume, NULL)
1465};
1466
Rajendra Nayakd92b0df2011-12-14 17:25:45 +05301467#if defined(CONFIG_OF)
1468static const struct of_device_id omap_serial_of_match[] = {
1469 { .compatible = "ti,omap2-uart" },
1470 { .compatible = "ti,omap3-uart" },
1471 { .compatible = "ti,omap4-uart" },
1472 {},
1473};
1474MODULE_DEVICE_TABLE(of, omap_serial_of_match);
1475#endif
1476
Govindraj.Rb6126332010-09-27 20:20:49 +05301477static struct platform_driver serial_omap_driver = {
1478 .probe = serial_omap_probe,
1479 .remove = serial_omap_remove,
Govindraj.Rb6126332010-09-27 20:20:49 +05301480 .driver = {
1481 .name = DRIVER_NAME,
Govindraj.Rfcdca752011-02-28 18:12:23 +05301482 .pm = &serial_omap_dev_pm_ops,
Rajendra Nayakd92b0df2011-12-14 17:25:45 +05301483 .of_match_table = of_match_ptr(omap_serial_of_match),
Govindraj.Rb6126332010-09-27 20:20:49 +05301484 },
1485};
1486
1487static int __init serial_omap_init(void)
1488{
1489 int ret;
1490
1491 ret = uart_register_driver(&serial_omap_reg);
1492 if (ret != 0)
1493 return ret;
1494 ret = platform_driver_register(&serial_omap_driver);
1495 if (ret != 0)
1496 uart_unregister_driver(&serial_omap_reg);
1497 return ret;
1498}
1499
1500static void __exit serial_omap_exit(void)
1501{
1502 platform_driver_unregister(&serial_omap_driver);
1503 uart_unregister_driver(&serial_omap_reg);
1504}
1505
1506module_init(serial_omap_init);
1507module_exit(serial_omap_exit);
1508
1509MODULE_DESCRIPTION("OMAP High Speed UART driver");
1510MODULE_LICENSE("GPL");
1511MODULE_AUTHOR("Texas Instruments Inc");