aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/serial.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-09-12 07:02:26 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-09-12 07:02:26 -0400
commitddd559b13f6d2fe3ad68c4b3f5235fd3c2eae4e3 (patch)
treed827bca3fc825a0ac33efbcd493713be40fcc812 /arch/arm/mach-omap2/serial.c
parentcf7a2b4fb6a9b86779930a0a123b0df41aa9208f (diff)
parentf17a1f06d2fa93f4825be572622eb02c4894db4e (diff)
Merge branch 'devel-stable' into devel
Conflicts: MAINTAINERS arch/arm/mm/fault.c
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
-rw-r--r--arch/arm/mach-omap2/serial.c207
1 files changed, 144 insertions, 63 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index b094c15bfe47..ce22344b94e7 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -54,6 +54,7 @@ struct omap_uart_state {
54 54
55 struct plat_serial8250_port *p; 55 struct plat_serial8250_port *p;
56 struct list_head node; 56 struct list_head node;
57 struct platform_device pdev;
57 58
58#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) 59#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
59 int context_valid; 60 int context_valid;
@@ -68,10 +69,9 @@ struct omap_uart_state {
68#endif 69#endif
69}; 70};
70 71
71static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS];
72static LIST_HEAD(uart_list); 72static LIST_HEAD(uart_list);
73 73
74static struct plat_serial8250_port serial_platform_data[] = { 74static struct plat_serial8250_port serial_platform_data0[] = {
75 { 75 {
76 .membase = IO_ADDRESS(OMAP_UART1_BASE), 76 .membase = IO_ADDRESS(OMAP_UART1_BASE),
77 .mapbase = OMAP_UART1_BASE, 77 .mapbase = OMAP_UART1_BASE,
@@ -81,6 +81,12 @@ static struct plat_serial8250_port serial_platform_data[] = {
81 .regshift = 2, 81 .regshift = 2,
82 .uartclk = OMAP24XX_BASE_BAUD * 16, 82 .uartclk = OMAP24XX_BASE_BAUD * 16,
83 }, { 83 }, {
84 .flags = 0
85 }
86};
87
88static struct plat_serial8250_port serial_platform_data1[] = {
89 {
84 .membase = IO_ADDRESS(OMAP_UART2_BASE), 90 .membase = IO_ADDRESS(OMAP_UART2_BASE),
85 .mapbase = OMAP_UART2_BASE, 91 .mapbase = OMAP_UART2_BASE,
86 .irq = 73, 92 .irq = 73,
@@ -89,6 +95,12 @@ static struct plat_serial8250_port serial_platform_data[] = {
89 .regshift = 2, 95 .regshift = 2,
90 .uartclk = OMAP24XX_BASE_BAUD * 16, 96 .uartclk = OMAP24XX_BASE_BAUD * 16,
91 }, { 97 }, {
98 .flags = 0
99 }
100};
101
102static struct plat_serial8250_port serial_platform_data2[] = {
103 {
92 .membase = IO_ADDRESS(OMAP_UART3_BASE), 104 .membase = IO_ADDRESS(OMAP_UART3_BASE),
93 .mapbase = OMAP_UART3_BASE, 105 .mapbase = OMAP_UART3_BASE,
94 .irq = 74, 106 .irq = 74,
@@ -97,6 +109,16 @@ static struct plat_serial8250_port serial_platform_data[] = {
97 .regshift = 2, 109 .regshift = 2,
98 .uartclk = OMAP24XX_BASE_BAUD * 16, 110 .uartclk = OMAP24XX_BASE_BAUD * 16,
99 }, { 111 }, {
112#ifdef CONFIG_ARCH_OMAP4
113 .membase = IO_ADDRESS(OMAP_UART4_BASE),
114 .mapbase = OMAP_UART4_BASE,
115 .irq = 70,
116 .flags = UPF_BOOT_AUTOCONF,
117 .iotype = UPIO_MEM,
118 .regshift = 2,
119 .uartclk = OMAP24XX_BASE_BAUD * 16,
120 }, {
121#endif
100 .flags = 0 122 .flags = 0
101 } 123 }
102}; 124};
@@ -217,6 +239,40 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
217 clk_disable(uart->fck); 239 clk_disable(uart->fck);
218} 240}
219 241
242static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
243{
244 /* Set wake-enable bit */
245 if (uart->wk_en && uart->wk_mask) {
246 u32 v = __raw_readl(uart->wk_en);
247 v |= uart->wk_mask;
248 __raw_writel(v, uart->wk_en);
249 }
250
251 /* Ensure IOPAD wake-enables are set */
252 if (cpu_is_omap34xx() && uart->padconf) {
253 u16 v = omap_ctrl_readw(uart->padconf);
254 v |= OMAP3_PADCONF_WAKEUPENABLE0;
255 omap_ctrl_writew(v, uart->padconf);
256 }
257}
258
259static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
260{
261 /* Clear wake-enable bit */
262 if (uart->wk_en && uart->wk_mask) {
263 u32 v = __raw_readl(uart->wk_en);
264 v &= ~uart->wk_mask;
265 __raw_writel(v, uart->wk_en);
266 }
267
268 /* Ensure IOPAD wake-enables are cleared */
269 if (cpu_is_omap34xx() && uart->padconf) {
270 u16 v = omap_ctrl_readw(uart->padconf);
271 v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
272 omap_ctrl_writew(v, uart->padconf);
273 }
274}
275
220static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, 276static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
221 int enable) 277 int enable)
222{ 278{
@@ -246,6 +302,11 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
246 302
247static void omap_uart_allow_sleep(struct omap_uart_state *uart) 303static void omap_uart_allow_sleep(struct omap_uart_state *uart)
248{ 304{
305 if (device_may_wakeup(&uart->pdev.dev))
306 omap_uart_enable_wakeup(uart);
307 else
308 omap_uart_disable_wakeup(uart);
309
249 if (!uart->clocked) 310 if (!uart->clocked)
250 return; 311 return;
251 312
@@ -292,7 +353,6 @@ void omap_uart_resume_idle(int num)
292 /* Check for normal UART wakeup */ 353 /* Check for normal UART wakeup */
293 if (__raw_readl(uart->wk_st) & uart->wk_mask) 354 if (__raw_readl(uart->wk_st) & uart->wk_mask)
294 omap_uart_block_sleep(uart); 355 omap_uart_block_sleep(uart);
295
296 return; 356 return;
297 } 357 }
298 } 358 }
@@ -346,16 +406,13 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
346 return IRQ_NONE; 406 return IRQ_NONE;
347} 407}
348 408
349static u32 sleep_timeout = DEFAULT_TIMEOUT;
350
351static void omap_uart_idle_init(struct omap_uart_state *uart) 409static void omap_uart_idle_init(struct omap_uart_state *uart)
352{ 410{
353 u32 v;
354 struct plat_serial8250_port *p = uart->p; 411 struct plat_serial8250_port *p = uart->p;
355 int ret; 412 int ret;
356 413
357 uart->can_sleep = 0; 414 uart->can_sleep = 0;
358 uart->timeout = sleep_timeout; 415 uart->timeout = DEFAULT_TIMEOUT;
359 setup_timer(&uart->timer, omap_uart_idle_timer, 416 setup_timer(&uart->timer, omap_uart_idle_timer,
360 (unsigned long) uart); 417 (unsigned long) uart);
361 mod_timer(&uart->timer, jiffies + uart->timeout); 418 mod_timer(&uart->timer, jiffies + uart->timeout);
@@ -413,76 +470,101 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
413 uart->padconf = 0; 470 uart->padconf = 0;
414 } 471 }
415 472
416 /* Set wake-enable bit */
417 if (uart->wk_en && uart->wk_mask) {
418 v = __raw_readl(uart->wk_en);
419 v |= uart->wk_mask;
420 __raw_writel(v, uart->wk_en);
421 }
422
423 /* Ensure IOPAD wake-enables are set */
424 if (cpu_is_omap34xx() && uart->padconf) {
425 u16 v;
426
427 v = omap_ctrl_readw(uart->padconf);
428 v |= OMAP3_PADCONF_WAKEUPENABLE0;
429 omap_ctrl_writew(v, uart->padconf);
430 }
431
432 p->flags |= UPF_SHARE_IRQ; 473 p->flags |= UPF_SHARE_IRQ;
433 ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, 474 ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
434 "serial idle", (void *)uart); 475 "serial idle", (void *)uart);
435 WARN_ON(ret); 476 WARN_ON(ret);
436} 477}
437 478
438static ssize_t sleep_timeout_show(struct kobject *kobj, 479void omap_uart_enable_irqs(int enable)
439 struct kobj_attribute *attr, 480{
481 int ret;
482 struct omap_uart_state *uart;
483
484 list_for_each_entry(uart, &uart_list, node) {
485 if (enable)
486 ret = request_irq(uart->p->irq, omap_uart_interrupt,
487 IRQF_SHARED, "serial idle", (void *)uart);
488 else
489 free_irq(uart->p->irq, (void *)uart);
490 }
491}
492
493static ssize_t sleep_timeout_show(struct device *dev,
494 struct device_attribute *attr,
440 char *buf) 495 char *buf)
441{ 496{
442 return sprintf(buf, "%u\n", sleep_timeout / HZ); 497 struct platform_device *pdev = container_of(dev,
498 struct platform_device, dev);
499 struct omap_uart_state *uart = container_of(pdev,
500 struct omap_uart_state, pdev);
501
502 return sprintf(buf, "%u\n", uart->timeout / HZ);
443} 503}
444 504
445static ssize_t sleep_timeout_store(struct kobject *kobj, 505static ssize_t sleep_timeout_store(struct device *dev,
446 struct kobj_attribute *attr, 506 struct device_attribute *attr,
447 const char *buf, size_t n) 507 const char *buf, size_t n)
448{ 508{
449 struct omap_uart_state *uart; 509 struct platform_device *pdev = container_of(dev,
510 struct platform_device, dev);
511 struct omap_uart_state *uart = container_of(pdev,
512 struct omap_uart_state, pdev);
450 unsigned int value; 513 unsigned int value;
451 514
452 if (sscanf(buf, "%u", &value) != 1) { 515 if (sscanf(buf, "%u", &value) != 1) {
453 printk(KERN_ERR "sleep_timeout_store: Invalid value\n"); 516 printk(KERN_ERR "sleep_timeout_store: Invalid value\n");
454 return -EINVAL; 517 return -EINVAL;
455 } 518 }
456 sleep_timeout = value * HZ; 519
457 list_for_each_entry(uart, &uart_list, node) { 520 uart->timeout = value * HZ;
458 uart->timeout = sleep_timeout; 521 if (uart->timeout)
459 if (uart->timeout) 522 mod_timer(&uart->timer, jiffies + uart->timeout);
460 mod_timer(&uart->timer, jiffies + uart->timeout); 523 else
461 else 524 /* A zero value means disable timeout feature */
462 /* A zero value means disable timeout feature */ 525 omap_uart_block_sleep(uart);
463 omap_uart_block_sleep(uart); 526
464 }
465 return n; 527 return n;
466} 528}
467 529
468static struct kobj_attribute sleep_timeout_attr = 530DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
469 __ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store); 531#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
470
471#else 532#else
472static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} 533static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
534#define DEV_CREATE_FILE(dev, attr)
473#endif /* CONFIG_PM */ 535#endif /* CONFIG_PM */
474 536
475static struct platform_device serial_device = { 537static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
476 .name = "serial8250", 538 {
477 .id = PLAT8250_DEV_PLATFORM, 539 .pdev = {
478 .dev = { 540 .name = "serial8250",
479 .platform_data = serial_platform_data, 541 .id = PLAT8250_DEV_PLATFORM,
542 .dev = {
543 .platform_data = serial_platform_data0,
544 },
545 },
546 }, {
547 .pdev = {
548 .name = "serial8250",
549 .id = PLAT8250_DEV_PLATFORM1,
550 .dev = {
551 .platform_data = serial_platform_data1,
552 },
553 },
554 }, {
555 .pdev = {
556 .name = "serial8250",
557 .id = PLAT8250_DEV_PLATFORM2,
558 .dev = {
559 .platform_data = serial_platform_data2,
560 },
561 },
480 }, 562 },
481}; 563};
482 564
483void __init omap_serial_init(void) 565void __init omap_serial_init(void)
484{ 566{
485 int i, err; 567 int i;
486 const struct omap_uart_config *info; 568 const struct omap_uart_config *info;
487 char name[16]; 569 char name[16];
488 570
@@ -496,14 +578,12 @@ void __init omap_serial_init(void)
496 578
497 if (info == NULL) 579 if (info == NULL)
498 return; 580 return;
499 if (cpu_is_omap44xx()) {
500 for (i = 0; i < OMAP_MAX_NR_PORTS; i++)
501 serial_platform_data[i].irq += 32;
502 }
503 581
504 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { 582 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
505 struct plat_serial8250_port *p = serial_platform_data + i;
506 struct omap_uart_state *uart = &omap_uart[i]; 583 struct omap_uart_state *uart = &omap_uart[i];
584 struct platform_device *pdev = &uart->pdev;
585 struct device *dev = &pdev->dev;
586 struct plat_serial8250_port *p = dev->platform_data;
507 587
508 if (!(info->enabled_uarts & (1 << i))) { 588 if (!(info->enabled_uarts & (1 << i))) {
509 p->membase = NULL; 589 p->membase = NULL;
@@ -531,20 +611,21 @@ void __init omap_serial_init(void)
531 uart->num = i; 611 uart->num = i;
532 p->private_data = uart; 612 p->private_data = uart;
533 uart->p = p; 613 uart->p = p;
534 list_add(&uart->node, &uart_list); 614 list_add_tail(&uart->node, &uart_list);
615
616 if (cpu_is_omap44xx())
617 p->irq += 32;
535 618
536 omap_uart_enable_clocks(uart); 619 omap_uart_enable_clocks(uart);
537 omap_uart_reset(uart); 620 omap_uart_reset(uart);
538 omap_uart_idle_init(uart); 621 omap_uart_idle_init(uart);
539 }
540
541 err = platform_device_register(&serial_device);
542
543#ifdef CONFIG_PM
544 if (!err)
545 err = sysfs_create_file(&serial_device.dev.kobj,
546 &sleep_timeout_attr.attr);
547#endif
548 622
623 if (WARN_ON(platform_device_register(pdev)))
624 continue;
625 if ((cpu_is_omap34xx() && uart->padconf) ||
626 (uart->wk_en && uart->wk_mask)) {
627 device_init_wakeup(dev, true);
628 DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
629 }
630 }
549} 631}
550