aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/msm_serial.c
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2014-01-14 15:34:55 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-12 14:34:23 -0500
commitf7e54d7ad743a0cf0e400ac185036df6a592567c (patch)
tree8a2be5d50787660b58026c8f8366a9065c9d5d60 /drivers/tty/serial/msm_serial.c
parentb28a960c42fcd9cfc987441fa6d1c1a471f0f9ed (diff)
msm_serial: Add support for poll_{get,put}_char()
Implement the polling functionality for the MSM serial driver. This allows us to use KGDB on this hardware. Cc: David Brown <davidb@codeaurora.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/msm_serial.c')
-rw-r--r--drivers/tty/serial/msm_serial.c140
1 files changed, 137 insertions, 3 deletions
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b5d779cd3c2b..053b98eb46c8 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -39,6 +39,13 @@
39 39
40#include "msm_serial.h" 40#include "msm_serial.h"
41 41
42enum {
43 UARTDM_1P1 = 1,
44 UARTDM_1P2,
45 UARTDM_1P3,
46 UARTDM_1P4,
47};
48
42struct msm_port { 49struct msm_port {
43 struct uart_port uart; 50 struct uart_port uart;
44 char name[16]; 51 char name[16];
@@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct uart_port *port)
309 316
310static void msm_reset(struct uart_port *port) 317static void msm_reset(struct uart_port *port)
311{ 318{
319 struct msm_port *msm_port = UART_TO_MSM(port);
320
312 /* reset everything */ 321 /* reset everything */
313 msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); 322 msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
314 msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); 323 msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
@@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *port)
316 msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); 325 msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
317 msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); 326 msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
318 msm_write(port, UART_CR_CMD_SET_RFR, UART_CR); 327 msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
328
329 /* Disable DM modes */
330 if (msm_port->is_uartdm)
331 msm_write(port, 0, UARTDM_DMEN);
319} 332}
320 333
321static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) 334static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -711,6 +724,117 @@ static void msm_power(struct uart_port *port, unsigned int state,
711 } 724 }
712} 725}
713 726
727#ifdef CONFIG_CONSOLE_POLL
728static int msm_poll_init(struct uart_port *port)
729{
730 struct msm_port *msm_port = UART_TO_MSM(port);
731
732 /* Enable single character mode on RX FIFO */
733 if (msm_port->is_uartdm >= UARTDM_1P4)
734 msm_write(port, UARTDM_DMEN_RX_SC_ENABLE, UARTDM_DMEN);
735
736 return 0;
737}
738
739static int msm_poll_get_char_single(struct uart_port *port)
740{
741 struct msm_port *msm_port = UART_TO_MSM(port);
742 unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF;
743
744 if (!(msm_read(port, UART_SR) & UART_SR_RX_READY))
745 return NO_POLL_CHAR;
746 else
747 return msm_read(port, rf_reg) & 0xff;
748}
749
750static int msm_poll_get_char_dm_1p3(struct uart_port *port)
751{
752 int c;
753 static u32 slop;
754 static int count;
755 unsigned char *sp = (unsigned char *)&slop;
756
757 /* Check if a previous read had more than one char */
758 if (count) {
759 c = sp[sizeof(slop) - count];
760 count--;
761 /* Or if FIFO is empty */
762 } else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) {
763 /*
764 * If RX packing buffer has less than a word, force stale to
765 * push contents into RX FIFO
766 */
767 count = msm_read(port, UARTDM_RXFS);
768 count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK;
769 if (count) {
770 msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR);
771 slop = msm_read(port, UARTDM_RF);
772 c = sp[0];
773 count--;
774 } else {
775 c = NO_POLL_CHAR;
776 }
777 /* FIFO has a word */
778 } else {
779 slop = msm_read(port, UARTDM_RF);
780 c = sp[0];
781 count = sizeof(slop) - 1;
782 }
783
784 return c;
785}
786
787static int msm_poll_get_char(struct uart_port *port)
788{
789 u32 imr;
790 int c;
791 struct msm_port *msm_port = UART_TO_MSM(port);
792
793 /* Disable all interrupts */
794 imr = msm_read(port, UART_IMR);
795 msm_write(port, 0, UART_IMR);
796
797 if (msm_port->is_uartdm == UARTDM_1P3)
798 c = msm_poll_get_char_dm_1p3(port);
799 else
800 c = msm_poll_get_char_single(port);
801
802 /* Enable interrupts */
803 msm_write(port, imr, UART_IMR);
804
805 return c;
806}
807
808static void msm_poll_put_char(struct uart_port *port, unsigned char c)
809{
810 u32 imr;
811 struct msm_port *msm_port = UART_TO_MSM(port);
812
813 /* Disable all interrupts */
814 imr = msm_read(port, UART_IMR);
815 msm_write(port, 0, UART_IMR);
816
817 if (msm_port->is_uartdm)
818 reset_dm_count(port, 1);
819
820 /* Wait until FIFO is empty */
821 while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
822 cpu_relax();
823
824 /* Write a character */
825 msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
826
827 /* Wait until FIFO is empty */
828 while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
829 cpu_relax();
830
831 /* Enable interrupts */
832 msm_write(port, imr, UART_IMR);
833
834 return;
835}
836#endif
837
714static struct uart_ops msm_uart_pops = { 838static struct uart_ops msm_uart_pops = {
715 .tx_empty = msm_tx_empty, 839 .tx_empty = msm_tx_empty,
716 .set_mctrl = msm_set_mctrl, 840 .set_mctrl = msm_set_mctrl,
@@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = {
729 .config_port = msm_config_port, 853 .config_port = msm_config_port,
730 .verify_port = msm_verify_port, 854 .verify_port = msm_verify_port,
731 .pm = msm_power, 855 .pm = msm_power,
856#ifdef CONFIG_CONSOLE_POLL
857 .poll_init = msm_poll_init,
858 .poll_get_char = msm_poll_get_char,
859 .poll_put_char = msm_poll_put_char,
860#endif
732}; 861};
733 862
734static struct msm_port msm_uart_ports[] = { 863static struct msm_port msm_uart_ports[] = {
@@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_driver = {
900static atomic_t msm_uart_next_id = ATOMIC_INIT(0); 1029static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
901 1030
902static const struct of_device_id msm_uartdm_table[] = { 1031static const struct of_device_id msm_uartdm_table[] = {
903 { .compatible = "qcom,msm-uartdm" }, 1032 { .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 },
1033 { .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 },
1034 { .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 },
1035 { .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 },
904 { } 1036 { }
905}; 1037};
906 1038
@@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
909 struct msm_port *msm_port; 1041 struct msm_port *msm_port;
910 struct resource *resource; 1042 struct resource *resource;
911 struct uart_port *port; 1043 struct uart_port *port;
1044 const struct of_device_id *id;
912 int irq; 1045 int irq;
913 1046
914 if (pdev->id == -1) 1047 if (pdev->id == -1)
@@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struct platform_device *pdev)
923 port->dev = &pdev->dev; 1056 port->dev = &pdev->dev;
924 msm_port = UART_TO_MSM(port); 1057 msm_port = UART_TO_MSM(port);
925 1058
926 if (of_match_device(msm_uartdm_table, &pdev->dev)) 1059 id = of_match_device(msm_uartdm_table, &pdev->dev);
927 msm_port->is_uartdm = 1; 1060 if (id)
1061 msm_port->is_uartdm = (unsigned long)id->data;
928 else 1062 else
929 msm_port->is_uartdm = 0; 1063 msm_port->is_uartdm = 0;
930 1064