123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- From 48ab619dd6e308c57dac3e5d022a3099806bf79e Mon Sep 17 00:00:00 2001
- From: Stephen Boyd <[email protected]>
- Date: Tue, 14 Jan 2014 12:34:55 -0800
- Subject: [PATCH 086/182] 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]>
- Signed-off-by: Greg Kroah-Hartman <[email protected]>
- ---
- drivers/tty/serial/msm_serial.c | 140 ++++++++++++++++++++++++++++++++++++++-
- drivers/tty/serial/msm_serial.h | 9 +++
- 2 files changed, 146 insertions(+), 3 deletions(-)
- --- a/drivers/tty/serial/msm_serial.c
- +++ b/drivers/tty/serial/msm_serial.c
- @@ -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
-
- 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 *
- 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 *
- }
- }
-
- +#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_drive
- 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(struc
- 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(struc
- 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;
-
- --- a/drivers/tty/serial/msm_serial.h
- +++ b/drivers/tty/serial/msm_serial.h
- @@ -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
|