aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/serial.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-08-05 17:10:52 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-08-05 17:10:52 -0400
commit13efdbecc65ef6ec4028551fb223dea5c5e3143c (patch)
tree634a2ce082abe3eb2a5defe0f1ddc2f3eb10f085 /arch/arm/mach-omap2/serial.c
parent61f4a10cb4e9447a85245c63b3e7f46e09299fed (diff)
parent6fd210a9cc398ecbff7bcdbe220651b73b654f56 (diff)
Merge branch 'pm-upstream/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into devel-stable
Diffstat (limited to 'arch/arm/mach-omap2/serial.c')
-rw-r--r--arch/arm/mach-omap2/serial.c197
1 files changed, 134 insertions, 63 deletions
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index c0bea75f13f8..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,
@@ -227,6 +239,40 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
227 clk_disable(uart->fck); 239 clk_disable(uart->fck);
228} 240}
229 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
230static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, 276static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
231 int enable) 277 int enable)
232{ 278{
@@ -256,6 +302,11 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
256 302
257static void omap_uart_allow_sleep(struct omap_uart_state *uart) 303static void omap_uart_allow_sleep(struct omap_uart_state *uart)
258{ 304{
305 if (device_may_wakeup(&uart->pdev.dev))
306 omap_uart_enable_wakeup(uart);
307 else
308 omap_uart_disable_wakeup(uart);
309
259 if (!uart->clocked) 310 if (!uart->clocked)
260 return; 311 return;
261 312
@@ -302,7 +353,6 @@ void omap_uart_resume_idle(int num)
302 /* Check for normal UART wakeup */ 353 /* Check for normal UART wakeup */
303 if (__raw_readl(uart->wk_st) & uart->wk_mask) 354 if (__raw_readl(uart->wk_st) & uart->wk_mask)
304 omap_uart_block_sleep(uart); 355 omap_uart_block_sleep(uart);
305
306 return; 356 return;
307 } 357 }
308 } 358 }
@@ -356,16 +406,13 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
356 return IRQ_NONE; 406 return IRQ_NONE;
357} 407}
358 408
359static u32 sleep_timeout = DEFAULT_TIMEOUT;
360
361static void omap_uart_idle_init(struct omap_uart_state *uart) 409static void omap_uart_idle_init(struct omap_uart_state *uart)
362{ 410{
363 u32 v;
364 struct plat_serial8250_port *p = uart->p; 411 struct plat_serial8250_port *p = uart->p;
365 int ret; 412 int ret;
366 413
367 uart->can_sleep = 0; 414 uart->can_sleep = 0;
368 uart->timeout = sleep_timeout; 415 uart->timeout = DEFAULT_TIMEOUT;
369 setup_timer(&uart->timer, omap_uart_idle_timer, 416 setup_timer(&uart->timer, omap_uart_idle_timer,
370 (unsigned long) uart); 417 (unsigned long) uart);
371 mod_timer(&uart->timer, jiffies + uart->timeout); 418 mod_timer(&uart->timer, jiffies + uart->timeout);
@@ -423,76 +470,101 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
423 uart->padconf = 0; 470 uart->padconf = 0;
424 } 471 }
425 472
426 /* Set wake-enable bit */
427 if (uart->wk_en && uart->wk_mask) {
428 v = __raw_readl(uart->wk_en);
429 v |= uart->wk_mask;
430 __raw_writel(v, uart->wk_en);
431 }
432
433 /* Ensure IOPAD wake-enables are set */
434 if (cpu_is_omap34xx() && uart->padconf) {
435 u16 v;
436
437 v = omap_ctrl_readw(uart->padconf);
438 v |= OMAP3_PADCONF_WAKEUPENABLE0;
439 omap_ctrl_writew(v, uart->padconf);
440 }
441
442 p->flags |= UPF_SHARE_IRQ; 473 p->flags |= UPF_SHARE_IRQ;
443 ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, 474 ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
444 "serial idle", (void *)uart); 475 "serial idle", (void *)uart);
445 WARN_ON(ret); 476 WARN_ON(ret);
446} 477}
447 478
448static ssize_t sleep_timeout_show(struct kobject *kobj, 479void omap_uart_enable_irqs(int enable)
449 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,
450 char *buf) 495 char *buf)
451{ 496{
452 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);
453} 503}
454 504
455static ssize_t sleep_timeout_store(struct kobject *kobj, 505static ssize_t sleep_timeout_store(struct device *dev,
456 struct kobj_attribute *attr, 506 struct device_attribute *attr,
457 const char *buf, size_t n) 507 const char *buf, size_t n)
458{ 508{
459 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);
460 unsigned int value; 513 unsigned int value;
461 514
462 if (sscanf(buf, "%u", &value) != 1) { 515 if (sscanf(buf, "%u", &value) != 1) {
463 printk(KERN_ERR "sleep_timeout_store: Invalid value\n"); 516 printk(KERN_ERR "sleep_timeout_store: Invalid value\n");
464 return -EINVAL; 517 return -EINVAL;
465 } 518 }
466 sleep_timeout = value * HZ; 519
467 list_for_each_entry(uart, &uart_list, node) { 520 uart->timeout = value * HZ;
468 uart->timeout = sleep_timeout; 521 if (uart->timeout)
469 if (uart->timeout) 522 mod_timer(&uart->timer, jiffies + uart->timeout);
470 mod_timer(&uart->timer, jiffies + uart->timeout); 523 else
471 else 524 /* A zero value means disable timeout feature */
472 /* A zero value means disable timeout feature */ 525 omap_uart_block_sleep(uart);
473 omap_uart_block_sleep(uart); 526
474 }
475 return n; 527 return n;
476} 528}
477 529
478static struct kobj_attribute sleep_timeout_attr = 530DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
479 __ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store); 531#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
480
481#else 532#else
482static 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)
483#endif /* CONFIG_PM */ 535#endif /* CONFIG_PM */
484 536
485static struct platform_device serial_device = { 537static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
486 .name = "serial8250", 538 {
487 .id = PLAT8250_DEV_PLATFORM, 539 .pdev = {
488 .dev = { 540 .name = "serial8250",
489 .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 },
490 }, 562 },
491}; 563};
492 564
493void __init omap_serial_init(void) 565void __init omap_serial_init(void)
494{ 566{
495 int i, err; 567 int i;
496 const struct omap_uart_config *info; 568 const struct omap_uart_config *info;
497 char name[16]; 569 char name[16];
498 570
@@ -506,14 +578,12 @@ void __init omap_serial_init(void)
506 578
507 if (info == NULL) 579 if (info == NULL)
508 return; 580 return;
509 if (cpu_is_omap44xx()) {
510 for (i = 0; i < OMAP_MAX_NR_PORTS; i++)
511 serial_platform_data[i].irq += 32;
512 }
513 581
514 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { 582 for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
515 struct plat_serial8250_port *p = serial_platform_data + i;
516 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;
517 587
518 if (!(info->enabled_uarts & (1 << i))) { 588 if (!(info->enabled_uarts & (1 << i))) {
519 p->membase = NULL; 589 p->membase = NULL;
@@ -541,20 +611,21 @@ void __init omap_serial_init(void)
541 uart->num = i; 611 uart->num = i;
542 p->private_data = uart; 612 p->private_data = uart;
543 uart->p = p; 613 uart->p = p;
544 list_add(&uart->node, &uart_list); 614 list_add_tail(&uart->node, &uart_list);
615
616 if (cpu_is_omap44xx())
617 p->irq += 32;
545 618
546 omap_uart_enable_clocks(uart); 619 omap_uart_enable_clocks(uart);
547 omap_uart_reset(uart); 620 omap_uart_reset(uart);
548 omap_uart_idle_init(uart); 621 omap_uart_idle_init(uart);
549 }
550
551 err = platform_device_register(&serial_device);
552
553#ifdef CONFIG_PM
554 if (!err)
555 err = sysfs_create_file(&serial_device.dev.kobj,
556 &sleep_timeout_attr.attr);
557#endif
558 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 }
559} 631}
560