GNU Linux-libre 4.9.337-gnu1
[releases.git] / drivers / hwmon / hwmon.c
1 /*
2  * hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
3  *
4  * This file defines the sysfs class "hwmon", for use by sensors drivers.
5  *
6  * Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  */
12
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
15 #include <linux/bitops.h>
16 #include <linux/device.h>
17 #include <linux/err.h>
18 #include <linux/gfp.h>
19 #include <linux/hwmon.h>
20 #include <linux/idr.h>
21 #include <linux/module.h>
22 #include <linux/pci.h>
23 #include <linux/slab.h>
24 #include <linux/string.h>
25 #include <linux/thermal.h>
26
27 #define HWMON_ID_PREFIX "hwmon"
28 #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
29
30 struct hwmon_device {
31         const char *name;
32         struct device dev;
33         const struct hwmon_chip_info *chip;
34
35         struct attribute_group group;
36         const struct attribute_group **groups;
37 };
38
39 #define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
40
41 #define MAX_SYSFS_ATTR_NAME_LENGTH      32
42
43 struct hwmon_device_attribute {
44         struct device_attribute dev_attr;
45         const struct hwmon_ops *ops;
46         enum hwmon_sensor_types type;
47         u32 attr;
48         int index;
49         char name[MAX_SYSFS_ATTR_NAME_LENGTH];
50 };
51
52 #define to_hwmon_attr(d) \
53         container_of(d, struct hwmon_device_attribute, dev_attr)
54 #define to_dev_attr(a) container_of(a, struct device_attribute, attr)
55
56 /*
57  * Thermal zone information
58  * In addition to the reference to the hwmon device,
59  * also provides the sensor index.
60  */
61 struct hwmon_thermal_data {
62         struct device *dev;             /* Reference to hwmon device */
63         int index;                      /* sensor index */
64 };
65
66 static ssize_t
67 show_name(struct device *dev, struct device_attribute *attr, char *buf)
68 {
69         return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
70 }
71 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
72
73 static struct attribute *hwmon_dev_attrs[] = {
74         &dev_attr_name.attr,
75         NULL
76 };
77
78 static umode_t hwmon_dev_name_is_visible(struct kobject *kobj,
79                                          struct attribute *attr, int n)
80 {
81         struct device *dev = container_of(kobj, struct device, kobj);
82
83         if (to_hwmon_device(dev)->name == NULL)
84                 return 0;
85
86         return attr->mode;
87 }
88
89 static struct attribute_group hwmon_dev_attr_group = {
90         .attrs          = hwmon_dev_attrs,
91         .is_visible     = hwmon_dev_name_is_visible,
92 };
93
94 static const struct attribute_group *hwmon_dev_attr_groups[] = {
95         &hwmon_dev_attr_group,
96         NULL
97 };
98
99 static void hwmon_free_attrs(struct attribute **attrs)
100 {
101         int i;
102
103         for (i = 0; attrs[i]; i++) {
104                 struct device_attribute *dattr = to_dev_attr(attrs[i]);
105                 struct hwmon_device_attribute *hattr = to_hwmon_attr(dattr);
106
107                 kfree(hattr);
108         }
109         kfree(attrs);
110 }
111
112 static void hwmon_dev_release(struct device *dev)
113 {
114         struct hwmon_device *hwdev = to_hwmon_device(dev);
115
116         if (hwdev->group.attrs)
117                 hwmon_free_attrs(hwdev->group.attrs);
118         kfree(hwdev->groups);
119         kfree(hwdev);
120 }
121
122 static struct class hwmon_class = {
123         .name = "hwmon",
124         .owner = THIS_MODULE,
125         .dev_groups = hwmon_dev_attr_groups,
126         .dev_release = hwmon_dev_release,
127 };
128
129 static DEFINE_IDA(hwmon_ida);
130
131 /* Thermal zone handling */
132
133 /*
134  * The complex conditional is necessary to avoid a cyclic dependency
135  * between hwmon and thermal_sys modules.
136  */
137 #if IS_REACHABLE(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OF) && \
138         (!defined(CONFIG_THERMAL_HWMON) || \
139          !(defined(MODULE) && IS_MODULE(CONFIG_THERMAL)))
140 static int hwmon_thermal_get_temp(void *data, int *temp)
141 {
142         struct hwmon_thermal_data *tdata = data;
143         struct hwmon_device *hwdev = to_hwmon_device(tdata->dev);
144         int ret;
145         long t;
146
147         ret = hwdev->chip->ops->read(tdata->dev, hwmon_temp, hwmon_temp_input,
148                                      tdata->index, &t);
149         if (ret < 0)
150                 return ret;
151
152         *temp = t;
153
154         return 0;
155 }
156
157 static struct thermal_zone_of_device_ops hwmon_thermal_ops = {
158         .get_temp = hwmon_thermal_get_temp,
159 };
160
161 static int hwmon_thermal_add_sensor(struct device *dev, int index)
162 {
163         struct hwmon_thermal_data *tdata;
164         struct thermal_zone_device *tzd;
165
166         tdata = devm_kzalloc(dev, sizeof(*tdata), GFP_KERNEL);
167         if (!tdata)
168                 return -ENOMEM;
169
170         tdata->dev = dev;
171         tdata->index = index;
172
173         tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata,
174                                                    &hwmon_thermal_ops);
175         /*
176          * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV,
177          * so ignore that error but forward any other error.
178          */
179         if (IS_ERR(tzd) && (PTR_ERR(tzd) != -ENODEV))
180                 return PTR_ERR(tzd);
181
182         return 0;
183 }
184 #else
185 static int hwmon_thermal_add_sensor(struct device *dev, int index)
186 {
187         return 0;
188 }
189 #endif /* IS_REACHABLE(CONFIG_THERMAL) && ... */
190
191 /* sysfs attribute management */
192
193 static ssize_t hwmon_attr_show(struct device *dev,
194                                struct device_attribute *devattr, char *buf)
195 {
196         struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
197         long val;
198         int ret;
199
200         ret = hattr->ops->read(dev, hattr->type, hattr->attr, hattr->index,
201                                &val);
202         if (ret < 0)
203                 return ret;
204
205         return sprintf(buf, "%ld\n", val);
206 }
207
208 static ssize_t hwmon_attr_store(struct device *dev,
209                                 struct device_attribute *devattr,
210                                 const char *buf, size_t count)
211 {
212         struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
213         long val;
214         int ret;
215
216         ret = kstrtol(buf, 10, &val);
217         if (ret < 0)
218                 return ret;
219
220         ret = hattr->ops->write(dev, hattr->type, hattr->attr, hattr->index,
221                                 val);
222         if (ret < 0)
223                 return ret;
224
225         return count;
226 }
227
228 static int hwmon_attr_base(enum hwmon_sensor_types type)
229 {
230         if (type == hwmon_in)
231                 return 0;
232         return 1;
233 }
234
235 static struct attribute *hwmon_genattr(const void *drvdata,
236                                        enum hwmon_sensor_types type,
237                                        u32 attr,
238                                        int index,
239                                        const char *template,
240                                        const struct hwmon_ops *ops)
241 {
242         struct hwmon_device_attribute *hattr;
243         struct device_attribute *dattr;
244         struct attribute *a;
245         umode_t mode;
246         char *name;
247
248         /* The attribute is invisible if there is no template string */
249         if (!template)
250                 return ERR_PTR(-ENOENT);
251
252         mode = ops->is_visible(drvdata, type, attr, index);
253         if (!mode)
254                 return ERR_PTR(-ENOENT);
255
256         if ((mode & S_IRUGO) && !ops->read)
257                 return ERR_PTR(-EINVAL);
258         if ((mode & S_IWUGO) && !ops->write)
259                 return ERR_PTR(-EINVAL);
260
261         hattr = kzalloc(sizeof(*hattr), GFP_KERNEL);
262         if (!hattr)
263                 return ERR_PTR(-ENOMEM);
264
265         if (type == hwmon_chip) {
266                 name = (char *)template;
267         } else {
268                 scnprintf(hattr->name, sizeof(hattr->name), template,
269                           index + hwmon_attr_base(type));
270                 name = hattr->name;
271         }
272
273         hattr->type = type;
274         hattr->attr = attr;
275         hattr->index = index;
276         hattr->ops = ops;
277
278         dattr = &hattr->dev_attr;
279         dattr->show = hwmon_attr_show;
280         dattr->store = hwmon_attr_store;
281
282         a = &dattr->attr;
283         sysfs_attr_init(a);
284         a->name = name;
285         a->mode = mode;
286
287         return a;
288 }
289
290 static const char * const hwmon_chip_attr_templates[] = {
291         [hwmon_chip_temp_reset_history] = "temp_reset_history",
292         [hwmon_chip_in_reset_history] = "in_reset_history",
293         [hwmon_chip_curr_reset_history] = "curr_reset_history",
294         [hwmon_chip_power_reset_history] = "power_reset_history",
295         [hwmon_chip_update_interval] = "update_interval",
296         [hwmon_chip_alarms] = "alarms",
297 };
298
299 static const char * const hwmon_temp_attr_templates[] = {
300         [hwmon_temp_input] = "temp%d_input",
301         [hwmon_temp_type] = "temp%d_type",
302         [hwmon_temp_lcrit] = "temp%d_lcrit",
303         [hwmon_temp_lcrit_hyst] = "temp%d_lcrit_hyst",
304         [hwmon_temp_min] = "temp%d_min",
305         [hwmon_temp_min_hyst] = "temp%d_min_hyst",
306         [hwmon_temp_max] = "temp%d_max",
307         [hwmon_temp_max_hyst] = "temp%d_max_hyst",
308         [hwmon_temp_crit] = "temp%d_crit",
309         [hwmon_temp_crit_hyst] = "temp%d_crit_hyst",
310         [hwmon_temp_emergency] = "temp%d_emergency",
311         [hwmon_temp_emergency_hyst] = "temp%d_emergency_hyst",
312         [hwmon_temp_alarm] = "temp%d_alarm",
313         [hwmon_temp_lcrit_alarm] = "temp%d_lcrit_alarm",
314         [hwmon_temp_min_alarm] = "temp%d_min_alarm",
315         [hwmon_temp_max_alarm] = "temp%d_max_alarm",
316         [hwmon_temp_crit_alarm] = "temp%d_crit_alarm",
317         [hwmon_temp_emergency_alarm] = "temp%d_emergency_alarm",
318         [hwmon_temp_fault] = "temp%d_fault",
319         [hwmon_temp_offset] = "temp%d_offset",
320         [hwmon_temp_label] = "temp%d_label",
321         [hwmon_temp_lowest] = "temp%d_lowest",
322         [hwmon_temp_highest] = "temp%d_highest",
323         [hwmon_temp_reset_history] = "temp%d_reset_history",
324 };
325
326 static const char * const hwmon_in_attr_templates[] = {
327         [hwmon_in_input] = "in%d_input",
328         [hwmon_in_min] = "in%d_min",
329         [hwmon_in_max] = "in%d_max",
330         [hwmon_in_lcrit] = "in%d_lcrit",
331         [hwmon_in_crit] = "in%d_crit",
332         [hwmon_in_average] = "in%d_average",
333         [hwmon_in_lowest] = "in%d_lowest",
334         [hwmon_in_highest] = "in%d_highest",
335         [hwmon_in_reset_history] = "in%d_reset_history",
336         [hwmon_in_label] = "in%d_label",
337         [hwmon_in_alarm] = "in%d_alarm",
338         [hwmon_in_min_alarm] = "in%d_min_alarm",
339         [hwmon_in_max_alarm] = "in%d_max_alarm",
340         [hwmon_in_lcrit_alarm] = "in%d_lcrit_alarm",
341         [hwmon_in_crit_alarm] = "in%d_crit_alarm",
342 };
343
344 static const char * const hwmon_curr_attr_templates[] = {
345         [hwmon_curr_input] = "curr%d_input",
346         [hwmon_curr_min] = "curr%d_min",
347         [hwmon_curr_max] = "curr%d_max",
348         [hwmon_curr_lcrit] = "curr%d_lcrit",
349         [hwmon_curr_crit] = "curr%d_crit",
350         [hwmon_curr_average] = "curr%d_average",
351         [hwmon_curr_lowest] = "curr%d_lowest",
352         [hwmon_curr_highest] = "curr%d_highest",
353         [hwmon_curr_reset_history] = "curr%d_reset_history",
354         [hwmon_curr_label] = "curr%d_label",
355         [hwmon_curr_alarm] = "curr%d_alarm",
356         [hwmon_curr_min_alarm] = "curr%d_min_alarm",
357         [hwmon_curr_max_alarm] = "curr%d_max_alarm",
358         [hwmon_curr_lcrit_alarm] = "curr%d_lcrit_alarm",
359         [hwmon_curr_crit_alarm] = "curr%d_crit_alarm",
360 };
361
362 static const char * const hwmon_power_attr_templates[] = {
363         [hwmon_power_average] = "power%d_average",
364         [hwmon_power_average_interval] = "power%d_average_interval",
365         [hwmon_power_average_interval_max] = "power%d_interval_max",
366         [hwmon_power_average_interval_min] = "power%d_interval_min",
367         [hwmon_power_average_highest] = "power%d_average_highest",
368         [hwmon_power_average_lowest] = "power%d_average_lowest",
369         [hwmon_power_average_max] = "power%d_average_max",
370         [hwmon_power_average_min] = "power%d_average_min",
371         [hwmon_power_input] = "power%d_input",
372         [hwmon_power_input_highest] = "power%d_input_highest",
373         [hwmon_power_input_lowest] = "power%d_input_lowest",
374         [hwmon_power_reset_history] = "power%d_reset_history",
375         [hwmon_power_accuracy] = "power%d_accuracy",
376         [hwmon_power_cap] = "power%d_cap",
377         [hwmon_power_cap_hyst] = "power%d_cap_hyst",
378         [hwmon_power_cap_max] = "power%d_cap_max",
379         [hwmon_power_cap_min] = "power%d_cap_min",
380         [hwmon_power_max] = "power%d_max",
381         [hwmon_power_crit] = "power%d_crit",
382         [hwmon_power_label] = "power%d_label",
383         [hwmon_power_alarm] = "power%d_alarm",
384         [hwmon_power_cap_alarm] = "power%d_cap_alarm",
385         [hwmon_power_max_alarm] = "power%d_max_alarm",
386         [hwmon_power_crit_alarm] = "power%d_crit_alarm",
387 };
388
389 static const char * const hwmon_energy_attr_templates[] = {
390         [hwmon_energy_input] = "energy%d_input",
391         [hwmon_energy_label] = "energy%d_label",
392 };
393
394 static const char * const hwmon_humidity_attr_templates[] = {
395         [hwmon_humidity_input] = "humidity%d_input",
396         [hwmon_humidity_label] = "humidity%d_label",
397         [hwmon_humidity_min] = "humidity%d_min",
398         [hwmon_humidity_min_hyst] = "humidity%d_min_hyst",
399         [hwmon_humidity_max] = "humidity%d_max",
400         [hwmon_humidity_max_hyst] = "humidity%d_max_hyst",
401         [hwmon_humidity_alarm] = "humidity%d_alarm",
402         [hwmon_humidity_fault] = "humidity%d_fault",
403 };
404
405 static const char * const hwmon_fan_attr_templates[] = {
406         [hwmon_fan_input] = "fan%d_input",
407         [hwmon_fan_label] = "fan%d_label",
408         [hwmon_fan_min] = "fan%d_min",
409         [hwmon_fan_max] = "fan%d_max",
410         [hwmon_fan_div] = "fan%d_div",
411         [hwmon_fan_pulses] = "fan%d_pulses",
412         [hwmon_fan_target] = "fan%d_target",
413         [hwmon_fan_alarm] = "fan%d_alarm",
414         [hwmon_fan_min_alarm] = "fan%d_min_alarm",
415         [hwmon_fan_max_alarm] = "fan%d_max_alarm",
416         [hwmon_fan_fault] = "fan%d_fault",
417 };
418
419 static const char * const hwmon_pwm_attr_templates[] = {
420         [hwmon_pwm_input] = "pwm%d",
421         [hwmon_pwm_enable] = "pwm%d_enable",
422         [hwmon_pwm_mode] = "pwm%d_mode",
423         [hwmon_pwm_freq] = "pwm%d_freq",
424 };
425
426 static const char * const *__templates[] = {
427         [hwmon_chip] = hwmon_chip_attr_templates,
428         [hwmon_temp] = hwmon_temp_attr_templates,
429         [hwmon_in] = hwmon_in_attr_templates,
430         [hwmon_curr] = hwmon_curr_attr_templates,
431         [hwmon_power] = hwmon_power_attr_templates,
432         [hwmon_energy] = hwmon_energy_attr_templates,
433         [hwmon_humidity] = hwmon_humidity_attr_templates,
434         [hwmon_fan] = hwmon_fan_attr_templates,
435         [hwmon_pwm] = hwmon_pwm_attr_templates,
436 };
437
438 static const int __templates_size[] = {
439         [hwmon_chip] = ARRAY_SIZE(hwmon_chip_attr_templates),
440         [hwmon_temp] = ARRAY_SIZE(hwmon_temp_attr_templates),
441         [hwmon_in] = ARRAY_SIZE(hwmon_in_attr_templates),
442         [hwmon_curr] = ARRAY_SIZE(hwmon_curr_attr_templates),
443         [hwmon_power] = ARRAY_SIZE(hwmon_power_attr_templates),
444         [hwmon_energy] = ARRAY_SIZE(hwmon_energy_attr_templates),
445         [hwmon_humidity] = ARRAY_SIZE(hwmon_humidity_attr_templates),
446         [hwmon_fan] = ARRAY_SIZE(hwmon_fan_attr_templates),
447         [hwmon_pwm] = ARRAY_SIZE(hwmon_pwm_attr_templates),
448 };
449
450 static int hwmon_num_channel_attrs(const struct hwmon_channel_info *info)
451 {
452         int i, n;
453
454         for (i = n = 0; info->config[i]; i++)
455                 n += hweight32(info->config[i]);
456
457         return n;
458 }
459
460 static int hwmon_genattrs(const void *drvdata,
461                           struct attribute **attrs,
462                           const struct hwmon_ops *ops,
463                           const struct hwmon_channel_info *info)
464 {
465         const char * const *templates;
466         int template_size;
467         int i, aindex = 0;
468
469         if (info->type >= ARRAY_SIZE(__templates))
470                 return -EINVAL;
471
472         templates = __templates[info->type];
473         template_size = __templates_size[info->type];
474
475         for (i = 0; info->config[i]; i++) {
476                 u32 attr_mask = info->config[i];
477                 u32 attr;
478
479                 while (attr_mask) {
480                         struct attribute *a;
481
482                         attr = __ffs(attr_mask);
483                         attr_mask &= ~BIT(attr);
484                         if (attr >= template_size)
485                                 return -EINVAL;
486                         a = hwmon_genattr(drvdata, info->type, attr, i,
487                                           templates[attr], ops);
488                         if (IS_ERR(a)) {
489                                 if (PTR_ERR(a) != -ENOENT)
490                                         return PTR_ERR(a);
491                                 continue;
492                         }
493                         attrs[aindex++] = a;
494                 }
495         }
496         return aindex;
497 }
498
499 static struct attribute **
500 __hwmon_create_attrs(const void *drvdata, const struct hwmon_chip_info *chip)
501 {
502         int ret, i, aindex = 0, nattrs = 0;
503         struct attribute **attrs;
504
505         for (i = 0; chip->info[i]; i++)
506                 nattrs += hwmon_num_channel_attrs(chip->info[i]);
507
508         if (nattrs == 0)
509                 return ERR_PTR(-EINVAL);
510
511         attrs = kcalloc(nattrs + 1, sizeof(*attrs), GFP_KERNEL);
512         if (!attrs)
513                 return ERR_PTR(-ENOMEM);
514
515         for (i = 0; chip->info[i]; i++) {
516                 ret = hwmon_genattrs(drvdata, &attrs[aindex], chip->ops,
517                                      chip->info[i]);
518                 if (ret < 0) {
519                         hwmon_free_attrs(attrs);
520                         return ERR_PTR(ret);
521                 }
522                 aindex += ret;
523         }
524
525         return attrs;
526 }
527
528 static struct device *
529 __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
530                         const struct hwmon_chip_info *chip,
531                         const struct attribute_group **groups)
532 {
533         struct hwmon_device *hwdev;
534         struct device *hdev;
535         int i, j, err, id;
536
537         /* Do not accept invalid characters in hwmon name attribute */
538         if (name && (!strlen(name) || strpbrk(name, "-* \t\n")))
539                 return ERR_PTR(-EINVAL);
540
541         id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
542         if (id < 0)
543                 return ERR_PTR(id);
544
545         hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL);
546         if (hwdev == NULL) {
547                 err = -ENOMEM;
548                 goto ida_remove;
549         }
550
551         hdev = &hwdev->dev;
552
553         if (chip && chip->ops->is_visible) {
554                 struct attribute **attrs;
555                 int ngroups = 2;
556
557                 if (groups)
558                         for (i = 0; groups[i]; i++)
559                                 ngroups++;
560
561                 hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL);
562                 if (!hwdev->groups) {
563                         err = -ENOMEM;
564                         goto free_hwmon;
565                 }
566
567                 attrs = __hwmon_create_attrs(drvdata, chip);
568                 if (IS_ERR(attrs)) {
569                         err = PTR_ERR(attrs);
570                         goto free_hwmon;
571                 }
572
573                 hwdev->group.attrs = attrs;
574                 ngroups = 0;
575                 hwdev->groups[ngroups++] = &hwdev->group;
576
577                 if (groups) {
578                         for (i = 0; groups[i]; i++)
579                                 hwdev->groups[ngroups++] = groups[i];
580                 }
581
582                 hdev->groups = hwdev->groups;
583         } else {
584                 hdev->groups = groups;
585         }
586
587         hwdev->name = name;
588         hdev->class = &hwmon_class;
589         hdev->parent = dev;
590         hdev->of_node = dev ? dev->of_node : NULL;
591         hwdev->chip = chip;
592         dev_set_drvdata(hdev, drvdata);
593         dev_set_name(hdev, HWMON_ID_FORMAT, id);
594         err = device_register(hdev);
595         if (err) {
596                 put_device(hdev);
597                 goto ida_remove;
598         }
599
600         if (chip && chip->ops->is_visible && chip->ops->read &&
601             chip->info[0]->type == hwmon_chip &&
602             (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
603                 const struct hwmon_channel_info **info = chip->info;
604
605                 for (i = 1; info[i]; i++) {
606                         if (info[i]->type != hwmon_temp)
607                                 continue;
608
609                         for (j = 0; info[i]->config[j]; j++) {
610                                 if (!chip->ops->is_visible(drvdata, hwmon_temp,
611                                                            hwmon_temp_input, j))
612                                         continue;
613                                 if (info[i]->config[j] & HWMON_T_INPUT) {
614                                         err = hwmon_thermal_add_sensor(hdev, j);
615                                         if (err) {
616                                                 device_unregister(hdev);
617                                                 goto ida_remove;
618                                         }
619                                 }
620                         }
621                 }
622         }
623
624         return hdev;
625
626 free_hwmon:
627         hwmon_dev_release(hdev);
628 ida_remove:
629         ida_simple_remove(&hwmon_ida, id);
630         return ERR_PTR(err);
631 }
632
633 /**
634  * hwmon_device_register_with_groups - register w/ hwmon
635  * @dev: the parent device
636  * @name: hwmon name attribute
637  * @drvdata: driver data to attach to created device
638  * @groups: List of attribute groups to create
639  *
640  * hwmon_device_unregister() must be called when the device is no
641  * longer needed.
642  *
643  * Returns the pointer to the new device.
644  */
645 struct device *
646 hwmon_device_register_with_groups(struct device *dev, const char *name,
647                                   void *drvdata,
648                                   const struct attribute_group **groups)
649 {
650         return __hwmon_device_register(dev, name, drvdata, NULL, groups);
651 }
652 EXPORT_SYMBOL_GPL(hwmon_device_register_with_groups);
653
654 /**
655  * hwmon_device_register_with_info - register w/ hwmon
656  * @dev: the parent device
657  * @name: hwmon name attribute
658  * @drvdata: driver data to attach to created device
659  * @info: Pointer to hwmon chip information
660  * @groups - pointer to list of driver specific attribute groups
661  *
662  * hwmon_device_unregister() must be called when the device is no
663  * longer needed.
664  *
665  * Returns the pointer to the new device.
666  */
667 struct device *
668 hwmon_device_register_with_info(struct device *dev, const char *name,
669                                 void *drvdata,
670                                 const struct hwmon_chip_info *chip,
671                                 const struct attribute_group **groups)
672 {
673         if (chip && (!chip->ops || !chip->info))
674                 return ERR_PTR(-EINVAL);
675
676         return __hwmon_device_register(dev, name, drvdata, chip, groups);
677 }
678 EXPORT_SYMBOL_GPL(hwmon_device_register_with_info);
679
680 /**
681  * hwmon_device_register - register w/ hwmon
682  * @dev: the device to register
683  *
684  * hwmon_device_unregister() must be called when the device is no
685  * longer needed.
686  *
687  * Returns the pointer to the new device.
688  */
689 struct device *hwmon_device_register(struct device *dev)
690 {
691         return hwmon_device_register_with_groups(dev, NULL, NULL, NULL);
692 }
693 EXPORT_SYMBOL_GPL(hwmon_device_register);
694
695 /**
696  * hwmon_device_unregister - removes the previously registered class device
697  *
698  * @dev: the class device to destroy
699  */
700 void hwmon_device_unregister(struct device *dev)
701 {
702         int id;
703
704         if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
705                 device_unregister(dev);
706                 ida_simple_remove(&hwmon_ida, id);
707         } else
708                 dev_dbg(dev->parent,
709                         "hwmon_device_unregister() failed: bad class ID!\n");
710 }
711 EXPORT_SYMBOL_GPL(hwmon_device_unregister);
712
713 static void devm_hwmon_release(struct device *dev, void *res)
714 {
715         struct device *hwdev = *(struct device **)res;
716
717         hwmon_device_unregister(hwdev);
718 }
719
720 /**
721  * devm_hwmon_device_register_with_groups - register w/ hwmon
722  * @dev: the parent device
723  * @name: hwmon name attribute
724  * @drvdata: driver data to attach to created device
725  * @groups: List of attribute groups to create
726  *
727  * Returns the pointer to the new device. The new device is automatically
728  * unregistered with the parent device.
729  */
730 struct device *
731 devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
732                                        void *drvdata,
733                                        const struct attribute_group **groups)
734 {
735         struct device **ptr, *hwdev;
736
737         if (!dev)
738                 return ERR_PTR(-EINVAL);
739
740         ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
741         if (!ptr)
742                 return ERR_PTR(-ENOMEM);
743
744         hwdev = hwmon_device_register_with_groups(dev, name, drvdata, groups);
745         if (IS_ERR(hwdev))
746                 goto error;
747
748         *ptr = hwdev;
749         devres_add(dev, ptr);
750         return hwdev;
751
752 error:
753         devres_free(ptr);
754         return hwdev;
755 }
756 EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
757
758 /**
759  * devm_hwmon_device_register_with_info - register w/ hwmon
760  * @dev: the parent device
761  * @name: hwmon name attribute
762  * @drvdata: driver data to attach to created device
763  * @info: Pointer to hwmon chip information
764  * @groups - pointer to list of driver specific attribute groups
765  *
766  * Returns the pointer to the new device. The new device is automatically
767  * unregistered with the parent device.
768  */
769 struct device *
770 devm_hwmon_device_register_with_info(struct device *dev, const char *name,
771                                      void *drvdata,
772                                      const struct hwmon_chip_info *chip,
773                                      const struct attribute_group **groups)
774 {
775         struct device **ptr, *hwdev;
776
777         if (!dev)
778                 return ERR_PTR(-EINVAL);
779
780         ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
781         if (!ptr)
782                 return ERR_PTR(-ENOMEM);
783
784         hwdev = hwmon_device_register_with_info(dev, name, drvdata, chip,
785                                                 groups);
786         if (IS_ERR(hwdev))
787                 goto error;
788
789         *ptr = hwdev;
790         devres_add(dev, ptr);
791
792         return hwdev;
793
794 error:
795         devres_free(ptr);
796         return hwdev;
797 }
798 EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_info);
799
800 static int devm_hwmon_match(struct device *dev, void *res, void *data)
801 {
802         struct device **hwdev = res;
803
804         return *hwdev == data;
805 }
806
807 /**
808  * devm_hwmon_device_unregister - removes a previously registered hwmon device
809  *
810  * @dev: the parent device of the device to unregister
811  */
812 void devm_hwmon_device_unregister(struct device *dev)
813 {
814         WARN_ON(devres_release(dev, devm_hwmon_release, devm_hwmon_match, dev));
815 }
816 EXPORT_SYMBOL_GPL(devm_hwmon_device_unregister);
817
818 static void __init hwmon_pci_quirks(void)
819 {
820 #if defined CONFIG_X86 && defined CONFIG_PCI
821         struct pci_dev *sb;
822         u16 base;
823         u8 enable;
824
825         /* Open access to 0x295-0x296 on MSI MS-7031 */
826         sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL);
827         if (sb) {
828                 if (sb->subsystem_vendor == 0x1462 &&   /* MSI */
829                     sb->subsystem_device == 0x0031) {   /* MS-7031 */
830                         pci_read_config_byte(sb, 0x48, &enable);
831                         pci_read_config_word(sb, 0x64, &base);
832
833                         if (base == 0 && !(enable & BIT(2))) {
834                                 dev_info(&sb->dev,
835                                          "Opening wide generic port at 0x295\n");
836                                 pci_write_config_word(sb, 0x64, 0x295);
837                                 pci_write_config_byte(sb, 0x48,
838                                                       enable | BIT(2));
839                         }
840                 }
841                 pci_dev_put(sb);
842         }
843 #endif
844 }
845
846 static int __init hwmon_init(void)
847 {
848         int err;
849
850         hwmon_pci_quirks();
851
852         err = class_register(&hwmon_class);
853         if (err) {
854                 pr_err("couldn't register hwmon sysfs class\n");
855                 return err;
856         }
857         return 0;
858 }
859
860 static void __exit hwmon_exit(void)
861 {
862         class_unregister(&hwmon_class);
863 }
864
865 subsys_initcall(hwmon_init);
866 module_exit(hwmon_exit);
867
868 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
869 MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
870 MODULE_LICENSE("GPL");
871