blob: e657674d549036cbdeb2b394101dd33b07707a1e [file] [log] [blame]
Tony Lindgren1dbae812005-11-10 14:26:51 +00001/*
Uwe Zeisbergerf30c2262006-10-03 23:01:26 +02002 * arch/arm/mach-omap2/serial.c
Tony Lindgren1dbae812005-11-10 14:26:51 +00003 *
4 * OMAP2 serial support.
5 *
Jouni Hogander6e811762008-10-06 15:49:15 +03006 * Copyright (C) 2005-2008 Nokia Corporation
Tony Lindgren1dbae812005-11-10 14:26:51 +00007 * Author: Paul Mundt <paul.mundt@nokia.com>
8 *
Kevin Hilman4af40162009-02-04 10:51:40 -08009 * Major rework for PM support by Kevin Hilman
10 *
Tony Lindgren1dbae812005-11-10 14:26:51 +000011 * Based off of arch/arm/mach-omap/omap1/serial.c
12 *
Santosh Shilimkar44169072009-05-28 14:16:04 -070013 * Copyright (C) 2009 Texas Instruments
14 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com
15 *
Tony Lindgren1dbae812005-11-10 14:26:51 +000016 * This file is subject to the terms and conditions of the GNU General Public
17 * License. See the file "COPYING" in the main directory of this archive
18 * for more details.
19 */
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/serial_8250.h>
23#include <linux/serial_reg.h>
Russell Kingf8ce2542006-01-07 16:15:52 +000024#include <linux/clk.h>
Russell Kingfced80c2008-09-06 12:10:45 +010025#include <linux/io.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000026
Tony Lindgrence491cf2009-10-20 09:40:47 -070027#include <plat/common.h>
28#include <plat/board.h>
29#include <plat/clock.h>
30#include <plat/control.h>
Tony Lindgren1dbae812005-11-10 14:26:51 +000031
Kevin Hilman4af40162009-02-04 10:51:40 -080032#include "prm.h"
33#include "pm.h"
34#include "prm-regbits-34xx.h"
35
vikram panditace13d472009-12-11 16:16:37 -080036#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52
Kevin Hilman4af40162009-02-04 10:51:40 -080037#define UART_OMAP_WER 0x17 /* Wake-up enable register */
38
Tony Lindgren301fe8e2010-02-01 12:34:31 -080039/*
40 * NOTE: By default the serial timeout is disabled as it causes lost characters
41 * over the serial ports. This means that the UART clocks will stay on until
42 * disabled via sysfs. This also causes that any deeper omap sleep states are
43 * blocked.
44 */
45#define DEFAULT_TIMEOUT 0
Kevin Hilman4af40162009-02-04 10:51:40 -080046
47struct omap_uart_state {
48 int num;
49 int can_sleep;
50 struct timer_list timer;
51 u32 timeout;
52
53 void __iomem *wk_st;
54 void __iomem *wk_en;
55 u32 wk_mask;
56 u32 padconf;
57
58 struct clk *ick;
59 struct clk *fck;
60 int clocked;
61
62 struct plat_serial8250_port *p;
63 struct list_head node;
Kevin Hilmanfd455ea2009-04-27 12:27:36 -070064 struct platform_device pdev;
Kevin Hilman4af40162009-02-04 10:51:40 -080065
66#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
67 int context_valid;
68
69 /* Registers to be saved/restored for OFF-mode */
70 u16 dll;
71 u16 dlh;
72 u16 ier;
73 u16 sysc;
74 u16 scr;
75 u16 wer;
76#endif
77};
78
Kevin Hilman4af40162009-02-04 10:51:40 -080079static LIST_HEAD(uart_list);
Tony Lindgren1dbae812005-11-10 14:26:51 +000080
Kevin Hilmanfd455ea2009-04-27 12:27:36 -070081static struct plat_serial8250_port serial_platform_data0[] = {
Tony Lindgren1dbae812005-11-10 14:26:51 +000082 {
Tony Lindgren1dbae812005-11-10 14:26:51 +000083 .irq = 72,
84 .flags = UPF_BOOT_AUTOCONF,
85 .iotype = UPIO_MEM,
86 .regshift = 2,
Jouni Hogander6e811762008-10-06 15:49:15 +030087 .uartclk = OMAP24XX_BASE_BAUD * 16,
Tony Lindgren1dbae812005-11-10 14:26:51 +000088 }, {
Kevin Hilmanfd455ea2009-04-27 12:27:36 -070089 .flags = 0
90 }
91};
92
93static struct plat_serial8250_port serial_platform_data1[] = {
94 {
Tony Lindgren1dbae812005-11-10 14:26:51 +000095 .irq = 73,
96 .flags = UPF_BOOT_AUTOCONF,
97 .iotype = UPIO_MEM,
98 .regshift = 2,
Jouni Hogander6e811762008-10-06 15:49:15 +030099 .uartclk = OMAP24XX_BASE_BAUD * 16,
Tony Lindgren1dbae812005-11-10 14:26:51 +0000100 }, {
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700101 .flags = 0
102 }
103};
104
105static struct plat_serial8250_port serial_platform_data2[] = {
106 {
Tony Lindgren1dbae812005-11-10 14:26:51 +0000107 .irq = 74,
108 .flags = UPF_BOOT_AUTOCONF,
109 .iotype = UPIO_MEM,
110 .regshift = 2,
Jouni Hogander6e811762008-10-06 15:49:15 +0300111 .uartclk = OMAP24XX_BASE_BAUD * 16,
Tony Lindgren1dbae812005-11-10 14:26:51 +0000112 }, {
113 .flags = 0
114 }
115};
116
Santosh Shilimkar0e3eaad2009-08-22 13:30:11 +0530117#ifdef CONFIG_ARCH_OMAP4
118static struct plat_serial8250_port serial_platform_data3[] = {
119 {
Santosh Shilimkar0e3eaad2009-08-22 13:30:11 +0530120 .irq = 70,
121 .flags = UPF_BOOT_AUTOCONF,
122 .iotype = UPIO_MEM,
123 .regshift = 2,
124 .uartclk = OMAP24XX_BASE_BAUD * 16,
125 }, {
126 .flags = 0
127 }
128};
129#endif
Tony Lindgren4f2c49f2010-02-15 08:48:53 -0800130
131void __init omap2_set_globals_uart(struct omap_globals *omap2_globals)
132{
133 serial_platform_data0[0].mapbase = omap2_globals->uart1_phys;
134 serial_platform_data1[0].mapbase = omap2_globals->uart2_phys;
135 serial_platform_data2[0].mapbase = omap2_globals->uart3_phys;
136#ifdef CONFIG_ARCH_OMAP4
137 serial_platform_data3[0].mapbase = omap2_globals->uart4_phys;
138#endif
139}
140
Alexander Shishkin92303722010-01-08 10:29:06 -0800141static inline unsigned int __serial_read_reg(struct uart_port *up,
142 int offset)
143{
144 offset <<= up->regshift;
145 return (unsigned int)__raw_readb(up->membase + offset);
146}
147
Tony Lindgren1dbae812005-11-10 14:26:51 +0000148static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
149 int offset)
150{
151 offset <<= up->regshift;
152 return (unsigned int)__raw_readb(up->membase + offset);
153}
154
155static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
156 int value)
157{
158 offset <<= p->regshift;
Russell Kinge8a91c92008-09-01 22:07:37 +0100159 __raw_writeb(value, p->membase + offset);
Tony Lindgren1dbae812005-11-10 14:26:51 +0000160}
161
162/*
163 * Internal UARTs need to be initialized for the 8250 autoconfig to work
164 * properly. Note that the TX watermark initialization may not be needed
165 * once the 8250.c watermark handling code is merged.
166 */
Kevin Hilman4af40162009-02-04 10:51:40 -0800167static inline void __init omap_uart_reset(struct omap_uart_state *uart)
Tony Lindgren1dbae812005-11-10 14:26:51 +0000168{
Kevin Hilman4af40162009-02-04 10:51:40 -0800169 struct plat_serial8250_port *p = uart->p;
170
Tony Lindgren1dbae812005-11-10 14:26:51 +0000171 serial_write_reg(p, UART_OMAP_MDR1, 0x07);
172 serial_write_reg(p, UART_OMAP_SCR, 0x08);
173 serial_write_reg(p, UART_OMAP_MDR1, 0x00);
Juha Yrjola671c7232006-12-06 17:13:49 -0800174 serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
Tony Lindgren1dbae812005-11-10 14:26:51 +0000175}
176
Kevin Hilman4af40162009-02-04 10:51:40 -0800177#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
178
Kevin Hilman4af40162009-02-04 10:51:40 -0800179static void omap_uart_save_context(struct omap_uart_state *uart)
Jouni Hogander6e811762008-10-06 15:49:15 +0300180{
Kevin Hilman4af40162009-02-04 10:51:40 -0800181 u16 lcr = 0;
182 struct plat_serial8250_port *p = uart->p;
183
184 if (!enable_off_mode)
185 return;
186
187 lcr = serial_read_reg(p, UART_LCR);
188 serial_write_reg(p, UART_LCR, 0xBF);
189 uart->dll = serial_read_reg(p, UART_DLL);
190 uart->dlh = serial_read_reg(p, UART_DLM);
191 serial_write_reg(p, UART_LCR, lcr);
192 uart->ier = serial_read_reg(p, UART_IER);
193 uart->sysc = serial_read_reg(p, UART_OMAP_SYSC);
194 uart->scr = serial_read_reg(p, UART_OMAP_SCR);
195 uart->wer = serial_read_reg(p, UART_OMAP_WER);
196
197 uart->context_valid = 1;
198}
199
200static void omap_uart_restore_context(struct omap_uart_state *uart)
201{
202 u16 efr = 0;
203 struct plat_serial8250_port *p = uart->p;
204
205 if (!enable_off_mode)
206 return;
207
208 if (!uart->context_valid)
209 return;
210
211 uart->context_valid = 0;
212
213 serial_write_reg(p, UART_OMAP_MDR1, 0x7);
214 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
215 efr = serial_read_reg(p, UART_EFR);
216 serial_write_reg(p, UART_EFR, UART_EFR_ECB);
217 serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
218 serial_write_reg(p, UART_IER, 0x0);
219 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
220 serial_write_reg(p, UART_DLL, uart->dll);
221 serial_write_reg(p, UART_DLM, uart->dlh);
222 serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
223 serial_write_reg(p, UART_IER, uart->ier);
224 serial_write_reg(p, UART_FCR, 0xA1);
225 serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
226 serial_write_reg(p, UART_EFR, efr);
227 serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
228 serial_write_reg(p, UART_OMAP_SCR, uart->scr);
229 serial_write_reg(p, UART_OMAP_WER, uart->wer);
230 serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
231 serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
232}
233#else
234static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
235static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
236#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
237
238static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
239{
240 if (uart->clocked)
241 return;
242
243 clk_enable(uart->ick);
244 clk_enable(uart->fck);
245 uart->clocked = 1;
246 omap_uart_restore_context(uart);
247}
248
249#ifdef CONFIG_PM
250
251static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
252{
253 if (!uart->clocked)
254 return;
255
256 omap_uart_save_context(uart);
257 uart->clocked = 0;
258 clk_disable(uart->ick);
259 clk_disable(uart->fck);
260}
261
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700262static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
263{
264 /* Set wake-enable bit */
265 if (uart->wk_en && uart->wk_mask) {
266 u32 v = __raw_readl(uart->wk_en);
267 v |= uart->wk_mask;
268 __raw_writel(v, uart->wk_en);
269 }
270
271 /* Ensure IOPAD wake-enables are set */
272 if (cpu_is_omap34xx() && uart->padconf) {
273 u16 v = omap_ctrl_readw(uart->padconf);
274 v |= OMAP3_PADCONF_WAKEUPENABLE0;
275 omap_ctrl_writew(v, uart->padconf);
276 }
277}
278
279static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
280{
281 /* Clear wake-enable bit */
282 if (uart->wk_en && uart->wk_mask) {
283 u32 v = __raw_readl(uart->wk_en);
284 v &= ~uart->wk_mask;
285 __raw_writel(v, uart->wk_en);
286 }
287
288 /* Ensure IOPAD wake-enables are cleared */
289 if (cpu_is_omap34xx() && uart->padconf) {
290 u16 v = omap_ctrl_readw(uart->padconf);
291 v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
292 omap_ctrl_writew(v, uart->padconf);
293 }
294}
295
Kevin Hilman4af40162009-02-04 10:51:40 -0800296static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
297 int enable)
298{
299 struct plat_serial8250_port *p = uart->p;
300 u16 sysc;
301
302 sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
303 if (enable)
304 sysc |= 0x2 << 3;
305 else
306 sysc |= 0x1 << 3;
307
308 serial_write_reg(p, UART_OMAP_SYSC, sysc);
309}
310
311static void omap_uart_block_sleep(struct omap_uart_state *uart)
312{
313 omap_uart_enable_clocks(uart);
314
315 omap_uart_smart_idle_enable(uart, 0);
316 uart->can_sleep = 0;
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200317 if (uart->timeout)
318 mod_timer(&uart->timer, jiffies + uart->timeout);
319 else
320 del_timer(&uart->timer);
Kevin Hilman4af40162009-02-04 10:51:40 -0800321}
322
323static void omap_uart_allow_sleep(struct omap_uart_state *uart)
324{
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700325 if (device_may_wakeup(&uart->pdev.dev))
326 omap_uart_enable_wakeup(uart);
327 else
328 omap_uart_disable_wakeup(uart);
329
Kevin Hilman4af40162009-02-04 10:51:40 -0800330 if (!uart->clocked)
331 return;
332
333 omap_uart_smart_idle_enable(uart, 1);
334 uart->can_sleep = 1;
335 del_timer(&uart->timer);
336}
337
338static void omap_uart_idle_timer(unsigned long data)
339{
340 struct omap_uart_state *uart = (struct omap_uart_state *)data;
341
342 omap_uart_allow_sleep(uart);
343}
344
345void omap_uart_prepare_idle(int num)
346{
347 struct omap_uart_state *uart;
348
349 list_for_each_entry(uart, &uart_list, node) {
350 if (num == uart->num && uart->can_sleep) {
351 omap_uart_disable_clocks(uart);
352 return;
Jouni Hogander6e811762008-10-06 15:49:15 +0300353 }
354 }
355}
356
Kevin Hilman4af40162009-02-04 10:51:40 -0800357void omap_uart_resume_idle(int num)
358{
359 struct omap_uart_state *uart;
360
361 list_for_each_entry(uart, &uart_list, node) {
362 if (num == uart->num) {
363 omap_uart_enable_clocks(uart);
364
365 /* Check for IO pad wakeup */
366 if (cpu_is_omap34xx() && uart->padconf) {
367 u16 p = omap_ctrl_readw(uart->padconf);
368
369 if (p & OMAP3_PADCONF_WAKEUPEVENT0)
370 omap_uart_block_sleep(uart);
371 }
372
373 /* Check for normal UART wakeup */
374 if (__raw_readl(uart->wk_st) & uart->wk_mask)
375 omap_uart_block_sleep(uart);
Kevin Hilman4af40162009-02-04 10:51:40 -0800376 return;
377 }
378 }
379}
380
381void omap_uart_prepare_suspend(void)
382{
383 struct omap_uart_state *uart;
384
385 list_for_each_entry(uart, &uart_list, node) {
386 omap_uart_allow_sleep(uart);
387 }
388}
389
390int omap_uart_can_sleep(void)
391{
392 struct omap_uart_state *uart;
393 int can_sleep = 1;
394
395 list_for_each_entry(uart, &uart_list, node) {
396 if (!uart->clocked)
397 continue;
398
399 if (!uart->can_sleep) {
400 can_sleep = 0;
401 continue;
402 }
403
404 /* This UART can now safely sleep. */
405 omap_uart_allow_sleep(uart);
406 }
407
408 return can_sleep;
409}
410
411/**
412 * omap_uart_interrupt()
413 *
414 * This handler is used only to detect that *any* UART interrupt has
415 * occurred. It does _nothing_ to handle the interrupt. Rather,
416 * any UART interrupt will trigger the inactivity timer so the
417 * UART will not idle or sleep for its timeout period.
418 *
419 **/
420static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
421{
422 struct omap_uart_state *uart = dev_id;
423
424 omap_uart_block_sleep(uart);
425
426 return IRQ_NONE;
427}
428
429static void omap_uart_idle_init(struct omap_uart_state *uart)
430{
Kevin Hilman4af40162009-02-04 10:51:40 -0800431 struct plat_serial8250_port *p = uart->p;
432 int ret;
433
434 uart->can_sleep = 0;
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700435 uart->timeout = DEFAULT_TIMEOUT;
Kevin Hilman4af40162009-02-04 10:51:40 -0800436 setup_timer(&uart->timer, omap_uart_idle_timer,
437 (unsigned long) uart);
Tony Lindgren301fe8e2010-02-01 12:34:31 -0800438 if (uart->timeout)
439 mod_timer(&uart->timer, jiffies + uart->timeout);
Kevin Hilman4af40162009-02-04 10:51:40 -0800440 omap_uart_smart_idle_enable(uart, 0);
441
442 if (cpu_is_omap34xx()) {
443 u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
444 u32 wk_mask = 0;
445 u32 padconf = 0;
446
447 uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
448 uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
449 switch (uart->num) {
450 case 0:
451 wk_mask = OMAP3430_ST_UART1_MASK;
452 padconf = 0x182;
453 break;
454 case 1:
455 wk_mask = OMAP3430_ST_UART2_MASK;
456 padconf = 0x17a;
457 break;
458 case 2:
459 wk_mask = OMAP3430_ST_UART3_MASK;
460 padconf = 0x19e;
461 break;
462 }
463 uart->wk_mask = wk_mask;
464 uart->padconf = padconf;
465 } else if (cpu_is_omap24xx()) {
466 u32 wk_mask = 0;
467
468 if (cpu_is_omap2430()) {
469 uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
470 uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
471 } else if (cpu_is_omap2420()) {
472 uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
473 uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
474 }
475 switch (uart->num) {
476 case 0:
477 wk_mask = OMAP24XX_ST_UART1_MASK;
478 break;
479 case 1:
480 wk_mask = OMAP24XX_ST_UART2_MASK;
481 break;
482 case 2:
483 wk_mask = OMAP24XX_ST_UART3_MASK;
484 break;
485 }
486 uart->wk_mask = wk_mask;
487 } else {
488 uart->wk_en = 0;
489 uart->wk_st = 0;
490 uart->wk_mask = 0;
491 uart->padconf = 0;
492 }
493
Vikram Panditac426df82009-08-28 11:24:08 -0700494 p->irqflags |= IRQF_SHARED;
Kevin Hilman4af40162009-02-04 10:51:40 -0800495 ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
496 "serial idle", (void *)uart);
497 WARN_ON(ret);
498}
499
Tero Kristo24662112009-03-05 16:32:23 +0200500void omap_uart_enable_irqs(int enable)
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200501{
Tero Kristo24662112009-03-05 16:32:23 +0200502 int ret;
503 struct omap_uart_state *uart;
504
505 list_for_each_entry(uart, &uart_list, node) {
506 if (enable)
507 ret = request_irq(uart->p->irq, omap_uart_interrupt,
508 IRQF_SHARED, "serial idle", (void *)uart);
509 else
510 free_irq(uart->p->irq, (void *)uart);
511 }
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200512}
513
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700514static ssize_t sleep_timeout_show(struct device *dev,
515 struct device_attribute *attr,
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200516 char *buf)
517{
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700518 struct platform_device *pdev = container_of(dev,
519 struct platform_device, dev);
520 struct omap_uart_state *uart = container_of(pdev,
521 struct omap_uart_state, pdev);
522
523 return sprintf(buf, "%u\n", uart->timeout / HZ);
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200524}
525
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700526static ssize_t sleep_timeout_store(struct device *dev,
527 struct device_attribute *attr,
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200528 const char *buf, size_t n)
529{
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700530 struct platform_device *pdev = container_of(dev,
531 struct platform_device, dev);
532 struct omap_uart_state *uart = container_of(pdev,
533 struct omap_uart_state, pdev);
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200534 unsigned int value;
535
536 if (sscanf(buf, "%u", &value) != 1) {
537 printk(KERN_ERR "sleep_timeout_store: Invalid value\n");
538 return -EINVAL;
539 }
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700540
541 uart->timeout = value * HZ;
542 if (uart->timeout)
543 mod_timer(&uart->timer, jiffies + uart->timeout);
544 else
545 /* A zero value means disable timeout feature */
546 omap_uart_block_sleep(uart);
547
Jouni Hoganderba87a9b2008-12-09 13:36:50 +0200548 return n;
549}
550
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700551DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
552#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
Kevin Hilman4af40162009-02-04 10:51:40 -0800553#else
554static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700555#define DEV_CREATE_FILE(dev, attr)
Kevin Hilman4af40162009-02-04 10:51:40 -0800556#endif /* CONFIG_PM */
557
Alexander Shishkin9d30b992009-11-22 10:10:47 -0800558static struct omap_uart_state omap_uart[] = {
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700559 {
560 .pdev = {
561 .name = "serial8250",
562 .id = PLAT8250_DEV_PLATFORM,
563 .dev = {
564 .platform_data = serial_platform_data0,
565 },
566 },
567 }, {
568 .pdev = {
569 .name = "serial8250",
570 .id = PLAT8250_DEV_PLATFORM1,
571 .dev = {
572 .platform_data = serial_platform_data1,
573 },
574 },
575 }, {
576 .pdev = {
577 .name = "serial8250",
578 .id = PLAT8250_DEV_PLATFORM2,
579 .dev = {
580 .platform_data = serial_platform_data2,
581 },
582 },
Vikram Pandita2aa57be2009-05-28 14:03:59 -0700583 },
Santosh Shilimkar0e3eaad2009-08-22 13:30:11 +0530584#ifdef CONFIG_ARCH_OMAP4
585 {
586 .pdev = {
587 .name = "serial8250",
Tony Lindgren61f04ee2009-09-24 16:23:07 -0700588 .id = 3,
Santosh Shilimkar0e3eaad2009-08-22 13:30:11 +0530589 .dev = {
590 .platform_data = serial_platform_data3,
591 },
592 },
593 },
594#endif
Vikram Pandita2aa57be2009-05-28 14:03:59 -0700595};
596
vikram panditace13d472009-12-11 16:16:37 -0800597/*
598 * Override the default 8250 read handler: mem_serial_in()
599 * Empty RX fifo read causes an abort on omap3630 and omap4
600 * This function makes sure that an empty rx fifo is not read on these silicons
601 * (OMAP1/2/3430 are not affected)
602 */
603static unsigned int serial_in_override(struct uart_port *up, int offset)
604{
605 if (UART_RX == offset) {
606 unsigned int lsr;
Alexander Shishkin92303722010-01-08 10:29:06 -0800607 lsr = __serial_read_reg(up, UART_LSR);
vikram panditace13d472009-12-11 16:16:37 -0800608 if (!(lsr & UART_LSR_DR))
609 return -EPERM;
610 }
Alexander Shishkin92303722010-01-08 10:29:06 -0800611
612 return __serial_read_reg(up, offset);
vikram panditace13d472009-12-11 16:16:37 -0800613}
614
Paul Walmsleyb3c6df32009-09-03 20:14:02 +0300615void __init omap_serial_early_init(void)
Tony Lindgren1dbae812005-11-10 14:26:51 +0000616{
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700617 int i;
Jouni Hogander6e811762008-10-06 15:49:15 +0300618 char name[16];
Tony Lindgren1dbae812005-11-10 14:26:51 +0000619
620 /*
621 * Make sure the serial ports are muxed on at this point.
622 * You have to mux them off in device drivers later on
623 * if not needed.
624 */
625
Alexander Shishkin9d30b992009-11-22 10:10:47 -0800626 for (i = 0; i < ARRAY_SIZE(omap_uart); i++) {
Kevin Hilman4af40162009-02-04 10:51:40 -0800627 struct omap_uart_state *uart = &omap_uart[i];
Kevin Hilmanfd455ea2009-04-27 12:27:36 -0700628 struct platform_device *pdev = &uart->pdev;
629 struct device *dev = &pdev->dev;
630 struct plat_serial8250_port *p = dev->platform_data;
Tony Lindgren1dbae812005-11-10 14:26:51 +0000631
Tony Lindgren84f90c92009-10-16 09:53:00 -0700632 /*
633 * Module 4KB + L4 interconnect 4KB
634 * Static mapping, never released
635 */
636 p->membase = ioremap(p->mapbase, SZ_8K);
637 if (!p->membase) {
638 printk(KERN_ERR "ioremap failed for uart%i\n", i + 1);
639 continue;
640 }
641
Jouni Hogander6e811762008-10-06 15:49:15 +0300642 sprintf(name, "uart%d_ick", i+1);
Kevin Hilman4af40162009-02-04 10:51:40 -0800643 uart->ick = clk_get(NULL, name);
644 if (IS_ERR(uart->ick)) {
Jouni Hogander6e811762008-10-06 15:49:15 +0300645 printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
Kevin Hilman4af40162009-02-04 10:51:40 -0800646 uart->ick = NULL;
647 }
Tony Lindgren1dbae812005-11-10 14:26:51 +0000648
Jouni Hogander6e811762008-10-06 15:49:15 +0300649 sprintf(name, "uart%d_fck", i+1);
Kevin Hilman4af40162009-02-04 10:51:40 -0800650 uart->fck = clk_get(NULL, name);
651 if (IS_ERR(uart->fck)) {
Jouni Hogander6e811762008-10-06 15:49:15 +0300652 printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
Kevin Hilman4af40162009-02-04 10:51:40 -0800653 uart->fck = NULL;
654 }
Tony Lindgren1dbae812005-11-10 14:26:51 +0000655
Santosh Shilimkaraae290f2009-08-22 13:30:12 +0530656 /* FIXME: Remove this once the clkdev is ready */
657 if (!cpu_is_omap44xx()) {
658 if (!uart->ick || !uart->fck)
659 continue;
660 }
Kevin Hilman4af40162009-02-04 10:51:40 -0800661
662 uart->num = i;
663 p->private_data = uart;
664 uart->p = p;
Kevin Hilman4af40162009-02-04 10:51:40 -0800665
Kevin Hilman47899982009-06-24 10:32:03 -0700666 if (cpu_is_omap44xx())
667 p->irq += 32;
Paul Walmsleyb3c6df32009-09-03 20:14:02 +0300668 }
669}
670
Mika Westerbergf62349e2009-12-11 16:16:35 -0800671/**
672 * omap_serial_init_port() - initialize single serial port
673 * @port: serial port number (0-3)
674 *
675 * This function initialies serial driver for given @port only.
676 * Platforms can call this function instead of omap_serial_init()
677 * if they don't plan to use all available UARTs as serial ports.
678 *
679 * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
680 * use only one of the two.
681 */
682void __init omap_serial_init_port(int port)
683{
684 struct omap_uart_state *uart;
685 struct platform_device *pdev;
686 struct device *dev;
687
688 BUG_ON(port < 0);
689 BUG_ON(port >= ARRAY_SIZE(omap_uart));
690
691 uart = &omap_uart[port];
692 pdev = &uart->pdev;
693 dev = &pdev->dev;
694
Mika Westerbergf2eeeae2009-12-14 13:59:18 +0000695 omap_uart_enable_clocks(uart);
696
Mika Westerbergf62349e2009-12-11 16:16:35 -0800697 omap_uart_reset(uart);
698 omap_uart_idle_init(uart);
699
Mika Westerbergf2eeeae2009-12-14 13:59:18 +0000700 list_add_tail(&uart->node, &uart_list);
701
Mika Westerbergf62349e2009-12-11 16:16:35 -0800702 if (WARN_ON(platform_device_register(pdev)))
703 return;
704
705 if ((cpu_is_omap34xx() && uart->padconf) ||
706 (uart->wk_en && uart->wk_mask)) {
707 device_init_wakeup(dev, true);
708 DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
709 }
710
vikram panditace13d472009-12-11 16:16:37 -0800711 /* omap44xx: Never read empty UART fifo
712 * omap3xxx: Never read empty UART fifo on UARTs
713 * with IP rev >=0x52
714 */
715 if (cpu_is_omap44xx())
716 uart->p->serial_in = serial_in_override;
717 else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF)
718 >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
719 uart->p->serial_in = serial_in_override;
Mika Westerbergf62349e2009-12-11 16:16:35 -0800720}
721
722/**
723 * omap_serial_init() - intialize all supported serial ports
724 *
725 * Initializes all available UARTs as serial ports. Platforms
726 * can call this function when they want to have default behaviour
727 * for serial ports (e.g initialize them all as serial ports).
728 */
Paul Walmsleyb3c6df32009-09-03 20:14:02 +0300729void __init omap_serial_init(void)
730{
731 int i;
732
Mika Westerbergf62349e2009-12-11 16:16:35 -0800733 for (i = 0; i < ARRAY_SIZE(omap_uart); i++)
734 omap_serial_init_port(i);
Tony Lindgren1dbae812005-11-10 14:26:51 +0000735}