aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0891-hwmon-emc2305-fixups-for-driver-submitted-to-mailing.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0891-hwmon-emc2305-fixups-for-driver-submitted-to-mailing.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.15/950-0891-hwmon-emc2305-fixups-for-driver-submitted-to-mailing.patch226
1 files changed, 226 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0891-hwmon-emc2305-fixups-for-driver-submitted-to-mailing.patch b/target/linux/bcm27xx/patches-5.15/950-0891-hwmon-emc2305-fixups-for-driver-submitted-to-mailing.patch
new file mode 100644
index 0000000000..cade5681ba
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.15/950-0891-hwmon-emc2305-fixups-for-driver-submitted-to-mailing.patch
@@ -0,0 +1,226 @@
+From 50fe870273543a821f25e7f78ea7389183d819e7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 5 May 2022 15:46:07 +0100
+Subject: [PATCH] hwmon: emc2305: fixups for driver submitted to
+ mailing lists
+
+The driver had a number of issues, checkpatch warnings/errors,
+and other limitations, so fix these up to make it usable.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/hwmon/emc2305.c | 86 ++++++++++++++++++++++++-----------------
+ 1 file changed, 50 insertions(+), 36 deletions(-)
+
+--- a/drivers/hwmon/emc2305.c
++++ b/drivers/hwmon/emc2305.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0+
+ /*
+- * Hardware monitoring driver for EMC2305 fan controller
++ * Hardware monitoring driver for Microchip EMC2305 fan controller
+ *
+ * Copyright (C) 2022 Nvidia Technologies Ltd and Delta Networks, Inc.
+ */
+@@ -17,17 +17,17 @@
+ 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_DEVICE 0xfd
+ #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
+-#define EMC2305_TACH_CNT_MULTIPLIER 0x02
++#define EMC2305_TACH_CNT_MULTIPLIER 1 /* Set by FAN_CFG RNGx bits */
+ #define EMC2305_PWM_MAX 5
+ #define EMC2305_PWM_CHNL_CMN 0
+
+@@ -42,6 +42,7 @@ emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2
+ #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))
+
+@@ -62,7 +63,8 @@ static const struct i2c_device_id emc230
+ MODULE_DEVICE_TABLE(i2c, emc2305_ids);
+
+ static const struct of_device_id emc2305_dt_ids[] = {
+- { .compatible = "smsc,emc2305" },
++ { .compatible = "microchip,emc2305" },
++ { .compatible = "microchip,emc2301" },
+ { }
+ };
+ MODULE_DEVICE_TABLE(of, emc2305_dt_ids);
+@@ -187,7 +189,7 @@ static int emc2305_set_cur_state(struct
+ struct emc2305_data *data = cdev->devdata;
+ struct i2c_client *client = data->client;
+ u8 val, i;
+-
++
+ if (state > data->max_state)
+ return -EINVAL;
+
+@@ -200,19 +202,20 @@ static int emc2305_set_cur_state(struct
+ state = max_t(unsigned long, state, data->cdev_data[cdev_idx].last_hwmon_state);
+
+ val = EMC2305_PWM_STATE2DUTY(state, data->max_state, data->pwm_max);
++
+ if (val > EMC2305_FAN_MAX)
+ return -EINVAL;
+
+ data->cdev_data[cdev_idx].cur_state = state;
+ if (data->pwm_channel == EMC2305_PWM_CHNL_CMN)
+- /* Set the same PWM value in all channels
++ /* Set the same PWM value in all channels
+ * if common PWM channel is used.
+ */
+ for (i = 0; i < data->pwm_num; i++)
+ i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(i), val);
+ else
+ i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(cdev_idx), val);
+-
++
+ return 0;
+ }
+
+@@ -274,7 +277,7 @@ static int emc2305_get_tz_of(struct devi
+ struct emc2305_data *data = dev_get_drvdata(dev);
+ int ret = 0;
+
+- /* OF parameters are optional - overwrite default setting
++ /* OF parameters are optional - overwrite default setting
+ * if some of them are provided.
+ */
+
+@@ -296,8 +299,8 @@ static int emc2305_get_tz_of(struct devi
+ return ret;
+ }
+
+- /* Not defined or 0 means one thermal zone over all colling devices.
+- * Otherwise - separted thermal zones for each PWM channel.
++ /* Not defined or 0 means one thermal zone over all cooling devices.
++ * Otherwise - separated thermal zones for each PWM channel.
+ */
+ if (of_find_property(np, "emc2305,pwm-channel", NULL)) {
+ ret = of_property_read_u8(np, "emc2305,pwm-channel", &data->pwm_channel);
+@@ -313,7 +316,7 @@ static int emc2305_set_single_tz(struct
+ struct emc2305_data *data = dev_get_drvdata(dev);
+ long pwm = data->pwm_max;
+ int cdev_idx;
+-
++
+ cdev_idx = (idx) ? idx - 1 : 0;
+
+ if (dev->of_node)
+@@ -323,7 +326,7 @@ static int emc2305_set_single_tz(struct
+ &emc2305_cooling_ops);
+ else
+ data->cdev_data[cdev_idx].cdev =
+- thermal_cooling_device_register(emc2305_fan_name[idx], data,
++ thermal_cooling_device_register(emc2305_fan_name[idx], data,
+ &emc2305_cooling_ops);
+
+ if (IS_ERR(data->cdev_data[cdev_idx].cdev)) {
+@@ -339,6 +342,22 @@ static int emc2305_set_single_tz(struct
+ return 0;
+ }
+
++static void emc2305_unset_tz(struct device *dev)
++{
++ struct emc2305_data *data = dev_get_drvdata(dev);
++ int i;
++
++ /* Unregister cooling device in case they have been registered by
++ * thermal_cooling_device_unregister(). No need for clean-up flow in case they
++ * have been registered by devm_thermal_of_cooling_device_register()
++ */
++ 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);
+@@ -359,22 +378,6 @@ thermal_cooling_device_register_fail:
+ return ret;
+ }
+
+-static void emc2305_unset_tz(struct device *dev)
+-{
+- struct emc2305_data *data = dev_get_drvdata(dev);
+- int i;
+-
+- /* Unregister cooling device in case they have been registered by
+- * thermal_cooling_device_unregister(). No need for clean-up flow in case they
+- * have been registered by devm_thermal_of_cooling_device_register()
+- */
+- 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
+ emc2305_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel)
+ {
+@@ -548,7 +551,7 @@ static int emc2305_probe(struct i2c_clie
+ struct i2c_adapter *adapter = client->adapter;
+ struct device *dev = &client->dev;
+ struct emc2305_data *data;
+- int vendor, device;
++ int vendor;
+ int ret;
+ int i;
+
+@@ -559,10 +562,6 @@ static int emc2305_probe(struct i2c_clie
+ if (vendor != EMC2305_VENDOR)
+ return -ENODEV;
+
+- device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE);
+- if (device != EMC2305_DEVICE)
+- return -ENODEV;
+-
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+@@ -595,8 +594,23 @@ static int emc2305_probe(struct i2c_clie
+ return ret;
+ }
+
+- for (i = 0; i < data->pwm_num; i++)
+- i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i), data->pwm_min);
++ for (i = 0; i < data->pwm_num; i++) {
++ u8 val;
++
++ i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i),
++ data->pwm_min);
++
++ val = i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_CFG(i));
++ /* Set RNGx so minRPM=500 */
++ val &= ~0x60;
++ i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_CFG(i), val);
++ }
++
++ /* 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;
+ }