Skip to content

Commit b6c7ff2

Browse files
wensgregkh
authored andcommitted
serial: 8250_mtk: Simplify clock sequencing and runtime PM
The 8250_mtk driver's runtime PM support has some issues: - The bus clock is enabled (through runtime PM callback) later than a register write - runtime PM resume callback directly called in probe, but no pm_runtime_set_active() call is present - UART PM function calls the callbacks directly, _and_ calls runtime PM API - runtime PM callbacks try to do reference counting, adding yet another count between runtime PM and clocks This fragile setup worked in a way, but broke recently with runtime PM support added to the serial core. The system would hang when the UART console was probed and brought up. Tony provided some potential fixes [1][2], though they were still a bit complicated. The 8250_dw driver, which the 8250_mtk driver might have been based on, has a similar structure but simpler runtime PM usage. Simplify clock sequencing and runtime PM support in the 8250_mtk driver. Specifically, the clock is acquired enabled and assumed to be active, unless toggled through runtime PM suspend/resume. Reference counting is removed and left to the runtime PM core. The serial pm function now only calls the runtime PM API. [1] https://lore.kernel.org/linux-serial/[email protected]/ [2] https://lore.kernel.org/linux-serial/[email protected]/ Fixes: 84a9582 ("serial: core: Start managing serial controllers to enable runtime PM") Suggested-by: Tony Lindgren <[email protected]> Signed-off-by: Chen-Yu Tsai <[email protected]> Reviewed-by: AngeloGioacchino Del Regno <[email protected]> Reviewed-by: Tony Lindgren <[email protected]> Message-ID: <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 643662d commit b6c7ff2

File tree

1 file changed

+10
-40
lines changed

1 file changed

+10
-40
lines changed

drivers/tty/serial/8250/8250_mtk.c

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -431,32 +431,16 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev)
431431
while
432432
(serial_in(up, MTK_UART_DEBUG0));
433433

434-
if (data->clk_count == 0U) {
435-
dev_dbg(dev, "%s clock count is 0\n", __func__);
436-
} else {
437-
clk_disable_unprepare(data->bus_clk);
438-
data->clk_count--;
439-
}
434+
clk_disable_unprepare(data->bus_clk);
440435

441436
return 0;
442437
}
443438

444439
static int __maybe_unused mtk8250_runtime_resume(struct device *dev)
445440
{
446441
struct mtk8250_data *data = dev_get_drvdata(dev);
447-
int err;
448442

449-
if (data->clk_count > 0U) {
450-
dev_dbg(dev, "%s clock count is %d\n", __func__,
451-
data->clk_count);
452-
} else {
453-
err = clk_prepare_enable(data->bus_clk);
454-
if (err) {
455-
dev_warn(dev, "Can't enable bus clock\n");
456-
return err;
457-
}
458-
data->clk_count++;
459-
}
443+
clk_prepare_enable(data->bus_clk);
460444

461445
return 0;
462446
}
@@ -465,14 +449,12 @@ static void
465449
mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
466450
{
467451
if (!state)
468-
if (!mtk8250_runtime_resume(port->dev))
469-
pm_runtime_get_sync(port->dev);
452+
pm_runtime_get_sync(port->dev);
470453

471454
serial8250_do_pm(port, state, old);
472455

473456
if (state)
474-
if (!pm_runtime_put_sync_suspend(port->dev))
475-
mtk8250_runtime_suspend(port->dev);
457+
pm_runtime_put_sync_suspend(port->dev);
476458
}
477459

478460
#ifdef CONFIG_SERIAL_8250_DMA
@@ -504,7 +486,7 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
504486
return 0;
505487
}
506488

507-
data->bus_clk = devm_clk_get(&pdev->dev, "bus");
489+
data->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus");
508490
if (IS_ERR(data->bus_clk))
509491
return PTR_ERR(data->bus_clk);
510492

@@ -587,25 +569,16 @@ static int mtk8250_probe(struct platform_device *pdev)
587569

588570
platform_set_drvdata(pdev, data);
589571

590-
pm_runtime_enable(&pdev->dev);
591-
err = mtk8250_runtime_resume(&pdev->dev);
592-
if (err)
593-
goto err_pm_disable;
594-
595572
data->line = serial8250_register_8250_port(&uart);
596-
if (data->line < 0) {
597-
err = data->line;
598-
goto err_pm_disable;
599-
}
573+
if (data->line < 0)
574+
return data->line;
600575

601576
data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1);
602577

603-
return 0;
604-
605-
err_pm_disable:
606-
pm_runtime_disable(&pdev->dev);
578+
pm_runtime_set_active(&pdev->dev);
579+
pm_runtime_enable(&pdev->dev);
607580

608-
return err;
581+
return 0;
609582
}
610583

611584
static int mtk8250_remove(struct platform_device *pdev)
@@ -619,9 +592,6 @@ static int mtk8250_remove(struct platform_device *pdev)
619592
pm_runtime_disable(&pdev->dev);
620593
pm_runtime_put_noidle(&pdev->dev);
621594

622-
if (!pm_runtime_status_suspended(&pdev->dev))
623-
mtk8250_runtime_suspend(&pdev->dev);
624-
625595
return 0;
626596
}
627597

0 commit comments

Comments
 (0)