* [RFC 1/8] ARM: imx: gpc: Do not print error message for EPROBE_DEFER
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
2017-03-22 16:53 ` [RFC 2/8] cpufreq: imx6q: Fix handling EPROBE_DEFER from regulator Leonard Crestez
` (6 subsequent siblings)
7 siblings, 0 replies; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
The pu regulator request will return -EPROBE_DEFER if it has a supply
from PMIC and this supply is not yet registered. This does not represent
an error since the driver will call probe again later, so only print a
warning message in this case.
Signed-off-by: Irina Tirdea <irina.tirdea@nxp.com>
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
arch/arm/mach-imx/gpc.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 1dc2a34..ce64d11 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -466,7 +466,11 @@ static int imx_gpc_probe(struct platform_device *pdev)
pu_reg = NULL;
if (IS_ERR(pu_reg)) {
ret = PTR_ERR(pu_reg);
- dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
+ if (ret == -EPROBE_DEFER)
+ dev_dbg(&pdev->dev, "pu regulator not ready, retry\n");
+ else
+ dev_err(&pdev->dev, "failed to get pu regulator: %d\n",
+ ret);
return ret;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [RFC 2/8] cpufreq: imx6q: Fix handling EPROBE_DEFER from regulator
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
2017-03-22 16:53 ` [RFC 1/8] ARM: imx: gpc: Do not print error message for EPROBE_DEFER Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
[not found] ` <7f2618363d43b30db29f5f8ae822df413392f99d.1490199005.git.leonard.crestez-3arQi8VN3Tc@public.gmane.org>
2017-03-22 16:53 ` [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend Leonard Crestez
` (5 subsequent siblings)
7 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
From: Irina Tirdea <irina.tirdea@nxp.com>
If there are any errors in getting the cpu0 regulators, the driver returns
-ENOENT. In case the regulators are not yet available, the devm_regulator_get
calls will return -EPROBE_DEFER, so that the driver can be probed later.
If we return -ENOENT, the driver will fail its initialization and will
not try to probe again (when the regulators become available).
Return the actual error received from regulator_get in probe. Print a
differentiated message in case we need to probe the device later and
in case we actually failed. Also add a message to inform when the
driver has been successfully registered.
Signed-off-by: Irina Tirdea <irina.tirdea@nxp.com>
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
drivers/cpufreq/imx6q-cpufreq.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 7719b02..be90ee3 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -222,6 +222,13 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
arm_reg = regulator_get(cpu_dev, "arm");
pu_reg = regulator_get_optional(cpu_dev, "pu");
soc_reg = regulator_get(cpu_dev, "soc");
+ if (PTR_ERR(arm_reg) == -EPROBE_DEFER ||
+ PTR_ERR(soc_reg) == -EPROBE_DEFER ||
+ PTR_ERR(pu_reg) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ dev_dbg(cpu_dev, "regulators not ready, defer\n");
+ goto put_reg;
+ }
if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
dev_err(cpu_dev, "failed to get regulators\n");
ret = -ENOENT;
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
2017-03-22 16:53 ` [RFC 1/8] ARM: imx: gpc: Do not print error message for EPROBE_DEFER Leonard Crestez
2017-03-22 16:53 ` [RFC 2/8] cpufreq: imx6q: Fix handling EPROBE_DEFER from regulator Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
2017-03-23 4:34 ` Viresh Kumar
2017-03-22 16:53 ` [RFC 4/8] regulator: core: Check enabling bypass respects constraints Leonard Crestez
` (4 subsequent siblings)
7 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
If the cpufreq driver tries to modify voltage/freq during suspend/resume
it might need to control an external PMIC via I2C or SPI but those
devices might be already suspended.
To avoid this scenario we just increase cpufreq to highest setpoint
before suspend. This issue can easily be triggered by ldo-bypass but in
theory any regulator set_voltage call can end up having to modify
external supply voltages.
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
drivers/cpufreq/imx6q-cpufreq.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index be90ee3..e2c1fbf 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -162,6 +162,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
{
policy->clk = arm_clk;
+ policy->suspend_freq = freq_table[soc_opp_count - 1].frequency;
return cpufreq_generic_init(policy, freq_table, transition_latency);
}
@@ -173,6 +174,7 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
.init = imx6q_cpufreq_init,
.name = "imx6q-cpufreq",
.attr = cpufreq_generic_attr,
+ .suspend = cpufreq_generic_suspend,
};
static int imx6q_cpufreq_probe(struct platform_device *pdev)
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend
2017-03-22 16:53 ` [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend Leonard Crestez
@ 2017-03-23 4:34 ` Viresh Kumar
2017-03-28 20:03 ` Leonard Crestez
0 siblings, 1 reply; 31+ messages in thread
From: Viresh Kumar @ 2017-03-23 4:34 UTC (permalink / raw)
To: Leonard Crestez
Cc: Mark Brown, Liam Girdwood, Rafael J. Wysocki, Shawn Guo,
Sascha Hauer, Robin Gong, Anson Huang, Irina Tirdea, Rob Herring,
Mark Rutland, Fabio Estevam, Octavian Purdila, linux-pm,
linux-arm-kernel, devicetree, linux-kernel
On 22-03-17, 18:53, Leonard Crestez wrote:
> If the cpufreq driver tries to modify voltage/freq during suspend/resume
> it might need to control an external PMIC via I2C or SPI but those
> devices might be already suspended.
>
> To avoid this scenario we just increase cpufreq to highest setpoint
> before suspend. This issue can easily be triggered by ldo-bypass but in
> theory any regulator set_voltage call can end up having to modify
> external supply voltages.
>
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> ---
> drivers/cpufreq/imx6q-cpufreq.c | 2 ++
> 1 file changed, 2 insertions(+)
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend
2017-03-23 4:34 ` Viresh Kumar
@ 2017-03-28 20:03 ` Leonard Crestez
2017-03-28 20:50 ` Rafael J. Wysocki
0 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-28 20:03 UTC (permalink / raw)
To: Viresh Kumar
Cc: Mark Brown, Liam Girdwood, Rafael J. Wysocki, Shawn Guo,
Sascha Hauer, Robin Gong, Anson Huang, Irina Tirdea, Rob Herring,
Mark Rutland, Fabio Estevam, Octavian Purdila,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Thu, 2017-03-23 at 10:04 +0530, Viresh Kumar wrote:
> On 22-03-17, 18:53, Leonard Crestez wrote:
> > If the cpufreq driver tries to modify voltage/freq during suspend/resume
> > it might need to control an external PMIC via I2C or SPI but those
> > devices might be already suspended.
> >
> > To avoid this scenario we just increase cpufreq to highest setpoint
> > before suspend. This issue can easily be triggered by ldo-bypass but in
> > theory any regulator set_voltage call can end up having to modify
> > external supply voltages.
> >
> > Signed-off-by: Leonard Crestez <leonard.crestez-3arQi8VN3Tc@public.gmane.org>
> > ---
> > drivers/cpufreq/imx6q-cpufreq.c | 2 ++
> > 1 file changed, 2 insertions(+)
>
> Acked-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
The first couple of patches are obvious fixes despite being marked as
RFC. It would be great if you could apply them to your tree separately
from the rest of the series but I'm not sure what the process is here.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend
2017-03-28 20:03 ` Leonard Crestez
@ 2017-03-28 20:50 ` Rafael J. Wysocki
2017-03-28 22:23 ` Rafael J. Wysocki
0 siblings, 1 reply; 31+ messages in thread
From: Rafael J. Wysocki @ 2017-03-28 20:50 UTC (permalink / raw)
To: Leonard Crestez
Cc: Mark Rutland, devicetree, Anson Huang, Irina Tirdea, Viresh Kumar,
linux-pm, Liam Girdwood, Rob Herring, linux-kernel, Mark Brown,
Octavian Purdila, Sascha Hauer, Fabio Estevam, Robin Gong,
Shawn Guo, linux-arm-kernel
On Tuesday, March 28, 2017 11:03:51 PM Leonard Crestez wrote:
> On Thu, 2017-03-23 at 10:04 +0530, Viresh Kumar wrote:
> > On 22-03-17, 18:53, Leonard Crestez wrote:
> > > If the cpufreq driver tries to modify voltage/freq during suspend/resume
> > > it might need to control an external PMIC via I2C or SPI but those
> > > devices might be already suspended.
> > >
> > > To avoid this scenario we just increase cpufreq to highest setpoint
> > > before suspend. This issue can easily be triggered by ldo-bypass but in
> > > theory any regulator set_voltage call can end up having to modify
> > > external supply voltages.
> > >
> > > Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> > > ---
> > > drivers/cpufreq/imx6q-cpufreq.c | 2 ++
> > > 1 file changed, 2 insertions(+)
> >
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>
> The first couple of patches are obvious fixes despite being marked as
> RFC. It would be great if you could apply them to your tree separately
Why?
> from the rest of the series but I'm not sure what the process is here.
Well, you have to talk to me.
Thanks,
Rafael
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend
2017-03-28 20:50 ` Rafael J. Wysocki
@ 2017-03-28 22:23 ` Rafael J. Wysocki
0 siblings, 0 replies; 31+ messages in thread
From: Rafael J. Wysocki @ 2017-03-28 22:23 UTC (permalink / raw)
To: Leonard Crestez
Cc: Viresh Kumar, Mark Brown, Liam Girdwood, Shawn Guo, Sascha Hauer,
Robin Gong, Anson Huang, Irina Tirdea, Rob Herring, Mark Rutland,
Fabio Estevam, Octavian Purdila, linux-pm, linux-arm-kernel,
devicetree, linux-kernel
On Tuesday, March 28, 2017 10:50:50 PM Rafael J. Wysocki wrote:
> On Tuesday, March 28, 2017 11:03:51 PM Leonard Crestez wrote:
> > On Thu, 2017-03-23 at 10:04 +0530, Viresh Kumar wrote:
> > > On 22-03-17, 18:53, Leonard Crestez wrote:
> > > > If the cpufreq driver tries to modify voltage/freq during suspend/resume
> > > > it might need to control an external PMIC via I2C or SPI but those
> > > > devices might be already suspended.
> > > >
> > > > To avoid this scenario we just increase cpufreq to highest setpoint
> > > > before suspend. This issue can easily be triggered by ldo-bypass but in
> > > > theory any regulator set_voltage call can end up having to modify
> > > > external supply voltages.
> > > >
> > > > Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> > > > ---
> > > > drivers/cpufreq/imx6q-cpufreq.c | 2 ++
> > > > 1 file changed, 2 insertions(+)
> > >
> > > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> >
> > The first couple of patches are obvious fixes despite being marked as
> > RFC. It would be great if you could apply them to your tree separately
>
> Why?
>
> > from the rest of the series but I'm not sure what the process is here.
>
> Well, you have to talk to me.
OK, so if I understand this correctly, you would like the patches ACKed by
Viresh to be applied regardless of what happens to the rest of the series,
right?
In that case please resend them separately without the [RFC] tag and with
the ACKs from Viresh.
Thanks,
Rafael
^ permalink raw reply [flat|nested] 31+ messages in thread
* [RFC 4/8] regulator: core: Check enabling bypass respects constraints
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
` (2 preceding siblings ...)
2017-03-22 16:53 ` [RFC 3/8] cpufreq: imx6q: Set max suspend_freq to avoid changes during suspend Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
[not found] ` <1edff9bc610969b0c53fa1080d5db021c8e00b2d.1490199005.git.leonard.crestez-3arQi8VN3Tc@public.gmane.org>
2017-03-22 16:53 ` [RFC 5/8] regulator: anatop: fix min dropout for bypass mode Leonard Crestez
` (3 subsequent siblings)
7 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
Enabling bypass mode makes a regulator passthrough the supply voltage
directly. It is possible that the supply voltage is set high enough that
it violates machine constraints so let's check for that.
The supply voltage might be higher because of min_dropout_uV or maybe
there is just an unrelated consumer who requested a higher voltage.
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
drivers/regulator/core.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 53d4fc7..9d893aa 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3453,6 +3453,54 @@ int regulator_set_load(struct regulator *regulator, int uA_load)
}
EXPORT_SYMBOL_GPL(regulator_set_load);
+static int _regulator_set_bypass(struct regulator *regulator, bool bypass)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ int output_voltage;
+ int supply_voltage;
+
+ if (bypass && !rdev->supply) {
+ rdev_err(rdev, "Refuse to set bypass on regulator with no supply!\n");
+ return -EINVAL;
+ }
+
+ /* Check that enabling bypass won't break constraints */
+ if (bypass && _regulator_is_enabled(rdev)) {
+ output_voltage = _regulator_get_voltage(rdev);
+ if (output_voltage < 0) {
+ rdev_err(rdev, "Failed to get old output voltage before"
+ " enabling bypass: %d\n", output_voltage);
+ return output_voltage;
+ }
+ supply_voltage = _regulator_get_voltage(rdev->supply->rdev);
+ if (supply_voltage < 0) {
+ rdev_err(rdev, "Failed to get supply voltage before"
+ " enabling bypass: %d\n", supply_voltage);
+ return supply_voltage;
+ }
+ if (supply_voltage < rdev->constraints->min_uV ||
+ supply_voltage > rdev->constraints->max_uV) {
+ rdev_err(rdev, "Enabling bypass would change voltage"
+ " from %duV to %duV violating"
+ " constraint range %duV to %duV\n",
+ output_voltage,
+ supply_voltage,
+ rdev->constraints->min_uV,
+ rdev->constraints->max_uV);
+ return -EINVAL;
+ }
+ rdev_dbg(rdev, "Enabling bypass would change voltage"
+ " from %duV to %duV respecting"
+ " constraint range %duV to %duV\n",
+ output_voltage,
+ supply_voltage,
+ rdev->constraints->min_uV,
+ rdev->constraints->max_uV);
+ }
+
+ return rdev->desc->ops->set_bypass(rdev, bypass);
+}
+
/**
* regulator_allow_bypass - allow the regulator to go into bypass mode
*
@@ -3481,7 +3529,7 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable)
rdev->bypass_count++;
if (rdev->bypass_count == rdev->open_count) {
- ret = rdev->desc->ops->set_bypass(rdev, enable);
+ ret = _regulator_set_bypass(regulator, enable);
if (ret != 0)
rdev->bypass_count--;
}
@@ -3490,7 +3538,7 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable)
rdev->bypass_count--;
if (rdev->bypass_count != rdev->open_count) {
- ret = rdev->desc->ops->set_bypass(rdev, enable);
+ ret = _regulator_set_bypass(regulator, enable);
if (ret != 0)
rdev->bypass_count++;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [RFC 5/8] regulator: anatop: fix min dropout for bypass mode
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
` (3 preceding siblings ...)
2017-03-22 16:53 ` [RFC 4/8] regulator: core: Check enabling bypass respects constraints Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
2017-03-24 12:54 ` Mark Brown
2017-03-22 16:53 ` [RFC 6/8] regulator: core: Add regulator_is_bypass function Leonard Crestez
` (2 subsequent siblings)
7 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
From: Irina Tirdea <irina.tirdea@nxp.com>
In bypass mode, the anatop digital regulators do not have any minimum
dropout value (the input voltage is equal to the output voltage according
to documentation).
Having a min dropout value of 125mV will lead to an increased voltage
for PMIC supplies.
Only set minimum dropout value for ldo enabled mode.
Signed-off-by: Irina Tirdea <irina.tirdea@nxp.com>
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
drivers/regulator/anatop-regulator.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index b041f27..64554e8 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -38,6 +38,8 @@
#define LDO_POWER_GATE 0x00
#define LDO_FET_FULL_ON 0x1f
+#define LDO_MIN_DROPOUT_UV 125000
+
struct anatop_regulator {
const char *name;
u32 control_reg;
@@ -153,6 +155,10 @@ static int anatop_regmap_set_bypass(struct regulator_dev *reg, bool enable)
sel = enable ? LDO_FET_FULL_ON : anatop_reg->sel;
anatop_reg->bypass = enable;
+ if (anatop_reg->bypass)
+ anatop_reg->rdesc.min_dropout_uV = 0;
+ else
+ anatop_reg->rdesc.min_dropout_uV = LDO_MIN_DROPOUT_UV;
return regulator_set_voltage_sel_regmap(reg, sel);
}
@@ -264,7 +270,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
rdesc->vsel_reg = sreg->control_reg;
rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) <<
sreg->vol_bit_shift;
- rdesc->min_dropout_uV = 125000;
+ rdesc->min_dropout_uV = LDO_MIN_DROPOUT_UV;
config.dev = &pdev->dev;
config.init_data = initdata;
@@ -286,6 +292,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
if (sreg->sel == LDO_FET_FULL_ON) {
sreg->sel = 0;
sreg->bypass = true;
+ rdesc->min_dropout_uV = 0;
}
/*
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [RFC 5/8] regulator: anatop: fix min dropout for bypass mode
2017-03-22 16:53 ` [RFC 5/8] regulator: anatop: fix min dropout for bypass mode Leonard Crestez
@ 2017-03-24 12:54 ` Mark Brown
2017-03-28 11:52 ` Leonard Crestez
0 siblings, 1 reply; 31+ messages in thread
From: Mark Brown @ 2017-03-24 12:54 UTC (permalink / raw)
To: Leonard Crestez
Cc: Mark Rutland, devicetree, Anson Huang, Irina Tirdea, Viresh Kumar,
linux-pm, Rafael J. Wysocki, Liam Girdwood, linux-kernel,
Rob Herring, Octavian Purdila, Sascha Hauer, Fabio Estevam,
Robin Gong, Shawn Guo, linux-arm-kernel
[-- Attachment #1.1: Type: text/plain, Size: 661 bytes --]
On Wed, Mar 22, 2017 at 06:53:07PM +0200, Leonard Crestez wrote:
> + if (anatop_reg->bypass)
> + anatop_reg->rdesc.min_dropout_uV = 0;
> + else
> + anatop_reg->rdesc.min_dropout_uV = LDO_MIN_DROPOUT_UV;
No, this is completely broken - you can't expect to randomly change hthe
regulator description at runtime behind the back of the framework and
expect things to work. If there is a need to do this we need an
interface for getting the current value and a way to notify of changes.
That said I would not expect the dropout voltage to be considered at
all when the regulator is bypassed, since the regulator is not
regulating it doesn't need any headroom.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [RFC 5/8] regulator: anatop: fix min dropout for bypass mode
2017-03-24 12:54 ` Mark Brown
@ 2017-03-28 11:52 ` Leonard Crestez
0 siblings, 0 replies; 31+ messages in thread
From: Leonard Crestez @ 2017-03-28 11:52 UTC (permalink / raw)
To: Mark Brown
Cc: Mark Rutland, devicetree, Anson Huang, Irina Tirdea, Viresh Kumar,
linux-pm, Rafael J. Wysocki, Liam Girdwood, linux-kernel,
Rob Herring, Octavian Purdila, Sascha Hauer, Fabio Estevam,
Robin Gong, Shawn Guo, linux-arm-kernel
On Fri, 2017-03-24 at 12:54 +0000, Mark Brown wrote:
> On Wed, Mar 22, 2017 at 06:53:07PM +0200, Leonard Crestez wrote:
> > + if (anatop_reg->bypass)
> > + anatop_reg->rdesc.min_dropout_uV = 0;
> > + else
> > + anatop_reg->rdesc.min_dropout_uV = LDO_MIN_DROPOUT_UV;
> No, this is completely broken - you can't expect to randomly change hthe
> regulator description at runtime behind the back of the framework and
> expect things to work. If there is a need to do this we need an
> interface for getting the current value and a way to notify of changes.
>
> That said I would not expect the dropout voltage to be considered at
> all when the regulator is bypassed, since the regulator is not
> regulating it doesn't need any headroom.
It's a more complex solution but this could be handled in the core instead.
Basically the core would treat min_dropout_uV as zero if the regulator is
currently in bypass mode.
In theory a function could be added in regulator_ops to ask a regulator driver
what requirements it has for its supply but this does not seem necessary.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 31+ messages in thread
* [RFC 6/8] regulator: core: Add regulator_is_bypass function
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
` (4 preceding siblings ...)
2017-03-22 16:53 ` [RFC 5/8] regulator: anatop: fix min dropout for bypass mode Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
[not found] ` <e74c2f4d2b452cbe01aa2a48edde5c024212ffcb.1490199005.git.leonard.crestez-3arQi8VN3Tc@public.gmane.org>
2017-03-22 16:53 ` [RFC 7/8] cpufreq: imx6q: Initialize LDO bypass Leonard Crestez
2017-03-22 16:53 ` [RFC 8/8] ARM: dts: imx6qdl-sabresd: Enable fsl,ldo-bypass Leonard Crestez
7 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
This is a simple kernel API to query the bypass state of a regulator.
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
drivers/regulator/core.c | 26 ++++++++++++++++++++++++++
include/linux/regulator/consumer.h | 1 +
2 files changed, 27 insertions(+)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9d893aa..7d4f59e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3554,6 +3554,32 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable)
EXPORT_SYMBOL_GPL(regulator_allow_bypass);
/**
+ * regulator_is_bypass - Determine if the regulator is in bypass mode
+ *
+ * @regulator: Regulator to examine
+ *
+ * @return 0 or 1 for true/false or errno on failure
+ *
+ * Returns zero on a regulator without bypass support.
+ */
+int regulator_is_bypass(struct regulator *regulator)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ bool bypass;
+ int ret = 0;
+
+ if (!rdev->desc->ops->get_bypass)
+ return 0;
+
+ mutex_lock(&rdev->mutex);
+ ret = rdev->desc->ops->get_bypass(rdev, &bypass);
+ mutex_unlock(&rdev->mutex);
+
+ return ret ? ret : !!bypass;
+}
+EXPORT_SYMBOL_GPL(regulator_is_bypass);
+
+/**
* regulator_register_notifier - register regulator event notifier
* @regulator: regulator source
* @nb: notifier block
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index ea0fffa..ba78511 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -261,6 +261,7 @@ int regulator_get_error_flags(struct regulator *regulator,
int regulator_set_load(struct regulator *regulator, int load_uA);
int regulator_allow_bypass(struct regulator *regulator, bool allow);
+int regulator_is_bypass(struct regulator *regulator);
struct regmap *regulator_get_regmap(struct regulator *regulator);
int regulator_get_hardware_vsel_register(struct regulator *regulator,
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [RFC 7/8] cpufreq: imx6q: Initialize LDO bypass
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
` (5 preceding siblings ...)
2017-03-22 16:53 ` [RFC 6/8] regulator: core: Add regulator_is_bypass function Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
2017-03-22 17:09 ` Lucas Stach
2017-03-22 16:53 ` [RFC 8/8] ARM: dts: imx6qdl-sabresd: Enable fsl,ldo-bypass Leonard Crestez
7 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
Several imx6* socs have three built-in regulators LDO_ARM LDO_SOC and
LDO_PU used to control internal chip voltages. "ldo-bypass" mode refers
to placing these regulators in bypass mode and controlling voltages from
an external power management chip instead. This is intended to save
power at the expense of an extra PMIC on the board.
The voltages for these regulators are controlled from the imxq6 cpufreq
driver so it makes sense to also control LDO bypass from here. The gpc
driver also fetches a reference to LDO_PU and uses it to gate power to
graphics blocks.
The LDO regulator has a minimum dropout voltage of 125mv so enabling
bypass mode will raise the effective voltage by that amount. We need set
the minimum frequency first to avoid overvolting when enabling LDO
bypass.
The binding is an u32 fsl,ldo-bypass in the gpc node because that's how
it was defined in the freescale vendor tree for a long time and
compatibility is desirable. Otherwise it would be a bool.
Some versions of u-boot shipped by freescale check this same property
and set regulators in bypass mode before linux actually starts so we
check for that scenario as well and finish early.
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
.../devicetree/bindings/power/fsl,imx-gpc.txt | 4 +
arch/arm/mach-imx/gpc.c | 7 +
drivers/cpufreq/imx6q-cpufreq.c | 171 +++++++++++++++++++++
3 files changed, 182 insertions(+)
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
index 65cc034..8a7584b 100644
--- a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
+++ b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
@@ -11,6 +11,10 @@ Required properties:
datasheet
- interrupts: Should contain GPC interrupt request 1
- pu-supply: Link to the LDO regulator powering the PU power domain
+- fsl,ldo-bypass: Should be 0 or 1 to enable LDO bypass mode (default 0).
+ This is performed in cooperation with cpufreq. Some versions of uboot will
+ also look at this property and set the arm and soc regulators in bypass mode
+ before linux.
- clocks: Clock phandles to devices in the PU power domain that need
to be enabled during domain power-up for reset propagation.
- #power-domain-cells: Should be 1, see below:
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index ce64d11..62a2555 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -22,6 +22,7 @@
#include <linux/pm_domain.h>
#include <linux/regulator/consumer.h>
#include <linux/irqchip/arm-gic.h>
+#include <linux/cpufreq.h>
#include "common.h"
#include "hardware.h"
@@ -461,6 +462,12 @@ static int imx_gpc_probe(struct platform_device *pdev)
if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
return 0;
+ /* wait for cpufreq to initialize before using pu_reg */
+ if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ) && cpufreq_get_current_driver() == NULL) {
+ dev_dbg(&pdev->dev, "cpufreq driver not ready, retry\n");
+ return -EPROBE_DEFER;
+ }
+
pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
if (PTR_ERR(pu_reg) == -ENODEV)
pu_reg = NULL;
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index e2c1fbf..a0c11ed 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -159,8 +159,179 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
return 0;
}
+/*
+ * Enable ldo-bypass mode if configured and not already performed by u-boot
+ */
+static int imx6q_cpufreq_init_ldo_bypass(void)
+{
+ struct device_node *gpc_node;
+ unsigned long old_freq_hz;
+ int i, old_freq_index;
+ u32 bypass = 0;
+ int ret = 0, ret2;
+
+ /* Read ldo-bypass property */
+ gpc_node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+ if (!gpc_node)
+ return 0;
+ ret = of_property_read_u32(gpc_node, "fsl,ldo-bypass", &bypass);
+ if (ret && ret != -EINVAL)
+ dev_warn(cpu_dev, "failed reading fsl,ldo-bypass property: %d\n", ret);
+ if (!bypass)
+ goto out;
+
+ /*
+ * Freescale u-boot handles ldo-bypass by setting
+ * arm/soc in bypass and vddpu disabled.
+ *
+ * If this is the case we don't need any special freq lowering.
+ */
+ if (regulator_is_bypass(arm_reg) == 1 &&
+ regulator_is_bypass(soc_reg) == 1)
+ {
+ dev_info(cpu_dev, "vddarm and vddsoc already in bypass\n");
+ if (IS_ERR(pu_reg)) {
+ ret = 0;
+ goto out;
+ } else if (regulator_is_enabled(pu_reg) == 0) {
+ ret = regulator_allow_bypass(pu_reg, true);
+ if (ret) {
+ dev_err(cpu_dev, "failed to enable vddpu bypass: %d\n", ret);
+ goto out;
+ }
+ ret = regulator_is_bypass(pu_reg);
+ if (ret != 1) {
+ ret = -EINVAL;
+ dev_err(cpu_dev, "failed bypass check for vddpu: %d\n", ret);
+ goto out;
+ }
+ ret = 0;
+ goto out;
+ } else if (regulator_is_bypass(pu_reg) == 1) {
+ dev_info(cpu_dev, "vddpu also already in bypass\n");
+ ret = 0;
+ goto out;
+ } else
+ dev_info(cpu_dev, "Need frequency lowering to set vddpu in bypass\n");
+ }
+
+ /*
+ * Enable LDO bypass from kernel.
+ *
+ * The LDO regulator has a minimum dropout voltage of 125mv so enabling
+ * bypass mode will raise the effective voltage by that amount.
+ *
+ * We set the minimum frequency first to avoid overvolting.
+ */
+
+ /* Find current freq so we can restore it. */
+ old_freq_hz = clk_get_rate(arm_clk);
+ if (!old_freq_hz) {
+ dev_err(cpu_dev, "failed to determine current arm freq\n");
+ goto out;
+ }
+ old_freq_index = 0;
+ for (i = 1; i < soc_opp_count; ++i) {
+ if (abs(freq_table[old_freq_index].frequency - old_freq_hz) >
+ abs(freq_table[i].frequency - old_freq_hz)) {
+ old_freq_index = i;
+ }
+ }
+ dev_dbg(cpu_dev, "current freq %lu Mhz index %d\n",
+ old_freq_hz / 1000000, old_freq_index);
+
+ dev_info(cpu_dev, "enabling ldo_bypass\n");
+ ret = imx6q_set_target(NULL, 0);
+ if (ret) {
+ dev_warn(cpu_dev, "Failed to lower frequency: %d\n", ret);
+ goto out;
+ }
+
+ ret = regulator_allow_bypass(arm_reg, true);
+ if (ret) {
+ dev_err(cpu_dev, "failed to enable bypass for vddarm: %d\n", ret);
+ goto out_restore_cpufreq;
+ }
+ ret = regulator_allow_bypass(soc_reg, true);
+ if (ret) {
+ dev_err(cpu_dev, "failed to enable bypass for vddsoc: %d\n", ret);
+ goto out_restore_arm_reg;
+ }
+ if (!IS_ERR(pu_reg)) {
+ ret = regulator_allow_bypass(pu_reg, true);
+ if (ret) {
+ dev_err(cpu_dev, "failed to enable bypass for vddsoc: %d\n", ret);
+ goto out_restore_soc_reg;
+ }
+ }
+
+ /*
+ * We need to do get_bypass afterwards because allow_bypass does not
+ * actually guarantee bypass mode was entered if it returns 0. In
+ * theory there might be another used.
+ */
+ ret = regulator_is_bypass(arm_reg);
+ if (ret != 1) {
+ ret = -EINVAL;
+ dev_err(cpu_dev, "failed bypass check for vddarm: %d\n", ret);
+ goto out_restore_pu_reg;
+ }
+ ret = regulator_is_bypass(soc_reg);
+ if (ret != 1) {
+ ret = -EINVAL;
+ dev_err(cpu_dev, "failed bypass check for vddsoc: %d\n", ret);
+ goto out_restore_pu_reg;
+ }
+ if (!IS_ERR(pu_reg)) {
+ ret = regulator_is_bypass(pu_reg);
+ if (ret != 1) {
+ ret = -EINVAL;
+ dev_err(cpu_dev, "failed bypass check for vddpu: %d\n", ret);
+ goto out_restore_pu_reg;
+ }
+ }
+
+ ret = imx6q_set_target(NULL, old_freq_index);
+ if (ret)
+ dev_warn(cpu_dev, "Failed to restore frequency: %d\n", ret);
+ /* Success! */
+ ret = 0;
+ goto out;
+
+out_restore_pu_reg:
+ if (!IS_ERR(pu_reg)) {
+ ret2 = regulator_allow_bypass(pu_reg, false);
+ if (ret2)
+ dev_err(cpu_dev, "failed to restore vddpu: %d\n", ret2);
+ }
+out_restore_arm_reg:
+ ret2 = regulator_allow_bypass(arm_reg, false);
+ if (ret2)
+ dev_err(cpu_dev, "failed to restore vddarm: %d\n", ret2);
+out_restore_soc_reg:
+ ret2 = regulator_allow_bypass(soc_reg, false);
+ if (ret2)
+ dev_err(cpu_dev, "failed to restore vddsoc: %d\n", ret2);
+out_restore_cpufreq:
+ ret2 = imx6q_set_target(NULL, old_freq_index);
+ if (ret2)
+ dev_warn(cpu_dev, "Failed to restore frequency: %d\n", ret2);
+
+out:
+ of_node_put(gpc_node);
+ return ret;
+}
+
static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
{
+ int ret;
+
+ ret = imx6q_cpufreq_init_ldo_bypass();
+ if (ret) {
+ dev_err(cpu_dev, "failed to enable ldo_bypass: %d\n", ret);
+ return ret;
+ }
+
policy->clk = arm_clk;
policy->suspend_freq = freq_table[soc_opp_count - 1].frequency;
return cpufreq_generic_init(policy, freq_table, transition_latency);
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [RFC 7/8] cpufreq: imx6q: Initialize LDO bypass
2017-03-22 16:53 ` [RFC 7/8] cpufreq: imx6q: Initialize LDO bypass Leonard Crestez
@ 2017-03-22 17:09 ` Lucas Stach
[not found] ` <1490202585.29056.5.camel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
0 siblings, 1 reply; 31+ messages in thread
From: Lucas Stach @ 2017-03-22 17:09 UTC (permalink / raw)
To: Leonard Crestez
Cc: Mark Rutland, devicetree, Anson Huang, Irina Tirdea, Viresh Kumar,
linux-pm, Rafael J. Wysocki, Liam Girdwood, Rob Herring,
linux-kernel, Mark Brown, Octavian Purdila, Sascha Hauer,
Fabio Estevam, Robin Gong, Shawn Guo, linux-arm-kernel
Am Mittwoch, den 22.03.2017, 18:53 +0200 schrieb Leonard Crestez:
> Several imx6* socs have three built-in regulators LDO_ARM LDO_SOC and
> LDO_PU used to control internal chip voltages. "ldo-bypass" mode refers
> to placing these regulators in bypass mode and controlling voltages from
> an external power management chip instead. This is intended to save
> power at the expense of an extra PMIC on the board.
>
> The voltages for these regulators are controlled from the imxq6 cpufreq
> driver so it makes sense to also control LDO bypass from here. The gpc
> driver also fetches a reference to LDO_PU and uses it to gate power to
> graphics blocks.
>
> The LDO regulator has a minimum dropout voltage of 125mv so enabling
> bypass mode will raise the effective voltage by that amount. We need set
> the minimum frequency first to avoid overvolting when enabling LDO
> bypass.
>
> The binding is an u32 fsl,ldo-bypass in the gpc node because that's how
> it was defined in the freescale vendor tree for a long time and
> compatibility is desirable. Otherwise it would be a bool.
>
> Some versions of u-boot shipped by freescale check this same property
> and set regulators in bypass mode before linux actually starts so we
> check for that scenario as well and finish early.
I've not looked at the patch at all, but this feels like the wrong
location to implement this. Using bypass mode or not should really be a
internal decision of the regulator driver, influenced by a DT property
to allow bypass mode.
The regulator driver can also implement the correct sequencing of first
lowering external voltage to min + dropout, then going into bypass mode,
then lower the external voltage by the amount of the dropout. I don't
see why we need a frequency switch for this at all.
Implementing this in the consumers seems like the wrong spot.
Regards,
Lucas
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> ---
> .../devicetree/bindings/power/fsl,imx-gpc.txt | 4 +
> arch/arm/mach-imx/gpc.c | 7 +
> drivers/cpufreq/imx6q-cpufreq.c | 171 +++++++++++++++++++++
> 3 files changed, 182 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
> index 65cc034..8a7584b 100644
> --- a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
> +++ b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
> @@ -11,6 +11,10 @@ Required properties:
> datasheet
> - interrupts: Should contain GPC interrupt request 1
> - pu-supply: Link to the LDO regulator powering the PU power domain
> +- fsl,ldo-bypass: Should be 0 or 1 to enable LDO bypass mode (default 0).
> + This is performed in cooperation with cpufreq. Some versions of uboot will
> + also look at this property and set the arm and soc regulators in bypass mode
> + before linux.
> - clocks: Clock phandles to devices in the PU power domain that need
> to be enabled during domain power-up for reset propagation.
> - #power-domain-cells: Should be 1, see below:
> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
> index ce64d11..62a2555 100644
> --- a/arch/arm/mach-imx/gpc.c
> +++ b/arch/arm/mach-imx/gpc.c
> @@ -22,6 +22,7 @@
> #include <linux/pm_domain.h>
> #include <linux/regulator/consumer.h>
> #include <linux/irqchip/arm-gic.h>
> +#include <linux/cpufreq.h>
> #include "common.h"
> #include "hardware.h"
>
> @@ -461,6 +462,12 @@ static int imx_gpc_probe(struct platform_device *pdev)
> if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
> return 0;
>
> + /* wait for cpufreq to initialize before using pu_reg */
> + if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ) && cpufreq_get_current_driver() == NULL) {
> + dev_dbg(&pdev->dev, "cpufreq driver not ready, retry\n");
> + return -EPROBE_DEFER;
> + }
> +
> pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
> if (PTR_ERR(pu_reg) == -ENODEV)
> pu_reg = NULL;
> diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
> index e2c1fbf..a0c11ed 100644
> --- a/drivers/cpufreq/imx6q-cpufreq.c
> +++ b/drivers/cpufreq/imx6q-cpufreq.c
> @@ -159,8 +159,179 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
> return 0;
> }
>
> +/*
> + * Enable ldo-bypass mode if configured and not already performed by u-boot
> + */
> +static int imx6q_cpufreq_init_ldo_bypass(void)
> +{
> + struct device_node *gpc_node;
> + unsigned long old_freq_hz;
> + int i, old_freq_index;
> + u32 bypass = 0;
> + int ret = 0, ret2;
> +
> + /* Read ldo-bypass property */
> + gpc_node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
> + if (!gpc_node)
> + return 0;
> + ret = of_property_read_u32(gpc_node, "fsl,ldo-bypass", &bypass);
> + if (ret && ret != -EINVAL)
> + dev_warn(cpu_dev, "failed reading fsl,ldo-bypass property: %d\n", ret);
> + if (!bypass)
> + goto out;
> +
> + /*
> + * Freescale u-boot handles ldo-bypass by setting
> + * arm/soc in bypass and vddpu disabled.
> + *
> + * If this is the case we don't need any special freq lowering.
> + */
> + if (regulator_is_bypass(arm_reg) == 1 &&
> + regulator_is_bypass(soc_reg) == 1)
> + {
> + dev_info(cpu_dev, "vddarm and vddsoc already in bypass\n");
> + if (IS_ERR(pu_reg)) {
> + ret = 0;
> + goto out;
> + } else if (regulator_is_enabled(pu_reg) == 0) {
> + ret = regulator_allow_bypass(pu_reg, true);
> + if (ret) {
> + dev_err(cpu_dev, "failed to enable vddpu bypass: %d\n", ret);
> + goto out;
> + }
> + ret = regulator_is_bypass(pu_reg);
> + if (ret != 1) {
> + ret = -EINVAL;
> + dev_err(cpu_dev, "failed bypass check for vddpu: %d\n", ret);
> + goto out;
> + }
> + ret = 0;
> + goto out;
> + } else if (regulator_is_bypass(pu_reg) == 1) {
> + dev_info(cpu_dev, "vddpu also already in bypass\n");
> + ret = 0;
> + goto out;
> + } else
> + dev_info(cpu_dev, "Need frequency lowering to set vddpu in bypass\n");
> + }
> +
> + /*
> + * Enable LDO bypass from kernel.
> + *
> + * The LDO regulator has a minimum dropout voltage of 125mv so enabling
> + * bypass mode will raise the effective voltage by that amount.
> + *
> + * We set the minimum frequency first to avoid overvolting.
> + */
> +
> + /* Find current freq so we can restore it. */
> + old_freq_hz = clk_get_rate(arm_clk);
> + if (!old_freq_hz) {
> + dev_err(cpu_dev, "failed to determine current arm freq\n");
> + goto out;
> + }
> + old_freq_index = 0;
> + for (i = 1; i < soc_opp_count; ++i) {
> + if (abs(freq_table[old_freq_index].frequency - old_freq_hz) >
> + abs(freq_table[i].frequency - old_freq_hz)) {
> + old_freq_index = i;
> + }
> + }
> + dev_dbg(cpu_dev, "current freq %lu Mhz index %d\n",
> + old_freq_hz / 1000000, old_freq_index);
> +
> + dev_info(cpu_dev, "enabling ldo_bypass\n");
> + ret = imx6q_set_target(NULL, 0);
> + if (ret) {
> + dev_warn(cpu_dev, "Failed to lower frequency: %d\n", ret);
> + goto out;
> + }
> +
> + ret = regulator_allow_bypass(arm_reg, true);
> + if (ret) {
> + dev_err(cpu_dev, "failed to enable bypass for vddarm: %d\n", ret);
> + goto out_restore_cpufreq;
> + }
> + ret = regulator_allow_bypass(soc_reg, true);
> + if (ret) {
> + dev_err(cpu_dev, "failed to enable bypass for vddsoc: %d\n", ret);
> + goto out_restore_arm_reg;
> + }
> + if (!IS_ERR(pu_reg)) {
> + ret = regulator_allow_bypass(pu_reg, true);
> + if (ret) {
> + dev_err(cpu_dev, "failed to enable bypass for vddsoc: %d\n", ret);
> + goto out_restore_soc_reg;
> + }
> + }
> +
> + /*
> + * We need to do get_bypass afterwards because allow_bypass does not
> + * actually guarantee bypass mode was entered if it returns 0. In
> + * theory there might be another used.
> + */
> + ret = regulator_is_bypass(arm_reg);
> + if (ret != 1) {
> + ret = -EINVAL;
> + dev_err(cpu_dev, "failed bypass check for vddarm: %d\n", ret);
> + goto out_restore_pu_reg;
> + }
> + ret = regulator_is_bypass(soc_reg);
> + if (ret != 1) {
> + ret = -EINVAL;
> + dev_err(cpu_dev, "failed bypass check for vddsoc: %d\n", ret);
> + goto out_restore_pu_reg;
> + }
> + if (!IS_ERR(pu_reg)) {
> + ret = regulator_is_bypass(pu_reg);
> + if (ret != 1) {
> + ret = -EINVAL;
> + dev_err(cpu_dev, "failed bypass check for vddpu: %d\n", ret);
> + goto out_restore_pu_reg;
> + }
> + }
> +
> + ret = imx6q_set_target(NULL, old_freq_index);
> + if (ret)
> + dev_warn(cpu_dev, "Failed to restore frequency: %d\n", ret);
> + /* Success! */
> + ret = 0;
> + goto out;
> +
> +out_restore_pu_reg:
> + if (!IS_ERR(pu_reg)) {
> + ret2 = regulator_allow_bypass(pu_reg, false);
> + if (ret2)
> + dev_err(cpu_dev, "failed to restore vddpu: %d\n", ret2);
> + }
> +out_restore_arm_reg:
> + ret2 = regulator_allow_bypass(arm_reg, false);
> + if (ret2)
> + dev_err(cpu_dev, "failed to restore vddarm: %d\n", ret2);
> +out_restore_soc_reg:
> + ret2 = regulator_allow_bypass(soc_reg, false);
> + if (ret2)
> + dev_err(cpu_dev, "failed to restore vddsoc: %d\n", ret2);
> +out_restore_cpufreq:
> + ret2 = imx6q_set_target(NULL, old_freq_index);
> + if (ret2)
> + dev_warn(cpu_dev, "Failed to restore frequency: %d\n", ret2);
> +
> +out:
> + of_node_put(gpc_node);
> + return ret;
> +}
> +
> static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
> {
> + int ret;
> +
> + ret = imx6q_cpufreq_init_ldo_bypass();
> + if (ret) {
> + dev_err(cpu_dev, "failed to enable ldo_bypass: %d\n", ret);
> + return ret;
> + }
> +
> policy->clk = arm_clk;
> policy->suspend_freq = freq_table[soc_opp_count - 1].frequency;
> return cpufreq_generic_init(policy, freq_table, transition_latency);
^ permalink raw reply [flat|nested] 31+ messages in thread
* [RFC 8/8] ARM: dts: imx6qdl-sabresd: Enable fsl,ldo-bypass
2017-03-22 16:53 [RFC 0/8] ARM: imx: Upstream fsl,ldo-bypass Leonard Crestez
` (6 preceding siblings ...)
2017-03-22 16:53 ` [RFC 7/8] cpufreq: imx6q: Initialize LDO bypass Leonard Crestez
@ 2017-03-22 16:53 ` Leonard Crestez
2017-03-22 17:13 ` Lucas Stach
7 siblings, 1 reply; 31+ messages in thread
From: Leonard Crestez @ 2017-03-22 16:53 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer
Cc: Mark Rutland, devicetree, Leonard Crestez, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
This enables LDO bypass by default on the imx6qdl-sabresd boards. New
dts files with -ldo suffix are added for users who want to run with LDOs
enabled on these boards anyway.
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
arch/arm/boot/dts/imx6dl-sabresd-ldo.dts | 13 +++++++++++++
arch/arm/boot/dts/imx6q-sabresd-ldo.dts | 13 +++++++++++++
arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 19 +++++++++++++++++++
arch/arm/boot/dts/imx6qdl.dtsi | 6 +++---
arch/arm/boot/dts/imx6qp-sabresd-ldo.dts | 13 +++++++++++++
arch/arm/boot/dts/imx6qp-sabresd.dts | 4 ++--
6 files changed, 63 insertions(+), 5 deletions(-)
create mode 100644 arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
create mode 100644 arch/arm/boot/dts/imx6q-sabresd-ldo.dts
create mode 100644 arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
diff --git a/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts b/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
new file mode 100644
index 0000000..1b224d6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6dl-sabresd.dts"
+
+&gpc {
+ fsl,ldo-bypass = <0>;
+};
diff --git a/arch/arm/boot/dts/imx6q-sabresd-ldo.dts b/arch/arm/boot/dts/imx6q-sabresd-ldo.dts
new file mode 100644
index 0000000..4d2e8cc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-ldo.dts
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6q-sabresd.dts"
+
+&gpc {
+ fsl,ldo-bypass = <0>;
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 63bf95e..5a73d9d 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -182,6 +182,10 @@
status = "okay";
};
+&gpc {
+ fsl,ldo-bypass = <1>;
+};
+
&hdmi {
ddc-i2c-bus = <&i2c2>;
status = "okay";
@@ -548,6 +552,21 @@
status = "okay";
};
+®_arm {
+ vin-supply = <&sw1a_reg>;
+ regulator-allow-bypass;
+};
+
+®_pu {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
+®_soc {
+ vin-supply = <&sw1c_reg>;
+ regulator-allow-bypass;
+};
+
&snvs_poweroff {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 6d7bf64..54fe769 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -677,7 +677,7 @@
compatible = "fsl,anatop-regulator";
regulator-name = "vddarm";
regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1450000>;
+ regulator-max-microvolt = <1300000>;
regulator-always-on;
anatop-reg-offset = <0x140>;
anatop-vol-bit-shift = <0>;
@@ -694,7 +694,7 @@
compatible = "fsl,anatop-regulator";
regulator-name = "vddpu";
regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1450000>;
+ regulator-max-microvolt = <1300000>;
regulator-enable-ramp-delay = <150>;
anatop-reg-offset = <0x140>;
anatop-vol-bit-shift = <9>;
@@ -711,7 +711,7 @@
compatible = "fsl,anatop-regulator";
regulator-name = "vddsoc";
regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1450000>;
+ regulator-max-microvolt = <1300000>;
regulator-always-on;
anatop-reg-offset = <0x140>;
anatop-vol-bit-shift = <18>;
diff --git a/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts b/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
new file mode 100644
index 0000000..c659533
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6qp-sabresd.dts"
+
+&gpc {
+ fsl,ldo-bypass = <0>;
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts
index b234580..a8a5004 100644
--- a/arch/arm/boot/dts/imx6qp-sabresd.dts
+++ b/arch/arm/boot/dts/imx6qp-sabresd.dts
@@ -50,8 +50,8 @@
compatible = "fsl,imx6qp-sabresd", "fsl,imx6qp";
};
-&cpu0 {
- arm-supply = <&sw2_reg>;
+®_arm {
+ vin-supply = <&sw2_reg>;
};
&iomuxc {
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [RFC 8/8] ARM: dts: imx6qdl-sabresd: Enable fsl,ldo-bypass
2017-03-22 16:53 ` [RFC 8/8] ARM: dts: imx6qdl-sabresd: Enable fsl,ldo-bypass Leonard Crestez
@ 2017-03-22 17:13 ` Lucas Stach
[not found] ` <1490202830.29056.8.camel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
0 siblings, 1 reply; 31+ messages in thread
From: Lucas Stach @ 2017-03-22 17:13 UTC (permalink / raw)
To: Leonard Crestez
Cc: Mark Brown, Liam Girdwood, Viresh Kumar, Rafael J. Wysocki,
Shawn Guo, Sascha Hauer, Mark Rutland, devicetree, Anson Huang,
Irina Tirdea, linux-pm, linux-kernel, Rob Herring,
Octavian Purdila, Fabio Estevam, Robin Gong, linux-arm-kernel
Am Mittwoch, den 22.03.2017, 18:53 +0200 schrieb Leonard Crestez:
> This enables LDO bypass by default on the imx6qdl-sabresd boards. New
> dts files with -ldo suffix are added for users who want to run with LDOs
> enabled on these boards anyway.
Given that using LDO bypass affects the device lifetime negatively (see
AN4724), I think the default should still be to use LDO enabled mode and
have new DTs for people that desire to shorten the lifetime of the SoC
for a minimal drop in power consumption.
Regards,
Lucas
>
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> ---
> arch/arm/boot/dts/imx6dl-sabresd-ldo.dts | 13 +++++++++++++
> arch/arm/boot/dts/imx6q-sabresd-ldo.dts | 13 +++++++++++++
> arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 19 +++++++++++++++++++
> arch/arm/boot/dts/imx6qdl.dtsi | 6 +++---
> arch/arm/boot/dts/imx6qp-sabresd-ldo.dts | 13 +++++++++++++
> arch/arm/boot/dts/imx6qp-sabresd.dts | 4 ++--
> 6 files changed, 63 insertions(+), 5 deletions(-)
> create mode 100644 arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
> create mode 100644 arch/arm/boot/dts/imx6q-sabresd-ldo.dts
> create mode 100644 arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
>
> diff --git a/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts b/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
> new file mode 100644
> index 0000000..1b224d6
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx6dl-sabresd-ldo.dts
> @@ -0,0 +1,13 @@
> +/*
> + * Copyright 2017 NXP
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include "imx6dl-sabresd.dts"
> +
> +&gpc {
> + fsl,ldo-bypass = <0>;
> +};
> diff --git a/arch/arm/boot/dts/imx6q-sabresd-ldo.dts b/arch/arm/boot/dts/imx6q-sabresd-ldo.dts
> new file mode 100644
> index 0000000..4d2e8cc
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx6q-sabresd-ldo.dts
> @@ -0,0 +1,13 @@
> +/*
> + * Copyright 2017 NXP
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include "imx6q-sabresd.dts"
> +
> +&gpc {
> + fsl,ldo-bypass = <0>;
> +};
> diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> index 63bf95e..5a73d9d 100644
> --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> @@ -182,6 +182,10 @@
> status = "okay";
> };
>
> +&gpc {
> + fsl,ldo-bypass = <1>;
> +};
> +
> &hdmi {
> ddc-i2c-bus = <&i2c2>;
> status = "okay";
> @@ -548,6 +552,21 @@
> status = "okay";
> };
>
> +®_arm {
> + vin-supply = <&sw1a_reg>;
> + regulator-allow-bypass;
> +};
> +
> +®_pu {
> + vin-supply = <&sw1c_reg>;
> + regulator-allow-bypass;
> +};
> +
> +®_soc {
> + vin-supply = <&sw1c_reg>;
> + regulator-allow-bypass;
> +};
> +
> &snvs_poweroff {
> status = "okay";
> };
> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
> index 6d7bf64..54fe769 100644
> --- a/arch/arm/boot/dts/imx6qdl.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> @@ -677,7 +677,7 @@
> compatible = "fsl,anatop-regulator";
> regulator-name = "vddarm";
> regulator-min-microvolt = <725000>;
> - regulator-max-microvolt = <1450000>;
> + regulator-max-microvolt = <1300000>;
> regulator-always-on;
> anatop-reg-offset = <0x140>;
> anatop-vol-bit-shift = <0>;
> @@ -694,7 +694,7 @@
> compatible = "fsl,anatop-regulator";
> regulator-name = "vddpu";
> regulator-min-microvolt = <725000>;
> - regulator-max-microvolt = <1450000>;
> + regulator-max-microvolt = <1300000>;
> regulator-enable-ramp-delay = <150>;
> anatop-reg-offset = <0x140>;
> anatop-vol-bit-shift = <9>;
> @@ -711,7 +711,7 @@
> compatible = "fsl,anatop-regulator";
> regulator-name = "vddsoc";
> regulator-min-microvolt = <725000>;
> - regulator-max-microvolt = <1450000>;
> + regulator-max-microvolt = <1300000>;
> regulator-always-on;
> anatop-reg-offset = <0x140>;
> anatop-vol-bit-shift = <18>;
> diff --git a/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts b/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
> new file mode 100644
> index 0000000..c659533
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx6qp-sabresd-ldo.dts
> @@ -0,0 +1,13 @@
> +/*
> + * Copyright 2017 NXP
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include "imx6qp-sabresd.dts"
> +
> +&gpc {
> + fsl,ldo-bypass = <0>;
> +};
> diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts
> index b234580..a8a5004 100644
> --- a/arch/arm/boot/dts/imx6qp-sabresd.dts
> +++ b/arch/arm/boot/dts/imx6qp-sabresd.dts
> @@ -50,8 +50,8 @@
> compatible = "fsl,imx6qp-sabresd", "fsl,imx6qp";
> };
>
> -&cpu0 {
> - arm-supply = <&sw2_reg>;
> +®_arm {
> + vin-supply = <&sw2_reg>;
> };
>
> &iomuxc {
^ permalink raw reply [flat|nested] 31+ messages in thread