Devicetree
 help / color / mirror / Atom feed
* [PATCH v10 0/6] Add VIM4 MCU/FAN support
@ 2026-09-01 15:25 Ronald Claveau via B4 Relay
  2026-09-01 15:25 ` [PATCH v10 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support Ronald Claveau via B4 Relay
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-01 15:25 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

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>
---
Changes in v10:
- PATCH 1: makes KHADAS_MCU_GENERIC explicitly non-zero to remove the ambiguity with
           of_device_get_match_data() returning NULL/0 on a failed match. Reported by Sashiko.
- PATCH 4: devres for the regulator and cooling device are now attached to the child device (not the parent),
           closing a leak/use-after-free window. Also adds proper regulator teardown on unbind,
           fixes a level-vs-index mixup in shutdown/suspend, and disables the regulator if resume fails.
- Link to v9: https://lore.kernel.org/r/20260805-add-mcu-fan-khadas-vim4-v9-0-75df78710b9e@aliel.fr

Changes in v9:
- Rebased on next-20260731 (patches 1/8, 2/8 and 6/8 already applied, dropped from this series).
- PATCH 1: Add levels table and nlevels in khadas_mcu_fan_pdata struct.
- PATCH 2: Use MFD_CELL_* macros instead of open-coding mfd_cell.
- PATCH 3: Provide levels table and nlevels to platform data.
           Check match_data before the switch.
- PATCH 4: Use levels[] and nlevels from platform data. VIM4 levels is (0, 30, 40, 55, 75, 100).
- Link to v8: https://lore.kernel.org/r/20260702-add-mcu-fan-khadas-vim4-v8-0-244feee91a36@aliel.fr

Changes in v8:
- PATCH 4: Define constant for fan max level, remove extra space for unnecessary alignment.
           Thanks to Lee's review.
- Link to v7: https://lore.kernel.org/r/20260603-add-mcu-fan-khadas-vim4-v7-0-594ba8a965d8@aliel.fr

Changes in v7:
- PATCH 3-4: Simplify the per-variant handling by using local variables in khadas_mcu_probe()
             instead of introducing a dedicated data structure. Thanks to Lee's review.
- Link to v6: https://lore.kernel.org/r/20260516-add-mcu-fan-khadas-vim4-v6-0-cccc9b61f465@aliel.fr

Changes in v6:
- PATCH 4: Address Lee's review comments:
  - Use an enum to discriminate between MCU types instead of passing
    MFD data through the DT match table
  - Fix error code from -EINVAL to -ENODEV when no MCU type is matched
  - Make khadas_mcu_fan_cells and khadas_mcu_cells const
  - Use dev_err_probe() for regmap initialization error
  - Document fan speed levels for max_level
- Link to v5: https://lore.kernel.org/r/20260424-add-mcu-fan-khadas-vim4-v5-0-afcfa7157b23@aliel.fr

Changes in v5:
- PATCH 5: Replace devm_regulator_get_optional() with devm_regulator_get()
           to simplify error handling and remove NULL checks, also
           ordering as reverse christmas according to Neil's feedback.
- Link to v4: https://lore.kernel.org/r/20260421-add-mcu-fan-khadas-vim4-v4-0-447114a28f2d@aliel.fr

Changes in v4:
- PATCH 1: limit fan-supply property by compatible according to Conor's feedback.
- Link to v3: https://lore.kernel.org/r/20260417-add-mcu-fan-khadas-vim4-v3-0-a6a7f570b11b@aliel.fr

Changes in v3:
- PATCH 1: adding comment on vim4 compatible saying it is not discoverable,
           thanks to Rob's and Neil's feedback.
- Link to v2: https://lore.kernel.org/r/20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr

Changes in v2:
- PATCH 5: Add regulator_disable on suspend thanks to Neil's feedback.
- Link to v1: https://lore.kernel.org/r/20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr

---
Ronald Claveau (6):
      mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
      mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations
      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 controller node
      arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node

 .../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts  |  13 +++
 arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi        |  10 ++
 drivers/mfd/khadas-mcu.c                           | 126 ++++++++++++++++++---
 drivers/thermal/khadas_mcu_fan.c                   |  94 +++++++++++----
 include/linux/mfd/khadas-mcu.h                     |  24 ++++
 5 files changed, 227 insertions(+), 40 deletions(-)
---
base-commit: 9dba66b6217aacb924d997de3866e7e4c0dcf952
change-id: 20260402-add-mcu-fan-khadas-vim4-ac1cbe553c9b

Best regards,
-- 
Ronald Claveau <linux-kernel-dev@aliel.fr>



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v10 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
  2026-09-01 15:25 [PATCH v10 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
@ 2026-09-01 15:25 ` Ronald Claveau via B4 Relay
  2026-09-01 15:36   ` sashiko-bot
  2026-09-01 15:25 ` [PATCH v10 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-01 15:25 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 introduce khadas_mcu_fan_pdata to pass fan register address, a
table named levels to get fan-supported levels on the MCU, and the number
of levels to the fan sub-driver. Done in preparation for a subsequent
commit.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 include/linux/mfd/khadas-mcu.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
index a99ba2ed0e4e0..7a9980ea63e7e 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,
@@ -88,4 +95,21 @@ struct khadas_mcu {
 	struct regmap *regmap;
 };
 
+/**
+ * struct khadas_mcu_fan_pdata - fan sub-driver configuration
+ * @fan_reg: register address to write the fan level
+ * @levels: table mapping logical cooling-device states to raw fan levels
+ * @nlevels: number of entries in @levels
+ */
+struct khadas_mcu_fan_pdata {
+	unsigned int fan_reg;
+	const unsigned int *levels;
+	unsigned int nlevels;
+};
+
+enum khadas_mcu_type {
+	KHADAS_MCU_GENERIC = 1, /* VIM1/2/3, Edge, Edge-V */
+	KHADAS_MCU_VIM4,
+};
+
 #endif /* MFD_KHADAS_MCU_H */

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v10 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations
  2026-09-01 15:25 [PATCH v10 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
  2026-09-01 15:25 ` [PATCH v10 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support Ronald Claveau via B4 Relay
@ 2026-09-01 15:25 ` Ronald Claveau via B4 Relay
  2026-09-01 15:36   ` sashiko-bot
  2026-09-01 15:25 ` [PATCH v10 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-01 15:25 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



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v10 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant
  2026-09-01 15:25 [PATCH v10 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
  2026-09-01 15:25 ` [PATCH v10 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support Ronald Claveau via B4 Relay
  2026-09-01 15:25 ` [PATCH v10 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations Ronald Claveau via B4 Relay
@ 2026-09-01 15:25 ` Ronald Claveau via B4 Relay
  2026-09-01 15:33   ` sashiko-bot
  2026-09-01 15:25 ` [PATCH v10 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-01 15:25 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.

Introduce struct khadas_mcu_fan_pdata to pass the fan
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).

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 | 120 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 106 insertions(+), 14 deletions(-)

diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index 0e74efe14f367..4cb305ac915e1 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -75,47 +75,138 @@ static const struct regmap_config khadas_mcu_regmap_config = {
 	.cache_type	= REGCACHE_MAPLE,
 };
 
+static const unsigned int khadas_mcu_fan_levels[] = {
+	0, 1, 2, 3,
+};
+
+static const struct khadas_mcu_fan_pdata khadas_mcu_fan_pdata = {
+	.fan_reg	= KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
+	.levels		= khadas_mcu_fan_levels,
+	.nlevels	= ARRAY_SIZE(khadas_mcu_fan_levels),
+};
+
 static const struct mfd_cell khadas_mcu_fan_cells[] = {
 	/* VIM1/2 Rev13+ and VIM3 only */
-	MFD_CELL_NAME("khadas-mcu-fan-ctrl"),
+	MFD_CELL_BASIC("khadas-mcu-fan-ctrl", NULL, &khadas_mcu_fan_pdata,
+		       sizeof(khadas_mcu_fan_pdata), 0),
 };
 
 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 unsigned int khadas_mcu_vim4_fan_levels[] = {
+	0, 30, 40, 55, 75, 100,
+};
+
+static const struct khadas_mcu_fan_pdata khadas_mcu_vim4_fan_pdata = {
+	.fan_reg	= KHADAS_MCU_VIM4_FAN_CTRL_REG,
+	.levels		= khadas_mcu_vim4_fan_levels,
+	.nlevels	= ARRAY_SIZE(khadas_mcu_vim4_fan_levels),
+};
+
+static const struct mfd_cell khadas_mcu_vim4_fan_cells[] = {
+	MFD_CELL_BASIC("khadas-mcu-fan-ctrl", NULL, &khadas_mcu_vim4_fan_pdata,
+		       sizeof(khadas_mcu_vim4_fan_pdata), 0),
+};
+
 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 *match;
 
 	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
 	if (!ddata)
 		return -ENOMEM;
 
+	match = i2c_get_match_data(client);
+	if (!match)
+		return -ENODEV;
+
+	switch ((uintptr_t)match) {
+	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 +214,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



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v10 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
  2026-09-01 15:25 [PATCH v10 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
                   ` (2 preceding siblings ...)
  2026-09-01 15:25 ` [PATCH v10 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant Ronald Claveau via B4 Relay
@ 2026-09-01 15:25 ` Ronald Claveau via B4 Relay
  2026-09-01 15:58   ` sashiko-bot
  2026-09-01 15:25 ` [PATCH v10 5/6] arm64: dts: amlogic: t7: Add i2c controller node Ronald Claveau via B4 Relay
  2026-09-01 15:25 ` [PATCH v10 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-01 15:25 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>

Read the fan register and level table from platform_data (fan_reg,
levels[] and nlevels) instead of hardcoding a single register and
level count, as new MCUs need different values. 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 | 94 ++++++++++++++++++++++++++++++----------
 1 file changed, 71 insertions(+), 23 deletions(-)

diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
index 21b3d0a71bd0d..512a6f0ff7c26 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,53 @@ 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 int khadas_mcu_fan_probe(struct platform_device *pdev)
 {
+	const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
 	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 = dev->parent->of_node;
+
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
+
 	ctx->mcu = mcu;
+	ctx->fan_reg = pdata->fan_reg;
+	ctx->levels = pdata->levels;
+	ctx->nlevels = pdata->nlevels;
+
+	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,30 +146,41 @@ 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;
-
-	return 0;
+	return regulator_disable(ctx->power);
 }
 
 static int khadas_mcu_fan_resume(struct device *dev)
 {
 	struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
+	int ret, ret2;
+
+	ret = regulator_enable(ctx->power);
+	if (ret)
+		return ret;
 
-	return khadas_mcu_fan_set_level(ctx, ctx->level);
+	ret = khadas_mcu_fan_set_level(ctx, ctx->levels[ctx->level]);
+	if (ret) {
+		ret2 = regulator_disable(ctx->power);
+		if (ret2)
+			dev_err(dev, "failed to disable regulator after error %d: %d\n", ret,
+				ret2);
+		return ret;
+	}
+
+	return 0;
 }
 #endif
 

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v10 5/6] arm64: dts: amlogic: t7: Add i2c controller node
  2026-09-01 15:25 [PATCH v10 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
                   ` (3 preceding siblings ...)
  2026-09-01 15:25 ` [PATCH v10 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support Ronald Claveau via B4 Relay
@ 2026-09-01 15:25 ` Ronald Claveau via B4 Relay
  2026-09-01 15:34   ` sashiko-bot
  2026-09-01 15:25 ` [PATCH v10 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-01 15:25 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



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v10 6/6] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
  2026-09-01 15:25 [PATCH v10 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
                   ` (4 preceding siblings ...)
  2026-09-01 15:25 ` [PATCH v10 5/6] arm64: dts: amlogic: t7: Add i2c controller node Ronald Claveau via B4 Relay
@ 2026-09-01 15:25 ` Ronald Claveau via B4 Relay
  2026-09-01 15:34   ` sashiko-bot
  5 siblings, 1 reply; 13+ messages in thread
From: Ronald Claveau via B4 Relay @ 2026-09-01 15:25 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



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v10 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant
  2026-09-01 15:25 ` [PATCH v10 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant Ronald Claveau via B4 Relay
@ 2026-09-01 15:33   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-01 15:33 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: linux-amlogic, lee, conor+dt, robh, devicetree, neil.armstrong,
	mfd

> 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.
> 
> Introduce struct khadas_mcu_fan_pdata to pass the fan
> 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).
> 
> 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>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260901-add-mcu-fan-khadas-vim4-v10-0-aecdb9955a30@aliel.fr?part=3


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v10 6/6] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
  2026-09-01 15:25 ` [PATCH v10 6/6] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node Ronald Claveau via B4 Relay
@ 2026-09-01 15:34   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-01 15:34 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: mfd, linux-amlogic, lee, neil.armstrong, conor+dt, robh,
	devicetree

> 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>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260901-add-mcu-fan-khadas-vim4-v10-0-aecdb9955a30@aliel.fr?part=6


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v10 5/6] arm64: dts: amlogic: t7: Add i2c controller node
  2026-09-01 15:25 ` [PATCH v10 5/6] arm64: dts: amlogic: t7: Add i2c controller node Ronald Claveau via B4 Relay
@ 2026-09-01 15:34   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-01 15:34 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: robh, neil.armstrong, conor+dt, linux-amlogic, devicetree, lee,
	mfd

> 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>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260901-add-mcu-fan-khadas-vim4-v10-0-aecdb9955a30@aliel.fr?part=5


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v10 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations
  2026-09-01 15:25 ` [PATCH v10 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations Ronald Claveau via B4 Relay
@ 2026-09-01 15:36   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-01 15:36 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: conor+dt, devicetree, lee, linux-amlogic, mfd, neil.armstrong,
	robh

> 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>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260901-add-mcu-fan-khadas-vim4-v10-0-aecdb9955a30@aliel.fr?part=2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v10 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
  2026-09-01 15:25 ` [PATCH v10 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support Ronald Claveau via B4 Relay
@ 2026-09-01 15:36   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-01 15:36 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: devicetree, neil.armstrong, mfd, linux-amlogic, lee, robh,
	conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Introducing a bespoke platform data structure (`struct khadas_mcu_fan_pdata`) for parent-initialized private resources violates MFD decoupling guidelines.
--

commit 8a8b8fef22780db703282e4a267b644d5339157a
Author: Ronald Claveau <linux-kernel-dev@aliel.fr>

mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support

This commit adds structures and registers to support per-variant configuration
for the Khadas MCU, specifically adding VIM4 support. It introduces an enum
for device matching and a custom platform data structure to pass fan
configuration from the parent to the sub-driver.

> diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
> index a99ba2ed0e4e0..7a9980ea63e7e 100644
> --- a/include/linux/mfd/khadas-mcu.h
> +++ b/include/linux/mfd/khadas-mcu.h

[ ... ]

> @@ -88,4 +95,21 @@ struct khadas_mcu {
>  	struct regmap *regmap;
>  };
>  
> +/**
> + * struct khadas_mcu_fan_pdata - fan sub-driver configuration
> + * @fan_reg: register address to write the fan level
> + * @levels: table mapping logical cooling-device states to raw fan levels
> + * @nlevels: number of entries in @levels
> + */
> +struct khadas_mcu_fan_pdata {
> +	unsigned int fan_reg;
> +	const unsigned int *levels;
> +	unsigned int nlevels;
> +};

[Severity: Low]
Does introducing this bespoke platform data structure for parent-initialized
private resources violate MFD decoupling guidelines?

The parent MFD driver is forced to handle fan-specific configuration (like
register addresses and levels) rather than being limited to genuinely shared
core resources. This creates tight coupling with the child driver and
violates the requirement that private resources be initialized directly in
the child.

> +
> +enum khadas_mcu_type {
> +	KHADAS_MCU_GENERIC = 1, /* VIM1/2/3, Edge, Edge-V */
> +	KHADAS_MCU_VIM4,
> +};
> +
>  #endif /* MFD_KHADAS_MCU_H */

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260901-add-mcu-fan-khadas-vim4-v10-0-aecdb9955a30@aliel.fr?part=1

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v10 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
  2026-09-01 15:25 ` [PATCH v10 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support Ronald Claveau via B4 Relay
@ 2026-09-01 15:58   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-01 15:58 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: neil.armstrong, devicetree, mfd, linux-amlogic, lee, robh,
	conor+dt

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Direct assignment of `dev->of_node` without `of_node_get()` causes a reference count underflow and use-after-free on device removal.
- [Medium] State desynchronization on `khadas_mcu_fan_suspend` error path leaves the fan permanently disabled.
- [Medium] Unchecked platform data pointer dereference causes a potential kernel panic.
- [Medium] Rolling back `regulator_enable` in the `khadas_mcu_fan_resume` error path causes a regulator enable count underflow on driver unbind.
--

commit 48a15d3c23acef32291aa52062459e22677349e6
Author: Ronald Claveau <linux-kernel-dev@aliel.fr>

thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support

This commit reads the fan register and level table from platform data instead
of hardcoding them. It also introduces regulator support for the fan's power
supply during probe, resume, and suspend.

> diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
> index 21b3d0a71bd0d..512a6f0ff7c26 100644
> --- a/drivers/thermal/khadas_mcu_fan.c
> +++ b/drivers/thermal/khadas_mcu_fan.c

[ ... ]

> @@ -76,22 +82,53 @@ 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 int khadas_mcu_fan_probe(struct platform_device *pdev)
>  {
> +	const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
>  	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 = dev->parent->of_node;

[Severity: High]
Does this code cause a reference count underflow and use-after-free on device
removal?  By assigning dev->of_node without incrementing the reference count
via of_node_get(), the driver core's unconditional of_node_put(dev->of_node)
on unbind could underflow the parent's reference count.

> +
>  	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
>  	if (!ctx)
>  		return -ENOMEM;
> +
>  	ctx->mcu = mcu;
> +	ctx->fan_reg = pdata->fan_reg;

[Severity: Medium]
Could this code cause a NULL pointer dereference?  If the device is manually
instantiated (e.g. via sysfs or a DT overlay) without providing the required
platform data, dev_get_platdata() returns NULL, which is then unconditionally
dereferenced here.

> +	ctx->levels = pdata->levels;
> +	ctx->nlevels = pdata->nlevels;
> +
> +	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);

[ ... ]

>  #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;
> -
> -	return 0;
> +	return regulator_disable(ctx->power);

[Severity: Medium]
If regulator_disable() fails here, the PM core aborts system suspend, and the
resume callback will not be executed.  Because the fan was successfully turned
off via khadas_mcu_fan_set_level(), but ctx->level was not updated to reflect
this, will the thermal framework later fail to restore the correct fan state
due to evaluating state == ctx->level in khadas_mcu_fan_set_cur_state()?

>  }
>  
>  static int khadas_mcu_fan_resume(struct device *dev)
>  {
>  	struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
> +	int ret, ret2;
> +
> +	ret = regulator_enable(ctx->power);
> +	if (ret)
> +		return ret;
>  
> -	return khadas_mcu_fan_set_level(ctx, ctx->level);
> +	ret = khadas_mcu_fan_set_level(ctx, ctx->levels[ctx->level]);
> +	if (ret) {
> +		ret2 = regulator_disable(ctx->power);

[Severity: Medium]
Does rolling back the regulator state here cause an enable count underflow
on driver unbind?

Because khadas_mcu_fan_probe() registered an unconditional cleanup action
via devm_add_action_or_reset(dev, khadas_mcu_fan_regulator_disable, ctx->power),
calling regulator_disable() here leaves the regulator disabled while the device
remains bound.  When the device is later unbound, the devm action will call
regulator_disable() again on the already disabled regulator.

> +		if (ret2)
> +			dev_err(dev, "failed to disable regulator after error %d: %d\n", ret,
> +				ret2);
> +		return ret;
> +	}
> +
> +	return 0;
>  }
>  #endif

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260901-add-mcu-fan-khadas-vim4-v10-0-aecdb9955a30@aliel.fr?part=4

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-09-01 15:58 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 15:25 [PATCH v10 0/6] Add VIM4 MCU/FAN support Ronald Claveau via B4 Relay
2026-09-01 15:25 ` [PATCH v10 1/6] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support Ronald Claveau via B4 Relay
2026-09-01 15:36   ` sashiko-bot
2026-09-01 15:25 ` [PATCH v10 2/6] mfd: khadas-mcu: Use MFD_CELL_* macros for cell declarations Ronald Claveau via B4 Relay
2026-09-01 15:36   ` sashiko-bot
2026-09-01 15:25 ` [PATCH v10 3/6] mfd: khadas-mcu: Add support for VIM4 MCU variant Ronald Claveau via B4 Relay
2026-09-01 15:33   ` sashiko-bot
2026-09-01 15:25 ` [PATCH v10 4/6] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support Ronald Claveau via B4 Relay
2026-09-01 15:58   ` sashiko-bot
2026-09-01 15:25 ` [PATCH v10 5/6] arm64: dts: amlogic: t7: Add i2c controller node Ronald Claveau via B4 Relay
2026-09-01 15:34   ` sashiko-bot
2026-09-01 15:25 ` [PATCH v10 6/6] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node Ronald Claveau via B4 Relay
2026-09-01 15:34   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox