diff mbox series

[v3,3/8] drm/imagination: Use pwrseq for TH1520 GPU power management

Message ID 20250530-apr_14_for_sending-v3-3-83d5744d997c@samsung.com
State New
Headers show
Series Add TH1520 GPU support with power sequencing | expand

Commit Message

Michal Wilczynski May 29, 2025, 10:23 p.m. UTC
Update the Imagination PVR DRM driver to leverage the pwrseq framework
for managing the power sequence of the GPU on the T-HEAD TH1520 SoC.

In pvr_device_init(), the driver now attempts to get a handle to the
"gpu-power" sequencer target using devm_pwrseq_get(). If successful,
the responsibility for powering on and off the GPU's core clocks and
resets is delegated to the power sequencer. Consequently, the GPU
driver conditionally skips acquiring the GPU reset line if the pwrseq
handle is obtained, as the sequencer's match function will acquire it.
Clock handles are still acquired by the GPU driver for other purposes
like devfreq.

The runtime PM callbacks, pvr_power_device_resume() and
pvr_power_device_suspend(), are modified to call pwrseq_power_on() and
pwrseq_power_off() respectively when the sequencer is present.  If no
sequencer is found, the driver falls back to its existing manual clock
and reset management. A helper function,
pvr_power_off_sequence_manual(), is introduced to encapsulate the manual
power-down logic.

Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
 drivers/gpu/drm/imagination/Kconfig      |  1 +
 drivers/gpu/drm/imagination/pvr_device.c | 33 +++++++++++--
 drivers/gpu/drm/imagination/pvr_device.h |  6 +++
 drivers/gpu/drm/imagination/pvr_power.c  | 82 +++++++++++++++++++++-----------
 4 files changed, 89 insertions(+), 33 deletions(-)

Comments

Michal Wilczynski June 4, 2025, 11:53 a.m. UTC | #1
On 6/4/25 08:36, Krzysztof Kozlowski wrote:
> On 03/06/2025 21:43, Michal Wilczynski wrote:
>>>> +	 * and resets. Otherwise, we fall back to managing them ourselves.
>>>> +	 */
>>>> +	pvr_dev->pwrseq = devm_pwrseq_get(dev, "gpu-power");
>>>> +	if (IS_ERR(pvr_dev->pwrseq)) {
>>>> +		int pwrseq_err = PTR_ERR(pvr_dev->pwrseq);
>>>> +
>>>> +		/*
>>>> +		 * If the error is -EPROBE_DEFER, it's because the
>>>> +		 * optional sequencer provider is not present
>>>> +		 * and it's safe to fall back on manual power-up.
>>>
>>> It is safe but why it is desirable? The rule is rather to defer the
>>> probe, assuming this is probe path.
>>
>> Yeah this is probe path.
>>
>> The GPU node will depend on the AON node, which will be the sole
>> provider for the 'gpu-power' sequencer (based on the discussion in patch
>> 1).
>>
>> Therefore, if the AON/pwrseq driver has already completed its probe, and
>> devm_pwrseq_get() in the GPU driver subsequently returns -EPROBE_DEFER
>> (because pwrseq_get found 'no match' on the bus for 'gpu-power'), the
>> interpretation is that the AON driver did not register this optional
>> sequencer. Since AON is the only anticipated source, it implies the
>> sequencer won't become available later from its designated provider.
> 
> I don't understand why you made this assumption. AON could be a module
> and this driver built-in. AON will likely probe later.

You're absolutely right that AON could be a module and would generally
probe later in that scenario. However, the GPU device also has a
'power-domains = <&aon TH1520_GPU_PD>' dependency. If the AON driver (as
the PM domain provider) were a late probing module, the GPU driver's
probe would hit -EPROBE_DEFER when its power domain is requested
which happens before attempting to get other resources like a power
sequencer.

So, if the GPU driver's code does reach the devm_pwrseq_get(dev,
"gpu-power") call, it strongly implies the AON driver has already
successfully probed.

This leads to the core challenge with the optional 'gpu-power'
sequencer: Even if the AON driver has already probed, if it then chooses
not to register the "gpu-power" sequence (because it's an optional
feature), pwrseq_get() will still find "no device matched" on the
pwrseq_bus and return EPROBE_DEFER.

If the GPU driver defers here, as it normally should for -EPROBE_DEFER,
it could wait indefinitely for an optional sequence that its
already probed AON provider will not supply.

Anyway I think you're right, that this is probably confusing and we
shouldn't rely on this behavior.

To solve this, and to allow the GPU driver to correctly handle
-EPROBE_DEFER when a sequencer is genuinely expected, I propose using a
boolean property on the GPU's DT node, e.g.
img,gpu-expects-power-sequencer. If the GPU node provides this property
it means the pwrseq 'gpu-power' is required.

I didn't want to use this approach at first, as it seemed to me like the
pwrseq API had a hands-off approach for the DT with its matching logic,
but it seems unavoidable at this point.

> 
> 
> 
> Best regards,
> Krzysztof
> 

Best regards,
Michal Wilczynski June 5, 2025, 7:47 a.m. UTC | #2
On 6/4/25 14:07, Krzysztof Kozlowski wrote:
> On 04/06/2025 13:53, Michal Wilczynski wrote:
>>>>
>>>> The GPU node will depend on the AON node, which will be the sole
>>>> provider for the 'gpu-power' sequencer (based on the discussion in patch
>>>> 1).
>>>>
>>>> Therefore, if the AON/pwrseq driver has already completed its probe, and
>>>> devm_pwrseq_get() in the GPU driver subsequently returns -EPROBE_DEFER
>>>> (because pwrseq_get found 'no match' on the bus for 'gpu-power'), the
>>>> interpretation is that the AON driver did not register this optional
>>>> sequencer. Since AON is the only anticipated source, it implies the
>>>> sequencer won't become available later from its designated provider.
>>>
>>> I don't understand why you made this assumption. AON could be a module
>>> and this driver built-in. AON will likely probe later.
>>
>> You're absolutely right that AON could be a module and would generally
>> probe later in that scenario. However, the GPU device also has a
>> 'power-domains = <&aon TH1520_GPU_PD>' dependency. If the AON driver (as
>> the PM domain provider) were a late probing module, the GPU driver's
>> probe would hit -EPROBE_DEFER when its power domain is requested
>> which happens before attempting to get other resources like a power
>> sequencer.
> 
> Huh, so basically you imply certain hardware design and certain DTS
> description in your driver code. Well, that's clearly fragile design to
> me, because you should not rely how hardware properties are presented in
> DTS. Will work here on th1520 with this DTS, won't work with something else.
> 
> Especially that this looks like generic Imagination GPU code, common to
> multiple devices, not TH1520 only specific.
> 
>>
>> So, if the GPU driver's code does reach the devm_pwrseq_get(dev,
>> "gpu-power") call, it strongly implies the AON driver has already
>> successfully probed.
>>
>> This leads to the core challenge with the optional 'gpu-power'
>> sequencer: Even if the AON driver has already probed, if it then chooses
>> not to register the "gpu-power" sequence (because it's an optional
>> feature), pwrseq_get() will still find "no device matched" on the
>> pwrseq_bus and return EPROBE_DEFER.
>>
>> If the GPU driver defers here, as it normally should for -EPROBE_DEFER,
>> it could wait indefinitely for an optional sequence that its
>> already probed AON provider will not supply.
>>
>> Anyway I think you're right, that this is probably confusing and we
>> shouldn't rely on this behavior.
>>
>> To solve this, and to allow the GPU driver to correctly handle
>> -EPROBE_DEFER when a sequencer is genuinely expected, I propose using a
>> boolean property on the GPU's DT node, e.g.
>> img,gpu-expects-power-sequencer. If the GPU node provides this property
>> it means the pwrseq 'gpu-power' is required.
> 
> No, that would be driver design in DTS.
> 
> I think the main problem is the pwrseq API: you should get via phandle,
> not name of the pwrseq controller. That's how all producer-consumer
> relationships are done in OF platforms.

Bart,
Given Krzysztof's valid concerns about the current name based
lookup in pwrseq_get() and the benefits of phandle based resource
linking in OF platforms: Would you be open to a proposal for extending
the pwrseq API to allow consumers to obtain a sequencer (or a specific
target sequence) via a phandle defined in their Device Tree node? For
instance, a consumer device could specify power-sequencer =
<&aon> and a new API variant could resolve this.

> 
> It's also fragile to rely on names in case of systems with multiple
> similar devices. This does not affect your platform and this hardware in
> general, but shows issues with interface: imagine multiple gpus and
> multiple pwr sequence devices. Which one should be obtained?
> gpu-power-1? But if GPUs are the same class of devices (e.g. 2x TG1520
> GPU) this is just imprecise.
> 
> 
> Best regards,
> Krzysztof
> 

Best regards,
Bartosz Golaszewski June 5, 2025, 8:10 a.m. UTC | #3
On Thu, Jun 5, 2025 at 9:47 AM Michal Wilczynski
<m.wilczynski@samsung.com> wrote:
>
>
>
> On 6/4/25 14:07, Krzysztof Kozlowski wrote:
> > On 04/06/2025 13:53, Michal Wilczynski wrote:
> >>>>
> >>>> The GPU node will depend on the AON node, which will be the sole
> >>>> provider for the 'gpu-power' sequencer (based on the discussion in patch
> >>>> 1).
> >>>>
> >>>> Therefore, if the AON/pwrseq driver has already completed its probe, and
> >>>> devm_pwrseq_get() in the GPU driver subsequently returns -EPROBE_DEFER
> >>>> (because pwrseq_get found 'no match' on the bus for 'gpu-power'), the
> >>>> interpretation is that the AON driver did not register this optional
> >>>> sequencer. Since AON is the only anticipated source, it implies the
> >>>> sequencer won't become available later from its designated provider.
> >>>
> >>> I don't understand why you made this assumption. AON could be a module
> >>> and this driver built-in. AON will likely probe later.
> >>
> >> You're absolutely right that AON could be a module and would generally
> >> probe later in that scenario. However, the GPU device also has a
> >> 'power-domains = <&aon TH1520_GPU_PD>' dependency. If the AON driver (as
> >> the PM domain provider) were a late probing module, the GPU driver's
> >> probe would hit -EPROBE_DEFER when its power domain is requested
> >> which happens before attempting to get other resources like a power
> >> sequencer.
> >
> > Huh, so basically you imply certain hardware design and certain DTS
> > description in your driver code. Well, that's clearly fragile design to
> > me, because you should not rely how hardware properties are presented in
> > DTS. Will work here on th1520 with this DTS, won't work with something else.
> >
> > Especially that this looks like generic Imagination GPU code, common to
> > multiple devices, not TH1520 only specific.
> >
> >>
> >> So, if the GPU driver's code does reach the devm_pwrseq_get(dev,
> >> "gpu-power") call, it strongly implies the AON driver has already
> >> successfully probed.
> >>
> >> This leads to the core challenge with the optional 'gpu-power'
> >> sequencer: Even if the AON driver has already probed, if it then chooses
> >> not to register the "gpu-power" sequence (because it's an optional
> >> feature), pwrseq_get() will still find "no device matched" on the
> >> pwrseq_bus and return EPROBE_DEFER.
> >>
> >> If the GPU driver defers here, as it normally should for -EPROBE_DEFER,
> >> it could wait indefinitely for an optional sequence that its
> >> already probed AON provider will not supply.
> >>
> >> Anyway I think you're right, that this is probably confusing and we
> >> shouldn't rely on this behavior.
> >>
> >> To solve this, and to allow the GPU driver to correctly handle
> >> -EPROBE_DEFER when a sequencer is genuinely expected, I propose using a
> >> boolean property on the GPU's DT node, e.g.
> >> img,gpu-expects-power-sequencer. If the GPU node provides this property
> >> it means the pwrseq 'gpu-power' is required.
> >
> > No, that would be driver design in DTS.
> >
> > I think the main problem is the pwrseq API: you should get via phandle,
> > not name of the pwrseq controller. That's how all producer-consumer
> > relationships are done in OF platforms.
>
> Bart,
> Given Krzysztof's valid concerns about the current name based
> lookup in pwrseq_get() and the benefits of phandle based resource
> linking in OF platforms: Would you be open to a proposal for extending
> the pwrseq API to allow consumers to obtain a sequencer (or a specific
> target sequence) via a phandle defined in their Device Tree node? For
> instance, a consumer device could specify power-sequencer =
> <&aon> and a new API variant could resolve this.
>

I can be open to it all I want, but I bet Krzysztof won't be open to
introducing anything like a power-sequencer device property in DT
bindings. Simply because there's no such thing in the physical world.
The concept behind the power sequencing framework was to bind
providers to consumers based on existing links modelling real device
properties (which a "power-sequencer" is not). I commented on it under
another email saying that you already have a link here - the
power-domains property taking the aon phandle. In your pwrseq
provider's match() callback you can parse and resolve it back to the
aon node thus making sure you're matching the consumer with the
correct provider.

Please take a look at the existing wcn pwrseq driver which does a
similar thing but parses the regulator properties of the power
management unit (in the pwrseq_qcom_wcn_match() function).

We've tried to do something like what you're proposing for years and
it always got stuck on the fact that DT must not make up bogus
properties only to satisfy the driver implementation. We've done it in
the past, that's true, but just because we didn't know any better and
DT maintainers are currently much stricter as to what kind of
properties to allow.

Bartosz
Krzysztof Kozlowski June 5, 2025, 9:07 a.m. UTC | #4
On 05/06/2025 10:10, Bartosz Golaszewski wrote:
>>
>> Bart,
>> Given Krzysztof's valid concerns about the current name based
>> lookup in pwrseq_get() and the benefits of phandle based resource
>> linking in OF platforms: Would you be open to a proposal for extending
>> the pwrseq API to allow consumers to obtain a sequencer (or a specific
>> target sequence) via a phandle defined in their Device Tree node? For
>> instance, a consumer device could specify power-sequencer =
>> <&aon> and a new API variant could resolve this.
>>
> 
> I can be open to it all I want, but I bet Krzysztof won't be open to
> introducing anything like a power-sequencer device property in DT
> bindings. Simply because there's no such thing in the physical world.

Yep

> The concept behind the power sequencing framework was to bind
> providers to consumers based on existing links modelling real device
> properties (which a "power-sequencer" is not). I commented on it under
> another email saying that you already have a link here - the
> power-domains property taking the aon phandle. In your pwrseq

Exactly.


Best regards,
Krzysztof
Michal Wilczynski June 11, 2025, 12:01 p.m. UTC | #5
On 6/5/25 10:10, Bartosz Golaszewski wrote:
> On Thu, Jun 5, 2025 at 9:47 AM Michal Wilczynski
> <m.wilczynski@samsung.com> wrote:
>>
>>
>>
>> On 6/4/25 14:07, Krzysztof Kozlowski wrote:
>>> On 04/06/2025 13:53, Michal Wilczynski wrote:
>>>>>>
>>>>>> The GPU node will depend on the AON node, which will be the sole
>>>>>> provider for the 'gpu-power' sequencer (based on the discussion in patch
>>>>>> 1).
>>>>>>
>>>>>> Therefore, if the AON/pwrseq driver has already completed its probe, and
>>>>>> devm_pwrseq_get() in the GPU driver subsequently returns -EPROBE_DEFER
>>>>>> (because pwrseq_get found 'no match' on the bus for 'gpu-power'), the
>>>>>> interpretation is that the AON driver did not register this optional
>>>>>> sequencer. Since AON is the only anticipated source, it implies the
>>>>>> sequencer won't become available later from its designated provider.
>>>>>
>>>>> I don't understand why you made this assumption. AON could be a module
>>>>> and this driver built-in. AON will likely probe later.
>>>>
>>>> You're absolutely right that AON could be a module and would generally
>>>> probe later in that scenario. However, the GPU device also has a
>>>> 'power-domains = <&aon TH1520_GPU_PD>' dependency. If the AON driver (as
>>>> the PM domain provider) were a late probing module, the GPU driver's
>>>> probe would hit -EPROBE_DEFER when its power domain is requested
>>>> which happens before attempting to get other resources like a power
>>>> sequencer.
>>>
>>> Huh, so basically you imply certain hardware design and certain DTS
>>> description in your driver code. Well, that's clearly fragile design to
>>> me, because you should not rely how hardware properties are presented in
>>> DTS. Will work here on th1520 with this DTS, won't work with something else.
>>>
>>> Especially that this looks like generic Imagination GPU code, common to
>>> multiple devices, not TH1520 only specific.
>>>
>>>>
>>>> So, if the GPU driver's code does reach the devm_pwrseq_get(dev,
>>>> "gpu-power") call, it strongly implies the AON driver has already
>>>> successfully probed.
>>>>
>>>> This leads to the core challenge with the optional 'gpu-power'
>>>> sequencer: Even if the AON driver has already probed, if it then chooses
>>>> not to register the "gpu-power" sequence (because it's an optional
>>>> feature), pwrseq_get() will still find "no device matched" on the
>>>> pwrseq_bus and return EPROBE_DEFER.
>>>>
>>>> If the GPU driver defers here, as it normally should for -EPROBE_DEFER,
>>>> it could wait indefinitely for an optional sequence that its
>>>> already probed AON provider will not supply.
>>>>
>>>> Anyway I think you're right, that this is probably confusing and we
>>>> shouldn't rely on this behavior.
>>>>
>>>> To solve this, and to allow the GPU driver to correctly handle
>>>> -EPROBE_DEFER when a sequencer is genuinely expected, I propose using a
>>>> boolean property on the GPU's DT node, e.g.
>>>> img,gpu-expects-power-sequencer. If the GPU node provides this property
>>>> it means the pwrseq 'gpu-power' is required.
>>>
>>> No, that would be driver design in DTS.
>>>
>>> I think the main problem is the pwrseq API: you should get via phandle,
>>> not name of the pwrseq controller. That's how all producer-consumer
>>> relationships are done in OF platforms.
>>
>> Bart,
>> Given Krzysztof's valid concerns about the current name based
>> lookup in pwrseq_get() and the benefits of phandle based resource
>> linking in OF platforms: Would you be open to a proposal for extending
>> the pwrseq API to allow consumers to obtain a sequencer (or a specific
>> target sequence) via a phandle defined in their Device Tree node? For
>> instance, a consumer device could specify power-sequencer =
>> <&aon> and a new API variant could resolve this.
>>
> 
> I can be open to it all I want, but I bet Krzysztof won't be open to
> introducing anything like a power-sequencer device property in DT
> bindings. Simply because there's no such thing in the physical world.
> The concept behind the power sequencing framework was to bind
> providers to consumers based on existing links modelling real device
> properties (which a "power-sequencer" is not). I commented on it under
> another email saying that you already have a link here - the
> power-domains property taking the aon phandle. In your pwrseq
> provider's match() callback you can parse and resolve it back to the
> aon node thus making sure you're matching the consumer with the
> correct provider.
> 
> Please take a look at the existing wcn pwrseq driver which does a
> similar thing but parses the regulator properties of the power
> management unit (in the pwrseq_qcom_wcn_match() function).
> 
> We've tried to do something like what you're proposing for years and
> it always got stuck on the fact that DT must not make up bogus
> properties only to satisfy the driver implementation. We've done it in
> the past, that's true, but just because we didn't know any better and
> DT maintainers are currently much stricter as to what kind of
> properties to allow.

Hi Bartosz, Krzysztof, Matt

Thanks for the detailed explanation. I understand and agree with your
point about using existing device tree links. The pwrseq framework's
design makes perfect sense, and matching via the power-domains property
is the right way forward for the provider.

Just to clarify, my intention is to add the power-domains check to my
existing .match() function, which already validates the consumer's
compatible ("thead,th1520-gpu"). Combining these two checks will create
an even stronger, more specific match. I will proceed with this change.

However, this leads me back to a fundamental issue with the
consumer side implementation in the generic pvr_device.c driver. The
current fallback code is:

/*
 * If the error is -EPROBE_DEFER, it's because the
 * optional sequencer provider is not present
 * and it's safe to fall back on manual power-up.
 */
if (pwrseq_err == -EPROBE_DEFER)
        pvr_dev->pwrseq = NULL;

As Krzysztof noted, simply ignoring -EPROBE_DEFER is not ideal. But if I
change this to a standard deferred probe, the pvr_device.c driver will
break on all other supported SoCs. It would wait indefinitely for a
pwrseq-thead-gpu provider that will never appear on those platforms.

The core of the problem is that any solution within the provider's
.match() function cannot help here. On other SoCs, the
pwrseq-thead-gpu.c driver is not even compiled, so its .match() function
will never be executed. The generic consumer driver needs a way to know
whether it should even attempt to get a sequencer.

This brings me back to the idea of a DT property, and I'd like to frame
it from a different perspective. A property like needs-power-sequencer
(perhaps vendor-prefixed as thead,needs-power-sequencer) isn't meant to
describe driver behavior, but rather to describe a physical integration
requirement of the hardware.

For the TH1520, the SoC integrators made a design choice that mandates a
specific software driven power on sequence. On other supported SoCs, as
noted by the Imagination developers [1], this sequencing is handled by
the hardware itself. Describing this platform specific requirement this
hardware quirk in the DT seems to be the most accurate way to model the
physical reality.

What would be the recommended way to proceed? The generic consumer
driver needs a way to know if it should expect a sequencer for a
particular platform, and the DT seems like the most appropriate place to
describe this hardware specific need.

If a DT property remains unacceptable, the only other path I can see is
a minimal change to the core pwrseq API itself, perhaps by adding a
non deferring devm_pwrseq_try_get() function.

[1] - https://lore.kernel.org/all/fd46f443-b1f9-4f82-8d73-117cda093315@imgtec.com/

> 
> Bartosz
> 

Best regards,
Bartosz Golaszewski June 11, 2025, 12:32 p.m. UTC | #6
On Wed, Jun 11, 2025 at 2:01 PM Michal Wilczynski
<m.wilczynski@samsung.com> wrote:
>
>
>
> On 6/5/25 10:10, Bartosz Golaszewski wrote:
> > On Thu, Jun 5, 2025 at 9:47 AM Michal Wilczynski
> > <m.wilczynski@samsung.com> wrote:
> >>
> >>
> >>
> >> On 6/4/25 14:07, Krzysztof Kozlowski wrote:
> >>> On 04/06/2025 13:53, Michal Wilczynski wrote:
> >>>>>>
> >>>>>> The GPU node will depend on the AON node, which will be the sole
> >>>>>> provider for the 'gpu-power' sequencer (based on the discussion in patch
> >>>>>> 1).
> >>>>>>
> >>>>>> Therefore, if the AON/pwrseq driver has already completed its probe, and
> >>>>>> devm_pwrseq_get() in the GPU driver subsequently returns -EPROBE_DEFER
> >>>>>> (because pwrseq_get found 'no match' on the bus for 'gpu-power'), the
> >>>>>> interpretation is that the AON driver did not register this optional
> >>>>>> sequencer. Since AON is the only anticipated source, it implies the
> >>>>>> sequencer won't become available later from its designated provider.
> >>>>>
> >>>>> I don't understand why you made this assumption. AON could be a module
> >>>>> and this driver built-in. AON will likely probe later.
> >>>>
> >>>> You're absolutely right that AON could be a module and would generally
> >>>> probe later in that scenario. However, the GPU device also has a
> >>>> 'power-domains = <&aon TH1520_GPU_PD>' dependency. If the AON driver (as
> >>>> the PM domain provider) were a late probing module, the GPU driver's
> >>>> probe would hit -EPROBE_DEFER when its power domain is requested
> >>>> which happens before attempting to get other resources like a power
> >>>> sequencer.
> >>>
> >>> Huh, so basically you imply certain hardware design and certain DTS
> >>> description in your driver code. Well, that's clearly fragile design to
> >>> me, because you should not rely how hardware properties are presented in
> >>> DTS. Will work here on th1520 with this DTS, won't work with something else.
> >>>
> >>> Especially that this looks like generic Imagination GPU code, common to
> >>> multiple devices, not TH1520 only specific.
> >>>
> >>>>
> >>>> So, if the GPU driver's code does reach the devm_pwrseq_get(dev,
> >>>> "gpu-power") call, it strongly implies the AON driver has already
> >>>> successfully probed.
> >>>>
> >>>> This leads to the core challenge with the optional 'gpu-power'
> >>>> sequencer: Even if the AON driver has already probed, if it then chooses
> >>>> not to register the "gpu-power" sequence (because it's an optional
> >>>> feature), pwrseq_get() will still find "no device matched" on the
> >>>> pwrseq_bus and return EPROBE_DEFER.
> >>>>
> >>>> If the GPU driver defers here, as it normally should for -EPROBE_DEFER,
> >>>> it could wait indefinitely for an optional sequence that its
> >>>> already probed AON provider will not supply.
> >>>>
> >>>> Anyway I think you're right, that this is probably confusing and we
> >>>> shouldn't rely on this behavior.
> >>>>
> >>>> To solve this, and to allow the GPU driver to correctly handle
> >>>> -EPROBE_DEFER when a sequencer is genuinely expected, I propose using a
> >>>> boolean property on the GPU's DT node, e.g.
> >>>> img,gpu-expects-power-sequencer. If the GPU node provides this property
> >>>> it means the pwrseq 'gpu-power' is required.
> >>>
> >>> No, that would be driver design in DTS.
> >>>
> >>> I think the main problem is the pwrseq API: you should get via phandle,
> >>> not name of the pwrseq controller. That's how all producer-consumer
> >>> relationships are done in OF platforms.
> >>
> >> Bart,
> >> Given Krzysztof's valid concerns about the current name based
> >> lookup in pwrseq_get() and the benefits of phandle based resource
> >> linking in OF platforms: Would you be open to a proposal for extending
> >> the pwrseq API to allow consumers to obtain a sequencer (or a specific
> >> target sequence) via a phandle defined in their Device Tree node? For
> >> instance, a consumer device could specify power-sequencer =
> >> <&aon> and a new API variant could resolve this.
> >>
> >
> > I can be open to it all I want, but I bet Krzysztof won't be open to
> > introducing anything like a power-sequencer device property in DT
> > bindings. Simply because there's no such thing in the physical world.
> > The concept behind the power sequencing framework was to bind
> > providers to consumers based on existing links modelling real device
> > properties (which a "power-sequencer" is not). I commented on it under
> > another email saying that you already have a link here - the
> > power-domains property taking the aon phandle. In your pwrseq
> > provider's match() callback you can parse and resolve it back to the
> > aon node thus making sure you're matching the consumer with the
> > correct provider.
> >
> > Please take a look at the existing wcn pwrseq driver which does a
> > similar thing but parses the regulator properties of the power
> > management unit (in the pwrseq_qcom_wcn_match() function).
> >
> > We've tried to do something like what you're proposing for years and
> > it always got stuck on the fact that DT must not make up bogus
> > properties only to satisfy the driver implementation. We've done it in
> > the past, that's true, but just because we didn't know any better and
> > DT maintainers are currently much stricter as to what kind of
> > properties to allow.
>
> Hi Bartosz, Krzysztof, Matt
>
> Thanks for the detailed explanation. I understand and agree with your
> point about using existing device tree links. The pwrseq framework's
> design makes perfect sense, and matching via the power-domains property
> is the right way forward for the provider.
>
> Just to clarify, my intention is to add the power-domains check to my
> existing .match() function, which already validates the consumer's
> compatible ("thead,th1520-gpu"). Combining these two checks will create
> an even stronger, more specific match. I will proceed with this change.
>
> However, this leads me back to a fundamental issue with the
> consumer side implementation in the generic pvr_device.c driver. The
> current fallback code is:
>
> /*
>  * If the error is -EPROBE_DEFER, it's because the
>  * optional sequencer provider is not present
>  * and it's safe to fall back on manual power-up.
>  */
> if (pwrseq_err == -EPROBE_DEFER)
>         pvr_dev->pwrseq = NULL;
>
> As Krzysztof noted, simply ignoring -EPROBE_DEFER is not ideal. But if I
> change this to a standard deferred probe, the pvr_device.c driver will
> break on all other supported SoCs. It would wait indefinitely for a
> pwrseq-thead-gpu provider that will never appear on those platforms.
>
> The core of the problem is that any solution within the provider's
> .match() function cannot help here. On other SoCs, the
> pwrseq-thead-gpu.c driver is not even compiled, so its .match() function
> will never be executed. The generic consumer driver needs a way to know
> whether it should even attempt to get a sequencer.
>
> This brings me back to the idea of a DT property, and I'd like to frame
> it from a different perspective. A property like needs-power-sequencer
> (perhaps vendor-prefixed as thead,needs-power-sequencer) isn't meant to
> describe driver behavior, but rather to describe a physical integration
> requirement of the hardware.
>
> For the TH1520, the SoC integrators made a design choice that mandates a
> specific software driven power on sequence. On other supported SoCs, as
> noted by the Imagination developers [1], this sequencing is handled by
> the hardware itself. Describing this platform specific requirement this
> hardware quirk in the DT seems to be the most accurate way to model the
> physical reality.
>

Krzysztof, this sounds a bit like the qcom,controlled-remotely and
qcom,powered-remotely boolean properties we have for the BAM DMA nodes
on Qualcomm platforms, doesn't it? They too, tell the driver to not
enable certain resources as it's the TrustZone that will do it. Maybe
it is a valid use-case for something more generic? And if not, then
something like thead,hlos-controlled for this particular use-case.

Bartosz

> What would be the recommended way to proceed? The generic consumer
> driver needs a way to know if it should expect a sequencer for a
> particular platform, and the DT seems like the most appropriate place to
> describe this hardware specific need.
>
> If a DT property remains unacceptable, the only other path I can see is
> a minimal change to the core pwrseq API itself, perhaps by adding a
> non deferring devm_pwrseq_try_get() function.
>
> [1] - https://lore.kernel.org/all/fd46f443-b1f9-4f82-8d73-117cda093315@imgtec.com/
>
> >
> > Bartosz
> >
>
> Best regards,
> --
> Michal Wilczynski <m.wilczynski@samsung.com>
Krzysztof Kozlowski June 13, 2025, 6:44 a.m. UTC | #7
On 11/06/2025 14:01, Michal Wilczynski wrote:
> 
> However, this leads me back to a fundamental issue with the
> consumer side implementation in the generic pvr_device.c driver. The
> current fallback code is:
> 
> /*
>  * If the error is -EPROBE_DEFER, it's because the
>  * optional sequencer provider is not present
>  * and it's safe to fall back on manual power-up.
>  */
> if (pwrseq_err == -EPROBE_DEFER)
>         pvr_dev->pwrseq = NULL;
> 
> As Krzysztof noted, simply ignoring -EPROBE_DEFER is not ideal. But if I
> change this to a standard deferred probe, the pvr_device.c driver will

Why? You have specific compatible for executing such quirks only for
given platform.

> break on all other supported SoCs. It would wait indefinitely for a
> pwrseq-thead-gpu provider that will never appear on those platforms.
> 



Best regards,
Krzysztof
Krzysztof Kozlowski June 13, 2025, 6:47 a.m. UTC | #8
On 11/06/2025 14:32, Bartosz Golaszewski wrote:
> On Wed, Jun 11, 2025 at 2:01 PM Michal Wilczynski
> <m.wilczynski@samsung.com> wrote:
>>
>>
>>
>> On 6/5/25 10:10, Bartosz Golaszewski wrote:
>>> On Thu, Jun 5, 2025 at 9:47 AM Michal Wilczynski
>>> <m.wilczynski@samsung.com> wrote:
>>>>
>>>>
>>>>
>>>> On 6/4/25 14:07, Krzysztof Kozlowski wrote:
>>>>> On 04/06/2025 13:53, Michal Wilczynski wrote:
>>>>>>>>
>>>>>>>> The GPU node will depend on the AON node, which will be the sole
>>>>>>>> provider for the 'gpu-power' sequencer (based on the discussion in patch
>>>>>>>> 1).
>>>>>>>>
>>>>>>>> Therefore, if the AON/pwrseq driver has already completed its probe, and
>>>>>>>> devm_pwrseq_get() in the GPU driver subsequently returns -EPROBE_DEFER
>>>>>>>> (because pwrseq_get found 'no match' on the bus for 'gpu-power'), the
>>>>>>>> interpretation is that the AON driver did not register this optional
>>>>>>>> sequencer. Since AON is the only anticipated source, it implies the
>>>>>>>> sequencer won't become available later from its designated provider.
>>>>>>>
>>>>>>> I don't understand why you made this assumption. AON could be a module
>>>>>>> and this driver built-in. AON will likely probe later.
>>>>>>
>>>>>> You're absolutely right that AON could be a module and would generally
>>>>>> probe later in that scenario. However, the GPU device also has a
>>>>>> 'power-domains = <&aon TH1520_GPU_PD>' dependency. If the AON driver (as
>>>>>> the PM domain provider) were a late probing module, the GPU driver's
>>>>>> probe would hit -EPROBE_DEFER when its power domain is requested
>>>>>> which happens before attempting to get other resources like a power
>>>>>> sequencer.
>>>>>
>>>>> Huh, so basically you imply certain hardware design and certain DTS
>>>>> description in your driver code. Well, that's clearly fragile design to
>>>>> me, because you should not rely how hardware properties are presented in
>>>>> DTS. Will work here on th1520 with this DTS, won't work with something else.
>>>>>
>>>>> Especially that this looks like generic Imagination GPU code, common to
>>>>> multiple devices, not TH1520 only specific.
>>>>>
>>>>>>
>>>>>> So, if the GPU driver's code does reach the devm_pwrseq_get(dev,
>>>>>> "gpu-power") call, it strongly implies the AON driver has already
>>>>>> successfully probed.
>>>>>>
>>>>>> This leads to the core challenge with the optional 'gpu-power'
>>>>>> sequencer: Even if the AON driver has already probed, if it then chooses
>>>>>> not to register the "gpu-power" sequence (because it's an optional
>>>>>> feature), pwrseq_get() will still find "no device matched" on the
>>>>>> pwrseq_bus and return EPROBE_DEFER.
>>>>>>
>>>>>> If the GPU driver defers here, as it normally should for -EPROBE_DEFER,
>>>>>> it could wait indefinitely for an optional sequence that its
>>>>>> already probed AON provider will not supply.
>>>>>>
>>>>>> Anyway I think you're right, that this is probably confusing and we
>>>>>> shouldn't rely on this behavior.
>>>>>>
>>>>>> To solve this, and to allow the GPU driver to correctly handle
>>>>>> -EPROBE_DEFER when a sequencer is genuinely expected, I propose using a
>>>>>> boolean property on the GPU's DT node, e.g.
>>>>>> img,gpu-expects-power-sequencer. If the GPU node provides this property
>>>>>> it means the pwrseq 'gpu-power' is required.
>>>>>
>>>>> No, that would be driver design in DTS.
>>>>>
>>>>> I think the main problem is the pwrseq API: you should get via phandle,
>>>>> not name of the pwrseq controller. That's how all producer-consumer
>>>>> relationships are done in OF platforms.
>>>>
>>>> Bart,
>>>> Given Krzysztof's valid concerns about the current name based
>>>> lookup in pwrseq_get() and the benefits of phandle based resource
>>>> linking in OF platforms: Would you be open to a proposal for extending
>>>> the pwrseq API to allow consumers to obtain a sequencer (or a specific
>>>> target sequence) via a phandle defined in their Device Tree node? For
>>>> instance, a consumer device could specify power-sequencer =
>>>> <&aon> and a new API variant could resolve this.
>>>>
>>>
>>> I can be open to it all I want, but I bet Krzysztof won't be open to
>>> introducing anything like a power-sequencer device property in DT
>>> bindings. Simply because there's no such thing in the physical world.
>>> The concept behind the power sequencing framework was to bind
>>> providers to consumers based on existing links modelling real device
>>> properties (which a "power-sequencer" is not). I commented on it under
>>> another email saying that you already have a link here - the
>>> power-domains property taking the aon phandle. In your pwrseq
>>> provider's match() callback you can parse and resolve it back to the
>>> aon node thus making sure you're matching the consumer with the
>>> correct provider.
>>>
>>> Please take a look at the existing wcn pwrseq driver which does a
>>> similar thing but parses the regulator properties of the power
>>> management unit (in the pwrseq_qcom_wcn_match() function).
>>>
>>> We've tried to do something like what you're proposing for years and
>>> it always got stuck on the fact that DT must not make up bogus
>>> properties only to satisfy the driver implementation. We've done it in
>>> the past, that's true, but just because we didn't know any better and
>>> DT maintainers are currently much stricter as to what kind of
>>> properties to allow.
>>
>> Hi Bartosz, Krzysztof, Matt
>>
>> Thanks for the detailed explanation. I understand and agree with your
>> point about using existing device tree links. The pwrseq framework's
>> design makes perfect sense, and matching via the power-domains property
>> is the right way forward for the provider.
>>
>> Just to clarify, my intention is to add the power-domains check to my
>> existing .match() function, which already validates the consumer's
>> compatible ("thead,th1520-gpu"). Combining these two checks will create
>> an even stronger, more specific match. I will proceed with this change.
>>
>> However, this leads me back to a fundamental issue with the
>> consumer side implementation in the generic pvr_device.c driver. The
>> current fallback code is:
>>
>> /*
>>  * If the error is -EPROBE_DEFER, it's because the
>>  * optional sequencer provider is not present
>>  * and it's safe to fall back on manual power-up.
>>  */
>> if (pwrseq_err == -EPROBE_DEFER)
>>         pvr_dev->pwrseq = NULL;
>>
>> As Krzysztof noted, simply ignoring -EPROBE_DEFER is not ideal. But if I
>> change this to a standard deferred probe, the pvr_device.c driver will
>> break on all other supported SoCs. It would wait indefinitely for a
>> pwrseq-thead-gpu provider that will never appear on those platforms.
>>
>> The core of the problem is that any solution within the provider's
>> .match() function cannot help here. On other SoCs, the
>> pwrseq-thead-gpu.c driver is not even compiled, so its .match() function
>> will never be executed. The generic consumer driver needs a way to know
>> whether it should even attempt to get a sequencer.
>>
>> This brings me back to the idea of a DT property, and I'd like to frame
>> it from a different perspective. A property like needs-power-sequencer
>> (perhaps vendor-prefixed as thead,needs-power-sequencer) isn't meant to
>> describe driver behavior, but rather to describe a physical integration
>> requirement of the hardware.
>>
>> For the TH1520, the SoC integrators made a design choice that mandates a
>> specific software driven power on sequence. On other supported SoCs, as
>> noted by the Imagination developers [1], this sequencing is handled by
>> the hardware itself. Describing this platform specific requirement this
>> hardware quirk in the DT seems to be the most accurate way to model the
>> physical reality.
>>
> 
> Krzysztof, this sounds a bit like the qcom,controlled-remotely and
> qcom,powered-remotely boolean properties we have for the BAM DMA nodes
> on Qualcomm platforms, doesn't it? They too, tell the driver to not
> enable certain resources as it's the TrustZone that will do it. Maybe
> it is a valid use-case for something more generic? And if not, then
> something like thead,hlos-controlled for this particular use-case.

Depends what "SoC integrators" mean. Following sentence suggests it is
about this given SoC, so it looks 100% purely compatible-deducible. You
have here something different for this one given hardware. That
something different is defined by compatible.

That's why every hardware binding MUST have specific compatible. Also
that's one of the reasons why we really dislike generic compatibles like
one used here, but it is a separate thing.

Best regards,
Krzysztof
Michal Wilczynski June 13, 2025, 8:25 a.m. UTC | #9
On 6/13/25 08:44, Krzysztof Kozlowski wrote:
> On 11/06/2025 14:01, Michal Wilczynski wrote:
>>
>> However, this leads me back to a fundamental issue with the
>> consumer side implementation in the generic pvr_device.c driver. The
>> current fallback code is:
>>
>> /*
>>  * If the error is -EPROBE_DEFER, it's because the
>>  * optional sequencer provider is not present
>>  * and it's safe to fall back on manual power-up.
>>  */
>> if (pwrseq_err == -EPROBE_DEFER)
>>         pvr_dev->pwrseq = NULL;
>>
>> As Krzysztof noted, simply ignoring -EPROBE_DEFER is not ideal. But if I
>> change this to a standard deferred probe, the pvr_device.c driver will
> 
> Why? You have specific compatible for executing such quirks only for
> given platform.

This is due to how the pwrseq API works; it constructs a bus on which
provider devices may appear at any time. With the current API, there is
no way to express that a provider for a specific target will never
appear. ('gpu-power' is the generic target name, and of course, more
specific binding is handled in the provider's .match callback - based on
the compatible and the node phandle like discussed previously).

For all other supported SoCs, no such provider will ever appear on the
bus, and the current pwrseq API doesn't allow a generic consumer to know
this.

However, your suggestion of handling this with a platform specific
driver is a good path forward. It would still require a minimal addition
to the pwrseq API to work. For example, a new SoC specific driver for
"thead,th1520" could call a new function like
pwrseq_enable_optional_target("gpu-power") during its probe. This would
signal to the pwrseq core that this target is expected on the platform.
Therefore, when the Imagination driver later calls pwrseq_get() on a
TH1520, it would correctly result in either a match or a deferral.

On all other platforms, this optional target would not be enabled. The
pwrseq_get() call would then immediately return -ENODEV instead of
deferring, which solves the problem and allows the other supported SoCs
to probe correctly.

I wonder whether Bartosz would be okay with such an addition.

> 
>> break on all other supported SoCs. It would wait indefinitely for a
>> pwrseq-thead-gpu provider that will never appear on those platforms.
>>
> 
> 
> 
> Best regards,
> Krzysztof
> 

Best regards,
Michal Wilczynski June 13, 2025, 9:49 a.m. UTC | #10
On 6/13/25 10:25, Michal Wilczynski wrote:
> 
> 
> On 6/13/25 08:44, Krzysztof Kozlowski wrote:
>> On 11/06/2025 14:01, Michal Wilczynski wrote:
>>>
>>> However, this leads me back to a fundamental issue with the
>>> consumer side implementation in the generic pvr_device.c driver. The
>>> current fallback code is:
>>>
>>> /*
>>>  * If the error is -EPROBE_DEFER, it's because the
>>>  * optional sequencer provider is not present
>>>  * and it's safe to fall back on manual power-up.
>>>  */
>>> if (pwrseq_err == -EPROBE_DEFER)
>>>         pvr_dev->pwrseq = NULL;
>>>
>>> As Krzysztof noted, simply ignoring -EPROBE_DEFER is not ideal. But if I
>>> change this to a standard deferred probe, the pvr_device.c driver will
>>
>> Why? You have specific compatible for executing such quirks only for
>> given platform.

I realized now that you may have meant the "thead,th1520-gpu" compatible,
not the "thead,th1520" SoC compatible.

In any case, the whole reason for using the pwrseq framework is to avoid
polluting the generic driver with SoC specific logic and instead offload
that responsibility to a pwrseq provider. Therefore, I can't simply add
a check like if (compatible == "thead,th1520-gpu") to the generic driver
to decide whether to get a power sequencer. This entire matching
responsibility was intended to be offloaded to the pwrseq framework.

> 
> This is due to how the pwrseq API works; it constructs a bus on which
> provider devices may appear at any time. With the current API, there is
> no way to express that a provider for a specific target will never
> appear. ('gpu-power' is the generic target name, and of course, more
> specific binding is handled in the provider's .match callback - based on
> the compatible and the node phandle like discussed previously).
> 
> For all other supported SoCs, no such provider will ever appear on the
> bus, and the current pwrseq API doesn't allow a generic consumer to know
> this.
> 
> However, your suggestion of handling this with a platform specific
> driver is a good path forward. It would still require a minimal addition
> to the pwrseq API to work. For example, a new SoC specific driver for
> "thead,th1520" could call a new function like
> pwrseq_enable_optional_target("gpu-power") during its probe. This would
> signal to the pwrseq core that this target is expected on the platform.
> Therefore, when the Imagination driver later calls pwrseq_get() on a
> TH1520, it would correctly result in either a match or a deferral.
> 
> On all other platforms, this optional target would not be enabled. The
> pwrseq_get() call would then immediately return -ENODEV instead of
> deferring, which solves the problem and allows the other supported SoCs
> to probe correctly.
> 
> I wonder whether Bartosz would be okay with such an addition.
> 
>>
>>> break on all other supported SoCs. It would wait indefinitely for a
>>> pwrseq-thead-gpu provider that will never appear on those platforms.
>>>
>>
>>
>>
>> Best regards,
>> Krzysztof
>>
> 
> Best regards,

Best regards,
Krzysztof Kozlowski June 13, 2025, 10:01 a.m. UTC | #11
On 13/06/2025 11:49, Michal Wilczynski wrote:
> 
> 
> On 6/13/25 10:25, Michal Wilczynski wrote:
>>
>>
>> On 6/13/25 08:44, Krzysztof Kozlowski wrote:
>>> On 11/06/2025 14:01, Michal Wilczynski wrote:
>>>>
>>>> However, this leads me back to a fundamental issue with the
>>>> consumer side implementation in the generic pvr_device.c driver. The
>>>> current fallback code is:
>>>>
>>>> /*
>>>>  * If the error is -EPROBE_DEFER, it's because the
>>>>  * optional sequencer provider is not present
>>>>  * and it's safe to fall back on manual power-up.
>>>>  */
>>>> if (pwrseq_err == -EPROBE_DEFER)
>>>>         pvr_dev->pwrseq = NULL;
>>>>
>>>> As Krzysztof noted, simply ignoring -EPROBE_DEFER is not ideal. But if I
>>>> change this to a standard deferred probe, the pvr_device.c driver will
>>>
>>> Why? You have specific compatible for executing such quirks only for
>>> given platform.
> 
> I realized now that you may have meant the "thead,th1520-gpu" compatible,
> not the "thead,th1520" SoC compatible.
> 
> In any case, the whole reason for using the pwrseq framework is to avoid
> polluting the generic driver with SoC specific logic and instead offload
> that responsibility to a pwrseq provider. Therefore, I can't simply add
> a check like if (compatible == "thead,th1520-gpu") to the generic driver
> to decide whether to get a power sequencer. This entire matching
> responsibility was intended to be offloaded to the pwrseq framework.

No, just do how all drivers are doing - driver match data, describing
that there is some component, e.g. quirks/flags, number of clocks and
their names typically. In your case - name or presence of pwrseq.



Best regards,
Krzysztof
Bartosz Golaszewski June 13, 2025, 10:41 a.m. UTC | #12
On Fri, Jun 13, 2025 at 10:25 AM Michal Wilczynski
<m.wilczynski@samsung.com> wrote:
>
> > Why? You have specific compatible for executing such quirks only for
> > given platform.
>
> This is due to how the pwrseq API works; it constructs a bus on which
> provider devices may appear at any time. With the current API, there is
> no way to express that a provider for a specific target will never
> appear. ('gpu-power' is the generic target name, and of course, more
> specific binding is handled in the provider's .match callback - based on
> the compatible and the node phandle like discussed previously).
>

This is by design and also the reason why we don't expose a
pwrseq_get_optional(). If the driver calls pwrseq_get() at all then it
expects the provider to eventually appear or will fail to initialize.

That still doesn't answer the question: why can't you have a callback
in your match data which - for this mode only - would call
pwrseq_get()/power_on()/power_off()?

> For all other supported SoCs, no such provider will ever appear on the
> bus, and the current pwrseq API doesn't allow a generic consumer to know
> this.
>
> However, your suggestion of handling this with a platform specific
> driver is a good path forward. It would still require a minimal addition
> to the pwrseq API to work. For example, a new SoC specific driver for
> "thead,th1520" could call a new function like
> pwrseq_enable_optional_target("gpu-power") during its probe. This would
> signal to the pwrseq core that this target is expected on the platform.
> Therefore, when the Imagination driver later calls pwrseq_get() on a
> TH1520, it would correctly result in either a match or a deferral.
>

I don't want to use the word optional. I think what you're thinking of
is a kind of "deferred" get where you get a valid handle, use it and
then, the provider eventually arrives it will get attached and its
state aligned with the current state of all the existing handles. I'm
not against it, it sounds quite elegant but there's an issue of error
reporting in this case. We'd need a notifier of some kind so that
consumers could subscribe and be notified about errors happening
behind the scenes.

Bart
diff mbox series

Patch

diff --git a/drivers/gpu/drm/imagination/Kconfig b/drivers/gpu/drm/imagination/Kconfig
index 3bfa2ac212dccb73c53bdc2bc259bcba636e7cfc..737ace77c4f1247c687cc1fde2f139fc2e118c50 100644
--- a/drivers/gpu/drm/imagination/Kconfig
+++ b/drivers/gpu/drm/imagination/Kconfig
@@ -11,6 +11,7 @@  config DRM_POWERVR
 	select DRM_SCHED
 	select DRM_GPUVM
 	select FW_LOADER
+  select POWER_SEQUENCING
 	help
 	  Choose this option if you have a system that has an Imagination
 	  Technologies PowerVR (Series 6 or later) or IMG GPU.
diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index 8b9ba4983c4cb5bc40342fcafc4259078bc70547..19d48bbc828cf2b8dbead602e90ff88780152124 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -25,6 +25,7 @@ 
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/pwrseq/consumer.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
@@ -631,10 +632,34 @@  pvr_device_init(struct pvr_device *pvr_dev)
 	if (err)
 		return err;
 
-	/* Get the reset line for the GPU */
-	err = pvr_device_reset_init(pvr_dev);
-	if (err)
-		return err;
+	/*
+	 * Try to get a power sequencer. If successful, it will handle clocks
+	 * and resets. Otherwise, we fall back to managing them ourselves.
+	 */
+	pvr_dev->pwrseq = devm_pwrseq_get(dev, "gpu-power");
+	if (IS_ERR(pvr_dev->pwrseq)) {
+		int pwrseq_err = PTR_ERR(pvr_dev->pwrseq);
+
+		/*
+		 * If the error is -EPROBE_DEFER, it's because the
+		 * optional sequencer provider is not present
+		 * and it's safe to fall back on manual power-up.
+		 */
+		if (pwrseq_err == -EPROBE_DEFER)
+			pvr_dev->pwrseq = NULL;
+		else
+			return dev_err_probe(dev, pwrseq_err,
+					     "Failed to get power sequencer\n");
+	}
+
+	/* Get the reset line for the GPU, but since it's exclusive only
+	 * get it if the pwerseq is NULL.
+	 */
+	if (!pvr_dev->pwrseq) {
+		err = pvr_device_reset_init(pvr_dev);
+		if (err)
+			return err;
+	}
 
 	/* Explicitly power the GPU so we can access control registers before the FW is booted. */
 	err = pm_runtime_resume_and_get(dev);
diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 7cb01c38d2a9c3fc71effe789d4dfe54eddd93ee..0b6d53994d25abe32a2f1b133a4efa574e150da9 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -37,6 +37,9 @@  struct clk;
 /* Forward declaration from <linux/firmware.h>. */
 struct firmware;
 
+/* Forward declaration from <linux/pwrseq/consumer.h */
+struct pwrseq_desc;
+
 /**
  * struct pvr_gpu_id - Hardware GPU ID information for a PowerVR device
  * @b: Branch ID.
@@ -148,6 +151,9 @@  struct pvr_device {
 	 */
 	struct reset_control *reset;
 
+	/** @pwrseq: Pointer to a power sequencer, if one is used. */
+	struct pwrseq_desc *pwrseq;
+
 	/** @irq: IRQ number. */
 	int irq;
 
diff --git a/drivers/gpu/drm/imagination/pvr_power.c b/drivers/gpu/drm/imagination/pvr_power.c
index 41f5d89e78b854cf6993838868a4416a220b490a..b7dcc03d7d9e06f03f059124fbe21dd844de713e 100644
--- a/drivers/gpu/drm/imagination/pvr_power.c
+++ b/drivers/gpu/drm/imagination/pvr_power.c
@@ -21,6 +21,7 @@ 
 #include <linux/reset.h>
 #include <linux/timer.h>
 #include <linux/types.h>
+#include <linux/pwrseq/consumer.h>
 #include <linux/workqueue.h>
 
 #define POWER_SYNC_TIMEOUT_US (1000000) /* 1s */
@@ -234,6 +235,19 @@  pvr_watchdog_init(struct pvr_device *pvr_dev)
 	return 0;
 }
 
+static int pvr_power_off_sequence_manual(struct pvr_device *pvr_dev)
+{
+	int err;
+
+	err = reset_control_assert(pvr_dev->reset);
+
+	clk_disable_unprepare(pvr_dev->mem_clk);
+	clk_disable_unprepare(pvr_dev->sys_clk);
+	clk_disable_unprepare(pvr_dev->core_clk);
+
+	return err;
+}
+
 int
 pvr_power_device_suspend(struct device *dev)
 {
@@ -252,11 +266,10 @@  pvr_power_device_suspend(struct device *dev)
 			goto err_drm_dev_exit;
 	}
 
-	clk_disable_unprepare(pvr_dev->mem_clk);
-	clk_disable_unprepare(pvr_dev->sys_clk);
-	clk_disable_unprepare(pvr_dev->core_clk);
-
-	err = reset_control_assert(pvr_dev->reset);
+	if (pvr_dev->pwrseq)
+		err = pwrseq_power_off(pvr_dev->pwrseq);
+	else
+		err = pvr_power_off_sequence_manual(pvr_dev);
 
 err_drm_dev_exit:
 	drm_dev_exit(idx);
@@ -276,44 +289,55 @@  pvr_power_device_resume(struct device *dev)
 	if (!drm_dev_enter(drm_dev, &idx))
 		return -EIO;
 
-	err = clk_prepare_enable(pvr_dev->core_clk);
-	if (err)
-		goto err_drm_dev_exit;
+	if (pvr_dev->pwrseq) {
+		err = pwrseq_power_on(pvr_dev->pwrseq);
+		if (err)
+			goto err_drm_dev_exit;
+	} else {
+		err = clk_prepare_enable(pvr_dev->core_clk);
+		if (err)
+			goto err_drm_dev_exit;
 
-	err = clk_prepare_enable(pvr_dev->sys_clk);
-	if (err)
-		goto err_core_clk_disable;
+		err = clk_prepare_enable(pvr_dev->sys_clk);
+		if (err)
+			goto err_core_clk_disable;
 
-	err = clk_prepare_enable(pvr_dev->mem_clk);
-	if (err)
-		goto err_sys_clk_disable;
+		err = clk_prepare_enable(pvr_dev->mem_clk);
+		if (err)
+			goto err_sys_clk_disable;
 
-	/*
-	 * According to the hardware manual, a delay of at least 32 clock
-	 * cycles is required between de-asserting the clkgen reset and
-	 * de-asserting the GPU reset. Assuming a worst-case scenario with
-	 * a very high GPU clock frequency, a delay of 1 microsecond is
-	 * sufficient to ensure this requirement is met across all
-	 * feasible GPU clock speeds.
-	 */
-	udelay(1);
+		/*
+		 * According to the hardware manual, a delay of at least 32 clock
+		 * cycles is required between de-asserting the clkgen reset and
+		 * de-asserting the GPU reset. Assuming a worst-case scenario with
+		 * a very high GPU clock frequency, a delay of 1 microsecond is
+		 * sufficient to ensure this requirement is met across all
+		 * feasible GPU clock speeds.
+		 */
+		udelay(1);
 
-	err = reset_control_deassert(pvr_dev->reset);
-	if (err)
-		goto err_mem_clk_disable;
+		err = reset_control_deassert(pvr_dev->reset);
+		if (err)
+			goto err_mem_clk_disable;
+	}
 
 	if (pvr_dev->fw_dev.booted) {
 		err = pvr_power_fw_enable(pvr_dev);
 		if (err)
-			goto err_reset_assert;
+			goto err_power_off;
 	}
 
 	drm_dev_exit(idx);
 
 	return 0;
 
-err_reset_assert:
-	reset_control_assert(pvr_dev->reset);
+err_power_off:
+	if (pvr_dev->pwrseq)
+		pwrseq_power_off(pvr_dev->pwrseq);
+	else
+		pvr_power_off_sequence_manual(pvr_dev);
+
+	goto err_drm_dev_exit;
 
 err_mem_clk_disable:
 	clk_disable_unprepare(pvr_dev->mem_clk);