bcm27xx: 6.1: add kernel patches
[openwrt/staging/stintel.git] / target / linux / bcm27xx / patches-6.1 / 950-0441-hwmon-emc2305-fixups-for-driver-submitted-to-mailing.patch
1 From c53aee9d78372213c34f5ebfb084b58be754a23c Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Thu, 5 May 2022 15:46:07 +0100
4 Subject: [PATCH] hwmon: emc2305: fixups for driver submitted to
5 mailing lists
6
7 The driver had a number of issues, checkpatch warnings/errors,
8 and other limitations, so fix these up to make it usable.
9
10 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
11 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
12 ---
13 drivers/hwmon/emc2305.c | 73 +++++++++++++++++++++++++++++++++++++++--
14 1 file changed, 71 insertions(+), 2 deletions(-)
15
16 --- a/drivers/hwmon/emc2305.c
17 +++ b/drivers/hwmon/emc2305.c
18 @@ -15,12 +15,13 @@
19 static const unsigned short
20 emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END };
21
22 +#define EMC2305_REG_FAN_STATUS 0x24
23 +#define EMC2305_REG_FAN_STALL_STATUS 0x25
24 #define EMC2305_REG_DRIVE_FAIL_STATUS 0x27
25 #define EMC2305_REG_VENDOR 0xfe
26 #define EMC2305_FAN_MAX 0xff
27 #define EMC2305_FAN_MIN 0x00
28 #define EMC2305_FAN_MAX_STATE 10
29 -#define EMC2305_DEVICE 0x34
30 #define EMC2305_VENDOR 0x5d
31 #define EMC2305_REG_PRODUCT_ID 0xfd
32 #define EMC2305_TACH_REGS_UNUSE_BITS 3
33 @@ -39,6 +40,7 @@ emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2
34 #define EMC2305_RPM_FACTOR 3932160
35
36 #define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * (n))
37 +#define EMC2305_REG_FAN_CFG(n) (0x32 + 0x10 * (n))
38 #define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * (n))
39 #define EMC2305_REG_FAN_TACH(n) (0x3e + 0x10 * (n))
40
41 @@ -58,6 +60,15 @@ static const struct i2c_device_id emc230
42 };
43 MODULE_DEVICE_TABLE(i2c, emc2305_ids);
44
45 +static const struct of_device_id emc2305_dt_ids[] = {
46 + { .compatible = "microchip,emc2305" },
47 + { .compatible = "microchip,emc2303" },
48 + { .compatible = "microchip,emc2302" },
49 + { .compatible = "microchip,emc2301" },
50 + { }
51 +};
52 +MODULE_DEVICE_TABLE(of, emc2305_dt_ids);
53 +
54 /**
55 * @cdev: cooling device;
56 * @curr_state: cooling current state;
57 @@ -101,6 +112,7 @@ struct emc2305_data {
58 u8 pwm_num;
59 bool pwm_separate;
60 u8 pwm_min[EMC2305_PWM_MAX];
61 + u8 pwm_max;
62 struct emc2305_cdev_data cdev_data[EMC2305_PWM_MAX];
63 };
64
65 @@ -273,7 +285,7 @@ static int emc2305_set_pwm(struct device
66 struct i2c_client *client = data->client;
67 int ret;
68
69 - if (val < data->pwm_min[channel] || val > EMC2305_FAN_MAX)
70 + if (val < data->pwm_min[channel] || val > data->pwm_max)
71 return -EINVAL;
72
73 ret = i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(channel), val);
74 @@ -284,6 +296,49 @@ static int emc2305_set_pwm(struct device
75 return 0;
76 }
77
78 +static int emc2305_get_tz_of(struct device *dev)
79 +{
80 + struct device_node *np = dev->of_node;
81 + struct emc2305_data *data = dev_get_drvdata(dev);
82 + int ret = 0;
83 + u32 val;
84 + int i;
85 +
86 + /* OF parameters are optional - overwrite default setting
87 + * if some of them are provided.
88 + */
89 +
90 + ret = of_property_read_u32(np, "emc2305,cooling-levels", &val);
91 + if (!ret)
92 + data->max_state = (u8)val;
93 + else if (ret != -EINVAL)
94 + return ret;
95 +
96 + ret = of_property_read_u32(np, "emc2305,pwm-max", &val);
97 + if (!ret)
98 + data->pwm_max = (u8)val;
99 + else if (ret != -EINVAL)
100 + return ret;
101 +
102 + ret = of_property_read_u32(np, "emc2305,pwm-min", &val);
103 + if (!ret)
104 + for (i = 0; i < EMC2305_PWM_MAX; i++)
105 + data->pwm_min[i] = (u8)val;
106 + else if (ret != -EINVAL)
107 + return ret;
108 +
109 + /* Not defined or 0 means one thermal zone over all cooling devices.
110 + * Otherwise - separated thermal zones for each PWM channel.
111 + */
112 + ret = of_property_read_u32(np, "emc2305,pwm-channel", &val);
113 + if (!ret)
114 + data->pwm_separate = (val != 0);
115 + else if (ret != -EINVAL)
116 + return ret;
117 +
118 + return 0;
119 +}
120 +
121 static int emc2305_set_single_tz(struct device *dev, int idx)
122 {
123 struct emc2305_data *data = dev_get_drvdata(dev);
124 @@ -572,11 +627,18 @@ static int emc2305_probe(struct i2c_clie
125 data->pwm_separate = pdata->pwm_separate;
126 for (i = 0; i < EMC2305_PWM_MAX; i++)
127 data->pwm_min[i] = pdata->pwm_min[i];
128 + data->pwm_max = EMC2305_FAN_MAX;
129 } else {
130 data->max_state = EMC2305_FAN_MAX_STATE;
131 data->pwm_separate = false;
132 for (i = 0; i < EMC2305_PWM_MAX; i++)
133 data->pwm_min[i] = EMC2305_FAN_MIN;
134 + data->pwm_max = EMC2305_FAN_MAX;
135 + if (dev->of_node) {
136 + ret = emc2305_get_tz_of(dev);
137 + if (ret < 0)
138 + return ret;
139 + }
140 }
141
142 data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "emc2305", data,
143 @@ -597,6 +659,12 @@ static int emc2305_probe(struct i2c_clie
144 return ret;
145 }
146
147 + /* Acknowledge any existing faults. Stops the device responding on the
148 + * SMBus alert address.
149 + */
150 + i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STALL_STATUS);
151 + i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STATUS);
152 +
153 return 0;
154 }
155
156 @@ -612,6 +680,7 @@ static struct i2c_driver emc2305_driver
157 .class = I2C_CLASS_HWMON,
158 .driver = {
159 .name = "emc2305",
160 + .of_match_table = emc2305_dt_ids,
161 },
162 .probe = emc2305_probe,
163 .remove = emc2305_remove,