diff options
Diffstat (limited to 'target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch')
-rw-r--r-- | target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch b/target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch new file mode 100644 index 0000000000..afc293bfbd --- /dev/null +++ b/target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch @@ -0,0 +1,246 @@ +From 48ab619dd6e308c57dac3e5d022a3099806bf79e Mon Sep 17 00:00:00 2001 +From: Stephen Boyd <sboyd@codeaurora.org> +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 <davidb@codeaurora.org> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/tty/serial/msm_serial.c | 140 ++++++++++++++++++++++++++++++++++++++- + drivers/tty/serial/msm_serial.h | 9 +++ + 2 files changed, 146 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c +index b5d779c..053b98e 100644 +--- 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 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; + +diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h +index 469fda5..1e9b68b 100644 +--- 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 +-- +1.7.10.4 + |