Omap-uart can be used as console uart to print early boot messages using earlyprintk so for console uart prevent hwmod reset or idling during bootup. Identify the console_uart set the id and use the custom pm_latency ops for console uart for the first time to idle console uart left enabled from bootup and then enable them back and reset pm_latency ops to default ops. Thanks to Kevin Hilman <khilman@xxxxxx> for suggesting this approach. Signed-off-by: Govindraj.R <govindraj.raja@xxxxxx> --- arch/arm/mach-omap2/serial.c | 79 ++++++++++++++++++++++++++++------------- 1 files changed, 54 insertions(+), 25 deletions(-) diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index e1eba7f..55903f0 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -63,6 +63,7 @@ struct omap_uart_state { static LIST_HEAD(uart_list); static u8 num_uarts; +static u8 console_uart_id = -1; #define DEFAULT_RXDMA_POLLRATE 1 /* RX DMA polling rate (us) */ #define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */ @@ -87,6 +88,29 @@ static struct omap_device_pm_latency omap_uart_latency[] = { }, }; +static int console_uart_enable_hwmod(struct omap_device *od) +{ + /* For early console we prevented hwmod reset and idle + * So before we enable the uart clocks idle and then + */ + omap_hwmod_idle(od->hwmods[0]); + omap_hwmod_enable(od->hwmods[0]); + + /* restore the default activate/deactivate funcs, + * since now we have set the hwmod state machine right + * with the idle/enable for console uart + */ + od->pm_lats = omap_uart_latency; + + return 0; +} + +static struct omap_device_pm_latency console_uart_latency[] = { + { + .activate_func = console_uart_enable_hwmod, + }, +}; + #ifdef CONFIG_PM static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) { @@ -251,12 +275,20 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata) static void omap_serial_fill_default_pads(struct omap_board_data *bdata) {} #endif +char *cmdline_find_option(char *str) +{ + extern char *saved_command_line; + + return strstr(saved_command_line, str); +} + static int __init omap_serial_early_init(void) { do { char oh_name[MAX_UART_HWMOD_NAME_LEN]; struct omap_hwmod *oh; struct omap_uart_state *uart; + char uart_name[MAX_UART_HWMOD_NAME_LEN]; snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num_uarts + 1); @@ -271,18 +303,23 @@ static int __init omap_serial_early_init(void) uart->oh = oh; uart->num = num_uarts++; list_add_tail(&uart->node, &uart_list); + snprintf(uart_name, MAX_UART_HWMOD_NAME_LEN, + "%s%d", OMAP_SERIAL_NAME, uart->num); + + if (cmdline_find_option(uart_name)) { + console_uart_id = uart->num; + /* + * omap-uart can be used for earlyprintk logs + * So if omap-uart is used as console then prevent + * uart reset and idle to get logs from omap-uart + * until uart console driver is available to take + * care for console messages. + * Idling or resetting omap-uart while printing logs + * early boot logs can stall the boot-up. + */ + oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; + } - /* - * NOTE: omap_hwmod_setup*() has not yet been called, - * so no hwmod functions will work yet. - */ - - /* - * During UART early init, device need to be probed - * to determine SoC specific init before omap_device - * is ready. Therefore, don't allow idle here - */ - uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; } while (1); return 0; @@ -311,6 +348,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, u32 pdata_size = 0; char *name; struct omap_uart_port_info omap_up; + struct omap_device *od; if (WARN_ON(!bdata)) return; @@ -357,6 +395,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n", name, oh->name); + if (console_uart_id == bdata->id) { + od = to_omap_device(pdev); + od->pm_lats = console_uart_latency; + } + omap_device_disable_idle_on_suspend(pdev); oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); @@ -364,20 +407,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, oh->dev_attr = uart; - console_lock(); /* in case the earlycon is on the UART */ - - /* - * Because of early UART probing, UART did not get idled - * on init. Now that omap_device is ready, ensure full idle - * before doing omap_device_enable(). - */ - omap_hwmod_idle(uart->oh); - - omap_device_enable(uart->pdev); - omap_device_idle(uart->pdev); - - console_unlock(); - if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) device_init_wakeup(&pdev->dev, true); } -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html