diff options
Diffstat (limited to 'drivers/serial/imx.c')
-rw-r--r-- | drivers/serial/imx.c | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4c985e6b3784..83c4c1216587 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
37 | #include <linux/console.h> | 37 | #include <linux/console.h> |
38 | #include <linux/sysrq.h> | 38 | #include <linux/sysrq.h> |
39 | #include <linux/device.h> | 39 | #include <linux/platform_device.h> |
40 | #include <linux/tty.h> | 40 | #include <linux/tty.h> |
41 | #include <linux/tty_flip.h> | 41 | #include <linux/tty_flip.h> |
42 | #include <linux/serial_core.h> | 42 | #include <linux/serial_core.h> |
@@ -73,7 +73,7 @@ struct imx_port { | |||
73 | struct uart_port port; | 73 | struct uart_port port; |
74 | struct timer_list timer; | 74 | struct timer_list timer; |
75 | unsigned int old_status; | 75 | unsigned int old_status; |
76 | int txirq,rxirq; | 76 | int txirq,rxirq,rtsirq; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | /* | 79 | /* |
@@ -181,6 +181,22 @@ static void imx_start_tx(struct uart_port *port) | |||
181 | imx_transmit_buffer(sport); | 181 | imx_transmit_buffer(sport); |
182 | } | 182 | } |
183 | 183 | ||
184 | static irqreturn_t imx_rtsint(int irq, void *dev_id, struct pt_regs *regs) | ||
185 | { | ||
186 | struct imx_port *sport = (struct imx_port *)dev_id; | ||
187 | unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS; | ||
188 | unsigned long flags; | ||
189 | |||
190 | spin_lock_irqsave(&sport->port.lock, flags); | ||
191 | |||
192 | USR1((u32)sport->port.membase) = USR1_RTSD; | ||
193 | uart_handle_cts_change(&sport->port, !!val); | ||
194 | wake_up_interruptible(&sport->port.info->delta_msr_wait); | ||
195 | |||
196 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
197 | return IRQ_HANDLED; | ||
198 | } | ||
199 | |||
184 | static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs) | 200 | static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs) |
185 | { | 201 | { |
186 | struct imx_port *sport = (struct imx_port *)dev_id; | 202 | struct imx_port *sport = (struct imx_port *)dev_id; |
@@ -383,18 +399,24 @@ static int imx_startup(struct uart_port *port) | |||
383 | */ | 399 | */ |
384 | retval = request_irq(sport->rxirq, imx_rxint, 0, | 400 | retval = request_irq(sport->rxirq, imx_rxint, 0, |
385 | DRIVER_NAME, sport); | 401 | DRIVER_NAME, sport); |
386 | if (retval) goto error_out2; | 402 | if (retval) goto error_out1; |
387 | 403 | ||
388 | retval = request_irq(sport->txirq, imx_txint, 0, | 404 | retval = request_irq(sport->txirq, imx_txint, 0, |
389 | "imx-uart", sport); | 405 | DRIVER_NAME, sport); |
390 | if (retval) goto error_out1; | 406 | if (retval) goto error_out2; |
407 | |||
408 | retval = request_irq(sport->rtsirq, imx_rtsint, 0, | ||
409 | DRIVER_NAME, sport); | ||
410 | if (retval) goto error_out3; | ||
411 | set_irq_type(sport->rtsirq, IRQT_BOTHEDGE); | ||
391 | 412 | ||
392 | /* | 413 | /* |
393 | * Finally, clear and enable interrupts | 414 | * Finally, clear and enable interrupts |
394 | */ | 415 | */ |
395 | 416 | ||
417 | USR1((u32)sport->port.membase) = USR1_RTSD; | ||
396 | UCR1((u32)sport->port.membase) |= | 418 | UCR1((u32)sport->port.membase) |= |
397 | (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN); | 419 | (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); |
398 | 420 | ||
399 | UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN); | 421 | UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN); |
400 | /* | 422 | /* |
@@ -406,10 +428,11 @@ static int imx_startup(struct uart_port *port) | |||
406 | 428 | ||
407 | return 0; | 429 | return 0; |
408 | 430 | ||
409 | error_out1: | 431 | error_out3: |
410 | free_irq(sport->rxirq, sport); | ||
411 | error_out2: | ||
412 | free_irq(sport->txirq, sport); | 432 | free_irq(sport->txirq, sport); |
433 | error_out2: | ||
434 | free_irq(sport->rxirq, sport); | ||
435 | error_out1: | ||
413 | return retval; | 436 | return retval; |
414 | } | 437 | } |
415 | 438 | ||
@@ -425,6 +448,7 @@ static void imx_shutdown(struct uart_port *port) | |||
425 | /* | 448 | /* |
426 | * Free the interrupts | 449 | * Free the interrupts |
427 | */ | 450 | */ |
451 | free_irq(sport->rtsirq, sport); | ||
428 | free_irq(sport->txirq, sport); | 452 | free_irq(sport->txirq, sport); |
429 | free_irq(sport->rxirq, sport); | 453 | free_irq(sport->rxirq, sport); |
430 | 454 | ||
@@ -433,7 +457,7 @@ static void imx_shutdown(struct uart_port *port) | |||
433 | */ | 457 | */ |
434 | 458 | ||
435 | UCR1((u32)sport->port.membase) &= | 459 | UCR1((u32)sport->port.membase) &= |
436 | ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN); | 460 | ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); |
437 | } | 461 | } |
438 | 462 | ||
439 | static void | 463 | static void |
@@ -523,7 +547,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios, | |||
523 | * disable interrupts and drain transmitter | 547 | * disable interrupts and drain transmitter |
524 | */ | 548 | */ |
525 | old_ucr1 = UCR1((u32)sport->port.membase); | 549 | old_ucr1 = UCR1((u32)sport->port.membase); |
526 | UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN); | 550 | UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); |
527 | 551 | ||
528 | while ( !(USR2((u32)sport->port.membase) & USR2_TXDC)) | 552 | while ( !(USR2((u32)sport->port.membase) & USR2_TXDC)) |
529 | barrier(); | 553 | barrier(); |
@@ -644,6 +668,7 @@ static struct imx_port imx_ports[] = { | |||
644 | { | 668 | { |
645 | .txirq = UART1_MINT_TX, | 669 | .txirq = UART1_MINT_TX, |
646 | .rxirq = UART1_MINT_RX, | 670 | .rxirq = UART1_MINT_RX, |
671 | .rtsirq = UART1_MINT_RTS, | ||
647 | .port = { | 672 | .port = { |
648 | .type = PORT_IMX, | 673 | .type = PORT_IMX, |
649 | .iotype = SERIAL_IO_MEM, | 674 | .iotype = SERIAL_IO_MEM, |
@@ -659,6 +684,7 @@ static struct imx_port imx_ports[] = { | |||
659 | }, { | 684 | }, { |
660 | .txirq = UART2_MINT_TX, | 685 | .txirq = UART2_MINT_TX, |
661 | .rxirq = UART2_MINT_RX, | 686 | .rxirq = UART2_MINT_RX, |
687 | .rtsirq = UART2_MINT_RTS, | ||
662 | .port = { | 688 | .port = { |
663 | .type = PORT_IMX, | 689 | .type = PORT_IMX, |
664 | .iotype = SERIAL_IO_MEM, | 690 | .iotype = SERIAL_IO_MEM, |
@@ -738,7 +764,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count) | |||
738 | 764 | ||
739 | UCR1((u32)sport->port.membase) = | 765 | UCR1((u32)sport->port.membase) = |
740 | (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) | 766 | (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) |
741 | & ~(UCR1_TXMPTYEN | UCR1_RRDYEN); | 767 | & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); |
742 | UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; | 768 | UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; |
743 | 769 | ||
744 | /* | 770 | /* |
@@ -860,7 +886,7 @@ imx_console_setup(struct console *co, char *options) | |||
860 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); | 886 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); |
861 | } | 887 | } |
862 | 888 | ||
863 | extern struct uart_driver imx_reg; | 889 | static struct uart_driver imx_reg; |
864 | static struct console imx_console = { | 890 | static struct console imx_console = { |
865 | .name = "ttySMX", | 891 | .name = "ttySMX", |
866 | .write = imx_console_write, | 892 | .write = imx_console_write, |
@@ -895,41 +921,39 @@ static struct uart_driver imx_reg = { | |||
895 | .cons = IMX_CONSOLE, | 921 | .cons = IMX_CONSOLE, |
896 | }; | 922 | }; |
897 | 923 | ||
898 | static int serial_imx_suspend(struct device *_dev, pm_message_t state, u32 level) | 924 | static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) |
899 | { | 925 | { |
900 | struct imx_port *sport = dev_get_drvdata(_dev); | 926 | struct imx_port *sport = platform_get_drvdata(dev); |
901 | 927 | ||
902 | if (sport && level == SUSPEND_DISABLE) | 928 | if (sport) |
903 | uart_suspend_port(&imx_reg, &sport->port); | 929 | uart_suspend_port(&imx_reg, &sport->port); |
904 | 930 | ||
905 | return 0; | 931 | return 0; |
906 | } | 932 | } |
907 | 933 | ||
908 | static int serial_imx_resume(struct device *_dev, u32 level) | 934 | static int serial_imx_resume(struct platform_device *dev) |
909 | { | 935 | { |
910 | struct imx_port *sport = dev_get_drvdata(_dev); | 936 | struct imx_port *sport = platform_get_drvdata(dev); |
911 | 937 | ||
912 | if (sport && level == RESUME_ENABLE) | 938 | if (sport) |
913 | uart_resume_port(&imx_reg, &sport->port); | 939 | uart_resume_port(&imx_reg, &sport->port); |
914 | 940 | ||
915 | return 0; | 941 | return 0; |
916 | } | 942 | } |
917 | 943 | ||
918 | static int serial_imx_probe(struct device *_dev) | 944 | static int serial_imx_probe(struct platform_device *dev) |
919 | { | 945 | { |
920 | struct platform_device *dev = to_platform_device(_dev); | 946 | imx_ports[dev->id].port.dev = &dev->dev; |
921 | |||
922 | imx_ports[dev->id].port.dev = _dev; | ||
923 | uart_add_one_port(&imx_reg, &imx_ports[dev->id].port); | 947 | uart_add_one_port(&imx_reg, &imx_ports[dev->id].port); |
924 | dev_set_drvdata(_dev, &imx_ports[dev->id]); | 948 | platform_set_drvdata(dev, &imx_ports[dev->id]); |
925 | return 0; | 949 | return 0; |
926 | } | 950 | } |
927 | 951 | ||
928 | static int serial_imx_remove(struct device *_dev) | 952 | static int serial_imx_remove(struct platform_device *dev) |
929 | { | 953 | { |
930 | struct imx_port *sport = dev_get_drvdata(_dev); | 954 | struct imx_port *sport = platform_get_drvdata(dev); |
931 | 955 | ||
932 | dev_set_drvdata(_dev, NULL); | 956 | platform_set_drvdata(dev, NULL); |
933 | 957 | ||
934 | if (sport) | 958 | if (sport) |
935 | uart_remove_one_port(&imx_reg, &sport->port); | 959 | uart_remove_one_port(&imx_reg, &sport->port); |
@@ -937,14 +961,15 @@ static int serial_imx_remove(struct device *_dev) | |||
937 | return 0; | 961 | return 0; |
938 | } | 962 | } |
939 | 963 | ||
940 | static struct device_driver serial_imx_driver = { | 964 | static struct platform_driver serial_imx_driver = { |
941 | .name = "imx-uart", | ||
942 | .bus = &platform_bus_type, | ||
943 | .probe = serial_imx_probe, | 965 | .probe = serial_imx_probe, |
944 | .remove = serial_imx_remove, | 966 | .remove = serial_imx_remove, |
945 | 967 | ||
946 | .suspend = serial_imx_suspend, | 968 | .suspend = serial_imx_suspend, |
947 | .resume = serial_imx_resume, | 969 | .resume = serial_imx_resume, |
970 | .driver = { | ||
971 | .name = "imx-uart", | ||
972 | }, | ||
948 | }; | 973 | }; |
949 | 974 | ||
950 | static int __init imx_serial_init(void) | 975 | static int __init imx_serial_init(void) |
@@ -959,7 +984,7 @@ static int __init imx_serial_init(void) | |||
959 | if (ret) | 984 | if (ret) |
960 | return ret; | 985 | return ret; |
961 | 986 | ||
962 | ret = driver_register(&serial_imx_driver); | 987 | ret = platform_driver_register(&serial_imx_driver); |
963 | if (ret != 0) | 988 | if (ret != 0) |
964 | uart_unregister_driver(&imx_reg); | 989 | uart_unregister_driver(&imx_reg); |
965 | 990 | ||
@@ -969,6 +994,7 @@ static int __init imx_serial_init(void) | |||
969 | static void __exit imx_serial_exit(void) | 994 | static void __exit imx_serial_exit(void) |
970 | { | 995 | { |
971 | uart_unregister_driver(&imx_reg); | 996 | uart_unregister_driver(&imx_reg); |
997 | platform_driver_unregister(&serial_imx_driver); | ||
972 | } | 998 | } |
973 | 999 | ||
974 | module_init(imx_serial_init); | 1000 | module_init(imx_serial_init); |