forked from Minki/linux
bus: ti-sysc: Improve handling for no-reset-on-init and no-idle-on-init
At least earlycon needs a delayed idle before the 8250 driver probes to avoid glitches in the console output. Let's handle the delayed idle for devices tagged with ti,no-reset-on-init and ti,no-idle-on-init with delayed_work. Others don't need it, and there should be no need to use runtime PM autosuspend for the interconnect target driver as it's the child device drivers that should configure it. Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
parent
3bb37c8e6e
commit
76f0f772e4
@ -74,6 +74,7 @@ struct sysc {
|
|||||||
u32 revision;
|
u32 revision;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool needs_resume;
|
bool needs_resume;
|
||||||
|
struct delayed_work idle_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 sysc_read(struct sysc *ddata, int offset)
|
static u32 sysc_read(struct sysc *ddata, int offset)
|
||||||
@ -1028,6 +1029,16 @@ static int sysc_init_match(struct sysc *ddata)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ti_sysc_idle(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct sysc *ddata;
|
||||||
|
|
||||||
|
ddata = container_of(work, struct sysc, idle_work.work);
|
||||||
|
|
||||||
|
if (pm_runtime_active(ddata->dev))
|
||||||
|
pm_runtime_put_sync(ddata->dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int sysc_probe(struct platform_device *pdev)
|
static int sysc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct sysc *ddata;
|
struct sysc *ddata;
|
||||||
@ -1081,8 +1092,6 @@ static int sysc_probe(struct platform_device *pdev)
|
|||||||
goto unprepare;
|
goto unprepare;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_runtime_use_autosuspend(ddata->dev);
|
|
||||||
|
|
||||||
sysc_show_registers(ddata);
|
sysc_show_registers(ddata);
|
||||||
|
|
||||||
ddata->dev->type = &sysc_device_type;
|
ddata->dev->type = &sysc_device_type;
|
||||||
@ -1091,13 +1100,19 @@ static int sysc_probe(struct platform_device *pdev)
|
|||||||
if (error)
|
if (error)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
pm_runtime_mark_last_busy(ddata->dev);
|
INIT_DELAYED_WORK(&ddata->idle_work, ti_sysc_idle);
|
||||||
pm_runtime_put_autosuspend(ddata->dev);
|
|
||||||
|
/* At least earlycon won't survive without deferred idle */
|
||||||
|
if (ddata->cfg.quirks & (SYSC_QUIRK_NO_IDLE_ON_INIT |
|
||||||
|
SYSC_QUIRK_NO_RESET_ON_INIT)) {
|
||||||
|
schedule_delayed_work(&ddata->idle_work, 3000);
|
||||||
|
} else {
|
||||||
|
pm_runtime_put(&pdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
|
||||||
pm_runtime_put_sync(&pdev->dev);
|
pm_runtime_put_sync(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
unprepare:
|
unprepare:
|
||||||
@ -1111,6 +1126,8 @@ static int sysc_remove(struct platform_device *pdev)
|
|||||||
struct sysc *ddata = platform_get_drvdata(pdev);
|
struct sysc *ddata = platform_get_drvdata(pdev);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&ddata->idle_work);
|
||||||
|
|
||||||
error = pm_runtime_get_sync(ddata->dev);
|
error = pm_runtime_get_sync(ddata->dev);
|
||||||
if (error < 0) {
|
if (error < 0) {
|
||||||
pm_runtime_put_noidle(ddata->dev);
|
pm_runtime_put_noidle(ddata->dev);
|
||||||
@ -1120,7 +1137,6 @@ static int sysc_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
of_platform_depopulate(&pdev->dev);
|
of_platform_depopulate(&pdev->dev);
|
||||||
|
|
||||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
|
||||||
pm_runtime_put_sync(&pdev->dev);
|
pm_runtime_put_sync(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user