diff --git a/patch/kernel/archive/meson64-6.1/hwmon-emc2305-fixups-for-driver.patch b/patch/kernel/archive/meson64-6.1/hwmon-emc2305-fixups-for-driver.patch new file mode 100644 index 0000000000..c6de52f544 --- /dev/null +++ b/patch/kernel/archive/meson64-6.1/hwmon-emc2305-fixups-for-driver.patch @@ -0,0 +1,212 @@ +From f6894c2a869e72a414cef2434d4f1f41197b1356 Mon Sep 17 00:00:00 2001 +From: Patrick Yavitz +Date: Tue, 10 Oct 2023 18:51:22 -0400 +Subject: [PATCH] hwmon: emc2305: fixups for driver + +BPI-CM4 fan control + +hwmon: emc2305: fixups for driver +The driver had a number of issues, checkpatch warnings/errors, +and other limitations, so fix these up to make it usable. +hwmon: emc2305: Change OF properties pwm-min & pwm-max to u8 +hwmon: emc2305: Add calls to initialize cooling maps +https://github.com/raspberrypi/linux/commits/233096b8a9023f7e02960543c85447d46af81e81/drivers/hwmon/emc2305.c + +Tested-on: CM4-IO-BASE-B: https://www.waveshare.com/wiki/CM4-IO-BASE-B +Signed-off-by: Phil Elwell +Signed-off-by: Dave Stevenson +Signed-off-by: Patrick Yavitz +--- + drivers/hwmon/emc2305.c | 96 +++++++++++++++++++++++++++++++++++++---- + 1 file changed, 88 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c +index e42ae43f3de4..de976a7521b3 100644 +--- a/drivers/hwmon/emc2305.c ++++ b/drivers/hwmon/emc2305.c +@@ -15,12 +15,13 @@ + static const unsigned short + emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END }; + ++#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 + #define EMC2305_FAN_MIN 0x00 + #define EMC2305_FAN_MAX_STATE 10 +-#define EMC2305_DEVICE 0x34 + #define EMC2305_VENDOR 0x5d + #define EMC2305_REG_PRODUCT_ID 0xfd + #define EMC2305_TACH_REGS_UNUSE_BITS 3 +@@ -39,6 +40,7 @@ emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_EN + #define EMC2305_RPM_FACTOR 3932160 + + #define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * (n)) ++#define EMC2305_REG_FAN_CFG(n) (0x32 + 0x10 * (n)) + #define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * (n)) + #define EMC2305_REG_FAN_TACH(n) (0x3e + 0x10 * (n)) + +@@ -58,6 +60,16 @@ static const struct i2c_device_id emc2305_ids[] = { + }; + MODULE_DEVICE_TABLE(i2c, emc2305_ids); + ++static const struct of_device_id emc2305_dt_ids[] = { ++ { .compatible = "smsc,emc2305" }, ++ { .compatible = "microchip,emc2305" }, ++ { .compatible = "microchip,emc2303" }, ++ { .compatible = "microchip,emc2302" }, ++ { .compatible = "microchip,emc2301" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, emc2305_dt_ids); ++ + /** + * @cdev: cooling device; + * @curr_state: cooling current state; +@@ -101,6 +113,7 @@ struct emc2305_data { + u8 pwm_num; + bool pwm_separate; + u8 pwm_min[EMC2305_PWM_MAX]; ++ u8 pwm_max; + struct emc2305_cdev_data cdev_data[EMC2305_PWM_MAX]; + }; + +@@ -273,7 +286,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 > EMC2305_FAN_MAX) ++ if (val < data->pwm_min[channel] || val > data->pwm_max) + return -EINVAL; + + ret = i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(channel), val); +@@ -284,6 +297,49 @@ 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, int idx) + { + struct emc2305_data *data = dev_get_drvdata(dev); +@@ -293,9 +349,17 @@ static int emc2305_set_single_tz(struct device *dev, int idx) + cdev_idx = (idx) ? idx - 1 : 0; + pwm = data->pwm_min[cdev_idx]; + +- data->cdev_data[cdev_idx].cdev = +- thermal_cooling_device_register(emc2305_fan_name[idx], data, +- &emc2305_cooling_ops); ++ if (dev->of_node) ++ data->cdev_data[cdev_idx].cdev = ++ devm_thermal_of_cooling_device_register(dev, dev->of_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); + + if (IS_ERR(data->cdev_data[cdev_idx].cdev)) { + dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]); +@@ -348,9 +412,11 @@ static void emc2305_unset_tz(struct device *dev) + int i; + + /* Unregister cooling device. */ +- for (i = 0; i < EMC2305_PWM_MAX; i++) +- if (data->cdev_data[i].cdev) +- thermal_cooling_device_unregister(data->cdev_data[i].cdev); ++ 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 umode_t +@@ -572,11 +638,18 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id * + data->pwm_separate = pdata->pwm_separate; + for (i = 0; i < EMC2305_PWM_MAX; i++) + data->pwm_min[i] = pdata->pwm_min[i]; ++ data->pwm_max = EMC2305_FAN_MAX; + } 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, +@@ -597,6 +670,12 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id * + 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; + } + +@@ -612,6 +691,7 @@ static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", ++ .of_match_table = emc2305_dt_ids, + }, + .probe = emc2305_probe, + .remove = emc2305_remove, +-- +2.39.2 + diff --git a/patch/kernel/archive/meson64-6.5/hwmon-emc2305-fixups-for-driver.patch b/patch/kernel/archive/meson64-6.5/hwmon-emc2305-fixups-for-driver.patch new file mode 100644 index 0000000000..73f9c446fd --- /dev/null +++ b/patch/kernel/archive/meson64-6.5/hwmon-emc2305-fixups-for-driver.patch @@ -0,0 +1,212 @@ +From 6f3753690d5117fc5893ee9a6cff69d6019d4bea Mon Sep 17 00:00:00 2001 +From: Patrick Yavitz +Date: Tue, 10 Oct 2023 18:54:22 -0400 +Subject: [PATCH] hwmon: emc2305: fixups for driver + +BPI-CM4 fan control + +hwmon: emc2305: fixups for driver +The driver had a number of issues, checkpatch warnings/errors, +and other limitations, so fix these up to make it usable. +hwmon: emc2305: Change OF properties pwm-min & pwm-max to u8 +hwmon: emc2305: Add calls to initialize cooling maps +https://github.com/raspberrypi/linux/commits/233096b8a9023f7e02960543c85447d46af81e81/drivers/hwmon/emc2305.c + +Tested-on: CM4-IO-BASE-B: https://www.waveshare.com/wiki/CM4-IO-BASE-B +Signed-off-by: Phil Elwell +Signed-off-by: Dave Stevenson +Signed-off-by: Patrick Yavitz +--- + drivers/hwmon/emc2305.c | 96 +++++++++++++++++++++++++++++++++++++---- + 1 file changed, 88 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c +index 29f0e4945f19..2581166cb978 100644 +--- a/drivers/hwmon/emc2305.c ++++ b/drivers/hwmon/emc2305.c +@@ -15,12 +15,13 @@ + static const unsigned short + emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END }; + ++#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 + #define EMC2305_FAN_MIN 0x00 + #define EMC2305_FAN_MAX_STATE 10 +-#define EMC2305_DEVICE 0x34 + #define EMC2305_VENDOR 0x5d + #define EMC2305_REG_PRODUCT_ID 0xfd + #define EMC2305_TACH_REGS_UNUSE_BITS 3 +@@ -39,6 +40,7 @@ emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_EN + #define EMC2305_RPM_FACTOR 3932160 + + #define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * (n)) ++#define EMC2305_REG_FAN_CFG(n) (0x32 + 0x10 * (n)) + #define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * (n)) + #define EMC2305_REG_FAN_TACH(n) (0x3e + 0x10 * (n)) + +@@ -58,6 +60,16 @@ static const struct i2c_device_id emc2305_ids[] = { + }; + MODULE_DEVICE_TABLE(i2c, emc2305_ids); + ++static const struct of_device_id emc2305_dt_ids[] = { ++ { .compatible = "smsc,emc2305" }, ++ { .compatible = "microchip,emc2305" }, ++ { .compatible = "microchip,emc2303" }, ++ { .compatible = "microchip,emc2302" }, ++ { .compatible = "microchip,emc2301" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, emc2305_dt_ids); ++ + /** + * struct emc2305_cdev_data - device-specific cooling device state + * @cdev: cooling device +@@ -103,6 +115,7 @@ struct emc2305_data { + u8 pwm_num; + bool pwm_separate; + u8 pwm_min[EMC2305_PWM_MAX]; ++ u8 pwm_max; + struct emc2305_cdev_data cdev_data[EMC2305_PWM_MAX]; + }; + +@@ -275,7 +288,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 > EMC2305_FAN_MAX) ++ if (val < data->pwm_min[channel] || val > data->pwm_max) + return -EINVAL; + + ret = i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(channel), val); +@@ -286,6 +299,49 @@ 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, int idx) + { + struct emc2305_data *data = dev_get_drvdata(dev); +@@ -295,9 +351,17 @@ static int emc2305_set_single_tz(struct device *dev, int idx) + cdev_idx = (idx) ? idx - 1 : 0; + pwm = data->pwm_min[cdev_idx]; + +- data->cdev_data[cdev_idx].cdev = +- thermal_cooling_device_register(emc2305_fan_name[idx], data, +- &emc2305_cooling_ops); ++ if (dev->of_node) ++ data->cdev_data[cdev_idx].cdev = ++ devm_thermal_of_cooling_device_register(dev, dev->of_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); + + if (IS_ERR(data->cdev_data[cdev_idx].cdev)) { + dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]); +@@ -350,9 +414,11 @@ static void emc2305_unset_tz(struct device *dev) + int i; + + /* Unregister cooling device. */ +- for (i = 0; i < EMC2305_PWM_MAX; i++) +- if (data->cdev_data[i].cdev) +- thermal_cooling_device_unregister(data->cdev_data[i].cdev); ++ 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 umode_t +@@ -574,11 +640,18 @@ static int emc2305_probe(struct i2c_client *client) + data->pwm_separate = pdata->pwm_separate; + for (i = 0; i < EMC2305_PWM_MAX; i++) + data->pwm_min[i] = pdata->pwm_min[i]; ++ data->pwm_max = EMC2305_FAN_MAX; + } 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, +@@ -599,6 +672,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; + } + +@@ -614,6 +693,7 @@ static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", ++ .of_match_table = emc2305_dt_ids, + }, + .probe = emc2305_probe, + .remove = emc2305_remove, +-- +2.39.2 + diff --git a/patch/kernel/archive/meson64-6.6/hwmon-emc2305-fixups-for-driver.patch b/patch/kernel/archive/meson64-6.6/hwmon-emc2305-fixups-for-driver.patch new file mode 100644 index 0000000000..73f9c446fd --- /dev/null +++ b/patch/kernel/archive/meson64-6.6/hwmon-emc2305-fixups-for-driver.patch @@ -0,0 +1,212 @@ +From 6f3753690d5117fc5893ee9a6cff69d6019d4bea Mon Sep 17 00:00:00 2001 +From: Patrick Yavitz +Date: Tue, 10 Oct 2023 18:54:22 -0400 +Subject: [PATCH] hwmon: emc2305: fixups for driver + +BPI-CM4 fan control + +hwmon: emc2305: fixups for driver +The driver had a number of issues, checkpatch warnings/errors, +and other limitations, so fix these up to make it usable. +hwmon: emc2305: Change OF properties pwm-min & pwm-max to u8 +hwmon: emc2305: Add calls to initialize cooling maps +https://github.com/raspberrypi/linux/commits/233096b8a9023f7e02960543c85447d46af81e81/drivers/hwmon/emc2305.c + +Tested-on: CM4-IO-BASE-B: https://www.waveshare.com/wiki/CM4-IO-BASE-B +Signed-off-by: Phil Elwell +Signed-off-by: Dave Stevenson +Signed-off-by: Patrick Yavitz +--- + drivers/hwmon/emc2305.c | 96 +++++++++++++++++++++++++++++++++++++---- + 1 file changed, 88 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c +index 29f0e4945f19..2581166cb978 100644 +--- a/drivers/hwmon/emc2305.c ++++ b/drivers/hwmon/emc2305.c +@@ -15,12 +15,13 @@ + static const unsigned short + emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END }; + ++#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 + #define EMC2305_FAN_MIN 0x00 + #define EMC2305_FAN_MAX_STATE 10 +-#define EMC2305_DEVICE 0x34 + #define EMC2305_VENDOR 0x5d + #define EMC2305_REG_PRODUCT_ID 0xfd + #define EMC2305_TACH_REGS_UNUSE_BITS 3 +@@ -39,6 +40,7 @@ emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_EN + #define EMC2305_RPM_FACTOR 3932160 + + #define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * (n)) ++#define EMC2305_REG_FAN_CFG(n) (0x32 + 0x10 * (n)) + #define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * (n)) + #define EMC2305_REG_FAN_TACH(n) (0x3e + 0x10 * (n)) + +@@ -58,6 +60,16 @@ static const struct i2c_device_id emc2305_ids[] = { + }; + MODULE_DEVICE_TABLE(i2c, emc2305_ids); + ++static const struct of_device_id emc2305_dt_ids[] = { ++ { .compatible = "smsc,emc2305" }, ++ { .compatible = "microchip,emc2305" }, ++ { .compatible = "microchip,emc2303" }, ++ { .compatible = "microchip,emc2302" }, ++ { .compatible = "microchip,emc2301" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, emc2305_dt_ids); ++ + /** + * struct emc2305_cdev_data - device-specific cooling device state + * @cdev: cooling device +@@ -103,6 +115,7 @@ struct emc2305_data { + u8 pwm_num; + bool pwm_separate; + u8 pwm_min[EMC2305_PWM_MAX]; ++ u8 pwm_max; + struct emc2305_cdev_data cdev_data[EMC2305_PWM_MAX]; + }; + +@@ -275,7 +288,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 > EMC2305_FAN_MAX) ++ if (val < data->pwm_min[channel] || val > data->pwm_max) + return -EINVAL; + + ret = i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(channel), val); +@@ -286,6 +299,49 @@ 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, int idx) + { + struct emc2305_data *data = dev_get_drvdata(dev); +@@ -295,9 +351,17 @@ static int emc2305_set_single_tz(struct device *dev, int idx) + cdev_idx = (idx) ? idx - 1 : 0; + pwm = data->pwm_min[cdev_idx]; + +- data->cdev_data[cdev_idx].cdev = +- thermal_cooling_device_register(emc2305_fan_name[idx], data, +- &emc2305_cooling_ops); ++ if (dev->of_node) ++ data->cdev_data[cdev_idx].cdev = ++ devm_thermal_of_cooling_device_register(dev, dev->of_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); + + if (IS_ERR(data->cdev_data[cdev_idx].cdev)) { + dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]); +@@ -350,9 +414,11 @@ static void emc2305_unset_tz(struct device *dev) + int i; + + /* Unregister cooling device. */ +- for (i = 0; i < EMC2305_PWM_MAX; i++) +- if (data->cdev_data[i].cdev) +- thermal_cooling_device_unregister(data->cdev_data[i].cdev); ++ 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 umode_t +@@ -574,11 +640,18 @@ static int emc2305_probe(struct i2c_client *client) + data->pwm_separate = pdata->pwm_separate; + for (i = 0; i < EMC2305_PWM_MAX; i++) + data->pwm_min[i] = pdata->pwm_min[i]; ++ data->pwm_max = EMC2305_FAN_MAX; + } 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, +@@ -599,6 +672,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; + } + +@@ -614,6 +693,7 @@ static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", ++ .of_match_table = emc2305_dt_ids, + }, + .probe = emc2305_probe, + .remove = emc2305_remove, +-- +2.39.2 +