add HSU RX timeout workarround for CTP
authorBin Yang <bin.yang@intel.com>
Thu, 19 Apr 2012 10:34:05 +0000 (18:34 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 2 May 2012 12:27:54 +0000 (05:27 -0700)
BZ: 31975

HSU RX timeout interrupt is lost for silicon issue. Need
this workarround to recovery the interrupt.

Change-Id: Ie38ac427519e04d5043cebc06873e4d429b8acaf
Signed-off-by: Bin Yang <bin.yang@intel.com>
Reviewed-on: http://android.intel.com:8080/44029
Reviewed-by: Kuppuswamy, Sathyanarayanan <sathyanarayanan.kuppuswamy@intel.com>
Reviewed-by: Wang, Yiyang <yiyang.wang@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
arch/x86/platform/intel-mid/mfld-hsu.c
drivers/tty/serial/mfd.c

index 267689f..d2fdbd4 100644 (file)
@@ -20,6 +20,7 @@ struct mfld_hsu_info {
 
 extern struct mfld_hsu_info *platform_hsu_info;
 extern unsigned char hsu_dma_enable;
+extern int hsu_rx_wa;
 void intel_mid_hsu_suspend(int port);
 void intel_mid_hsu_resume(int port);
 void intel_mid_hsu_switch(int port);
index 597e5a7..fcc3450 100644 (file)
@@ -25,6 +25,16 @@ int __init setup_hsu_dma_enable_flag(char *p)
 }
 early_param("hsu_dma", setup_hsu_dma_enable_flag);
 
+int hsu_rx_wa;
+EXPORT_SYMBOL_GPL(hsu_rx_wa);
+
+int __init setup_hsu_rx_workarround_flag(char *p)
+{
+       hsu_rx_wa = 1;
+       return 0;
+}
+early_param("hsu_rx_wa", setup_hsu_rx_workarround_flag);
+
 static struct mfld_hsu_info default_hsu_info[] = {
        [0] = {
                .id = 0,
index f619469..56796cc 100644 (file)
@@ -57,7 +57,7 @@
 #define mfd_readl(obj, offset)         readl(obj->reg + offset)
 #define mfd_writel(obj, offset, val)   writel(val, obj->reg + offset)
 
-#define HSU_DMA_TIMEOUT_CHECK_FREQ     (HZ/10)
+#define HSU_DMA_TIMEOUT_CHECK_FREQ     (HZ/100)
 
 struct hsu_dma_buffer {
        u8              *buf;
@@ -200,7 +200,15 @@ module_param(hsu_low_latency, uint, S_IRUGO);
  */
 static inline int dmarx_need_timer(void)
 {
-       return (boot_cpu_data.x86_model == 0x27 && boot_cpu_data.x86_mask == 0);
+       return hsu_rx_wa ||
+               (boot_cpu_data.x86_model == 0x27 &&
+               boot_cpu_data.x86_mask == 0);
+}
+
+static inline void runtime_suspend_delay(struct uart_hsu_port *up)
+{
+       pm_runtime_get(up->dev);
+       pm_runtime_put(up->dev);
 }
 
 static inline unsigned int serial_in_irq(struct uart_hsu_port *up, int offset)
@@ -517,8 +525,10 @@ void hsu_dma_start_rx_chan(struct uart_hsu_port *up,
        chan_writel(rxc, HSU_CH_CR, 0x3);
        up->dma_rx_on = 1;
 
-       if (dmarx_need_timer())
+       if (dmarx_need_timer()) {
                mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
+               runtime_suspend_delay(up);
+       }
 }
 
 /* Protected by spin_lock_irqsave(port->lock) */
@@ -598,6 +608,7 @@ static void hsu_dma_rx_tasklet(unsigned long data)
                        chan->rx_timer.expires =
                                        jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ;
                        add_timer(&chan->rx_timer);
+                       runtime_suspend_delay(up);
                }
 
                /* If function is called from tasklet context, pm_runtime
@@ -642,8 +653,10 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
                return;
        }
 
-       if (dmarx_need_timer())
+       if (dmarx_need_timer()) {
                del_timer(&chan->rx_timer);
+               runtime_suspend_delay(up);
+       }
 
        dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
                        dbuf->dma_size, DMA_FROM_DEVICE);
@@ -1708,9 +1721,11 @@ static void hsu_dma_rx_timeout(unsigned long data)
        count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
 
        if (!count) {
-               if (dmarx_need_timer())
+               if (dmarx_need_timer()) {
                        mod_timer(&chan->rx_timer,
                                jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
+                       runtime_suspend_delay(up);
+               }
                goto exit;
        }