diff mbox

[4/5] cpufreq: imx6q: add ldo-bypass support

Message ID 1414729631-11005-5-git-send-email-tharvey@gateworks.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tim Harvey Oct. 31, 2014, 4:27 a.m. UTC
When an external PMIC is used for VDD_SOC and VDD_ARM you can save power by
bypassing the internal LDO's provided by the anantop regulator as long as
you are running less than 1.2GHz. If running at 1.2GHz the IMX6 datasheets
state that you must use the internal LDO's to reduce ripple on the suplies.

A failure to bypass the LDO's when using an external PMIC will result in an
extra voltage drop (~125mV) between VDD_ARM_IN and VDD_ARM and VDD_SOC_IN and
VDD_SOC which violates the voltages specificed by the datasheets.

Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Shawn Guo <shawn.guo@freescale.com>
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 drivers/cpufreq/imx6q-cpufreq.c | 51 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

Comments

Fabio Estevam Dec. 17, 2014, 2:36 p.m. UTC | #1
Hi Tim,

On Fri, Oct 31, 2014 at 2:27 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> When an external PMIC is used for VDD_SOC and VDD_ARM you can save power by
> bypassing the internal LDO's provided by the anantop regulator as long as
> you are running less than 1.2GHz. If running at 1.2GHz the IMX6 datasheets
> state that you must use the internal LDO's to reduce ripple on the suplies.
>
> A failure to bypass the LDO's when using an external PMIC will result in an
> extra voltage drop (~125mV) between VDD_ARM_IN and VDD_ARM and VDD_SOC_IN and
> VDD_SOC which violates the voltages specificed by the datasheets.
>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Shawn Guo <shawn.guo@freescale.com>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
>  drivers/cpufreq/imx6q-cpufreq.c | 51 +++++++++++++++++++++++++++++++++++++++++

Shouldn't the LDO bypass support be added into the anatop regulator
driver instead?

What if someone wants to use LDO bypass and not use the cpufreq driver?
Tim Harvey Dec. 18, 2014, 2:11 p.m. UTC | #2
On Wed, Dec 17, 2014 at 6:36 AM, Fabio Estevam <festevam@gmail.com> wrote:
> Hi Tim,
>
> On Fri, Oct 31, 2014 at 2:27 AM, Tim Harvey <tharvey@gateworks.com> wrote:
>> When an external PMIC is used for VDD_SOC and VDD_ARM you can save power by
>> bypassing the internal LDO's provided by the anantop regulator as long as
>> you are running less than 1.2GHz. If running at 1.2GHz the IMX6 datasheets
>> state that you must use the internal LDO's to reduce ripple on the suplies.
>>
>> A failure to bypass the LDO's when using an external PMIC will result in an
>> extra voltage drop (~125mV) between VDD_ARM_IN and VDD_ARM and VDD_SOC_IN and
>> VDD_SOC which violates the voltages specificed by the datasheets.
>>
>> Cc: Philipp Zabel <p.zabel@pengutronix.de>
>> Cc: Shawn Guo <shawn.guo@freescale.com>
>> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
>> ---
>>  drivers/cpufreq/imx6q-cpufreq.c | 51 +++++++++++++++++++++++++++++++++++++++++
>
> Shouldn't the LDO bypass support be added into the anatop regulator
> driver instead?
>
> What if someone wants to use LDO bypass and not use the cpufreq driver?

Fabio,

That does make sense perhaps - I'm just not sure the best way to do it.

What is needed is to determine if the cpu vddsoc and vddarm regulators
are both 'not' the same as the anatop provided regulators (then we
bypass the anatop regulators) so I need to do such a check after all
regulators are registered. Perhaps I need to have a late_init call (or
some other init call that happens after all regulators are
registered).

Phillipp/Mark - what are your thoughts here? Do the regulator core
functions regulator_is_same() [1] and regulator_is_bypass() [2] I
propose make sense to determine if regulators are the same and in
bypass mode and overcome the detection issues Phillipp discussed in a
previous thread [3]?

[1] http://article.gmane.org/gmane.linux.kernel/1818320/
[2] http://article.gmane.org/gmane.linux.kernel/1818324/
[3] http://thread.gmane.org/gmane.linux.ports.arm.kernel/359856

Regards,

Tim
Mark Brown Dec. 18, 2014, 2:22 p.m. UTC | #3
On Thu, Dec 18, 2014 at 06:11:15AM -0800, Tim Harvey wrote:
> On Wed, Dec 17, 2014 at 6:36 AM, Fabio Estevam <festevam@gmail.com> wrote:
> > On Fri, Oct 31, 2014 at 2:27 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> >> When an external PMIC is used for VDD_SOC and VDD_ARM you can save power by
> >> bypassing the internal LDO's provided by the anantop regulator as long as
> >> you are running less than 1.2GHz. If running at 1.2GHz the IMX6 datasheets
> >> state that you must use the internal LDO's to reduce ripple on the suplies.
> >>
> >> A failure to bypass the LDO's when using an external PMIC will result in an
> >> extra voltage drop (~125mV) between VDD_ARM_IN and VDD_ARM and VDD_SOC_IN and
> >> VDD_SOC which violates the voltages specificed by the datasheets.

This description doesn't make much sense - there must of course always
be an external power source for the SoC and the discussion of bypassing
also suggests that it's not just a case of disconnecting the internal
LDOs.

> What is needed is to determine if the cpu vddsoc and vddarm regulators
> are both 'not' the same as the anatop provided regulators (then we
> bypass the anatop regulators) so I need to do such a check after all
> regulators are registered. Perhaps I need to have a late_init call (or
> some other init call that happens after all regulators are
> registered).

> Phillipp/Mark - what are your thoughts here? Do the regulator core
> functions regulator_is_same() [1] and regulator_is_bypass() [2] I
> propose make sense to determine if regulators are the same and in
> bypass mode and overcome the detection issues Phillipp discussed in a
> previous thread [3]?

Please provide a clear description of what's actually going on here.
What does the hardware actually look like and what is being configured?
You're telling me the solution you've decided on, not what the problem
that this is supposed to solve is.
Tim Harvey Dec. 19, 2014, 4:17 p.m. UTC | #4
On Thu, Dec 18, 2014 at 6:22 AM, Mark Brown <broonie@kernel.org> wrote:
> On Thu, Dec 18, 2014 at 06:11:15AM -0800, Tim Harvey wrote:
>> On Wed, Dec 17, 2014 at 6:36 AM, Fabio Estevam <festevam@gmail.com> wrote:
>> > On Fri, Oct 31, 2014 at 2:27 AM, Tim Harvey <tharvey@gateworks.com> wrote:
>> >> When an external PMIC is used for VDD_SOC and VDD_ARM you can save power by
>> >> bypassing the internal LDO's provided by the anantop regulator as long as
>> >> you are running less than 1.2GHz. If running at 1.2GHz the IMX6 datasheets
>> >> state that you must use the internal LDO's to reduce ripple on the suplies.
>> >>
>> >> A failure to bypass the LDO's when using an external PMIC will result in an
>> >> extra voltage drop (~125mV) between VDD_ARM_IN and VDD_ARM and VDD_SOC_IN and
>> >> VDD_SOC which violates the voltages specificed by the datasheets.
>
> This description doesn't make much sense - there must of course always
> be an external power source for the SoC and the discussion of bypassing
> also suggests that it's not just a case of disconnecting the internal
> LDOs.
>
>> What is needed is to determine if the cpu vddsoc and vddarm regulators
>> are both 'not' the same as the anatop provided regulators (then we
>> bypass the anatop regulators) so I need to do such a check after all
>> regulators are registered. Perhaps I need to have a late_init call (or
>> some other init call that happens after all regulators are
>> registered).
>
>> Phillipp/Mark - what are your thoughts here? Do the regulator core
>> functions regulator_is_same() [1] and regulator_is_bypass() [2] I
>> propose make sense to determine if regulators are the same and in
>> bypass mode and overcome the detection issues Phillipp discussed in a
>> previous thread [3]?
>
> Please provide a clear description of what's actually going on here.
> What does the hardware actually look like and what is being configured?
> You're telling me the solution you've decided on, not what the problem
> that this is supposed to solve is.

Mark,

I can embellish the description with more information. Does this
describe the issue better?

---

The IMX6 CPU family (IMX6S/IMX6DL/IMX6D/IMX6Q) have three CPU related
voltage rails: VDD_ARM (for the ARM core(s)), VDD_SOC (for the SoC
logic), and VDD_PU (for the GPU and VPU). All three of these have
voltage setpoints recommended by the datasheet which vary per CPU
frequency. They also all have internal LDO's (implemented via the
anantop voltage regulator) such that a board does not have to have a
complex PMIC with scalable voltages. The VDD_PU LDO is internally tied
to the VDD_SOC input. Therefore, there are two external power inputs
to the chip: VDD_ARM and VDD_SOC. When using a non scalable PMIC you
can provide VDD_ARM and VDD_SOC with a set voltage level specified by
the datasheet, and use the three internal LDO's inside the IMX6 to
adjust the three power rails down to the proper value per CPU
frequency setpoint. If however you have an external PMIC that is
capable of adjusting the VDD_ARM and VDD_SOC to the IMX6 and an
appropriate regulator driver is capable of doing so, you must
configure the cpu nodes vddarm and vddsoc regulators to those provided
by your PMIC and 'bypass' the internal LDO's by setting their scaling
value to full-scale (0x1f). Failure to place the internal LDO's in
'bypass mode' will result in a minimum of 125mV drop from the external
input to the internal voltage rail such that the CPU operating points
describing the voltage of the external inputs per CPU frequency will
not be properly met.

An additional benefit of using a PMIC with a regulator driver is that
you can save power regulating the voltage with a switching regulator
PMIC vs an inefficient LDO within the CPU. This also will help to move
thermal power out of the IMX6 and to your PMIC.

If running at 1.2GHz the IMX6 datasheets state that you must use the
internal LDO's to reduce ripple on the supplies.

----

Maybe Fabio has something to add? Perhaps this should go somewhere
under Documentation but I'm not clear where.

Tim
Mark Brown Dec. 19, 2014, 4:23 p.m. UTC | #5
On Fri, Dec 19, 2014 at 08:17:41AM -0800, Tim Harvey wrote:

> frequency setpoint. If however you have an external PMIC that is
> capable of adjusting the VDD_ARM and VDD_SOC to the IMX6 and an
> appropriate regulator driver is capable of doing so, you must
> configure the cpu nodes vddarm and vddsoc regulators to those provided
> by your PMIC and 'bypass' the internal LDO's by setting their scaling

You're describing the implementation again, not the system.  Describe
the system then if you want to describe the solution you've come up with
for modelling it do so separately.

Please also try to use paragraphs to break up what you're saying a bit.
Tim Harvey Jan. 5, 2015, 2:38 p.m. UTC | #6
On Fri, Dec 19, 2014 at 8:23 AM, Mark Brown <broonie@kernel.org> wrote:
> On Fri, Dec 19, 2014 at 08:17:41AM -0800, Tim Harvey wrote:
>
>> frequency setpoint. If however you have an external PMIC that is
>> capable of adjusting the VDD_ARM and VDD_SOC to the IMX6 and an
>> appropriate regulator driver is capable of doing so, you must
>> configure the cpu nodes vddarm and vddsoc regulators to those provided
>> by your PMIC and 'bypass' the internal LDO's by setting their scaling
>
> You're describing the implementation again, not the system.  Describe
> the system then if you want to describe the solution you've come up with
> for modelling it do so separately.
>
> Please also try to use paragraphs to break up what you're saying a bit.

Mark,

I'm not sure I'm understanding what your asking for or how to describe
it differently. Fabio / Shawn / Philipp could you help me out here
with the proper explanation of the IMX6 LDO's so that we can make some
progress on getting LDO bypass implemented?

Regards,

Tim
Mark Brown Jan. 5, 2015, 2:43 p.m. UTC | #7
On Mon, Jan 05, 2015 at 06:38:50AM -0800, Tim Harvey wrote:
> On Fri, Dec 19, 2014 at 8:23 AM, Mark Brown <broonie@kernel.org> wrote:
> > On Fri, Dec 19, 2014 at 08:17:41AM -0800, Tim Harvey wrote:

> >> frequency setpoint. If however you have an external PMIC that is
> >> capable of adjusting the VDD_ARM and VDD_SOC to the IMX6 and an
> >> appropriate regulator driver is capable of doing so, you must
> >> configure the cpu nodes vddarm and vddsoc regulators to those provided
> >> by your PMIC and 'bypass' the internal LDO's by setting their scaling

> > You're describing the implementation again, not the system.  Describe
> > the system then if you want to describe the solution you've come up with
> > for modelling it do so separately.

> > Please also try to use paragraphs to break up what you're saying a bit.

> I'm not sure I'm understanding what your asking for or how to describe
> it differently. Fabio / Shawn / Philipp could you help me out here
> with the proper explanation of the IMX6 LDO's so that we can make some
> progress on getting LDO bypass implemented?

I have no idea what the context is any more, sorry.  The above looks
like you're talking about the specifics of how you've implemented
something instead of describing the hardware you're trying to abstract -
you're taling about the "cpu nodes" in what sounds like it's supposed to
be a description of the hardware for example.
diff mbox

Patch

diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index c2d3076..fc69f36 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -159,6 +159,9 @@  static int imx6q_cpufreq_probe(struct platform_device *pdev)
 	int num, ret;
 	const struct property *prop;
 	const __be32 *val;
+	struct regulator *anatop_arm_reg = NULL;
+	struct regulator *anatop_pu_reg = NULL;
+	struct regulator *anatop_soc_reg = NULL;
 	u32 nr, i, j;
 
 	cpu_dev = get_cpu_device(0);
@@ -167,6 +170,20 @@  static int imx6q_cpufreq_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+	if (np) {
+		anatop_arm_reg = regulator_get(&pdev->dev, "vddarm");
+		anatop_pu_reg = regulator_get(&pdev->dev, "vddpu");
+		anatop_soc_reg = regulator_get(&pdev->dev, "vddsoc");
+		if (PTR_ERR(anatop_arm_reg) == -EPROBE_DEFER ||
+		    PTR_ERR(anatop_pu_reg) == -EPROBE_DEFER ||
+		    PTR_ERR(anatop_soc_reg) == -EPROBE_DEFER) {
+				ret = -EPROBE_DEFER;
+				goto put_reg;
+		}
+		of_node_put(np);
+	}
+
 	np = of_node_get(cpu_dev->of_node);
 	if (!np) {
 		dev_err(cpu_dev, "failed to find cpu0 node\n");
@@ -301,7 +318,41 @@  soc_opp_out:
 		goto free_freq_table;
 	}
 
+	/* enable LDO bypass mode if anatop regs are not being used for core */
+	if ((!IS_ERR(anatop_arm_reg) &&
+	     !IS_ERR(anatop_pu_reg) &&
+	     !IS_ERR(anatop_soc_reg) &&
+	     regulator_is_same(arm_reg, anatop_arm_reg) &&
+	     regulator_is_same(pu_reg, anatop_pu_reg) &&
+	     regulator_is_same(soc_reg, anatop_soc_reg)) ||
+            (freq_table[num].frequency == FREQ_1P2_GHZ / 1000))
+	{
+		printk("Using anatop regulators: LDO enabled\n");
+	} else {
+		int puvolt = regulator_get_voltage(anatop_pu_reg);
+
+		printk("Not using anatop LDO's: enabling LDO bypass\n");
+		regulator_allow_bypass(anatop_arm_reg, true);
+		regulator_allow_bypass(anatop_pu_reg, true);
+		if (regulator_is_same(pu_reg, anatop_pu_reg))
+			regulator_allow_bypass(pu_reg, true);
+		regulator_allow_bypass(anatop_soc_reg, true);
+		if (!regulator_is_bypass(anatop_arm_reg) ||
+		    !regulator_is_bypass(anatop_pu_reg) ||
+		    !regulator_is_bypass(anatop_soc_reg))
+			dev_err(cpu_dev, "failed to set LDO bypass\n");
+		else {
+			if (puvolt == 0)
+				regulator_set_voltage(anatop_pu_reg, 0, 0);
+		}
+
+	}
+	regulator_put(anatop_arm_reg);
+	regulator_put(anatop_pu_reg);
+	regulator_put(anatop_soc_reg);
+
 	of_node_put(np);
+
 	return 0;
 
 free_freq_table: