diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c index 4c04cec67f9e..6804b25f0810 100644 --- a/arch/arm/common/fiq_debugger.c +++ b/arch/arm/common/fiq_debugger.c @@ -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); diff --git a/arch/arm/include/asm/fiq_debugger.h b/arch/arm/include/asm/fiq_debugger.h index e711b57b22f1..39a7c1612868 100644 --- a/arch/arm/include/asm/fiq_debugger.h +++ b/arch/arm/include/asm/fiq_debugger.h @@ -27,6 +27,13 @@ #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);