diff options
-rw-r--r-- | drivers/hwmon/gl518sm.c | 110 |
1 files changed, 60 insertions, 50 deletions
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 8287a3af6d79..ed901f96a04f 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/jiffies.h> | 38 | #include <linux/jiffies.h> |
39 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
40 | #include <linux/hwmon.h> | 40 | #include <linux/hwmon.h> |
41 | #include <linux/hwmon-sysfs.h> | ||
41 | #include <linux/err.h> | 42 | #include <linux/err.h> |
42 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
43 | #include <linux/sysfs.h> | 44 | #include <linux/sysfs.h> |
@@ -166,24 +167,10 @@ static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, | |||
166 | return sprintf(buf, "%d\n", type##_FROM_REG(data->value)); \ | 167 | return sprintf(buf, "%d\n", type##_FROM_REG(data->value)); \ |
167 | } | 168 | } |
168 | 169 | ||
169 | #define show_fan(suffix, value, index) \ | ||
170 | static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \ | ||
171 | { \ | ||
172 | struct gl518_data *data = gl518_update_device(dev); \ | ||
173 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[index], \ | ||
174 | DIV_FROM_REG(data->fan_div[index]))); \ | ||
175 | } | ||
176 | |||
177 | show(TEMP, temp_input1, temp_in); | 170 | show(TEMP, temp_input1, temp_in); |
178 | show(TEMP, temp_max1, temp_max); | 171 | show(TEMP, temp_max1, temp_max); |
179 | show(TEMP, temp_hyst1, temp_hyst); | 172 | show(TEMP, temp_hyst1, temp_hyst); |
180 | show(BOOL, fan_auto1, fan_auto1); | 173 | show(BOOL, fan_auto1, fan_auto1); |
181 | show_fan(fan_input1, fan_in, 0); | ||
182 | show_fan(fan_input2, fan_in, 1); | ||
183 | show_fan(fan_min1, fan_min, 0); | ||
184 | show_fan(fan_min2, fan_min, 1); | ||
185 | show(DIV, fan_div1, fan_div[0]); | ||
186 | show(DIV, fan_div2, fan_div[1]); | ||
187 | show(VDD, in_input0, voltage_in[0]); | 174 | show(VDD, in_input0, voltage_in[0]); |
188 | show(IN, in_input1, voltage_in[1]); | 175 | show(IN, in_input1, voltage_in[1]); |
189 | show(IN, in_input2, voltage_in[2]); | 176 | show(IN, in_input2, voltage_in[2]); |
@@ -200,6 +187,32 @@ show(RAW, alarms, alarms); | |||
200 | show(BOOL, beep_enable, beep_enable); | 187 | show(BOOL, beep_enable, beep_enable); |
201 | show(BEEP_MASK, beep_mask, beep_mask); | 188 | show(BEEP_MASK, beep_mask, beep_mask); |
202 | 189 | ||
190 | static ssize_t show_fan_input(struct device *dev, | ||
191 | struct device_attribute *attr, char *buf) | ||
192 | { | ||
193 | int nr = to_sensor_dev_attr(attr)->index; | ||
194 | struct gl518_data *data = gl518_update_device(dev); | ||
195 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_in[nr], | ||
196 | DIV_FROM_REG(data->fan_div[nr]))); | ||
197 | } | ||
198 | |||
199 | static ssize_t show_fan_min(struct device *dev, | ||
200 | struct device_attribute *attr, char *buf) | ||
201 | { | ||
202 | int nr = to_sensor_dev_attr(attr)->index; | ||
203 | struct gl518_data *data = gl518_update_device(dev); | ||
204 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], | ||
205 | DIV_FROM_REG(data->fan_div[nr]))); | ||
206 | } | ||
207 | |||
208 | static ssize_t show_fan_div(struct device *dev, | ||
209 | struct device_attribute *attr, char *buf) | ||
210 | { | ||
211 | int nr = to_sensor_dev_attr(attr)->index; | ||
212 | struct gl518_data *data = gl518_update_device(dev); | ||
213 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | ||
214 | } | ||
215 | |||
203 | #define set(type, suffix, value, reg) \ | 216 | #define set(type, suffix, value, reg) \ |
204 | static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ | 217 | static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ |
205 | size_t count) \ | 218 | size_t count) \ |
@@ -241,8 +254,6 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c | |||
241 | set(TEMP, temp_max1, temp_max, GL518_REG_TEMP_MAX); | 254 | set(TEMP, temp_max1, temp_max, GL518_REG_TEMP_MAX); |
242 | set(TEMP, temp_hyst1, temp_hyst, GL518_REG_TEMP_HYST); | 255 | set(TEMP, temp_hyst1, temp_hyst, GL518_REG_TEMP_HYST); |
243 | set_bits(BOOL, fan_auto1, fan_auto1, GL518_REG_MISC, 0x08, 3); | 256 | set_bits(BOOL, fan_auto1, fan_auto1, GL518_REG_MISC, 0x08, 3); |
244 | set_bits(DIV, fan_div1, fan_div[0], GL518_REG_MISC, 0xc0, 6); | ||
245 | set_bits(DIV, fan_div2, fan_div[1], GL518_REG_MISC, 0x30, 4); | ||
246 | set_low(VDD, in_min0, voltage_min[0], GL518_REG_VDD_LIMIT); | 257 | set_low(VDD, in_min0, voltage_min[0], GL518_REG_VDD_LIMIT); |
247 | set_low(IN, in_min1, voltage_min[1], GL518_REG_VIN1_LIMIT); | 258 | set_low(IN, in_min1, voltage_min[1], GL518_REG_VIN1_LIMIT); |
248 | set_low(IN, in_min2, voltage_min[2], GL518_REG_VIN2_LIMIT); | 259 | set_low(IN, in_min2, voltage_min[2], GL518_REG_VIN2_LIMIT); |
@@ -254,25 +265,27 @@ set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT); | |||
254 | set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2); | 265 | set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2); |
255 | set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM); | 266 | set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM); |
256 | 267 | ||
257 | static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 268 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, |
269 | const char *buf, size_t count) | ||
258 | { | 270 | { |
259 | struct i2c_client *client = to_i2c_client(dev); | 271 | struct i2c_client *client = to_i2c_client(dev); |
260 | struct gl518_data *data = i2c_get_clientdata(client); | 272 | struct gl518_data *data = i2c_get_clientdata(client); |
273 | int nr = to_sensor_dev_attr(attr)->index; | ||
261 | int regvalue; | 274 | int regvalue; |
262 | unsigned long val = simple_strtoul(buf, NULL, 10); | 275 | unsigned long val = simple_strtoul(buf, NULL, 10); |
263 | 276 | ||
264 | mutex_lock(&data->update_lock); | 277 | mutex_lock(&data->update_lock); |
265 | regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); | 278 | regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); |
266 | data->fan_min[0] = FAN_TO_REG(val, | 279 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
267 | DIV_FROM_REG(data->fan_div[0])); | 280 | regvalue = (regvalue & (0xff << (8 * nr))) |
268 | regvalue = (regvalue & 0x00ff) | (data->fan_min[0] << 8); | 281 | | (data->fan_min[nr] << (8 * (1 - nr))); |
269 | gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue); | 282 | gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue); |
270 | 283 | ||
271 | data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); | 284 | data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); |
272 | if (data->fan_min[0] == 0) | 285 | if (data->fan_min[nr] == 0) |
273 | data->alarm_mask &= ~0x20; | 286 | data->alarm_mask &= ~(0x20 << nr); |
274 | else | 287 | else |
275 | data->alarm_mask |= 0x20; | 288 | data->alarm_mask |= (0x20 << nr); |
276 | data->beep_mask &= data->alarm_mask; | 289 | data->beep_mask &= data->alarm_mask; |
277 | gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); | 290 | gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); |
278 | 291 | ||
@@ -280,28 +293,21 @@ static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, c | |||
280 | return count; | 293 | return count; |
281 | } | 294 | } |
282 | 295 | ||
283 | static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 296 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, |
297 | const char *buf, size_t count) | ||
284 | { | 298 | { |
285 | struct i2c_client *client = to_i2c_client(dev); | 299 | struct i2c_client *client = to_i2c_client(dev); |
286 | struct gl518_data *data = i2c_get_clientdata(client); | 300 | struct gl518_data *data = i2c_get_clientdata(client); |
301 | int nr = to_sensor_dev_attr(attr)->index; | ||
287 | int regvalue; | 302 | int regvalue; |
288 | unsigned long val = simple_strtoul(buf, NULL, 10); | 303 | unsigned long val = simple_strtoul(buf, NULL, 10); |
289 | 304 | ||
290 | mutex_lock(&data->update_lock); | 305 | mutex_lock(&data->update_lock); |
291 | regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); | 306 | regvalue = gl518_read_value(client, GL518_REG_MISC); |
292 | data->fan_min[1] = FAN_TO_REG(val, | 307 | data->fan_div[nr] = DIV_TO_REG(val); |
293 | DIV_FROM_REG(data->fan_div[1])); | 308 | regvalue = (regvalue & ~(0xc0 >> (2 * nr))) |
294 | regvalue = (regvalue & 0xff00) | data->fan_min[1]; | 309 | | (data->fan_div[nr] << (6 - 2 * nr)); |
295 | gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue); | 310 | gl518_write_value(client, GL518_REG_MISC, regvalue); |
296 | |||
297 | data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); | ||
298 | if (data->fan_min[1] == 0) | ||
299 | data->alarm_mask &= ~0x40; | ||
300 | else | ||
301 | data->alarm_mask |= 0x40; | ||
302 | data->beep_mask &= data->alarm_mask; | ||
303 | gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); | ||
304 | |||
305 | mutex_unlock(&data->update_lock); | 311 | mutex_unlock(&data->update_lock); |
306 | return count; | 312 | return count; |
307 | } | 313 | } |
@@ -311,12 +317,16 @@ static DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1); | |||
311 | static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO, | 317 | static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO, |
312 | show_temp_hyst1, set_temp_hyst1); | 318 | show_temp_hyst1, set_temp_hyst1); |
313 | static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1); | 319 | static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1); |
314 | static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL); | 320 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); |
315 | static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL); | 321 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); |
316 | static DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, show_fan_min1, set_fan_min1); | 322 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, |
317 | static DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, show_fan_min2, set_fan_min2); | 323 | show_fan_min, set_fan_min, 0); |
318 | static DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, show_fan_div1, set_fan_div1); | 324 | static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, |
319 | static DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, show_fan_div2, set_fan_div2); | 325 | show_fan_min, set_fan_min, 1); |
326 | static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, | ||
327 | show_fan_div, set_fan_div, 0); | ||
328 | static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, | ||
329 | show_fan_div, set_fan_div, 1); | ||
320 | static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL); | 330 | static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL); |
321 | static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL); | 331 | static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL); |
322 | static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL); | 332 | static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL); |
@@ -347,12 +357,12 @@ static struct attribute *gl518_attributes[] = { | |||
347 | &dev_attr_in3_max.attr, | 357 | &dev_attr_in3_max.attr, |
348 | 358 | ||
349 | &dev_attr_fan1_auto.attr, | 359 | &dev_attr_fan1_auto.attr, |
350 | &dev_attr_fan1_input.attr, | 360 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
351 | &dev_attr_fan2_input.attr, | 361 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
352 | &dev_attr_fan1_min.attr, | 362 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
353 | &dev_attr_fan2_min.attr, | 363 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
354 | &dev_attr_fan1_div.attr, | 364 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
355 | &dev_attr_fan2_div.attr, | 365 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
356 | 366 | ||
357 | &dev_attr_temp1_input.attr, | 367 | &dev_attr_temp1_input.attr, |
358 | &dev_attr_temp1_max.attr, | 368 | &dev_attr_temp1_max.attr, |