ARM: common: fiq_debugger: add uart_enable/disable platform callbacks
authorDima Zavin <dima@android.com>
Wed, 5 Oct 2011 21:08:20 +0000 (14:08 -0700)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 20:25:18 +0000 (12:25 -0800)
This allows the platform specific drivers to properly enable
and disable the uart at the appropriate times. On some platforms, just
managing the clock is not enough.

Change-Id: I5feaab04cfe313a4a9470ca274838676b9684201
Signed-off-by: Dima Zavin <dima@android.com>
arch/arm/common/fiq_debugger.c
arch/arm/include/asm/fiq_debugger.h

index 4c04cec..6804b25 100644 (file)
@@ -73,7 +73,7 @@ struct fiq_debugger_state {
        bool debug_enable;
        bool ignore_next_wakeup_irq;
        struct timer_list sleep_timer;
-       bool uart_clk_enabled;
+       bool uart_enabled;
        struct wake_lock debugger_wake_lock;
        bool console_enable;
        int current_cpu;
@@ -152,6 +152,22 @@ static void debug_force_irq(struct fiq_debugger_state *state)
        }
 }
 
+static void debug_uart_enable(struct fiq_debugger_state *state)
+{
+       if (state->clk)
+               clk_enable(state->clk);
+       if (state->pdata->uart_enable)
+               state->pdata->uart_enable(state->pdev);
+}
+
+static void debug_uart_disable(struct fiq_debugger_state *state)
+{
+       if (state->pdata->uart_disable)
+               state->pdata->uart_disable(state->pdev);
+       if (state->clk)
+               clk_disable(state->clk);
+}
+
 static void debug_uart_flush(struct fiq_debugger_state *state)
 {
        if (state->pdata->uart_flush)
@@ -564,15 +580,14 @@ static void sleep_timer_expired(unsigned long data)
 {
        struct fiq_debugger_state *state = (struct fiq_debugger_state *)data;
 
-       if (state->uart_clk_enabled && !state->no_sleep) {
+       if (state->uart_enabled && !state->no_sleep) {
                if (state->debug_enable && !state->console_enable) {
                        state->debug_enable = false;
                        debug_printf_nfiq(state, "suspending fiq debugger\n");
                }
                state->ignore_next_wakeup_irq = true;
-               if (state->clk)
-                       clk_disable(state->clk);
-               state->uart_clk_enabled = false;
+               debug_uart_disable(state);
+               state->uart_enabled = false;
                enable_wakeup_irq(state);
        }
        wake_unlock(&state->debugger_wake_lock);
@@ -582,11 +597,10 @@ static void handle_wakeup(struct fiq_debugger_state *state)
 {
        if (state->wakeup_irq >= 0 && state->ignore_next_wakeup_irq) {
                state->ignore_next_wakeup_irq = false;
-       } else if (!state->uart_clk_enabled) {
+       } else if (!state->uart_enabled) {
                wake_lock(&state->debugger_wake_lock);
-               if (state->clk)
-                       clk_enable(state->clk);
-               state->uart_clk_enabled = true;
+               debug_uart_enable(state);
+               state->uart_enabled = true;
                disable_wakeup_irq(state);
                mod_timer(&state->sleep_timer, jiffies + HZ / 2);
        }
@@ -806,12 +820,14 @@ static void debug_console_write(struct console *co,
        if (!state->console_enable)
                return;
 
+       debug_uart_enable(state);
        while (count--) {
                if (*s == '\n')
                        state->pdata->uart_putc(state->pdev, '\r');
                state->pdata->uart_putc(state->pdev, *s++);
        }
        debug_uart_flush(state);
+       debug_uart_disable(state);
 }
 
 static struct console fiq_debugger_console = {
@@ -848,12 +864,10 @@ int  fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
        if (!state->console_enable)
                return count;
 
-       if (state->clk)
-               clk_enable(state->clk);
+       debug_uart_enable(state);
        for (i = 0; i < count; i++)
                state->pdata->uart_putc(state->pdev, *buf++);
-       if (state->clk)
-               clk_disable(state->clk);
+       debug_uart_disable(state);
 
        return count;
 }
@@ -928,6 +942,9 @@ static int fiq_debugger_probe(struct platform_device *pdev)
 
        if (!pdata->uart_getc || !pdata->uart_putc)
                return -EINVAL;
+       if ((pdata->uart_enable && !pdata->uart_disable) ||
+           (!pdata->uart_enable && pdata->uart_disable))
+               return -EINVAL;
 
        fiq = platform_get_irq_byname(pdev, "fiq");
        uart_irq = platform_get_irq_byname(pdev, "uart_irq");
@@ -964,6 +981,10 @@ static int fiq_debugger_probe(struct platform_device *pdev)
        if (IS_ERR(state->clk))
                state->clk = NULL;
 
+       /* do not call pdata->uart_enable here since uart_init may still
+        * need to do some initialization before uart_enable can work.
+        * So, only try to manage the clock during init.
+        */
        if (state->clk)
                clk_enable(state->clk);
 
index e711b57..39a7c16 100644 (file)
 #define FIQ_DEBUGGER_SIGNAL_IRQ_NAME   "signal"
 #define FIQ_DEBUGGER_WAKEUP_IRQ_NAME   "wakeup"
 
+/**
+ * struct fiq_debugger_pdata - fiq debugger platform data
+ * @uart_enable:       Do the work necessary to communicate with the uart
+ *                     hw (enable clocks, etc.). This must be ref-counted.
+ * @uart_disable:      Do the work necessary to disable the uart hw
+ *                     (disable clocks, etc.). This must be ref-counted.
+ */
 struct fiq_debugger_pdata {
        int (*uart_init)(struct platform_device *pdev);
        void (*uart_free)(struct platform_device *pdev);
@@ -34,6 +41,8 @@ struct fiq_debugger_pdata {
        int (*uart_getc)(struct platform_device *pdev);
        void (*uart_putc)(struct platform_device *pdev, unsigned int c);
        void (*uart_flush)(struct platform_device *pdev);
+       void (*uart_enable)(struct platform_device *pdev);
+       void (*uart_disable)(struct platform_device *pdev);
 
        void (*fiq_enable)(struct platform_device *pdev, unsigned int fiq,
                                                                bool enable);