* [PATCH v12 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
2026-09-17 7:58 [PATCH v12 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
@ 2026-09-17 7:59 ` Ronald Claveau via B4 Relay
2026-09-17 8:06 ` sashiko-bot
2026-09-17 7:59 ` [PATCH v12 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations Ronald Claveau via B4 Relay
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-17 7:59 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, mfd, Ronald Claveau
From: Ronald Claveau <linux-kernel-dev@aliel.fr>
Some values change per variant, add the structure to manage it.
Add VIM4 specific registers done for a subsequent patch, which will use a
new compatible especially to get the right regmap config.
Add an enum khadas_mcu_type used as value to match.
Also fix a kernel-doc warning for the khadas_mcu struct.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
include/linux/mfd/khadas-mcu.h | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
index a99ba2ed0e4e0..acd3291061b40 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,
@@ -80,7 +87,7 @@ enum {
/**
* struct khadas_mcu - Khadas MCU structure
- * @device: device reference used for logs
+ * @dev: device reference used for logs
* @regmap: register map
*/
struct khadas_mcu {
@@ -88,4 +95,14 @@ struct khadas_mcu {
struct regmap *regmap;
};
+/**
+ * enum khadas_mcu_type - Khadas MCU hardware variant
+ * @KHADAS_MCU_GENERIC: VIM1, VIM2, VIM3, Edge, Edge-V (shared register map)
+ * @KHADAS_MCU_VIM4: VIM4 (extended register map, distinct fan/LED/WDT regs)
+ */
+enum khadas_mcu_type {
+ KHADAS_MCU_GENERIC = 1,
+ KHADAS_MCU_VIM4,
+};
+
#endif /* MFD_KHADAS_MCU_H */
--
2.49.0
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v12 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations
2026-09-17 7:58 [PATCH v12 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
2026-09-17 7:59 ` [PATCH v12 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support Ronald Claveau via B4 Relay
@ 2026-09-17 7:59 ` Ronald Claveau via B4 Relay
2026-09-17 8:07 ` sashiko-bot
2026-09-17 7:59 ` [PATCH v12 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant Ronald Claveau via B4 Relay
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-17 7:59 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, mfd, Ronald Claveau
From: Ronald Claveau <linux-kernel-dev@aliel.fr>
Convert khadas_mcu_fan_cells[] and khadas_mcu_cells[] to use the
MFD_CELL_NAME() helper macro instead of open-coding the struct
mfd_cell initialisers. While at it, make both arrays const since
they are never modified after initialisation.
This is a pure cleanup with no functional change, done in
preparation for a subsequent patch which will need to attach
platform_data to the fan cell.
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/mfd/khadas-mcu.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index ba981a7886921..0e74efe14f367 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -75,13 +75,13 @@ static const struct regmap_config khadas_mcu_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
-static struct mfd_cell khadas_mcu_fan_cells[] = {
+static const struct mfd_cell khadas_mcu_fan_cells[] = {
/* VIM1/2 Rev13+ and VIM3 only */
- { .name = "khadas-mcu-fan-ctrl", },
+ MFD_CELL_NAME("khadas-mcu-fan-ctrl"),
};
-static struct mfd_cell khadas_mcu_cells[] = {
- { .name = "khadas-mcu-user-mem", },
+static const struct mfd_cell khadas_mcu_cells[] = {
+ MFD_CELL_NAME("khadas-mcu-user-mem"),
};
static int khadas_mcu_probe(struct i2c_client *client)
--
2.49.0
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v12 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant
2026-09-17 7:58 [PATCH v12 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
2026-09-17 7:59 ` [PATCH v12 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support Ronald Claveau via B4 Relay
2026-09-17 7:59 ` [PATCH v12 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations Ronald Claveau via B4 Relay
@ 2026-09-17 7:59 ` Ronald Claveau via B4 Relay
2026-09-17 8:11 ` sashiko-bot
2026-09-17 7:59 ` [PATCH v12 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support Ronald Claveau via B4 Relay
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-17 7:59 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, mfd, Ronald Claveau
From: Ronald Claveau <linux-kernel-dev@aliel.fr>
Refactor probe() to use per-variant values
instead of hardcoded globals.
Add dedicated regmap configuration for the VIM4 MCU,
with its own volatile/writeable registers.
Add a new compatible string "khadas,vim4-mcu".
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/mfd/khadas-mcu.c | 96 +++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 83 insertions(+), 13 deletions(-)
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index 0e74efe14f367..4b37e74e2b04a 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -84,38 +84,107 @@ static const struct mfd_cell khadas_mcu_cells[] = {
MFD_CELL_NAME("khadas-mcu-user-mem"),
};
+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 mfd_cell khadas_mcu_vim4_fan_cells[] = {
+ MFD_CELL_NAME("khadas-mcu-vim4-fan"),
+};
+
static int khadas_mcu_probe(struct i2c_client *client)
{
+ const struct mfd_cell *cells, *fan_cells;
+ const struct regmap_config *regmap_cfg;
struct device *dev = &client->dev;
+ int ncells, nfan_cells, ret;
struct khadas_mcu *ddata;
- int ret;
+ const void *mcu_variant;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
+ mcu_variant = i2c_get_match_data(client);
+ if (!mcu_variant)
+ return -ENODEV;
+
+ switch ((uintptr_t)mcu_variant) {
+ case KHADAS_MCU_GENERIC:
+ regmap_cfg = &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);
+ break;
+ case KHADAS_MCU_VIM4:
+ regmap_cfg = &khadas_mcu_vim4_regmap_config;
+ cells = NULL;
+ ncells = 0;
+ fan_cells = khadas_mcu_vim4_fan_cells;
+ nfan_cells = ARRAY_SIZE(khadas_mcu_vim4_fan_cells);
+ break;
+ default:
+ return -ENODEV;
+ }
+
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, regmap_cfg);
if (IS_ERR(ddata->regmap)) {
ret = PTR_ERR(ddata->regmap);
- dev_err(dev, "Failed to allocate register map: %d\n", ret);
- return ret;
+ return dev_err_probe(dev, ret, "Failed to allocate register map\n");
}
- 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 (cells && ncells) {
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+ cells,
+ 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),
+ fan_cells,
+ nfan_cells,
NULL, 0, NULL);
return 0;
@@ -123,7 +192,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 = (void *)KHADAS_MCU_GENERIC },
+ { .compatible = "khadas,vim4-mcu", .data = (void *)KHADAS_MCU_VIM4 },
{},
};
MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);
--
2.49.0
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v12 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant
2026-09-17 7:59 ` [PATCH v12 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant Ronald Claveau via B4 Relay
@ 2026-09-17 8:11 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-17 8:11 UTC (permalink / raw)
To: Ronald Claveau
Cc: neil.armstrong, linux-amlogic, devicetree, mfd, robh, lee, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] mfd: Incorrect writeable registers in VIM4 regmap config
--
commit fc44329d7ee6d12a0077930b2632df3554d1e38f
Author: Ronald Claveau <linux-kernel-dev@aliel.fr>
mfd: khadas-mcu: Add support for VIM4 MCU variant
This commit adds support for the VIM4 MCU variant by refactoring the
probe function to use per-variant values. It introduces a dedicated
regmap configuration for the VIM4 MCU, with its own volatile and
writeable register checks.
> diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
> index 0e74efe14f367..4b37e74e2b04a 100644
> --- a/drivers/mfd/khadas-mcu.c
> +++ b/drivers/mfd/khadas-mcu.c
[ ... ]
> +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;
[Severity: Low]
Does this function omit multiple known read-only registers defined for the MCU,
such as KHADAS_MCU_MAC_0_REG and KHADAS_MCU_USID_0_REG?
Because this switch defaults to true, any unlisted read-only register is
incorrectly marked as writeable. Because the regmap uses REGCACHE_MAPLE,
writing to an omitted read-only register will inappropriately cache the written
value instead of failing, which could poison the cache for subsequent reads.
Even though the khadas-mcu-user-mem cell isn't instantiated for the VIM4 variant
(meaning there is no active code path writing to these registers in normal
production operation), should these known read-only registers be explicitly
handled to prevent future caching issues?
> + }
> +}
> +
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260917-add-mcu-fan-khadas-vim4-v12-0-497cd543a148@aliel.fr?part=3
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v12 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
2026-09-17 7:58 [PATCH v12 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
` (2 preceding siblings ...)
2026-09-17 7:59 ` [PATCH v12 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant Ronald Claveau via B4 Relay
@ 2026-09-17 7:59 ` Ronald Claveau via B4 Relay
2026-09-17 8:13 ` sashiko-bot
2026-09-17 7:59 ` [PATCH v12 5/6] arm64: dts: amlogic: t7: Add i2c controller node Ronald Claveau via B4 Relay
2026-09-17 7:59 ` [PATCH v12 6/6] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node Ronald Claveau via B4 Relay
5 siblings, 1 reply; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-17 7:59 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, mfd, Ronald Claveau
From: Ronald Claveau <linux-kernel-dev@aliel.fr>
Introduce platform name, control register and duty-cycle
levels per variant.
VIM4 uses a different register and level set (0-100)
declared as a list (0, 30, 40, 55, 75, 100) compared
to previous boards (0-3).
MAX_LEVEL is kept and bumped from 3 to 5 to make
the speed change more gradual with the newer MCUs.
The cooling device's state is stored as an index into levels[],
and khadas_mcu_fan_set_level() writes levels[state] to fan_reg,
rather than writing the raw state value as before.
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.
The regulator is released via a devm_add_action_or_reset()
callback.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
drivers/thermal/khadas_mcu_fan.c | 108 +++++++++++++++++++++++++++++++--------
1 file changed, 86 insertions(+), 22 deletions(-)
diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
index 21b3d0a71bd0d..1da639d054971 100644
--- a/drivers/thermal/khadas_mcu_fan.c
+++ b/drivers/thermal/khadas_mcu_fan.c
@@ -13,34 +13,33 @@
#include <linux/regmap.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
+#include <linux/regulator/consumer.h>
+#include <linux/minmax.h>
-#define MAX_LEVEL 3
+#define MAX_LEVEL 5
struct khadas_mcu_fan_ctx {
struct khadas_mcu *mcu;
+ unsigned int fan_reg;
unsigned int level;
+ const unsigned int *levels;
+ unsigned int nlevels;
struct thermal_cooling_device *cdev;
+ struct regulator *power;
};
static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
unsigned int level)
{
- int ret;
-
- ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
- level);
- if (ret)
- return ret;
-
- ctx->level = level;
-
- return 0;
+ return regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
}
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 = min_t(unsigned int, MAX_LEVEL, ctx->nlevels - 1);
return 0;
}
@@ -60,14 +59,21 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
unsigned long state)
{
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
+ int ret;
- if (state > MAX_LEVEL)
+ if (state > MAX_LEVEL || state >= ctx->nlevels)
return -EINVAL;
if (state == ctx->level)
return 0;
- return khadas_mcu_fan_set_level(ctx, state);
+ ret = khadas_mcu_fan_set_level(ctx, ctx->levels[state]);
+ if (ret)
+ return ret;
+
+ ctx->level = state;
+
+ return 0;
}
static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
@@ -76,22 +82,71 @@ static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
.set_cur_state = khadas_mcu_fan_set_cur_state,
};
+static void khadas_mcu_fan_regulator_disable(void *data)
+{
+ struct regulator *power = data;
+
+ regulator_disable(power);
+}
+
+static const unsigned int khadas_mcu_fan_levels[] = { 0, 1, 2, 3 };
+
+static const unsigned int khadas_mcu_vim4_fan_levels[] = { 0, 30, 40, 55, 75, 100 };
+
static int khadas_mcu_fan_probe(struct platform_device *pdev)
{
+ const struct platform_device_id *id = platform_get_device_id(pdev);
struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent);
struct thermal_cooling_device *cdev;
struct device *dev = &pdev->dev;
struct khadas_mcu_fan_ctx *ctx;
int ret;
+
+ if (!dev->of_node)
+ dev->of_node = of_node_get(dev->parent->of_node);
+
+ if (!id)
+ return -EINVAL;
+
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
+
ctx->mcu = mcu;
+ switch (id->driver_data) {
+ case KHADAS_MCU_GENERIC:
+ ctx->fan_reg = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG;
+ ctx->levels = khadas_mcu_fan_levels;
+ ctx->nlevels = ARRAY_SIZE(khadas_mcu_fan_levels);
+ break;
+ case KHADAS_MCU_VIM4:
+ ctx->fan_reg = KHADAS_MCU_VIM4_FAN_CTRL_REG;
+ ctx->levels = khadas_mcu_vim4_fan_levels;
+ ctx->nlevels = ARRAY_SIZE(khadas_mcu_vim4_fan_levels);
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ ctx->power = devm_regulator_get(dev, "fan");
+ if (IS_ERR(ctx->power))
+ return PTR_ERR(ctx->power);
+
+ ret = regulator_enable(ctx->power);
+ if (ret) {
+ dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(dev, khadas_mcu_fan_regulator_disable, ctx->power);
+ if (ret)
+ return ret;
+
platform_set_drvdata(pdev, ctx);
- cdev = devm_thermal_of_child_cooling_device_register(dev->parent,
- dev->parent->of_node,
+ cdev = devm_thermal_of_child_cooling_device_register(dev,
+ dev->of_node,
"khadas-mcu-fan", ctx,
&khadas_mcu_fan_cooling_ops);
if (IS_ERR(cdev)) {
@@ -109,21 +164,24 @@ static void khadas_mcu_fan_shutdown(struct platform_device *pdev)
{
struct khadas_mcu_fan_ctx *ctx = platform_get_drvdata(pdev);
- khadas_mcu_fan_set_level(ctx, 0);
+ khadas_mcu_fan_set_level(ctx, ctx->levels[0]);
}
#ifdef CONFIG_PM_SLEEP
static int khadas_mcu_fan_suspend(struct device *dev)
{
struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
- unsigned int level_save = ctx->level;
int ret;
- ret = khadas_mcu_fan_set_level(ctx, 0);
+ ret = khadas_mcu_fan_set_level(ctx, ctx->levels[0]);
if (ret)
return ret;
- ctx->level = level_save;
+ ret = regulator_disable(ctx->power);
+ if (ret) {
+ khadas_mcu_fan_set_level(ctx, ctx->levels[ctx->level]);
+ return ret;
+ }
return 0;
}
@@ -131,8 +189,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;
+
+ ret = regulator_enable(ctx->power);
+ if (ret)
+ return ret;
- return khadas_mcu_fan_set_level(ctx, ctx->level);
+ return khadas_mcu_fan_set_level(ctx, ctx->levels[ctx->level]);
}
#endif
@@ -140,7 +203,8 @@ static SIMPLE_DEV_PM_OPS(khadas_mcu_fan_pm, khadas_mcu_fan_suspend,
khadas_mcu_fan_resume);
static const struct platform_device_id khadas_mcu_fan_id_table[] = {
- { .name = "khadas-mcu-fan-ctrl", },
+ { .name = "khadas-mcu-fan-ctrl", .driver_data = KHADAS_MCU_GENERIC },
+ { .name = "khadas-mcu-vim4-fan", .driver_data = KHADAS_MCU_VIM4 },
{},
};
MODULE_DEVICE_TABLE(platform, khadas_mcu_fan_id_table);
--
2.49.0
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v12 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
2026-09-17 7:59 ` [PATCH v12 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support Ronald Claveau via B4 Relay
@ 2026-09-17 8:13 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-17 8:13 UTC (permalink / raw)
To: Ronald Claveau
Cc: linux-amlogic, conor+dt, robh, lee, mfd, devicetree, neil.armstrong
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] thermal: khadas-mcu-fan: OF node reference leak in probe
--
commit c3a0644be46518f47124644a90235d26979c4299
Author: Ronald Claveau <linux-kernel-dev@aliel.fr>
thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
This commit introduces variant-specific platform data including control
registers and duty-cycle levels, while also bumping the maximum level.
It optionally acquires and enables a fan regulator supply at probe time
to handle boards that gate fan power.
> diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
> index 21b3d0a71bd0d..1da639d054971 100644
> --- a/drivers/thermal/khadas_mcu_fan.c
> +++ b/drivers/thermal/khadas_mcu_fan.c
[ ... ]
> @@ -76,22 +82,71 @@ static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
> static int khadas_mcu_fan_probe(struct platform_device *pdev)
> {
> + const struct platform_device_id *id = platform_get_device_id(pdev);
> struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent);
> struct thermal_cooling_device *cdev;
> struct device *dev = &pdev->dev;
> struct khadas_mcu_fan_ctx *ctx;
> int ret;
>
> +
> + if (!dev->of_node)
> + dev->of_node = of_node_get(dev->parent->of_node);
[Severity: Medium]
Does this leak the OF node reference? The probe function explicitly
acquires the node with of_node_get() and assigns it to dev->of_node,
but there is no corresponding cleanup mechanism.
Since there is no .remove callback or devm action registered to call
of_node_put(), and the driver core does not automatically drop
references assigned directly to dev->of_node in this manner, the
reference count appears to leak every time the driver is unbound.
> +
> + if (!id)
> + return -EINVAL;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260917-add-mcu-fan-khadas-vim4-v12-0-497cd543a148@aliel.fr?part=4
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v12 5/6] arm64: dts: amlogic: t7: Add i2c controller node
2026-09-17 7:58 [PATCH v12 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
` (3 preceding siblings ...)
2026-09-17 7:59 ` [PATCH v12 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support Ronald Claveau via B4 Relay
@ 2026-09-17 7:59 ` Ronald Claveau via B4 Relay
2026-09-17 8:03 ` sashiko-bot
2026-09-17 7:59 ` [PATCH v12 6/6] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node Ronald Claveau via B4 Relay
5 siblings, 1 reply; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-17 7:59 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, mfd, Ronald Claveau
From: Ronald Claveau <linux-kernel-dev@aliel.fr>
Add the T7 i2c controller node used by the Khadas VIM4
for MCU communication.
Use amlogic,meson-axg-i2c as fallback compatible.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
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 c3dc479b137de..0f48e23077e99 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -724,6 +724,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
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v12 6/6] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
2026-09-17 7:58 [PATCH v12 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
` (4 preceding siblings ...)
2026-09-17 7:59 ` [PATCH v12 5/6] arm64: dts: amlogic: t7: Add i2c controller node Ronald Claveau via B4 Relay
@ 2026-09-17 7:59 ` Ronald Claveau via B4 Relay
2026-09-17 8:08 ` sashiko-bot
5 siblings, 1 reply; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-17 7:59 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, mfd, Ronald Claveau
From: Ronald Claveau <linux-kernel-dev@aliel.fr>
Enable and configure i2c MCU node to get fan working on Khadas VIM4.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
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 c41525a34b721..7d95aadcf6a66 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
@@ -167,6 +167,19 @@ xtal: xtal-clk {
};
};
+&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
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply [flat|nested] 13+ messages in thread