Skip to content

Commit d878970

Browse files
committed
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 <[email protected]>
1 parent ff43728 commit d878970

File tree

1 file changed

+123
-18
lines changed

1 file changed

+123
-18
lines changed

drivers/bus/ti-sysc.c

Lines changed: 123 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,112 @@ static int sysc_get_clocks(struct sysc *ddata)
231231
return 0;
232232
}
233233

234+
static int sysc_enable_main_clocks(struct sysc *ddata)
235+
{
236+
struct clk *clock;
237+
int i, error;
238+
239+
if (!ddata->clocks)
240+
return 0;
241+
242+
for (i = 0; i < SYSC_OPTFCK0; i++) {
243+
clock = ddata->clocks[i];
244+
245+
/* Main clocks may not have ick */
246+
if (IS_ERR_OR_NULL(clock))
247+
continue;
248+
249+
error = clk_enable(clock);
250+
if (error)
251+
goto err_disable;
252+
}
253+
254+
return 0;
255+
256+
err_disable:
257+
for (i--; i >= 0; i--) {
258+
clock = ddata->clocks[i];
259+
260+
/* Main clocks may not have ick */
261+
if (IS_ERR_OR_NULL(clock))
262+
continue;
263+
264+
clk_disable(clock);
265+
}
266+
267+
return error;
268+
}
269+
270+
static void sysc_disable_main_clocks(struct sysc *ddata)
271+
{
272+
struct clk *clock;
273+
int i;
274+
275+
if (!ddata->clocks)
276+
return;
277+
278+
for (i = 0; i < SYSC_OPTFCK0; i++) {
279+
clock = ddata->clocks[i];
280+
if (IS_ERR_OR_NULL(clock))
281+
continue;
282+
283+
clk_disable(clock);
284+
}
285+
}
286+
287+
static int sysc_enable_opt_clocks(struct sysc *ddata)
288+
{
289+
struct clk *clock;
290+
int i, error;
291+
292+
if (!ddata->clocks)
293+
return 0;
294+
295+
for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
296+
clock = ddata->clocks[i];
297+
298+
/* Assume no holes for opt clocks */
299+
if (IS_ERR_OR_NULL(clock))
300+
return 0;
301+
302+
error = clk_enable(clock);
303+
if (error)
304+
goto err_disable;
305+
}
306+
307+
return 0;
308+
309+
err_disable:
310+
for (i--; i >= 0; i--) {
311+
clock = ddata->clocks[i];
312+
if (IS_ERR_OR_NULL(clock))
313+
continue;
314+
315+
clk_disable(clock);
316+
}
317+
318+
return error;
319+
}
320+
321+
static void sysc_disable_opt_clocks(struct sysc *ddata)
322+
{
323+
struct clk *clock;
324+
int i;
325+
326+
if (!ddata->clocks)
327+
return;
328+
329+
for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
330+
clock = ddata->clocks[i];
331+
332+
/* Assume no holes for opt clocks */
333+
if (IS_ERR_OR_NULL(clock))
334+
return;
335+
336+
clk_disable(clock);
337+
}
338+
}
339+
234340
/**
235341
* sysc_init_resets - reset module on init
236342
* @ddata: device driver data
@@ -667,7 +773,7 @@ static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev,
667773
static int __maybe_unused sysc_runtime_suspend(struct device *dev)
668774
{
669775
struct sysc *ddata;
670-
int error = 0, i;
776+
int error = 0;
671777

672778
ddata = dev_get_drvdata(dev);
673779

@@ -682,15 +788,10 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
682788
return error;
683789
}
684790

685-
for (i = 0; i < ddata->nr_clocks; i++) {
686-
if (IS_ERR_OR_NULL(ddata->clocks[i]))
687-
continue;
791+
sysc_disable_main_clocks(ddata);
688792

689-
if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
690-
break;
691-
692-
clk_disable(ddata->clocks[i]);
693-
}
793+
if (sysc_opt_clks_needed(ddata))
794+
sysc_disable_opt_clocks(ddata);
694795

695796
ddata->enabled = false;
696797

@@ -700,7 +801,7 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
700801
static int __maybe_unused sysc_runtime_resume(struct device *dev)
701802
{
702803
struct sysc *ddata;
703-
int error = 0, i;
804+
int error = 0;
704805

705806
ddata = dev_get_drvdata(dev);
706807

@@ -715,20 +816,24 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
715816
return error;
716817
}
717818

718-
for (i = 0; i < ddata->nr_clocks; i++) {
719-
if (IS_ERR_OR_NULL(ddata->clocks[i]))
720-
continue;
721-
722-
if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
723-
break;
724-
725-
error = clk_enable(ddata->clocks[i]);
819+
if (sysc_opt_clks_needed(ddata)) {
820+
error = sysc_enable_opt_clocks(ddata);
726821
if (error)
727822
return error;
728823
}
729824

825+
error = sysc_enable_main_clocks(ddata);
826+
if (error)
827+
goto err_main_clocks;
828+
730829
ddata->enabled = true;
731830

831+
return 0;
832+
833+
err_main_clocks:
834+
if (sysc_opt_clks_needed(ddata))
835+
sysc_disable_opt_clocks(ddata);
836+
732837
return error;
733838
}
734839

0 commit comments

Comments
 (0)