* [PATCH v2] cpupower: remove extern declarations in cmd functions
From: Kaushlendra Kumar @ 2026-04-02 16:15 UTC (permalink / raw)
To: shuah, jwyatt, jkacur; +Cc: linux-pm, Kaushlendra Kumar
extern char *optarg and extern int optind, opterr, optopt are
already declared by <getopt.h>, which is included at the top of
the file. Repeating extern declarations inside a function body
is misleading and unnecessary.
Signed-off-by: Kaushlendra Kumar <kaushlendra.kumar@intel.com>
---
v2: Extended the fix to all cmd functions across cpupower utils
tools/power/cpupower/utils/cpufreq-info.c | 2 --
tools/power/cpupower/utils/cpufreq-set.c | 2 --
tools/power/cpupower/utils/cpuidle-info.c | 2 --
tools/power/cpupower/utils/cpuidle-set.c | 2 --
tools/power/cpupower/utils/cpupower-info.c | 2 --
tools/power/cpupower/utils/cpupower-set.c | 2 --
6 files changed, 12 deletions(-)
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index 5fe01e516817..5a242b491a9d 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -542,8 +542,6 @@ static struct option info_opts[] = {
int cmd_freq_info(int argc, char **argv)
{
- extern char *optarg;
- extern int optind, opterr, optopt;
int ret = 0, cont = 1;
unsigned int cpu = 0;
unsigned int human = 0;
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
index c5e60a39cfa6..06cd4b280132 100644
--- a/tools/power/cpupower/utils/cpufreq-set.c
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -195,8 +195,6 @@ static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
int cmd_freq_set(int argc, char **argv)
{
- extern char *optarg;
- extern int optind, opterr, optopt;
int ret = 0, cont = 1;
int double_parm = 0, related = 0, policychange = 0;
unsigned long freq = 0;
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index 81b4763a97d6..ccb37125bd37 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -139,8 +139,6 @@ static inline void cpuidle_exit(int fail)
int cmd_idle_info(int argc, char **argv)
{
- extern char *optarg;
- extern int optind, opterr, optopt;
int ret = 0, cont = 1, output_param = 0, verbose = 1;
unsigned int cpu = 0;
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c
index a551d1d4ac51..703094f1343c 100644
--- a/tools/power/cpupower/utils/cpuidle-set.c
+++ b/tools/power/cpupower/utils/cpuidle-set.c
@@ -24,8 +24,6 @@ static struct option info_opts[] = {
int cmd_idle_set(int argc, char **argv)
{
- extern char *optarg;
- extern int optind, opterr, optopt;
int ret = 0, cont = 1, param = 0, disabled;
unsigned long long latency = 0, state_latency;
unsigned int cpu = 0, idlestate = 0, idlestates = 0;
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c
index 18fd7751f509..79154d71e498 100644
--- a/tools/power/cpupower/utils/cpupower-info.c
+++ b/tools/power/cpupower/utils/cpupower-info.c
@@ -28,8 +28,6 @@ static void print_wrong_arg_exit(void)
int cmd_info(int argc, char **argv)
{
- extern char *optarg;
- extern int optind, opterr, optopt;
unsigned int cpu;
struct utsname uts;
diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c
index 550a942e72ce..c2176b9fa57d 100644
--- a/tools/power/cpupower/utils/cpupower-set.c
+++ b/tools/power/cpupower/utils/cpupower-set.c
@@ -33,8 +33,6 @@ static void print_wrong_arg_exit(void)
int cmd_set(int argc, char **argv)
{
- extern char *optarg;
- extern int optind, opterr, optopt;
unsigned int cpu;
struct utsname uts;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] MAINTAINERS: amd-pstate: Step down as maintainer, add Prateek as reviewer
From: Mario Limonciello @ 2026-04-02 16:09 UTC (permalink / raw)
To: Gautham R. Shenoy
Cc: linux-pm, linux-kernel, gautham.shenoy, K Prateek Nayak, rafael,
viresh.kumar, ray.huang, perry.yuan
In-Reply-To: <31d6da20-c0d8-4ccf-90e0-7484e6f07264@amd.com>
On 4/2/26 6:21 AM, K Prateek Nayak wrote:
> Hello Gautham,
>
> On 4/2/2026 3:56 PM, Gautham R. Shenoy wrote:
>> Mario Limonciello has led amd-pstate maintenance in recent years and
>> has done excellent work. The amd-pstate driver is in good hands with
>> him. I am stepping down as co-maintainer as I move on to other things.
>
> Thank you for helping build the strong foundations that amd-pstate rests
> on. What was once a house of cards is now a fortress thanks to all your
> hard work!
>
> _I'm not crying. Just sweating from my eyes_
>
>>
>> Add K Prateek Nayak as a reviewer. He has been actively contributing
>> to the driver including preferred-core and ITMT improvements, and has
>> been helping review amd-pstate patches for a while now.
>>
>> Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
>
> Acked-by: K Prateek Nayak <kprateek.nayak@amd.com>
>
If I don't Ack, you have to stay right?
But seriously, thank you for all your contributions.
Acked-by: Mario Limonciello (AMD) <superm1@kernel.org>
^ permalink raw reply
* Re: [PATCH] interconnect: debugfs: fix devm_kstrdup and kfree mismatch
From: Georgi Djakov @ 2026-04-02 16:00 UTC (permalink / raw)
To: Gui-Dong Han; +Cc: Kuan-Wei Chiu, linux-pm, linux-kernel, akaieurus, me
In-Reply-To: <CALbr=LYyNh0AwC+8ni6iS=9UiTyVz9+r_gM7M=ohacCv97ujOw@mail.gmail.com>
On 4/2/26 6:42 PM, Gui-Dong Han wrote:
> On Wed, Mar 18, 2026 at 10:48 AM Gui-Dong Han <hanguidong02@gmail.com> wrote:
>>
>> debugfs_write_file_str() uses standard kfree() to release old strings.
>> Initializing src_node and dst_node with devm_kstrdup() creates a memory
>> management mismatch. If a user writes to these debugfs nodes, the
>> devm-allocated memory is freed via kfree(), leaving a dangling pointer
>> in the device resource list that can lead to a double free.
>>
>> Fix this by using standard kstrdup() instead. Since the interconnect
>> subsystem is strictly built-in and cannot be unloaded as a module, there
>> is no exit path requiring manual cleanup of these strings. The error
>> handling path is also simplified by taking advantage of the fact that
>> kfree(NULL) is a safe no-op.
>>
>> Fixes: 8cc27f5c6dd1 ("interconnect: debugfs: initialize src_node and dst_node to empty strings")
>> Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com>
>> ---
>> I noticed this memory management mismatch while working on similar
>> debugfs string initialization fixes [1] recently.
>>
>> [1] https://lore.kernel.org/driver-core/20260317185920.43387-1-hanguidong02@gmail.com/
>
> Hello Georgi,
>
> Gentle ping on this patch.
>
> Just wanted to note that my other related fix has already been accepted [1].
>
> Could you please let me know if this fell through the cracks, or if
> you have any feedback or modification requests? I'd be very happy to
> address them.
Hello,
Thanks for the patch! I applied it already and it's available in today's linux-next.
Thanks,
Georgi
^ permalink raw reply
* RE: [PATCH] cpupower: remove extern declarations in cmd_set()
From: Kumar, Kaushlendra @ 2026-04-02 15:45 UTC (permalink / raw)
To: Shuah Khan, shuah@kernel.org, jwyatt@redhat.com,
jkacur@redhat.com
Cc: linux-pm@vger.kernel.org
In-Reply-To: <f0bcad85-81e9-451d-8267-729b60531590@linuxfoundation.org>
> There are a few other places in cpupower that can be fixed. Send me a
> patch that removes just the extern declarations without the
> parse_int_range() stuff
>
> extern char *optarg;
> extern int optind, opterr, optopt;
Sure, will do.
Thanks,
Kaushlendra
^ permalink raw reply
* Re: [PATCH] interconnect: debugfs: fix devm_kstrdup and kfree mismatch
From: Gui-Dong Han @ 2026-04-02 15:42 UTC (permalink / raw)
To: Georgi Djakov; +Cc: Kuan-Wei Chiu, linux-pm, linux-kernel, akaieurus, me
In-Reply-To: <20260318024815.7655-1-hanguidong02@gmail.com>
On Wed, Mar 18, 2026 at 10:48 AM Gui-Dong Han <hanguidong02@gmail.com> wrote:
>
> debugfs_write_file_str() uses standard kfree() to release old strings.
> Initializing src_node and dst_node with devm_kstrdup() creates a memory
> management mismatch. If a user writes to these debugfs nodes, the
> devm-allocated memory is freed via kfree(), leaving a dangling pointer
> in the device resource list that can lead to a double free.
>
> Fix this by using standard kstrdup() instead. Since the interconnect
> subsystem is strictly built-in and cannot be unloaded as a module, there
> is no exit path requiring manual cleanup of these strings. The error
> handling path is also simplified by taking advantage of the fact that
> kfree(NULL) is a safe no-op.
>
> Fixes: 8cc27f5c6dd1 ("interconnect: debugfs: initialize src_node and dst_node to empty strings")
> Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com>
> ---
> I noticed this memory management mismatch while working on similar
> debugfs string initialization fixes [1] recently.
>
> [1] https://lore.kernel.org/driver-core/20260317185920.43387-1-hanguidong02@gmail.com/
Hello Georgi,
Gentle ping on this patch.
Just wanted to note that my other related fix has already been accepted [1].
Could you please let me know if this fell through the cracks, or if
you have any feedback or modification requests? I'd be very happy to
address them.
Thanks.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git/commit/?h=driver-core-testing&id=31de83980d37
> ---
> drivers/interconnect/debugfs-client.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/interconnect/debugfs-client.c b/drivers/interconnect/debugfs-client.c
> index 5107bff53173..08df9188ef94 100644
> --- a/drivers/interconnect/debugfs-client.c
> +++ b/drivers/interconnect/debugfs-client.c
> @@ -150,10 +150,13 @@ int icc_debugfs_client_init(struct dentry *icc_dir)
> return ret;
> }
>
> - src_node = devm_kstrdup(&pdev->dev, "", GFP_KERNEL);
> - dst_node = devm_kstrdup(&pdev->dev, "", GFP_KERNEL);
> - if (!src_node || !dst_node)
> + src_node = kstrdup("", GFP_KERNEL);
> + dst_node = kstrdup("", GFP_KERNEL);
> + if (!src_node || !dst_node) {
> + kfree(dst_node);
> + kfree(src_node);
> return -ENOMEM;
> + }
>
> client_dir = debugfs_create_dir("test_client", icc_dir);
>
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH] power: sequencing: pcie-m2: add SERIAL_DEV_BUS dependency
From: Arnd Bergmann @ 2026-04-02 15:42 UTC (permalink / raw)
To: Bartosz Golaszewski, Arnd Bergmann
Cc: Manivannan Sadhasivam, Ulf Hansson, Michal Wilczynski, linux-pm,
linux-kernel
In-Reply-To: <CAMRc=Meu4DjZ0=r1FRnBGXGN67VxK74x3AjO_T0J7NcA6koCRQ@mail.gmail.com>
On Thu, Apr 2, 2026, at 17:38, Bartosz Golaszewski wrote:
> On Wed, Apr 1, 2026 at 9:10 PM Arnd Bergmann <arnd@kernel.org> wrote:
>> diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
>> index 77c6d9227251..1c5f5820f5b7 100644
>> --- a/drivers/power/sequencing/Kconfig
>> +++ b/drivers/power/sequencing/Kconfig
>> @@ -39,6 +39,7 @@ config POWER_SEQUENCING_PCIE_M2
>> tristate "PCIe M.2 connector power sequencing driver"
>> depends on OF
>> depends on PCI
>> + depends on SERIAL_DEV_BUS
>> select OF_DYNAMIC
>> help
>> Say Y here to enable the power sequencing driver for PCIe M.2
>> --
>> 2.39.5
>>
>
> I assume with this patch[1] from Mani, we no longer need this one?
>
> [1]
> https://lore.kernel.org/all/20260401070735.107162-2-manivannan.sadhasivam@oss.qualcomm.com/
Depends on which one you mean with 'this one'.
My patch is needed with or without Mani's, while
his patch is harmless but does not fix the issue.
Arnd
^ permalink raw reply
* Re: [PATCH 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Neil Armstrong @ 2026-04-02 15:39 UTC (permalink / raw)
To: Ronald Claveau, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-5-2b12eb4ac7b0@aliel.fr>
On 4/2/26 16:27, Ronald Claveau wrote:
> Replace the hardcoded MAX_LEVEL constant and fan register
> with values read from platform_data (fan_reg, max_level),
> as new MCUs need different values.
>
> Optionally acquire and enable a "fan" regulator supply
> at probe time and on resume,
> so boards that gate fan power through a regulator are handled.
>
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
> drivers/thermal/khadas_mcu_fan.c | 43 ++++++++++++++++++++++++++++++++++------
> 1 file changed, 37 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
> index d35e5313bea41..55b496625e3bd 100644
> --- a/drivers/thermal/khadas_mcu_fan.c
> +++ b/drivers/thermal/khadas_mcu_fan.c
> @@ -13,13 +13,15 @@
> #include <linux/regmap.h>
> #include <linux/sysfs.h>
> #include <linux/thermal.h>
> -
> -#define MAX_LEVEL 3
> +#include <linux/regulator/consumer.h>
>
> struct khadas_mcu_fan_ctx {
> struct khadas_mcu *mcu;
> + unsigned int fan_reg;
> unsigned int level;
> + unsigned int max_level;
> struct thermal_cooling_device *cdev;
> + struct regulator *power;
> };
>
> static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
> @@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
> {
> int ret;
>
> - ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
> - level);
> + ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
> if (ret)
> return ret;
>
> @@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
> static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
> unsigned long *state)
> {
> - *state = MAX_LEVEL;
> + struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
> +
> + *state = ctx->max_level;
>
> return 0;
> }
> @@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
> {
> struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
>
> - if (state > MAX_LEVEL)
> + if (state > ctx->max_level)
> return -EINVAL;
>
> if (state == ctx->level)
> @@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> struct khadas_mcu_fan_ctx *ctx;
> int ret;
> + const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
>
> ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
> if (!ctx)
> return -ENOMEM;
> +
> ctx->mcu = mcu;
> + ctx->fan_reg = pdata->fan_reg;
> + ctx->max_level = pdata->max_level;
> +
> + ctx->power = devm_regulator_get_optional(dev->parent, "fan");
> + if (IS_ERR(ctx->power)) {
> + if (PTR_ERR(ctx->power) == -ENODEV)
> + ctx->power = NULL;
> + else
> + return PTR_ERR(ctx->power);
> + }
> +
> + if (ctx->power) {
> + ret = regulator_enable(ctx->power);
> + if (ret) {
> + dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
> + return ret;
> + }
> + }
> +
> platform_set_drvdata(pdev, ctx);
>
> cdev = devm_thermal_of_cooling_device_register(dev->parent,
> @@ -130,6 +154,13 @@ static int khadas_mcu_fan_suspend(struct device *dev)
> static int khadas_mcu_fan_resume(struct device *dev)
> {
> struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
> + int ret;
> +
> + if (ctx->power) {
> + ret = regulator_enable(ctx->power);
Seems you're missing a regulator_disable() on suspend.
Neil
> + if (ret)
> + return ret;
> + }
>
> return khadas_mcu_fan_set_level(ctx, ctx->level);
> }
>
^ permalink raw reply
* Re: [PATCH] power: sequencing: pcie-m2: add SERIAL_DEV_BUS dependency
From: Bartosz Golaszewski @ 2026-04-02 15:38 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Manivannan Sadhasivam, Arnd Bergmann, Ulf Hansson,
Michal Wilczynski, linux-pm, linux-kernel
In-Reply-To: <20260401191030.948046-1-arnd@kernel.org>
On Wed, Apr 1, 2026 at 9:10 PM Arnd Bergmann <arnd@kernel.org> wrote:
>
> From: Arnd Bergmann <arnd@arndb.de>
>
> The newly added serdev code fails to link when serdev is turned off:
>
> arm-linux-gnueabi-ld: drivers/power/sequencing/pwrseq-pcie-m2.o: in function `pwrseq_pcie_m2_remove_serdev':
> pwrseq-pcie-m2.c:(.text+0xc8): undefined reference to `serdev_device_remove'
> arm-linux-gnueabi-ld: drivers/power/sequencing/pwrseq-pcie-m2.o: in function `pwrseq_m2_pcie_notify':
> pwrseq-pcie-m2.c:(.text+0x69c): undefined reference to `of_find_serdev_controller_by_node'
> arm-linux-gnueabi-ld: pwrseq-pcie-m2.c:(.text+0x6f8): undefined reference to `serdev_device_alloc'
> arm-linux-gnueabi-ld: pwrseq-pcie-m2.c:(.text+0x724): undefined reference to `serdev_device_add'
>
> Add another Kconfig dependency for this
>
> Fixes: 3f736aecbdc8 ("power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> I noticed this one only after I had already sent the patch to add the other
> two dependency, feel free to combine the patches into one
> ---
> drivers/power/sequencing/Kconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
> index 77c6d9227251..1c5f5820f5b7 100644
> --- a/drivers/power/sequencing/Kconfig
> +++ b/drivers/power/sequencing/Kconfig
> @@ -39,6 +39,7 @@ config POWER_SEQUENCING_PCIE_M2
> tristate "PCIe M.2 connector power sequencing driver"
> depends on OF
> depends on PCI
> + depends on SERIAL_DEV_BUS
> select OF_DYNAMIC
> help
> Say Y here to enable the power sequencing driver for PCIe M.2
> --
> 2.39.5
>
I assume with this patch[1] from Mani, we no longer need this one?
Bart
[1] https://lore.kernel.org/all/20260401070735.107162-2-manivannan.sadhasivam@oss.qualcomm.com/
^ permalink raw reply
* Re: [PATCH v10 6/6] usb: typec: tcpm/tcpci_maxim: deprecate WAR for setting charger mode
From: Heikki Krogerus @ 2026-04-02 14:33 UTC (permalink / raw)
To: amitsd
Cc: André Draszik, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Greg Kroah-Hartman, Jagan Sridharan, Mark Brown,
Matti Vaittinen, Andrew Morton, Sebastian Reichel, Peter Griffin,
Tudor Ambarus, Alim Akhtar, linux-kernel, devicetree, linux-usb,
linux-pm, linux-arm-kernel, linux-samsung-soc, RD Babiera,
Kyle Tso
In-Reply-To: <20260331-max77759-charger-v10-6-76f59233c369@google.com>
Hi Amit,
> +static int get_vbus_regulator_handle(struct max_tcpci_chip *chip)
> +{
> + if (IS_ERR_OR_NULL(chip->vbus_reg)) {
> + chip->vbus_reg = devm_regulator_get_exclusive(chip->dev,
> + "vbus");
Sorry to go back to this, but why can't you just get the regulator in
max_tcpci_probe()?
thanks,
> + if (IS_ERR_OR_NULL(chip->vbus_reg)) {
> + dev_err(chip->dev,
> + "Failed to get vbus regulator handle\n");
> + return -ENODEV;
> + }
> + }
> +
> + return 0;
> +}
--
heikki
^ permalink raw reply
* [PATCH 8/8] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Enable and configure i2c MCU node to get fan working on Khadas VIM4.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index 69d6118ba57e7..5d7f5390f3a66 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -157,6 +157,19 @@ wifi32k: wifi32k {
};
};
+&i2c_m_ao_a {
+ status = "okay";
+ pinctrl-0 = <&i2c0_ao_d_pins>;
+ pinctrl-names = "default";
+
+ khadas_mcu: system-controller@18 {
+ compatible = "khadas,vim4-mcu";
+ reg = <0x18>;
+ fan-supply = <&vcc5v>;
+ #cooling-cells = <2>;
+ };
+};
+
&pwm_ab {
status = "okay";
pinctrl-0 = <&pwm_a_pins>;
--
2.49.0
^ permalink raw reply related
* [PATCH 4/8] mfd: khadas-mcu: Add support for VIM4 MCU variant
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Refactor probe() to use per-variant khadas_mcu_data
instead of hardcoded globals.
Add dedicated regmap configuration and device data for the VIM4 MCU,
with its own volatile/writeable registers.
Add the fan control register
(0–100 levels vs 0–3 for previous supported boards).
Add a new compatible string "khadas,vim4-mcu".
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/mfd/khadas-mcu.c | 106 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 95 insertions(+), 11 deletions(-)
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index ba981a7886921..b36b3b3ab73c0 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -75,15 +75,91 @@ static const struct regmap_config khadas_mcu_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
+static const struct khadas_mcu_fan_pdata khadas_mcu_fan_pdata = {
+ .fan_reg = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
+ .max_level = 3,
+};
+
static struct mfd_cell khadas_mcu_fan_cells[] = {
/* VIM1/2 Rev13+ and VIM3 only */
- { .name = "khadas-mcu-fan-ctrl", },
+ {
+ .name = "khadas-mcu-fan-ctrl",
+ .platform_data = &khadas_mcu_fan_pdata,
+ .pdata_size = sizeof(khadas_mcu_fan_pdata),
+ },
};
static struct mfd_cell khadas_mcu_cells[] = {
{ .name = "khadas-mcu-user-mem", },
};
+static const struct khadas_mcu_data khadas_mcu_data = {
+ .regmap_config = &khadas_mcu_regmap_config,
+ .cells = khadas_mcu_cells,
+ .ncells = ARRAY_SIZE(khadas_mcu_cells),
+ .fan_cells = khadas_mcu_fan_cells,
+ .nfan_cells = ARRAY_SIZE(khadas_mcu_fan_cells),
+};
+
+static bool khadas_mcu_vim4_reg_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case KHADAS_MCU_PWR_OFF_CMD_REG:
+ case KHADAS_MCU_VIM4_REST_CONF_REG:
+ case KHADAS_MCU_WOL_INIT_START_REG:
+ case KHADAS_MCU_VIM4_LED_ON_RAM_REG:
+ case KHADAS_MCU_VIM4_FAN_CTRL_REG:
+ case KHADAS_MCU_VIM4_WDT_EN_REG:
+ case KHADAS_MCU_VIM4_SYS_RST_REG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool khadas_mcu_vim4_reg_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case KHADAS_MCU_VERSION_0_REG:
+ case KHADAS_MCU_VERSION_1_REG:
+ case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static const struct regmap_config khadas_mcu_vim4_regmap_config = {
+ .reg_bits = 8,
+ .reg_stride = 1,
+ .val_bits = 8,
+ .max_register = KHADAS_MCU_VIM4_SYS_RST_REG,
+ .volatile_reg = khadas_mcu_vim4_reg_volatile,
+ .writeable_reg = khadas_mcu_vim4_reg_writeable,
+ .cache_type = REGCACHE_MAPLE,
+};
+
+static const struct khadas_mcu_fan_pdata khadas_vim4_fan_pdata = {
+ .fan_reg = KHADAS_MCU_VIM4_FAN_CTRL_REG,
+ .max_level = 0x64,
+};
+
+static const struct mfd_cell khadas_mcu_vim4_cells[] = {
+ {
+ .name = "khadas-mcu-fan-ctrl",
+ .platform_data = &khadas_vim4_fan_pdata,
+ .pdata_size = sizeof(khadas_vim4_fan_pdata),
+ },
+};
+
+static const struct khadas_mcu_data khadas_vim4_mcu_data = {
+ .regmap_config = &khadas_mcu_vim4_regmap_config,
+ .cells = NULL,
+ .ncells = 0,
+ .fan_cells = khadas_mcu_vim4_cells,
+ .nfan_cells = ARRAY_SIZE(khadas_mcu_vim4_cells),
+};
+
static int khadas_mcu_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -94,28 +170,35 @@ static int khadas_mcu_probe(struct i2c_client *client)
if (!ddata)
return -ENOMEM;
+ ddata->data = i2c_get_match_data(client);
+ if (!ddata->data)
+ return -EINVAL;
+
i2c_set_clientdata(client, ddata);
ddata->dev = dev;
- ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
+ ddata->regmap = devm_regmap_init_i2c(client,
+ ddata->data->regmap_config);
if (IS_ERR(ddata->regmap)) {
ret = PTR_ERR(ddata->regmap);
dev_err(dev, "Failed to allocate register map: %d\n", ret);
return ret;
}
- ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- khadas_mcu_cells,
- ARRAY_SIZE(khadas_mcu_cells),
- NULL, 0, NULL);
- if (ret)
- return ret;
+ if (ddata->data->cells && ddata->data->ncells) {
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+ ddata->data->cells,
+ ddata->data->ncells,
+ NULL, 0, NULL);
+ if (ret)
+ return ret;
+ }
if (of_property_present(dev->of_node, "#cooling-cells"))
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- khadas_mcu_fan_cells,
- ARRAY_SIZE(khadas_mcu_fan_cells),
+ ddata->data->fan_cells,
+ ddata->data->nfan_cells,
NULL, 0, NULL);
return 0;
@@ -123,7 +206,8 @@ static int khadas_mcu_probe(struct i2c_client *client)
#ifdef CONFIG_OF
static const struct of_device_id khadas_mcu_of_match[] = {
- { .compatible = "khadas,mcu", },
+ { .compatible = "khadas,mcu", .data = &khadas_mcu_data },
+ { .compatible = "khadas,vim4-mcu", .data = &khadas_vim4_mcu_data },
{},
};
MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);
--
2.49.0
^ permalink raw reply related
* [PATCH 6/8] arm64: dts: amlogic: t7: Add i2c pinctrl node
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Add the T7 pinctrl used by the Khadas VIM4 for MCU communication.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index 7fe72c94ed623..e96fe10b251a0 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -376,6 +376,16 @@ mux {
};
};
+ i2c0_ao_d_pins: i2c0-ao-d {
+ mux {
+ groups = "i2c0_ao_sck_d",
+ "i2c0_ao_sda_d";
+ function = "i2c0_ao";
+ bias-disable;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
pwm_a_pins: pwm-a {
mux {
groups = "pwm_a";
--
2.49.0
^ permalink raw reply related
* [PATCH 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Replace the hardcoded MAX_LEVEL constant and fan register
with values read from platform_data (fan_reg, max_level),
as new MCUs need different values.
Optionally acquire and enable a "fan" regulator supply
at probe time and on resume,
so boards that gate fan power through a regulator are handled.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/thermal/khadas_mcu_fan.c | 43 ++++++++++++++++++++++++++++++++++------
1 file changed, 37 insertions(+), 6 deletions(-)
diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
index d35e5313bea41..55b496625e3bd 100644
--- a/drivers/thermal/khadas_mcu_fan.c
+++ b/drivers/thermal/khadas_mcu_fan.c
@@ -13,13 +13,15 @@
#include <linux/regmap.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
-
-#define MAX_LEVEL 3
+#include <linux/regulator/consumer.h>
struct khadas_mcu_fan_ctx {
struct khadas_mcu *mcu;
+ unsigned int fan_reg;
unsigned int level;
+ unsigned int max_level;
struct thermal_cooling_device *cdev;
+ struct regulator *power;
};
static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
@@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
{
int ret;
- ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
- level);
+ ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
if (ret)
return ret;
@@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
- *state = MAX_LEVEL;
+ struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
+
+ *state = ctx->max_level;
return 0;
}
@@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
{
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
- if (state > MAX_LEVEL)
+ if (state > ctx->max_level)
return -EINVAL;
if (state == ctx->level)
@@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct khadas_mcu_fan_ctx *ctx;
int ret;
+ const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
+
ctx->mcu = mcu;
+ ctx->fan_reg = pdata->fan_reg;
+ ctx->max_level = pdata->max_level;
+
+ ctx->power = devm_regulator_get_optional(dev->parent, "fan");
+ if (IS_ERR(ctx->power)) {
+ if (PTR_ERR(ctx->power) == -ENODEV)
+ ctx->power = NULL;
+ else
+ return PTR_ERR(ctx->power);
+ }
+
+ if (ctx->power) {
+ ret = regulator_enable(ctx->power);
+ if (ret) {
+ dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
+ return ret;
+ }
+ }
+
platform_set_drvdata(pdev, ctx);
cdev = devm_thermal_of_cooling_device_register(dev->parent,
@@ -130,6 +154,13 @@ static int khadas_mcu_fan_suspend(struct device *dev)
static int khadas_mcu_fan_resume(struct device *dev)
{
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
+ int ret;
+
+ if (ctx->power) {
+ ret = regulator_enable(ctx->power);
+ if (ret)
+ return ret;
+ }
return khadas_mcu_fan_set_level(ctx, ctx->level);
}
--
2.49.0
^ permalink raw reply related
* [PATCH 7/8] arm64: dts: amlogic: t7: Add i2c controller node
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Add the T7 i2c controller node used by the Khadas VIM4
for MCU communication.
Use amlogic,meson-axg-i2c as fallback compatible.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index e96fe10b251a0..560c9dce35266 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -711,6 +711,16 @@ pwm_ao_cd: pwm@60000 {
status = "disabled";
};
+ i2c_m_ao_a: i2c@76000 {
+ compatible = "amlogic,t7-i2c", "amlogic,meson-axg-i2c";
+ reg = <0x0 0x76000 0x0 0x48>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc_periphs CLKID_SYS_I2C_AO_A>;
+ status = "disabled";
+ };
+
sd_emmc_a: mmc@88000 {
compatible = "amlogic,t7-mmc", "amlogic,meson-axg-mmc";
reg = <0x0 0x88000 0x0 0x800>;
--
2.49.0
^ permalink raw reply related
* [PATCH 3/8] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Introduce a per-variant configuration structure (khadas_mcu_data)
holding the regmap config and MFD cells,
selected at probe time via the of_device_id match data.
This makes adding other variants straightforward.
Also introduce khadas_mcu_fan_pdata to pass fan register address and
maximum level to the fan sub-driver, removing the hardcoded constants.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
include/linux/mfd/khadas-mcu.h | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
index a99ba2ed0e4e0..75e275d3fa8d9 100644
--- a/include/linux/mfd/khadas-mcu.h
+++ b/include/linux/mfd/khadas-mcu.h
@@ -70,6 +70,13 @@
#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */
+/* VIM4 specific registers */
+#define KHADAS_MCU_VIM4_REST_CONF_REG 0x2c /* WO - reset EEPROM */
+#define KHADAS_MCU_VIM4_LED_ON_RAM_REG 0x89 /* WO - LED volatile */
+#define KHADAS_MCU_VIM4_FAN_CTRL_REG 0x8a /* WO */
+#define KHADAS_MCU_VIM4_WDT_EN_REG 0x8b /* WO */
+#define KHADAS_MCU_VIM4_SYS_RST_REG 0x91 /* WO */
+
enum {
KHADAS_BOARD_VIM1 = 0x1,
KHADAS_BOARD_VIM2,
@@ -82,10 +89,38 @@ enum {
* struct khadas_mcu - Khadas MCU structure
* @device: device reference used for logs
* @regmap: register map
+ * @data: pointer to variant-specific config
*/
struct khadas_mcu {
- struct device *dev;
- struct regmap *regmap;
+ struct device *dev;
+ struct regmap *regmap;
+ const struct khadas_mcu_data *data;
+};
+
+/**
+ * struct khadas_mcu_data - per-variant configuration
+ * @regmap_config: regmap configuration
+ * @cells: MFD sub-devices
+ * @ncells: number of sub-devices
+ * @fan_cells: MFD fan sub-devices
+ * @nfan_cells: number of fan sub-devices
+ */
+struct khadas_mcu_data {
+ const struct regmap_config *regmap_config;
+ const struct mfd_cell *cells;
+ int ncells;
+ const struct mfd_cell *fan_cells;
+ int nfan_cells;
+};
+
+/**
+ * struct khadas_mcu_fan_pdata - fan sub-driver configuration
+ * @fan_reg: register address to write the fan level
+ * @max_level: maximum fan level
+ */
+struct khadas_mcu_fan_pdata {
+ unsigned int fan_reg;
+ unsigned int max_level;
};
#endif /* MFD_KHADAS_MCU_H */
--
2.49.0
^ permalink raw reply related
* [PATCH 2/8] dt-bindings: i2c: amlogic: Add compatible for T7 SOC
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
Add the T7 SOC compatible which fallback to AXG compatible.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
.../devicetree/bindings/i2c/amlogic,meson6-i2c.yaml | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
index c4cc8af182807..7b59b60b62e5b 100644
--- a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
@@ -16,10 +16,15 @@ allOf:
properties:
compatible:
- enum:
- - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
- - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
- - amlogic,meson-axg-i2c # AXG and compatible SoCs
+ oneOf:
+ - items:
+ - enum:
+ - amlogic,t7-i2c
+ - const: amlogic,meson-axg-i2c
+ - enum:
+ - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
+ - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
+ - amlogic,meson-axg-i2c # AXG and compatible SoCs
reg:
maxItems: 1
--
2.49.0
^ permalink raw reply related
* [PATCH 1/8] dt-bindings: mfd: khadas: Add new compatible for Khadas VIM4 MCU
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr>
The Khadas VIM4 MCU register is slightly different
from previous boards' MCU.
This board also features a switchable power source for its fan.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
index 084960fd5a1fd..67769ef5d58b1 100644
--- a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
+++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
@@ -18,6 +18,7 @@ properties:
compatible:
enum:
- khadas,mcu # MCU revision is discoverable
+ - khadas,vim4-mcu
"#cooling-cells": # Only needed for boards having FAN control feature
const: 2
@@ -25,6 +26,10 @@ properties:
reg:
maxItems: 1
+ fan-supply:
+ description: Phandle to the regulator that powers the fan.
+ $ref: /schemas/types.yaml#/definitions/phandle
+
required:
- compatible
- reg
--
2.49.0
^ permalink raw reply related
* [PATCH 0/8] Add VIM4 MCU/FAN support
From: Ronald Claveau @ 2026-04-02 14:27 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm, Ronald Claveau
The Khadas VIM4 board features a different MCU variant compared to
previous VIM boards.
While it shares the same I2C-based communication model,
it differs in some ways:
- A distinct register map with its own volatile/writeable register set
- A fan control with 0–100 levels instead of the 0–3 levels previously
- A fan power supply gated through a regulator
This series adds support for this new variant by:
1. Refactoring the khadas-mcu MFD driver to use per-variant data
structures (regmap config, cells, fan platform data),
and adding the khadas,vim4-mcu compatible string.
2. Extending the fan thermal driver to retrieve the fan register
and maximum level from platform_data,
and to optionally manage a power regulator for the fan supply.
3. Adding the corresponding DTS node for the VIM4, wiring the MCU to
the I2C AO_A bus and exposing it as a thermal cooling device.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
Ronald Claveau (8):
dt-bindings: mfd: khadas: Add new compatible for Khadas VIM4 MCU
dt-bindings: i2c: amlogic: Add compatible for T7 SOC
mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
mfd: khadas-mcu: Add support for VIM4 MCU variant
thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
arm64: dts: amlogic: t7: Add i2c pinctrl node
arm64: dts: amlogic: t7: Add i2c controller node
arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
.../bindings/i2c/amlogic,meson6-i2c.yaml | 13 ++-
.../devicetree/bindings/mfd/khadas,mcu.yaml | 5 +
.../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 13 +++
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 20 ++++
drivers/mfd/khadas-mcu.c | 106 ++++++++++++++++++---
drivers/thermal/khadas_mcu_fan.c | 43 +++++++--
include/linux/mfd/khadas-mcu.h | 39 +++++++-
7 files changed, 216 insertions(+), 23 deletions(-)
---
base-commit: f7b64ed948718290209074a50bb0df17e5944873
change-id: 20260402-add-mcu-fan-khadas-vim4-ac1cbe553c9b
prerequisite-message-id: <20260326092645.1053261-1-jian.hu@amlogic.com>
prerequisite-patch-id: f03a086b4137158412b2d47b3de793b858de8dde
prerequisite-patch-id: 123970c9b29c2090440f2fd71c85d3c6fd8e36de
prerequisite-patch-id: 3e2e56b0926ba327b520f935df4ced5089bbe503
prerequisite-patch-id: 65a5d76ffdbc9b3aab3385bb65cb027004c30e7e
prerequisite-patch-id: 237269801826dd3ad7fb16eb4d7d6d4eab504278
prerequisite-patch-id: 57e9b08a968aedf543d3d0d56cf1ca4db20b2a16
prerequisite-change-id: 20260326-add-bcm43752-compatible-e264a4f7973a:v2
prerequisite-patch-id: cd98b74fa56af72af2553f391c400981d83cd4f4
prerequisite-patch-id: b730f5e42be1d89d193e63a0265495cdbf2c7d7b
prerequisite-change-id: 20260330-fix-invalid-property-bbe54d933f71:v2
prerequisite-patch-id: 8d675e7a239985c762843515b241f0a2f45f9c92
prerequisite-change-id: 20260331-fix-aml-t7-null-reset-2b608ebf9da4:v1
prerequisite-patch-id: 5b5de77af11747ce964404fb827d2ee2bff47ea5
prerequisite-patch-id: 1e37fc75fed1e533adee0f3e7e6ead1f8ff3c55c
prerequisite-patch-id: 65a5d76ffdbc9b3aab3385bb65cb027004c30e7e
prerequisite-patch-id: 2daf583fb5e7449a02bd217d8aca330171b598aa
prerequisite-patch-id: 237269801826dd3ad7fb16eb4d7d6d4eab504278
prerequisite-patch-id: d1ddf9b7710e91f8062de83bd7ba55afb2c4c112
prerequisite-patch-id: 57e9b08a968aedf543d3d0d56cf1ca4db20b2a16
prerequisite-patch-id: cd98b74fa56af72af2553f391c400981d83cd4f4
prerequisite-patch-id: b730f5e42be1d89d193e63a0265495cdbf2c7d7b
prerequisite-patch-id: 9debd88fa60febed9cd7208f86603b4c2d270520
prerequisite-patch-id: 314ef9ff0c4d1d15dab1dea9d92aa065f1eac3e9
Best regards,
--
Ronald Claveau <linux-kernel-dev@aliel.fr>
^ permalink raw reply
* Re: [PATCH v4 1/2] cpufreq/amd-pstate: Pass the policy to amd_pstate_update()
From: Mario Limonciello @ 2026-04-02 13:52 UTC (permalink / raw)
To: Viresh Kumar, K Prateek Nayak
Cc: Rafael J. Wysocki, Huang Rui, Gautham R. Shenoy,
Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt,
Perry Yuan, linux-pm, linux-kernel, rust-for-linux,
linux-rt-devel, Mario Limonciello
In-Reply-To: <4bwfgnjiywkm4dyslhzmk6lvar3a6rhvtcyyruc7okybckuwuf@mkdc5dlconx4>
On 4/2/26 01:39, Viresh Kumar wrote:
> On 02-04-26, 12:07, Viresh Kumar wrote:
>> On 16-03-26, 08:18, K Prateek Nayak wrote:
>>> All callers of amd_pstate_update() already have a reference to the
>>> cpufreq_policy object.
>>>
>>> Pass the entire policy object and grab the cpudata using
>>> "policy->driver_data" instead of passing the cpudata and unnecessarily
>>> grabbing another read-side reference to the cpufreq policy object when
>>> it is already available in the caller.
>>>
>>> No functional changes intended.
>>>
>>> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
>>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>>> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
>>> ---
>>> changelog v3..v4:
>>>
>>> o No changes.
>>> ---
>>> drivers/cpufreq/amd-pstate.c | 11 ++++-------
>>> 1 file changed, 4 insertions(+), 7 deletions(-)
>>
>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>
> Oops, I already Acked it once :)
>
> It is ready for Rafael to pick now.
>
I'm sending an amd-pstate PR later today after some more testing.
I'll pick this up in my PR that goes to Rafael.
^ permalink raw reply
* Re: [PATCH] PM / wakeup: Allocate class wakeup_class statically
From: Heiner Kallweit @ 2026-04-02 13:05 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Pavel Machek, Len Brown, Greg Kroah-Hartman, Danilo Krummrich,
Linux PM, driver-core
In-Reply-To: <CAJZ5v0i5dSuQ7f8Okb-Ch5igzNn=L_Fj5d3H4pftvxoEVBaDUw@mail.gmail.com>
On 01.04.2026 19:32, Rafael J. Wysocki wrote:
> On Wed, Apr 1, 2026 at 5:45 PM Heiner Kallweit <hkallweit1@gmail.com> wrote:
>>
>> On 01.04.2026 16:19, Rafael J. Wysocki wrote:
>>> On Sun, Mar 29, 2026 at 6:14 PM Heiner Kallweit <hkallweit1@gmail.com> wrote:
>>>>
>>>> Allocating wakeup_class statically avoids a little runtime overhead.
>>>> Define groups and device release function as part of the class, so that
>>>> we don't have to repeat this for each class device.
>>>> Whilst at it, constify wakeup_source_attrs[].
>>>>
>>>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
>>>
>>> Can you please have a look at this and let me know what you think:
>>>
>>> https://sashiko.dev/#/patchset/0fe1b679-ab28-4505-b0db-14e7ac3ba749%40gmail.com
>>>
>> Interesting finding! I think the diagnosis is right.
>>
>> But: I would say the current behavior isn't a nice solution as well:
>
> It is not fantastic, but it doesn't have this issue.
>
>> wakeup_source_device_create() does: dev->class = wakeup_class;
>> I think no reader will expect that wakeup_class may be NULL here due to
>> initcall ordering. In addition this behavior results in such early
>> wakeup sources not being shown in sysfs.
>
> They are registered too early to show up in sysfs, but they can work regardless.
>
> I think that it's just pointless to call device_register() for a given
> wakeup source if wakeup_class has not been registered yet.
>
>> But I'm not sure whether registering class "wakeup" (and registering
>> classes in general) would be possible early enough (core_initcall,
>> or even pure_initcall).
>
> driver_init() is called before do_initcalls() is do_basic_setup(), so
> class registration should work for all initcall levels AFAICS.
>
When testing the current code on my system, autosleep is the first wakeup
source, registered in a core_initcall, and it's not shown in sysfs.
Same result when class wakeup is registered in a core_initcall
(instead of postcore_initcall). Registering class wakeup in a pure_initcall
works and fixes the issue. So, would this be an acceptable solution for the
discussed issue?
>>>> ---
>>>> drivers/base/power/wakeup_stats.c | 18 +++++++++---------
>>>> 1 file changed, 9 insertions(+), 9 deletions(-)
>>>>
>>>> diff --git a/drivers/base/power/wakeup_stats.c b/drivers/base/power/wakeup_stats.c
>>>> index 308f8bde9..72beb8fce 100644
>>>> --- a/drivers/base/power/wakeup_stats.c
>>>> +++ b/drivers/base/power/wakeup_stats.c
>>>> @@ -18,8 +18,6 @@
>>>>
>>>> #include "power.h"
>>>>
>>>> -static struct class *wakeup_class;
>>>> -
>>>> #define wakeup_attr(_name) \
>>>> static ssize_t _name##_show(struct device *dev, \
>>>> struct device_attribute *attr, char *buf) \
>>>> @@ -114,7 +112,7 @@ static ssize_t prevent_suspend_time_ms_show(struct device *dev,
>>>> }
>>>> static DEVICE_ATTR_RO(prevent_suspend_time_ms);
>>>>
>>>> -static struct attribute *wakeup_source_attrs[] = {
>>>> +static const struct attribute *const wakeup_source_attrs[] = {
>>>> &dev_attr_name.attr,
>>>> &dev_attr_active_count.attr,
>>>> &dev_attr_event_count.attr,
>>>> @@ -135,6 +133,12 @@ static void device_create_release(struct device *dev)
>>>> kfree(dev);
>>>> }
>>>>
>>>> +static const struct class wakeup_class = {
>>>> + .name = "wakeup",
>>>> + .dev_release = device_create_release,
>>>> + .dev_groups = wakeup_source_groups,
>>>> +};
>>>> +
>>>> static struct device *wakeup_source_device_create(struct device *parent,
>>>> struct wakeup_source *ws)
>>>> {
>>>> @@ -149,10 +153,8 @@ static struct device *wakeup_source_device_create(struct device *parent,
>>>>
>>>> device_initialize(dev);
>>>> dev->devt = MKDEV(0, 0);
>>>> - dev->class = wakeup_class;
>>>> + dev->class = &wakeup_class;
>>>> dev->parent = parent;
>>>> - dev->groups = wakeup_source_groups;
>>>> - dev->release = device_create_release;
>>>> dev_set_drvdata(dev, ws);
>>>> device_set_pm_not_required(dev);
>>>>
>>>> @@ -212,8 +214,6 @@ void wakeup_source_sysfs_remove(struct wakeup_source *ws)
>>>>
>>>> static int __init wakeup_sources_sysfs_init(void)
>>>> {
>>>> - wakeup_class = class_create("wakeup");
>>>> -
>>>> - return PTR_ERR_OR_ZERO(wakeup_class);
>>>> + return class_register(&wakeup_class);
>>>> }
>>>> postcore_initcall(wakeup_sources_sysfs_init);
>>>> --
>>>> 2.53.0
>>>>
>>
^ permalink raw reply
* Re: [PATCH] MAINTAINERS: amd-pstate: Step down as maintainer, add Prateek as reviewer
From: K Prateek Nayak @ 2026-04-02 11:21 UTC (permalink / raw)
To: Gautham R. Shenoy, rafael, viresh.kumar, ray.huang,
mario.limonciello, perry.yuan
Cc: linux-pm, linux-kernel, gautham.shenoy
In-Reply-To: <20260402102611.16519-1-gautham.shenoy@amd.com>
Hello Gautham,
On 4/2/2026 3:56 PM, Gautham R. Shenoy wrote:
> Mario Limonciello has led amd-pstate maintenance in recent years and
> has done excellent work. The amd-pstate driver is in good hands with
> him. I am stepping down as co-maintainer as I move on to other things.
Thank you for helping build the strong foundations that amd-pstate rests
on. What was once a house of cards is now a fortress thanks to all your
hard work!
_I'm not crying. Just sweating from my eyes_
>
> Add K Prateek Nayak as a reviewer. He has been actively contributing
> to the driver including preferred-core and ITMT improvements, and has
> been helping review amd-pstate patches for a while now.
>
> Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
Acked-by: K Prateek Nayak <kprateek.nayak@amd.com>
--
Thanks and Regards,
Prateek
^ permalink raw reply
* Re: [PATCH] thermal/core: Remove pointless variable when registering a cooling device
From: Lukasz Luba @ 2026-04-02 11:03 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Daniel Lezcano, rafael, Zhang Rui, open list:THERMAL, open list
In-Reply-To: <20260402084426.1360086-1-daniel.lezcano@kernel.org>
On 4/2/26 09:44, Daniel Lezcano wrote:
> From: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
>
> The 'id' variable is set to store the ida_alloc() value which is
> already stored into cdev->id. It is pointless to use it because
> cdev->id can be used instead.
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
> ---
> drivers/thermal/thermal_core.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index b7d706ed7ed9..02ce58223f9f 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -1061,7 +1061,7 @@ __thermal_cooling_device_register(struct device_node *np,
> {
> struct thermal_cooling_device *cdev;
> unsigned long current_state;
> - int id, ret;
> + int ret;
>
> if (!ops || !ops->get_max_state || !ops->get_cur_state ||
> !ops->set_cur_state)
> @@ -1078,7 +1078,6 @@ __thermal_cooling_device_register(struct device_node *np,
> if (ret < 0)
> goto out_kfree_cdev;
> cdev->id = ret;
> - id = ret;
>
> cdev->type = kstrdup_const(type ? type : "", GFP_KERNEL);
> if (!cdev->type) {
> @@ -1135,7 +1134,7 @@ __thermal_cooling_device_register(struct device_node *np,
> out_cdev_type:
> kfree_const(cdev->type);
> out_ida_remove:
> - ida_free(&thermal_cdev_ida, id);
> + ida_free(&thermal_cdev_ida, cdev->id);
> out_kfree_cdev:
> kfree(cdev);
> return ERR_PTR(ret);
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
^ permalink raw reply
* [PATCH] MAINTAINERS: amd-pstate: Step down as maintainer, add Prateek as reviewer
From: Gautham R. Shenoy @ 2026-04-02 10:26 UTC (permalink / raw)
To: rafael, viresh.kumar, ray.huang, mario.limonciello, perry.yuan,
kprateek.nayak
Cc: linux-pm, linux-kernel, gautham.shenoy, Gautham R. Shenoy
Mario Limonciello has led amd-pstate maintenance in recent years and
has done excellent work. The amd-pstate driver is in good hands with
him. I am stepping down as co-maintainer as I move on to other things.
Add K Prateek Nayak as a reviewer. He has been actively contributing
to the driver including preferred-core and ITMT improvements, and has
been helping review amd-pstate patches for a while now.
Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index c3fe46d7c4bc..a85a0b45f023 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1234,9 +1234,9 @@ F: drivers/gpu/drm/amd/pm/
AMD PSTATE DRIVER
M: Huang Rui <ray.huang@amd.com>
-M: Gautham R. Shenoy <gautham.shenoy@amd.com>
M: Mario Limonciello <mario.limonciello@amd.com>
R: Perry Yuan <perry.yuan@amd.com>
+R: K Prateek Nayak <kprateek.nayak@amd.com>
L: linux-pm@vger.kernel.org
S: Supported
F: Documentation/admin-guide/pm/amd-pstate.rst
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v8 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
From: Gautham R. Shenoy @ 2026-04-02 9:04 UTC (permalink / raw)
To: Mario Limonciello (AMD)
Cc: Perry Yuan, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK
In-Reply-To: <20260402050214.1238624-2-superm1@kernel.org>
Hello Mario,
On Thu, Apr 02, 2026 at 12:02:10AM -0500, Mario Limonciello (AMD) wrote:
> Dynamic energy performance preference changes the EPP profile based on
> whether the machine is running on AC or DC power.
>
> A notification chain from the power supply core is used to adjust EPP
> values on plug in or plug out events.
>
> When enabled, the driver exposes a sysfs toggle for dynamic EPP, blocks
> manual writes to energy_performance_preference, and keeps the policy in
> performance mode while it "owns" the EPP updates.
The commit message still says "..keeps the policy in performance mode
while it owns the EPP updates".
That is no longer true in this version, so this needs to be removed.
Other than that, the patch looks good to me.
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
--
Thanks and Regards
gautham.
>
> For non-server systems:
> * the default EPP for AC mode is `performance`.
> * the default EPP for DC mode is `balance_performance`.
>
> For server systems dynamic EPP is mostly a no-op.
>
> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
> v7->v8:
> * Handle failures to enable dynamic epp
> * Don't set policy to CPUFREQ_POLICY_PERFORMANCE in dymamic epp
> * Allow policy governor changes
> v6->v7:
> * Fix accidental casualty of floor perf from rebase (Gautham)
> * Adjust documentation (Gautham)
> ---
> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
> drivers/cpufreq/Kconfig.x86 | 12 ++
> drivers/cpufreq/amd-pstate.c | 128 +++++++++++++++++++-
> drivers/cpufreq/amd-pstate.h | 10 +-
> 4 files changed, 160 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
> index b43675b7f739b..bb1341763882b 100644
> --- a/Documentation/admin-guide/pm/amd-pstate.rst
> +++ b/Documentation/admin-guide/pm/amd-pstate.rst
> @@ -325,7 +325,7 @@ and user can change current preference according to energy or performance needs
> Please get all support profiles list from
> ``energy_performance_available_preferences`` attribute, all the profiles are
> integer values defined between 0 to 255 when EPP feature is enabled by platform
> -firmware, if EPP feature is disabled, driver will ignore the written value
> +firmware, but if the dynamic EPP feature is enabled, driver will block writes.
> This attribute is read-write.
>
> ``boost``
> @@ -347,6 +347,22 @@ boost or `1` to enable it, for the respective CPU using the sysfs path
> Other performance and frequency values can be read back from
> ``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`.
>
> +Dynamic energy performance profile
> +==================================
> +The amd-pstate driver supports dynamically selecting the energy performance
> +profile based on whether the machine is running on AC or DC power.
> +
> +Whether this behavior is enabled by default depends on the kernel
> +config option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be overridden
> +at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
> +
> +When set to enabled, the driver will select a different energy performance
> +profile when the machine is running on battery or AC power.
> +When set to disabled, the driver will not change the energy performance profile
> +based on the power source and will not react to user desired power state.
> +
> +Attempting to manually write to the ``energy_performance_preference`` sysfs
> +file will fail when ``dynamic_epp`` is enabled.
>
> ``amd-pstate`` vs ``acpi-cpufreq``
> ======================================
> diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
> index 2c5c228408bf2..cdaa8d858045a 100644
> --- a/drivers/cpufreq/Kconfig.x86
> +++ b/drivers/cpufreq/Kconfig.x86
> @@ -68,6 +68,18 @@ config X86_AMD_PSTATE_DEFAULT_MODE
> For details, take a look at:
> <file:Documentation/admin-guide/pm/amd-pstate.rst>.
>
> +config X86_AMD_PSTATE_DYNAMIC_EPP
> + bool "AMD Processor P-State dynamic EPP support"
> + depends on X86_AMD_PSTATE
> + default n
> + help
> + Allow the kernel to dynamically change the energy performance
> + value from events like ACPI platform profile and AC adapter plug
> + events.
> +
> + This feature can also be changed at runtime, this configuration
> + option only sets the kernel default value behavior.
> +
> config X86_AMD_PSTATE_UT
> tristate "selftest for AMD Processor P-State driver"
> depends on X86 && ACPI_PROCESSOR
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index f207252eb5f5f..379e7dd442522 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -36,6 +36,7 @@
> #include <linux/io.h>
> #include <linux/delay.h>
> #include <linux/uaccess.h>
> +#include <linux/power_supply.h>
> #include <linux/static_call.h>
> #include <linux/topology.h>
>
> @@ -86,6 +87,11 @@ static struct cpufreq_driver amd_pstate_driver;
> static struct cpufreq_driver amd_pstate_epp_driver;
> static int cppc_state = AMD_PSTATE_UNDEFINED;
> static bool amd_pstate_prefcore = true;
> +#ifdef CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP
> +static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
> +#else
> +static bool dynamic_epp;
> +#endif
> static struct quirk_entry *quirks;
>
> /*
> @@ -1155,6 +1161,73 @@ static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
> kfree(cpudata);
> }
>
> +static int amd_pstate_get_balanced_epp(struct cpufreq_policy *policy)
> +{
> + struct amd_cpudata *cpudata = policy->driver_data;
> +
> + if (power_supply_is_system_supplied())
> + return cpudata->epp_default_ac;
> + else
> + return cpudata->epp_default_dc;
> +}
> +
> +static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
> + unsigned long event, void *data)
> +{
> + struct amd_cpudata *cpudata = container_of(nb, struct amd_cpudata, power_nb);
> + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
> + u8 epp;
> + int ret;
> +
> + if (event != PSY_EVENT_PROP_CHANGED)
> + return NOTIFY_OK;
> +
> + epp = amd_pstate_get_balanced_epp(policy);
> +
> + ret = amd_pstate_set_epp(policy, epp);
> + if (ret)
> + pr_warn("Failed to set CPU %d EPP %u: %d\n", cpudata->cpu, epp, ret);
> +
> + return NOTIFY_OK;
> +}
> +static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
> +{
> + struct amd_cpudata *cpudata = policy->driver_data;
> +
> + if (cpudata->power_nb.notifier_call)
> + power_supply_unreg_notifier(&cpudata->power_nb);
> + cpudata->dynamic_epp = false;
> +}
> +
> +static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
> +{
> + struct amd_cpudata *cpudata = policy->driver_data;
> + int ret;
> + u8 epp;
> +
> + epp = amd_pstate_get_balanced_epp(policy);
> + ret = amd_pstate_set_epp(policy, epp);
> + if (ret)
> + return ret;
> +
> + /* only enable notifier if things will actually change */
> + if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
> + cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier;
> + ret = power_supply_reg_notifier(&cpudata->power_nb);
> + if (ret)
> + goto cleanup;
> + }
> +
> + cpudata->dynamic_epp = true;
> +
> + return 0;
> +
> +cleanup:
> + amd_pstate_clear_dynamic_epp(policy);
> +
> + return ret;
> +}
> +
> /* Sysfs attributes */
>
> /*
> @@ -1244,14 +1317,19 @@ static ssize_t store_energy_performance_preference(
> ssize_t ret;
> u8 epp;
>
> + if (cpudata->dynamic_epp) {
> + pr_debug("EPP cannot be set when dynamic EPP is enabled\n");
> + return -EBUSY;
> + }
> +
> ret = sysfs_match_string(energy_perf_strings, buf);
> if (ret < 0)
> return -EINVAL;
>
> - if (!ret)
> - epp = cpudata->epp_default;
> - else
> + if (ret)
> epp = epp_values[ret];
> + else
> + epp = amd_pstate_get_balanced_epp(policy);
>
> if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
> pr_debug("EPP cannot be set under performance policy\n");
> @@ -1259,6 +1337,8 @@ static ssize_t store_energy_performance_preference(
> }
>
> ret = amd_pstate_set_epp(policy, epp);
> + if (ret)
> + return ret;
>
> return ret ? ret : count;
> }
> @@ -1620,12 +1700,42 @@ static ssize_t prefcore_show(struct device *dev,
> return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore));
> }
>
> +static ssize_t dynamic_epp_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + return sysfs_emit(buf, "%s\n", str_enabled_disabled(dynamic_epp));
> +}
> +
> +static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b,
> + const char *buf, size_t count)
> +{
> + bool enabled;
> + int ret;
> +
> + ret = kstrtobool(buf, &enabled);
> + if (ret)
> + return ret;
> +
> + if (dynamic_epp == enabled)
> + return -EINVAL;
> +
> + /* reinitialize with desired dynamic EPP value */
> + dynamic_epp = enabled;
> + ret = amd_pstate_change_driver_mode(cppc_state);
> + if (ret)
> + dynamic_epp = false;
> +
> + return ret ? ret : count;
> +}
> +
> static DEVICE_ATTR_RW(status);
> static DEVICE_ATTR_RO(prefcore);
> +static DEVICE_ATTR_RW(dynamic_epp);
>
> static struct attribute *pstate_global_attributes[] = {
> &dev_attr_status.attr,
> &dev_attr_prefcore.attr,
> + &dev_attr_dynamic_epp.attr,
> NULL
> };
>
> @@ -1715,13 +1825,17 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
> if (amd_pstate_acpi_pm_profile_server() ||
> amd_pstate_acpi_pm_profile_undefined()) {
> policy->policy = CPUFREQ_POLICY_PERFORMANCE;
> - cpudata->epp_default = amd_pstate_get_epp(cpudata);
> + cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
> } else {
> policy->policy = CPUFREQ_POLICY_POWERSAVE;
> - cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
> + cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
> + cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
> }
>
> - ret = amd_pstate_set_epp(policy, cpudata->epp_default);
> + if (dynamic_epp)
> + ret = amd_pstate_set_dynamic_epp(policy);
> + else
> + ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy));
> if (ret)
> goto free_cpudata1;
>
> @@ -1753,6 +1867,8 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
> amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
> amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf);
>
> + if (cpudata->dynamic_epp)
> + amd_pstate_clear_dynamic_epp(policy);
> kfree(cpudata);
> policy->driver_data = NULL;
> }
> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
> index 32b8b26ce388f..d929ae3163b3d 100644
> --- a/drivers/cpufreq/amd-pstate.h
> +++ b/drivers/cpufreq/amd-pstate.h
> @@ -85,6 +85,11 @@ struct amd_aperf_mperf {
> * AMD P-State driver supports preferred core featue.
> * @epp_cached: Cached CPPC energy-performance preference value
> * @policy: Cpufreq policy value
> + * @suspended: If CPU core if offlined
> + * @epp_default_ac: Default EPP value for AC power source
> + * @epp_default_dc: Default EPP value for DC power source
> + * @dynamic_epp: Whether dynamic EPP is enabled
> + * @power_nb: Notifier block for power events
> *
> * The amd_cpudata is key private data for each CPU thread in AMD P-State, and
> * represents all the attributes and goals that AMD P-State requests at runtime.
> @@ -118,7 +123,10 @@ struct amd_cpudata {
> /* EPP feature related attributes*/
> u32 policy;
> bool suspended;
> - u8 epp_default;
> + u8 epp_default_ac;
> + u8 epp_default_dc;
> + bool dynamic_epp;
> + struct notifier_block power_nb;
> };
>
> /*
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH] power: sequencing: pcie-m2: enforce PCI and OF dependencies
From: Arnd Bergmann @ 2026-04-02 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Arnd Bergmann, Rob Herring
Cc: Manivannan Sadhasivam, Ulf Hansson, Michal Wilczynski, linux-pm,
linux-kernel
In-Reply-To: <CAMRc=McYdb-R6QpEKn+VoB4KNKLUJzT82BVzBUYdX+HEqhyB1w@mail.gmail.com>
On Thu, Apr 2, 2026, at 10:39, Bartosz Golaszewski wrote:
> On Wed, Apr 1, 2026 at 11:19 AM Arnd Bergmann <arnd@kernel.org> wrote:
>
> Hi Arnd,
>
> Mani posted the following series[1]. It seems to me it fixes at least
> some of the build issues.
I don't think that covers the case of CONFIG_SERIAL_DEV_BUS=m
with POWER_SEQUENCING_PCIE_M2. Trying to make this work with
compile testing adds a lot of complexity for little benefit,
so I think my second patch is better there. SERIAL_DEV_BUS
is visible on all architectures, so compile-testing works
fine on allmodconfig and randconfig builds either way.
For PCI it's similar: while you can't build test this on
architectures without PCI (m68k, hexagon, ...), nobody
cares, and you just make the driver uglier, though there is
less risk of introducing additional regressions here.
Obviously the m2 pwrseq driver has a real dependency on pcie,
so there is no point trying to make it build with PCI=n,
the same way we don't allow building normal PCI device drivers
without PCI support.
> I would really prefer to keep the COMPILE_TEST option here. I'm seeing
> that only some of the symbols depending on OF_DYNAMIC are stubbed out.
> Rob: is there any reason for that? Would you be willing to Ack a patch
> adding stubs for the remainder and me taking it along with the pwrseq
> changes?
The idea with OF_DYNAMIC is that any driver that uses it should
'select' that symbol, so there is no need for stubs.
More generally: I think the stub helpers in headers are useful
for features that are truly optional, e.g. a driver may be
able to light LEDs if they are enabled but still work fine without
that. COMPILE_TEST in turn is nice when it enables building
platform specific drivers on other platforms. The combination of
the two causes more problems than it helps: if a driver has
a clear dependency on a particular subsystem, we should just
enforce that in Kconfig and not artificially allow compile
testing a configuration that is neither useful in practice
nor hard to build test already.
Arnd
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox