bus: ti-sysc: Add separate functions for handling clocks
At least McPDM module depends on an external optional clock to be usable. To make handling of the McPDM clock easier in the following patches, let's add separate functions for handling the main clocks and the optional clocks. Let's also add error handling to shut down already enabled clocks while at it. Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
parent
ff43728c4a
commit
d878970f6c
|
@ -231,6 +231,112 @@ static int sysc_get_clocks(struct sysc *ddata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sysc_enable_main_clocks(struct sysc *ddata)
|
||||
{
|
||||
struct clk *clock;
|
||||
int i, error;
|
||||
|
||||
if (!ddata->clocks)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < SYSC_OPTFCK0; i++) {
|
||||
clock = ddata->clocks[i];
|
||||
|
||||
/* Main clocks may not have ick */
|
||||
if (IS_ERR_OR_NULL(clock))
|
||||
continue;
|
||||
|
||||
error = clk_enable(clock);
|
||||
if (error)
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable:
|
||||
for (i--; i >= 0; i--) {
|
||||
clock = ddata->clocks[i];
|
||||
|
||||
/* Main clocks may not have ick */
|
||||
if (IS_ERR_OR_NULL(clock))
|
||||
continue;
|
||||
|
||||
clk_disable(clock);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void sysc_disable_main_clocks(struct sysc *ddata)
|
||||
{
|
||||
struct clk *clock;
|
||||
int i;
|
||||
|
||||
if (!ddata->clocks)
|
||||
return;
|
||||
|
||||
for (i = 0; i < SYSC_OPTFCK0; i++) {
|
||||
clock = ddata->clocks[i];
|
||||
if (IS_ERR_OR_NULL(clock))
|
||||
continue;
|
||||
|
||||
clk_disable(clock);
|
||||
}
|
||||
}
|
||||
|
||||
static int sysc_enable_opt_clocks(struct sysc *ddata)
|
||||
{
|
||||
struct clk *clock;
|
||||
int i, error;
|
||||
|
||||
if (!ddata->clocks)
|
||||
return 0;
|
||||
|
||||
for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
|
||||
clock = ddata->clocks[i];
|
||||
|
||||
/* Assume no holes for opt clocks */
|
||||
if (IS_ERR_OR_NULL(clock))
|
||||
return 0;
|
||||
|
||||
error = clk_enable(clock);
|
||||
if (error)
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable:
|
||||
for (i--; i >= 0; i--) {
|
||||
clock = ddata->clocks[i];
|
||||
if (IS_ERR_OR_NULL(clock))
|
||||
continue;
|
||||
|
||||
clk_disable(clock);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void sysc_disable_opt_clocks(struct sysc *ddata)
|
||||
{
|
||||
struct clk *clock;
|
||||
int i;
|
||||
|
||||
if (!ddata->clocks)
|
||||
return;
|
||||
|
||||
for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
|
||||
clock = ddata->clocks[i];
|
||||
|
||||
/* Assume no holes for opt clocks */
|
||||
if (IS_ERR_OR_NULL(clock))
|
||||
return;
|
||||
|
||||
clk_disable(clock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sysc_init_resets - reset module on init
|
||||
* @ddata: device driver data
|
||||
|
@ -667,7 +773,7 @@ static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev,
|
|||
static int __maybe_unused sysc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct sysc *ddata;
|
||||
int error = 0, i;
|
||||
int error = 0;
|
||||
|
||||
ddata = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -682,15 +788,10 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
|
|||
return error;
|
||||
}
|
||||
|
||||
for (i = 0; i < ddata->nr_clocks; i++) {
|
||||
if (IS_ERR_OR_NULL(ddata->clocks[i]))
|
||||
continue;
|
||||
sysc_disable_main_clocks(ddata);
|
||||
|
||||
if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
|
||||
break;
|
||||
|
||||
clk_disable(ddata->clocks[i]);
|
||||
}
|
||||
if (sysc_opt_clks_needed(ddata))
|
||||
sysc_disable_opt_clocks(ddata);
|
||||
|
||||
ddata->enabled = false;
|
||||
|
||||
|
@ -700,7 +801,7 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
|
|||
static int __maybe_unused sysc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct sysc *ddata;
|
||||
int error = 0, i;
|
||||
int error = 0;
|
||||
|
||||
ddata = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -715,20 +816,24 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
|
|||
return error;
|
||||
}
|
||||
|
||||
for (i = 0; i < ddata->nr_clocks; i++) {
|
||||
if (IS_ERR_OR_NULL(ddata->clocks[i]))
|
||||
continue;
|
||||
|
||||
if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
|
||||
break;
|
||||
|
||||
error = clk_enable(ddata->clocks[i]);
|
||||
if (sysc_opt_clks_needed(ddata)) {
|
||||
error = sysc_enable_opt_clocks(ddata);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
error = sysc_enable_main_clocks(ddata);
|
||||
if (error)
|
||||
goto err_main_clocks;
|
||||
|
||||
ddata->enabled = true;
|
||||
|
||||
return 0;
|
||||
|
||||
err_main_clocks:
|
||||
if (sysc_opt_clks_needed(ddata))
|
||||
sysc_disable_opt_clocks(ddata);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue