Merge tag 'armsoc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-block.git] / drivers / bus / ti-sysc.c
index 9207ac2913412e9da29daa41222930442fd37673..ad50efb470aaa296bdc9cae1ba7a3ea321ddcf1c 100644 (file)
@@ -280,9 +280,6 @@ static int sysc_get_one_clock(struct sysc *ddata, const char *name)
 
        ddata->clocks[index] = devm_clk_get(ddata->dev, name);
        if (IS_ERR(ddata->clocks[index])) {
-               if (PTR_ERR(ddata->clocks[index]) == -ENOENT)
-                       return 0;
-
                dev_err(ddata->dev, "clock get error for %s: %li\n",
                        name, PTR_ERR(ddata->clocks[index]));
 
@@ -357,7 +354,7 @@ static int sysc_get_clocks(struct sysc *ddata)
                        continue;
 
                error = sysc_get_one_clock(ddata, name);
-               if (error && error != -ENOENT)
+               if (error)
                        return error;
        }
 
@@ -1632,17 +1629,19 @@ static int sysc_init_module(struct sysc *ddata)
        if (error)
                return error;
 
-       if (manage_clocks) {
-               sysc_clkdm_deny_idle(ddata);
+       sysc_clkdm_deny_idle(ddata);
 
-               error = sysc_enable_opt_clocks(ddata);
-               if (error)
-                       return error;
+       /*
+        * Always enable clocks. The bootloader may or may not have enabled
+        * the related clocks.
+        */
+       error = sysc_enable_opt_clocks(ddata);
+       if (error)
+               return error;
 
-               error = sysc_enable_main_clocks(ddata);
-               if (error)
-                       goto err_opt_clocks;
-       }
+       error = sysc_enable_main_clocks(ddata);
+       if (error)
+               goto err_opt_clocks;
 
        if (!(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)) {
                error = sysc_rstctrl_reset_deassert(ddata, true);
@@ -1660,7 +1659,7 @@ static int sysc_init_module(struct sysc *ddata)
                        goto err_main_clocks;
        }
 
-       if (!ddata->legacy_mode && manage_clocks) {
+       if (!ddata->legacy_mode) {
                error = sysc_enable_module(ddata->dev);
                if (error)
                        goto err_main_clocks;
@@ -1677,6 +1676,7 @@ err_main_clocks:
        if (manage_clocks)
                sysc_disable_main_clocks(ddata);
 err_opt_clocks:
+       /* No re-enable of clockdomain autoidle to prevent module autoidle */
        if (manage_clocks) {
                sysc_disable_opt_clocks(ddata);
                sysc_clkdm_allow_idle(ddata);
@@ -2357,6 +2357,27 @@ static void ti_sysc_idle(struct work_struct *work)
 
        ddata = container_of(work, struct sysc, idle_work.work);
 
+       /*
+        * One time decrement of clock usage counts if left on from init.
+        * Note that we disable opt clocks unconditionally in this case
+        * as they are enabled unconditionally during init without
+        * considering sysc_opt_clks_needed() at that point.
+        */
+       if (ddata->cfg.quirks & (SYSC_QUIRK_NO_IDLE |
+                                SYSC_QUIRK_NO_IDLE_ON_INIT)) {
+               sysc_disable_main_clocks(ddata);
+               sysc_disable_opt_clocks(ddata);
+               sysc_clkdm_allow_idle(ddata);
+       }
+
+       /* Keep permanent PM runtime usage count for SYSC_QUIRK_NO_IDLE */
+       if (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE)
+               return;
+
+       /*
+        * Decrement PM runtime usage count for SYSC_QUIRK_NO_IDLE_ON_INIT
+        * and SYSC_QUIRK_NO_RESET_ON_INIT
+        */
        if (pm_runtime_active(ddata->dev))
                pm_runtime_put_sync(ddata->dev);
 }
@@ -2445,7 +2466,8 @@ static int sysc_probe(struct platform_device *pdev)
        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 |
+       if (ddata->cfg.quirks & (SYSC_QUIRK_NO_IDLE |
+                                SYSC_QUIRK_NO_IDLE_ON_INIT |
                                 SYSC_QUIRK_NO_RESET_ON_INIT)) {
                schedule_delayed_work(&ddata->idle_work, 3000);
        } else {