From eb729a0532435a6d1603cbee877193c94243fdf8 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 15 Jul 2026 12:49:37 +0100 Subject: [PATCH 1/3] Revert "hwmon: emc2305: fixups for driver submitted to mailing lists" This reverts commit 6eb7aef127ac6e2125db80c969f50a04a5fbb05a. --- drivers/hwmon/emc2305.c | 112 +++------------------------------------- 1 file changed, 6 insertions(+), 106 deletions(-) diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index 4aa9855aa0bda..eef3b021671b0 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -15,8 +15,6 @@ #include #include -#define EMC2305_REG_FAN_STATUS 0x24 -#define EMC2305_REG_FAN_STALL_STATUS 0x25 #define EMC2305_REG_DRIVE_FAIL_STATUS 0x27 #define EMC2305_REG_VENDOR 0xfe #define EMC2305_FAN_MAX 0xff @@ -122,7 +120,6 @@ struct emc2305_data { bool pwm_separate; s16 pwm_shutdown[EMC2305_PWM_MAX]; u8 pwm_min[EMC2305_PWM_MAX]; - u8 pwm_max; u16 pwm_freq[EMC2305_PWM_MAX]; struct emc2305_cdev_data cdev_data[EMC2305_PWM_MAX]; }; @@ -294,7 +291,7 @@ static int emc2305_set_pwm(struct device *dev, long val, int channel) struct i2c_client *client = data->client; int ret; - if (val < data->pwm_min[channel] || val > data->pwm_max) + if (val < data->pwm_min[channel] || val > EMC2305_FAN_MAX) return -EINVAL; ret = i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(channel), val); @@ -305,49 +302,6 @@ static int emc2305_set_pwm(struct device *dev, long val, int channel) return 0; } -static int emc2305_get_tz_of(struct device *dev) -{ - struct device_node *np = dev->of_node; - struct emc2305_data *data = dev_get_drvdata(dev); - int ret = 0; - u8 val; - int i; - - /* OF parameters are optional - overwrite default setting - * if some of them are provided. - */ - - ret = of_property_read_u8(np, "emc2305,cooling-levels", &val); - if (!ret) - data->max_state = val; - else if (ret != -EINVAL) - return ret; - - ret = of_property_read_u8(np, "emc2305,pwm-max", &val); - if (!ret) - data->pwm_max = val; - else if (ret != -EINVAL) - return ret; - - ret = of_property_read_u8(np, "emc2305,pwm-min", &val); - if (!ret) - for (i = 0; i < EMC2305_PWM_MAX; i++) - data->pwm_min[i] = val; - else if (ret != -EINVAL) - return ret; - - /* Not defined or 0 means one thermal zone over all cooling devices. - * Otherwise - separated thermal zones for each PWM channel. - */ - ret = of_property_read_u8(np, "emc2305,pwm-channel", &val); - if (!ret) - data->pwm_separate = (val != 0); - else if (ret != -EINVAL) - return ret; - - return 0; -} - static int emc2305_set_single_tz(struct device *dev, struct device_node *fan_node, int idx) { struct emc2305_data *data = dev_get_drvdata(dev); @@ -357,16 +311,10 @@ static int emc2305_set_single_tz(struct device *dev, struct device_node *fan_nod cdev_idx = (idx) ? idx - 1 : 0; pwm = data->pwm_min[cdev_idx]; - if (dev->of_node) - data->cdev_data[cdev_idx].cdev = - devm_thermal_of_child_cooling_device_register(dev, fan_node, - emc2305_fan_name[idx], data, - &emc2305_cooling_ops); - else - data->cdev_data[cdev_idx].cdev = - thermal_cooling_device_register(emc2305_fan_name[idx], - data, - &emc2305_cooling_ops); + data->cdev_data[cdev_idx].cdev = + devm_thermal_of_child_cooling_device_register(dev, fan_node, + emc2305_fan_name[idx], data, + &emc2305_cooling_ops); if (IS_ERR(data->cdev_data[cdev_idx].cdev)) { dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]); @@ -399,19 +347,6 @@ static int emc2305_set_single_tz(struct device *dev, struct device_node *fan_nod return 0; } -static void emc2305_unset_tz(struct device *dev) -{ - struct emc2305_data *data = dev_get_drvdata(dev); - int i; - - /* Unregister cooling device. */ - if (!dev->of_node) { - for (i = 0; i < EMC2305_PWM_MAX; i++) - if (data->cdev_data[i].cdev) - thermal_cooling_device_unregister(data->cdev_data[i].cdev); - } -} - static int emc2305_set_tz(struct device *dev) { struct emc2305_data *data = dev_get_drvdata(dev); @@ -423,13 +358,9 @@ static int emc2305_set_tz(struct device *dev) for (i = 0; i < data->pwm_num; i++) { ret = emc2305_set_single_tz(dev, dev->of_node, i + 1); if (ret) - goto thermal_cooling_device_register_fail; + return ret; } return 0; - -thermal_cooling_device_register_fail: - emc2305_unset_tz(dev); - return ret; } static umode_t @@ -748,7 +679,6 @@ static int emc2305_probe(struct i2c_client *client) data->pwm_min[i] = pdata->pwm_min[i]; data->pwm_freq[i] = pdata->pwm_freq[i]; } - data->pwm_max = EMC2305_FAN_MAX; } else { data->max_state = EMC2305_FAN_MAX_STATE; data->pwm_separate = false; @@ -758,24 +688,12 @@ static int emc2305_probe(struct i2c_client *client) data->pwm_min[i] = EMC2305_FAN_MIN; data->pwm_freq[i] = base_freq_table[3]; } - data->pwm_max = EMC2305_FAN_MAX; - if (dev->of_node) { - ret = emc2305_get_tz_of(dev); - if (ret < 0) - return ret; - } } } else { data->max_state = EMC2305_FAN_MAX_STATE; data->pwm_separate = false; for (i = 0; i < EMC2305_PWM_MAX; i++) data->pwm_min[i] = EMC2305_FAN_MIN; - data->pwm_max = EMC2305_FAN_MAX; - if (dev->of_node) { - ret = emc2305_get_tz_of(dev); - if (ret < 0) - return ret; - } } data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "emc2305", data, @@ -823,12 +741,6 @@ static int emc2305_probe(struct i2c_client *client) return ret; } - /* Acknowledge any existing faults. Stops the device responding on the - * SMBus alert address. - */ - i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STALL_STATUS); - i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STATUS); - return 0; } @@ -851,21 +763,10 @@ static void emc2305_shutdown(struct i2c_client *client) static const struct of_device_id of_emc2305_match_table[] = { { .compatible = "microchip,emc2305", }, - { .compatible = "microchip,emc2303", }, - { .compatible = "microchip,emc2302", }, - { .compatible = "microchip,emc2301", }, {}, }; MODULE_DEVICE_TABLE(of, of_emc2305_match_table); -static void emc2305_remove(struct i2c_client *client) -{ - struct device *dev = &client->dev; - - if (IS_REACHABLE(CONFIG_THERMAL)) - emc2305_unset_tz(dev); -} - static struct i2c_driver emc2305_driver = { .driver = { .name = "emc2305", @@ -873,7 +774,6 @@ static struct i2c_driver emc2305_driver = { }, .probe = emc2305_probe, .shutdown = emc2305_shutdown, - .remove = emc2305_remove, .id_table = emc2305_ids, }; From 3f07aeddf09c46e420a42b0eae1e4011b1034989 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 15 Jul 2026 12:51:06 +0100 Subject: [PATCH 2/3] hwmon: emc2305: Acknowledge all errors during probe If the fan controller has detected any errors it responds on the SMBus Alert Response Address (0x0c). As the driver doesn't currently handle SMBus Alert, acknowledge all errors on probe so that the fan controller is doesn't respond to that address. Signed-off-by: Dave Stevenson --- drivers/hwmon/emc2305.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index eef3b021671b0..4f0a94a4d41d3 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -15,6 +15,8 @@ #include #include +#define EMC2305_REG_FAN_STATUS 0x24 +#define EMC2305_REG_FAN_STALL_STATUS 0x25 #define EMC2305_REG_DRIVE_FAIL_STATUS 0x27 #define EMC2305_REG_VENDOR 0xfe #define EMC2305_FAN_MAX 0xff @@ -741,6 +743,12 @@ static int emc2305_probe(struct i2c_client *client) return ret; } + /* Acknowledge any existing faults. Stops the device responding on the + * SMBus alert address. + */ + i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STALL_STATUS); + i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STATUS); + return 0; } From d765cc8e1a836437c4780f5780b1180060405f98 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 16 Jul 2026 15:03:54 +0100 Subject: [PATCH 3/3] dtoverlays: Update i2c-fan for the mainline emc2305 driver We had backported an early version of the emc230[125] driver. The final version that was merged configured things slightly differently, and dropped the ability to set pwm-min and pwm-max. Adopt the new approach, and drop the pwm-min and pwm-max overrides. Signed-off-by: Dave Stevenson --- arch/arm/boot/dts/overlays/README | 4 ---- .../arm/boot/dts/overlays/i2c-fan-overlay.dts | 19 ++++++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 9d01818906297..1d76dffbdc2a9 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -2247,10 +2247,6 @@ Params: addr Sets the address for the fan controller. Note i2c-bus Supports all the standard I2C bus selection parameters - see "dtoverlay -h i2c-bus" - minpwm PWM setting for the fan when the SoC is below - mintemp (range 0-255. default 0) - maxpwm PWM setting for the fan when the SoC is above - maxtemp (range 0-255. default 255) midtemp Temperature (in millicelsius) at which the fan begins to speed up (default 50000) diff --git a/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts b/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts index 43a0db6fe5cff..675a75c76425a 100644 --- a/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts +++ b/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts @@ -19,7 +19,14 @@ emc2301: emc2301@2f { compatible = "microchip,emc2301", "microchip,emc2305"; reg = <0x2f>; - #cooling-cells = <0x02>; + #pwm-cells = <3>; + + fan0: fan@0 { + reg = <0x0>; + pwms = <&emc2301 26000 0 1>; + #cooling-cells = <2>; + }; + }; }; }; @@ -52,26 +59,24 @@ __overlay__ { map0: map0 { trip = <&fanmid0>; - cooling-device = <&emc2301 2 6>; + cooling-device = <&fan0 2 6>; }; map1: map1 { trip = <&fanmax0>; - cooling-device = <&emc2301 7 THERMAL_NO_LIMIT>; + cooling-device = <&fan0 7 THERMAL_NO_LIMIT>; }; }; }; __overrides__ { addr = <&emc2301>,"reg:0"; - minpwm = <&emc2301>,"emc2305,pwm-min.0"; - maxpwm = <&emc2301>,"emc2305,pwm-max.0"; midtemp = <&fanmid0>,"temperature:0"; midtemp_hyst = <&fanmid0>,"hysteresis:0"; maxtemp = <&fanmax0>,"temperature:0"; maxtemp_hyst = <&fanmax0>,"hysteresis:0"; emc2301 = <0>,"+0", - <&map0>,"cooling-device:0=",<&emc2301>, - <&map1>,"cooling-device:0=",<&emc2301>; + <&map0>,"cooling-device:0=",<&fan0>, + <&map1>,"cooling-device:0=",<&fan0>; }; };