Skip to content

Commit 05cfb98

Browse files
jonhunterthierryreding
authored andcommitted
soc/tegra: pmc: Initialise resets associated with a power partition
When registering the Tegra power partitions with the generic PM domain framework, the current state of the each partition is checked and used as the default state for the partition. However, the state of each reset associated with the partition is not initialised and so it is possible that the state of the resets are not in the expected state. For example, if a partition is on, then the resets should be de-asserted and if the partition is off, the resets should be asserted. There have been cases where the bootloader has powered on a partition and only de-asserted some of the resets to some of the devices in the partition. This can cause accesses to these devices to hang the system when the kernel boots and attempts to probe these devices. Ideally, the driver for the device should ensure the reset has been de-asserted when probing, but the resets cannot be shared between the PMC driver (that needs to de-assert/assert the reset when turning the partition on or off) and another driver because we cannot ensure the reset is in the correct state. To ensure the resets are in the correct state, when using the generic PM domain framework, put each reset associated with the partition in the correct state (based upon the partition's current state) when obtaining the resets for a partition. Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
1 parent f5353c6 commit 05cfb98

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

drivers/soc/tegra/pmc.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
738738
}
739739

740740
static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
741-
struct device_node *np)
741+
struct device_node *np, bool off)
742742
{
743743
struct reset_control *rst;
744744
unsigned int i, count;
@@ -758,6 +758,16 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
758758
err = PTR_ERR(pg->resets[i]);
759759
goto error;
760760
}
761+
762+
if (off)
763+
err = reset_control_assert(pg->resets[i]);
764+
else
765+
err = reset_control_deassert(pg->resets[i]);
766+
767+
if (err) {
768+
reset_control_put(pg->resets[i]);
769+
goto error;
770+
}
761771
}
762772

763773
pg->num_resets = count;
@@ -798,14 +808,14 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
798808
pg->genpd.power_on = tegra_genpd_power_on;
799809
pg->pmc = pmc;
800810

811+
off = !tegra_powergate_is_powered(pg->id);
812+
801813
if (tegra_powergate_of_get_clks(pg, np))
802814
goto set_available;
803815

804-
if (tegra_powergate_of_get_resets(pg, np))
816+
if (tegra_powergate_of_get_resets(pg, np, off))
805817
goto remove_clks;
806818

807-
off = !tegra_powergate_is_powered(pg->id);
808-
809819
pm_genpd_init(&pg->genpd, NULL, off);
810820

811821
if (of_genpd_add_provider_simple(np, &pg->genpd))

0 commit comments

Comments
 (0)