diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
commit | 7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch) | |
tree | e730a4565e0318140d2fbd2f0415d18a339d7336 /drivers/serial/atmel_serial.c | |
parent | 41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff) | |
parent | 0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff) |
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'drivers/serial/atmel_serial.c')
-rw-r--r-- | drivers/serial/atmel_serial.c | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 6aeef22bd203..61fb8b6d19af 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
@@ -42,11 +42,11 @@ | |||
42 | #include <asm/io.h> | 42 | #include <asm/io.h> |
43 | 43 | ||
44 | #include <asm/mach/serial_at91.h> | 44 | #include <asm/mach/serial_at91.h> |
45 | #include <asm/arch/board.h> | 45 | #include <mach/board.h> |
46 | 46 | ||
47 | #ifdef CONFIG_ARM | 47 | #ifdef CONFIG_ARM |
48 | #include <asm/arch/cpu.h> | 48 | #include <mach/cpu.h> |
49 | #include <asm/arch/gpio.h> | 49 | #include <mach/gpio.h> |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #define PDC_BUFFER_SIZE 512 | 52 | #define PDC_BUFFER_SIZE 512 |
@@ -131,7 +131,8 @@ struct atmel_uart_char { | |||
131 | struct atmel_uart_port { | 131 | struct atmel_uart_port { |
132 | struct uart_port uart; /* uart */ | 132 | struct uart_port uart; /* uart */ |
133 | struct clk *clk; /* uart clock */ | 133 | struct clk *clk; /* uart clock */ |
134 | unsigned short suspended; /* is port suspended? */ | 134 | int may_wakeup; /* cached value of device_may_wakeup for times we need to disable it */ |
135 | u32 backup_imr; /* IMR saved during suspend */ | ||
135 | int break_active; /* break being received */ | 136 | int break_active; /* break being received */ |
136 | 137 | ||
137 | short use_dma_rx; /* enable PDC receiver */ | 138 | short use_dma_rx; /* enable PDC receiver */ |
@@ -662,14 +663,14 @@ static void atmel_rx_from_ring(struct uart_port *port) | |||
662 | * uart_start(), which takes the lock. | 663 | * uart_start(), which takes the lock. |
663 | */ | 664 | */ |
664 | spin_unlock(&port->lock); | 665 | spin_unlock(&port->lock); |
665 | tty_flip_buffer_push(port->info->tty); | 666 | tty_flip_buffer_push(port->info->port.tty); |
666 | spin_lock(&port->lock); | 667 | spin_lock(&port->lock); |
667 | } | 668 | } |
668 | 669 | ||
669 | static void atmel_rx_from_dma(struct uart_port *port) | 670 | static void atmel_rx_from_dma(struct uart_port *port) |
670 | { | 671 | { |
671 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 672 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
672 | struct tty_struct *tty = port->info->tty; | 673 | struct tty_struct *tty = port->info->port.tty; |
673 | struct atmel_dma_buffer *pdc; | 674 | struct atmel_dma_buffer *pdc; |
674 | int rx_idx = atmel_port->pdc_rx_idx; | 675 | int rx_idx = atmel_port->pdc_rx_idx; |
675 | unsigned int head; | 676 | unsigned int head; |
@@ -794,7 +795,7 @@ static void atmel_tasklet_func(unsigned long data) | |||
794 | static int atmel_startup(struct uart_port *port) | 795 | static int atmel_startup(struct uart_port *port) |
795 | { | 796 | { |
796 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 797 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
797 | struct tty_struct *tty = port->info->tty; | 798 | struct tty_struct *tty = port->info->port.tty; |
798 | int retval; | 799 | int retval; |
799 | 800 | ||
800 | /* | 801 | /* |
@@ -956,6 +957,20 @@ static void atmel_shutdown(struct uart_port *port) | |||
956 | } | 957 | } |
957 | 958 | ||
958 | /* | 959 | /* |
960 | * Flush any TX data submitted for DMA. Called when the TX circular | ||
961 | * buffer is reset. | ||
962 | */ | ||
963 | static void atmel_flush_buffer(struct uart_port *port) | ||
964 | { | ||
965 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
966 | |||
967 | if (atmel_use_dma_tx(port)) { | ||
968 | UART_PUT_TCR(port, 0); | ||
969 | atmel_port->pdc_tx.ofs = 0; | ||
970 | } | ||
971 | } | ||
972 | |||
973 | /* | ||
959 | * Power / Clock management. | 974 | * Power / Clock management. |
960 | */ | 975 | */ |
961 | static void atmel_serial_pm(struct uart_port *port, unsigned int state, | 976 | static void atmel_serial_pm(struct uart_port *port, unsigned int state, |
@@ -970,8 +985,15 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, | |||
970 | * This is called on uart_open() or a resume event. | 985 | * This is called on uart_open() or a resume event. |
971 | */ | 986 | */ |
972 | clk_enable(atmel_port->clk); | 987 | clk_enable(atmel_port->clk); |
988 | |||
989 | /* re-enable interrupts if we disabled some on suspend */ | ||
990 | UART_PUT_IER(port, atmel_port->backup_imr); | ||
973 | break; | 991 | break; |
974 | case 3: | 992 | case 3: |
993 | /* Back up the interrupt mask and disable all interrupts */ | ||
994 | atmel_port->backup_imr = UART_GET_IMR(port); | ||
995 | UART_PUT_IDR(port, -1); | ||
996 | |||
975 | /* | 997 | /* |
976 | * Disable the peripheral clock for this serial port. | 998 | * Disable the peripheral clock for this serial port. |
977 | * This is called on uart_close() or a suspend event. | 999 | * This is called on uart_close() or a suspend event. |
@@ -1189,6 +1211,7 @@ static struct uart_ops atmel_pops = { | |||
1189 | .break_ctl = atmel_break_ctl, | 1211 | .break_ctl = atmel_break_ctl, |
1190 | .startup = atmel_startup, | 1212 | .startup = atmel_startup, |
1191 | .shutdown = atmel_shutdown, | 1213 | .shutdown = atmel_shutdown, |
1214 | .flush_buffer = atmel_flush_buffer, | ||
1192 | .set_termios = atmel_set_termios, | 1215 | .set_termios = atmel_set_termios, |
1193 | .type = atmel_type, | 1216 | .type = atmel_type, |
1194 | .release_port = atmel_release_port, | 1217 | .release_port = atmel_release_port, |
@@ -1460,13 +1483,12 @@ static int atmel_serial_suspend(struct platform_device *pdev, | |||
1460 | cpu_relax(); | 1483 | cpu_relax(); |
1461 | } | 1484 | } |
1462 | 1485 | ||
1463 | if (device_may_wakeup(&pdev->dev) | 1486 | /* we can not wake up if we're running on slow clock */ |
1464 | && !atmel_serial_clk_will_stop()) | 1487 | atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); |
1465 | enable_irq_wake(port->irq); | 1488 | if (atmel_serial_clk_will_stop()) |
1466 | else { | 1489 | device_set_wakeup_enable(&pdev->dev, 0); |
1467 | uart_suspend_port(&atmel_uart, port); | 1490 | |
1468 | atmel_port->suspended = 1; | 1491 | uart_suspend_port(&atmel_uart, port); |
1469 | } | ||
1470 | 1492 | ||
1471 | return 0; | 1493 | return 0; |
1472 | } | 1494 | } |
@@ -1476,11 +1498,8 @@ static int atmel_serial_resume(struct platform_device *pdev) | |||
1476 | struct uart_port *port = platform_get_drvdata(pdev); | 1498 | struct uart_port *port = platform_get_drvdata(pdev); |
1477 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 1499 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
1478 | 1500 | ||
1479 | if (atmel_port->suspended) { | 1501 | uart_resume_port(&atmel_uart, port); |
1480 | uart_resume_port(&atmel_uart, port); | 1502 | device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup); |
1481 | atmel_port->suspended = 0; | ||
1482 | } else | ||
1483 | disable_irq_wake(port->irq); | ||
1484 | 1503 | ||
1485 | return 0; | 1504 | return 0; |
1486 | } | 1505 | } |
@@ -1498,6 +1517,8 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) | |||
1498 | BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE)); | 1517 | BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE)); |
1499 | 1518 | ||
1500 | port = &atmel_ports[pdev->id]; | 1519 | port = &atmel_ports[pdev->id]; |
1520 | port->backup_imr = 0; | ||
1521 | |||
1501 | atmel_init_port(port, pdev); | 1522 | atmel_init_port(port, pdev); |
1502 | 1523 | ||
1503 | if (!atmel_use_dma_rx(&port->uart)) { | 1524 | if (!atmel_use_dma_rx(&port->uart)) { |