Add Khadas MCU and fan control support for Khadas Edge 2
Subsystems (5)
v2 cover Add Khadas MCU and fan control support for Khadas Edge 2
From: Muhammed Efe Cetin <[email protected]>
This patch series adds support for the Khadas MCU and fan control for Khadas Edge 2 board.
The first patch updates the device tree bindings to add new "khadas,mcu-v2" compatible for Khadas Edge 2.
The second mfd patch removes unused nvmem code.
The third patch adds the Khadas Edge 2 registers to the mfd driver.
The fourth patch adds support for Khadas Edge 2's new fan control registers to MCU thermal driver and the last one adds the Khadas Edge 2 device tree node for the MCU and fan control. And the final patch adds the Khadas Edge 2 device tree node for the MCU and fan control.
Changes in v2:
- Added a new compatible "khadas,mcu-v2" for Khadas Edge 2 instead of cooling-levels property in old variant.
- Added Khadas Edge 2 registers with KHADAS_MCU_V2 prefix.
Muhammed Efe Cetin (5):
dt-bindings: mfd: khadas-mcu: add new compatible for Khadas Edge 2
mfd: khadas-mcu: drop unused nvmem code
mfd: add Khadas Edge 2 registers to khadas-mcu.
thermal: khadas_mcu_fan: add support for Khadas Edge 2
arm64: dts: rockchip: add Khadas MCU and fan control nodes
.../devicetree/bindings/mfd/khadas,mcu.yaml | 5 +- .../dts/rockchip/rk3588s-khadas-edge2.dts | 58 +++++++++++++++++++ drivers/mfd/khadas-mcu.c | 56 +++++++++++++----- drivers/thermal/khadas_mcu_fan.c | 20 +++++-- include/linux/mfd/khadas-mcu.h | 32 ++++++++++ 5 files changed, 152 insertions(+), 19 deletions(-)
Signature · 1 line
2.50.1
PATCH v2 1/5 dt-bindings: mfd: khadas-mcu: add new compatible for Khadas Edge 2
From: Muhammed Efe Cetin <[email protected]>
Add new khadas,mcu-v2 compatible which is going to be used with Khadas Edge 2 and potantially new Khadas boards like Vim4, using the same fan control register.
--- Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +3 -2
@@ -11,13 +11,14 @@ maintainers: description: | Khadas embeds a microcontroller on their VIM and Edge boards adding some - system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory + system feature as PWM Fan control (for VIM2 rev14, VIM3, Edge2), User memory storage, IR/Key resume control, system power LED control and more. properties: compatible: enum: - - khadas,mcu # MCU revision is discoverable + - khadas,mcu # Used by VIM2 rev14, VIM3 + - khadas,mcu-v2 # Used by Edge2 "#cooling-cells": # Only needed for boards having FAN control feature const: 2
Signature · 1 line
2.50.1
Re: [PATCH v2 1/5] dt-bindings: mfd: khadas-mcu: add new compatible for Khadas Edge 2
Quoted 19 lines · On Tue, Jul 22, 2025 at 03:38:11PM +0300, [email protected] wrote:
From: Muhammed Efe Cetin <[email protected]>
Add new khadas,mcu-v2 compatible which is going to be used with Khadas Edge 2 and potantially new Khadas boards like Vim4, using the same fan control register.
Signed-off-by Muhammed Efe Cetin <[email protected]>--- Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +0
-0@@ -11,13 +11,14 @@ maintainers: description: | Khadas embeds a microcontroller on their VIM and Edge boards adding some
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml maintainers: · line 21
Quoted 10 lines
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +3
-2- system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory + system feature as PWM Fan control (for VIM2 rev14, VIM3, Edge2), User memory storage, IR/Key resume control, system power LED control and more. properties: compatible: enum: - - khadas,mcu # MCU revision is discoverable + - khadas,mcu # Used by VIM2 rev14, VIM3 + - khadas,mcu-v2 # Used by Edge2
You need documented versioning (provide a link/datasheet). Otherwise you should use compatibles specific to the hardware, e.g. edge2
Best regards,
Krzysztof
PATCH v2 2/5 mfd: khadas-mcu: drop unused nvmem code
In reply to [email protected]From: Muhammed Efe Cetin <[email protected]>
Drop "khadas-mcu-user-mem" code since it is not used anywhere.
--- drivers/mfd/khadas-mcu.c | 11 ----------- 1 file changed, 11 deletions(-)
drivers/mfd/khadas-mcu.c +0 -11
@@ -80,10 +80,6 @@ static struct mfd_cell khadas_mcu_fan_cells[] = { { .name = "khadas-mcu-fan-ctrl", }, }; -static struct mfd_cell khadas_mcu_cells[] = { - { .name ="khadas-mcu-user-mem" , }, -}; -static int khadas_mcu_probe (struct i2c_client *client) {struct device *dev = &client->dev;
@@ -105,13 +101,6 @@ static int khadas_mcu_probe(struct i2c_client *client)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 (of_property_present (dev->of_node,"#cooling-cells" )) return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, khadas_mcu_fan_cells,
Signature · 1 line
2.50.1
PATCH v2 3/5 mfd: add Khadas Edge 2 registers to khadas-mcu.
In reply to [email protected]From: Muhammed Efe Cetin <[email protected]>
Add Khadas Edge 2 MCU registers to khadas-mcu.h with KHADAS_MCU_V2 register. New "khadas,mcu-v2" compatible added as it is quite different compared to older MCU variants and there are no way to distinguish them using any register.
--- drivers/mfd/khadas-mcu.c | 45 ++++++++++++++++++++++++++++++++-- include/linux/mfd/khadas-mcu.h | 32 ++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-)
drivers/mfd/khadas-mcu.c +43 -2
@@ -32,6 +32,20 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) } } +static bool khadas_mcu_reg_volatile_v2 (struct device *dev,unsigned int reg) +{ +switch (reg) { +case KHADAS_MCU_V2_SLEEP_EN_REG : +case KHADAS_MCU_V2_LED_ON_RAM_REG : +case KHADAS_MCU_V2_FAN_CTRL_REG : +case KHADAS_MCU_V2_WDT_EN_REG : +case KHADAS_MCU_V2_SYS_RST_REG : +return true; +default : +return false; + } +} +static bool khadas_mcu_reg_writeable (struct device *dev,unsigned int reg) {switch (reg) {
@@ -65,6 +79,17 @@ static bool khadas_mcu_reg_writeable(struct device *dev, unsigned int reg) } } +static bool khadas_mcu_reg_writeable_v2 (struct device *dev,unsigned int reg) +{ +switch (reg) { +case KHADAS_MCU_V2_VERSION1_REG : +case KHADAS_MCU_V2_VERSION2_REG : +return false; +default : +return true; + } +} +static const struct regmap_config khadas_mcu_regmap_config = { .reg_bits =8 , .reg_stride =1 ,
@@ -75,8 +100,18 @@ static const struct regmap_config khadas_mcu_regmap_config = { .cache_type = REGCACHE_MAPLE, }; +static const struct regmap_config khadas_mcu_regmap_config_v2 = { + .reg_bits =8 , + .reg_stride =1 , + .val_bits =8 , + .max_register =KHADAS_MCU_V2_SYS_RST_REG , + .volatile_reg = khadas_mcu_reg_volatile_v2, + .writeable_reg = khadas_mcu_reg_writeable_v2, + .cache_type =REGCACHE_MAPLE , +}; +static struct mfd_cell khadas_mcu_fan_cells[] = { -/* VIM1/2 Rev13+ and VIM3 only */ +/* VIM1/2 Rev13+, VIM3 and Edge2 only */ { .name ="khadas-mcu-fan-ctrl" , }, };
@@ -84,6 +119,7 @@ static int khadas_mcu_probe(struct i2c_client *client) {struct device *dev = &client->dev;struct khadas_mcu *ddata; +const struct regmap_config *regmap_config;int ret; ddata =devm_kzalloc (dev,sizeof (*ddata),GFP_KERNEL );
@@ -94,7 +130,11 @@ static int khadas_mcu_probe(struct i2c_client *client) ddata->dev = dev; - ddata->regmap =devm_regmap_init_i2c (client, &khadas_mcu_regmap_config); +if (of_device_is_compatible (dev->of_node,"khadas,mcu-v2" )) + regmap_config = &khadas_mcu_regmap_config_v2; +else + regmap_config = &khadas_mcu_regmap_config; + ddata->regmap =devm_regmap_init_i2c (client, regmap_config);if (IS_ERR (ddata->regmap)) { ret =PTR_ERR (ddata->regmap);dev_err (dev,"Failed to allocate register map: %d\n" , ret);
@@ -113,6 +153,7 @@ 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-v2" , }, {}, };MODULE_DEVICE_TABLE (of, khadas_mcu_of_match);
include/linux/mfd/khadas-mcu.h +32 -0
@@ -10,6 +10,7 @@#ifndef MFD_KHADAS_MCU_H #define MFD_KHADAS_MCU_H +/* Registers used by Khadas VIM2 rev14 and VIM3 */ #define KHADAS_MCU_PASSWD_VEN_0_REG 0x00/* RO */ #define KHADAS_MCU_PASSWD_VEN_1_REG 0x01/* RO */ #define KHADAS_MCU_PASSWD_VEN_2_REG 0x02/* RO */
@@ -70,12 +71,43 @@#define KHADAS_MCU_WOL_INIT_START_REG 0x87/* WO */ #define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88/* WO */ +/* Registers used by Khadas Edge 2 */ +#define KHADAS_MCU_V2_VERSION1_REG 0x12/* RO */ +#define KHADAS_MCU_V2_VERSION2_REG 0x13/* RO */ +#define KHADAS_MCU_V2_BOOT_MODE_REG 0x20/* RW */ +#define KHADAS_MCU_V2_BOOT_EN_DCIN_REG 0x21/* RW */ +#define KHADAS_MCU_V2_BOOT_EN_RTC_REG 0x22/* RW */ +#define KHADAS_MCU_V2_LED_MODE_ON_REG 0x23/* RW */ +#define KHADAS_MCU_V2_LED_MODE_OFF_REG 0x24/* RW */ +#define KHADAS_MCU_V2_RGB_ON_R_REG 0x25/* RW */ +#define KHADAS_MCU_V2_RGB_ON_G_REG 0x26/* RW */ +#define KHADAS_MCU_V2_RGB_ON_B_REG 0x27/* RW */ +#define KHADAS_MCU_V2_RGB_OFF_R_REG 0x28/* RW */ +#define KHADAS_MCU_V2_RGB_OFF_G_REG 0x29/* RW */ +#define KHADAS_MCU_V2_RGB_OFF_B_REG 0x2A/* RW */ +#define KHADAS_MCU_V2_REST_CONF_REG 0x2C/* WO */ +#define KHADAS_MCU_V2_SLEEP_EN_REG 0x2E/* RW */ +#define KHADAS_MCU_V2_BOOT_EN_IR_REG 0x2F/* RW */ +#define KHADAS_MCU_V2_IR1_CUST1_REG 0x30/* RW */ +#define KHADAS_MCU_V2_IR1_CUST2_REG 0x31/* RW */ +#define KHADAS_MCU_V2_IR1_ORDER1_REG 0x32/* RW */ +#define KHADAS_MCU_V2_IR1_ORDER2_REG 0x33/* RW */ +#define KHADAS_MCU_V2_IR2_CUST1_REG 0x34/* RW */ +#define KHADAS_MCU_V2_IR2_CUST2_REG 0x35/* RW */ +#define KHADAS_MCU_V2_IR2_ORDER1_REG 0x36/* RW */ +#define KHADAS_MCU_V2_IR2_ORDER2_REG 0x37/* RW */ +#define KHADAS_MCU_V2_LED_ON_RAM_REG 0x89/* WO */ +#define KHADAS_MCU_V2_FAN_CTRL_REG 0x8A/* WO */ +#define KHADAS_MCU_V2_WDT_EN_REG 0x8B/* WO */ +#define KHADAS_MCU_V2_SYS_RST_REG 0x91/* WO */ +enum {KHADAS_BOARD_VIM1 =0x1 ,KHADAS_BOARD_VIM2 ,KHADAS_BOARD_VIM3 ,KHADAS_BOARD_EDGE =0x11 ,KHADAS_BOARD_EDGE_V , +KHADAS_BOARD_EDGE2 , };/**
Signature · 1 line
2.50.1
Re: [PATCH v2 3/5] mfd: add Khadas Edge 2 registers to khadas-mcu.
drivers/mfd/khadas-mcu.c static int khadas_mcu_probe(struct i2c_client *client) · line 133
Quoted 7 lines · On Tue, Jul 22, 2025 at 03:38:13PM +0300, [email protected] wrote:
drivers/mfd/khadas-mcu.c +1
-1ddata =devm_kzalloc (dev,sizeof (*ddata),GFP_KERNEL );@@ -94,7 +130,11 @@ static int khadas_mcu_probe(struct i2c_client *client) ddata->dev = dev; - ddata->regmap =devm_regmap_init_i2c (client, &khadas_mcu_regmap_config); +if (of_device_is_compatible (dev->of_node,"khadas,mcu-v2" ))
This does not scale. Use device match data for exactly this purpose.
drivers/mfd/khadas-mcu.c static int khadas_mcu_probe(struct i2c_client *client) · line 156
Quoted 12 lines
drivers/mfd/khadas-mcu.c +5
-0+ regmap_config = &khadas_mcu_regmap_config_v2; + else + regmap_config = &khadas_mcu_regmap_config; + ddata->regmap =devm_regmap_init_i2c (client, regmap_config);if (IS_ERR (ddata->regmap)) { ret =PTR_ERR (ddata->regmap);dev_err (dev,"Failed to allocate register map: %d\n" , ret);@@ -113,6 +153,7 @@ 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-v2", },
So devices are 100% compatible? Empty match data suggests that...
Best regards,
Krzysztof
PATCH v2 4/5 thermal: khadas_mcu_fan: add support for Khadas Edge 2
In reply to [email protected]From: Muhammed Efe Cetin <[email protected]>
Fan control on the Khadas Edge 2 is controlled with the 0x8A register, using percentage values from 0 to 100, whereas there are only 3 constant steps in previous Khadas boards. Therefore, i adjusted max_level and fan_ctrl_reg when the mcu node is defined with khadas-mcu-v2 compatible.
--- drivers/thermal/khadas_mcu_fan.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
drivers/thermal/khadas_mcu_fan.c +16 -4
@@ -15,10 +15,13 @@#include <linux/thermal.h> #define MAX_LEVEL 3 +#define MAX_LEVEL_V2 100struct khadas_mcu_fan_ctx {struct khadas_mcu *mcu;unsigned int level; +unsigned int max_level; +unsigned int fan_ctrl_reg;struct thermal_cooling_device *cdev; };
@@ -26,8 +29,7 @@ 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 , + ret =regmap_write (ctx->mcu->regmap, ctx->fan_ctrl_reg, level);if (ret)return ret;
@@ -40,7 +42,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 +65,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)
@@ -88,6 +92,14 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)if (!ctx)return -ENOMEM ; ctx->mcu = mcu; + ctx->max_level =MAX_LEVEL ; + ctx->fan_ctrl_reg =KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG ; + +if (of_device_is_compatible (mcu->dev->of_node,"khadas,mcu-v2" )) { + ctx->fan_ctrl_reg =KHADAS_MCU_V2_FAN_CTRL_REG ; + ctx->max_level =MAX_LEVEL_V2 ; + } +platform_set_drvdata (pdev, ctx); cdev = devm_thermal_of_cooling_device_register(dev->parent,
Signature · 1 line
2.50.1
PATCH v2 5/5 arm64: dts: rockchip: add Khadas MCU and fan control nodes
In reply to [email protected]From: Muhammed Efe Cetin <[email protected]>
Add Khadas MCU fan control to Khadas Edge 2 with 4 fan control levels.
--- .../dts/rockchip/rk3588s-khadas-edge2.dts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+)
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +58 -0
@@ -271,12 +271,70 @@ hym8563: rtc@51 { clock-output-names = "hym8563"; wakeup-source; }; + + khadas_mcu: system-controller@18 { + compatible = "khadas,mcu-v2"; + reg = <0x18>; + #cooling-cells = <2>; + }; }; &i2s5_8ch { status = "okay"; }; +&package_thermal { + polling-delay = <2000>; + + trips { + package_fan0: package-fan0 { + temperature = <50000>; + hysteresis = <5000>; + type = "active"; + }; + + package_fan1: package-fan1 { + temperature = <60000>; + hysteresis = <5000>; + type = "active"; + }; + + package_fan2: package-fan2 { + temperature = <65000>; + hysteresis = <5000>; + type = "active"; + }; + + package_fan3: package-fan3 { + temperature = <75000>; + hysteresis = <5000>; + type = "active"; + }; + }; + + cooling-maps { + map0 { + trip = <&package_fan0>; + cooling-device = <&khadas_mcu THERMAL_NO_LIMIT 50>; + }; + + map1 { + trip = <&package_fan1>; + cooling-device = <&khadas_mcu 50 72>; + }; + + map2 { + trip = <&package_fan2>; + cooling-device = <&khadas_mcu 72 100>; + }; + + map3 { + trip = <&package_fan3>; + cooling-device = <&khadas_mcu 100 THERMAL_NO_LIMIT>; + }; + }; +}; + &pd_gpu { domain-supply = <&vdd_gpu_s0>; };
Signature · 1 line
2.50.1