aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Hunter <jonathanh@nvidia.com>2016-06-30 06:56:25 -0400
committerThierry Reding <treding@nvidia.com>2016-06-30 07:41:46 -0400
commite2d17960532d925a202682ce72379c6055068ca4 (patch)
tree2e0b6b1d93afc4239bc2c1b799f2064317c20823
parentc2710ac9f5a8dab4f9bb080713452fe6286ca83d (diff)
soc/tegra: pmc: Initialise power partitions early
If CONFIG_PM_GENERIC_DOMAINS is not enabled, then power partitions associated with a device will not be enabled automatically by the PM core when the device is in use. To avoid situations where a device in a power partition is to be used but the partition is not enabled, initialise the power partitions for Tegra early in the boot process and if CONFIG_PM_GENERIC_DOMAINS is not enabled, then power on all partitions defined in the device-tree blob. Note that if CONFIG_PM_GENERIC_DOMAINS is not enabled, after the partitions are turned on, the clocks and resets used as part of the sequence for turning on the partition are released again as they are no longer needed by the PMC driver. Another benefit of this is that this avoids any issues of sharing resets between the PMC driver and other device drivers that may wish to independently control a particular reset. Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/soc/tegra/pmc.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index ecc1ec0a4ada..7199726198e1 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -834,6 +834,9 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
834 goto remove_clks; 834 goto remove_clks;
835 } 835 }
836 836
837 if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
838 goto power_on_cleanup;
839
837 pm_genpd_init(&pg->genpd, NULL, off); 840 pm_genpd_init(&pg->genpd, NULL, off);
838 841
839 err = of_genpd_add_provider_simple(np, &pg->genpd); 842 err = of_genpd_add_provider_simple(np, &pg->genpd);
@@ -847,6 +850,10 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
847 850
848 return; 851 return;
849 852
853power_on_cleanup:
854 if (off)
855 WARN_ON(tegra_powergate_power_up(pg, true));
856
850remove_resets: 857remove_resets:
851 while (pg->num_resets--) 858 while (pg->num_resets--)
852 reset_control_put(pg->resets[pg->num_resets]); 859 reset_control_put(pg->resets[pg->num_resets]);
@@ -866,11 +873,18 @@ free_mem:
866 kfree(pg); 873 kfree(pg);
867} 874}
868 875
869static void tegra_powergate_init(struct tegra_pmc *pmc) 876static void tegra_powergate_init(struct tegra_pmc *pmc,
877 struct device_node *parent)
870{ 878{
871 struct device_node *np, *child; 879 struct device_node *np, *child;
880 unsigned int i;
872 881
873 np = of_get_child_by_name(pmc->dev->of_node, "powergates"); 882 /* Create a bitmap of the available and valid partitions */
883 for (i = 0; i < pmc->soc->num_powergates; i++)
884 if (pmc->soc->powergates[i])
885 set_bit(i, pmc->powergates_available);
886
887 np = of_get_child_by_name(parent, "powergates");
874 if (!np) 888 if (!np)
875 return; 889 return;
876 890
@@ -1291,8 +1305,6 @@ static int tegra_pmc_probe(struct platform_device *pdev)
1291 return err; 1305 return err;
1292 } 1306 }
1293 1307
1294 tegra_powergate_init(pmc);
1295
1296 mutex_lock(&pmc->powergates_lock); 1308 mutex_lock(&pmc->powergates_lock);
1297 iounmap(pmc->base); 1309 iounmap(pmc->base);
1298 pmc->base = base; 1310 pmc->base = base;
@@ -1526,7 +1538,6 @@ static int __init tegra_pmc_early_init(void)
1526 const struct of_device_id *match; 1538 const struct of_device_id *match;
1527 struct device_node *np; 1539 struct device_node *np;
1528 struct resource regs; 1540 struct resource regs;
1529 unsigned int i;
1530 bool invert; 1541 bool invert;
1531 u32 value; 1542 u32 value;
1532 1543
@@ -1581,10 +1592,7 @@ static int __init tegra_pmc_early_init(void)
1581 if (np) { 1592 if (np) {
1582 pmc->soc = match->data; 1593 pmc->soc = match->data;
1583 1594
1584 /* Create a bit-map of the available and valid partitions */ 1595 tegra_powergate_init(pmc, np);
1585 for (i = 0; i < pmc->soc->num_powergates; i++)
1586 if (pmc->soc->powergates[i])
1587 set_bit(i, pmc->powergates_available);
1588 1596
1589 /* 1597 /*
1590 * Invert the interrupt polarity if a PMC device tree node 1598 * Invert the interrupt polarity if a PMC device tree node