diff mbox

[5/6] ARM: mvebu: Add thermal quirk for the Armada 375 DB board

Message ID 1397657720-10893-6-git-send-email-ezequiel.garcia@free-electrons.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ezequiel Garcia April 16, 2014, 2:15 p.m. UTC
The initial release of the Armada 375 DB board has an Armada 375
Z1 stepping silicon. This commit introduces a quirk that allows
to workaround a series of issues with the thermal sensor in this
stepping, but updating the devicetree:

  * Updates the compatible string for the thermal, so the driver
    can perform a specific initialization of the sensor.

  * Moves the offset of the thermal control register. This quirk
    allows to specifiy the correct (A0 stepping) offset in the
    devicetree.

Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/mach-mvebu/board-v7.c     | 57 ++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-mvebu/mvebu-soc-id.h |  3 ++
 2 files changed, 60 insertions(+)

Comments

Sebastian Hesselbarth April 16, 2014, 3:59 p.m. UTC | #1
On 04/16/2014 04:15 PM, Ezequiel Garcia wrote:
> The initial release of the Armada 375 DB board has an Armada 375
> Z1 stepping silicon. This commit introduces a quirk that allows
> to workaround a series of issues with the thermal sensor in this
> stepping, but updating the devicetree:
>
>    * Updates the compatible string for the thermal, so the driver
>      can perform a specific initialization of the sensor.
>
>    * Moves the offset of the thermal control register. This quirk
>      allows to specifiy the correct (A0 stepping) offset in the
>      devicetree.
>
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ---
>   arch/arm/mach-mvebu/board-v7.c     | 57 ++++++++++++++++++++++++++++++++++++++
>   arch/arm/mach-mvebu/mvebu-soc-id.h |  3 ++
>   2 files changed, 60 insertions(+)
>
> diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
> index 333fca8..93f50f2 100644
> --- a/arch/arm/mach-mvebu/board-v7.c
> +++ b/arch/arm/mach-mvebu/board-v7.c
> @@ -96,10 +96,66 @@ static void __init i2c_quirk(void)
>   	return;
>   }
>
> +#define A375_Z1_THERMAL_FIXUP_OFFSET 0xc
> +
> +static void __init thermal_quirk(void)

Are we sure, we want to fixup quirks like this the way below?

Alternatively, we can also keep some armada-375-z1.dtsi and one
for the board including it.

Sebastian

> +{
> +	struct device_node *np;
> +	u32 dev, rev;
> +
> +	if (mvebu_get_soc_id(&dev, &rev) && rev > ARMADA_375_Z1_REV)
> +		return;
> +
> +	for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
> +		struct property *prop;
> +		__be32 newval, *newprop, *oldprop;
> +		int len;
> +
> +		/*
> +		 * The register offset is at a wrong location. This quirk
> +		 * creates a new reg property as a clone of the previous
> +		 * one and corrects the offset.
> +		 */
> +		oldprop = (__be32 *)of_get_property(np, "reg", &len);
> +		if (!oldprop)
> +			continue;
> +
> +		/* Create a duplicate of the 'reg' property */
> +		prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> +		prop->length = len;
> +		prop->name = kstrdup("reg", GFP_KERNEL);
> +		prop->value = kzalloc(len, GFP_KERNEL);
> +		memcpy(prop->value, oldprop, len);
> +
> +		/* Fixup the register offset of the second entry */
> +		oldprop += 2;
> +		newprop = (__be32 *)prop->value + 2;
> +		newval = cpu_to_be32(be32_to_cpu(*oldprop) -
> +				     A375_Z1_THERMAL_FIXUP_OFFSET);
> +		*newprop = newval;
> +		of_update_property(np, prop);
> +
> +		/*
> +		 * The thermal controller needs some quirk too, so let's change
> +		 * the compatible string to reflect this.
> +		 */
> +		prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> +		prop->name = kstrdup("compatible", GFP_KERNEL);
> +		prop->length = sizeof("marvell,armada375-z1-thermal");
> +		prop->value = kstrdup("marvell,armada375-z1-thermal",
> +						GFP_KERNEL);
> +		of_update_property(np, prop);
> +	}
> +	return;
> +}
> +
>   static void __init mvebu_dt_init(void)
>   {
>   	if (of_machine_is_compatible("plathome,openblocks-ax3-4"))
>   		i2c_quirk();
> +	if (of_machine_is_compatible("marvell,a375-db"))
> +		thermal_quirk();
> +
>   	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
>   }
>
> @@ -123,6 +179,7 @@ static const char * const armada_375_dt_compat[] = {
>
>   DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)")
>   	.init_time	= mvebu_timer_and_clk_init,
> +	.init_machine	= mvebu_dt_init,
>   	.restart	= mvebu_restart,
>   	.dt_compat	= armada_375_dt_compat,
>   MACHINE_END
> diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.h b/arch/arm/mach-mvebu/mvebu-soc-id.h
> index 3165425..294a443 100644
> --- a/arch/arm/mach-mvebu/mvebu-soc-id.h
> +++ b/arch/arm/mach-mvebu/mvebu-soc-id.h
> @@ -20,6 +20,9 @@
>   #define MV78XX0_A0_REV	    0x1
>   #define MV78XX0_B0_REV	    0x2
>
> +/* Armada 375 */
> +#define ARMADA_375_Z1_REV   0x0
> +
>   #ifdef CONFIG_ARCH_MVEBU
>   int mvebu_get_soc_id(u32 *dev, u32 *rev);
>   #else
>
Thomas Petazzoni April 16, 2014, 4:03 p.m. UTC | #2
Dear Sebastian Hesselbarth,

On Wed, 16 Apr 2014 17:59:05 +0200, Sebastian Hesselbarth wrote:

> Are we sure, we want to fixup quirks like this the way below?

We already have an exactly identical quirk for the A0 I2C issue, in the
same file, right above the quirk Ezequiel is adding here. So using the
same strategy for both cases would be nice.

> Alternatively, we can also keep some armada-375-z1.dtsi and one
> for the board including it.

For minor differences such as SoC stepping, I personally prefer to not
have separate Device Trees. We already have many of them, for each
variant of the various SOCs. If we add the different steppings, it's
going to be even more complicated. Also, there will be a new iteration
of the Armada 375 DB with an A0 chip, which does not have the Z1 bug.

Best regards,

Thomas
Andrew Lunn April 16, 2014, 4:08 p.m. UTC | #3
> For minor differences such as SoC stepping, I personally prefer to not
> have separate Device Trees. We already have many of them, for each
> variant of the various SOCs. If we add the different steppings, it's
> going to be even more complicated. Also, there will be a new iteration
> of the Armada 375 DB with an A0 chip, which does not have the Z1 bug.

How many Z1 are there out and about? Would it be simpler to just
disable thermal on Z1? If only development boards have Z1, this could
be reasonable.

	Andrew
Thomas Petazzoni April 16, 2014, 4:19 p.m. UTC | #4
Dear Andrew Lunn,

On Wed, 16 Apr 2014 18:08:24 +0200, Andrew Lunn wrote:
> > For minor differences such as SoC stepping, I personally prefer to not
> > have separate Device Trees. We already have many of them, for each
> > variant of the various SOCs. If we add the different steppings, it's
> > going to be even more complicated. Also, there will be a new iteration
> > of the Armada 375 DB with an A0 chip, which does not have the Z1 bug.
> 
> How many Z1 are there out and about? Would it be simpler to just
> disable thermal on Z1? If only development boards have Z1, this could
> be reasonable.

Not many, but we also need workarounds for other Z1 issues, such as the
I/O coherency workaround (see the 375 coherency patches) and the SMP
issue (see the 375 SMP patches).

For now, Gregory, Ezequiel and myself only have access to Z1 boards, so
we would like to support this stepping at least until all of us have
access to A0 boards. If we don't do this, then we need to keep an ugly
pile of out-of-tree patches just to get our boards running, which is
clearly not the best way of ensuring that mainline has all the
necessary fixes.

So, I would like to see the Z1 stepping supported for now, and have the
freedom to remove its support later once we are all ready to switch to
A0.

For 375 and 38x, we have the chance of having started the mainlining
process very early compared to the life cycle of the SoC, and part of
the consequences of this chance is that we work on early steppings. It
would seem weird for the kernel community to ask silicon vendors to
mainline their code earlier, and at the same time refuse workarounds
needed to bring up early SoC variants.

Thanks,

Thomas
Andrew Lunn April 16, 2014, 4:34 p.m. UTC | #5
> So, I would like to see the Z1 stepping supported for now, and have the
> freedom to remove its support later once we are all ready to switch to
> A0.

Hi Thomas

Sounds like a good plan. Try to keep all the mess to support Z1 in one
place so that it can be easily taken out once people have A0.

       Andrew
Jason Cooper April 16, 2014, 4:55 p.m. UTC | #6
On Wed, Apr 16, 2014 at 06:34:47PM +0200, Andrew Lunn wrote:
> > So, I would like to see the Z1 stepping supported for now, and have the
> > freedom to remove its support later once we are all ready to switch to
> > A0.
> 
> Hi Thomas
> 
> Sounds like a good plan. Try to keep all the mess to support Z1 in one
> place so that it can be easily taken out once people have A0.

Agreed.  Thomas, do you think you'll be able to get a definitive answer
from Marvell re the number of Z1 boards in the wild?  Once they've moved
to the A0, of course.

Unless we can get a hard answer on that, I doubt we'll ever withdraw
support for the Z1.  Not that that's a bad thing, just trying to be
realistic.  If we add code, expect to support it.

And keeping it all in one place is kind of an impossibility.  Just for
thermal Z1, there are changes to the binding docs, the thermal driver,
and the soc code.

I'd say it's more important to keep it clean, with dts files targeting
the A0+ SoCs, and the Z1 being the exception case(s).

thx,

Jason.
Thomas Petazzoni April 16, 2014, 5:08 p.m. UTC | #7
Dear Jason Cooper,

On Wed, 16 Apr 2014 12:55:48 -0400, Jason Cooper wrote:

> > Sounds like a good plan. Try to keep all the mess to support Z1 in one
> > place so that it can be easily taken out once people have A0.
> 
> Agreed.  Thomas, do you think you'll be able to get a definitive answer
> from Marvell re the number of Z1 boards in the wild?  Once they've moved
> to the A0, of course.

My understanding is that Marvell has never been interested in having
mainline support for the Z1 stepping. It just happens to be a necessary
step to make progress with the general goal of supporting 375 in
mainline, but I don't expect Marvell to be interested in supporting the
Z1 boards in the wild.

> Unless we can get a hard answer on that, I doubt we'll ever withdraw
> support for the Z1.  Not that that's a bad thing, just trying to be
> realistic.  If we add code, expect to support it.

Yes, indeed.

> And keeping it all in one place is kind of an impossibility.  Just for
> thermal Z1, there are changes to the binding docs, the thermal driver,
> and the soc code.
> 
> I'd say it's more important to keep it clean, with dts files targeting
> the A0+ SoCs, and the Z1 being the exception case(s).

That's what we've tried to do so far: the thermal driver works for the
A0+ by default, and only as an exception supports Z1.

Thanks!

Thomas
diff mbox

Patch

diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 333fca8..93f50f2 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -96,10 +96,66 @@  static void __init i2c_quirk(void)
 	return;
 }
 
+#define A375_Z1_THERMAL_FIXUP_OFFSET 0xc
+
+static void __init thermal_quirk(void)
+{
+	struct device_node *np;
+	u32 dev, rev;
+
+	if (mvebu_get_soc_id(&dev, &rev) && rev > ARMADA_375_Z1_REV)
+		return;
+
+	for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
+		struct property *prop;
+		__be32 newval, *newprop, *oldprop;
+		int len;
+
+		/*
+		 * The register offset is at a wrong location. This quirk
+		 * creates a new reg property as a clone of the previous
+		 * one and corrects the offset.
+		 */
+		oldprop = (__be32 *)of_get_property(np, "reg", &len);
+		if (!oldprop)
+			continue;
+
+		/* Create a duplicate of the 'reg' property */
+		prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+		prop->length = len;
+		prop->name = kstrdup("reg", GFP_KERNEL);
+		prop->value = kzalloc(len, GFP_KERNEL);
+		memcpy(prop->value, oldprop, len);
+
+		/* Fixup the register offset of the second entry */
+		oldprop += 2;
+		newprop = (__be32 *)prop->value + 2;
+		newval = cpu_to_be32(be32_to_cpu(*oldprop) -
+				     A375_Z1_THERMAL_FIXUP_OFFSET);
+		*newprop = newval;
+		of_update_property(np, prop);
+
+		/*
+		 * The thermal controller needs some quirk too, so let's change
+		 * the compatible string to reflect this.
+		 */
+		prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+		prop->name = kstrdup("compatible", GFP_KERNEL);
+		prop->length = sizeof("marvell,armada375-z1-thermal");
+		prop->value = kstrdup("marvell,armada375-z1-thermal",
+						GFP_KERNEL);
+		of_update_property(np, prop);
+	}
+	return;
+}
+
 static void __init mvebu_dt_init(void)
 {
 	if (of_machine_is_compatible("plathome,openblocks-ax3-4"))
 		i2c_quirk();
+	if (of_machine_is_compatible("marvell,a375-db"))
+		thermal_quirk();
+
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -123,6 +179,7 @@  static const char * const armada_375_dt_compat[] = {
 
 DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)")
 	.init_time	= mvebu_timer_and_clk_init,
+	.init_machine	= mvebu_dt_init,
 	.restart	= mvebu_restart,
 	.dt_compat	= armada_375_dt_compat,
 MACHINE_END
diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.h b/arch/arm/mach-mvebu/mvebu-soc-id.h
index 3165425..294a443 100644
--- a/arch/arm/mach-mvebu/mvebu-soc-id.h
+++ b/arch/arm/mach-mvebu/mvebu-soc-id.h
@@ -20,6 +20,9 @@ 
 #define MV78XX0_A0_REV	    0x1
 #define MV78XX0_B0_REV	    0x2
 
+/* Armada 375 */
+#define ARMADA_375_Z1_REV   0x0
+
 #ifdef CONFIG_ARCH_MVEBU
 int mvebu_get_soc_id(u32 *dev, u32 *rev);
 #else