| From a83f1fc3f33930d01e579b9d4de92a045297b402 Mon Sep 17 00:00:00 2001 |
| From: Jon Hunter <jonathanh@nvidia.com> |
| Date: Tue, 28 Jun 2016 11:38:28 +0100 |
| Subject: soc/tegra: pmc: Don't probe PMC if early initialisation fails |
| |
| From: Jon Hunter <jonathanh@nvidia.com> |
| |
| commit a83f1fc3f33930d01e579b9d4de92a045297b402 upstream. |
| |
| Commit 0259f522e04f ('soc/tegra: pmc: Restore base address on probe |
| failure') fixes an issue where the PMC base address pointer is not |
| restored on probe failure. However, this fix creates another problem |
| where if early initialisation of the PMC driver fails and an initial |
| mapping for the PMC address space is not created, then when the PMC |
| device is probed, the PMC base address pointer will not be valid and |
| this will cause a crash when tegra_pmc_init() is called and attempts |
| to access a register. |
| |
| Although the PMC address space is mapped a 2nd time during the probe |
| and so this could be fixed by populating the base address pointer |
| earlier during the probe, this adds more complexity to the code. |
| Moreover, the PMC probe also assumes the the soc data pointer is also |
| initialised when the device is probed and if not will also lead to a |
| crash when calling tegra_pmc_init_tsense_reset(). Given that if the |
| early initialisation does fail then something bad has happen, it seems |
| acceptable to allow the PMC device probe to fail as well. Therefore, if |
| the PMC base address pointer or soc data pointer are not valid when |
| probing the PMC device, WARN and return an error. |
| |
| Fixes: 0259f522e04f ('soc/tegra: pmc: Restore base address on probe failure') |
| Signed-off-by: Jon Hunter <jonathanh@nvidia.com> |
| Signed-off-by: Thierry Reding <treding@nvidia.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/soc/tegra/pmc.c | 8 ++++++++ |
| 1 file changed, 8 insertions(+) |
| |
| --- a/drivers/soc/tegra/pmc.c |
| +++ b/drivers/soc/tegra/pmc.c |
| @@ -1205,6 +1205,14 @@ static int tegra_pmc_probe(struct platfo |
| struct resource *res; |
| int err; |
| |
| + /* |
| + * Early initialisation should have configured an initial |
| + * register mapping and setup the soc data pointer. If these |
| + * are not valid then something went badly wrong! |
| + */ |
| + if (WARN_ON(!pmc->base || !pmc->soc)) |
| + return -ENODEV; |
| + |
| err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node); |
| if (err < 0) |
| return err; |