msm_serial: Add support for poll_{get,put}_char()
Subsystems (2)
PATCH 1/1 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 <[email protected]>
Signed-off-by Stephen Boyd <[email protected]>
--- drivers/tty/serial/msm_serial.c | 140 +++++++++++++++++++++++++++++++++++++++- drivers/tty/serial/msm_serial.h | 9 +++ 2 files changed, 146 insertions(+), 3 deletions(-)
drivers/tty/serial/msm_serial.c +137 -3
@@ -39,6 +39,13 @@#include "msm_serial.h" +enum { +UARTDM_1P1 =1 , +UARTDM_1P2 , +UARTDM_1P3 , +UARTDM_1P4 , +}; +struct msm_port {struct uart_port uart;char name[16 ];
@@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct uart_port *port)static void msm_reset (struct uart_port *port) { +struct msm_port *msm_port =UART_TO_MSM (port); +/* reset everything */ msm_write (port,UART_CR_CMD_RESET_RX ,UART_CR );msm_write (port,UART_CR_CMD_RESET_TX ,UART_CR );
@@ -316,6 +325,10 @@ static void msm_reset(struct uart_port *port)msm_write (port,UART_CR_CMD_RESET_BREAK_INT ,UART_CR );msm_write (port,UART_CR_CMD_RESET_CTS ,UART_CR );msm_write (port,UART_CR_CMD_SET_RFR ,UART_CR ); + +/* Disable DM modes */ +if (msm_port->is_uartdm) +msm_write (port,0 ,UARTDM_DMEN ); }static 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, } } +#ifdef CONFIG_CONSOLE_POLL +static int msm_poll_init (struct uart_port *port) +{ +struct msm_port *msm_port =UART_TO_MSM (port); + +/* Enable single character mode on RX FIFO */ +if (msm_port->is_uartdm >=UARTDM_1P4 ) +msm_write (port,UARTDM_DMEN_RX_SC_ENABLE ,UARTDM_DMEN ); + +return 0 ; +} + +static int msm_poll_get_char_single (struct uart_port *port) +{ +struct msm_port *msm_port =UART_TO_MSM (port); +unsigned int rf_reg = msm_port->is_uartdm ?UARTDM_RF :UART_RF ; + +if (!(msm_read (port,UART_SR ) &UART_SR_RX_READY )) +return NO_POLL_CHAR ; +else +return msm_read (port, rf_reg) &0xff ; +} + +static int msm_poll_get_char_dm_1p3 (struct uart_port *port) +{ +int c; +static u32 slop; +static int count; +unsigned char *sp = (unsigned char *)&slop; + +/* Check if a previous read had more than one char */ +if (count) { + c = sp[sizeof (slop) - count]; + count--; +/* Or if FIFO is empty */ + }else if (!(msm_read (port,UART_SR ) &UART_SR_RX_READY )) { +/* +* If RX packing buffer has less than a word, force stale to +* push contents into RX FIFO +*/ + count =msm_read (port,UARTDM_RXFS ); + count = (count >>UARTDM_RXFS_BUF_SHIFT ) &UARTDM_RXFS_BUF_MASK ; +if (count) { +msm_write (port,UART_CR_CMD_FORCE_STALE ,UART_CR ); + slop =msm_read (port,UARTDM_RF ); + c = sp[0 ]; + count--; + }else { + c =NO_POLL_CHAR ; + } +/* FIFO has a word */ + }else { + slop =msm_read (port,UARTDM_RF ); + c = sp[0 ]; + count =sizeof (slop) -1 ; + } + +return c; +} + +static int msm_poll_get_char (struct uart_port *port) +{ +u32 imr; +int c; +struct msm_port *msm_port =UART_TO_MSM (port); + +/* Disable all interrupts */ + imr =msm_read (port,UART_IMR ); +msm_write (port,0 ,UART_IMR ); + +if (msm_port->is_uartdm ==UARTDM_1P3 ) + c =msm_poll_get_char_dm_1p3 (port); +else + c =msm_poll_get_char_single (port); + +/* Enable interrupts */ +msm_write (port, imr,UART_IMR ); + +return c; +} + +static void msm_poll_put_char (struct uart_port *port,unsigned char c) +{ +u32 imr; +struct msm_port *msm_port =UART_TO_MSM (port); + +/* Disable all interrupts */ + imr =msm_read (port,UART_IMR ); +msm_write (port,0 ,UART_IMR ); + +if (msm_port->is_uartdm) +reset_dm_count (port,1 ); + +/* Wait until FIFO is empty */ +while (!(msm_read (port,UART_SR ) &UART_SR_TX_READY )) +cpu_relax (); + +/* Write a character */ +msm_write (port, c, msm_port->is_uartdm ?UARTDM_TF :UART_TF ); + +/* Wait until FIFO is empty */ +while (!(msm_read (port,UART_SR ) &UART_SR_TX_READY )) +cpu_relax (); + +/* Enable interrupts */ +msm_write (port, imr,UART_IMR ); + +return ; +} +#endif +static struct uart_ops msm_uart_pops = { .tx_empty = msm_tx_empty, .set_mctrl = msm_set_mctrl,
@@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = { .config_port = msm_config_port, .verify_port = msm_verify_port, .pm = msm_power, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = msm_poll_init, + .poll_get_char = msm_poll_get_char, + .poll_put_char = msm_poll_put_char, +#endif }; static struct msm_port msm_uart_ports[] = {
@@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_driver = {static atomic_t msm_uart_next_id =ATOMIC_INIT (0 );static const struct of_device_id msm_uartdm_table[] = { - { .compatible ="qcom,msm-uartdm" }, + { .compatible ="qcom,msm-uartdm-v1.1" , .data = (void *)UARTDM_1P1 }, + { .compatible ="qcom,msm-uartdm-v1.2" , .data = (void *)UARTDM_1P2 }, + { .compatible ="qcom,msm-uartdm-v1.3" , .data = (void *)UARTDM_1P3 }, + { .compatible ="qcom,msm-uartdm-v1.4" , .data = (void *)UARTDM_1P4 }, { } };
@@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)struct msm_port *msm_port;struct resource *resource;struct uart_port *port; +const struct of_device_id *id;int irq;if (pdev->id ==-1 )
@@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struct platform_device *pdev) port->dev = &pdev->dev; msm_port =UART_TO_MSM (port); -if (of_match_device (msm_uartdm_table, &pdev->dev)) - msm_port->is_uartdm =1 ; + id =of_match_device (msm_uartdm_table, &pdev->dev); +if (id) + msm_port->is_uartdm = (unsigned long )id->data;else msm_port->is_uartdm =0 ;
drivers/tty/serial/msm_serial.h +9 -0
@@ -59,6 +59,7 @@#define UART_CR_CMD_RESET_RFR (14 << 4)#define UART_CR_CMD_PROTECTION_EN (16 << 4)#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) +#define UART_CR_CMD_FORCE_STALE (4 << 8)#define UART_CR_CMD_RESET_TX_READY (3 << 8)#define UART_CR_TX_DISABLE (1 << 3)#define UART_CR_TX_ENABLE (1 << 2)
@@ -113,6 +114,14 @@#define GSBI_PROTOCOL_UART 0x40#define GSBI_PROTOCOL_IDLE 0x0 +#define UARTDM_RXFS 0x50 +#define UARTDM_RXFS_BUF_SHIFT 0x7 +#define UARTDM_RXFS_BUF_MASK 0x7 + +#define UARTDM_DMEN 0x3C +#define UARTDM_DMEN_RX_SC_ENABLE BIT(5) +#define UARTDM_DMEN_TX_SC_ENABLE BIT(4) +#define UARTDM_DMRX 0x34#define UARTDM_NCF_TX 0x40#define UARTDM_RX_TOTAL_SNAP 0x38
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation