support different hsu pin settings on multi platform
authorBin Yang <bin.yang@intel.com>
Fri, 6 Apr 2012 10:50:23 +0000 (18:50 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 11 Apr 2012 09:54:19 +0000 (02:54 -0700)
BZ: 30744

Old HSU driver hard coding the pin setting. It cannot
work on CLV VV/PRx board correctly.

This patch supports different pin settings on multi platform.

Change-Id: Ie9b8a591df680a9f61687c70444cf5233b28c08c
Signed-off-by: Bin Yang <bin.yang@intel.com>
Reviewed-on: http://android.intel.com:8080/42685
Reviewed-by: Zhang, Shijie <shijie.zhang@intel.com>
Reviewed-by: Du, Alek <alek.du@intel.com>
Tested-by: Wang, Zhifeng <zhifeng.wang@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
arch/x86/include/asm/intel_mid_hsu.h [new file with mode: 0644]
arch/x86/platform/intel-mid/Makefile
arch/x86/platform/intel-mid/board-ctp.c
arch/x86/platform/intel-mid/mfld-hsu.c [new file with mode: 0644]
arch/x86/platform/intel-mid/mfld.c
drivers/tty/serial/mfd.c

diff --git a/arch/x86/include/asm/intel_mid_hsu.h b/arch/x86/include/asm/intel_mid_hsu.h
new file mode 100644 (file)
index 0000000..267689f
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __INTEL_MID_HSU_H__
+#define __INTEL_MID_HSU_H__
+
+#define MFLD_HSU_NUM   4
+struct mfld_hsu_info {
+       char *name;
+       int id;
+       int wake_gpio;
+       int rx_gpio;
+       int rx_alt;
+       int tx_gpio;
+       int tx_alt;
+       int cts_gpio;
+       int cts_alt;
+       int rts_gpio;
+       int rts_alt;
+       struct device *dev;
+       irq_handler_t wake_isr;
+};
+
+extern struct mfld_hsu_info *platform_hsu_info;
+extern unsigned char hsu_dma_enable;
+void intel_mid_hsu_suspend(int port);
+void intel_mid_hsu_resume(int port);
+void intel_mid_hsu_switch(int port);
+int intel_mid_hsu_init(int port, struct device *dev, irq_handler_t wake_isr);
+
+
+#endif
+
index 99614fd..1cd8531 100644 (file)
@@ -18,3 +18,4 @@ obj-$(CONFIG_BOARD_REDRIDGE)          += board-redridge.o
 obj-$(CONFIG_BOARD_CTP)                        += board-ctp.o
 obj-$(CONFIG_BOARD_MRFLD_VP)           += board-vp.o
 obj-$(CONFIG_BOARD_MRFLD_HVP)          += board-hvp.o
+obj-$(CONFIG_SERIAL_MFD_HSU)   += mfld-hsu.o
index 10d47fd..88c1d4e 100644 (file)
@@ -74,6 +74,7 @@
 #include <asm/intel_mid_gpadc.h>
 #include <asm/intel_mid_pwm.h>
 #include <asm/reboot.h>
+#include <asm/intel_mid_hsu.h>
 
 /* the offset for the mapping of global gpio pin to irq */
 #define MRST_IRQ_OFFSET 0x100
@@ -1908,3 +1909,58 @@ static int __init switch_mid_init(void)
 }
 device_initcall(switch_mid_init);
 #endif
+
+#ifdef CONFIG_SERIAL_MFD_HSU
+static struct mfld_hsu_info ctp_hsu_info[] = {
+       [0] = {
+               .id = 0,
+               .name = "hsu0",
+               .wake_gpio = 42,
+               .cts_gpio = 96+28,
+               .cts_alt = 1,
+               .rts_gpio = 96+29,
+               .rts_alt = 1,
+       },
+       [1] = {
+               .id = 1,
+               .name = "hsu1",
+               .wake_gpio = 64,
+               .rx_gpio = 64,
+               .rx_alt = 1,
+               .tx_gpio = 65,
+               .tx_alt = 1,
+               .cts_gpio = 68,
+               .cts_alt = 1,
+               .rts_gpio = 66,
+               .rts_alt = 2,
+       },
+       [2] = {
+               .id = 2,
+               .name = "hsu2",
+               .wake_gpio = 67,
+               .rx_gpio = 67,
+               .rx_alt = 1,
+       },
+       [3] = {
+               .id = 1,
+               .name = "hsu3",
+               .wake_gpio = 96+30,
+               .rx_gpio = 96+30,
+               .rx_alt = 1,
+               .tx_gpio = 96+31,
+               .tx_alt = 1,
+               .cts_gpio = 96+33,
+               .cts_alt = 1,
+               .rts_gpio = 96+32,
+               .rts_alt = 2,
+       },
+
+};
+
+static int __init ctp_hsu_init(void)
+{
+       platform_hsu_info = ctp_hsu_info;
+       return 0;
+}
+device_initcall(ctp_hsu_init);
+#endif
diff --git a/arch/x86/platform/intel-mid/mfld-hsu.c b/arch/x86/platform/intel-mid/mfld-hsu.c
new file mode 100644 (file)
index 0000000..597e5a7
--- /dev/null
@@ -0,0 +1,187 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/lnw_gpio.h>
+#include <linux/gpio.h>
+#include <asm/setup.h>
+#include <asm/intel_mid_hsu.h>
+
+/* a 3 bits bit-map, from 0 to 7, default 0 */
+unsigned char hsu_dma_enable;
+EXPORT_SYMBOL_GPL(hsu_dma_enable);
+
+int __init setup_hsu_dma_enable_flag(char *p)
+{
+       if (!p)
+               return -EINVAL;
+
+       hsu_dma_enable = (unsigned char)memparse(p, &p);
+       if (hsu_dma_enable & (~0x7))
+               return -EINVAL;
+
+       return 0;
+}
+early_param("hsu_dma", setup_hsu_dma_enable_flag);
+
+static struct mfld_hsu_info default_hsu_info[] = {
+       [0] = {
+               .id = 0,
+               .name = "hsu0",
+               .wake_gpio = 13,
+               .cts_gpio = 96+28,
+               .cts_alt = 1,
+               .rts_gpio = 96+29,
+               .rts_alt = 1,
+       },
+       [1] = {
+               .id = 1,
+               .name = "hsu1",
+               .wake_gpio = 64,
+               .rx_gpio = 64,
+               .rx_alt = 1,
+               .tx_gpio = 65,
+               .tx_alt = 1,
+               .cts_gpio = 68,
+               .cts_alt = 1,
+               .rts_gpio = 66,
+               .rts_alt = 2,
+       },
+       [2] = {
+               .id = 2,
+               .name = "hsu2",
+       },
+       [3] = {
+               .id = 1,
+               .name = "hsu3",
+               .wake_gpio = 96+30,
+               .rx_gpio = 96+30,
+               .rx_alt = 1,
+               .tx_gpio = 96+31,
+               .tx_alt = 1,
+       },
+
+};
+
+struct mfld_hsu_info *platform_hsu_info = default_hsu_info;
+
+static irqreturn_t hsu_wakeup_isr(int irq, void *dev)
+{
+       dev_dbg(dev, "HSU wake up\n");
+       pm_runtime_get(dev);
+       pm_runtime_put(dev);
+       return IRQ_HANDLED;
+}
+
+static void hsu_port_enable(int port)
+{
+       struct mfld_hsu_info *info = platform_hsu_info + port;
+
+       if (info->rx_gpio) {
+               lnw_gpio_set_alt(info->rx_gpio, info->rx_alt);
+               gpio_direction_input(info->rx_gpio);
+       }
+       if (info->tx_gpio) {
+               lnw_gpio_set_alt(info->tx_gpio, info->tx_alt);
+               gpio_direction_output(info->tx_gpio, 0);
+       }
+       if (info->cts_gpio) {
+               lnw_gpio_set_alt(info->cts_gpio, info->cts_alt);
+               gpio_direction_input(info->cts_gpio);
+       }
+       if (info->rts_gpio) {
+               lnw_gpio_set_alt(info->rts_gpio, info->rts_alt);
+               gpio_direction_output(info->rts_gpio, 0);
+       }
+}
+
+static void hsu_port_disable(int port)
+{
+       struct mfld_hsu_info *info = platform_hsu_info + port;
+
+       if (info->rx_gpio) {
+               lnw_gpio_set_alt(info->rx_gpio, LNW_GPIO);
+               gpio_direction_input(info->rx_gpio);
+       }
+       if (info->tx_gpio) {
+               lnw_gpio_set_alt(info->tx_gpio, LNW_GPIO);
+               gpio_direction_input(info->tx_gpio);
+       }
+       if (info->cts_gpio) {
+               lnw_gpio_set_alt(info->cts_gpio, LNW_GPIO);
+               gpio_direction_input(info->cts_gpio);
+       }
+       if (info->rts_gpio) {
+               lnw_gpio_set_alt(info->rts_gpio, LNW_GPIO);
+               gpio_direction_input(info->rts_gpio);
+       }
+}
+
+void intel_mid_hsu_suspend(int port)
+{
+       int ret;
+       struct mfld_hsu_info *info = platform_hsu_info + port;
+
+       if (info->rts_gpio) {
+               lnw_gpio_set_alt(info->rts_gpio, LNW_GPIO);
+               gpio_direction_output(info->rts_gpio, 1);
+       }
+       if (info->wake_gpio) {
+               lnw_gpio_set_alt(info->wake_gpio, LNW_GPIO);
+               gpio_direction_input(info->wake_gpio);
+               udelay(100);
+               ret = request_irq(gpio_to_irq(info->wake_gpio), info->wake_isr,
+                               IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING,
+                               info->name, info->dev);
+               if (ret)
+                       dev_err(info->dev, "failed to register wakeup irq\n");
+       }
+}
+
+void intel_mid_hsu_resume(int port)
+{
+       struct mfld_hsu_info *info = platform_hsu_info + port;
+
+       if (info->wake_gpio)
+               free_irq(gpio_to_irq(info->wake_gpio), info->dev);
+       hsu_port_enable(port);
+}
+
+void intel_mid_hsu_switch(int port)
+{
+       int i;
+       struct mfld_hsu_info *tmp;
+       struct mfld_hsu_info *info = platform_hsu_info + port;
+
+       for (i = 0; i < MFLD_HSU_NUM; i++) {
+               tmp = platform_hsu_info + i;
+               if (tmp != info && tmp->id == info->id)
+                       hsu_port_disable(i);
+       }
+       hsu_port_enable(port);
+}
+
+int intel_mid_hsu_init(int port, struct device *dev, irq_handler_t wake_isr)
+{
+       struct mfld_hsu_info *info;
+
+       if (platform_hsu_info == NULL)
+               return -ENODEV;
+       if (port >= MFLD_HSU_NUM)
+               return -ENODEV;
+       info = platform_hsu_info + port;
+       info->dev = dev;
+       info->wake_isr = wake_isr;
+       if (info->wake_gpio)
+               gpio_request(info->wake_gpio, "hsu");
+       if (info->rx_gpio)
+               gpio_request(info->rx_gpio, "hsu");
+       if (info->tx_gpio)
+               gpio_request(info->tx_gpio, "hsu");
+       if (info->cts_gpio)
+               gpio_request(info->cts_gpio, "hsu");
+       if (info->rts_gpio)
+               gpio_request(info->rts_gpio, "hsu");
+}
+
index b188a0c..3bcb918 100644 (file)
@@ -117,143 +117,3 @@ unsigned long __init intel_mid_calibrate_tsc(void)
 
        return 0;
 }
-
-/* a 3 bits bit-map, from 0 to 7, default 0 */
-unsigned char hsu_dma_enable;
-EXPORT_SYMBOL_GPL(hsu_dma_enable);
-
-int __init setup_hsu_dma_enable_flag(char *p)
-{
-       if (!p)
-               return -EINVAL;
-
-       hsu_dma_enable = (unsigned char)memparse(p, &p);
-       if (hsu_dma_enable & (~0x7))
-               return -EINVAL;
-
-       return 0;
-}
-early_param("hsu_dma", setup_hsu_dma_enable_flag);
-
-#define HSU0_CTS (13)
-#define HSU0_RTS (96 + 29)
-#define HSU1_RX (64)
-#define HSU1_TX (65)
-#define HSU1_CTS (68)
-#define HSU1_RTS (66)
-#define HSU1_ALT_RX (96 + 30)
-#define HSU1_ALT_TX (96 + 31)
-#define HSU2_RX (67)
-
-/* on = 1: the port1 is muxed (named as port 3) for debug output
- * on = 0: the port1 is for modem fw download.
- */
-void mfld_hsu_port1_switch(int on)
-{
-       static int first = 1;
-
-       if (unlikely(first)) {
-               gpio_request(HSU1_RX, "hsu");
-               gpio_request(HSU1_TX, "hsu");
-               gpio_request(HSU1_CTS, "hsu");
-               gpio_request(HSU1_RTS, "hsu");
-               gpio_request(HSU1_ALT_RX, "hsu");
-               gpio_request(HSU1_ALT_TX, "hsu");
-               first = 0;
-       }
-       if (on) {
-               lnw_gpio_set_alt(HSU1_RX, LNW_GPIO);
-               lnw_gpio_set_alt(HSU1_TX, LNW_GPIO);
-               lnw_gpio_set_alt(HSU1_CTS, LNW_GPIO);
-               lnw_gpio_set_alt(HSU1_RTS, LNW_GPIO);
-               gpio_direction_input(HSU1_RX);
-               gpio_direction_input(HSU1_TX);
-               gpio_direction_input(HSU1_CTS);
-               gpio_direction_input(HSU1_RTS);
-               gpio_direction_input(HSU1_ALT_RX);
-               gpio_direction_output(HSU1_ALT_TX, 0);
-               lnw_gpio_set_alt(HSU1_ALT_RX, LNW_ALT_1);
-               lnw_gpio_set_alt(HSU1_ALT_TX, LNW_ALT_1);
-       } else {
-               lnw_gpio_set_alt(HSU1_ALT_RX, LNW_GPIO);
-               lnw_gpio_set_alt(HSU1_ALT_TX, LNW_GPIO);
-               gpio_direction_input(HSU1_ALT_RX);
-               gpio_direction_input(HSU1_ALT_TX);
-               gpio_direction_input(HSU1_RX);
-               gpio_direction_output(HSU1_TX, 0);
-               gpio_direction_input(HSU1_CTS);
-               gpio_direction_output(HSU1_RTS, 0);
-               lnw_gpio_set_alt(HSU1_RX, LNW_ALT_1);
-               lnw_gpio_set_alt(HSU1_TX, LNW_ALT_1);
-               lnw_gpio_set_alt(HSU1_CTS, LNW_ALT_1);
-               lnw_gpio_set_alt(HSU1_RTS, LNW_ALT_2);
-       }
-}
-EXPORT_SYMBOL_GPL(mfld_hsu_port1_switch);
-
-void mfld_hsu_enable_wakeup(int index, struct device *dev, irq_handler_t wakeup)
-{
-       int ret;
-
-       switch (index) {
-       case 0:
-               lnw_gpio_set_alt(HSU0_CTS, LNW_GPIO);
-               ret = request_irq(gpio_to_irq(HSU0_CTS), wakeup,
-                               IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING,
-                               "hsu0_cts_wakeup", dev);
-               if (ret)
-                       dev_err(dev, "hsu0: failed to register wakeup irq\n");
-
-               /* turn off flow control */
-               gpio_set_value(HSU0_RTS, 1);
-               lnw_gpio_set_alt(HSU0_RTS, LNW_GPIO);
-               udelay(100);
-               break;
-       case 1:
-               lnw_gpio_set_alt(HSU1_RX, LNW_GPIO);
-               udelay(100);
-               ret = request_irq(gpio_to_irq(HSU1_RX), wakeup,
-                               IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING,
-                               "hsu1_rx_wakeup", dev);
-               if (ret)
-                       dev_err(dev, "hsu1: failed to register wakeup irq\n");
-               break;
-       case 2:
-               break;
-       case 3:
-               lnw_gpio_set_alt(HSU1_ALT_RX, LNW_GPIO);
-               udelay(100);
-               ret = request_irq(gpio_to_irq(HSU1_ALT_RX), wakeup,
-                               IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING,
-                               "hsu1_rx_wakeup", dev);
-               if (ret)
-                       dev_err(dev, "hsu1: failed to register wakeup irq\n");
-               break;
-       default:
-               dev_err(dev, "hsu: unknow hsu port\n");
-       }
-}
-EXPORT_SYMBOL_GPL(mfld_hsu_enable_wakeup);
-
-void mfld_hsu_disable_wakeup(int index, struct device *dev)
-{
-       switch (index) {
-       case 0:
-               free_irq(gpio_to_irq(HSU0_CTS), dev);
-               lnw_gpio_set_alt(HSU0_CTS, LNW_ALT_1);
-               lnw_gpio_set_alt(HSU0_RTS, LNW_ALT_1);
-               break;
-       case 1:
-               free_irq(gpio_to_irq(HSU1_RX), dev);
-               lnw_gpio_set_alt(HSU1_RX, LNW_ALT_1);
-               break;
-       case 2:
-               break;
-       case 3:
-               free_irq(gpio_to_irq(HSU1_ALT_RX), dev);
-               lnw_gpio_set_alt(HSU1_ALT_RX, LNW_ALT_1);
-               break;
-       default:
-               dev_err(dev, "hsu: unknow hsu port\n");
-       }
-}
index 0084f92..9457589 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/intel-mid.h>
 #include <asm/processor.h>
 #include <linux/pm_runtime.h>
+#include <asm/intel_mid_hsu.h>
 
 #define  MFD_HSU_A0_STEPPING   1
 
@@ -1050,7 +1051,7 @@ static int serial_hsu_startup(struct uart_port *port)
                /* wait for mux port to close */
                while (up1->running)
                        msleep(1000);
-               mfld_hsu_port1_switch(1);
+               intel_mid_hsu_switch(3);
        }
        if (up->index == 1) {
                struct uart_hsu_port *up3 = serial_hsu_ports[3];
@@ -1061,7 +1062,7 @@ static int serial_hsu_startup(struct uart_port *port)
                         */
                        up3->running = 1;
                }
-               mfld_hsu_port1_switch(0);
+               intel_mid_hsu_switch(1);
        }
        /* startup function is not under atomic context for sure */
        pm_runtime_get_sync(up->dev);
@@ -1172,7 +1173,7 @@ static void serial_hsu_shutdown(struct uart_port *port)
        up->running = 0;
        if (up->index == 1) {
                struct uart_hsu_port *up3 = serial_hsu_ports[3];
-               mfld_hsu_port1_switch(1);
+               intel_mid_hsu_switch(3);
                if (up3->running) {
                        mutex_unlock(&hsu_lock);
                        uart_resume_port(&serial_hsu_reg, &up3->port);
@@ -1651,6 +1652,7 @@ static int serial_hsu_probe(struct pci_dev *pdev,
                        uport->port.irq = pdev->irq;
                        uport->port.dev = &pdev->dev;
                        uport->dev = &pdev->dev;
+                       intel_mid_hsu_init(index, &pdev->dev, wakeup_irq);
 
                        if (index != 3) {
                                ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport);
@@ -1673,7 +1675,6 @@ static int serial_hsu_probe(struct pci_dev *pdev,
                        }
 #endif
                        if ( index == 1 ) {
-                               mfld_hsu_port1_switch(1);
                                index = 3;
                        } else
                                break;
@@ -1891,9 +1892,6 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 };
 
 #ifdef CONFIG_PM
-void mfld_hsu_enable_wakeup(int index, struct device *dev, irq_handler_t wakeup);
-void mfld_hsu_disable_wakeup(int index, struct device *dev);
-
 static bool allow_for_suspend(struct uart_hsu_port *up)
 {
        struct circ_buf *xmit = &up->port.state->xmit;
@@ -1973,7 +1971,7 @@ static int hsu_runtime_suspend(struct device *dev)
        if (up->index == 1) {
                struct uart_hsu_port *up3 = serial_hsu_ports[3];
                if (up3->running) {
-                       mfld_hsu_enable_wakeup(up3->index, dev, wakeup_irq);
+                       intel_mid_hsu_suspend(up3->index);
                        clear_bit(PM_WAKEUP, &up3->pm_flags);
                }
                memcpy(up3->reg_shadow + 1, up3->port.membase + 1,
@@ -1981,7 +1979,7 @@ static int hsu_runtime_suspend(struct device *dev)
        }
        memcpy(up->reg_shadow + 1, up->port.membase + 1, HSU_PORT_REG_LENGTH - 1);
        if (up->running)
-               mfld_hsu_enable_wakeup(up->index, dev, wakeup_irq);
+               intel_mid_hsu_suspend(up->index);
 
        return 0;
 }
@@ -1993,12 +1991,12 @@ static int hsu_runtime_resume(struct device *dev)
        int dma_rx_on = 0;
 
        if (up->running)
-               mfld_hsu_disable_wakeup(up->index, dev);
+               intel_mid_hsu_resume(up->index);
        if (up->index == 1) {
                struct uart_hsu_port *up3 = serial_hsu_ports[3];
 
                if (up3->running)
-                       mfld_hsu_disable_wakeup(up3->index, dev);
+                       intel_mid_hsu_resume(up3->index);
                if (up3->dma_rx_on)
                        dma_rx_on = 1;
        }
@@ -2077,7 +2075,7 @@ static int hsu_suspend(struct device *dev)
                if (up->running) {
                        uart_suspend_port(&serial_hsu_reg, &up->port);
                        up->running = 1;
-                       mfld_hsu_enable_wakeup(up->index, dev, wakeup_irq);
+                       intel_mid_hsu_suspend(up->index);
                }
                up->suspended = 1;
        }
@@ -2107,7 +2105,7 @@ static int hsu_resume(struct device *dev)
 
                if (up->suspended && up->running) {
                        uart_resume_port(&serial_hsu_reg, &up->port);
-                       mfld_hsu_disable_wakeup(up->index, dev);
+                       intel_mid_hsu_resume(up->index);
                        schedule_work(&up->qwork);
                }
                up->suspended = 0;