Commit 008e5f3350e0a474baff3ed3eb4f79653a6b6745

Authored by Jean Delvare
1 parent 9d32df192d

hwmon: (pc87427) Add temperature monitoring support

Add support for the 6 temperature monitoring channels of the PC87427.
Note that the sensors resolution can vary, and I couldn't find a way
to figure it out, so we might have to compensate in user-space.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Guenter Roeck <guenter.roeck@ericsson.com>

Showing 3 changed files with 379 additions and 7 deletions Side-by-side Diff

Documentation/hwmon/pc87427
... ... @@ -18,7 +18,8 @@
18 18  
19 19 The National Semiconductor Super I/O chip includes complete hardware
20 20 monitoring capabilities. It can monitor up to 18 voltages, 8 fans and
21   -6 temperature sensors. Only the fans are supported at the moment.
  21 +6 temperature sensors. Only the fans and temperatures are supported at
  22 +the moment, voltages aren't.
22 23  
23 24 This chip also has fan controlling features (up to 4 PWM outputs),
24 25 which are partly supported by this driver.
... ... @@ -45,4 +46,15 @@
45 46 always off, always on, manual and automatic. The latter isn't supported
46 47 by the driver: you can only return to that mode if it was the original
47 48 setting, and the configuration interface is missing.
  49 +
  50 +
  51 +Temperature Monitoring
  52 +----------------------
  53 +
  54 +The PC87427 relies on external sensors (following the SensorPath
  55 +standard), so the resolution and range depend on the type of sensor
  56 +connected. The integer part can be 8-bit or 9-bit, and can be signed or
  57 +not. I couldn't find a way to figure out the external sensor data
  58 +temperature format, so user-space adjustment (typically by a factor 2)
  59 +may be required.
drivers/hwmon/Kconfig
... ... @@ -711,8 +711,8 @@
711 711 functions of the National Semiconductor PC87427 Super-I/O chip.
712 712 The chip has two distinct logical devices, one for fan speed
713 713 monitoring and control, and one for voltage and temperature
714   - monitoring. Only fan speed monitoring and control is supported
715   - right now.
  714 + monitoring. Fan speed monitoring and control are supported, as
  715 + well as temperature monitoring. Voltages aren't supported yet.
716 716  
717 717 This driver can also be built as a module. If so, the module
718 718 will be called pc87427.
drivers/hwmon/pc87427.c
1 1 /*
2 2 * pc87427.c - hardware monitoring driver for the
3 3 * National Semiconductor PC87427 Super-I/O chip
4   - * Copyright (C) 2006, 2008 Jean Delvare <khali@linux-fr.org>
  4 + * Copyright (C) 2006, 2008, 2010 Jean Delvare <khali@linux-fr.org>
5 5 *
6 6 * This program is free software; you can redistribute it and/or modify
7 7 * it under the terms of the GNU General Public License version 2 as
8 8  
... ... @@ -15,10 +15,11 @@
15 15 * Supports the following chips:
16 16 *
17 17 * Chip #vin #fan #pwm #temp devid
18   - * PC87427 - 8 4 - 0xF2
  18 + * PC87427 - 8 4 6 0xF2
19 19 *
20 20 * This driver assumes that no more than one chip is present.
21   - * Only fans are supported so far, although the chip can do much more.
  21 + * Only fans are fully supported so far. Temperatures are in read-only
  22 + * mode, and voltages aren't supported at all.
22 23 */
23 24  
24 25 #include <linux/module.h>
... ... @@ -62,6 +63,14 @@
62 63 u8 pwm_auto_ok; /* bit vector */
63 64 u8 pwm_enable[4]; /* register values */
64 65 u8 pwm[4]; /* register values */
  66 +
  67 + u8 temp_enabled; /* bit vector */
  68 + s16 temp[6]; /* register values */
  69 + s8 temp_min[6]; /* register values */
  70 + s8 temp_max[6]; /* register values */
  71 + s8 temp_crit[6]; /* register values */
  72 + u8 temp_status[6]; /* register values */
  73 + u8 temp_type[6]; /* register values */
65 74 };
66 75  
67 76 struct pc87427_sio_data {
... ... @@ -120,6 +129,8 @@
120 129 #define BANK_FM(nr) (nr)
121 130 #define BANK_FT(nr) (0x08 + (nr))
122 131 #define BANK_FC(nr) (0x10 + (nr) * 2)
  132 +#define BANK_TM(nr) (nr)
  133 +#define BANK_VM(nr) (0x08 + (nr))
123 134  
124 135 /*
125 136 * I/O access functions
... ... @@ -252,6 +263,72 @@
252 263 }
253 264  
254 265 /*
  266 + * Temperature registers and conversions
  267 + */
  268 +
  269 +#define PC87427_REG_TEMP_STATUS 0x10
  270 +#define PC87427_REG_TEMP 0x14
  271 +#define PC87427_REG_TEMP_MAX 0x18
  272 +#define PC87427_REG_TEMP_MIN 0x19
  273 +#define PC87427_REG_TEMP_CRIT 0x1a
  274 +#define PC87427_REG_TEMP_TYPE 0x1d
  275 +
  276 +#define TEMP_STATUS_CHANEN (1 << 0)
  277 +#define TEMP_STATUS_LOWFLG (1 << 1)
  278 +#define TEMP_STATUS_HIGHFLG (1 << 2)
  279 +#define TEMP_STATUS_CRITFLG (1 << 3)
  280 +#define TEMP_STATUS_SENSERR (1 << 5)
  281 +#define TEMP_TYPE_MASK (3 << 5)
  282 +
  283 +#define TEMP_TYPE_THERMISTOR (1 << 5)
  284 +#define TEMP_TYPE_REMOTE_DIODE (2 << 5)
  285 +#define TEMP_TYPE_LOCAL_DIODE (3 << 5)
  286 +
  287 +/* Dedicated function to read all registers related to a given temperature
  288 + input. This saves us quite a few locks and bank selections.
  289 + Must be called with data->lock held.
  290 + nr is from 0 to 5 */
  291 +static void pc87427_readall_temp(struct pc87427_data *data, u8 nr)
  292 +{
  293 + int iobase = data->address[LD_TEMP];
  294 +
  295 + outb(BANK_TM(nr), iobase + PC87427_REG_BANK);
  296 + data->temp[nr] = le16_to_cpu(inw(iobase + PC87427_REG_TEMP));
  297 + data->temp_max[nr] = inb(iobase + PC87427_REG_TEMP_MAX);
  298 + data->temp_min[nr] = inb(iobase + PC87427_REG_TEMP_MIN);
  299 + data->temp_crit[nr] = inb(iobase + PC87427_REG_TEMP_CRIT);
  300 + data->temp_type[nr] = inb(iobase + PC87427_REG_TEMP_TYPE);
  301 + data->temp_status[nr] = inb(iobase + PC87427_REG_TEMP_STATUS);
  302 + /* Clear fan alarm bits */
  303 + outb(data->temp_status[nr], iobase + PC87427_REG_TEMP_STATUS);
  304 +}
  305 +
  306 +static inline unsigned int temp_type_from_reg(u8 reg)
  307 +{
  308 + switch (reg & TEMP_TYPE_MASK) {
  309 + case TEMP_TYPE_THERMISTOR:
  310 + return 4;
  311 + case TEMP_TYPE_REMOTE_DIODE:
  312 + case TEMP_TYPE_LOCAL_DIODE:
  313 + return 3;
  314 + default:
  315 + return 0;
  316 + }
  317 +}
  318 +
  319 +/* We assume 8-bit thermal sensors; 9-bit thermal sensors are possible
  320 + too, but I have no idea how to figure out when they are used. */
  321 +static inline long temp_from_reg(s16 reg)
  322 +{
  323 + return reg * 1000 / 256;
  324 +}
  325 +
  326 +static inline long temp_from_reg8(s8 reg)
  327 +{
  328 + return reg * 1000;
  329 +}
  330 +
  331 +/*
255 332 * Data interface
256 333 */
257 334  
... ... @@ -279,6 +356,13 @@
279 356 pc87427_readall_pwm(data, i);
280 357 }
281 358  
  359 + /* Temperature channels */
  360 + for (i = 0; i < 6; i++) {
  361 + if (!(data->temp_enabled & (1 << i)))
  362 + continue;
  363 + pc87427_readall_temp(data, i);
  364 + }
  365 +
282 366 data->last_updated = jiffies;
283 367  
284 368 done:
... ... @@ -595,6 +679,251 @@
595 679 { .attrs = pc87427_attributes_pwm[3] },
596 680 };
597 681  
  682 +static ssize_t show_temp_input(struct device *dev, struct device_attribute
  683 + *devattr, char *buf)
  684 +{
  685 + struct pc87427_data *data = pc87427_update_device(dev);
  686 + int nr = to_sensor_dev_attr(devattr)->index;
  687 +
  688 + return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
  689 +}
  690 +
  691 +static ssize_t show_temp_min(struct device *dev, struct device_attribute
  692 + *devattr, char *buf)
  693 +{
  694 + struct pc87427_data *data = pc87427_update_device(dev);
  695 + int nr = to_sensor_dev_attr(devattr)->index;
  696 +
  697 + return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr]));
  698 +}
  699 +
  700 +static ssize_t show_temp_max(struct device *dev, struct device_attribute
  701 + *devattr, char *buf)
  702 +{
  703 + struct pc87427_data *data = pc87427_update_device(dev);
  704 + int nr = to_sensor_dev_attr(devattr)->index;
  705 +
  706 + return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr]));
  707 +}
  708 +
  709 +static ssize_t show_temp_crit(struct device *dev, struct device_attribute
  710 + *devattr, char *buf)
  711 +{
  712 + struct pc87427_data *data = pc87427_update_device(dev);
  713 + int nr = to_sensor_dev_attr(devattr)->index;
  714 +
  715 + return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr]));
  716 +}
  717 +
  718 +static ssize_t show_temp_type(struct device *dev, struct device_attribute
  719 + *devattr, char *buf)
  720 +{
  721 + struct pc87427_data *data = pc87427_update_device(dev);
  722 + int nr = to_sensor_dev_attr(devattr)->index;
  723 +
  724 + return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr]));
  725 +}
  726 +
  727 +static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute
  728 + *devattr, char *buf)
  729 +{
  730 + struct pc87427_data *data = pc87427_update_device(dev);
  731 + int nr = to_sensor_dev_attr(devattr)->index;
  732 +
  733 + return sprintf(buf, "%d\n", !!(data->temp_status[nr]
  734 + & TEMP_STATUS_LOWFLG));
  735 +}
  736 +
  737 +static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute
  738 + *devattr, char *buf)
  739 +{
  740 + struct pc87427_data *data = pc87427_update_device(dev);
  741 + int nr = to_sensor_dev_attr(devattr)->index;
  742 +
  743 + return sprintf(buf, "%d\n", !!(data->temp_status[nr]
  744 + & TEMP_STATUS_HIGHFLG));
  745 +}
  746 +
  747 +static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute
  748 + *devattr, char *buf)
  749 +{
  750 + struct pc87427_data *data = pc87427_update_device(dev);
  751 + int nr = to_sensor_dev_attr(devattr)->index;
  752 +
  753 + return sprintf(buf, "%d\n", !!(data->temp_status[nr]
  754 + & TEMP_STATUS_CRITFLG));
  755 +}
  756 +
  757 +static ssize_t show_temp_fault(struct device *dev, struct device_attribute
  758 + *devattr, char *buf)
  759 +{
  760 + struct pc87427_data *data = pc87427_update_device(dev);
  761 + int nr = to_sensor_dev_attr(devattr)->index;
  762 +
  763 + return sprintf(buf, "%d\n", !!(data->temp_status[nr]
  764 + & TEMP_STATUS_SENSERR));
  765 +}
  766 +
  767 +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
  768 +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
  769 +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2);
  770 +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3);
  771 +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4);
  772 +static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5);
  773 +
  774 +static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, NULL, 0);
  775 +static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, NULL, 1);
  776 +static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, NULL, 2);
  777 +static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, NULL, 3);
  778 +static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, NULL, 4);
  779 +static SENSOR_DEVICE_ATTR(temp6_min, S_IRUGO, show_temp_min, NULL, 5);
  780 +
  781 +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
  782 +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
  783 +static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
  784 +static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
  785 +static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
  786 +static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
  787 +
  788 +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
  789 +static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
  790 +static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
  791 +static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
  792 +static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
  793 +static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
  794 +
  795 +static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
  796 +static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
  797 +static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
  798 +static SENSOR_DEVICE_ATTR(temp4_type, S_IRUGO, show_temp_type, NULL, 3);
  799 +static SENSOR_DEVICE_ATTR(temp5_type, S_IRUGO, show_temp_type, NULL, 4);
  800 +static SENSOR_DEVICE_ATTR(temp6_type, S_IRUGO, show_temp_type, NULL, 5);
  801 +
  802 +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
  803 + show_temp_min_alarm, NULL, 0);
  804 +static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO,
  805 + show_temp_min_alarm, NULL, 1);
  806 +static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO,
  807 + show_temp_min_alarm, NULL, 2);
  808 +static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO,
  809 + show_temp_min_alarm, NULL, 3);
  810 +static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO,
  811 + show_temp_min_alarm, NULL, 4);
  812 +static SENSOR_DEVICE_ATTR(temp6_min_alarm, S_IRUGO,
  813 + show_temp_min_alarm, NULL, 5);
  814 +
  815 +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
  816 + show_temp_max_alarm, NULL, 0);
  817 +static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO,
  818 + show_temp_max_alarm, NULL, 1);
  819 +static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO,
  820 + show_temp_max_alarm, NULL, 2);
  821 +static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO,
  822 + show_temp_max_alarm, NULL, 3);
  823 +static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO,
  824 + show_temp_max_alarm, NULL, 4);
  825 +static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO,
  826 + show_temp_max_alarm, NULL, 5);
  827 +
  828 +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
  829 + show_temp_crit_alarm, NULL, 0);
  830 +static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO,
  831 + show_temp_crit_alarm, NULL, 1);
  832 +static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO,
  833 + show_temp_crit_alarm, NULL, 2);
  834 +static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO,
  835 + show_temp_crit_alarm, NULL, 3);
  836 +static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO,
  837 + show_temp_crit_alarm, NULL, 4);
  838 +static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO,
  839 + show_temp_crit_alarm, NULL, 5);
  840 +
  841 +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
  842 +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
  843 +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
  844 +static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
  845 +static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
  846 +static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
  847 +
  848 +static struct attribute *pc87427_attributes_temp[6][10] = {
  849 + {
  850 + &sensor_dev_attr_temp1_input.dev_attr.attr,
  851 + &sensor_dev_attr_temp1_min.dev_attr.attr,
  852 + &sensor_dev_attr_temp1_max.dev_attr.attr,
  853 + &sensor_dev_attr_temp1_crit.dev_attr.attr,
  854 + &sensor_dev_attr_temp1_type.dev_attr.attr,
  855 + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
  856 + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
  857 + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
  858 + &sensor_dev_attr_temp1_fault.dev_attr.attr,
  859 + NULL
  860 + }, {
  861 + &sensor_dev_attr_temp2_input.dev_attr.attr,
  862 + &sensor_dev_attr_temp2_min.dev_attr.attr,
  863 + &sensor_dev_attr_temp2_max.dev_attr.attr,
  864 + &sensor_dev_attr_temp2_crit.dev_attr.attr,
  865 + &sensor_dev_attr_temp2_type.dev_attr.attr,
  866 + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
  867 + &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
  868 + &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
  869 + &sensor_dev_attr_temp2_fault.dev_attr.attr,
  870 + NULL
  871 + }, {
  872 + &sensor_dev_attr_temp3_input.dev_attr.attr,
  873 + &sensor_dev_attr_temp3_min.dev_attr.attr,
  874 + &sensor_dev_attr_temp3_max.dev_attr.attr,
  875 + &sensor_dev_attr_temp3_crit.dev_attr.attr,
  876 + &sensor_dev_attr_temp3_type.dev_attr.attr,
  877 + &sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
  878 + &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
  879 + &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
  880 + &sensor_dev_attr_temp3_fault.dev_attr.attr,
  881 + NULL
  882 + }, {
  883 + &sensor_dev_attr_temp4_input.dev_attr.attr,
  884 + &sensor_dev_attr_temp4_min.dev_attr.attr,
  885 + &sensor_dev_attr_temp4_max.dev_attr.attr,
  886 + &sensor_dev_attr_temp4_crit.dev_attr.attr,
  887 + &sensor_dev_attr_temp4_type.dev_attr.attr,
  888 + &sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
  889 + &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
  890 + &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
  891 + &sensor_dev_attr_temp4_fault.dev_attr.attr,
  892 + NULL
  893 + }, {
  894 + &sensor_dev_attr_temp5_input.dev_attr.attr,
  895 + &sensor_dev_attr_temp5_min.dev_attr.attr,
  896 + &sensor_dev_attr_temp5_max.dev_attr.attr,
  897 + &sensor_dev_attr_temp5_crit.dev_attr.attr,
  898 + &sensor_dev_attr_temp5_type.dev_attr.attr,
  899 + &sensor_dev_attr_temp5_min_alarm.dev_attr.attr,
  900 + &sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
  901 + &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
  902 + &sensor_dev_attr_temp5_fault.dev_attr.attr,
  903 + NULL
  904 + }, {
  905 + &sensor_dev_attr_temp6_input.dev_attr.attr,
  906 + &sensor_dev_attr_temp6_min.dev_attr.attr,
  907 + &sensor_dev_attr_temp6_max.dev_attr.attr,
  908 + &sensor_dev_attr_temp6_crit.dev_attr.attr,
  909 + &sensor_dev_attr_temp6_type.dev_attr.attr,
  910 + &sensor_dev_attr_temp6_min_alarm.dev_attr.attr,
  911 + &sensor_dev_attr_temp6_max_alarm.dev_attr.attr,
  912 + &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
  913 + &sensor_dev_attr_temp6_fault.dev_attr.attr,
  914 + NULL
  915 + }
  916 +};
  917 +
  918 +static const struct attribute_group pc87427_group_temp[6] = {
  919 + { .attrs = pc87427_attributes_temp[0] },
  920 + { .attrs = pc87427_attributes_temp[1] },
  921 + { .attrs = pc87427_attributes_temp[2] },
  922 + { .attrs = pc87427_attributes_temp[3] },
  923 + { .attrs = pc87427_attributes_temp[4] },
  924 + { .attrs = pc87427_attributes_temp[5] },
  925 +};
  926 +
598 927 static ssize_t show_name(struct device *dev, struct device_attribute
599 928 *devattr, char *buf)
600 929 {
... ... @@ -659,7 +988,7 @@
659 988 /* The FMC module should be ready */
660 989 reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
661 990 if (!(reg & 0x80))
662   - dev_warn(dev, "FMC module not ready!\n");
  991 + dev_warn(dev, "%s module not ready!\n", "FMC");
663 992  
664 993 /* Check which fans are enabled */
665 994 for (i = 0; i < 8; i++) {
... ... @@ -701,6 +1030,19 @@
701 1030 data->pwm_auto_ok |= (1 << i);
702 1031 }
703 1032 }
  1033 +
  1034 + /* The HMC module should be ready */
  1035 + reg = pc87427_read8(data, LD_TEMP, PC87427_REG_BANK);
  1036 + if (!(reg & 0x80))
  1037 + dev_warn(dev, "%s module not ready!\n", "HMC");
  1038 +
  1039 + /* Check which temperature channels are enabled */
  1040 + for (i = 0; i < 6; i++) {
  1041 + reg = pc87427_read8_bank(data, LD_TEMP, BANK_TM(i),
  1042 + PC87427_REG_TEMP_STATUS);
  1043 + if (reg & TEMP_STATUS_CHANEN)
  1044 + data->temp_enabled |= (1 << i);
  1045 + }
704 1046 }
705 1047  
706 1048 static int __devinit pc87427_probe(struct platform_device *pdev)
... ... @@ -749,6 +1091,14 @@
749 1091 if (err)
750 1092 goto exit_remove_files;
751 1093 }
  1094 + for (i = 0; i < 6; i++) {
  1095 + if (!(data->temp_enabled & (1 << i)))
  1096 + continue;
  1097 + err = sysfs_create_group(&pdev->dev.kobj,
  1098 + &pc87427_group_temp[i]);
  1099 + if (err)
  1100 + goto exit_remove_files;
  1101 + }
752 1102  
753 1103 data->hwmon_dev = hwmon_device_register(&pdev->dev);
754 1104 if (IS_ERR(data->hwmon_dev)) {
... ... @@ -770,6 +1120,11 @@
770 1120 continue;
771 1121 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_pwm[i]);
772 1122 }
  1123 + for (i = 0; i < 6; i++) {
  1124 + if (!(data->temp_enabled & (1 << i)))
  1125 + continue;
  1126 + sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_temp[i]);
  1127 + }
773 1128 exit_release_region:
774 1129 pc87427_release_regions(pdev, res_count);
775 1130 exit_kfree:
... ... @@ -797,6 +1152,11 @@
797 1152 if (!(data->pwm_enabled & (1 << i)))
798 1153 continue;
799 1154 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_pwm[i]);
  1155 + }
  1156 + for (i = 0; i < 6; i++) {
  1157 + if (!(data->temp_enabled & (1 << i)))
  1158 + continue;
  1159 + sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_temp[i]);
800 1160 }
801 1161 platform_set_drvdata(pdev, NULL);
802 1162 kfree(data);