* [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 12:25 ` Gatien CHEVALLIER
2025-09-09 10:12 ` [PATCH v6 02/20] dt-bindings: stm32: stm32mp25: add `#access-controller-cells` property Clément Le Goffic
` (18 subsequent siblings)
19 siblings, 1 reply; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Other driver than rifsc and etzpc can implement firewall ops, such as
rcc.
In order for them to have access to the ops and type of this framework,
we need to get the `stm32_firewall.h` file in the include/ folder.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
drivers/bus/stm32_etzpc.c | 3 +--
drivers/bus/stm32_firewall.c | 3 +--
drivers/bus/stm32_rifsc.c | 3 +--
{drivers => include/linux}/bus/stm32_firewall.h | 0
4 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/bus/stm32_etzpc.c b/drivers/bus/stm32_etzpc.c
index 7fc0f16960be..4918a14e507e 100644
--- a/drivers/bus/stm32_etzpc.c
+++ b/drivers/bus/stm32_etzpc.c
@@ -5,6 +5,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/bus/stm32_firewall.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -16,8 +17,6 @@
#include <linux/platform_device.h>
#include <linux/types.h>
-#include "stm32_firewall.h"
-
/*
* ETZPC registers
*/
diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c
index 2fc9761dadec..ef4988054b44 100644
--- a/drivers/bus/stm32_firewall.c
+++ b/drivers/bus/stm32_firewall.c
@@ -5,6 +5,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/bus/stm32_firewall.h>
#include <linux/bus/stm32_firewall_device.h>
#include <linux/device.h>
#include <linux/err.h>
@@ -18,8 +19,6 @@
#include <linux/types.h>
#include <linux/slab.h>
-#include "stm32_firewall.h"
-
/* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
#define STM32_FIREWALL_MAX_ARGS (STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c
index 4cf1b60014b7..643ddd0a5f54 100644
--- a/drivers/bus/stm32_rifsc.c
+++ b/drivers/bus/stm32_rifsc.c
@@ -5,6 +5,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/bus/stm32_firewall.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -16,8 +17,6 @@
#include <linux/platform_device.h>
#include <linux/types.h>
-#include "stm32_firewall.h"
-
/*
* RIFSC offset register
*/
diff --git a/drivers/bus/stm32_firewall.h b/include/linux/bus/stm32_firewall.h
similarity index 100%
rename from drivers/bus/stm32_firewall.h
rename to include/linux/bus/stm32_firewall.h
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder
2025-09-09 10:12 ` [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder Clément Le Goffic
@ 2025-09-09 12:25 ` Gatien CHEVALLIER
2025-09-10 7:47 ` Clément Le Goffic
0 siblings, 1 reply; 36+ messages in thread
From: Gatien CHEVALLIER @ 2025-09-09 12:25 UTC (permalink / raw)
To: Clément Le Goffic, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic
On 9/9/25 12:12, Clément Le Goffic wrote:
> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> Other driver than rifsc and etzpc can implement firewall ops, such as
> rcc.
> In order for them to have access to the ops and type of this framework,
> we need to get the `stm32_firewall.h` file in the include/ folder.
>
> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
> ---
> drivers/bus/stm32_etzpc.c | 3 +--
> drivers/bus/stm32_firewall.c | 3 +--
> drivers/bus/stm32_rifsc.c | 3 +--
> {drivers => include/linux}/bus/stm32_firewall.h | 0
> 4 files changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/bus/stm32_etzpc.c b/drivers/bus/stm32_etzpc.c
> index 7fc0f16960be..4918a14e507e 100644
> --- a/drivers/bus/stm32_etzpc.c
> +++ b/drivers/bus/stm32_etzpc.c
> @@ -5,6 +5,7 @@
>
> #include <linux/bitfield.h>
> #include <linux/bits.h>
> +#include <linux/bus/stm32_firewall.h>
> #include <linux/device.h>
> #include <linux/err.h>
> #include <linux/init.h>
> @@ -16,8 +17,6 @@
> #include <linux/platform_device.h>
> #include <linux/types.h>
>
> -#include "stm32_firewall.h"
> -
> /*
> * ETZPC registers
> */
> diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c
> index 2fc9761dadec..ef4988054b44 100644
> --- a/drivers/bus/stm32_firewall.c
> +++ b/drivers/bus/stm32_firewall.c
> @@ -5,6 +5,7 @@
>
> #include <linux/bitfield.h>
> #include <linux/bits.h>
> +#include <linux/bus/stm32_firewall.h>
> #include <linux/bus/stm32_firewall_device.h>
> #include <linux/device.h>
> #include <linux/err.h>
> @@ -18,8 +19,6 @@
> #include <linux/types.h>
> #include <linux/slab.h>
>
> -#include "stm32_firewall.h"
> -
> /* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
> #define STM32_FIREWALL_MAX_ARGS (STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
>
> diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c
> index 4cf1b60014b7..643ddd0a5f54 100644
> --- a/drivers/bus/stm32_rifsc.c
> +++ b/drivers/bus/stm32_rifsc.c
> @@ -5,6 +5,7 @@
>
> #include <linux/bitfield.h>
> #include <linux/bits.h>
> +#include <linux/bus/stm32_firewall.h>
> #include <linux/device.h>
> #include <linux/err.h>
> #include <linux/init.h>
> @@ -16,8 +17,6 @@
> #include <linux/platform_device.h>
> #include <linux/types.h>
>
> -#include "stm32_firewall.h"
> -
> /*
> * RIFSC offset register
> */
> diff --git a/drivers/bus/stm32_firewall.h b/include/linux/bus/stm32_firewall.h
> similarity index 100%
> rename from drivers/bus/stm32_firewall.h
> rename to include/linux/bus/stm32_firewall.h
>
Hi Clément,
Thank you for keeping up the work on this series.
As the firewall header is moved to a dedicated firewall directory,
maybe it would be coherent to create the same kind of directory
for the sources as non-buses drivers use it. I can test it on my
side if you're willing to make the change.
Sorry for the late comment.
Cheers,
Gatien
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder
2025-09-09 12:25 ` Gatien CHEVALLIER
@ 2025-09-10 7:47 ` Clément Le Goffic
2025-09-10 8:42 ` Gatien CHEVALLIER
0 siblings, 1 reply; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-10 7:47 UTC (permalink / raw)
To: Gatien CHEVALLIER, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic
On 09/09/2025 14:25, Gatien CHEVALLIER wrote:
>
>
> On 9/9/25 12:12, Clément Le Goffic wrote:
>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>
>> Other driver than rifsc and etzpc can implement firewall ops, such as
>> rcc.
>> In order for them to have access to the ops and type of this framework,
>> we need to get the `stm32_firewall.h` file in the include/ folder.
>>
>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
>> ---
>> drivers/bus/stm32_etzpc.c | 3 +--
>> drivers/bus/stm32_firewall.c | 3 +--
>> drivers/bus/stm32_rifsc.c | 3 +--
>> {drivers => include/linux}/bus/stm32_firewall.h | 0
>> 4 files changed, 3 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/bus/stm32_etzpc.c b/drivers/bus/stm32_etzpc.c
>> index 7fc0f16960be..4918a14e507e 100644
>> --- a/drivers/bus/stm32_etzpc.c
>> +++ b/drivers/bus/stm32_etzpc.c
>> @@ -5,6 +5,7 @@
>> #include <linux/bitfield.h>
>> #include <linux/bits.h>
>> +#include <linux/bus/stm32_firewall.h>
>> #include <linux/device.h>
>> #include <linux/err.h>
>> #include <linux/init.h>
>> @@ -16,8 +17,6 @@
>> #include <linux/platform_device.h>
>> #include <linux/types.h>
>> -#include "stm32_firewall.h"
>> -
>> /*
>> * ETZPC registers
>> */
>> diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c
>> index 2fc9761dadec..ef4988054b44 100644
>> --- a/drivers/bus/stm32_firewall.c
>> +++ b/drivers/bus/stm32_firewall.c
>> @@ -5,6 +5,7 @@
>> #include <linux/bitfield.h>
>> #include <linux/bits.h>
>> +#include <linux/bus/stm32_firewall.h>
>> #include <linux/bus/stm32_firewall_device.h>
>> #include <linux/device.h>
>> #include <linux/err.h>
>> @@ -18,8 +19,6 @@
>> #include <linux/types.h>
>> #include <linux/slab.h>
>> -#include "stm32_firewall.h"
>> -
>> /* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
>> #define STM32_FIREWALL_MAX_ARGS
>> (STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
>> diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c
>> index 4cf1b60014b7..643ddd0a5f54 100644
>> --- a/drivers/bus/stm32_rifsc.c
>> +++ b/drivers/bus/stm32_rifsc.c
>> @@ -5,6 +5,7 @@
>> #include <linux/bitfield.h>
>> #include <linux/bits.h>
>> +#include <linux/bus/stm32_firewall.h>
>> #include <linux/device.h>
>> #include <linux/err.h>
>> #include <linux/init.h>
>> @@ -16,8 +17,6 @@
>> #include <linux/platform_device.h>
>> #include <linux/types.h>
>> -#include "stm32_firewall.h"
>> -
>> /*
>> * RIFSC offset register
>> */
>> diff --git a/drivers/bus/stm32_firewall.h b/include/linux/bus/
>> stm32_firewall.h
>> similarity index 100%
>> rename from drivers/bus/stm32_firewall.h
>> rename to include/linux/bus/stm32_firewall.h
>>
Hi Gatien
> As the firewall header is moved to a dedicated firewall directory,
I don't move it to a dedicated firewall directory just to the "bus"
directory where the "stm32_firewall_device.h" header file is already
located.
> maybe it would be coherent to create the same kind of directory
> for the sources as non-buses drivers use it. I can test it on my
> side if you're willing to make the change.
Do you mean create an include/linux/bus/firewall/ directory ?
Best regards,
Clément
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder
2025-09-10 7:47 ` Clément Le Goffic
@ 2025-09-10 8:42 ` Gatien CHEVALLIER
2025-09-10 9:43 ` Clément Le Goffic
0 siblings, 1 reply; 36+ messages in thread
From: Gatien CHEVALLIER @ 2025-09-10 8:42 UTC (permalink / raw)
To: Clément Le Goffic, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic
On 9/10/25 09:47, Clément Le Goffic wrote:
> On 09/09/2025 14:25, Gatien CHEVALLIER wrote:
>>
>>
>> On 9/9/25 12:12, Clément Le Goffic wrote:
>>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>>
>>> Other driver than rifsc and etzpc can implement firewall ops, such as
>>> rcc.
>>> In order for them to have access to the ops and type of this framework,
>>> we need to get the `stm32_firewall.h` file in the include/ folder.
>>>
>>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
>>> ---
>>> drivers/bus/stm32_etzpc.c | 3 +--
>>> drivers/bus/stm32_firewall.c | 3 +--
>>> drivers/bus/stm32_rifsc.c | 3 +--
>>> {drivers => include/linux}/bus/stm32_firewall.h | 0
>>> 4 files changed, 3 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/bus/stm32_etzpc.c b/drivers/bus/stm32_etzpc.c
>>> index 7fc0f16960be..4918a14e507e 100644
>>> --- a/drivers/bus/stm32_etzpc.c
>>> +++ b/drivers/bus/stm32_etzpc.c
>>> @@ -5,6 +5,7 @@
>>> #include <linux/bitfield.h>
>>> #include <linux/bits.h>
>>> +#include <linux/bus/stm32_firewall.h>
>>> #include <linux/device.h>
>>> #include <linux/err.h>
>>> #include <linux/init.h>
>>> @@ -16,8 +17,6 @@
>>> #include <linux/platform_device.h>
>>> #include <linux/types.h>
>>> -#include "stm32_firewall.h"
>>> -
>>> /*
>>> * ETZPC registers
>>> */
>>> diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/stm32_firewall.c
>>> index 2fc9761dadec..ef4988054b44 100644
>>> --- a/drivers/bus/stm32_firewall.c
>>> +++ b/drivers/bus/stm32_firewall.c
>>> @@ -5,6 +5,7 @@
>>> #include <linux/bitfield.h>
>>> #include <linux/bits.h>
>>> +#include <linux/bus/stm32_firewall.h>
>>> #include <linux/bus/stm32_firewall_device.h>
>>> #include <linux/device.h>
>>> #include <linux/err.h>
>>> @@ -18,8 +19,6 @@
>>> #include <linux/types.h>
>>> #include <linux/slab.h>
>>> -#include "stm32_firewall.h"
>>> -
>>> /* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
>>> #define STM32_FIREWALL_MAX_ARGS (STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
>>> diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c
>>> index 4cf1b60014b7..643ddd0a5f54 100644
>>> --- a/drivers/bus/stm32_rifsc.c
>>> +++ b/drivers/bus/stm32_rifsc.c
>>> @@ -5,6 +5,7 @@
>>> #include <linux/bitfield.h>
>>> #include <linux/bits.h>
>>> +#include <linux/bus/stm32_firewall.h>
>>> #include <linux/device.h>
>>> #include <linux/err.h>
>>> #include <linux/init.h>
>>> @@ -16,8 +17,6 @@
>>> #include <linux/platform_device.h>
>>> #include <linux/types.h>
>>> -#include "stm32_firewall.h"
>>> -
>>> /*
>>> * RIFSC offset register
>>> */
>>> diff --git a/drivers/bus/stm32_firewall.h b/include/linux/bus/
>>> stm32_firewall.h
>>> similarity index 100%
>>> rename from drivers/bus/stm32_firewall.h
>>> rename to include/linux/bus/stm32_firewall.h
>>>
>
> Hi Gatien
>
>> As the firewall header is moved to a dedicated firewall directory,
>
> I don't move it to a dedicated firewall directory just to the "bus"
> directory where the "stm32_firewall_device.h" header file is already
> located.
>
Yes, my bad, I mixed my words there.
>> maybe it would be coherent to create the same kind of directory
>> for the sources as non-buses drivers use it. I can test it on my
>> side if you're willing to make the change.
>
> Do you mean create an include/linux/bus/firewall/ directory ?
>
Rather include/linux/firewall/(stm32/). and a drivers/firewall/(stm32/)
directory for the firewall files would be great. If that's not too much
of a burden.
Cheers,
Gatien
> Best regards,
> Clément
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder
2025-09-10 8:42 ` Gatien CHEVALLIER
@ 2025-09-10 9:43 ` Clément Le Goffic
2025-09-10 9:52 ` Gatien CHEVALLIER
0 siblings, 1 reply; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-10 9:43 UTC (permalink / raw)
To: Gatien CHEVALLIER, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic
On 10/09/2025 10:42, Gatien CHEVALLIER wrote:
>
>
> On 9/10/25 09:47, Clément Le Goffic wrote:
>> On 09/09/2025 14:25, Gatien CHEVALLIER wrote:
>>>
>>>
>>> On 9/9/25 12:12, Clément Le Goffic wrote:
>>>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>>>
>>>> Other driver than rifsc and etzpc can implement firewall ops, such as
>>>> rcc.
>>>> In order for them to have access to the ops and type of this framework,
>>>> we need to get the `stm32_firewall.h` file in the include/ folder.
>>>>
>>>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>>>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
>>>> ---
>>>> drivers/bus/stm32_etzpc.c | 3 +--
>>>> drivers/bus/stm32_firewall.c | 3 +--
>>>> drivers/bus/stm32_rifsc.c | 3 +--
>>>> {drivers => include/linux}/bus/stm32_firewall.h | 0
>>>> 4 files changed, 3 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/bus/stm32_etzpc.c b/drivers/bus/stm32_etzpc.c
>>>> index 7fc0f16960be..4918a14e507e 100644
>>>> --- a/drivers/bus/stm32_etzpc.c
>>>> +++ b/drivers/bus/stm32_etzpc.c
>>>> @@ -5,6 +5,7 @@
>>>> #include <linux/bitfield.h>
>>>> #include <linux/bits.h>
>>>> +#include <linux/bus/stm32_firewall.h>
>>>> #include <linux/device.h>
>>>> #include <linux/err.h>
>>>> #include <linux/init.h>
>>>> @@ -16,8 +17,6 @@
>>>> #include <linux/platform_device.h>
>>>> #include <linux/types.h>
>>>> -#include "stm32_firewall.h"
>>>> -
>>>> /*
>>>> * ETZPC registers
>>>> */
>>>> diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/
>>>> stm32_firewall.c
>>>> index 2fc9761dadec..ef4988054b44 100644
>>>> --- a/drivers/bus/stm32_firewall.c
>>>> +++ b/drivers/bus/stm32_firewall.c
>>>> @@ -5,6 +5,7 @@
>>>> #include <linux/bitfield.h>
>>>> #include <linux/bits.h>
>>>> +#include <linux/bus/stm32_firewall.h>
>>>> #include <linux/bus/stm32_firewall_device.h>
>>>> #include <linux/device.h>
>>>> #include <linux/err.h>
>>>> @@ -18,8 +19,6 @@
>>>> #include <linux/types.h>
>>>> #include <linux/slab.h>
>>>> -#include "stm32_firewall.h"
>>>> -
>>>> /* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
>>>> #define STM32_FIREWALL_MAX_ARGS (STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
>>>> diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c
>>>> index 4cf1b60014b7..643ddd0a5f54 100644
>>>> --- a/drivers/bus/stm32_rifsc.c
>>>> +++ b/drivers/bus/stm32_rifsc.c
>>>> @@ -5,6 +5,7 @@
>>>> #include <linux/bitfield.h>
>>>> #include <linux/bits.h>
>>>> +#include <linux/bus/stm32_firewall.h>
>>>> #include <linux/device.h>
>>>> #include <linux/err.h>
>>>> #include <linux/init.h>
>>>> @@ -16,8 +17,6 @@
>>>> #include <linux/platform_device.h>
>>>> #include <linux/types.h>
>>>> -#include "stm32_firewall.h"
>>>> -
>>>> /*
>>>> * RIFSC offset register
>>>> */
>>>> diff --git a/drivers/bus/stm32_firewall.h b/include/linux/bus/
>>>> stm32_firewall.h
>>>> similarity index 100%
>>>> rename from drivers/bus/stm32_firewall.h
>>>> rename to include/linux/bus/stm32_firewall.h
>>>>
>>
>> Hi Gatien
>>
>>> As the firewall header is moved to a dedicated firewall directory,
>>
>> I don't move it to a dedicated firewall directory just to the "bus"
>> directory where the "stm32_firewall_device.h" header file is already
>> located.
>>
>
> Yes, my bad, I mixed my words there.
>
>>> maybe it would be coherent to create the same kind of directory
>>> for the sources as non-buses drivers use it. I can test it on my
>>> side if you're willing to make the change.
>>
>> Do you mean create an include/linux/bus/firewall/ directory ?
>>
>
> Rather include/linux/firewall/(stm32/). and a drivers/firewall/(stm32/)
> directory for the firewall files would be great. If that's not too much
> of a burden.
I thinks that's a bit too much for this one.
As you're the firewall maintainer I would need to modify your entry in
the MAINTAINER file (and I just see that your entry is lacking the
header file path).
For now I think it is not urgent neither mandatory.
Maybe in a next patch series ?
Even in the driver bus directory there is no vendor policy so adding a
path like drivers/bus/{stm32/|firewall/}stm32_firewall.c is a bit
overlapping as with the filename we already know it is ST and its firewall.
Let me know what you think !
BR,
Clément
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder
2025-09-10 9:43 ` Clément Le Goffic
@ 2025-09-10 9:52 ` Gatien CHEVALLIER
0 siblings, 0 replies; 36+ messages in thread
From: Gatien CHEVALLIER @ 2025-09-10 9:52 UTC (permalink / raw)
To: Clément Le Goffic, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic
On 9/10/25 11:43, Clément Le Goffic wrote:
> On 10/09/2025 10:42, Gatien CHEVALLIER wrote:
>>
>>
>> On 9/10/25 09:47, Clément Le Goffic wrote:
>>> On 09/09/2025 14:25, Gatien CHEVALLIER wrote:
>>>>
>>>>
>>>> On 9/9/25 12:12, Clément Le Goffic wrote:
>>>>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>>>>
>>>>> Other driver than rifsc and etzpc can implement firewall ops, such as
>>>>> rcc.
>>>>> In order for them to have access to the ops and type of this
>>>>> framework,
>>>>> we need to get the `stm32_firewall.h` file in the include/ folder.
>>>>>
>>>>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>>>>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
>>>>> ---
>>>>> drivers/bus/stm32_etzpc.c | 3 +--
>>>>> drivers/bus/stm32_firewall.c | 3 +--
>>>>> drivers/bus/stm32_rifsc.c | 3 +--
>>>>> {drivers => include/linux}/bus/stm32_firewall.h | 0
>>>>> 4 files changed, 3 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/drivers/bus/stm32_etzpc.c b/drivers/bus/stm32_etzpc.c
>>>>> index 7fc0f16960be..4918a14e507e 100644
>>>>> --- a/drivers/bus/stm32_etzpc.c
>>>>> +++ b/drivers/bus/stm32_etzpc.c
>>>>> @@ -5,6 +5,7 @@
>>>>> #include <linux/bitfield.h>
>>>>> #include <linux/bits.h>
>>>>> +#include <linux/bus/stm32_firewall.h>
>>>>> #include <linux/device.h>
>>>>> #include <linux/err.h>
>>>>> #include <linux/init.h>
>>>>> @@ -16,8 +17,6 @@
>>>>> #include <linux/platform_device.h>
>>>>> #include <linux/types.h>
>>>>> -#include "stm32_firewall.h"
>>>>> -
>>>>> /*
>>>>> * ETZPC registers
>>>>> */
>>>>> diff --git a/drivers/bus/stm32_firewall.c b/drivers/bus/
>>>>> stm32_firewall.c
>>>>> index 2fc9761dadec..ef4988054b44 100644
>>>>> --- a/drivers/bus/stm32_firewall.c
>>>>> +++ b/drivers/bus/stm32_firewall.c
>>>>> @@ -5,6 +5,7 @@
>>>>> #include <linux/bitfield.h>
>>>>> #include <linux/bits.h>
>>>>> +#include <linux/bus/stm32_firewall.h>
>>>>> #include <linux/bus/stm32_firewall_device.h>
>>>>> #include <linux/device.h>
>>>>> #include <linux/err.h>
>>>>> @@ -18,8 +19,6 @@
>>>>> #include <linux/types.h>
>>>>> #include <linux/slab.h>
>>>>> -#include "stm32_firewall.h"
>>>>> -
>>>>> /* Corresponds to STM32_FIREWALL_MAX_EXTRA_ARGS + firewall ID */
>>>>> #define STM32_FIREWALL_MAX_ARGS (STM32_FIREWALL_MAX_EXTRA_ARGS + 1)
>>>>> diff --git a/drivers/bus/stm32_rifsc.c b/drivers/bus/stm32_rifsc.c
>>>>> index 4cf1b60014b7..643ddd0a5f54 100644
>>>>> --- a/drivers/bus/stm32_rifsc.c
>>>>> +++ b/drivers/bus/stm32_rifsc.c
>>>>> @@ -5,6 +5,7 @@
>>>>> #include <linux/bitfield.h>
>>>>> #include <linux/bits.h>
>>>>> +#include <linux/bus/stm32_firewall.h>
>>>>> #include <linux/device.h>
>>>>> #include <linux/err.h>
>>>>> #include <linux/init.h>
>>>>> @@ -16,8 +17,6 @@
>>>>> #include <linux/platform_device.h>
>>>>> #include <linux/types.h>
>>>>> -#include "stm32_firewall.h"
>>>>> -
>>>>> /*
>>>>> * RIFSC offset register
>>>>> */
>>>>> diff --git a/drivers/bus/stm32_firewall.h b/include/linux/bus/
>>>>> stm32_firewall.h
>>>>> similarity index 100%
>>>>> rename from drivers/bus/stm32_firewall.h
>>>>> rename to include/linux/bus/stm32_firewall.h
>>>>>
>>>
>>> Hi Gatien
>>>
>>>> As the firewall header is moved to a dedicated firewall directory,
>>>
>>> I don't move it to a dedicated firewall directory just to the "bus"
>>> directory where the "stm32_firewall_device.h" header file is already
>>> located.
>>>
>>
>> Yes, my bad, I mixed my words there.
>>
>>>> maybe it would be coherent to create the same kind of directory
>>>> for the sources as non-buses drivers use it. I can test it on my
>>>> side if you're willing to make the change.
>>>
>>> Do you mean create an include/linux/bus/firewall/ directory ?
>>>
>>
>> Rather include/linux/firewall/(stm32/). and a drivers/firewall/(stm32/)
>> directory for the firewall files would be great. If that's not too much
>> of a burden.
>
> I thinks that's a bit too much for this one.
> As you're the firewall maintainer I would need to modify your entry in
> the MAINTAINER file (and I just see that your entry is lacking the
> header file path).
> For now I think it is not urgent neither mandatory.
> Maybe in a next patch series ?
> Even in the driver bus directory there is no vendor policy so adding a
> path like drivers/bus/{stm32/|firewall/}stm32_firewall.c is a bit
> overlapping as with the filename we already know it is ST and its firewall.
> Let me know what you think !
>
> BR,
> Clément
>
Yes, let me handle this afterwards, I don't want to restrain this
patchset from being accepted.
There would be no /bus/ for the firewall files. and the RIFSC/ETZPC
drivers would stay where they are ATM.
Gatien
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v6 02/20] dt-bindings: stm32: stm32mp25: add `#access-controller-cells` property
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 03/20] clk: stm32mp25: add firewall grant_access ops Clément Le Goffic
` (17 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
RCC is able to check the availability of a clock.
Allow to query the RCC with a firewall ID.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml b/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml
index 88e52f10d1ec..4d471e3d89bc 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml
+++ b/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml
@@ -31,6 +31,11 @@ properties:
'#reset-cells':
const: 1
+ '#access-controller-cells':
+ const: 1
+ description:
+ Contains the firewall ID associated to the peripheral.
+
clocks:
items:
- description: CK_SCMI_HSE High Speed External oscillator (8 to 48 MHz)
@@ -123,6 +128,7 @@ required:
- reg
- '#clock-cells'
- '#reset-cells'
+ - '#access-controller-cells'
- clocks
additionalProperties: false
@@ -136,6 +142,7 @@ examples:
reg = <0x44200000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
+ #access-controller-cells = <1>;
clocks = <&scmi_clk CK_SCMI_HSE>,
<&scmi_clk CK_SCMI_HSI>,
<&scmi_clk CK_SCMI_MSI>,
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 03/20] clk: stm32mp25: add firewall grant_access ops
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 02/20] dt-bindings: stm32: stm32mp25: add `#access-controller-cells` property Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 04/20] arm64: dts: st: set rcc as an access-controller Clément Le Goffic
` (16 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
On STM32MP25, the RCC peripheral manages the secure level of resources
that are used by other devices such as clocks.
Declare this peripheral as a firewall controller.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
drivers/clk/stm32/clk-stm32mp25.c | 40 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/stm32/clk-stm32mp25.c b/drivers/clk/stm32/clk-stm32mp25.c
index 52f0e8a12926..af4bc06d703a 100644
--- a/drivers/clk/stm32/clk-stm32mp25.c
+++ b/drivers/clk/stm32/clk-stm32mp25.c
@@ -4,8 +4,10 @@
* Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
*/
+#include <linux/bus/stm32_firewall.h>
#include <linux/bus/stm32_firewall_device.h>
#include <linux/clk-provider.h>
+#include <linux/device.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -1602,6 +1604,11 @@ static int stm32_rcc_get_access(void __iomem *base, u32 index)
return 0;
}
+static int stm32mp25_rcc_grant_access(struct stm32_firewall_controller *ctrl, u32 firewall_id)
+{
+ return stm32_rcc_get_access(ctrl->mmio, firewall_id);
+}
+
static int stm32mp25_check_security(struct device_node *np, void __iomem *base,
const struct clock_config *cfg)
{
@@ -1970,6 +1977,7 @@ MODULE_DEVICE_TABLE(of, stm32mp25_match_data);
static int stm32mp25_rcc_clocks_probe(struct platform_device *pdev)
{
+ struct stm32_firewall_controller *rcc_controller;
struct device *dev = &pdev->dev;
void __iomem *base;
int ret;
@@ -1982,7 +1990,36 @@ static int stm32mp25_rcc_clocks_probe(struct platform_device *pdev)
if (ret)
return ret;
- return stm32_rcc_init(dev, stm32mp25_match_data, base);
+ ret = stm32_rcc_init(dev, stm32mp25_match_data, base);
+ if (ret)
+ return ret;
+
+ rcc_controller = devm_kzalloc(&pdev->dev, sizeof(*rcc_controller), GFP_KERNEL);
+ if (!rcc_controller)
+ return -ENOMEM;
+
+ rcc_controller->dev = dev;
+ rcc_controller->mmio = base;
+ rcc_controller->name = dev_driver_string(dev);
+ rcc_controller->type = STM32_PERIPHERAL_FIREWALL;
+ rcc_controller->grant_access = stm32mp25_rcc_grant_access;
+
+ platform_set_drvdata(pdev, rcc_controller);
+
+ ret = stm32_firewall_controller_register(rcc_controller);
+ if (ret) {
+ dev_err(dev, "Couldn't register as a firewall controller: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void stm32mp25_rcc_clocks_remove(struct platform_device *pdev)
+{
+ struct stm32_firewall_controller *rcc_controller = platform_get_drvdata(pdev);
+
+ stm32_firewall_controller_unregister(rcc_controller);
}
static struct platform_driver stm32mp25_rcc_clocks_driver = {
@@ -1991,6 +2028,7 @@ static struct platform_driver stm32mp25_rcc_clocks_driver = {
.of_match_table = stm32mp25_match_data,
},
.probe = stm32mp25_rcc_clocks_probe,
+ .remove = stm32mp25_rcc_clocks_remove,
};
static int __init stm32mp25_clocks_init(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 04/20] arm64: dts: st: set rcc as an access-controller
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (2 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 03/20] clk: stm32mp25: add firewall grant_access ops Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props Clément Le Goffic
` (15 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
RCC now implements firewall access ops to check the access to
resources. Allow client nodes to query the RCC with one firewall ID.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm64/boot/dts/st/stm32mp251.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index 303abf915b8e..fbedf23def52 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -1677,6 +1677,7 @@ rcc: clock-controller@44200000 {
reg = <0x44200000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
+ #access-controller-cells = <1>;
clocks = <&scmi_clk CK_SCMI_HSE>,
<&scmi_clk CK_SCMI_HSI>,
<&scmi_clk CK_SCMI_MSI>,
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (3 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 04/20] arm64: dts: st: set rcc as an access-controller Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-10 7:54 ` Krzysztof Kozlowski
2025-09-09 10:12 ` [PATCH v6 06/20] dt-bindings: memory: introduce DDR4 Clément Le Goffic
` (14 subsequent siblings)
19 siblings, 1 reply; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
LPDDR and DDR bindings are SDRAM types and are likely to share the same
properties (at least for density, io-width and reg).
To avoid bindings duplication, factorise the properties.
The compatible description has been updated because the MR (Mode
registers) used to get manufacturer ID and revision ID are not present
in case of DDR.
Those information should be in a SPD (Serial Presence Detect) EEPROM in
case of DIMM module or are known in case of soldered memory chips as
they are in the datasheet of the memory chips.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
.../memory-controllers/ddr/jedec,lpddr-props.yaml | 74 -----------------
.../memory-controllers/ddr/jedec,lpddr2.yaml | 2 +-
.../memory-controllers/ddr/jedec,lpddr3.yaml | 2 +-
.../memory-controllers/ddr/jedec,lpddr4.yaml | 2 +-
.../memory-controllers/ddr/jedec,lpddr5.yaml | 2 +-
.../memory-controllers/ddr/jedec,sdram-props.yaml | 94 ++++++++++++++++++++++
6 files changed, 98 insertions(+), 78 deletions(-)
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-props.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-props.yaml
deleted file mode 100644
index 30267ce70124..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-props.yaml
+++ /dev/null
@@ -1,74 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr-props.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Common properties for LPDDR types
-
-description:
- Different LPDDR types generally use the same properties and only differ in the
- range of legal values for each. This file defines the common parts that can be
- reused for each type. Nodes using this schema should generally be nested under
- an LPDDR channel node.
-
-maintainers:
- - Krzysztof Kozlowski <krzk@kernel.org>
-
-properties:
- compatible:
- description:
- Compatible strings can be either explicit vendor names and part numbers
- (e.g. elpida,ECB240ABACN), or generated strings of the form
- lpddrX-YY,ZZZZ where X is the LPDDR version, YY is the manufacturer ID
- (from MR5) and ZZZZ is the revision ID (from MR6 and MR7). Both IDs are
- formatted in lower case hexadecimal representation with leading zeroes.
- The latter form can be useful when LPDDR nodes are created at runtime by
- boot firmware that doesn't have access to static part number information.
-
- reg:
- description:
- The rank number of this LPDDR rank when used as a subnode to an LPDDR
- channel.
- minimum: 0
- maximum: 3
-
- revision-id:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- description:
- Revision IDs read from Mode Register 6 and 7. One byte per uint32 cell (i.e. <MR6 MR7>).
- maxItems: 2
- items:
- minimum: 0
- maximum: 255
-
- density:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
- Density in megabits of SDRAM chip. Decoded from Mode Register 8.
- enum:
- - 64
- - 128
- - 256
- - 512
- - 1024
- - 2048
- - 3072
- - 4096
- - 6144
- - 8192
- - 12288
- - 16384
- - 24576
- - 32768
-
- io-width:
- $ref: /schemas/types.yaml#/definitions/uint32
- description:
- IO bus width in bits of SDRAM chip. Decoded from Mode Register 8.
- enum:
- - 8
- - 16
- - 32
-
-additionalProperties: true
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
index a237bc259273..704bbc562528 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
@@ -10,7 +10,7 @@ maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
allOf:
- - $ref: jedec,lpddr-props.yaml#
+ - $ref: jedec,sdram-props.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml
index e328a1195ba6..0d28df3d2bfa 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml
@@ -10,7 +10,7 @@ maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
allOf:
- - $ref: jedec,lpddr-props.yaml#
+ - $ref: jedec,sdram-props.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml
index a078892fecee..65aa07861453 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml
@@ -10,7 +10,7 @@ maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
allOf:
- - $ref: jedec,lpddr-props.yaml#
+ - $ref: jedec,sdram-props.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml
index e441dac5f154..cf5d5a8e94b3 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml
@@ -10,7 +10,7 @@ maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
allOf:
- - $ref: jedec,lpddr-props.yaml#
+ - $ref: jedec,sdram-props.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-props.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-props.yaml
new file mode 100644
index 000000000000..38472a3febc5
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-props.yaml
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,sdram-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common properties for SDRAM types
+
+description:
+ Different SDRAM types generally use the same properties and only differ in the
+ range of legal values for each. This file defines the common parts that can be
+ reused for each type. Nodes using this schema should generally be nested under
+ a SDRAM channel node.
+
+maintainers:
+ - Krzysztof Kozlowski <krzk@kernel.org>
+
+properties:
+ compatible:
+ description: |
+ Compatible strings can be either explicit vendor names and part numbers
+ (e.g. elpida,ECB240ABACN), or generated strings of the form
+ lpddrX,YY,ZZZZ or ddrX-YYYY,AAAA...,ZZ where X, Y, and Z are in lower
+ case hexadecimal with leading zeroes and A is in lowercase ASCII.
+ For LPDDR and DDR SDRAM, X is the SDRAM version (2, 3, 4, etc.).
+ For LPDDR SDRAM:
+ - YY is the manufacturer ID (from MR5), 1 byte
+ - ZZZZ is the revision ID (from MR6 and MR7), 2 bytes
+ For DDR4 SDRAM with SPD, according to JEDEC SPD4.1.2.L-6 :
+ - YYYY is the manufacturer ID, 2 bytes, from bytes 320 and 321
+ - AAAA... is the part number, 20 bytes (10 chars) from bytes 329 to 348
+ without trailing spaces.
+ - ZZ is the revision ID, 1 byte, from byte 349
+ The former form is useful when the SDRAM vendor and part number are
+ known, such as when the SDRAM is soldered on the board.
+ The latter form can be useful when SDRAM nodes are created at runtime by
+ boot firmware that doesn't have access to statis part number information.
+
+ reg:
+ description:
+ The rank number of this memory rank when used as a subnode to an memory
+ channel.
+ minimum: 0
+ maximum: 3
+
+ revision-id:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: |
+ SDRAM revision ID:
+ - LPDDR SDRAM, decoded from Mode Register 6 and 7, always 2 bytes.
+ - DDR4 SDRAM, decoded from the SPD from byte 349 according to
+ JEDEC SPD4.1.2.L-6, always 1 byte.
+ One byte per uint32 cell (i.e. <MR6 MR7>).
+ maxItems: 2
+ items:
+ minimum: 0
+ maximum: 255
+
+ density:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Density of SDRAM chip in megabits:
+ - LPDDR SDRAM, decoded from Mode Register 8.
+ - DDR4 SDRAM, decoded from the SPD from bits 3~0 of byte 4 according to
+ JEDEC SPD4.1.2.L-6.
+ enum:
+ - 64
+ - 128
+ - 256
+ - 512
+ - 1024
+ - 2048
+ - 3072
+ - 4096
+ - 6144
+ - 8192
+ - 12288
+ - 16384
+ - 24576
+ - 32768
+
+ io-width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ IO bus width in bits of SDRAM chip:
+ - LPDDR SDRAM, decoded from Mode Register 8.
+ - DDR4 SDRAM, decoded from the SPD from bits 2~0 of byte 12 according to
+ JEDEC SPD4.1.2.L-6.
+ enum:
+ - 8
+ - 16
+ - 32
+
+additionalProperties: true
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props
2025-09-09 10:12 ` [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props Clément Le Goffic
@ 2025-09-10 7:54 ` Krzysztof Kozlowski
2025-09-10 8:31 ` Clément Le Goffic
2025-09-10 8:41 ` Clément Le Goffic
0 siblings, 2 replies; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-10 7:54 UTC (permalink / raw)
To: Clément Le Goffic
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On Tue, Sep 09, 2025 at 12:12:12PM +0200, Clément Le Goffic wrote:
> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> LPDDR and DDR bindings are SDRAM types and are likely to share the same
> properties (at least for density, io-width and reg).
> To avoid bindings duplication, factorise the properties.
>
> The compatible description has been updated because the MR (Mode
> registers) used to get manufacturer ID and revision ID are not present
> in case of DDR.
> Those information should be in a SPD (Serial Presence Detect) EEPROM in
> case of DIMM module or are known in case of soldered memory chips as
> they are in the datasheet of the memory chips.
>
> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Is this email defunct now, that you add second SoB?
> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
I still see in this patchset around 5 different subsystems. Nothing in
the cover letter explains the dependencies, so grouping looks like
coincidence and you just make it difficult for maintainers for no
reason.
Please organize your patchsets per subsystems, see submitting patches
doc for more details.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props
2025-09-10 7:54 ` Krzysztof Kozlowski
@ 2025-09-10 8:31 ` Clément Le Goffic
2025-09-10 8:41 ` Clément Le Goffic
1 sibling, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-10 8:31 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On 10/09/2025 09:54, Krzysztof Kozlowski wrote:
> On Tue, Sep 09, 2025 at 12:12:12PM +0200, Clément Le Goffic wrote:
>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>
>> LPDDR and DDR bindings are SDRAM types and are likely to share the same
>> properties (at least for density, io-width and reg).
>> To avoid bindings duplication, factorise the properties.
>>
>> The compatible description has been updated because the MR (Mode
>> registers) used to get manufacturer ID and revision ID are not present
>> in case of DDR.
>> Those information should be in a SPD (Serial Presence Detect) EEPROM in
>> case of DIMM module or are known in case of soldered memory chips as
>> they are in the datasheet of the memory chips.
>>
>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> Is this email defunct now, that you add second SoB?
>
>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
Hi Krzysztof,
>
> I still see in this patchset around 5 different subsystems. Nothing in
> the cover letter explains the dependencies, so grouping looks like
> coincidence and you just make it difficult for maintainers for no
> reason.
>
> Please organize your patchsets per subsystems, see submitting patches
> doc for more details.
Yes I agree it is a big series.
I'll split it according to each subsystem it targets.
Best regards,
Clément
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props
2025-09-10 7:54 ` Krzysztof Kozlowski
2025-09-10 8:31 ` Clément Le Goffic
@ 2025-09-10 8:41 ` Clément Le Goffic
2025-09-10 8:52 ` Krzysztof Kozlowski
1 sibling, 1 reply; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-10 8:41 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On 10/09/2025 09:54, Krzysztof Kozlowski wrote:
> On Tue, Sep 09, 2025 at 12:12:12PM +0200, Clément Le Goffic wrote:
>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>
>> LPDDR and DDR bindings are SDRAM types and are likely to share the same
>> properties (at least for density, io-width and reg).
>> To avoid bindings duplication, factorise the properties.
>>
>> The compatible description has been updated because the MR (Mode
>> registers) used to get manufacturer ID and revision ID are not present
>> in case of DDR.
>> Those information should be in a SPD (Serial Presence Detect) EEPROM in
>> case of DIMM module or are known in case of soldered memory chips as
>> they are in the datasheet of the memory chips.
>>
>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> Is this email defunct now, that you add second SoB?
Yes, but I still want to upstream it and was thinking to keep the
"original" author even if it is me.
Am I wrong here ? What should I do ?
>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props
2025-09-10 8:41 ` Clément Le Goffic
@ 2025-09-10 8:52 ` Krzysztof Kozlowski
0 siblings, 0 replies; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-10 8:52 UTC (permalink / raw)
To: Clément Le Goffic
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On 10/09/2025 10:41, Clément Le Goffic wrote:
> On 10/09/2025 09:54, Krzysztof Kozlowski wrote:
>> On Tue, Sep 09, 2025 at 12:12:12PM +0200, Clément Le Goffic wrote:
>>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>>
>>> LPDDR and DDR bindings are SDRAM types and are likely to share the same
>>> properties (at least for density, io-width and reg).
>>> To avoid bindings duplication, factorise the properties.
>>>
>>> The compatible description has been updated because the MR (Mode
>>> registers) used to get manufacturer ID and revision ID are not present
>>> in case of DDR.
>>> Those information should be in a SPD (Serial Presence Detect) EEPROM in
>>> case of DIMM module or are known in case of soldered memory chips as
>>> they are in the datasheet of the memory chips.
>>>
>>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>>
>> Is this email defunct now, that you add second SoB?
>
> Yes, but I still want to upstream it and was thinking to keep the
> "original" author even if it is me.
> Am I wrong here ? What should I do ?
It's fine, I just wanted to clarify this.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v6 06/20] dt-bindings: memory: introduce DDR4
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (4 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 07/20] dt-bindings: memory: factorise LPDDR channel binding into SDRAM channel Clément Le Goffic
` (13 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Introduce JEDEC compliant DDR bindings, that use new memory-props binding.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
.../memory-controllers/ddr/jedec,ddr4.yaml | 34 ++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,ddr4.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,ddr4.yaml
new file mode 100644
index 000000000000..bf1dae15b65b
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,ddr4.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,ddr4.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DDR4 SDRAM compliant to JEDEC JESD79-4D
+
+maintainers:
+ - Krzysztof Kozlowski <krzk@kernel.org>
+
+allOf:
+ - $ref: jedec,sdram-props.yaml#
+
+properties:
+ compatible:
+ items:
+ - pattern: "^ddr4-[0-9a-f]{4},[a-z]{1,10},[0-9a-f]{2}$"
+ - const: jedec,ddr4
+
+required:
+ - compatible
+ - density
+ - io-width
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ ddr {
+ compatible = "ddr4-00ff,azaz,ff", "jedec,ddr4";
+ density = <8192>;
+ io-width = <8>;
+ };
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 07/20] dt-bindings: memory: factorise LPDDR channel binding into SDRAM channel
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (5 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 06/20] dt-bindings: memory: introduce DDR4 Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 08/20] dt-binding: memory: add DDR4 channel compatible Clément Le Goffic
` (12 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
LPDDR, DDR and so SDRAM channels exist and share the same properties, they
have a compatible, ranks, and an io-width.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
...lpddr-channel.yaml => jedec,sdram-channel.yaml} | 23 +++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-channel.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
similarity index 83%
rename from Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-channel.yaml
rename to Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
index 34b5bd153f63..9892da520fe4 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-channel.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
@@ -1,16 +1,17 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr-channel.yaml#
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,sdram-channel.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: LPDDR channel with chip/rank topology description
+title: SDRAM channel with chip/rank topology description
description:
- An LPDDR channel is a completely independent set of LPDDR pins (DQ, CA, CS,
- CK, etc.) that connect one or more LPDDR chips to a host system. The main
- purpose of this node is to overall LPDDR topology of the system, including the
- amount of individual LPDDR chips and the ranks per chip.
+ A memory channel of SDRAM memory like DDR SDRAM or LPDDR SDRAM is a completely
+ independent set of pins (DQ, CA, CS, CK, etc.) that connect one or more memory
+ chips to a host system. The main purpose of this node is to overall memory
+ topology of the system, including the amount of individual memory chips and
+ the ranks per chip.
maintainers:
- Julius Werner <jwerner@chromium.org>
@@ -26,14 +27,14 @@ properties:
io-width:
description:
The number of DQ pins in the channel. If this number is different
- from (a multiple of) the io-width of the LPDDR chip, that means that
+ from (a multiple of) the io-width of the SDRAM chip, that means that
multiple instances of that type of chip are wired in parallel on this
channel (with the channel's DQ pins split up between the different
chips, and the CA, CS, etc. pins of the different chips all shorted
together). This means that the total physical memory controlled by a
channel is equal to the sum of the densities of each rank on the
- connected LPDDR chip, times the io-width of the channel divided by
- the io-width of the LPDDR chip.
+ connected SDRAM chip, times the io-width of the channel divided by
+ the io-width of the SDRAM chip.
enum:
- 8
- 16
@@ -51,8 +52,8 @@ patternProperties:
"^rank@[0-9]+$":
type: object
description:
- Each physical LPDDR chip may have one or more ranks. Ranks are
- internal but fully independent sub-units of the chip. Each LPDDR bus
+ Each physical SDRAM chip may have one or more ranks. Ranks are
+ internal but fully independent sub-units of the chip. Each SDRAM bus
transaction on the channel targets exactly one rank, based on the
state of the CS pins. Different ranks may have different densities and
timing requirements.
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 08/20] dt-binding: memory: add DDR4 channel compatible
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (6 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 07/20] dt-bindings: memory: factorise LPDDR channel binding into SDRAM channel Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 09/20] dt-bindings: memory: SDRAM channel: standardise node name Clément Le Goffic
` (11 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Add in the memory channel binding the DDR4 compatible to support DDR4
memory channel.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
.../bindings/memory-controllers/ddr/jedec,sdram-channel.yaml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
index 9892da520fe4..866af40b654d 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
@@ -19,6 +19,7 @@ maintainers:
properties:
compatible:
enum:
+ - jedec,ddr4-channel
- jedec,lpddr2-channel
- jedec,lpddr3-channel
- jedec,lpddr4-channel
@@ -61,6 +62,15 @@ patternProperties:
- reg
allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: jedec,ddr4-channel
+ then:
+ patternProperties:
+ "^rank@[0-9]+$":
+ $ref: /schemas/memory-controllers/ddr/jedec,ddr4.yaml#
- if:
properties:
compatible:
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 09/20] dt-bindings: memory: SDRAM channel: standardise node name
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (7 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 08/20] dt-binding: memory: add DDR4 channel compatible Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 10/20] arm64: dts: st: add LPDDR channel to stm32mp257f-dk board Clément Le Goffic
` (10 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Add a pattern for sdram channel node name.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
.../bindings/memory-controllers/ddr/jedec,sdram-channel.yaml | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
index 866af40b654d..5cdd8ef45100 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,sdram-channel.yaml
@@ -17,6 +17,9 @@ maintainers:
- Julius Werner <jwerner@chromium.org>
properties:
+ $nodename:
+ pattern: "sdram-channel-[0-9]+$"
+
compatible:
enum:
- jedec,ddr4-channel
@@ -118,7 +121,7 @@ additionalProperties: false
examples:
- |
- lpddr-channel0 {
+ sdram-channel-0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "jedec,lpddr3-channel";
@@ -133,7 +136,7 @@ examples:
};
};
- lpddr-channel1 {
+ sdram-channel-1 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "jedec,lpddr4-channel";
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 10/20] arm64: dts: st: add LPDDR channel to stm32mp257f-dk board
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (8 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 09/20] dt-bindings: memory: SDRAM channel: standardise node name Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 11/20] arm64: dts: st: add DDR channel to stm32mp257f-ev1 board Clément Le Goffic
` (9 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Add 32bits LPDDR4 channel to the stm32mp257f-dk board.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm64/boot/dts/st/stm32mp257f-dk.dts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-dk.dts b/arch/arm64/boot/dts/st/stm32mp257f-dk.dts
index a278a1e3ce03..45ffa358c800 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-dk.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-dk.dts
@@ -54,6 +54,13 @@ led-blue {
};
};
+ lpddr_channel: sdram-channel-0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "jedec,lpddr4-channel";
+ io-width = <32>;
+ };
+
memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x1 0x0>;
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 11/20] arm64: dts: st: add DDR channel to stm32mp257f-ev1 board
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (9 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 10/20] arm64: dts: st: add LPDDR channel to stm32mp257f-dk board Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings Clément Le Goffic
` (8 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Add 32bits DDR4 channel to the stm32mp257f-dk board.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 836b1958ce65..c4223f06396a 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -41,6 +41,13 @@ pad_clk: pad-clk {
};
};
+ ddr_channel: sdram-channel-0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "jedec,ddr4-channel";
+ io-width = <32>;
+ };
+
imx335_2v9: regulator-2v9 {
compatible = "regulator-fixed";
regulator-name = "imx335-avdd";
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (10 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 11/20] arm64: dts: st: add DDR channel to stm32mp257f-ev1 board Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-10 7:57 ` Krzysztof Kozlowski
2025-09-10 7:57 ` Krzysztof Kozlowski
2025-09-09 10:12 ` [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver Clément Le Goffic
` (7 subsequent siblings)
19 siblings, 2 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
DDRPERFM is the DDR Performance Monitor embedded in STM32MPU SoC.
It allows to monitor DDR events that come from the DDR Controller
such as read or write events.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
.../devicetree/bindings/perf/st,stm32-ddr-pmu.yaml | 94 ++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml
new file mode 100644
index 000000000000..1d97861e3d44
--- /dev/null
+++ b/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/perf/st,stm32-ddr-pmu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+maintainers:
+ - Clément Le Goffic <legoffic.clement@gmail.com>
+
+title: STMicroelectronics STM32 DDR Performance Monitor (DDRPERFM)
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - const: st,stm32mp131-ddr-pmu
+ - items:
+ - enum:
+ - st,stm32mp151-ddr-pmu
+ - const: st,stm32mp131-ddr-pmu
+ - items:
+ - const: st,stm32mp251-ddr-pmu
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ access-controllers:
+ minItems: 1
+ maxItems: 2
+
+ memory-channel:
+ description:
+ The memory channel this DDRPERFM is attached to.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,stm32mp131-ddr-pmu
+ then:
+ required:
+ - clocks
+ - resets
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,stm32mp251-ddr-pmu
+ then:
+ required:
+ - access-controllers
+ - memory-channel
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/stm32mp1-clks.h>
+ #include <dt-bindings/reset/stm32mp1-resets.h>
+
+ perf@5a007000 {
+ compatible = "st,stm32mp151-ddr-pmu", "st,stm32mp131-ddr-pmu";
+ reg = <0x5a007000 0x400>;
+ clocks = <&rcc DDRPERFM>;
+ resets = <&rcc DDRPERFM_R>;
+ };
+
+ - |
+ ddr_channel: sdram-channel-0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "jedec,ddr4-channel";
+ io-width = <16>;
+ };
+
+ perf@48041000 {
+ compatible = "st,stm32mp251-ddr-pmu";
+ reg = <0x48041000 0x400>;
+ access-controllers = <&rcc 104>;
+ memory-channel = <&ddr_channel>;
+ };
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings
2025-09-09 10:12 ` [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings Clément Le Goffic
@ 2025-09-10 7:57 ` Krzysztof Kozlowski
2025-09-10 8:33 ` Clément Le Goffic
2025-09-10 7:57 ` Krzysztof Kozlowski
1 sibling, 1 reply; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-10 7:57 UTC (permalink / raw)
To: Clément Le Goffic
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On Tue, Sep 09, 2025 at 12:12:19PM +0200, Clément Le Goffic wrote:
> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> DDRPERFM is the DDR Performance Monitor embedded in STM32MPU SoC.
> It allows to monitor DDR events that come from the DDR Controller
> such as read or write events.
>
> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
> ---
> .../devicetree/bindings/perf/st,stm32-ddr-pmu.yaml | 94 ++++++++++++++++++++++
> 1 file changed, 94 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml
> new file mode 100644
> index 000000000000..1d97861e3d44
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml
> @@ -0,0 +1,94 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/perf/st,stm32-ddr-pmu.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +maintainers:
> + - Clément Le Goffic <legoffic.clement@gmail.com>
> +
> +title: STMicroelectronics STM32 DDR Performance Monitor (DDRPERFM)
> +
> +properties:
> + compatible:
> + oneOf:
> + - items:
> + - const: st,stm32mp131-ddr-pmu
> + - items:
> + - enum:
> + - st,stm32mp151-ddr-pmu
> + - const: st,stm32mp131-ddr-pmu
> + - items:
> + - const: st,stm32mp251-ddr-pmu
You did not implement Rob's comment.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings
2025-09-10 7:57 ` Krzysztof Kozlowski
@ 2025-09-10 8:33 ` Clément Le Goffic
0 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-10 8:33 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On 10/09/2025 09:57, Krzysztof Kozlowski wrote:
> On Tue, Sep 09, 2025 at 12:12:19PM +0200, Clément Le Goffic wrote:
>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>
>> DDRPERFM is the DDR Performance Monitor embedded in STM32MPU SoC.
>> It allows to monitor DDR events that come from the DDR Controller
>> such as read or write events.
>>
>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
>> ---
>> .../devicetree/bindings/perf/st,stm32-ddr-pmu.yaml | 94 ++++++++++++++++++++++
>> 1 file changed, 94 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml
>> new file mode 100644
>> index 000000000000..1d97861e3d44
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml
>> @@ -0,0 +1,94 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/perf/st,stm32-ddr-pmu.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +maintainers:
>> + - Clément Le Goffic <legoffic.clement@gmail.com>
>> +
>> +title: STMicroelectronics STM32 DDR Performance Monitor (DDRPERFM)
>> +
>> +properties:
>> + compatible:
>> + oneOf:
>> + - items:
>> + - const: st,stm32mp131-ddr-pmu
>> + - items:
>> + - enum:
>> + - st,stm32mp151-ddr-pmu
>> + - const: st,stm32mp131-ddr-pmu
>> + - items:
>> + - const: st,stm32mp251-ddr-pmu
>
> You did not implement Rob's comment.
Indeed I miss it. Will fix it for the next version.
Best regards,
Clément
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings
2025-09-09 10:12 ` [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings Clément Le Goffic
2025-09-10 7:57 ` Krzysztof Kozlowski
@ 2025-09-10 7:57 ` Krzysztof Kozlowski
2025-09-10 8:34 ` Clément Le Goffic
1 sibling, 1 reply; 36+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-10 7:57 UTC (permalink / raw)
To: Clément Le Goffic
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On Tue, Sep 09, 2025 at 12:12:19PM +0200, Clément Le Goffic wrote:
> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> DDRPERFM is the DDR Performance Monitor embedded in STM32MPU SoC.
> It allows to monitor DDR events that come from the DDR Controller
> such as read or write events.
Also:
A nit, subject: drop second/last, redundant "dt-bindings". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings
2025-09-10 7:57 ` Krzysztof Kozlowski
@ 2025-09-10 8:34 ` Clément Le Goffic
0 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-10 8:34 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Julius Werner, Will Deacon,
Mark Rutland, Philipp Zabel, Jonathan Corbet, linux-stm32,
linux-arm-kernel, linux-kernel, linux-clk, devicetree,
linux-perf-users, linux-doc, Clément Le Goffic
On 10/09/2025 09:57, Krzysztof Kozlowski wrote:
> On Tue, Sep 09, 2025 at 12:12:19PM +0200, Clément Le Goffic wrote:
>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>
>> DDRPERFM is the DDR Performance Monitor embedded in STM32MPU SoC.
>> It allows to monitor DDR events that come from the DDR Controller
>> such as read or write events.
>
> Also:
>
> A nit, subject: drop second/last, redundant "dt-bindings". The
> "dt-bindings" prefix is already stating that these are bindings.
> See also:
> https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
Oops, it will be fixed in next version.
Best regards,
Clément
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (11 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-10 9:26 ` Jonathan Cameron
2025-09-09 10:12 ` [PATCH v6 14/20] Documentation: perf: stm32: add ddrperfm support Clément Le Goffic
` (6 subsequent siblings)
19 siblings, 1 reply; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Introduce the driver for the DDR Performance Monitor available on
STM32MPU SoC.
On STM32MP2 platforms, the DDRPERFM allows to monitor up to 8 DDR events
that come from the DDR Controller such as read or write events.
On STM32MP1 platforms, the DDRPERFM cannot monitor any event on any
counter, there is a notion of set of events.
Events from different sets cannot be monitored at the same time.
The first chosen event selects the set.
The set is coded in the first two bytes of the config value which is on 4
bytes.
On STM32MP25x series, the DDRPERFM clock is shared with the DDR controller
and may be secured by bootloaders.
Access controllers allow to check access to a resource. Use the access
controller defined in the devicetree to know about the access to the
DDRPERFM clock.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
drivers/perf/Kconfig | 11 +
drivers/perf/Makefile | 1 +
drivers/perf/stm32_ddr_pmu.c | 897 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 909 insertions(+)
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index a9188dec36fe..a45a574c2125 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -198,6 +198,17 @@ config QCOM_L3_PMU
Adds the L3 cache PMU into the perf events subsystem for
monitoring L3 cache events.
+config STM32_DDR_PMU
+ tristate "STM32 DDR PMU"
+ depends on ARCH_STM32 || COMPILE_TEST
+ default m
+ help
+ Provides support for the DDR performance monitor on STM32MPU platforms.
+ The monitor provides counters for memory related events.
+ It allows developers to analyze and optimize DDR performance.
+ Enabling this feature is useful for performance tuning and debugging memory
+ subsystem issues on supported hardware.
+
config THUNDERX2_PMU
tristate "Cavium ThunderX2 SoC PMU UNCORE"
depends on ARCH_THUNDER2 || COMPILE_TEST
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index 192fc8b16204..2fa5844a2672 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_RISCV_PMU) += riscv_pmu.o
obj-$(CONFIG_RISCV_PMU_LEGACY) += riscv_pmu_legacy.o
obj-$(CONFIG_RISCV_PMU_SBI) += riscv_pmu_sbi.o
obj-$(CONFIG_STARFIVE_STARLINK_PMU) += starfive_starlink_pmu.o
+obj-$(CONFIG_STM32_DDR_PMU) += stm32_ddr_pmu.o
obj-$(CONFIG_THUNDERX2_PMU) += thunderx2_pmu.o
obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o
obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o
diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c
new file mode 100644
index 000000000000..38328663d2c5
--- /dev/null
+++ b/drivers/perf/stm32_ddr_pmu.c
@@ -0,0 +1,897 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
+ * Author: Clément Le Goffic <clement.legoffic@foss.st.com> for STMicroelectronics.
+ */
+
+#include <linux/bus/stm32_firewall_device.h>
+#include <linux/clk.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define DRIVER_NAME "stm32_ddr_pmu"
+
+/*
+ * The PMU is able to freeze all counters and generate an interrupt when there
+ * is a counter overflow. But, relying on this means that we lose all the
+ * events that occur between the freeze and the interrupt handler execution.
+ * So we use a polling mechanism to avoid this lost of information.
+ * The fastest counter can overflow in ~7s @600MHz (that is the maximum DDR
+ * frequency supported on STM32MP257), so we poll in 3.5s intervals to ensure
+ * we don't reach this limit.
+ */
+#define POLL_MS 3500
+
+#define DDRPERFM_CTRL 0x000
+#define DDRPERFM_CFG 0x004
+#define DDRPERFM_STATUS 0x008
+#define DDRPERFM_CLR 0x00C
+#define DDRPERFM_TCNT 0x020
+#define DDRPERFM_EVCNT(X) (0x030 + 8 * (X))
+
+#define DDRPERFM_MP2_CFG0 0x010
+#define DDRPERFM_MP2_CFG1 0x014
+#define DDRPERFM_MP2_CFG5 0x024
+#define DDRPERFM_MP2_DRAMINF 0x028
+#define DDRPERFM_MP2_EVCNT(X) (0x040 + 4 * (X))
+#define DDRPERFM_MP2_TCNT 0x060
+#define DDRPERFM_MP2_STATUS 0x080
+
+#define MP1_STATUS_BUSY BIT(16)
+#define MP2_STATUS_BUSY BIT(31)
+
+#define CTRL_START BIT(0)
+#define CTRL_STOP BIT(1)
+
+#define CFG_SEL_MSK GENMASK(17, 16)
+#define CFG_SEL_SHIFT 16
+#define CFG_EN_MSK GENMASK(3, 0)
+
+#define MP1_CLR_CNT GENMASK(3, 0)
+#define MP1_CLR_TIME BIT(31)
+#define MP2_CLR_CNT GENMASK(7, 0)
+#define MP2_CLR_TIME BIT(8)
+
+/* 4 event counters plus 1 dedicated to time */
+#define MP1_CNT_NB (4 + 1)
+/* Index of the time dedicated counter */
+#define MP1_TIME_CNT_IDX 4
+
+/* 8 event counters plus 1 dedicated to time */
+#define MP2_CNT_NB (8 + 1)
+/* Index of the time dedicated counter */
+#define MP2_TIME_CNT_IDX 8
+/* 4 event counters per register */
+#define MP2_CNT_SEL_PER_REG 4
+
+/* Arbitrary value used to identify a time event */
+#define TIME_CNT 64
+
+struct stm32_ddr_pmu_reg {
+ unsigned int reg;
+ u32 mask;
+};
+
+struct stm32_ddr_cnt {
+ int idx;
+ struct perf_event *evt;
+ struct list_head cnt_list;
+};
+
+struct stm32_ddr_pmu_regspec {
+ const struct stm32_ddr_pmu_reg stop;
+ const struct stm32_ddr_pmu_reg start;
+ const struct stm32_ddr_pmu_reg enable;
+ const struct stm32_ddr_pmu_reg status;
+ const struct stm32_ddr_pmu_reg clear_cnt;
+ const struct stm32_ddr_pmu_reg clear_time;
+ const struct stm32_ddr_pmu_reg cfg;
+ const struct stm32_ddr_pmu_reg cfg0;
+ const struct stm32_ddr_pmu_reg cfg1;
+ const struct stm32_ddr_pmu_reg dram_inf;
+ const struct stm32_ddr_pmu_reg counter_time;
+ const struct stm32_ddr_pmu_reg counter_evt[];
+};
+
+struct stm32_ddr_pmu {
+ struct pmu pmu;
+ void __iomem *membase;
+ struct device *dev;
+ struct clk *clk;
+ const struct stm32_ddr_pmu_cfg *cfg;
+ struct hrtimer hrtimer;
+ ktime_t poll_period;
+ int selected_set;
+ u32 dram_type;
+ struct list_head counters[];
+};
+
+struct stm32_ddr_pmu_cfg {
+ const struct stm32_ddr_pmu_regspec *regs;
+ const struct attribute_group **attribute;
+ u32 counters_nb;
+ u32 evt_counters_nb;
+ u32 time_cnt_idx;
+ struct stm32_ddr_cnt * (*get_counter)(struct stm32_ddr_pmu *p, struct perf_event *e);
+};
+
+#define STM32_DDR_PMU_EVENT_NUMBER(group, index) (((group) << 8) | (index))
+#define STM32_DDR_PMU_GROUP_VALUE(event_number) ((event_number) >> 8)
+#define STM32_DDR_PMU_EVENT_INDEX(event_number) ((event_number) & 0xFF)
+
+/* MP1 ddrperfm events */
+enum stm32_ddr_pmu_events_mp1 {
+ PERF_OP_IS_RD = STM32_DDR_PMU_EVENT_NUMBER(0, 0),
+ PERF_OP_IS_WR = STM32_DDR_PMU_EVENT_NUMBER(0, 1),
+ PERF_OP_IS_ACTIVATE = STM32_DDR_PMU_EVENT_NUMBER(0, 2),
+ CTL_IDLE = STM32_DDR_PMU_EVENT_NUMBER(0, 3),
+ PERF_HPR_REQ_WITH_NO_CREDIT = STM32_DDR_PMU_EVENT_NUMBER(1, 0),
+ PERF_LPR_REQ_WITH_NO_CREDIT = STM32_DDR_PMU_EVENT_NUMBER(1, 1),
+ CACTIVE_DDRC = STM32_DDR_PMU_EVENT_NUMBER(1, 3),
+ PERF_OP_IS_ENTER_POWERDOWN = STM32_DDR_PMU_EVENT_NUMBER(2, 0),
+ PERF_OP_IS_REFRESH = STM32_DDR_PMU_EVENT_NUMBER(2, 1),
+ PERF_SELFRESH_MODE = STM32_DDR_PMU_EVENT_NUMBER(2, 2),
+ DFI_LP_REQ = STM32_DDR_PMU_EVENT_NUMBER(2, 3),
+ PERF_HPR_XACT_WHEN_CRITICAL = STM32_DDR_PMU_EVENT_NUMBER(3, 0),
+ PERF_LPR_XACT_WHEN_CRITICAL = STM32_DDR_PMU_EVENT_NUMBER(3, 1),
+ PERF_WR_XACT_WHEN_CRITICAL = STM32_DDR_PMU_EVENT_NUMBER(3, 2),
+ DFI_LP_REQ_SCND = STM32_DDR_PMU_EVENT_NUMBER(3, 3),
+};
+
+/* MP2 ddrperfm events */
+enum stm32_ddr_pmu_events_mp2 {
+ DFI_IS_ACT = STM32_DDR_PMU_EVENT_NUMBER(0, 0),
+ DFI_IS_PREPB = STM32_DDR_PMU_EVENT_NUMBER(0, 1),
+ DFI_IS_PREAB = STM32_DDR_PMU_EVENT_NUMBER(0, 2),
+ DFI_IS_RD = STM32_DDR_PMU_EVENT_NUMBER(0, 3),
+ DFI_IS_RDA = STM32_DDR_PMU_EVENT_NUMBER(0, 4),
+ DFI_IS_WR = STM32_DDR_PMU_EVENT_NUMBER(0, 6),
+ DFI_IS_WRA = STM32_DDR_PMU_EVENT_NUMBER(0, 7),
+ DFI_IS_MWR = STM32_DDR_PMU_EVENT_NUMBER(0, 9),
+ DFI_IS_MWRA = STM32_DDR_PMU_EVENT_NUMBER(0, 10),
+ DFI_IS_MRW = STM32_DDR_PMU_EVENT_NUMBER(0, 12),
+ DFI_IS_MRR = STM32_DDR_PMU_EVENT_NUMBER(0, 13),
+ DFI_IS_REFPB = STM32_DDR_PMU_EVENT_NUMBER(0, 14),
+ DFI_IS_REFAB = STM32_DDR_PMU_EVENT_NUMBER(0, 15),
+ DFI_IS_MPC = STM32_DDR_PMU_EVENT_NUMBER(0, 16),
+ PERF_OP_IS_ACT = STM32_DDR_PMU_EVENT_NUMBER(0, 32),
+ PERF_OP_IS_RD_MP2 = STM32_DDR_PMU_EVENT_NUMBER(0, 33),
+ PERF_OP_IS_WR_MP2 = STM32_DDR_PMU_EVENT_NUMBER(0, 34),
+ PERF_OP_IS_MWR = STM32_DDR_PMU_EVENT_NUMBER(0, 35),
+ PERF_OP_IS_REF = STM32_DDR_PMU_EVENT_NUMBER(0, 36),
+ PERF_OP_IS_CRIT_REF = STM32_DDR_PMU_EVENT_NUMBER(0, 37),
+ PERF_OP_IS_SPEC_REF = STM32_DDR_PMU_EVENT_NUMBER(0, 38),
+ PERF_OP_IS_ZQCAL = STM32_DDR_PMU_EVENT_NUMBER(0, 39),
+ PERF_OP_IS_ENTER_POWDN = STM32_DDR_PMU_EVENT_NUMBER(0, 40),
+ PERF_OP_IS_ENTER_SELFREF = STM32_DDR_PMU_EVENT_NUMBER(0, 41),
+ PERF_OP_IS_PRE = STM32_DDR_PMU_EVENT_NUMBER(0, 42),
+ PERF_OP_IS_PRE_FOR_RDWR = STM32_DDR_PMU_EVENT_NUMBER(0, 43),
+ PERF_OP_IS_PRE_FOR_OTHERS = STM32_DDR_PMU_EVENT_NUMBER(0, 44),
+ PERF_OP_IS_RD_ACTIVATE = STM32_DDR_PMU_EVENT_NUMBER(0, 45),
+ PERF_HPR_REQ_WITH_NOCREDIT = STM32_DDR_PMU_EVENT_NUMBER(0, 48),
+ PERF_LPR_REQ_WITH_NOCREDIT = STM32_DDR_PMU_EVENT_NUMBER(0, 49),
+ PERF_HPR_XACT_WHEN_CRITICAL_MP2 = STM32_DDR_PMU_EVENT_NUMBER(0, 50),
+ PERF_LPR_XACT_WHEN_CRITICAL_MP2 = STM32_DDR_PMU_EVENT_NUMBER(0, 51),
+ PERF_WR_XACT_WHEN_CRITICAL_MP2 = STM32_DDR_PMU_EVENT_NUMBER(0, 52),
+ PERF_RDWR_TRANSITIONS = STM32_DDR_PMU_EVENT_NUMBER(0, 53),
+ PERF_WAR_HAZARD = STM32_DDR_PMU_EVENT_NUMBER(0, 54),
+ PERF_RAW_HAZARD = STM32_DDR_PMU_EVENT_NUMBER(0, 55),
+ PERF_WAW_HAZARD = STM32_DDR_PMU_EVENT_NUMBER(0, 56),
+ PERF_RANK = STM32_DDR_PMU_EVENT_NUMBER(0, 58),
+ PERF_READ_BYPASS = STM32_DDR_PMU_EVENT_NUMBER(0, 59),
+ PERF_ACT_BYPASS = STM32_DDR_PMU_EVENT_NUMBER(0, 60),
+ PERF_WINDOW_LIMIT_REACHED_RD = STM32_DDR_PMU_EVENT_NUMBER(0, 61),
+ PERF_WINDOW_LIMIT_REACHED_WR = STM32_DDR_PMU_EVENT_NUMBER(0, 62),
+ NO_EVENT = STM32_DDR_PMU_EVENT_NUMBER(0, 63),
+};
+
+enum stm32_ddr_pmu_memory_type {
+ STM32_DDR_PMU_LPDDR4,
+ STM32_DDR_PMU_LPDDR3,
+ STM32_DDR_PMU_DDR4,
+ STM32_DDR_PMU_DDR3,
+};
+
+static struct stm32_ddr_pmu *to_stm32_ddr_pmu(struct pmu *p)
+{
+ return container_of(p, struct stm32_ddr_pmu, pmu);
+}
+
+static struct stm32_ddr_pmu *hrtimer_to_stm32_ddr_pmu(struct hrtimer *h)
+{
+ return container_of(h, struct stm32_ddr_pmu, hrtimer);
+}
+
+static void stm32_ddr_start_counters(struct stm32_ddr_pmu *pmu)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+
+ writel_relaxed(r->start.mask, pmu->membase + r->start.reg);
+}
+
+static void stm32_ddr_stop_counters(struct stm32_ddr_pmu *pmu)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+
+ writel_relaxed(r->stop.mask, pmu->membase + r->stop.reg);
+}
+
+static void stm32_ddr_clear_time_counter(struct stm32_ddr_pmu *pmu)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+
+ writel_relaxed(r->clear_time.mask, pmu->membase + r->clear_time.reg);
+}
+
+static void stm32_ddr_clear_event_counter(struct stm32_ddr_pmu *pmu, struct stm32_ddr_cnt *counter)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+
+ writel_relaxed(r->clear_cnt.mask & BIT(counter->idx), pmu->membase + r->clear_cnt.reg);
+}
+
+static void stm32_ddr_clear_counter(struct stm32_ddr_pmu *pmu, struct stm32_ddr_cnt *counter)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+ u32 status = readl_relaxed(pmu->membase + r->status.reg);
+
+ if (counter->idx == pmu->cfg->time_cnt_idx)
+ stm32_ddr_clear_time_counter(pmu);
+ else
+ stm32_ddr_clear_event_counter(pmu, counter);
+
+ if (status & r->status.mask)
+ dev_err(pmu->dev, "Failed to clear counter %i because the PMU is busy\n",
+ counter->idx);
+}
+
+static void stm32_ddr_counter_enable(struct stm32_ddr_pmu *pmu, struct stm32_ddr_cnt *counter)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+ u32 val = readl_relaxed(pmu->membase + r->enable.reg);
+
+ val |= BIT(counter->idx);
+ writel_relaxed(val, pmu->membase + r->enable.reg);
+}
+
+static void stm32_ddr_counter_disable(struct stm32_ddr_pmu *pmu, struct stm32_ddr_cnt *counter)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+ u32 val = readl_relaxed(pmu->membase + r->enable.reg);
+
+ val &= ~BIT(counter->idx);
+ writel_relaxed(val, pmu->membase + r->enable.reg);
+}
+
+static int stm32_ddr_sel_evnt(struct stm32_ddr_pmu *pmu, struct stm32_ddr_cnt *counter)
+{
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+ u32 cnt_sel_val;
+
+ u32 group_val = STM32_DDR_PMU_GROUP_VALUE(counter->evt->attr.config);
+ u32 evt_val = STM32_DDR_PMU_EVENT_INDEX(counter->evt->attr.config);
+
+ if (pmu->selected_set != -1 && pmu->selected_set != group_val) {
+ dev_err(pmu->dev, "Selected events are from different set\n");
+ return -EINVAL;
+ }
+ pmu->selected_set = group_val;
+
+ if (pmu->cfg->regs->cfg.reg) {
+ cnt_sel_val = readl_relaxed(pmu->membase + r->cfg.reg);
+ cnt_sel_val &= ~CFG_SEL_MSK;
+ cnt_sel_val |= (CFG_SEL_MSK & (group_val << CFG_SEL_SHIFT));
+ writel_relaxed(cnt_sel_val, pmu->membase + r->cfg.reg);
+
+ return 0;
+ }
+
+ /* We assume cfg0 and cfg1 are filled in the match data */
+ u32 cnt_idx = counter->idx;
+ u32 cnt_sel_evt_reg = r->cfg0.reg;
+
+ if (!(cnt_idx < MP2_CNT_SEL_PER_REG)) {
+ cnt_sel_evt_reg = r->cfg1.reg;
+ cnt_idx -= MP2_CNT_SEL_PER_REG;
+ }
+
+ cnt_sel_val = readl_relaxed(pmu->membase + cnt_sel_evt_reg);
+ cnt_sel_val &= ~GENMASK(8 * cnt_idx + 7, 8 * cnt_idx);
+ cnt_sel_val |= evt_val << (8 * cnt_idx);
+
+ writel_relaxed(cnt_sel_val, pmu->membase + cnt_sel_evt_reg);
+
+ return 0;
+}
+
+static struct stm32_ddr_cnt *stm32_ddr_pmu_get_event_counter_mp1(struct stm32_ddr_pmu *pmu,
+ struct perf_event *event)
+{
+ u32 config = event->attr.config;
+ u32 event_idx = STM32_DDR_PMU_EVENT_INDEX(config);
+ struct stm32_ddr_cnt *cnt;
+
+ cnt = kzalloc(sizeof(*cnt), GFP_KERNEL);
+ if (!cnt)
+ return ERR_PTR(-ENOMEM);
+
+ cnt->evt = event;
+ cnt->idx = event_idx;
+ event->pmu_private = cnt;
+ list_add(&cnt->cnt_list, &pmu->counters[event_idx]);
+
+ return cnt;
+}
+
+static struct stm32_ddr_cnt *stm32_ddr_pmu_get_event_counter_mp2(struct stm32_ddr_pmu *pmu,
+ struct perf_event *event)
+{
+ struct stm32_ddr_cnt *cnt;
+ int idx = -1;
+
+ /* Loop on all the counters except TIME_CNT_IDX */
+ for (int i = 0; i < pmu->cfg->evt_counters_nb; i++) {
+ u64 config;
+
+ if (list_empty(&pmu->counters[i])) {
+ idx = i;
+ continue;
+ }
+ config = list_first_entry(&pmu->counters[i], struct stm32_ddr_cnt,
+ cnt_list)->evt->attr.config;
+ if (config == event->attr.config) {
+ idx = i;
+ break;
+ }
+ }
+
+ if (idx == -1)
+ return ERR_PTR(-ENOENT);
+
+ cnt = kzalloc(sizeof(*cnt), GFP_KERNEL);
+ if (!cnt)
+ return ERR_PTR(-ENOMEM);
+
+ cnt->evt = event;
+ cnt->idx = idx;
+ event->pmu_private = cnt;
+
+ list_add(&cnt->cnt_list, &pmu->counters[idx]);
+
+ return cnt;
+}
+
+static inline struct stm32_ddr_cnt *stm32_get_event_counter(struct stm32_ddr_pmu *pmu,
+ struct perf_event *event)
+{
+ return pmu->cfg->get_counter(pmu, event);
+}
+
+static int stm32_ddr_pmu_get_counter(struct stm32_ddr_pmu *pmu, struct perf_event *event)
+{
+ u32 time_cnt_idx = pmu->cfg->time_cnt_idx;
+ u32 config = event->attr.config;
+ struct stm32_ddr_cnt *cnt;
+
+ pmu->selected_set = STM32_DDR_PMU_GROUP_VALUE(config);
+
+ if (config == TIME_CNT) {
+ cnt = kzalloc(sizeof(*cnt), GFP_KERNEL);
+ if (!cnt)
+ return -ENOMEM;
+
+ cnt->evt = event;
+ cnt->idx = time_cnt_idx;
+ event->pmu_private = cnt;
+ list_add(&cnt->cnt_list, &pmu->counters[time_cnt_idx]);
+
+ return 0;
+ }
+
+ cnt = stm32_get_event_counter(pmu, event);
+ if (IS_ERR(cnt))
+ return PTR_ERR(cnt);
+
+ if (list_count_nodes(&cnt->cnt_list) == 1) {
+ stm32_ddr_stop_counters(pmu);
+ stm32_ddr_sel_evnt(pmu, cnt);
+ stm32_ddr_counter_enable(pmu, cnt);
+ stm32_ddr_start_counters(pmu);
+ }
+
+ return 0;
+}
+
+static void stm32_ddr_pmu_free_counter(struct stm32_ddr_pmu *pmu,
+ struct stm32_ddr_cnt *counter)
+{
+ size_t count = list_count_nodes(&counter->cnt_list);
+
+ if (counter->evt->attr.config != TIME_CNT && count == 1)
+ stm32_ddr_counter_disable(pmu, counter);
+
+ list_del(&counter->cnt_list);
+ kfree(counter);
+}
+
+static void stm32_ddr_pmu_event_update_list(struct stm32_ddr_pmu *pmu, struct list_head *list)
+{
+ struct stm32_ddr_cnt *counter = list_first_entry(list, struct stm32_ddr_cnt, cnt_list);
+ const struct stm32_ddr_pmu_regspec *r = pmu->cfg->regs;
+ u32 val;
+
+ if (counter->evt->attr.config != TIME_CNT)
+ val = readl_relaxed(pmu->membase + r->counter_evt[counter->idx].reg);
+ else
+ val = readl_relaxed(pmu->membase + r->counter_time.reg);
+
+ stm32_ddr_clear_counter(pmu, counter);
+
+ list_for_each_entry(counter, list, cnt_list)
+ local64_add(val, &counter->evt->count);
+}
+
+static void stm32_ddr_pmu_event_read(struct perf_event *event)
+{
+ struct stm32_ddr_pmu *pmu = to_stm32_ddr_pmu(event->pmu);
+ struct stm32_ddr_cnt *cnt = event->pmu_private;
+
+ hrtimer_start(&pmu->hrtimer, pmu->poll_period, HRTIMER_MODE_REL_PINNED);
+
+ stm32_ddr_stop_counters(pmu);
+
+ stm32_ddr_pmu_event_update_list(pmu, &pmu->counters[cnt->idx]);
+
+ stm32_ddr_start_counters(pmu);
+}
+
+static void stm32_ddr_pmu_event_start(struct perf_event *event, int flags)
+{
+ struct stm32_ddr_pmu *pmu = to_stm32_ddr_pmu(event->pmu);
+ struct stm32_ddr_cnt *counter = event->pmu_private;
+ struct hw_perf_event *hw = &event->hw;
+
+ if (WARN_ON_ONCE(!(hw->state & PERF_HES_STOPPED)))
+ return;
+
+ if (flags & PERF_EF_RELOAD)
+ WARN_ON_ONCE(!(hw->state & PERF_HES_UPTODATE));
+
+ stm32_ddr_stop_counters(pmu);
+
+ if (list_count_nodes(&counter->cnt_list) == 1)
+ stm32_ddr_clear_counter(pmu, counter);
+ else
+ stm32_ddr_pmu_event_update_list(pmu, &pmu->counters[counter->idx]);
+
+ stm32_ddr_start_counters(pmu);
+ local64_set(&hw->prev_count, 0);
+ hw->state = 0;
+}
+
+static void stm32_ddr_pmu_event_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hw = &event->hw;
+
+ if (WARN_ON_ONCE(hw->state & PERF_HES_STOPPED))
+ return;
+
+ hw->state |= PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_UPDATE) {
+ stm32_ddr_pmu_event_read(event);
+ hw->state |= PERF_HES_UPTODATE;
+ }
+}
+
+static int stm32_ddr_pmu_event_add(struct perf_event *event, int flags)
+{
+ struct stm32_ddr_pmu *pmu = to_stm32_ddr_pmu(event->pmu);
+ int ret;
+
+ clk_enable(pmu->clk);
+
+ hrtimer_start(&pmu->hrtimer, pmu->poll_period, HRTIMER_MODE_REL_PINNED);
+
+ ret = stm32_ddr_pmu_get_counter(pmu, event);
+ if (ret)
+ return ret;
+
+ event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+
+ if (flags & PERF_EF_START)
+ stm32_ddr_pmu_event_start(event, flags);
+
+ return 0;
+}
+
+static void stm32_ddr_pmu_event_del(struct perf_event *event, int flags)
+{
+ struct stm32_ddr_pmu *pmu = to_stm32_ddr_pmu(event->pmu);
+ struct stm32_ddr_cnt *counter = event->pmu_private;
+ bool events = true;
+
+ stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE);
+
+ stm32_ddr_pmu_free_counter(pmu, counter);
+
+ for (int i = 0; i < pmu->cfg->counters_nb; i++) {
+ events = !list_empty(&pmu->counters[i]);
+ if (events) /* If there is activity nothing to do */
+ return;
+ }
+
+ hrtimer_cancel(&pmu->hrtimer);
+ stm32_ddr_stop_counters(pmu);
+
+ pmu->selected_set = -1;
+
+ clk_disable(pmu->clk);
+}
+
+static int stm32_ddr_pmu_event_init(struct perf_event *event)
+{
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static enum hrtimer_restart stm32_ddr_pmu_poll(struct hrtimer *hrtimer)
+{
+ struct stm32_ddr_pmu *pmu = hrtimer_to_stm32_ddr_pmu(hrtimer);
+
+ stm32_ddr_stop_counters(pmu);
+
+ for (int i = 0; i < MP2_CNT_NB; i++)
+ if (!list_empty(&pmu->counters[i]))
+ stm32_ddr_pmu_event_update_list(pmu, &pmu->counters[i]);
+
+ if (list_empty(&pmu->counters[pmu->cfg->time_cnt_idx]))
+ stm32_ddr_clear_time_counter(pmu);
+
+ stm32_ddr_start_counters(pmu);
+
+ hrtimer_forward_now(hrtimer, pmu->poll_period);
+
+ return HRTIMER_RESTART;
+}
+
+static ssize_t stm32_ddr_pmu_sysfs_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct perf_pmu_events_attr *pmu_attr;
+
+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+
+ return sysfs_emit(buf, "event=0x%02llx\n", pmu_attr->id);
+}
+
+static int stm32_ddr_pmu_get_memory_type(struct stm32_ddr_pmu *pmu)
+{
+ struct platform_device *pdev = to_platform_device(pmu->dev);
+ struct device_node *memchan;
+
+ memchan = of_parse_phandle(pdev->dev.of_node, "memory-channel", 0);
+ if (!memchan)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "Missing device-tree property 'memory-channel'\n");
+
+ if (of_device_is_compatible(memchan, "jedec,lpddr4-channel"))
+ pmu->dram_type = STM32_DDR_PMU_LPDDR4;
+ else if (of_device_is_compatible(memchan, "jedec,lpddr3-channel"))
+ pmu->dram_type = STM32_DDR_PMU_LPDDR3;
+ else if (of_device_is_compatible(memchan, "jedec,ddr4-channel"))
+ pmu->dram_type = STM32_DDR_PMU_DDR4;
+ else if (of_device_is_compatible(memchan, "jedec,ddr3-channel"))
+ pmu->dram_type = STM32_DDR_PMU_DDR3;
+ else
+ return dev_err_probe(&pdev->dev, -EINVAL, "Unsupported memory channel type\n");
+
+ if (pmu->dram_type == STM32_DDR_PMU_LPDDR3)
+ dev_warn(&pdev->dev,
+ "LPDDR3 supported by DDRPERFM but not supported by DDRCTRL/DDRPHY\n");
+
+ return 0;
+}
+
+#define STM32_DDR_PMU_EVENT_ATTR(_name, _id) \
+ PMU_EVENT_ATTR_ID(_name, stm32_ddr_pmu_sysfs_show, _id)
+
+static struct attribute *stm32_ddr_pmu_events_attrs_mp[] = {
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_rd, PERF_OP_IS_RD),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_wr, PERF_OP_IS_WR),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_activate, PERF_OP_IS_ACTIVATE),
+ STM32_DDR_PMU_EVENT_ATTR(ctl_idle, CTL_IDLE),
+ STM32_DDR_PMU_EVENT_ATTR(perf_hpr_req_with_no_credit, PERF_HPR_REQ_WITH_NO_CREDIT),
+ STM32_DDR_PMU_EVENT_ATTR(perf_lpr_req_with_no_credit, PERF_LPR_REQ_WITH_NO_CREDIT),
+ STM32_DDR_PMU_EVENT_ATTR(cactive_ddrc, CACTIVE_DDRC),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_enter_powerdown, PERF_OP_IS_ENTER_POWERDOWN),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_refresh, PERF_OP_IS_REFRESH),
+ STM32_DDR_PMU_EVENT_ATTR(perf_selfresh_mode, PERF_SELFRESH_MODE),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req, DFI_LP_REQ),
+ STM32_DDR_PMU_EVENT_ATTR(perf_hpr_xact_when_critical, PERF_HPR_XACT_WHEN_CRITICAL),
+ STM32_DDR_PMU_EVENT_ATTR(perf_lpr_xact_when_critical, PERF_LPR_XACT_WHEN_CRITICAL),
+ STM32_DDR_PMU_EVENT_ATTR(perf_wr_xact_when_critical, PERF_WR_XACT_WHEN_CRITICAL),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req_cpy, DFI_LP_REQ), /* Suffixed '_cpy' to allow the
+ * choice between sets 2 and 3
+ */
+ STM32_DDR_PMU_EVENT_ATTR(time_cnt, TIME_CNT),
+ NULL
+};
+
+static struct attribute_group stm32_ddr_pmu_events_attrs_group_mp = {
+ .name = "events",
+ .attrs = stm32_ddr_pmu_events_attrs_mp,
+};
+
+static struct attribute *stm32_ddr_pmu_events_attrs_mp2[] = {
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_act, DFI_IS_ACT),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_prepb, DFI_IS_PREPB),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_preab, DFI_IS_PREAB),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_rd, DFI_IS_RD),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_rda, DFI_IS_RDA),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_wr, DFI_IS_WR),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_wra, DFI_IS_WRA),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_mwr, DFI_IS_MWR),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_mwra, DFI_IS_MWRA),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_mrw, DFI_IS_MRW),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_mrr, DFI_IS_MRR),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_refpb, DFI_IS_REFPB),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_refab, DFI_IS_REFAB),
+ STM32_DDR_PMU_EVENT_ATTR(dfi_is_mpc, DFI_IS_MPC),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_act, PERF_OP_IS_ACT),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_rd, PERF_OP_IS_RD),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_wr, PERF_OP_IS_WR),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_mwr, PERF_OP_IS_MWR),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_ref, PERF_OP_IS_REF),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_crit_ref, PERF_OP_IS_CRIT_REF),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_spec_ref, PERF_OP_IS_SPEC_REF),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_zqcal, PERF_OP_IS_ZQCAL),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_enter_powdn, PERF_OP_IS_ENTER_POWDN),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_enter_selfref, PERF_OP_IS_ENTER_SELFREF),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_pre, PERF_OP_IS_PRE),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_pre_for_rdwr, PERF_OP_IS_PRE_FOR_RDWR),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_pre_for_others, PERF_OP_IS_PRE_FOR_OTHERS),
+ STM32_DDR_PMU_EVENT_ATTR(perf_op_is_rd_activate, PERF_OP_IS_RD_ACTIVATE),
+ STM32_DDR_PMU_EVENT_ATTR(perf_hpr_req_with_nocredit, PERF_HPR_REQ_WITH_NOCREDIT),
+ STM32_DDR_PMU_EVENT_ATTR(perf_lpr_req_with_nocredit, PERF_LPR_REQ_WITH_NOCREDIT),
+ STM32_DDR_PMU_EVENT_ATTR(perf_hpr_xact_when_critical, PERF_HPR_XACT_WHEN_CRITICAL),
+ STM32_DDR_PMU_EVENT_ATTR(perf_lpr_xact_when_critical, PERF_LPR_XACT_WHEN_CRITICAL),
+ STM32_DDR_PMU_EVENT_ATTR(perf_wr_xact_when_critical, PERF_WR_XACT_WHEN_CRITICAL),
+ STM32_DDR_PMU_EVENT_ATTR(perf_rdwr_transitions, PERF_RDWR_TRANSITIONS),
+ STM32_DDR_PMU_EVENT_ATTR(perf_war_hazard, PERF_WAR_HAZARD),
+ STM32_DDR_PMU_EVENT_ATTR(perf_raw_hazard, PERF_RAW_HAZARD),
+ STM32_DDR_PMU_EVENT_ATTR(perf_waw_hazard, PERF_WAW_HAZARD),
+ STM32_DDR_PMU_EVENT_ATTR(perf_rank, PERF_RANK),
+ STM32_DDR_PMU_EVENT_ATTR(perf_read_bypass, PERF_READ_BYPASS),
+ STM32_DDR_PMU_EVENT_ATTR(perf_act_bypass, PERF_ACT_BYPASS),
+ STM32_DDR_PMU_EVENT_ATTR(perf_window_limit_reached_rd, PERF_WINDOW_LIMIT_REACHED_RD),
+ STM32_DDR_PMU_EVENT_ATTR(perf_window_limit_reached_wr, PERF_WINDOW_LIMIT_REACHED_WR),
+ STM32_DDR_PMU_EVENT_ATTR(time_cnt, TIME_CNT),
+ NULL
+};
+
+static struct attribute_group stm32_ddr_pmu_events_attrs_group_mp2 = {
+ .name = "events",
+ .attrs = stm32_ddr_pmu_events_attrs_mp2,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-8");
+
+static struct attribute *stm32_ddr_pmu_format_attrs[] = {
+ &format_attr_event.attr,
+ NULL
+};
+
+static const struct attribute_group stm32_ddr_pmu_format_attr_group = {
+ .name = "format",
+ .attrs = stm32_ddr_pmu_format_attrs,
+};
+
+static const struct attribute_group *stm32_ddr_pmu_attr_groups_mp1[] = {
+ &stm32_ddr_pmu_events_attrs_group_mp,
+ &stm32_ddr_pmu_format_attr_group,
+ NULL
+};
+
+static const struct attribute_group *stm32_ddr_pmu_attr_groups_mp2[] = {
+ &stm32_ddr_pmu_events_attrs_group_mp2,
+ &stm32_ddr_pmu_format_attr_group,
+ NULL
+};
+
+static int stm32_ddr_pmu_device_probe(struct platform_device *pdev)
+{
+ struct stm32_firewall firewall;
+ struct stm32_ddr_pmu *pmu;
+ struct reset_control *rst;
+ struct resource *res;
+ int ret;
+
+ pmu = devm_kzalloc(&pdev->dev, struct_size(pmu, counters, MP2_CNT_NB), GFP_KERNEL);
+ if (!pmu)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, pmu);
+ pmu->dev = &pdev->dev;
+
+ pmu->cfg = device_get_match_data(pmu->dev);
+
+ pmu->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(pmu->membase))
+ return PTR_ERR(pmu->membase);
+
+ if (of_property_present(pmu->dev->of_node, "access-controllers")) {
+ ret = stm32_firewall_get_firewall(pmu->dev->of_node, &firewall, 1);
+ if (ret)
+ return dev_err_probe(pmu->dev, ret, "Failed to get firewall\n");
+ ret = stm32_firewall_grant_access_by_id(&firewall, firewall.firewall_id);
+ if (ret)
+ return dev_err_probe(pmu->dev, ret, "Failed to grant access\n");
+ }
+
+ pmu->clk = devm_clk_get_optional_enabled(pmu->dev, NULL);
+ if (IS_ERR(pmu->clk))
+ return dev_err_probe(pmu->dev, PTR_ERR(pmu->clk),
+ "Failed to get prepare enable clock\n");
+
+ rst = devm_reset_control_get_optional_exclusive(pmu->dev, NULL);
+ if (IS_ERR(rst))
+ return dev_err_probe(pmu->dev, PTR_ERR(rst), "Failed to get reset\n");
+
+ reset_control_assert(rst);
+ reset_control_deassert(rst);
+
+ pmu->poll_period = ms_to_ktime(POLL_MS);
+ hrtimer_setup(&pmu->hrtimer, stm32_ddr_pmu_poll, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
+ for (int i = 0; i < MP2_CNT_NB; i++)
+ INIT_LIST_HEAD(&pmu->counters[i]);
+
+ pmu->selected_set = -1;
+
+ pmu->pmu = (struct pmu) {
+ .task_ctx_nr = perf_invalid_context,
+ .start = stm32_ddr_pmu_event_start,
+ .stop = stm32_ddr_pmu_event_stop,
+ .add = stm32_ddr_pmu_event_add,
+ .del = stm32_ddr_pmu_event_del,
+ .read = stm32_ddr_pmu_event_read,
+ .event_init = stm32_ddr_pmu_event_init,
+ .attr_groups = pmu->cfg->attribute,
+ .module = THIS_MODULE,
+ };
+
+ if (pmu->cfg->regs->dram_inf.reg) {
+ ret = stm32_ddr_pmu_get_memory_type(pmu);
+ if (ret)
+ return dev_err_probe(pmu->dev, ret, "Failed to get memory type\n");
+
+ writel_relaxed(pmu->dram_type, pmu->membase + pmu->cfg->regs->dram_inf.reg);
+ }
+
+ ret = perf_pmu_register(&pmu->pmu, DRIVER_NAME, -1);
+ if (ret)
+ return dev_err_probe(pmu->dev, ret,
+ "Couldn't register DDRPERFM driver as a PMU\n");
+
+ clk_disable(pmu->clk);
+
+ return 0;
+}
+
+static void stm32_ddr_pmu_device_remove(struct platform_device *pdev)
+{
+ struct stm32_ddr_pmu *stm32_ddr_pmu = platform_get_drvdata(pdev);
+
+ perf_pmu_unregister(&stm32_ddr_pmu->pmu);
+}
+
+static int __maybe_unused stm32_ddr_pmu_device_resume(struct device *dev)
+{
+ struct stm32_ddr_pmu *pmu = dev_get_drvdata(dev);
+
+ clk_enable(pmu->clk);
+ writel_relaxed(pmu->dram_type, pmu->membase + pmu->cfg->regs->dram_inf.reg);
+ clk_disable(pmu->clk);
+
+ return 0;
+}
+
+static const struct stm32_ddr_pmu_regspec stm32_ddr_pmu_regspec_mp1 = {
+ .stop = { DDRPERFM_CTRL, CTRL_STOP },
+ .start = { DDRPERFM_CTRL, CTRL_START },
+ .enable = { DDRPERFM_CFG },
+ .cfg = { DDRPERFM_CFG },
+ .status = { DDRPERFM_STATUS, MP1_STATUS_BUSY },
+ .clear_cnt = { DDRPERFM_CLR, MP1_CLR_CNT },
+ .clear_time = { DDRPERFM_CLR, MP1_CLR_TIME },
+ .counter_time = { DDRPERFM_TCNT },
+ .counter_evt = {
+ { DDRPERFM_EVCNT(0) },
+ { DDRPERFM_EVCNT(1) },
+ { DDRPERFM_EVCNT(2) },
+ { DDRPERFM_EVCNT(3) },
+ },
+};
+
+static const struct stm32_ddr_pmu_regspec stm32_ddr_pmu_regspec_mp2 = {
+ .stop = { DDRPERFM_CTRL, CTRL_STOP },
+ .start = { DDRPERFM_CTRL, CTRL_START },
+ .status = { DDRPERFM_MP2_STATUS, MP2_STATUS_BUSY },
+ .clear_cnt = { DDRPERFM_CLR, MP2_CLR_CNT },
+ .clear_time = { DDRPERFM_CLR, MP2_CLR_TIME },
+ .cfg0 = { DDRPERFM_MP2_CFG0 },
+ .cfg1 = { DDRPERFM_MP2_CFG1 },
+ .enable = { DDRPERFM_MP2_CFG5 },
+ .dram_inf = { DDRPERFM_MP2_DRAMINF },
+ .counter_time = { DDRPERFM_MP2_TCNT },
+ .counter_evt = {
+ { DDRPERFM_MP2_EVCNT(0) },
+ { DDRPERFM_MP2_EVCNT(1) },
+ { DDRPERFM_MP2_EVCNT(2) },
+ { DDRPERFM_MP2_EVCNT(3) },
+ { DDRPERFM_MP2_EVCNT(4) },
+ { DDRPERFM_MP2_EVCNT(5) },
+ { DDRPERFM_MP2_EVCNT(6) },
+ { DDRPERFM_MP2_EVCNT(7) },
+ },
+};
+
+static const struct stm32_ddr_pmu_cfg stm32_ddr_pmu_cfg_mp1 = {
+ .regs = &stm32_ddr_pmu_regspec_mp1,
+ .attribute = stm32_ddr_pmu_attr_groups_mp1,
+ .counters_nb = MP1_CNT_NB,
+ .evt_counters_nb = MP1_CNT_NB - 1, /* Time counter is not an event counter */
+ .time_cnt_idx = MP1_TIME_CNT_IDX,
+ .get_counter = stm32_ddr_pmu_get_event_counter_mp1,
+};
+
+static const struct stm32_ddr_pmu_cfg stm32_ddr_pmu_cfg_mp2 = {
+ .regs = &stm32_ddr_pmu_regspec_mp2,
+ .attribute = stm32_ddr_pmu_attr_groups_mp2,
+ .counters_nb = MP2_CNT_NB,
+ .evt_counters_nb = MP2_CNT_NB - 1, /* Time counter is an event counter */
+ .time_cnt_idx = MP2_TIME_CNT_IDX,
+ .get_counter = stm32_ddr_pmu_get_event_counter_mp2,
+};
+
+static DEFINE_SIMPLE_DEV_PM_OPS(stm32_ddr_pmu_pm_ops, NULL, stm32_ddr_pmu_device_resume);
+
+static const struct of_device_id stm32_ddr_pmu_of_match[] = {
+ {
+ .compatible = "st,stm32mp131-ddr-pmu",
+ .data = &stm32_ddr_pmu_cfg_mp1
+ },
+ {
+ .compatible = "st,stm32mp251-ddr-pmu",
+ .data = &stm32_ddr_pmu_cfg_mp2
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, stm32_ddr_pmu_of_match);
+
+static struct platform_driver stm32_ddr_pmu_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .pm = pm_sleep_ptr(&stm32_ddr_pmu_pm_ops),
+ .of_match_table = stm32_ddr_pmu_of_match,
+ },
+ .probe = stm32_ddr_pmu_device_probe,
+ .remove = stm32_ddr_pmu_device_remove,
+};
+
+module_platform_driver(stm32_ddr_pmu_driver);
+
+MODULE_AUTHOR("Clément Le Goffic");
+MODULE_DESCRIPTION("STMicroelectronics STM32 DDR performance monitor driver");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver
2025-09-09 10:12 ` [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver Clément Le Goffic
@ 2025-09-10 9:26 ` Jonathan Cameron
2025-09-11 9:56 ` Clément Le Goffic
0 siblings, 1 reply; 36+ messages in thread
From: Jonathan Cameron @ 2025-09-10 9:26 UTC (permalink / raw)
To: Clément Le Goffic
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet, linux-stm32, linux-arm-kernel, linux-kernel,
linux-clk, devicetree, linux-perf-users, linux-doc,
Clément Le Goffic
On Tue, 09 Sep 2025 12:12:20 +0200
Clément Le Goffic <legoffic.clement@gmail.com> wrote:
> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> Introduce the driver for the DDR Performance Monitor available on
> STM32MPU SoC.
>
> On STM32MP2 platforms, the DDRPERFM allows to monitor up to 8 DDR events
> that come from the DDR Controller such as read or write events.
>
> On STM32MP1 platforms, the DDRPERFM cannot monitor any event on any
> counter, there is a notion of set of events.
> Events from different sets cannot be monitored at the same time.
> The first chosen event selects the set.
> The set is coded in the first two bytes of the config value which is on 4
> bytes.
>
> On STM32MP25x series, the DDRPERFM clock is shared with the DDR controller
> and may be secured by bootloaders.
> Access controllers allow to check access to a resource. Use the access
> controller defined in the devicetree to know about the access to the
> DDRPERFM clock.
>
> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
Hi Clément
A quick drive by review,
J
> diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c
> new file mode 100644
> index 000000000000..38328663d2c5
> --- /dev/null
> +++ b/drivers/perf/stm32_ddr_pmu.c
> @@ -0,0 +1,897 @@
> +
> +#define MP1_CLR_CNT GENMASK(3, 0)
> +#define MP1_CLR_TIME BIT(31)
> +#define MP2_CLR_CNT GENMASK(7, 0)
> +#define MP2_CLR_TIME BIT(8)
> +
> +/* 4 event counters plus 1 dedicated to time */
> +#define MP1_CNT_NB (4 + 1)
This is never used so I would drop it and rename the MP2_CNT_NB
to indicate it is the max value for any devices supported.
> +/* Index of the time dedicated counter */
> +#define MP1_TIME_CNT_IDX 4
> +
> +/* 8 event counters plus 1 dedicated to time */
> +#define MP2_CNT_NB (8 + 1)
...
> +struct stm32_ddr_pmu {
> + struct pmu pmu;
> + void __iomem *membase;
> + struct device *dev;
> + struct clk *clk;
> + const struct stm32_ddr_pmu_cfg *cfg;
> + struct hrtimer hrtimer;
> + ktime_t poll_period;
> + int selected_set;
> + u32 dram_type;
> + struct list_head counters[];
The absence of a __counted_by() marking made me wonder how
we ensured that this wasn't overrun. I see below that's because
size is always the same. So
struct list_head counters[MP2_CNT_NB];
If you do want to make it dynamic then that is fine but added
a local variable for the size and the __counted_by() marking so
the various analysis tools can check for buffer overruns.
> +};
> +static void stm32_ddr_pmu_event_del(struct perf_event *event, int flags)
> +{
> + struct stm32_ddr_pmu *pmu = to_stm32_ddr_pmu(event->pmu);
> + struct stm32_ddr_cnt *counter = event->pmu_private;
> + bool events = true;
Always set before use, so don't set it here. I'd move this into the
scope of the for loop to make this more obvious.
> +
> + stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE);
> +
> + stm32_ddr_pmu_free_counter(pmu, counter);
> +
> + for (int i = 0; i < pmu->cfg->counters_nb; i++) {
> + events = !list_empty(&pmu->counters[i]);
> + if (events) /* If there is activity nothing to do */
> + return;
> + }
> +
> + hrtimer_cancel(&pmu->hrtimer);
> + stm32_ddr_stop_counters(pmu);
> +
> + pmu->selected_set = -1;
> +
> + clk_disable(pmu->clk);
> +}
> +
> +#define STM32_DDR_PMU_EVENT_ATTR(_name, _id) \
> + PMU_EVENT_ATTR_ID(_name, stm32_ddr_pmu_sysfs_show, _id)
> +
> +static struct attribute *stm32_ddr_pmu_events_attrs_mp[] = {
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_rd, PERF_OP_IS_RD),
Prefixing perf events with perf_ seems unnecessary.
I guess perf_op_is_rd is counting all reads? Is so why not call it simply 'reads'
or something else short like that? If it's cycles when a read is going on then
maybe a more complex is needed, but perf_op_is_rd doesn't convey that to me.
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_wr, PERF_OP_IS_WR),
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_activate, PERF_OP_IS_ACTIVATE),
> + STM32_DDR_PMU_EVENT_ATTR(ctl_idle, CTL_IDLE),
> + STM32_DDR_PMU_EVENT_ATTR(perf_hpr_req_with_no_credit, PERF_HPR_REQ_WITH_NO_CREDIT),
> + STM32_DDR_PMU_EVENT_ATTR(perf_lpr_req_with_no_credit, PERF_LPR_REQ_WITH_NO_CREDIT),
> + STM32_DDR_PMU_EVENT_ATTR(cactive_ddrc, CACTIVE_DDRC),
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_enter_powerdown, PERF_OP_IS_ENTER_POWERDOWN),
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_refresh, PERF_OP_IS_REFRESH),
> + STM32_DDR_PMU_EVENT_ATTR(perf_selfresh_mode, PERF_SELFRESH_MODE),
> + STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req, DFI_LP_REQ),
> + STM32_DDR_PMU_EVENT_ATTR(perf_hpr_xact_when_critical, PERF_HPR_XACT_WHEN_CRITICAL),
> + STM32_DDR_PMU_EVENT_ATTR(perf_lpr_xact_when_critical, PERF_LPR_XACT_WHEN_CRITICAL),
> + STM32_DDR_PMU_EVENT_ATTR(perf_wr_xact_when_critical, PERF_WR_XACT_WHEN_CRITICAL),
> + STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req_cpy, DFI_LP_REQ), /* Suffixed '_cpy' to allow the
> + * choice between sets 2 and 3
> + */
> + STM32_DDR_PMU_EVENT_ATTR(time_cnt, TIME_CNT),
> + NULL
> +};
> +static int stm32_ddr_pmu_device_probe(struct platform_device *pdev)
> +{
> + struct stm32_firewall firewall;
> + struct stm32_ddr_pmu *pmu;
> + struct reset_control *rst;
> + struct resource *res;
> + int ret;
> +
> + pmu = devm_kzalloc(&pdev->dev, struct_size(pmu, counters, MP2_CNT_NB), GFP_KERNEL);
If using a fixed number of counters why not put it in the struct
definition and simplify the code? I agree it is probably not
worth making this dynamic given small sizes but I don't mind
if you do want to do this. The only thing that isn't a good idea
is this dynamic, but not really, current situation.
> + if (!pmu)
> + return -ENOMEM;
> +static DEFINE_SIMPLE_DEV_PM_OPS(stm32_ddr_pmu_pm_ops, NULL, stm32_ddr_pmu_device_resume);
> +
> +static const struct of_device_id stm32_ddr_pmu_of_match[] = {
> + {
> + .compatible = "st,stm32mp131-ddr-pmu",
> + .data = &stm32_ddr_pmu_cfg_mp1
Trivial but if you are spinning again, normal convention is trailing commas
in cases like this because maybe other fields will get set later.
> + },
> + {
> + .compatible = "st,stm32mp251-ddr-pmu",
> + .data = &stm32_ddr_pmu_cfg_mp2
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, stm32_ddr_pmu_of_match);
> +
> +static struct platform_driver stm32_ddr_pmu_driver = {
> + .driver = {
> + .name = DRIVER_NAME,
> + .pm = pm_sleep_ptr(&stm32_ddr_pmu_pm_ops),
> + .of_match_table = stm32_ddr_pmu_of_match,
> + },
> + .probe = stm32_ddr_pmu_device_probe,
> + .remove = stm32_ddr_pmu_device_remove,
> +};
> +
> +module_platform_driver(stm32_ddr_pmu_driver);
> +
> +MODULE_AUTHOR("Clément Le Goffic");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 DDR performance monitor driver");
> +MODULE_LICENSE("GPL");
>
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver
2025-09-10 9:26 ` Jonathan Cameron
@ 2025-09-11 9:56 ` Clément Le Goffic
0 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-11 9:56 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet, linux-stm32, linux-arm-kernel, linux-kernel,
linux-clk, devicetree, linux-perf-users, linux-doc,
Clément Le Goffic
On 10/09/2025 11:26, Jonathan Cameron wrote:
> On Tue, 09 Sep 2025 12:12:20 +0200
> Clément Le Goffic <legoffic.clement@gmail.com> wrote:
>
>> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>>
>> Introduce the driver for the DDR Performance Monitor available on
>> STM32MPU SoC.
>>
>> On STM32MP2 platforms, the DDRPERFM allows to monitor up to 8 DDR events
>> that come from the DDR Controller such as read or write events.
>>
>> On STM32MP1 platforms, the DDRPERFM cannot monitor any event on any
>> counter, there is a notion of set of events.
>> Events from different sets cannot be monitored at the same time.
>> The first chosen event selects the set.
>> The set is coded in the first two bytes of the config value which is on 4
>> bytes.
>>
>> On STM32MP25x series, the DDRPERFM clock is shared with the DDR controller
>> and may be secured by bootloaders.
>> Access controllers allow to check access to a resource. Use the access
>> controller defined in the devicetree to know about the access to the
>> DDRPERFM clock.
>>
>> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
>> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
> Hi Clément
>
> A quick drive by review,
>
Hi Jonathan,
Thank you for the review, below are my answers
>
>> diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c
>> new file mode 100644
>> index 000000000000..38328663d2c5
>> --- /dev/null
>> +++ b/drivers/perf/stm32_ddr_pmu.c
>> @@ -0,0 +1,897 @@
>
>> +
>> +#define MP1_CLR_CNT GENMASK(3, 0)
>> +#define MP1_CLR_TIME BIT(31)
>> +#define MP2_CLR_CNT GENMASK(7, 0)
>> +#define MP2_CLR_TIME BIT(8)
>> +
>> +/* 4 event counters plus 1 dedicated to time */
>> +#define MP1_CNT_NB (4 + 1)
>
> This is never used so I would drop it and rename the MP2_CNT_NB
> to indicate it is the max value for any devices supported.
It is used in the stm32_ddr_pmu_cfg_mp1 struct which is the device
platform data.
>
>
>> +/* Index of the time dedicated counter */
>> +#define MP1_TIME_CNT_IDX 4
>> +
>> +/* 8 event counters plus 1 dedicated to time */
>> +#define MP2_CNT_NB (8 + 1)
> ...
>
>> +struct stm32_ddr_pmu {
>> + struct pmu pmu;
>> + void __iomem *membase;
>> + struct device *dev;
>> + struct clk *clk;
>> + const struct stm32_ddr_pmu_cfg *cfg;
>> + struct hrtimer hrtimer;
>> + ktime_t poll_period;
>> + int selected_set;
>> + u32 dram_type;
>> + struct list_head counters[];
> The absence of a __counted_by() marking made me wonder how
> we ensured that this wasn't overrun. I see below that's because
> size is always the same. So
> struct list_head counters[MP2_CNT_NB];
> If you do want to make it dynamic then that is fine but added
> a local variable for the size and the __counted_by() marking so
> the various analysis tools can check for buffer overruns.
Oh I didn't know about this __counted_by compiler attribute.
I'll have a look and try to use it.
The array shouldn't have the same size basically it should depends on
the platform counters number.
There is definitely something to rework regarding the allocation.
Thank you for pointing it.
>
>> +};
>
>
>
>> +static void stm32_ddr_pmu_event_del(struct perf_event *event, int flags)
>> +{
>> + struct stm32_ddr_pmu *pmu = to_stm32_ddr_pmu(event->pmu);
>> + struct stm32_ddr_cnt *counter = event->pmu_private;
>> + bool events = true;
>
> Always set before use, so don't set it here. I'd move this into the
> scope of the for loop to make this more obvious.
Right, i'll remove the assignation.
>
>> +
>> + stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE);
>> +
>> + stm32_ddr_pmu_free_counter(pmu, counter);
>> +
>> + for (int i = 0; i < pmu->cfg->counters_nb; i++) {
>> + events = !list_empty(&pmu->counters[i]);
>> + if (events) /* If there is activity nothing to do */
>> + return;
>> + }
>> +
>> + hrtimer_cancel(&pmu->hrtimer);
>> + stm32_ddr_stop_counters(pmu);
>> +
>> + pmu->selected_set = -1;
>> +
>> + clk_disable(pmu->clk);
>> +}
>
>> +
>> +#define STM32_DDR_PMU_EVENT_ATTR(_name, _id) \
>> + PMU_EVENT_ATTR_ID(_name, stm32_ddr_pmu_sysfs_show, _id)
>> +
>> +static struct attribute *stm32_ddr_pmu_events_attrs_mp[] = {
>> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_rd, PERF_OP_IS_RD),
>
> Prefixing perf events with perf_ seems unnecessary.
>
> I guess perf_op_is_rd is counting all reads? Is so why not call it simply 'reads'
> or something else short like that? If it's cycles when a read is going on then
> maybe a more complex is needed, but perf_op_is_rd doesn't convey that to me.
Here I just extracted the name of each event from the datasheet and for
some of them there are prefixed by "perf_".
I do not have enough knowledge of the HW to just rename it read and let
other event with their "scientific name".
To me I should stick to a policy either rename all the events with
understandable names or keep all event names like this.
And I'm unable to find an understandable name for each event.
>
>> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_wr, PERF_OP_IS_WR),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_activate, PERF_OP_IS_ACTIVATE),
>> + STM32_DDR_PMU_EVENT_ATTR(ctl_idle, CTL_IDLE),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_hpr_req_with_no_credit, PERF_HPR_REQ_WITH_NO_CREDIT),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_lpr_req_with_no_credit, PERF_LPR_REQ_WITH_NO_CREDIT),
>> + STM32_DDR_PMU_EVENT_ATTR(cactive_ddrc, CACTIVE_DDRC),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_enter_powerdown, PERF_OP_IS_ENTER_POWERDOWN),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_refresh, PERF_OP_IS_REFRESH),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_selfresh_mode, PERF_SELFRESH_MODE),
>> + STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req, DFI_LP_REQ),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_hpr_xact_when_critical, PERF_HPR_XACT_WHEN_CRITICAL),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_lpr_xact_when_critical, PERF_LPR_XACT_WHEN_CRITICAL),
>> + STM32_DDR_PMU_EVENT_ATTR(perf_wr_xact_when_critical, PERF_WR_XACT_WHEN_CRITICAL),
>> + STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req_cpy, DFI_LP_REQ), /* Suffixed '_cpy' to allow the
>> + * choice between sets 2 and 3
>> + */
>> + STM32_DDR_PMU_EVENT_ATTR(time_cnt, TIME_CNT),
>> + NULL
>> +};
>
>
>> +static int stm32_ddr_pmu_device_probe(struct platform_device *pdev)
>> +{
>> + struct stm32_firewall firewall;
>> + struct stm32_ddr_pmu *pmu;
>> + struct reset_control *rst;
>> + struct resource *res;
>> + int ret;
>> +
>> + pmu = devm_kzalloc(&pdev->dev, struct_size(pmu, counters, MP2_CNT_NB), GFP_KERNEL);
>
> If using a fixed number of counters why not put it in the struct
> definition and simplify the code? I agree it is probably not
> worth making this dynamic given small sizes but I don't mind
> if you do want to do this. The only thing that isn't a good idea
> is this dynamic, but not really, current situation.
Yes something need reworks here as said above in your first comment.
I will try to find the best solution.
>
>> + if (!pmu)
>> + return -ENOMEM;
>
>
>
>> +static DEFINE_SIMPLE_DEV_PM_OPS(stm32_ddr_pmu_pm_ops, NULL, stm32_ddr_pmu_device_resume);
>> +
>> +static const struct of_device_id stm32_ddr_pmu_of_match[] = {
>> + {
>> + .compatible = "st,stm32mp131-ddr-pmu",
>> + .data = &stm32_ddr_pmu_cfg_mp1
>
> Trivial but if you are spinning again, normal convention is trailing commas
> in cases like this because maybe other fields will get set later.
Yes this is something I should keep in mind each time I init a struct.
I'll fix it for the next version.
>
>> + },
>> + {
>> + .compatible = "st,stm32mp251-ddr-pmu",
>> + .data = &stm32_ddr_pmu_cfg_mp2
>> + },
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(of, stm32_ddr_pmu_of_match);
>> +
>> +static struct platform_driver stm32_ddr_pmu_driver = {
>> + .driver = {
>> + .name = DRIVER_NAME,
>> + .pm = pm_sleep_ptr(&stm32_ddr_pmu_pm_ops),
>> + .of_match_table = stm32_ddr_pmu_of_match,
>> + },
>> + .probe = stm32_ddr_pmu_device_probe,
>> + .remove = stm32_ddr_pmu_device_remove,
>> +};
>> +
>> +module_platform_driver(stm32_ddr_pmu_driver);
>> +
>> +MODULE_AUTHOR("Clément Le Goffic");
>> +MODULE_DESCRIPTION("STMicroelectronics STM32 DDR performance monitor driver");
>> +MODULE_LICENSE("GPL");
>>
>
Best regards,
Clément
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v6 14/20] Documentation: perf: stm32: add ddrperfm support
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (12 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 15/20] MAINTAINERS: add myself as STM32 DDR PMU maintainer Clément Le Goffic
` (5 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
The DDRPERFM is the DDR Performance Monitor embedded in STM32MPU SoC.
This documentation introduces the DDRPERFM, the stm32-ddr-pmu driver
supporting it and how to use it with the perf tool.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
Documentation/admin-guide/perf/index.rst | 1 +
Documentation/admin-guide/perf/stm32-ddr-pmu.rst | 86 ++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst
index 072b510385c4..33aedc4ee5c3 100644
--- a/Documentation/admin-guide/perf/index.rst
+++ b/Documentation/admin-guide/perf/index.rst
@@ -29,3 +29,4 @@ Performance monitor support
cxl
ampere_cspmu
mrvl-pem-pmu
+ stm32-ddr-pmu
diff --git a/Documentation/admin-guide/perf/stm32-ddr-pmu.rst b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst
new file mode 100644
index 000000000000..5b02bf44dd7a
--- /dev/null
+++ b/Documentation/admin-guide/perf/stm32-ddr-pmu.rst
@@ -0,0 +1,86 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========================================
+STM32 DDR Performance Monitor (DDRPERFM)
+========================================
+
+The DDRPERFM is the DDR Performance Monitor embedded in STM32MPU SoC.
+The DDR controller provides events to DDRPERFM, once selected they are counted in the DDRPERFM
+peripheral.
+
+In MP1 family, the DDRPERFM is able to count 4 different events at the same time.
+However, the 4 events must belong to the same set.
+One hardware counter is dedicated to the time counter, `time_cnt`.
+
+In MP2 family, the DDRPERFM is able to select between 44 different DDR events.
+As for MP1, there is a dedicated hardware counter for the time.
+It is incremented every 4 DDR clock cycles.
+All the other counters can be freely allocated to count any other DDR event.
+
+The stm32-ddr-pmu driver relies on the perf PMU framework to expose the counters via sysfs:
+
+On MP1:
+
+ .. code-block:: bash
+
+ $ ls /sys/bus/event_source/devices/stm32_ddr_pmu/events/
+ cactive_ddrc perf_lpr_req_with_no_credit perf_op_is_wr
+ ctl_idle perf_lpr_xact_when_critical perf_selfresh_mode
+ dfi_lp_req perf_op_is_activate perf_wr_xact_when_critical
+ dfi_lp_req_cpy perf_op_is_enter_powerdown time_cnt
+ perf_hpr_req_with_no_credit perf_op_is_rd
+ perf_hpr_xact_when_critical perf_op_is_refresh
+
+On MP2:
+
+ .. code-block:: bash
+
+ $ ls /sys/bus/event_source/devices/stm32_ddr_pmu/events/
+ dfi_is_act perf_hpr_req_with_nocredit perf_op_is_spec_ref
+ dfi_is_mpc perf_hpr_xact_when_critical perf_op_is_wr
+ dfi_is_mrr perf_lpr_req_with_nocredit perf_op_is_zqcal
+ dfi_is_mrw perf_lpr_xact_when_critical perf_rank
+ dfi_is_mwr perf_op_is_act perf_raw_hazard
+ dfi_is_mwra perf_op_is_crit_ref perf_rdwr_transitions
+ dfi_is_preab perf_op_is_enter_powdn perf_read_bypass
+ dfi_is_prepb perf_op_is_enter_selfref perf_war_hazard
+ dfi_is_rd perf_op_is_mwr perf_waw_hazard
+ dfi_is_rda perf_op_is_pre perf_window_limit_reached_rd
+ dfi_is_refab perf_op_is_pre_for_others perf_window_limit_reached_wr
+ dfi_is_refpb perf_op_is_pre_for_rdwr perf_wr_xact_when_critical
+ dfi_is_wr perf_op_is_rd time_cnt
+ dfi_is_wra perf_op_is_rd_activate
+ perf_act_bypass perf_op_is_ref
+
+
+The perf PMU framework is usually invoked via the 'perf stat' tool.
+
+
+Example:
+
+ .. code-block:: bash
+
+ $ perf stat --timeout 60000 -e stm32_ddr_pmu/dfi_is_act/,\
+ > stm32_ddr_pmu/dfi_is_rd/,\
+ > stm32_ddr_pmu/dfi_is_wr/,\
+ > stm32_ddr_pmu/dfi_is_refab/,\
+ > stm32_ddr_pmu/dfi_is_mrw/,\
+ > stm32_ddr_pmu/dfi_is_rda/,\
+ > stm32_ddr_pmu/dfi_is_wra/,\
+ > stm32_ddr_pmu/dfi_is_mrr/,\
+ > stm32_ddr_pmu/time_cnt/ \
+ > -a sleep 5
+
+ Performance counter stats for 'system wide':
+
+ 481025 stm32_ddr_pmu/dfi_is_act/
+ 732166 stm32_ddr_pmu/dfi_is_rd/
+ 144926 stm32_ddr_pmu/dfi_is_wr/
+ 644154 stm32_ddr_pmu/dfi_is_refab/
+ 0 stm32_ddr_pmu/dfi_is_mrw/
+ 0 stm32_ddr_pmu/dfi_is_rda/
+ 0 stm32_ddr_pmu/dfi_is_wra/
+ 0 stm32_ddr_pmu/dfi_is_mrr/
+ 752347686 stm32_ddr_pmu/time_cnt/
+
+ 5.014910750 seconds time elapsed
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 15/20] MAINTAINERS: add myself as STM32 DDR PMU maintainer
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (13 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 14/20] Documentation: perf: stm32: add ddrperfm support Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 16/20] ARM: dts: stm32: add ddrperfm on stm32mp131 Clément Le Goffic
` (4 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Add Clément Le Goffic as STM32 DDR PMU maintainer.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index cd7ff55b5d32..a35c48ae925f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23865,6 +23865,13 @@ S: Maintained
F: Documentation/devicetree/bindings/power/supply/st,stc3117.yaml
F: drivers/power/supply/stc3117_fuel_gauge.c
+ST STM32 DDR PMU
+M: Clément Le Goffic <legoffic.clement@gmail.com>
+S: Maintained
+F: Documentation/admin-guide/perf/stm32-ddr-pmu.rst
+F: Documentation/devicetree/bindings/perf/st,stm32-ddr-pmu.yaml
+F: drivers/perf/stm32_ddr-pmu.c
+
ST STM32 FIREWALL
M: Gatien Chevallier <gatien.chevallier@foss.st.com>
S: Maintained
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 16/20] ARM: dts: stm32: add ddrperfm on stm32mp131
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (14 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 15/20] MAINTAINERS: add myself as STM32 DDR PMU maintainer Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 17/20] ARM: dts: stm32: add ddrperfm on stm32mp151 Clément Le Goffic
` (3 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
The DDRPERFM is the DDR Performance Monitor embedded in STM32MP131 SoC.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm/boot/dts/st/stm32mp131.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/st/stm32mp131.dtsi b/arch/arm/boot/dts/st/stm32mp131.dtsi
index ace9495b9b06..7ef3931fd6c5 100644
--- a/arch/arm/boot/dts/st/stm32mp131.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp131.dtsi
@@ -998,6 +998,13 @@ iwdg2: watchdog@5a002000 {
status = "disabled";
};
+ ddrperfm: perf@5a007000 {
+ compatible = "st,stm32mp131-ddr-pmu";
+ reg = <0x5a007000 0x400>;
+ clocks = <&rcc DDRPERFM>;
+ resets = <&rcc DDRPERFM_R>;
+ };
+
rtc: rtc@5c004000 {
compatible = "st,stm32mp1-rtc";
reg = <0x5c004000 0x400>;
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 17/20] ARM: dts: stm32: add ddrperfm on stm32mp151
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (15 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 16/20] ARM: dts: stm32: add ddrperfm on stm32mp131 Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 18/20] arm64: dts: st: add ddrperfm on stm32mp251 Clément Le Goffic
` (2 subsequent siblings)
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
The DDRPERFM is the DDR Performance Monitor embedded in STM32MP151 SoC.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm/boot/dts/st/stm32mp151.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/st/stm32mp151.dtsi b/arch/arm/boot/dts/st/stm32mp151.dtsi
index 0daa8ffe2ff5..e121de52a054 100644
--- a/arch/arm/boot/dts/st/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp151.dtsi
@@ -383,6 +383,13 @@ usbphyc_port1: usb-phy@1 {
};
};
+ ddrperfm: perf@5a007000 {
+ compatible = "st,stm32mp151-ddr-pmu", "st,stm32mp131-ddr-pmu";
+ reg = <0x5a007000 0x400>;
+ clocks = <&rcc DDRPERFM>;
+ resets = <&rcc DDRPERFM_R>;
+ };
+
rtc: rtc@5c004000 {
compatible = "st,stm32mp1-rtc";
reg = <0x5c004000 0x400>;
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 18/20] arm64: dts: st: add ddrperfm on stm32mp251
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (16 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 17/20] ARM: dts: stm32: add ddrperfm on stm32mp151 Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 19/20] arm64: dts: st: support ddrperfm on stm32mp257f-dk Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 20/20] arm64: dts: st: support ddrperfm on stm32mp257f-ev1 Clément Le Goffic
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
The DDRPERFM is the DDR Performance Monitor embedded in STM32MP251 SoC.
Keep the node disabled at SoC level as it requires the property
`st,dram-type` which is provided in board dtsi file.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm64/boot/dts/st/stm32mp251.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index fbedf23def52..69f0276d3324 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -2100,5 +2100,12 @@ exti2: interrupt-controller@46230000 {
<0>,
<&intc GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>; /* EXTI_70 */
};
+
+ ddrperfm: perf@48041000 {
+ compatible = "st,stm32mp251-ddr-pmu";
+ reg = <0x48041000 0x400>;
+ access-controllers = <&rcc 104>;
+ status = "disabled";
+ };
};
};
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 19/20] arm64: dts: st: support ddrperfm on stm32mp257f-dk
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (17 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 18/20] arm64: dts: st: add ddrperfm on stm32mp251 Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 20/20] arm64: dts: st: support ddrperfm on stm32mp257f-ev1 Clément Le Goffic
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Configure DDRPERFM node on stm32mp257f-dk board.
Disable the node as DDRPERFM will produce an error message if it's clock
(shared with the DDRCTRL on STM32MP25x) is secured by common bootloaders.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm64/boot/dts/st/stm32mp257f-dk.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-dk.dts b/arch/arm64/boot/dts/st/stm32mp257f-dk.dts
index 45ffa358c800..81b115280bd4 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-dk.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-dk.dts
@@ -84,6 +84,11 @@ &arm_wdt {
status = "okay";
};
+&ddrperfm {
+ memory-channel = <&lpddr_channel>;
+ status = "disabled";
+};
+
&scmi_regu {
scmi_vddio1: regulator@0 {
regulator-min-microvolt = <1800000>;
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v6 20/20] arm64: dts: st: support ddrperfm on stm32mp257f-ev1
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
` (18 preceding siblings ...)
2025-09-09 10:12 ` [PATCH v6 19/20] arm64: dts: st: support ddrperfm on stm32mp257f-dk Clément Le Goffic
@ 2025-09-09 10:12 ` Clément Le Goffic
19 siblings, 0 replies; 36+ messages in thread
From: Clément Le Goffic @ 2025-09-09 10:12 UTC (permalink / raw)
To: Gatien Chevallier, Maxime Coquelin, Alexandre Torgue,
Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Gabriel Fernandez, Krzysztof Kozlowski,
Julius Werner, Will Deacon, Mark Rutland, Philipp Zabel,
Jonathan Corbet
Cc: linux-stm32, linux-arm-kernel, linux-kernel, linux-clk,
devicetree, linux-perf-users, linux-doc, Clément Le Goffic,
Clément Le Goffic
From: Clément Le Goffic <clement.legoffic@foss.st.com>
Configure DDRPERFM node on stm32mp257f-ev1 board.
Disable the node as DDRPERFM will produce an error message if it's clock
(shared with the DDRCTRL on STM32MP25x) is secured by common bootloaders.
Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
---
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index c4223f06396a..c685a646a21b 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -130,6 +130,11 @@ csi_source: endpoint {
};
};
+&ddrperfm {
+ memory-channel = <&ddr_channel>;
+ status = "disabled";
+};
+
&dcmipp {
status = "okay";
port {
--
2.43.0
^ permalink raw reply related [flat|nested] 36+ messages in thread