aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-06-25 15:14:32 -0400
committerGuenter Roeck <linux@roeck-us.net>2016-09-09 00:34:18 -0400
commita584287cd26cefba42d72b0cb7050e01b3aa77b8 (patch)
treeebbabbae8c6ae9499d1b7f6b58f8dd1e0f6f3bbf
parentbb43cc45dac37475c70b114502f067c535389edc (diff)
hwmon: (ltc4245) Convert to use new hwmon registration API
Simplify code and reduce code size by using the new hwmon registration API. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/ltc4245.c362
1 files changed, 175 insertions, 187 deletions
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index 681b5b7b3c3b..4680d89556ce 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -16,6 +16,7 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/bitops.h>
19#include <linux/err.h> 20#include <linux/err.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <linux/i2c.h> 22#include <linux/i2c.h>
@@ -53,8 +54,6 @@ enum ltc4245_cmd {
53struct ltc4245_data { 54struct ltc4245_data {
54 struct i2c_client *client; 55 struct i2c_client *client;
55 56
56 const struct attribute_group *groups[3];
57
58 struct mutex update_lock; 57 struct mutex update_lock;
59 bool valid; 58 bool valid;
60 unsigned long last_updated; /* in jiffies */ 59 unsigned long last_updated; /* in jiffies */
@@ -162,7 +161,7 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
162 ltc4245_update_gpios(dev); 161 ltc4245_update_gpios(dev);
163 162
164 data->last_updated = jiffies; 163 data->last_updated = jiffies;
165 data->valid = 1; 164 data->valid = true;
166 } 165 }
167 166
168 mutex_unlock(&data->update_lock); 167 mutex_unlock(&data->update_lock);
@@ -256,213 +255,204 @@ static unsigned int ltc4245_get_current(struct device *dev, u8 reg)
256 return curr; 255 return curr;
257} 256}
258 257
259static ssize_t ltc4245_show_voltage(struct device *dev, 258/* Map from voltage channel index to voltage register */
260 struct device_attribute *da,
261 char *buf)
262{
263 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
264 const int voltage = ltc4245_get_voltage(dev, attr->index);
265 259
266 return snprintf(buf, PAGE_SIZE, "%d\n", voltage); 260static const s8 ltc4245_in_regs[] = {
267} 261 LTC4245_12VIN, LTC4245_5VIN, LTC4245_3VIN, LTC4245_VEEIN,
262 LTC4245_12VOUT, LTC4245_5VOUT, LTC4245_3VOUT, LTC4245_VEEOUT,
263};
264
265/* Map from current channel index to current register */
268 266
269static ssize_t ltc4245_show_current(struct device *dev, 267static const s8 ltc4245_curr_regs[] = {
270 struct device_attribute *da, 268 LTC4245_12VSENSE, LTC4245_5VSENSE, LTC4245_3VSENSE, LTC4245_VEESENSE,
271 char *buf) 269};
270
271static int ltc4245_read_curr(struct device *dev, u32 attr, int channel,
272 long *val)
272{ 273{
273 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 274 struct ltc4245_data *data = ltc4245_update_device(dev);
274 const unsigned int curr = ltc4245_get_current(dev, attr->index);
275 275
276 return snprintf(buf, PAGE_SIZE, "%u\n", curr); 276 switch (attr) {
277 case hwmon_curr_input:
278 *val = ltc4245_get_current(dev, ltc4245_curr_regs[channel]);
279 return 0;
280 case hwmon_curr_max_alarm:
281 *val = !!(data->cregs[LTC4245_FAULT1] & BIT(channel + 4));
282 return 0;
283 default:
284 return -EOPNOTSUPP;
285 }
277} 286}
278 287
279static ssize_t ltc4245_show_power(struct device *dev, 288static int ltc4245_read_in(struct device *dev, u32 attr, int channel, long *val)
280 struct device_attribute *da,
281 char *buf)
282{ 289{
283 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 290 struct ltc4245_data *data = ltc4245_update_device(dev);
284 const unsigned int curr = ltc4245_get_current(dev, attr->index);
285 const int output_voltage = ltc4245_get_voltage(dev, attr->index+1);
286 291
287 /* current in mA * voltage in mV == power in uW */ 292 switch (attr) {
288 const unsigned int power = abs(output_voltage * curr); 293 case hwmon_in_input:
294 if (channel < 8) {
295 *val = ltc4245_get_voltage(dev,
296 ltc4245_in_regs[channel]);
297 } else {
298 int regval = data->gpios[channel - 8];
299
300 if (regval < 0)
301 return regval;
302 *val = regval * 10;
303 }
304 return 0;
305 case hwmon_in_min_alarm:
306 if (channel < 4)
307 *val = !!(data->cregs[LTC4245_FAULT1] & BIT(channel));
308 else
309 *val = !!(data->cregs[LTC4245_FAULT2] &
310 BIT(channel - 4));
311 return 0;
312 default:
313 return -EOPNOTSUPP;
314 }
315}
289 316
290 return snprintf(buf, PAGE_SIZE, "%u\n", power); 317static int ltc4245_read_power(struct device *dev, u32 attr, int channel,
318 long *val)
319{
320 unsigned long curr;
321 long voltage;
322
323 switch (attr) {
324 case hwmon_power_input:
325 (void)ltc4245_update_device(dev);
326 curr = ltc4245_get_current(dev, ltc4245_curr_regs[channel]);
327 voltage = ltc4245_get_voltage(dev, ltc4245_in_regs[channel]);
328 *val = abs(curr * voltage);
329 return 0;
330 default:
331 return -EOPNOTSUPP;
332 }
291} 333}
292 334
293static ssize_t ltc4245_show_alarm(struct device *dev, 335static int ltc4245_read(struct device *dev, enum hwmon_sensor_types type,
294 struct device_attribute *da, 336 u32 attr, int channel, long *val)
295 char *buf)
296{ 337{
297 struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
298 struct ltc4245_data *data = ltc4245_update_device(dev);
299 const u8 reg = data->cregs[attr->index];
300 const u32 mask = attr->nr;
301 338
302 return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); 339 switch (type) {
340 case hwmon_curr:
341 return ltc4245_read_curr(dev, attr, channel, val);
342 case hwmon_power:
343 return ltc4245_read_power(dev, attr, channel, val);
344 case hwmon_in:
345 return ltc4245_read_in(dev, attr, channel - 1, val);
346 default:
347 return -EOPNOTSUPP;
348 }
303} 349}
304 350
305static ssize_t ltc4245_show_gpio(struct device *dev, 351static umode_t ltc4245_is_visible(const void *_data,
306 struct device_attribute *da, 352 enum hwmon_sensor_types type,
307 char *buf) 353 u32 attr, int channel)
308{ 354{
309 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 355 const struct ltc4245_data *data = _data;
310 struct ltc4245_data *data = ltc4245_update_device(dev); 356
311 int val = data->gpios[attr->index]; 357 switch (type) {
358 case hwmon_in:
359 if (channel == 0)
360 return 0;
361 switch (attr) {
362 case hwmon_in_input:
363 if (channel > 9 && !data->use_extra_gpios)
364 return 0;
365 return S_IRUGO;
366 case hwmon_in_min_alarm:
367 if (channel > 8)
368 return 0;
369 return S_IRUGO;
370 default:
371 return 0;
372 }
373 case hwmon_curr:
374 switch (attr) {
375 case hwmon_curr_input:
376 case hwmon_curr_max_alarm:
377 return S_IRUGO;
378 default:
379 return 0;
380 }
381 case hwmon_power:
382 switch (attr) {
383 case hwmon_power_input:
384 return S_IRUGO;
385 default:
386 return 0;
387 }
388 default:
389 return 0;
390 }
391}
312 392
313 /* handle stale GPIO's */ 393static const u32 ltc4245_in_config[] = {
314 if (val < 0) 394 HWMON_I_INPUT, /* dummy, skipped in is_visible */
315 return val; 395 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
396 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
397 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
398 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
399 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
400 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
401 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
402 HWMON_I_INPUT | HWMON_I_MIN_ALARM,
403 HWMON_I_INPUT,
404 HWMON_I_INPUT,
405 HWMON_I_INPUT,
406 0
407};
316 408
317 /* Convert to millivolts and print */ 409static const struct hwmon_channel_info ltc4245_in = {
318 return snprintf(buf, PAGE_SIZE, "%u\n", val * 10); 410 .type = hwmon_in,
319} 411 .config = ltc4245_in_config,
412};
320 413
321/* Construct a sensor_device_attribute structure for each register */ 414static const u32 ltc4245_curr_config[] = {
322 415 HWMON_C_INPUT | HWMON_C_MAX_ALARM,
323/* Input voltages */ 416 HWMON_C_INPUT | HWMON_C_MAX_ALARM,
324static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4245_show_voltage, NULL, 417 HWMON_C_INPUT | HWMON_C_MAX_ALARM,
325 LTC4245_12VIN); 418 HWMON_C_INPUT | HWMON_C_MAX_ALARM,
326static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4245_show_voltage, NULL, 419 0
327 LTC4245_5VIN); 420};
328static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc4245_show_voltage, NULL,
329 LTC4245_3VIN);
330static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc4245_show_voltage, NULL,
331 LTC4245_VEEIN);
332
333/* Input undervoltage alarms */
334static SENSOR_DEVICE_ATTR_2(in1_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
335 1 << 0, LTC4245_FAULT1);
336static SENSOR_DEVICE_ATTR_2(in2_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
337 1 << 1, LTC4245_FAULT1);
338static SENSOR_DEVICE_ATTR_2(in3_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
339 1 << 2, LTC4245_FAULT1);
340static SENSOR_DEVICE_ATTR_2(in4_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
341 1 << 3, LTC4245_FAULT1);
342
343/* Currents (via sense resistor) */
344static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4245_show_current, NULL,
345 LTC4245_12VSENSE);
346static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc4245_show_current, NULL,
347 LTC4245_5VSENSE);
348static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, ltc4245_show_current, NULL,
349 LTC4245_3VSENSE);
350static SENSOR_DEVICE_ATTR(curr4_input, S_IRUGO, ltc4245_show_current, NULL,
351 LTC4245_VEESENSE);
352
353/* Overcurrent alarms */
354static SENSOR_DEVICE_ATTR_2(curr1_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
355 1 << 4, LTC4245_FAULT1);
356static SENSOR_DEVICE_ATTR_2(curr2_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
357 1 << 5, LTC4245_FAULT1);
358static SENSOR_DEVICE_ATTR_2(curr3_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
359 1 << 6, LTC4245_FAULT1);
360static SENSOR_DEVICE_ATTR_2(curr4_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
361 1 << 7, LTC4245_FAULT1);
362
363/* Output voltages */
364static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ltc4245_show_voltage, NULL,
365 LTC4245_12VOUT);
366static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ltc4245_show_voltage, NULL,
367 LTC4245_5VOUT);
368static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ltc4245_show_voltage, NULL,
369 LTC4245_3VOUT);
370static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, ltc4245_show_voltage, NULL,
371 LTC4245_VEEOUT);
372
373/* Power Bad alarms */
374static SENSOR_DEVICE_ATTR_2(in5_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
375 1 << 0, LTC4245_FAULT2);
376static SENSOR_DEVICE_ATTR_2(in6_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
377 1 << 1, LTC4245_FAULT2);
378static SENSOR_DEVICE_ATTR_2(in7_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
379 1 << 2, LTC4245_FAULT2);
380static SENSOR_DEVICE_ATTR_2(in8_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
381 1 << 3, LTC4245_FAULT2);
382
383/* GPIO voltages */
384static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, ltc4245_show_gpio, NULL, 0);
385static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, ltc4245_show_gpio, NULL, 1);
386static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, ltc4245_show_gpio, NULL, 2);
387
388/* Power Consumption (virtual) */
389static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ltc4245_show_power, NULL,
390 LTC4245_12VSENSE);
391static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, ltc4245_show_power, NULL,
392 LTC4245_5VSENSE);
393static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, ltc4245_show_power, NULL,
394 LTC4245_3VSENSE);
395static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, ltc4245_show_power, NULL,
396 LTC4245_VEESENSE);
397 421
398/* 422static const struct hwmon_channel_info ltc4245_curr = {
399 * Finally, construct an array of pointers to members of the above objects, 423 .type = hwmon_curr,
400 * as required for sysfs_create_group() 424 .config = ltc4245_curr_config,
401 */
402static struct attribute *ltc4245_std_attributes[] = {
403 &sensor_dev_attr_in1_input.dev_attr.attr,
404 &sensor_dev_attr_in2_input.dev_attr.attr,
405 &sensor_dev_attr_in3_input.dev_attr.attr,
406 &sensor_dev_attr_in4_input.dev_attr.attr,
407
408 &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
409 &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
410 &sensor_dev_attr_in3_min_alarm.dev_attr.attr,
411 &sensor_dev_attr_in4_min_alarm.dev_attr.attr,
412
413 &sensor_dev_attr_curr1_input.dev_attr.attr,
414 &sensor_dev_attr_curr2_input.dev_attr.attr,
415 &sensor_dev_attr_curr3_input.dev_attr.attr,
416 &sensor_dev_attr_curr4_input.dev_attr.attr,
417
418 &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
419 &sensor_dev_attr_curr2_max_alarm.dev_attr.attr,
420 &sensor_dev_attr_curr3_max_alarm.dev_attr.attr,
421 &sensor_dev_attr_curr4_max_alarm.dev_attr.attr,
422
423 &sensor_dev_attr_in5_input.dev_attr.attr,
424 &sensor_dev_attr_in6_input.dev_attr.attr,
425 &sensor_dev_attr_in7_input.dev_attr.attr,
426 &sensor_dev_attr_in8_input.dev_attr.attr,
427
428 &sensor_dev_attr_in5_min_alarm.dev_attr.attr,
429 &sensor_dev_attr_in6_min_alarm.dev_attr.attr,
430 &sensor_dev_attr_in7_min_alarm.dev_attr.attr,
431 &sensor_dev_attr_in8_min_alarm.dev_attr.attr,
432
433 &sensor_dev_attr_in9_input.dev_attr.attr,
434
435 &sensor_dev_attr_power1_input.dev_attr.attr,
436 &sensor_dev_attr_power2_input.dev_attr.attr,
437 &sensor_dev_attr_power3_input.dev_attr.attr,
438 &sensor_dev_attr_power4_input.dev_attr.attr,
439
440 NULL,
441}; 425};
442 426
443static struct attribute *ltc4245_gpio_attributes[] = { 427static const u32 ltc4245_power_config[] = {
444 &sensor_dev_attr_in10_input.dev_attr.attr, 428 HWMON_P_INPUT,
445 &sensor_dev_attr_in11_input.dev_attr.attr, 429 HWMON_P_INPUT,
446 NULL, 430 HWMON_P_INPUT,
431 HWMON_P_INPUT,
432 0
447}; 433};
448 434
449static const struct attribute_group ltc4245_std_group = { 435static const struct hwmon_channel_info ltc4245_power = {
450 .attrs = ltc4245_std_attributes, 436 .type = hwmon_power,
437 .config = ltc4245_power_config,
451}; 438};
452 439
453static const struct attribute_group ltc4245_gpio_group = { 440static const struct hwmon_channel_info *ltc4245_info[] = {
454 .attrs = ltc4245_gpio_attributes, 441 &ltc4245_in,
442 &ltc4245_curr,
443 &ltc4245_power,
444 NULL
455}; 445};
456 446
457static void ltc4245_sysfs_add_groups(struct ltc4245_data *data) 447static const struct hwmon_ops ltc4245_hwmon_ops = {
458{ 448 .is_visible = ltc4245_is_visible,
459 /* standard sysfs attributes */ 449 .read = ltc4245_read,
460 data->groups[0] = &ltc4245_std_group; 450};
461 451
462 /* if we're using the extra gpio support, register it's attributes */ 452static const struct hwmon_chip_info ltc4245_chip_info = {
463 if (data->use_extra_gpios) 453 .ops = &ltc4245_hwmon_ops,
464 data->groups[1] = &ltc4245_gpio_group; 454 .info = ltc4245_info,
465} 455};
466 456
467static bool ltc4245_use_extra_gpios(struct i2c_client *client) 457static bool ltc4245_use_extra_gpios(struct i2c_client *client)
468{ 458{
@@ -502,12 +492,10 @@ static int ltc4245_probe(struct i2c_client *client,
502 i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); 492 i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
503 i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); 493 i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
504 494
505 /* Add sysfs hooks */ 495 hwmon_dev = devm_hwmon_device_register_with_info(&client->dev,
506 ltc4245_sysfs_add_groups(data); 496 client->name, data,
507 497 &ltc4245_chip_info,
508 hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, 498 NULL);
509 client->name, data,
510 data->groups);
511 return PTR_ERR_OR_ZERO(hwmon_dev); 499 return PTR_ERR_OR_ZERO(hwmon_dev);
512} 500}
513 501