aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch
diff options
context:
space:
mode:
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.patch246
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
+