* [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs"
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-10-29 9:44 ` Ivan T . Ivanov
2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
` (7 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
The commit d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
introduced a regression on Raspberry Pi 3 B Plus, which prevents
enumeration of the onboard Microchip LAN7800 in case no external USB device
is connected during boot.
Fixes: d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/usb/dwc2/params.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 68226defdc60..4d73fae80b12 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -23,7 +23,6 @@ static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg)
p->max_transfer_size = 65535;
p->max_packet_count = 511;
p->ahbcfg = 0x10;
- p->no_clock_gating = true;
}
static void dwc2_set_his_params(struct dwc2_hsotg *hsotg)
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs"
2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
@ 2024-10-29 9:44 ` Ivan T . Ivanov
0 siblings, 0 replies; 18+ messages in thread
From: Ivan T . Ivanov @ 2024-10-29 9:44 UTC (permalink / raw)
To: Stefan Wahren
Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman,
Lukas Wunner, Peter Robinson, linux-arm-kernel, kernel-list,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
Hi Stefan,
On 10-25 12:36, Stefan Wahren wrote:
>
> The commit d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
> introduced a regression on Raspberry Pi 3 B Plus, which prevents
> enumeration of the onboard Microchip LAN7800 in case no external USB device
> is connected during boot.
>
> Fixes: d483f034f032 ("usb: dwc2: Skip clock gating on Broadcom SoCs")
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
> drivers/usb/dwc2/params.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
> index 68226defdc60..4d73fae80b12 100644
> --- a/drivers/usb/dwc2/params.c
> +++ b/drivers/usb/dwc2/params.c
> @@ -23,7 +23,6 @@ static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg)
> p->max_transfer_size = 65535;
> p->max_packet_count = 511;
> p->ahbcfg = 0x10;
> - p->no_clock_gating = true;
> }
>
Thanks, this makes RPi3 Ethernet operational again.
Tested-by: Ivan T. Ivanov <iivanov@suse.de>
Regards.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-11-09 17:37 ` Stefan Wahren
2024-12-02 16:52 ` Vinod Koul
2024-10-25 10:36 ` [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed Stefan Wahren
` (6 subsequent siblings)
8 siblings, 2 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
bcm2835-dma provides the service to others, so it should
suspend late and resume early.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index e1b92b4d7b05..647dda9f3376 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
return chan;
}
+static int bcm2835_dma_suspend_late(struct device *dev)
+{
+ struct bcm2835_dmadev *od = dev_get_drvdata(dev);
+ struct bcm2835_chan *c, *next;
+
+ list_for_each_entry_safe(c, next, &od->ddev.channels,
+ vc.chan.device_node) {
+ void __iomem *chan_base = c->chan_base;
+
+ if (readl(chan_base + BCM2835_DMA_ADDR)) {
+ dev_warn(dev, "Suspend is prevented by chan %d\n",
+ c->ch);
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
+
+static int bcm2835_dma_resume_early(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops bcm2835_dma_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(bcm2835_dma_suspend_late,
+ bcm2835_dma_resume_early)
+};
+
static int bcm2835_dma_probe(struct platform_device *pdev)
{
struct bcm2835_dmadev *od;
@@ -1033,6 +1062,7 @@ static struct platform_driver bcm2835_dma_driver = {
.driver = {
.name = "bcm2835-dma",
.of_match_table = of_match_ptr(bcm2835_dma_of_match),
+ .pm = pm_ptr(&bcm2835_dma_pm_ops),
},
};
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
@ 2024-11-09 17:37 ` Stefan Wahren
2024-12-02 16:52 ` Vinod Koul
1 sibling, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-11-09 17:37 UTC (permalink / raw)
To: Russell King, Lukas Wunner, Florian Fainelli, Ray Jui,
Scott Branden, Vinod Koul
Cc: Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, Ulf Hansson,
kernel-list, Greg Kroah-Hartman, Minas Harutyunyan,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
Am 25.10.24 um 12:36 schrieb Stefan Wahren:
> bcm2835-dma provides the service to others, so it should
> suspend late and resume early.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Since there wasn't any feedback for this patch, i want to send a gentle
ping ...
Regards
> ---
> drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> index e1b92b4d7b05..647dda9f3376 100644
> --- a/drivers/dma/bcm2835-dma.c
> +++ b/drivers/dma/bcm2835-dma.c
> @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
> return chan;
> }
>
> +static int bcm2835_dma_suspend_late(struct device *dev)
> +{
> + struct bcm2835_dmadev *od = dev_get_drvdata(dev);
> + struct bcm2835_chan *c, *next;
> +
> + list_for_each_entry_safe(c, next, &od->ddev.channels,
> + vc.chan.device_node) {
> + void __iomem *chan_base = c->chan_base;
> +
> + if (readl(chan_base + BCM2835_DMA_ADDR)) {
> + dev_warn(dev, "Suspend is prevented by chan %d\n",
> + c->ch);
> + return -EBUSY;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int bcm2835_dma_resume_early(struct device *dev)
> +{
> + return 0;
> +}
> +
> +static const struct dev_pm_ops bcm2835_dma_pm_ops = {
> + SET_LATE_SYSTEM_SLEEP_PM_OPS(bcm2835_dma_suspend_late,
> + bcm2835_dma_resume_early)
> +};
> +
> static int bcm2835_dma_probe(struct platform_device *pdev)
> {
> struct bcm2835_dmadev *od;
> @@ -1033,6 +1062,7 @@ static struct platform_driver bcm2835_dma_driver = {
> .driver = {
> .name = "bcm2835-dma",
> .of_match_table = of_match_ptr(bcm2835_dma_of_match),
> + .pm = pm_ptr(&bcm2835_dma_pm_ops),
> },
> };
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
2024-11-09 17:37 ` Stefan Wahren
@ 2024-12-02 16:52 ` Vinod Koul
2024-12-02 18:51 ` Stefan Wahren
1 sibling, 1 reply; 18+ messages in thread
From: Vinod Koul @ 2024-12-02 16:52 UTC (permalink / raw)
To: Stefan Wahren
Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
On 25-10-24, 12:36, Stefan Wahren wrote:
> bcm2835-dma provides the service to others, so it should
> suspend late and resume early.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
> drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> index e1b92b4d7b05..647dda9f3376 100644
> --- a/drivers/dma/bcm2835-dma.c
> +++ b/drivers/dma/bcm2835-dma.c
> @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
> return chan;
> }
>
> +static int bcm2835_dma_suspend_late(struct device *dev)
> +{
> + struct bcm2835_dmadev *od = dev_get_drvdata(dev);
> + struct bcm2835_chan *c, *next;
> +
> + list_for_each_entry_safe(c, next, &od->ddev.channels,
> + vc.chan.device_node) {
> + void __iomem *chan_base = c->chan_base;
> +
> + if (readl(chan_base + BCM2835_DMA_ADDR)) {
> + dev_warn(dev, "Suspend is prevented by chan %d\n",
> + c->ch);
> + return -EBUSY;
> + }
Can you help understand how this helps by logging... we are not adding
anything except checking this and resume is NOP as well!
> + }
> +
> + return 0;
> +}
> +
> +static int bcm2835_dma_resume_early(struct device *dev)
> +{
> + return 0;
> +}
> +
> +static const struct dev_pm_ops bcm2835_dma_pm_ops = {
> + SET_LATE_SYSTEM_SLEEP_PM_OPS(bcm2835_dma_suspend_late,
> + bcm2835_dma_resume_early)
> +};
> +
> static int bcm2835_dma_probe(struct platform_device *pdev)
> {
> struct bcm2835_dmadev *od;
> @@ -1033,6 +1062,7 @@ static struct platform_driver bcm2835_dma_driver = {
> .driver = {
> .name = "bcm2835-dma",
> .of_match_table = of_match_ptr(bcm2835_dma_of_match),
> + .pm = pm_ptr(&bcm2835_dma_pm_ops),
> },
> };
>
> --
> 2.34.1
--
~Vinod
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
2024-12-02 16:52 ` Vinod Koul
@ 2024-12-02 18:51 ` Stefan Wahren
2024-12-04 12:27 ` Vinod Koul
0 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-12-02 18:51 UTC (permalink / raw)
To: Vinod Koul
Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
Hi Vinod,
Am 02.12.24 um 17:52 schrieb Vinod Koul:
> On 25-10-24, 12:36, Stefan Wahren wrote:
>> bcm2835-dma provides the service to others, so it should
>> suspend late and resume early.
>>
>> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
>> ---
>> drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
>> 1 file changed, 30 insertions(+)
>>
>> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
>> index e1b92b4d7b05..647dda9f3376 100644
>> --- a/drivers/dma/bcm2835-dma.c
>> +++ b/drivers/dma/bcm2835-dma.c
>> @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
>> return chan;
>> }
>>
>> +static int bcm2835_dma_suspend_late(struct device *dev)
>> +{
>> + struct bcm2835_dmadev *od = dev_get_drvdata(dev);
>> + struct bcm2835_chan *c, *next;
>> +
>> + list_for_each_entry_safe(c, next, &od->ddev.channels,
>> + vc.chan.device_node) {
>> + void __iomem *chan_base = c->chan_base;
>> +
>> + if (readl(chan_base + BCM2835_DMA_ADDR)) {
>> + dev_warn(dev, "Suspend is prevented by chan %d\n",
>> + c->ch);
>> + return -EBUSY;
>> + }
> Can you help understand how this helps by logging... we are not adding
> anything except checking this and resume is NOP as well!
My intention of this patch is just to make sure, that no DMA transfer is
in progress during late_suspend. So i followed the implementation of
fsldma.c
Additionally i added this warning mostly to know if this ever occurs.
But i wasn't able to trigger.
Should i drop the warning and make resume callback = NULL?
Best regards
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support
2024-12-02 18:51 ` Stefan Wahren
@ 2024-12-04 12:27 ` Vinod Koul
0 siblings, 0 replies; 18+ messages in thread
From: Vinod Koul @ 2024-12-04 12:27 UTC (permalink / raw)
To: Stefan Wahren
Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
On 02-12-24, 19:51, Stefan Wahren wrote:
> Hi Vinod,
>
> Am 02.12.24 um 17:52 schrieb Vinod Koul:
> > On 25-10-24, 12:36, Stefan Wahren wrote:
> > > bcm2835-dma provides the service to others, so it should
> > > suspend late and resume early.
> > >
> > > Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> > > ---
> > > drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++++++++
> > > 1 file changed, 30 insertions(+)
> > >
> > > diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> > > index e1b92b4d7b05..647dda9f3376 100644
> > > --- a/drivers/dma/bcm2835-dma.c
> > > +++ b/drivers/dma/bcm2835-dma.c
> > > @@ -875,6 +875,35 @@ static struct dma_chan *bcm2835_dma_xlate(struct of_phandle_args *spec,
> > > return chan;
> > > }
> > >
> > > +static int bcm2835_dma_suspend_late(struct device *dev)
> > > +{
> > > + struct bcm2835_dmadev *od = dev_get_drvdata(dev);
> > > + struct bcm2835_chan *c, *next;
> > > +
> > > + list_for_each_entry_safe(c, next, &od->ddev.channels,
> > > + vc.chan.device_node) {
> > > + void __iomem *chan_base = c->chan_base;
> > > +
> > > + if (readl(chan_base + BCM2835_DMA_ADDR)) {
> > > + dev_warn(dev, "Suspend is prevented by chan %d\n",
> > > + c->ch);
> > > + return -EBUSY;
> > > + }
> > Can you help understand how this helps by logging... we are not adding
> > anything except checking this and resume is NOP as well!
> My intention of this patch is just to make sure, that no DMA transfer is
> in progress during late_suspend. So i followed the implementation of
> fsldma.c
>
> Additionally i added this warning mostly to know if this ever occurs.
> But i wasn't able to trigger.
Okay in the case I dont think it is a abd idea. But the patch
description should mention that add a warning while suspending if
channels are active or something like that.
Patch title and description should mention this..
>
> Should i drop the warning and make resume callback = NULL?
Yes that would be better as well, no point in having dummy code
--
~Vinod
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 1/9] Revert "usb: dwc2: Skip clock gating on Broadcom SoCs" Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 2/9] dmaengine: bcm2835-dma: add suspend/resume pm support Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-10-28 11:43 ` Ulf Hansson
2024-10-25 10:36 ` [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling Stefan Wahren
` (5 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
The type of mmc_ios.clock is unsigned int, so the cached value
should be of the same type.
Fixes: 660fc733bd74 ("mmc: bcm2835: Add new driver for the sdhost controller.")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/mmc/host/bcm2835.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 35d8fdea668b..3d3eda5a337c 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -150,7 +150,7 @@ struct bcm2835_host {
struct platform_device *pdev;
- int clock; /* Current clock speed */
+ unsigned int clock; /* Current clock speed */
unsigned int max_clk; /* Max possible freq */
struct work_struct dma_work;
struct delayed_work timeout_work; /* Timer for timeouts */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed
2024-10-25 10:36 ` [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed Stefan Wahren
@ 2024-10-28 11:43 ` Ulf Hansson
0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2024-10-28 11:43 UTC (permalink / raw)
To: Stefan Wahren
Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
On Fri, 25 Oct 2024 at 12:36, Stefan Wahren <wahrenst@gmx.net> wrote:
>
> The type of mmc_ios.clock is unsigned int, so the cached value
> should be of the same type.
>
> Fixes: 660fc733bd74 ("mmc: bcm2835: Add new driver for the sdhost controller.")
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Applied for next, thanks!
Kind regards
Uffe
> ---
> drivers/mmc/host/bcm2835.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
> index 35d8fdea668b..3d3eda5a337c 100644
> --- a/drivers/mmc/host/bcm2835.c
> +++ b/drivers/mmc/host/bcm2835.c
> @@ -150,7 +150,7 @@ struct bcm2835_host {
>
> struct platform_device *pdev;
>
> - int clock; /* Current clock speed */
> + unsigned int clock; /* Current clock speed */
> unsigned int max_clk; /* Max possible freq */
> struct work_struct dma_work;
> struct delayed_work timeout_work; /* Timer for timeouts */
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
` (2 preceding siblings ...)
2024-10-25 10:36 ` [PATCH V5 3/9] mmc: bcm2835: Fix type of current clock speed Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-10-28 11:43 ` Ulf Hansson
2024-10-25 10:36 ` [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support Stefan Wahren
` (4 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
The custom sdhost controller on BCM2835 is feed by the critical VPU clock.
In preparation for PM suspend/resume support, add a proper clock handling
to the driver like in the other clock consumers (e.g. I2C).
Move the clock handling behind mmc_of_parse(), because it could return
with -EPROBE_DEFER and we want to minimize potential clock operation during
boot phase.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/mmc/host/bcm2835.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 3d3eda5a337c..107666b7c1c8 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -148,6 +148,7 @@ struct bcm2835_host {
void __iomem *ioaddr;
u32 phys_addr;
+ struct clk *clk;
struct platform_device *pdev;
unsigned int clock; /* Current clock speed */
@@ -1345,7 +1346,6 @@ static int bcm2835_add_host(struct bcm2835_host *host)
static int bcm2835_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct clk *clk;
struct bcm2835_host *host;
struct mmc_host *mmc;
const __be32 *regaddr_p;
@@ -1393,15 +1393,6 @@ static int bcm2835_probe(struct platform_device *pdev)
/* Ignore errors to fall back to PIO mode */
}
-
- clk = devm_clk_get(dev, NULL);
- if (IS_ERR(clk)) {
- ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n");
- goto err;
- }
-
- host->max_clk = clk_get_rate(clk);
-
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
ret = host->irq;
@@ -1412,16 +1403,30 @@ static int bcm2835_probe(struct platform_device *pdev)
if (ret)
goto err;
- ret = bcm2835_add_host(host);
+ host->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(host->clk)) {
+ ret = dev_err_probe(dev, PTR_ERR(host->clk), "could not get clk\n");
+ goto err;
+ }
+
+ ret = clk_prepare_enable(host->clk);
if (ret)
goto err;
+ host->max_clk = clk_get_rate(host->clk);
+
+ ret = bcm2835_add_host(host);
+ if (ret)
+ goto err_clk;
+
platform_set_drvdata(pdev, host);
dev_dbg(dev, "%s -> OK\n", __func__);
return 0;
+err_clk:
+ clk_disable_unprepare(host->clk);
err:
dev_dbg(dev, "%s -> err %d\n", __func__, ret);
if (host->dma_chan_rxtx)
@@ -1445,6 +1450,8 @@ static void bcm2835_remove(struct platform_device *pdev)
cancel_work_sync(&host->dma_work);
cancel_delayed_work_sync(&host->timeout_work);
+ clk_disable_unprepare(host->clk);
+
if (host->dma_chan_rxtx)
dma_release_channel(host->dma_chan_rxtx);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling
2024-10-25 10:36 ` [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling Stefan Wahren
@ 2024-10-28 11:43 ` Ulf Hansson
0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2024-10-28 11:43 UTC (permalink / raw)
To: Stefan Wahren
Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
On Fri, 25 Oct 2024 at 12:36, Stefan Wahren <wahrenst@gmx.net> wrote:
>
> The custom sdhost controller on BCM2835 is feed by the critical VPU clock.
> In preparation for PM suspend/resume support, add a proper clock handling
> to the driver like in the other clock consumers (e.g. I2C).
>
> Move the clock handling behind mmc_of_parse(), because it could return
> with -EPROBE_DEFER and we want to minimize potential clock operation during
> boot phase.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Applied for next, thanks!
Kind regards
Uffe
> ---
> drivers/mmc/host/bcm2835.c | 29 ++++++++++++++++++-----------
> 1 file changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
> index 3d3eda5a337c..107666b7c1c8 100644
> --- a/drivers/mmc/host/bcm2835.c
> +++ b/drivers/mmc/host/bcm2835.c
> @@ -148,6 +148,7 @@ struct bcm2835_host {
> void __iomem *ioaddr;
> u32 phys_addr;
>
> + struct clk *clk;
> struct platform_device *pdev;
>
> unsigned int clock; /* Current clock speed */
> @@ -1345,7 +1346,6 @@ static int bcm2835_add_host(struct bcm2835_host *host)
> static int bcm2835_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> - struct clk *clk;
> struct bcm2835_host *host;
> struct mmc_host *mmc;
> const __be32 *regaddr_p;
> @@ -1393,15 +1393,6 @@ static int bcm2835_probe(struct platform_device *pdev)
> /* Ignore errors to fall back to PIO mode */
> }
>
> -
> - clk = devm_clk_get(dev, NULL);
> - if (IS_ERR(clk)) {
> - ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n");
> - goto err;
> - }
> -
> - host->max_clk = clk_get_rate(clk);
> -
> host->irq = platform_get_irq(pdev, 0);
> if (host->irq < 0) {
> ret = host->irq;
> @@ -1412,16 +1403,30 @@ static int bcm2835_probe(struct platform_device *pdev)
> if (ret)
> goto err;
>
> - ret = bcm2835_add_host(host);
> + host->clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(host->clk)) {
> + ret = dev_err_probe(dev, PTR_ERR(host->clk), "could not get clk\n");
> + goto err;
> + }
> +
> + ret = clk_prepare_enable(host->clk);
> if (ret)
> goto err;
>
> + host->max_clk = clk_get_rate(host->clk);
> +
> + ret = bcm2835_add_host(host);
> + if (ret)
> + goto err_clk;
> +
> platform_set_drvdata(pdev, host);
>
> dev_dbg(dev, "%s -> OK\n", __func__);
>
> return 0;
>
> +err_clk:
> + clk_disable_unprepare(host->clk);
> err:
> dev_dbg(dev, "%s -> err %d\n", __func__, ret);
> if (host->dma_chan_rxtx)
> @@ -1445,6 +1450,8 @@ static void bcm2835_remove(struct platform_device *pdev)
> cancel_work_sync(&host->dma_work);
> cancel_delayed_work_sync(&host->timeout_work);
>
> + clk_disable_unprepare(host->clk);
> +
> if (host->dma_chan_rxtx)
> dma_release_channel(host->dma_chan_rxtx);
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
` (3 preceding siblings ...)
2024-10-25 10:36 ` [PATCH V5 4/9] mmc: bcm2835: Introduce proper clock handling Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-10-28 10:56 ` Ulf Hansson
2024-10-25 10:36 ` [PATCH V5 6/9] usb: dwc2: gadget: Introduce register restore flags Stefan Wahren
` (3 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
Add a minimalistic suspend/resume PM support.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/mmc/host/bcm2835.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 107666b7c1c8..17c327b7b5cc 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -1343,6 +1343,30 @@ static int bcm2835_add_host(struct bcm2835_host *host)
return 0;
}
+static int bcm2835_suspend(struct device *dev)
+{
+ struct bcm2835_host *host = dev_get_drvdata(dev);
+
+ if (!host->data_complete) {
+ dev_warn(dev, "Suspend is prevented\n");
+ return -EBUSY;
+ }
+
+ clk_disable_unprepare(host->clk);
+
+ return 0;
+}
+
+static int bcm2835_resume(struct device *dev)
+{
+ struct bcm2835_host *host = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(host->clk);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(bcm2835_pm_ops, bcm2835_suspend,
+ bcm2835_resume);
+
static int bcm2835_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1471,6 +1495,7 @@ static struct platform_driver bcm2835_driver = {
.name = "sdhost-bcm2835",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = bcm2835_match,
+ .pm = pm_ptr(&bcm2835_pm_ops),
},
};
module_platform_driver(bcm2835_driver);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support
2024-10-25 10:36 ` [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support Stefan Wahren
@ 2024-10-28 10:56 ` Ulf Hansson
0 siblings, 0 replies; 18+ messages in thread
From: Ulf Hansson @ 2024-10-28 10:56 UTC (permalink / raw)
To: Stefan Wahren
Cc: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Minas Harutyunyan, Greg Kroah-Hartman, Lukas Wunner,
Peter Robinson, Ivan T . Ivanov, linux-arm-kernel, kernel-list,
bcm-kernel-feedback-list, dmaengine, linux-mmc, linux-usb
On Fri, 25 Oct 2024 at 12:36, Stefan Wahren <wahrenst@gmx.net> wrote:
>
> Add a minimalistic suspend/resume PM support.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> ---
> drivers/mmc/host/bcm2835.c | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
> index 107666b7c1c8..17c327b7b5cc 100644
> --- a/drivers/mmc/host/bcm2835.c
> +++ b/drivers/mmc/host/bcm2835.c
> @@ -1343,6 +1343,30 @@ static int bcm2835_add_host(struct bcm2835_host *host)
> return 0;
> }
>
> +static int bcm2835_suspend(struct device *dev)
> +{
> + struct bcm2835_host *host = dev_get_drvdata(dev);
> +
> + if (!host->data_complete) {
> + dev_warn(dev, "Suspend is prevented\n");
> + return -EBUSY;
> + }
This should not be needed.
The mmc core makes sure all outstanding requests have been flushed,
before the host controller becomes suspended.
> +
> + clk_disable_unprepare(host->clk);
> +
> + return 0;
> +}
> +
> +static int bcm2835_resume(struct device *dev)
> +{
> + struct bcm2835_host *host = dev_get_drvdata(dev);
> +
> + return clk_prepare_enable(host->clk);
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(bcm2835_pm_ops, bcm2835_suspend,
> + bcm2835_resume);
> +
> static int bcm2835_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -1471,6 +1495,7 @@ static struct platform_driver bcm2835_driver = {
> .name = "sdhost-bcm2835",
> .probe_type = PROBE_PREFER_ASYNCHRONOUS,
> .of_match_table = bcm2835_match,
> + .pm = pm_ptr(&bcm2835_pm_ops),
> },
> };
> module_platform_driver(bcm2835_driver);
Kind regards
Uffe
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V5 6/9] usb: dwc2: gadget: Introduce register restore flags
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
` (4 preceding siblings ...)
2024-10-25 10:36 ` [PATCH V5 5/9] mmc: bcm2835: add suspend/resume pm support Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 7/9] usb: dwc2: Refactor backup/restore of registers Stefan Wahren
` (2 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
dwc2_restore_device_registers() use a single boolean
to decide about the register restoring behavior.
So replace this with a flags parameter, which can
be extended later.
No functional change intended.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/usb/dwc2/core.h | 6 ++++--
drivers/usb/dwc2/gadget.c | 12 +++++++-----
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 2bd74f3033ed..48f4b639ca2f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1127,6 +1127,8 @@ struct dwc2_hsotg {
#define DWC2_FS_IOT_ID 0x55310000
#define DWC2_HS_IOT_ID 0x55320000
+#define DWC2_RESTORE_DCTL BIT(0)
+
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
union dwc2_hcd_internal_flags {
u32 d32;
@@ -1420,7 +1422,7 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
#define dwc2_is_device_connected(hsotg) (hsotg->connected)
#define dwc2_is_device_enabled(hsotg) (hsotg->enabled)
int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup);
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags);
int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg);
int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
int rem_wakeup, int reset);
@@ -1459,7 +1461,7 @@ static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg,
- int remote_wakeup)
+ unsigned int flags)
{ return 0; }
static inline int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
{ return 0; }
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index e7bf9cc635be..96d703f4c509 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5203,11 +5203,11 @@ int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
* if controller power were disabled.
*
* @hsotg: Programming view of the DWC_otg controller
- * @remote_wakeup: Indicates whether resume is initiated by Device or Host.
+ * @flags: Defines which registers should be restored.
*
* Return: 0 if successful, negative error code otherwise
*/
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags)
{
struct dwc2_dregs_backup *dr;
int i;
@@ -5223,7 +5223,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
}
dr->valid = false;
- if (!remote_wakeup)
+ if (flags & DWC2_RESTORE_DCTL)
dwc2_writel(hsotg, dr->dctl, DCTL);
dwc2_writel(hsotg, dr->daintmsk, DAINTMSK);
@@ -5414,6 +5414,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
u32 gpwrdn;
u32 dctl;
int ret = 0;
+ unsigned int flags = 0;
struct dwc2_gregs_backup *gr;
struct dwc2_dregs_backup *dr;
@@ -5476,6 +5477,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
dctl = dwc2_readl(hsotg, DCTL);
dctl |= DCTL_PWRONPRGDONE;
dwc2_writel(hsotg, dctl, DCTL);
+ flags |= DWC2_RESTORE_DCTL;
}
/* Wait for interrupts which must be cleared */
mdelay(2);
@@ -5491,7 +5493,7 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
}
/* Restore device registers */
- ret = dwc2_restore_device_registers(hsotg, rem_wakeup);
+ ret = dwc2_restore_device_registers(hsotg, flags);
if (ret) {
dev_err(hsotg->dev, "%s: failed to restore device registers\n",
__func__);
@@ -5619,7 +5621,7 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
/* Restore DCFG */
dwc2_writel(hsotg, dr->dcfg, DCFG);
- ret = dwc2_restore_device_registers(hsotg, 0);
+ ret = dwc2_restore_device_registers(hsotg, DWC2_RESTORE_DCTL);
if (ret) {
dev_err(hsotg->dev, "%s: failed to restore device registers\n",
__func__);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH V5 7/9] usb: dwc2: Refactor backup/restore of registers
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
` (5 preceding siblings ...)
2024-10-25 10:36 ` [PATCH V5 6/9] usb: dwc2: gadget: Introduce register restore flags Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 8/9] usb: dwc2: Implement recovery after PM domain off Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 9/9] ARM: bcm2835_defconfig: Enable SUSPEND Stefan Wahren
8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
The DWC2 runtime PM code reuses similar patterns to backup and
restore the registers. So consolidate them in USB mode specific
variants. This also has the advantage it is reusable for further
PM improvements.
Special care is taken for DCFG register during device mode restore.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
drivers/usb/dwc2/core.h | 15 ++++++
drivers/usb/dwc2/gadget.c | 108 +++++++++++++++++++-------------------
drivers/usb/dwc2/hcd.c | 99 +++++++++++++++++-----------------
3 files changed, 121 insertions(+), 101 deletions(-)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 48f4b639ca2f..265791fbe87f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1128,6 +1128,7 @@ struct dwc2_hsotg {
#define DWC2_HS_IOT_ID 0x55320000
#define DWC2_RESTORE_DCTL BIT(0)
+#define DWC2_RESTORE_DCFG BIT(1)
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
union dwc2_hcd_internal_flags {
@@ -1437,6 +1438,9 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg);
+int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg);
+int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg,
+ unsigned int flags);
static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg)
{ hsotg->fifo_map = 0; }
#else
@@ -1484,6 +1488,11 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {}
+static inline int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg,
+ unsigned int flags)
+{ return 0; }
static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg) {}
#endif
@@ -1507,6 +1516,8 @@ int dwc2_host_exit_partial_power_down(struct dwc2_hsotg *hsotg,
void dwc2_host_enter_clock_gating(struct dwc2_hsotg *hsotg);
void dwc2_host_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup);
bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2);
+int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg);
+int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg);
static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg)
{ schedule_work(&hsotg->phy_reset_work); }
#else
@@ -1546,6 +1557,10 @@ static inline void dwc2_host_exit_clock_gating(struct dwc2_hsotg *hsotg,
int rem_wakeup) {}
static inline bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2)
{ return false; }
+static inline int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg) {}
#endif
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 96d703f4c509..2e071a0342f8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5223,6 +5223,9 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, unsigned int flags)
}
dr->valid = false;
+ if (flags & DWC2_RESTORE_DCFG)
+ dwc2_writel(hsotg, dr->dcfg, DCFG);
+
if (flags & DWC2_RESTORE_DCTL)
dwc2_writel(hsotg, dr->dctl, DCTL);
@@ -5309,6 +5312,49 @@ void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "GREFCLK=0x%08x\n", dwc2_readl(hsotg, GREFCLK));
}
+int dwc2_gadget_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{
+ int ret;
+
+ /* Backup all registers */
+ ret = dwc2_backup_global_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to backup global registers\n",
+ __func__);
+ return ret;
+ }
+
+ ret = dwc2_backup_device_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to backup device registers\n",
+ __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+int dwc2_gadget_restore_critical_registers(struct dwc2_hsotg *hsotg,
+ unsigned int flags)
+{
+ int ret;
+
+ ret = dwc2_restore_global_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to restore registers\n",
+ __func__);
+ return ret;
+ }
+ ret = dwc2_restore_device_registers(hsotg, flags);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to restore device registers\n",
+ __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* dwc2_gadget_enter_hibernation() - Put controller in Hibernation.
*
@@ -5326,18 +5372,9 @@ int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
/* Change to L2(suspend) state */
hsotg->lx_state = DWC2_L2;
dev_dbg(hsotg->dev, "Start of hibernation completed\n");
- ret = dwc2_backup_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup global registers\n",
- __func__);
- return ret;
- }
- ret = dwc2_backup_device_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup device registers\n",
- __func__);
+ ret = dwc2_gadget_backup_critical_registers(hsotg);
+ if (ret)
return ret;
- }
gpwrdn = GPWRDN_PWRDNRSTN;
udelay(10);
@@ -5485,20 +5522,9 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
dwc2_writel(hsotg, 0xffffffff, GINTSTS);
/* Restore global registers */
- ret = dwc2_restore_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore registers\n",
- __func__);
- return ret;
- }
-
- /* Restore device registers */
- ret = dwc2_restore_device_registers(hsotg, flags);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore device registers\n",
- __func__);
+ ret = dwc2_gadget_restore_critical_registers(hsotg, flags);
+ if (ret)
return ret;
- }
if (rem_wakeup) {
mdelay(10);
@@ -5532,19 +5558,9 @@ int dwc2_gadget_enter_partial_power_down(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "Entering device partial power down started.\n");
/* Backup all registers */
- ret = dwc2_backup_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup global registers\n",
- __func__);
- return ret;
- }
-
- ret = dwc2_backup_device_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup device registers\n",
- __func__);
+ ret = dwc2_gadget_backup_critical_registers(hsotg);
+ if (ret)
return ret;
- }
/*
* Clear any pending interrupts since dwc2 will not be able to
@@ -5591,11 +5607,8 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
{
u32 pcgcctl;
u32 dctl;
- struct dwc2_dregs_backup *dr;
int ret = 0;
- dr = &hsotg->dr_backup;
-
dev_dbg(hsotg->dev, "Exiting device partial Power Down started.\n");
pcgcctl = dwc2_readl(hsotg, PCGCTL);
@@ -5612,21 +5625,10 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
udelay(100);
if (restore) {
- ret = dwc2_restore_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore registers\n",
- __func__);
- return ret;
- }
- /* Restore DCFG */
- dwc2_writel(hsotg, dr->dcfg, DCFG);
-
- ret = dwc2_restore_device_registers(hsotg, DWC2_RESTORE_DCTL);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore device registers\n",
- __func__);
+ ret = dwc2_gadget_restore_critical_registers(hsotg, DWC2_RESTORE_DCTL |
+ DWC2_RESTORE_DCFG);
+ if (ret)
return ret;
- }
}
/* Set the Power-On Programming done bit */
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index cb54390e7de4..32fa606e5d59 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5477,6 +5477,49 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
return 0;
}
+int dwc2_host_backup_critical_registers(struct dwc2_hsotg *hsotg)
+{
+ int ret;
+
+ /* Backup all registers */
+ ret = dwc2_backup_global_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to backup global registers\n",
+ __func__);
+ return ret;
+ }
+
+ ret = dwc2_backup_host_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to backup host registers\n",
+ __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+int dwc2_host_restore_critical_registers(struct dwc2_hsotg *hsotg)
+{
+ int ret;
+
+ ret = dwc2_restore_global_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to restore registers\n",
+ __func__);
+ return ret;
+ }
+
+ ret = dwc2_restore_host_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to restore host registers\n",
+ __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* dwc2_host_enter_hibernation() - Put controller in Hibernation.
*
@@ -5492,18 +5535,9 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
u32 gpwrdn;
dev_dbg(hsotg->dev, "Preparing host for hibernation\n");
- ret = dwc2_backup_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup global registers\n",
- __func__);
- return ret;
- }
- ret = dwc2_backup_host_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup host registers\n",
- __func__);
+ ret = dwc2_host_backup_critical_registers(hsotg);
+ if (ret)
return ret;
- }
/* Enter USB Suspend Mode */
hprt0 = dwc2_readl(hsotg, HPRT0);
@@ -5697,20 +5731,9 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
dwc2_writel(hsotg, 0xffffffff, GINTSTS);
/* Restore global registers */
- ret = dwc2_restore_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore registers\n",
- __func__);
+ ret = dwc2_host_restore_critical_registers(hsotg);
+ if (ret)
return ret;
- }
-
- /* Restore host registers */
- ret = dwc2_restore_host_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore host registers\n",
- __func__);
- return ret;
- }
if (rem_wakeup) {
dwc2_hcd_rem_wakeup(hsotg);
@@ -5777,19 +5800,9 @@ int dwc2_host_enter_partial_power_down(struct dwc2_hsotg *hsotg)
dev_warn(hsotg->dev, "Suspend wasn't generated\n");
/* Backup all registers */
- ret = dwc2_backup_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup global registers\n",
- __func__);
- return ret;
- }
-
- ret = dwc2_backup_host_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to backup host registers\n",
- __func__);
+ ret = dwc2_host_backup_critical_registers(hsotg);
+ if (ret)
return ret;
- }
/*
* Clear any pending interrupts since dwc2 will not be able to
@@ -5858,19 +5871,9 @@ int dwc2_host_exit_partial_power_down(struct dwc2_hsotg *hsotg,
udelay(100);
if (restore) {
- ret = dwc2_restore_global_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore registers\n",
- __func__);
- return ret;
- }
-
- ret = dwc2_restore_host_registers(hsotg);
- if (ret) {
- dev_err(hsotg->dev, "%s: failed to restore host registers\n",
- __func__);
+ ret = dwc2_host_restore_critical_registers(hsotg);
+ if (ret)
return ret;
- }
}
/* Drive resume signaling and exit suspend mode on the port. */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH V5 8/9] usb: dwc2: Implement recovery after PM domain off
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
` (6 preceding siblings ...)
2024-10-25 10:36 ` [PATCH V5 7/9] usb: dwc2: Refactor backup/restore of registers Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
2024-10-25 10:36 ` [PATCH V5 9/9] ARM: bcm2835_defconfig: Enable SUSPEND Stefan Wahren
8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren, Douglas Anderson
According to the dt-bindings there are some platforms, which have a
dedicated USB power domain for DWC2 IP core supply. If the power domain
is switched off during system suspend then all USB register will lose
their settings.
Use GUSBCFG_TOUTCAL as a canary to detect that the power domain has
been powered off during suspend. Since the GOTGCTL_CURMODE_HOST doesn't
match on all platform with the current mode, additionally backup
GINTSTS. This works reliable to decide which registers should be
restored.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
drivers/usb/dwc2/core.c | 1 +
drivers/usb/dwc2/core.h | 2 ++
drivers/usb/dwc2/platform.c | 38 +++++++++++++++++++++++++++++++++++++
3 files changed, 41 insertions(+)
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 9919ab725d54..c3d24312db0f 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -43,6 +43,7 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
/* Backup global regs */
gr = &hsotg->gr_backup;
+ gr->gintsts = dwc2_readl(hsotg, GINTSTS);
gr->gotgctl = dwc2_readl(hsotg, GOTGCTL);
gr->gintmsk = dwc2_readl(hsotg, GINTMSK);
gr->gahbcfg = dwc2_readl(hsotg, GAHBCFG);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 265791fbe87f..34127b890b2a 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -667,6 +667,7 @@ struct dwc2_hw_params {
/**
* struct dwc2_gregs_backup - Holds global registers state before
* entering partial power down
+ * @gintsts: Backup of GINTSTS register
* @gotgctl: Backup of GOTGCTL register
* @gintmsk: Backup of GINTMSK register
* @gahbcfg: Backup of GAHBCFG register
@@ -683,6 +684,7 @@ struct dwc2_hw_params {
* @valid: True if registers values backuped.
*/
struct dwc2_gregs_backup {
+ u32 gintsts;
u32 gotgctl;
u32 gintmsk;
u32 gahbcfg;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index c1b7209b9483..4a3c81cd45d6 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -685,6 +685,14 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
regulator_disable(dwc2->usb33d);
}
+ if (is_device_mode)
+ ret = dwc2_gadget_backup_critical_registers(dwc2);
+ else
+ ret = dwc2_host_backup_critical_registers(dwc2);
+
+ if (ret)
+ return ret;
+
if (dwc2->ll_hw_enabled &&
(is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) {
ret = __dwc2_lowlevel_hw_disable(dwc2);
@@ -694,6 +702,24 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
return ret;
}
+static int dwc2_restore_critical_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_gregs_backup *gr;
+
+ gr = &hsotg->gr_backup;
+
+ if (!gr->valid) {
+ dev_err(hsotg->dev, "No valid register backup, failed to restore\n");
+ return -EINVAL;
+ }
+
+ if (gr->gintsts & GINTSTS_CURMODE_HOST)
+ return dwc2_host_restore_critical_registers(hsotg);
+
+ return dwc2_gadget_restore_critical_registers(hsotg, DWC2_RESTORE_DCTL |
+ DWC2_RESTORE_DCFG);
+}
+
static int __maybe_unused dwc2_resume(struct device *dev)
{
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
@@ -706,6 +732,18 @@ static int __maybe_unused dwc2_resume(struct device *dev)
}
dwc2->phy_off_for_suspend = false;
+ /*
+ * During suspend it's possible that the power domain for the
+ * DWC2 controller is disabled and all register values get lost.
+ * In case the GUSBCFG register is not initialized, it's clear the
+ * registers must be restored.
+ */
+ if (!(dwc2_readl(dwc2, GUSBCFG) & GUSBCFG_TOUTCAL_MASK)) {
+ ret = dwc2_restore_critical_registers(dwc2);
+ if (ret)
+ return ret;
+ }
+
if (dwc2->params.activate_stm_id_vb_detection) {
unsigned long flags;
u32 ggpio, gotgctl;
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH V5 9/9] ARM: bcm2835_defconfig: Enable SUSPEND
2024-10-25 10:36 [PATCH V5 0/9] ARM: bcm2835: Implement initial S2Idle for Raspberry Pi Stefan Wahren
` (7 preceding siblings ...)
2024-10-25 10:36 ` [PATCH V5 8/9] usb: dwc2: Implement recovery after PM domain off Stefan Wahren
@ 2024-10-25 10:36 ` Stefan Wahren
8 siblings, 0 replies; 18+ messages in thread
From: Stefan Wahren @ 2024-10-25 10:36 UTC (permalink / raw)
To: Russell King, Florian Fainelli, Ray Jui, Scott Branden,
Vinod Koul, Ulf Hansson, Minas Harutyunyan, Greg Kroah-Hartman
Cc: Lukas Wunner, Peter Robinson, Ivan T . Ivanov, linux-arm-kernel,
kernel-list, bcm-kernel-feedback-list, dmaengine, linux-mmc,
linux-usb, Stefan Wahren
Since the Raspberry Pi supports Suspend-To-Idle now, this option
should be enabled. This should make power management testing easier.
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
---
arch/arm/configs/bcm2835_defconfig | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index b5f0bd8dd536..97632dee1ab3 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -38,8 +38,6 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
CONFIG_VFP=y
-# CONFIG_SUSPEND is not set
-CONFIG_PM=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread