All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] soc/tegra: Various PMC fixes
@ 2016-06-28 10:38 ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jon Hunter

A few fixes for the Tegra PMC driver.

Jon Hunter (6):
  soc/tegra: pmc: Ensure powergate is available when powering on
  soc/tegra: pmc: Fix early initialisation of PMC
  soc/tegra: pmc: Don't populate soc data until register space is mapped
  soc/tegra: pmc: Ensure mutex is always initialised
  soc/tegra: pmc: Add missing of_node_put
  soc/tegra: pmc: Don't probe pmc if early initialisation fails

 drivers/soc/tegra/pmc.c | 51 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 18 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 0/6] soc/tegra: Various PMC fixes
@ 2016-06-28 10:38 ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

A few fixes for the Tegra PMC driver.

Jon Hunter (6):
  soc/tegra: pmc: Ensure powergate is available when powering on
  soc/tegra: pmc: Fix early initialisation of PMC
  soc/tegra: pmc: Don't populate soc data until register space is mapped
  soc/tegra: pmc: Ensure mutex is always initialised
  soc/tegra: pmc: Add missing of_node_put
  soc/tegra: pmc: Don't probe pmc if early initialisation fails

 drivers/soc/tegra/pmc.c | 51 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 18 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/6] soc/tegra: pmc: Ensure powergate is available when powering on
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-28 10:38   ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

The function tegra_power_sequence_power_up() is a public function used
to power on a partition. When this function is called, we do not check
to see if the partition being powered up is valid/available. Fix this
by checking to see that the partition is valid/available.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 8a421a0b1ece..52a9e9703668 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -549,6 +549,9 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
 	struct tegra_powergate pg;
 	int err;
 
+	if (!tegra_powergate_is_available(id))
+		return -EINVAL;
+
 	pg.id = id;
 	pg.clks = &clk;
 	pg.num_clks = 1;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 1/6] soc/tegra: pmc: Ensure powergate is available when powering on
@ 2016-06-28 10:38   ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

The function tegra_power_sequence_power_up() is a public function used
to power on a partition. When this function is called, we do not check
to see if the partition being powered up is valid/available. Fix this
by checking to see that the partition is valid/available.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 8a421a0b1ece..52a9e9703668 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -549,6 +549,9 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
 	struct tegra_powergate pg;
 	int err;
 
+	if (!tegra_powergate_is_available(id))
+		return -EINVAL;
+
 	pg.id = id;
 	pg.clks = &clk;
 	pg.num_clks = 1;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 2/6] soc/tegra: pmc: Fix early initialisation of PMC
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-28 10:38     ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jon Hunter

During early initialisation, the available power partitions for a given
device is configured as well as the polarity of the PMC interrupt. Both
of which should only be configured if there is a valid device node for
the PMC device. This is because the soc data used for configuring the
power partitions is only available if a device node for the PMC is found
and the code to configure the interrupt polarity uses the device node
pointer directly.

Some early device-tree images may not have this device node and so fix
this by ensuring the device node pointer is valid when configuring these
items.

Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/soc/tegra/pmc.c | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 52a9e9703668..2e031c4ad547 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1550,27 +1550,29 @@ static int __init tegra_pmc_early_init(void)
 		return -ENXIO;
 	}
 
-	/* Create a bit-map of the available and valid partitions */
-	for (i = 0; i < pmc->soc->num_powergates; i++)
-		if (pmc->soc->powergates[i])
-			set_bit(i, pmc->powergates_available);
-
 	mutex_init(&pmc->powergates_lock);
 
-	/*
-	 * Invert the interrupt polarity if a PMC device tree node exists and
-	 * contains the nvidia,invert-interrupt property.
-	 */
-	invert = of_property_read_bool(np, "nvidia,invert-interrupt");
+	if (np) {
+		/* Create a bit-map of the available and valid partitions */
+		for (i = 0; i < pmc->soc->num_powergates; i++)
+			if (pmc->soc->powergates[i])
+				set_bit(i, pmc->powergates_available);
 
-	value = tegra_pmc_readl(PMC_CNTRL);
+		/*
+		 * Invert the interrupt polarity if a PMC device tree node
+		 * exists and contains the nvidia,invert-interrupt property.
+		 */
+		invert = of_property_read_bool(np, "nvidia,invert-interrupt");
 
-	if (invert)
-		value |= PMC_CNTRL_INTR_POLARITY;
-	else
-		value &= ~PMC_CNTRL_INTR_POLARITY;
+		value = tegra_pmc_readl(PMC_CNTRL);
 
-	tegra_pmc_writel(value, PMC_CNTRL);
+		if (invert)
+			value |= PMC_CNTRL_INTR_POLARITY;
+		else
+			value &= ~PMC_CNTRL_INTR_POLARITY;
+
+		tegra_pmc_writel(value, PMC_CNTRL);
+	}
 
 	return 0;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 2/6] soc/tegra: pmc: Fix early initialisation of PMC
@ 2016-06-28 10:38     ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

During early initialisation, the available power partitions for a given
device is configured as well as the polarity of the PMC interrupt. Both
of which should only be configured if there is a valid device node for
the PMC device. This is because the soc data used for configuring the
power partitions is only available if a device node for the PMC is found
and the code to configure the interrupt polarity uses the device node
pointer directly.

Some early device-tree images may not have this device node and so fix
this by ensuring the device node pointer is valid when configuring these
items.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 52a9e9703668..2e031c4ad547 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1550,27 +1550,29 @@ static int __init tegra_pmc_early_init(void)
 		return -ENXIO;
 	}
 
-	/* Create a bit-map of the available and valid partitions */
-	for (i = 0; i < pmc->soc->num_powergates; i++)
-		if (pmc->soc->powergates[i])
-			set_bit(i, pmc->powergates_available);
-
 	mutex_init(&pmc->powergates_lock);
 
-	/*
-	 * Invert the interrupt polarity if a PMC device tree node exists and
-	 * contains the nvidia,invert-interrupt property.
-	 */
-	invert = of_property_read_bool(np, "nvidia,invert-interrupt");
+	if (np) {
+		/* Create a bit-map of the available and valid partitions */
+		for (i = 0; i < pmc->soc->num_powergates; i++)
+			if (pmc->soc->powergates[i])
+				set_bit(i, pmc->powergates_available);
 
-	value = tegra_pmc_readl(PMC_CNTRL);
+		/*
+		 * Invert the interrupt polarity if a PMC device tree node
+		 * exists and contains the nvidia,invert-interrupt property.
+		 */
+		invert = of_property_read_bool(np, "nvidia,invert-interrupt");
 
-	if (invert)
-		value |= PMC_CNTRL_INTR_POLARITY;
-	else
-		value &= ~PMC_CNTRL_INTR_POLARITY;
+		value = tegra_pmc_readl(PMC_CNTRL);
 
-	tegra_pmc_writel(value, PMC_CNTRL);
+		if (invert)
+			value |= PMC_CNTRL_INTR_POLARITY;
+		else
+			value &= ~PMC_CNTRL_INTR_POLARITY;
+
+		tegra_pmc_writel(value, PMC_CNTRL);
+	}
 
 	return 0;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 3/6] soc/tegra: pmc: Don't populate soc data until register space is mapped
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-28 10:38   ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

The public functions exported by the PMC driver use the presence of the
soc data pointer to determine if the PMC device is configured and the
registers can be accessed. However, the soc data is populated before the
PMC register space is mapped and this opens a window where the soc data
pointer is valid but the register space has not yet been mapped which
could lead to a crash. Furthermore, if the mapping of the PMC register
space fails, then the soc data pointer is not cleared and so would
expose a larger window where a crash could occur.

Fix this by initialising the soc data pointer after the PMC register
space has been mapped.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 2e031c4ad547..ed2b2c83e4eb 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1540,8 +1540,6 @@ static int __init tegra_pmc_early_init(void)
 			pr_err("failed to get PMC registers\n");
 			return -ENXIO;
 		}
-
-		pmc->soc = match->data;
 	}
 
 	pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
@@ -1553,6 +1551,8 @@ static int __init tegra_pmc_early_init(void)
 	mutex_init(&pmc->powergates_lock);
 
 	if (np) {
+		pmc->soc = match->data;
+
 		/* Create a bit-map of the available and valid partitions */
 		for (i = 0; i < pmc->soc->num_powergates; i++)
 			if (pmc->soc->powergates[i])
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 3/6] soc/tegra: pmc: Don't populate soc data until register space is mapped
@ 2016-06-28 10:38   ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

The public functions exported by the PMC driver use the presence of the
soc data pointer to determine if the PMC device is configured and the
registers can be accessed. However, the soc data is populated before the
PMC register space is mapped and this opens a window where the soc data
pointer is valid but the register space has not yet been mapped which
could lead to a crash. Furthermore, if the mapping of the PMC register
space fails, then the soc data pointer is not cleared and so would
expose a larger window where a crash could occur.

Fix this by initialising the soc data pointer after the PMC register
space has been mapped.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 2e031c4ad547..ed2b2c83e4eb 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1540,8 +1540,6 @@ static int __init tegra_pmc_early_init(void)
 			pr_err("failed to get PMC registers\n");
 			return -ENXIO;
 		}
-
-		pmc->soc = match->data;
 	}
 
 	pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
@@ -1553,6 +1551,8 @@ static int __init tegra_pmc_early_init(void)
 	mutex_init(&pmc->powergates_lock);
 
 	if (np) {
+		pmc->soc = match->data;
+
 		/* Create a bit-map of the available and valid partitions */
 		for (i = 0; i < pmc->soc->num_powergates; i++)
 			if (pmc->soc->powergates[i])
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 4/6] soc/tegra: pmc: Ensure mutex is always initialised
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-28 10:38   ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

The mutex used by the PMC driver may not be initialised if early
initialisation of the driver fails. If this does happen, then it could
be possible for callers of the public PMC functions to still attempt to
acquire the mutex. Fix this by initialising the mutex as soon as
possible to ensure it will always be initialised.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index ed2b2c83e4eb..483d54623ec5 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1504,6 +1504,8 @@ static int __init tegra_pmc_early_init(void)
 	bool invert;
 	u32 value;
 
+	mutex_init(&pmc->powergates_lock);
+
 	np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
 	if (!np) {
 		/*
@@ -1548,8 +1550,6 @@ static int __init tegra_pmc_early_init(void)
 		return -ENXIO;
 	}
 
-	mutex_init(&pmc->powergates_lock);
-
 	if (np) {
 		pmc->soc = match->data;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 4/6] soc/tegra: pmc: Ensure mutex is always initialised
@ 2016-06-28 10:38   ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

The mutex used by the PMC driver may not be initialised if early
initialisation of the driver fails. If this does happen, then it could
be possible for callers of the public PMC functions to still attempt to
acquire the mutex. Fix this by initialising the mutex as soon as
possible to ensure it will always be initialised.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index ed2b2c83e4eb..483d54623ec5 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1504,6 +1504,8 @@ static int __init tegra_pmc_early_init(void)
 	bool invert;
 	u32 value;
 
+	mutex_init(&pmc->powergates_lock);
+
 	np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
 	if (!np) {
 		/*
@@ -1548,8 +1550,6 @@ static int __init tegra_pmc_early_init(void)
 		return -ENXIO;
 	}
 
-	mutex_init(&pmc->powergates_lock);
-
 	if (np) {
 		pmc->soc = match->data;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 5/6] soc/tegra: pmc: Add missing of_node_put
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-28 10:38   ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

Add missing of_node_put() in PMC early initialisation function.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 483d54623ec5..e62acaef140a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1572,6 +1572,8 @@ static int __init tegra_pmc_early_init(void)
 			value &= ~PMC_CNTRL_INTR_POLARITY;
 
 		tegra_pmc_writel(value, PMC_CNTRL);
+
+		of_node_put(np);
 	}
 
 	return 0;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 5/6] soc/tegra: pmc: Add missing of_node_put
@ 2016-06-28 10:38   ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

Add missing of_node_put() in PMC early initialisation function.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 483d54623ec5..e62acaef140a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1572,6 +1572,8 @@ static int __init tegra_pmc_early_init(void)
 			value &= ~PMC_CNTRL_INTR_POLARITY;
 
 		tegra_pmc_writel(value, PMC_CNTRL);
+
+		of_node_put(np);
 	}
 
 	return 0;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 6/6] soc/tegra: pmc: Don't probe pmc if early initialisation fails
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-28 10:38   ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

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>
---

I am not too happy with this. The more I was looking at the transition
from the early init code to the driver probe the more holes I saw. I
tried to see if I could handle this better in the probe itself, but it
was adding a lot more code to the probe. So this was a simple way to
at least make it more robust.

If this approach is not acceptable, then how about if we simplify matters
in the probe, and if the probe fails then set the 'pmc->base' and 'pmc->soc'
pointers to NULL and not worry about restoring the initial base address?
Yes it may prevent users from controlling the powergates, but if the probe
fails then there are probably other problems and so may be we don't care.

 drivers/soc/tegra/pmc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index e62acaef140a..d5635db78b61 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1228,6 +1228,14 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 	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;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 6/6] soc/tegra: pmc: Don't probe pmc if early initialisation fails
@ 2016-06-28 10:38   ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:38 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel, Jon Hunter

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>
---

I am not too happy with this. The more I was looking at the transition
from the early init code to the driver probe the more holes I saw. I
tried to see if I could handle this better in the probe itself, but it
was adding a lot more code to the probe. So this was a simple way to
at least make it more robust.

If this approach is not acceptable, then how about if we simplify matters
in the probe, and if the probe fails then set the 'pmc->base' and 'pmc->soc'
pointers to NULL and not worry about restoring the initial base address?
Yes it may prevent users from controlling the powergates, but if the probe
fails then there are probably other problems and so may be we don't care.

 drivers/soc/tegra/pmc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index e62acaef140a..d5635db78b61 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1228,6 +1228,14 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 	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;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/6] soc/tegra: Various PMC fixes
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-28 10:40     ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:40 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA


On 28/06/16 11:38, Jon Hunter wrote:
> A few fixes for the Tegra PMC driver.
> 
> Jon Hunter (6):
>   soc/tegra: pmc: Ensure powergate is available when powering on
>   soc/tegra: pmc: Fix early initialisation of PMC
>   soc/tegra: pmc: Don't populate soc data until register space is mapped
>   soc/tegra: pmc: Ensure mutex is always initialised
>   soc/tegra: pmc: Add missing of_node_put
>   soc/tegra: pmc: Don't probe pmc if early initialisation fails
> 
>  drivers/soc/tegra/pmc.c | 51 ++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 18 deletions(-)

Forgot to mentioned this is based upon the DPAUX series [0] as that also
has a change for the pmc driver.

Cheers
Jon

[0] http://marc.info/?l=linux-tegra&m=146669756307955&w=2

-- 
nvpublic

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/6] soc/tegra: Various PMC fixes
@ 2016-06-28 10:40     ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:40 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel


On 28/06/16 11:38, Jon Hunter wrote:
> A few fixes for the Tegra PMC driver.
> 
> Jon Hunter (6):
>   soc/tegra: pmc: Ensure powergate is available when powering on
>   soc/tegra: pmc: Fix early initialisation of PMC
>   soc/tegra: pmc: Don't populate soc data until register space is mapped
>   soc/tegra: pmc: Ensure mutex is always initialised
>   soc/tegra: pmc: Add missing of_node_put
>   soc/tegra: pmc: Don't probe pmc if early initialisation fails
> 
>  drivers/soc/tegra/pmc.c | 51 ++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 18 deletions(-)

Forgot to mentioned this is based upon the DPAUX series [0] as that also
has a change for the pmc driver.

Cheers
Jon

[0] http://marc.info/?l=linux-tegra&m=146669756307955&w=2

-- 
nvpublic

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/6] soc/tegra: pmc: Add missing of_node_put
  2016-06-28 10:38   ` Jon Hunter
@ 2016-06-28 10:46     ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:46 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel


On 28/06/16 11:38, Jon Hunter wrote:
> Add missing of_node_put() in PMC early initialisation function.
> 
> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>  drivers/soc/tegra/pmc.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 483d54623ec5..e62acaef140a 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -1572,6 +1572,8 @@ static int __init tegra_pmc_early_init(void)
>  			value &= ~PMC_CNTRL_INTR_POLARITY;
>  
>  		tegra_pmc_writel(value, PMC_CNTRL);
> +
> +		of_node_put(np);
>  	}
>  
>  	return 0;

Actually there are a couple other places we should put the node ...

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 483d54623ec5..48e1de2f7aeb 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1540,6 +1540,7 @@ static int __init tegra_pmc_early_init(void)
                 */
                if (of_address_to_resource(np, 0, &regs) < 0) {
                        pr_err("failed to get PMC registers\n");
+                       of_node_put(np);
                        return -ENXIO;
                }
        }
@@ -1547,6 +1548,7 @@ static int __init tegra_pmc_early_init(void)
        pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
        if (!pmc->base) {
                pr_err("failed to map PMC registers\n");
+               of_node_put(np);
                return -ENXIO;
        }

@@ -1572,6 +1574,8 @@ static int __init tegra_pmc_early_init(void)
                        value &= ~PMC_CNTRL_INTR_POLARITY;

                tegra_pmc_writel(value, PMC_CNTRL);
+
+               of_node_put(np);
        }

        return 0;

-- 
nvpublic

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/6] soc/tegra: pmc: Add missing of_node_put
@ 2016-06-28 10:46     ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-28 10:46 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel


On 28/06/16 11:38, Jon Hunter wrote:
> Add missing of_node_put() in PMC early initialisation function.
> 
> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>  drivers/soc/tegra/pmc.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 483d54623ec5..e62acaef140a 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -1572,6 +1572,8 @@ static int __init tegra_pmc_early_init(void)
>  			value &= ~PMC_CNTRL_INTR_POLARITY;
>  
>  		tegra_pmc_writel(value, PMC_CNTRL);
> +
> +		of_node_put(np);
>  	}
>  
>  	return 0;

Actually there are a couple other places we should put the node ...

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 483d54623ec5..48e1de2f7aeb 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1540,6 +1540,7 @@ static int __init tegra_pmc_early_init(void)
                 */
                if (of_address_to_resource(np, 0, &regs) < 0) {
                        pr_err("failed to get PMC registers\n");
+                       of_node_put(np);
                        return -ENXIO;
                }
        }
@@ -1547,6 +1548,7 @@ static int __init tegra_pmc_early_init(void)
        pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
        if (!pmc->base) {
                pr_err("failed to map PMC registers\n");
+               of_node_put(np);
                return -ENXIO;
        }

@@ -1572,6 +1574,8 @@ static int __init tegra_pmc_early_init(void)
                        value &= ~PMC_CNTRL_INTR_POLARITY;

                tegra_pmc_writel(value, PMC_CNTRL);
+
+               of_node_put(np);
        }

        return 0;

-- 
nvpublic

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/6] soc/tegra: pmc: Fix early initialisation of PMC
  2016-06-28 10:38     ` Jon Hunter
@ 2016-06-29 16:17         ` Jon Hunter
  -1 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-29 16:17 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA


On 28/06/16 11:38, Jon Hunter wrote:
> During early initialisation, the available power partitions for a given
> device is configured as well as the polarity of the PMC interrupt. Both
> of which should only be configured if there is a valid device node for
> the PMC device. This is because the soc data used for configuring the
> power partitions is only available if a device node for the PMC is found
> and the code to configure the interrupt polarity uses the device node
> pointer directly.
> 
> Some early device-tree images may not have this device node and so fix
> this by ensuring the device node pointer is valid when configuring these
> items.
> 
> Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> ---
>  drivers/soc/tegra/pmc.c | 34 ++++++++++++++++++----------------
>  1 file changed, 18 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 52a9e9703668..2e031c4ad547 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -1550,27 +1550,29 @@ static int __init tegra_pmc_early_init(void)
>  		return -ENXIO;
>  	}
>  
> -	/* Create a bit-map of the available and valid partitions */
> -	for (i = 0; i < pmc->soc->num_powergates; i++)
> -		if (pmc->soc->powergates[i])
> -			set_bit(i, pmc->powergates_available);
> -
>  	mutex_init(&pmc->powergates_lock);
>  
> -	/*
> -	 * Invert the interrupt polarity if a PMC device tree node exists and
> -	 * contains the nvidia,invert-interrupt property.
> -	 */
> -	invert = of_property_read_bool(np, "nvidia,invert-interrupt");
> +	if (np) {
> +		/* Create a bit-map of the available and valid partitions */
> +		for (i = 0; i < pmc->soc->num_powergates; i++)
> +			if (pmc->soc->powergates[i])
> +				set_bit(i, pmc->powergates_available);
>  
> -	value = tegra_pmc_readl(PMC_CNTRL);
> +		/*
> +		 * Invert the interrupt polarity if a PMC device tree node
> +		 * exists and contains the nvidia,invert-interrupt property.
> +		 */
> +		invert = of_property_read_bool(np, "nvidia,invert-interrupt");
>  
> -	if (invert)
> -		value |= PMC_CNTRL_INTR_POLARITY;
> -	else
> -		value &= ~PMC_CNTRL_INTR_POLARITY;
> +		value = tegra_pmc_readl(PMC_CNTRL);
>  
> -	tegra_pmc_writel(value, PMC_CNTRL);
> +		if (invert)
> +			value |= PMC_CNTRL_INTR_POLARITY;
> +		else
> +			value &= ~PMC_CNTRL_INTR_POLARITY;
> +
> +		tegra_pmc_writel(value, PMC_CNTRL);
> +	}
>  
>  	return 0;
>  }

By the way, the more I think about this, if there is no valid 'pmc'
node in the device-tree blob, then I wonder if we should even bother
mapping the pmc address space at all? The reason being, if there is
no 'pmc' node then we cannot look-up the SoC data and so all the
public PMC APIs are pretty useless AFAICT. I wonder if we should do
something like ...

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index e09c7ed385f6..34d1385d7ef0 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1510,7 +1510,6 @@ static int __init tegra_pmc_early_init(void)
 {
        const struct of_device_id *match;
        struct device_node *np;
-       struct resource regs;
        unsigned int i;
        bool invert;
        u32 value;
@@ -1520,73 +1519,47 @@ static int __init tegra_pmc_early_init(void)
        np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
        if (!np) {
                /*
-                * Fall back to legacy initialization for 32-bit ARM only. All
-                * 64-bit ARM device tree files for Tegra are required to have
-                * a PMC node.
-                *
-                * This is for backwards-compatibility with old device trees
-                * that didn't contain a PMC node. Note that in this case the
-                * SoC data can't be matched and therefore powergating is
-                * disabled.
+                * All 64-bit ARM device tree files for Tegra are required to
+                * have a PMC node. For old 32-bit Tegra device trees that
+                * don't contain a PMC node, the SoC data can't be matched
+                * and therefore powergating is disabled.
                 */
-               if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
+               if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra())
                        pr_warn("DT node not found, powergating disabled\n");
 
-                       regs.start = 0x7000e400;
-                       regs.end = 0x7000e7ff;
-                       regs.flags = IORESOURCE_MEM;
-
-                       pr_warn("Using memory region %pR\n", &regs);
-               } else {
-                       /*
-                        * At this point we're not running on Tegra, so play
-                        * nice with multi-platform kernels.
-                        */
-                       return 0;
-               }
-       } else {
-               /*
-                * Extract information from the device tree if we've found a
-                * matching node.
-                */
-               if (of_address_to_resource(np, 0, &regs) < 0) {
-                       pr_err("failed to get PMC registers\n");
-                       return -ENXIO;
-               }
+               return 0;
        }
 
-       pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
+       pmc->base = of_iomap(np, 0);
        if (!pmc->base) {
                pr_err("failed to map PMC registers\n");
                of_node_put(np);
                return -ENXIO;
        }

Cheers
Jon
 

-- 
nvpublic

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/6] soc/tegra: pmc: Fix early initialisation of PMC
@ 2016-06-29 16:17         ` Jon Hunter
  0 siblings, 0 replies; 24+ messages in thread
From: Jon Hunter @ 2016-06-29 16:17 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot
  Cc: linux-tegra, linux-kernel


On 28/06/16 11:38, Jon Hunter wrote:
> During early initialisation, the available power partitions for a given
> device is configured as well as the polarity of the PMC interrupt. Both
> of which should only be configured if there is a valid device node for
> the PMC device. This is because the soc data used for configuring the
> power partitions is only available if a device node for the PMC is found
> and the code to configure the interrupt polarity uses the device node
> pointer directly.
> 
> Some early device-tree images may not have this device node and so fix
> this by ensuring the device node pointer is valid when configuring these
> items.
> 
> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>  drivers/soc/tegra/pmc.c | 34 ++++++++++++++++++----------------
>  1 file changed, 18 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 52a9e9703668..2e031c4ad547 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -1550,27 +1550,29 @@ static int __init tegra_pmc_early_init(void)
>  		return -ENXIO;
>  	}
>  
> -	/* Create a bit-map of the available and valid partitions */
> -	for (i = 0; i < pmc->soc->num_powergates; i++)
> -		if (pmc->soc->powergates[i])
> -			set_bit(i, pmc->powergates_available);
> -
>  	mutex_init(&pmc->powergates_lock);
>  
> -	/*
> -	 * Invert the interrupt polarity if a PMC device tree node exists and
> -	 * contains the nvidia,invert-interrupt property.
> -	 */
> -	invert = of_property_read_bool(np, "nvidia,invert-interrupt");
> +	if (np) {
> +		/* Create a bit-map of the available and valid partitions */
> +		for (i = 0; i < pmc->soc->num_powergates; i++)
> +			if (pmc->soc->powergates[i])
> +				set_bit(i, pmc->powergates_available);
>  
> -	value = tegra_pmc_readl(PMC_CNTRL);
> +		/*
> +		 * Invert the interrupt polarity if a PMC device tree node
> +		 * exists and contains the nvidia,invert-interrupt property.
> +		 */
> +		invert = of_property_read_bool(np, "nvidia,invert-interrupt");
>  
> -	if (invert)
> -		value |= PMC_CNTRL_INTR_POLARITY;
> -	else
> -		value &= ~PMC_CNTRL_INTR_POLARITY;
> +		value = tegra_pmc_readl(PMC_CNTRL);
>  
> -	tegra_pmc_writel(value, PMC_CNTRL);
> +		if (invert)
> +			value |= PMC_CNTRL_INTR_POLARITY;
> +		else
> +			value &= ~PMC_CNTRL_INTR_POLARITY;
> +
> +		tegra_pmc_writel(value, PMC_CNTRL);
> +	}
>  
>  	return 0;
>  }

By the way, the more I think about this, if there is no valid 'pmc'
node in the device-tree blob, then I wonder if we should even bother
mapping the pmc address space at all? The reason being, if there is
no 'pmc' node then we cannot look-up the SoC data and so all the
public PMC APIs are pretty useless AFAICT. I wonder if we should do
something like ...

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index e09c7ed385f6..34d1385d7ef0 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1510,7 +1510,6 @@ static int __init tegra_pmc_early_init(void)
 {
        const struct of_device_id *match;
        struct device_node *np;
-       struct resource regs;
        unsigned int i;
        bool invert;
        u32 value;
@@ -1520,73 +1519,47 @@ static int __init tegra_pmc_early_init(void)
        np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
        if (!np) {
                /*
-                * Fall back to legacy initialization for 32-bit ARM only. All
-                * 64-bit ARM device tree files for Tegra are required to have
-                * a PMC node.
-                *
-                * This is for backwards-compatibility with old device trees
-                * that didn't contain a PMC node. Note that in this case the
-                * SoC data can't be matched and therefore powergating is
-                * disabled.
+                * All 64-bit ARM device tree files for Tegra are required to
+                * have a PMC node. For old 32-bit Tegra device trees that
+                * don't contain a PMC node, the SoC data can't be matched
+                * and therefore powergating is disabled.
                 */
-               if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
+               if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra())
                        pr_warn("DT node not found, powergating disabled\n");
 
-                       regs.start = 0x7000e400;
-                       regs.end = 0x7000e7ff;
-                       regs.flags = IORESOURCE_MEM;
-
-                       pr_warn("Using memory region %pR\n", &regs);
-               } else {
-                       /*
-                        * At this point we're not running on Tegra, so play
-                        * nice with multi-platform kernels.
-                        */
-                       return 0;
-               }
-       } else {
-               /*
-                * Extract information from the device tree if we've found a
-                * matching node.
-                */
-               if (of_address_to_resource(np, 0, &regs) < 0) {
-                       pr_err("failed to get PMC registers\n");
-                       return -ENXIO;
-               }
+               return 0;
        }
 
-       pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
+       pmc->base = of_iomap(np, 0);
        if (!pmc->base) {
                pr_err("failed to map PMC registers\n");
                of_node_put(np);
                return -ENXIO;
        }

Cheers
Jon
 

-- 
nvpublic

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/6] soc/tegra: pmc: Fix early initialisation of PMC
  2016-06-29 16:17         ` Jon Hunter
@ 2016-06-30 10:03             ` Thierry Reding
  -1 siblings, 0 replies; 24+ messages in thread
From: Thierry Reding @ 2016-06-30 10:03 UTC (permalink / raw)
  To: Jon Hunter
  Cc: Stephen Warren, Alexandre Courbot,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 3316 bytes --]

On Wed, Jun 29, 2016 at 05:17:09PM +0100, Jon Hunter wrote:
> 
> On 28/06/16 11:38, Jon Hunter wrote:
> > During early initialisation, the available power partitions for a given
> > device is configured as well as the polarity of the PMC interrupt. Both
> > of which should only be configured if there is a valid device node for
> > the PMC device. This is because the soc data used for configuring the
> > power partitions is only available if a device node for the PMC is found
> > and the code to configure the interrupt polarity uses the device node
> > pointer directly.
> > 
> > Some early device-tree images may not have this device node and so fix
> > this by ensuring the device node pointer is valid when configuring these
> > items.
> > 
> > Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> > ---
> >  drivers/soc/tegra/pmc.c | 34 ++++++++++++++++++----------------
> >  1 file changed, 18 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> > index 52a9e9703668..2e031c4ad547 100644
> > --- a/drivers/soc/tegra/pmc.c
> > +++ b/drivers/soc/tegra/pmc.c
> > @@ -1550,27 +1550,29 @@ static int __init tegra_pmc_early_init(void)
> >  		return -ENXIO;
> >  	}
> >  
> > -	/* Create a bit-map of the available and valid partitions */
> > -	for (i = 0; i < pmc->soc->num_powergates; i++)
> > -		if (pmc->soc->powergates[i])
> > -			set_bit(i, pmc->powergates_available);
> > -
> >  	mutex_init(&pmc->powergates_lock);
> >  
> > -	/*
> > -	 * Invert the interrupt polarity if a PMC device tree node exists and
> > -	 * contains the nvidia,invert-interrupt property.
> > -	 */
> > -	invert = of_property_read_bool(np, "nvidia,invert-interrupt");
> > +	if (np) {
> > +		/* Create a bit-map of the available and valid partitions */
> > +		for (i = 0; i < pmc->soc->num_powergates; i++)
> > +			if (pmc->soc->powergates[i])
> > +				set_bit(i, pmc->powergates_available);
> >  
> > -	value = tegra_pmc_readl(PMC_CNTRL);
> > +		/*
> > +		 * Invert the interrupt polarity if a PMC device tree node
> > +		 * exists and contains the nvidia,invert-interrupt property.
> > +		 */
> > +		invert = of_property_read_bool(np, "nvidia,invert-interrupt");
> >  
> > -	if (invert)
> > -		value |= PMC_CNTRL_INTR_POLARITY;
> > -	else
> > -		value &= ~PMC_CNTRL_INTR_POLARITY;
> > +		value = tegra_pmc_readl(PMC_CNTRL);
> >  
> > -	tegra_pmc_writel(value, PMC_CNTRL);
> > +		if (invert)
> > +			value |= PMC_CNTRL_INTR_POLARITY;
> > +		else
> > +			value &= ~PMC_CNTRL_INTR_POLARITY;
> > +
> > +		tegra_pmc_writel(value, PMC_CNTRL);
> > +	}
> >  
> >  	return 0;
> >  }
> 
> By the way, the more I think about this, if there is no valid 'pmc'
> node in the device-tree blob, then I wonder if we should even bother
> mapping the pmc address space at all? The reason being, if there is
> no 'pmc' node then we cannot look-up the SoC data and so all the
> public PMC APIs are pretty useless AFAICT. I wonder if we should do
> something like ...

I think it's fine as-is. The PMC driver does more than just powergates
and it'd be useful to have the rest continue to work even on old DTBs.
Everything should already be properly guarded against this exception.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/6] soc/tegra: pmc: Fix early initialisation of PMC
@ 2016-06-30 10:03             ` Thierry Reding
  0 siblings, 0 replies; 24+ messages in thread
From: Thierry Reding @ 2016-06-30 10:03 UTC (permalink / raw)
  To: Jon Hunter; +Cc: Stephen Warren, Alexandre Courbot, linux-tegra, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3287 bytes --]

On Wed, Jun 29, 2016 at 05:17:09PM +0100, Jon Hunter wrote:
> 
> On 28/06/16 11:38, Jon Hunter wrote:
> > During early initialisation, the available power partitions for a given
> > device is configured as well as the polarity of the PMC interrupt. Both
> > of which should only be configured if there is a valid device node for
> > the PMC device. This is because the soc data used for configuring the
> > power partitions is only available if a device node for the PMC is found
> > and the code to configure the interrupt polarity uses the device node
> > pointer directly.
> > 
> > Some early device-tree images may not have this device node and so fix
> > this by ensuring the device node pointer is valid when configuring these
> > items.
> > 
> > Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> > ---
> >  drivers/soc/tegra/pmc.c | 34 ++++++++++++++++++----------------
> >  1 file changed, 18 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> > index 52a9e9703668..2e031c4ad547 100644
> > --- a/drivers/soc/tegra/pmc.c
> > +++ b/drivers/soc/tegra/pmc.c
> > @@ -1550,27 +1550,29 @@ static int __init tegra_pmc_early_init(void)
> >  		return -ENXIO;
> >  	}
> >  
> > -	/* Create a bit-map of the available and valid partitions */
> > -	for (i = 0; i < pmc->soc->num_powergates; i++)
> > -		if (pmc->soc->powergates[i])
> > -			set_bit(i, pmc->powergates_available);
> > -
> >  	mutex_init(&pmc->powergates_lock);
> >  
> > -	/*
> > -	 * Invert the interrupt polarity if a PMC device tree node exists and
> > -	 * contains the nvidia,invert-interrupt property.
> > -	 */
> > -	invert = of_property_read_bool(np, "nvidia,invert-interrupt");
> > +	if (np) {
> > +		/* Create a bit-map of the available and valid partitions */
> > +		for (i = 0; i < pmc->soc->num_powergates; i++)
> > +			if (pmc->soc->powergates[i])
> > +				set_bit(i, pmc->powergates_available);
> >  
> > -	value = tegra_pmc_readl(PMC_CNTRL);
> > +		/*
> > +		 * Invert the interrupt polarity if a PMC device tree node
> > +		 * exists and contains the nvidia,invert-interrupt property.
> > +		 */
> > +		invert = of_property_read_bool(np, "nvidia,invert-interrupt");
> >  
> > -	if (invert)
> > -		value |= PMC_CNTRL_INTR_POLARITY;
> > -	else
> > -		value &= ~PMC_CNTRL_INTR_POLARITY;
> > +		value = tegra_pmc_readl(PMC_CNTRL);
> >  
> > -	tegra_pmc_writel(value, PMC_CNTRL);
> > +		if (invert)
> > +			value |= PMC_CNTRL_INTR_POLARITY;
> > +		else
> > +			value &= ~PMC_CNTRL_INTR_POLARITY;
> > +
> > +		tegra_pmc_writel(value, PMC_CNTRL);
> > +	}
> >  
> >  	return 0;
> >  }
> 
> By the way, the more I think about this, if there is no valid 'pmc'
> node in the device-tree blob, then I wonder if we should even bother
> mapping the pmc address space at all? The reason being, if there is
> no 'pmc' node then we cannot look-up the SoC data and so all the
> public PMC APIs are pretty useless AFAICT. I wonder if we should do
> something like ...

I think it's fine as-is. The PMC driver does more than just powergates
and it'd be useful to have the rest continue to work even on old DTBs.
Everything should already be properly guarded against this exception.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/6] soc/tegra: Various PMC fixes
  2016-06-28 10:38 ` Jon Hunter
@ 2016-06-30 10:04     ` Thierry Reding
  -1 siblings, 0 replies; 24+ messages in thread
From: Thierry Reding @ 2016-06-30 10:04 UTC (permalink / raw)
  To: Jon Hunter
  Cc: Stephen Warren, Alexandre Courbot,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 735 bytes --]

On Tue, Jun 28, 2016 at 11:38:22AM +0100, Jon Hunter wrote:
> A few fixes for the Tegra PMC driver.
> 
> Jon Hunter (6):
>   soc/tegra: pmc: Ensure powergate is available when powering on
>   soc/tegra: pmc: Fix early initialisation of PMC
>   soc/tegra: pmc: Don't populate soc data until register space is mapped
>   soc/tegra: pmc: Ensure mutex is always initialised
>   soc/tegra: pmc: Add missing of_node_put
>   soc/tegra: pmc: Don't probe pmc if early initialisation fails
> 
>  drivers/soc/tegra/pmc.c | 51 ++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 18 deletions(-)

Applied all patches to for-4.8/soc and squashed the follow-up from 5/6
into 5/6. Thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/6] soc/tegra: Various PMC fixes
@ 2016-06-30 10:04     ` Thierry Reding
  0 siblings, 0 replies; 24+ messages in thread
From: Thierry Reding @ 2016-06-30 10:04 UTC (permalink / raw)
  To: Jon Hunter; +Cc: Stephen Warren, Alexandre Courbot, linux-tegra, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 735 bytes --]

On Tue, Jun 28, 2016 at 11:38:22AM +0100, Jon Hunter wrote:
> A few fixes for the Tegra PMC driver.
> 
> Jon Hunter (6):
>   soc/tegra: pmc: Ensure powergate is available when powering on
>   soc/tegra: pmc: Fix early initialisation of PMC
>   soc/tegra: pmc: Don't populate soc data until register space is mapped
>   soc/tegra: pmc: Ensure mutex is always initialised
>   soc/tegra: pmc: Add missing of_node_put
>   soc/tegra: pmc: Don't probe pmc if early initialisation fails
> 
>  drivers/soc/tegra/pmc.c | 51 ++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 18 deletions(-)

Applied all patches to for-4.8/soc and squashed the follow-up from 5/6
into 5/6. Thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2016-06-30 10:04 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-28 10:38 [PATCH 0/6] soc/tegra: Various PMC fixes Jon Hunter
2016-06-28 10:38 ` Jon Hunter
2016-06-28 10:38 ` [PATCH 1/6] soc/tegra: pmc: Ensure powergate is available when powering on Jon Hunter
2016-06-28 10:38   ` Jon Hunter
2016-06-28 10:38 ` [PATCH 3/6] soc/tegra: pmc: Don't populate soc data until register space is mapped Jon Hunter
2016-06-28 10:38   ` Jon Hunter
2016-06-28 10:38 ` [PATCH 4/6] soc/tegra: pmc: Ensure mutex is always initialised Jon Hunter
2016-06-28 10:38   ` Jon Hunter
2016-06-28 10:38 ` [PATCH 5/6] soc/tegra: pmc: Add missing of_node_put Jon Hunter
2016-06-28 10:38   ` Jon Hunter
2016-06-28 10:46   ` Jon Hunter
2016-06-28 10:46     ` Jon Hunter
2016-06-28 10:38 ` [PATCH 6/6] soc/tegra: pmc: Don't probe pmc if early initialisation fails Jon Hunter
2016-06-28 10:38   ` Jon Hunter
     [not found] ` <1467110308-22126-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-06-28 10:38   ` [PATCH 2/6] soc/tegra: pmc: Fix early initialisation of PMC Jon Hunter
2016-06-28 10:38     ` Jon Hunter
     [not found]     ` <1467110308-22126-3-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-06-29 16:17       ` Jon Hunter
2016-06-29 16:17         ` Jon Hunter
     [not found]         ` <5773F485.8090504-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-06-30 10:03           ` Thierry Reding
2016-06-30 10:03             ` Thierry Reding
2016-06-28 10:40   ` [PATCH 0/6] soc/tegra: Various PMC fixes Jon Hunter
2016-06-28 10:40     ` Jon Hunter
2016-06-30 10:04   ` Thierry Reding
2016-06-30 10:04     ` Thierry Reding

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.