Skip to content

Commit

Permalink
bus: ti-sysc: Improve handling for no-reset-on-init and no-idle-on-init
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
tmlind committed Feb 26, 2018
1 parent 3bb37c8 commit 76f0f77
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions drivers/bus/ti-sysc.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ struct sysc {
u32 revision;
bool enabled;
bool needs_resume;
struct delayed_work idle_work;
};

static u32 sysc_read(struct sysc *ddata, int offset)
Expand Down Expand Up @@ -1028,6 +1029,16 @@ static int sysc_init_match(struct sysc *ddata)
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)
{
struct sysc *ddata;
Expand Down Expand Up @@ -1081,8 +1092,6 @@ static int sysc_probe(struct platform_device *pdev)
goto unprepare;
}

pm_runtime_use_autosuspend(ddata->dev);

sysc_show_registers(ddata);

ddata->dev->type = &sysc_device_type;
Expand All @@ -1091,13 +1100,19 @@ static int sysc_probe(struct platform_device *pdev)
if (error)
goto err;

pm_runtime_mark_last_busy(ddata->dev);
pm_runtime_put_autosuspend(ddata->dev);
INIT_DELAYED_WORK(&ddata->idle_work, ti_sysc_idle);

/* 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;

err:
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
unprepare:
Expand All @@ -1111,6 +1126,8 @@ static int sysc_remove(struct platform_device *pdev)
struct sysc *ddata = platform_get_drvdata(pdev);
int error;

cancel_delayed_work_sync(&ddata->idle_work);

error = pm_runtime_get_sync(ddata->dev);
if (error < 0) {
pm_runtime_put_noidle(ddata->dev);
Expand All @@ -1120,7 +1137,6 @@ static int sysc_remove(struct platform_device *pdev)

of_platform_depopulate(&pdev->dev);

pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);

Expand Down

0 comments on commit 76f0f77

Please sign in to comment.