soc: ti: Remove pm_runtime_irq_safe() usage for smartreflex
authorTony Lindgren <tony@atomide.com>
Mon, 9 Aug 2021 16:27:47 +0000 (11:27 -0500)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Tue, 10 Aug 2021 22:51:22 +0000 (15:51 -0700)
For the smartreflex device, we need to disable smartreflex on SoC idle,
and have been using pm_runtime_irq_safe() to do that. But we want to
remove the irq_safe usage as PM runtime takes a permanent usage count
on the parent device with it.

In order to remove the need for pm_runtime_irq_safe(), let's gate
the clock directly in the driver. This removes the need to call PM runtime
during idle, and allows us to switch to using CPU_PM in the following
patch.

Note that the smartreflex interconnect target module is configured for smart
idle, but the clock does not have autoidle capability, and needs to be gated
manually. If the clock supported autoidle, we would not need to even gate
the clock.

With this change, we can now remove the related quirk flags for ti-sysc
also.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
drivers/bus/ti-sysc.c
drivers/soc/ti/smartreflex.c
include/linux/power/smartreflex.h

index 38cb116..f87783a 100644 (file)
@@ -1444,10 +1444,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
                   SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET),
        SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE),
-       SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
-       SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x38, -ENODEV, 0x00000000, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff,
                   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
@@ -1583,6 +1579,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0),
        SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40000902, 0xffffffff, 0),
        SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40002903, 0xffffffff, 0),
+       SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff, 0),
+       SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x38, -ENODEV, 0x00000000, 0xffffffff, 0),
        SYSC_QUIRK("spinlock", 0, 0, 0x10, -ENODEV, 0x50020000, 0xffffffff, 0),
        SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -ENODEV, 0x00000020, 0xffffffff, 0),
        SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000013, 0xffffffff, 0),
index 06cbee5..b5b2fa5 100644 (file)
@@ -126,23 +126,13 @@ static irqreturn_t sr_interrupt(int irq, void *data)
 
 static void sr_set_clk_length(struct omap_sr *sr)
 {
-       struct clk *fck;
        u32 fclk_speed;
 
        /* Try interconnect target module fck first if it already exists */
-       fck = clk_get(sr->pdev->dev.parent, "fck");
-       if (IS_ERR(fck)) {
-               fck = clk_get(&sr->pdev->dev, "fck");
-               if (IS_ERR(fck)) {
-                       dev_err(&sr->pdev->dev,
-                               "%s: unable to get fck for device %s\n",
-                               __func__, dev_name(&sr->pdev->dev));
-                       return;
-               }
-       }
+       if (IS_ERR(sr->fck))
+               return;
 
-       fclk_speed = clk_get_rate(fck);
-       clk_put(fck);
+       fclk_speed = clk_get_rate(sr->fck);
 
        switch (fclk_speed) {
        case 12000000:
@@ -587,21 +577,25 @@ int sr_enable(struct omap_sr *sr, unsigned long volt)
        /* errminlimit is opp dependent and hence linked to voltage */
        sr->err_minlimit = nvalue_row->errminlimit;
 
-       pm_runtime_get_sync(&sr->pdev->dev);
+       clk_enable(sr->fck);
 
        /* Check if SR is already enabled. If yes do nothing */
        if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
-               return 0;
+               goto out_enabled;
 
        /* Configure SR */
        ret = sr_class->configure(sr);
        if (ret)
-               return ret;
+               goto out_enabled;
 
        sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
 
        /* SRCONFIG - enable SR */
        sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
+
+out_enabled:
+       sr->enabled = 1;
+
        return 0;
 }
 
@@ -621,7 +615,7 @@ void sr_disable(struct omap_sr *sr)
        }
 
        /* Check if SR clocks are already disabled. If yes do nothing */
-       if (pm_runtime_suspended(&sr->pdev->dev))
+       if (!sr->enabled)
                return;
 
        /*
@@ -642,7 +636,8 @@ void sr_disable(struct omap_sr *sr)
                }
        }
 
-       pm_runtime_put_sync_suspend(&sr->pdev->dev);
+       clk_disable(sr->fck);
+       sr->enabled = 0;
 }
 
 /**
@@ -851,8 +846,12 @@ static int omap_sr_probe(struct platform_device *pdev)
 
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 
+       sr_info->fck = devm_clk_get(pdev->dev.parent, "fck");
+       if (IS_ERR(sr_info->fck))
+               return PTR_ERR(sr_info->fck);
+       clk_prepare(sr_info->fck);
+
        pm_runtime_enable(&pdev->dev);
-       pm_runtime_irq_safe(&pdev->dev);
 
        snprintf(sr_info->name, SMARTREFLEX_NAME_LEN, "%s", pdata->name);
 
@@ -878,12 +877,6 @@ static int omap_sr_probe(struct platform_device *pdev)
 
        list_add(&sr_info->node, &sr_list);
 
-       ret = pm_runtime_get_sync(&pdev->dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(&pdev->dev);
-               goto err_list_del;
-       }
-
        /*
         * Call into late init to do initializations that require
         * both sr driver and sr class driver to be initiallized.
@@ -933,16 +926,13 @@ static int omap_sr_probe(struct platform_device *pdev)
 
        }
 
-       pm_runtime_put_sync(&pdev->dev);
-
        return ret;
 
 err_debugfs:
        debugfs_remove_recursive(sr_info->dbg_dir);
 err_list_del:
        list_del(&sr_info->node);
-
-       pm_runtime_put_sync(&pdev->dev);
+       clk_unprepare(sr_info->fck);
 
        return ret;
 }
@@ -950,6 +940,7 @@ err_list_del:
 static int omap_sr_remove(struct platform_device *pdev)
 {
        struct omap_sr_data *pdata = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
        struct omap_sr *sr_info;
 
        if (!pdata) {
@@ -968,7 +959,8 @@ static int omap_sr_remove(struct platform_device *pdev)
                sr_stop_vddautocomp(sr_info);
        debugfs_remove_recursive(sr_info->dbg_dir);
 
-       pm_runtime_disable(&pdev->dev);
+       pm_runtime_disable(dev);
+       clk_unprepare(sr_info->fck);
        list_del(&sr_info->node);
        return 0;
 }
index 971c926..167b9b0 100644 (file)
@@ -155,6 +155,7 @@ struct omap_sr {
        struct voltagedomain            *voltdm;
        struct dentry                   *dbg_dir;
        unsigned int                    irq;
+       struct clk                      *fck;
        int                             srid;
        int                             ip_type;
        int                             nvalue_count;
@@ -169,6 +170,7 @@ struct omap_sr {
        u32                             senp_mod;
        u32                             senn_mod;
        void __iomem                    *base;
+       unsigned long                   enabled:1;
 };
 
 /**