aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/fschmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/fschmd.c')
-rw-r--r--drivers/hwmon/fschmd.c229
1 files changed, 170 insertions, 59 deletions
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index d07f4ef75092..ea955edde87e 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -1,6 +1,6 @@
1/* fschmd.c 1/* fschmd.c
2 * 2 *
3 * Copyright (C) 2007,2008 Hans de Goede <hdegoede@redhat.com> 3 * Copyright (C) 2007 - 2009 Hans de Goede <hdegoede@redhat.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
19 19
20/* 20/*
21 * Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes, 21 * Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes,
22 * Scylla, Heracles and Heimdall chips 22 * Scylla, Heracles, Heimdall, Hades and Syleus chips
23 * 23 *
24 * Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6 24 * Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6
25 * (candidate) fschmd drivers: 25 * (candidate) fschmd drivers:
@@ -56,7 +56,7 @@ static int nowayout = WATCHDOG_NOWAYOUT;
56module_param(nowayout, int, 0); 56module_param(nowayout, int, 0);
57MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 57MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
58 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 58 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
59I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); 59I2C_CLIENT_INSMOD_7(fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl);
60 60
61/* 61/*
62 * The FSCHMD registers and other defines 62 * The FSCHMD registers and other defines
@@ -75,9 +75,12 @@ I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd);
75#define FSCHMD_CONTROL_ALERT_LED 0x01 75#define FSCHMD_CONTROL_ALERT_LED 0x01
76 76
77/* watchdog */ 77/* watchdog */
78#define FSCHMD_REG_WDOG_PRESET 0x28 78static const u8 FSCHMD_REG_WDOG_CONTROL[7] =
79#define FSCHMD_REG_WDOG_STATE 0x23 79 { 0x21, 0x21, 0x21, 0x21, 0x21, 0x28, 0x28 };
80#define FSCHMD_REG_WDOG_CONTROL 0x21 80static const u8 FSCHMD_REG_WDOG_STATE[7] =
81 { 0x23, 0x23, 0x23, 0x23, 0x23, 0x29, 0x29 };
82static const u8 FSCHMD_REG_WDOG_PRESET[7] =
83 { 0x28, 0x28, 0x28, 0x28, 0x28, 0x2a, 0x2a };
81 84
82#define FSCHMD_WDOG_CONTROL_TRIGGER 0x10 85#define FSCHMD_WDOG_CONTROL_TRIGGER 0x10
83#define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */ 86#define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */
@@ -87,70 +90,95 @@ I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd);
87#define FSCHMD_WDOG_STATE_CARDRESET 0x02 90#define FSCHMD_WDOG_STATE_CARDRESET 0x02
88 91
89/* voltages, weird order is to keep the same order as the old drivers */ 92/* voltages, weird order is to keep the same order as the old drivers */
90static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 }; 93static const u8 FSCHMD_REG_VOLT[7][6] = {
94 { 0x45, 0x42, 0x48 }, /* pos */
95 { 0x45, 0x42, 0x48 }, /* her */
96 { 0x45, 0x42, 0x48 }, /* scy */
97 { 0x45, 0x42, 0x48 }, /* hrc */
98 { 0x45, 0x42, 0x48 }, /* hmd */
99 { 0x21, 0x20, 0x22 }, /* hds */
100 { 0x21, 0x20, 0x22, 0x23, 0x24, 0x25 }, /* syl */
101};
102
103static const int FSCHMD_NO_VOLT_SENSORS[7] = { 3, 3, 3, 3, 3, 3, 6 };
91 104
92/* minimum pwm at which the fan is driven (pwm can by increased depending on 105/* minimum pwm at which the fan is driven (pwm can by increased depending on
93 the temp. Notice that for the scy some fans share there minimum speed. 106 the temp. Notice that for the scy some fans share there minimum speed.
94 Also notice that with the scy the sensor order is different than with the 107 Also notice that with the scy the sensor order is different than with the
95 other chips, this order was in the 2.4 driver and kept for consistency. */ 108 other chips, this order was in the 2.4 driver and kept for consistency. */
96static const u8 FSCHMD_REG_FAN_MIN[5][6] = { 109static const u8 FSCHMD_REG_FAN_MIN[7][7] = {
97 { 0x55, 0x65 }, /* pos */ 110 { 0x55, 0x65 }, /* pos */
98 { 0x55, 0x65, 0xb5 }, /* her */ 111 { 0x55, 0x65, 0xb5 }, /* her */
99 { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 }, /* scy */ 112 { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 }, /* scy */
100 { 0x55, 0x65, 0xa5, 0xb5 }, /* hrc */ 113 { 0x55, 0x65, 0xa5, 0xb5 }, /* hrc */
101 { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hmd */ 114 { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hmd */
115 { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hds */
116 { 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb4 }, /* syl */
102}; 117};
103 118
104/* actual fan speed */ 119/* actual fan speed */
105static const u8 FSCHMD_REG_FAN_ACT[5][6] = { 120static const u8 FSCHMD_REG_FAN_ACT[7][7] = {
106 { 0x0e, 0x6b, 0xab }, /* pos */ 121 { 0x0e, 0x6b, 0xab }, /* pos */
107 { 0x0e, 0x6b, 0xbb }, /* her */ 122 { 0x0e, 0x6b, 0xbb }, /* her */
108 { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb }, /* scy */ 123 { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb }, /* scy */
109 { 0x0e, 0x6b, 0xab, 0xbb }, /* hrc */ 124 { 0x0e, 0x6b, 0xab, 0xbb }, /* hrc */
110 { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hmd */ 125 { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hmd */
126 { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hds */
127 { 0x57, 0x67, 0x77, 0x87, 0x97, 0xa7, 0xb7 }, /* syl */
111}; 128};
112 129
113/* fan status registers */ 130/* fan status registers */
114static const u8 FSCHMD_REG_FAN_STATE[5][6] = { 131static const u8 FSCHMD_REG_FAN_STATE[7][7] = {
115 { 0x0d, 0x62, 0xa2 }, /* pos */ 132 { 0x0d, 0x62, 0xa2 }, /* pos */
116 { 0x0d, 0x62, 0xb2 }, /* her */ 133 { 0x0d, 0x62, 0xb2 }, /* her */
117 { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 }, /* scy */ 134 { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 }, /* scy */
118 { 0x0d, 0x62, 0xa2, 0xb2 }, /* hrc */ 135 { 0x0d, 0x62, 0xa2, 0xb2 }, /* hrc */
119 { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hmd */ 136 { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hmd */
137 { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hds */
138 { 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0 }, /* syl */
120}; 139};
121 140
122/* fan ripple / divider registers */ 141/* fan ripple / divider registers */
123static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = { 142static const u8 FSCHMD_REG_FAN_RIPPLE[7][7] = {
124 { 0x0f, 0x6f, 0xaf }, /* pos */ 143 { 0x0f, 0x6f, 0xaf }, /* pos */
125 { 0x0f, 0x6f, 0xbf }, /* her */ 144 { 0x0f, 0x6f, 0xbf }, /* her */
126 { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf }, /* scy */ 145 { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf }, /* scy */
127 { 0x0f, 0x6f, 0xaf, 0xbf }, /* hrc */ 146 { 0x0f, 0x6f, 0xaf, 0xbf }, /* hrc */
128 { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hmd */ 147 { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hmd */
148 { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hds */
149 { 0x56, 0x66, 0x76, 0x86, 0x96, 0xa6, 0xb6 }, /* syl */
129}; 150};
130 151
131static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 }; 152static const int FSCHMD_NO_FAN_SENSORS[7] = { 3, 3, 6, 4, 5, 5, 7 };
132 153
133/* Fan status register bitmasks */ 154/* Fan status register bitmasks */
134#define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */ 155#define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */
135#define FSCHMD_FAN_NOT_PRESENT 0x08 /* not documented */ 156#define FSCHMD_FAN_NOT_PRESENT 0x08
157#define FSCHMD_FAN_DISABLED 0x80
136 158
137 159
138/* actual temperature registers */ 160/* actual temperature registers */
139static const u8 FSCHMD_REG_TEMP_ACT[5][5] = { 161static const u8 FSCHMD_REG_TEMP_ACT[7][11] = {
140 { 0x64, 0x32, 0x35 }, /* pos */ 162 { 0x64, 0x32, 0x35 }, /* pos */
141 { 0x64, 0x32, 0x35 }, /* her */ 163 { 0x64, 0x32, 0x35 }, /* her */
142 { 0x64, 0xD0, 0x32, 0x35 }, /* scy */ 164 { 0x64, 0xD0, 0x32, 0x35 }, /* scy */
143 { 0x64, 0x32, 0x35 }, /* hrc */ 165 { 0x64, 0x32, 0x35 }, /* hrc */
144 { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hmd */ 166 { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hmd */
167 { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hds */
168 { 0x58, 0x68, 0x78, 0x88, 0x98, 0xa8, /* syl */
169 0xb8, 0xc8, 0xd8, 0xe8, 0xf8 },
145}; 170};
146 171
147/* temperature state registers */ 172/* temperature state registers */
148static const u8 FSCHMD_REG_TEMP_STATE[5][5] = { 173static const u8 FSCHMD_REG_TEMP_STATE[7][11] = {
149 { 0x71, 0x81, 0x91 }, /* pos */ 174 { 0x71, 0x81, 0x91 }, /* pos */
150 { 0x71, 0x81, 0x91 }, /* her */ 175 { 0x71, 0x81, 0x91 }, /* her */
151 { 0x71, 0xd1, 0x81, 0x91 }, /* scy */ 176 { 0x71, 0xd1, 0x81, 0x91 }, /* scy */
152 { 0x71, 0x81, 0x91 }, /* hrc */ 177 { 0x71, 0x81, 0x91 }, /* hrc */
153 { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */ 178 { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */
179 { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hds */
180 { 0x59, 0x69, 0x79, 0x89, 0x99, 0xa9, /* syl */
181 0xb9, 0xc9, 0xd9, 0xe9, 0xf9 },
154}; 182};
155 183
156/* temperature high limit registers, FSC does not document these. Proven to be 184/* temperature high limit registers, FSC does not document these. Proven to be
@@ -158,24 +186,31 @@ static const u8 FSCHMD_REG_TEMP_STATE[5][5] = {
158 in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers 186 in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers
159 at these addresses, but doesn't want to confirm they are the same as with 187 at these addresses, but doesn't want to confirm they are the same as with
160 the fscher?? */ 188 the fscher?? */
161static const u8 FSCHMD_REG_TEMP_LIMIT[5][5] = { 189static const u8 FSCHMD_REG_TEMP_LIMIT[7][11] = {
162 { 0, 0, 0 }, /* pos */ 190 { 0, 0, 0 }, /* pos */
163 { 0x76, 0x86, 0x96 }, /* her */ 191 { 0x76, 0x86, 0x96 }, /* her */
164 { 0x76, 0xd6, 0x86, 0x96 }, /* scy */ 192 { 0x76, 0xd6, 0x86, 0x96 }, /* scy */
165 { 0x76, 0x86, 0x96 }, /* hrc */ 193 { 0x76, 0x86, 0x96 }, /* hrc */
166 { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */ 194 { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */
195 { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hds */
196 { 0x5a, 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, /* syl */
197 0xba, 0xca, 0xda, 0xea, 0xfa },
167}; 198};
168 199
169/* These were found through experimenting with an fscher, currently they are 200/* These were found through experimenting with an fscher, currently they are
170 not used, but we keep them around for future reference. 201 not used, but we keep them around for future reference.
202 On the fscsyl AUTOP1 lives at 0x#c (so 0x5c for fan1, 0x6c for fan2, etc),
203 AUTOP2 lives at 0x#e, and 0x#1 is a bitmask defining which temps influence
204 the fan speed.
171static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 }; 205static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 };
172static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */ 206static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */
173 207
174static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; 208static const int FSCHMD_NO_TEMP_SENSORS[7] = { 3, 3, 4, 3, 5, 5, 11 };
175 209
176/* temp status register bitmasks */ 210/* temp status register bitmasks */
177#define FSCHMD_TEMP_WORKING 0x01 211#define FSCHMD_TEMP_WORKING 0x01
178#define FSCHMD_TEMP_ALERT 0x02 212#define FSCHMD_TEMP_ALERT 0x02
213#define FSCHMD_TEMP_DISABLED 0x80
179/* there only really is an alarm if the sensor is working and alert == 1 */ 214/* there only really is an alarm if the sensor is working and alert == 1 */
180#define FSCHMD_TEMP_ALARM_MASK \ 215#define FSCHMD_TEMP_ALARM_MASK \
181 (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT) 216 (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT)
@@ -201,6 +236,8 @@ static const struct i2c_device_id fschmd_id[] = {
201 { "fscscy", fscscy }, 236 { "fscscy", fscscy },
202 { "fschrc", fschrc }, 237 { "fschrc", fschrc },
203 { "fschmd", fschmd }, 238 { "fschmd", fschmd },
239 { "fschds", fschds },
240 { "fscsyl", fscsyl },
204 { } 241 { }
205}; 242};
206MODULE_DEVICE_TABLE(i2c, fschmd_id); 243MODULE_DEVICE_TABLE(i2c, fschmd_id);
@@ -242,14 +279,14 @@ struct fschmd_data {
242 u8 watchdog_control; /* watchdog control register */ 279 u8 watchdog_control; /* watchdog control register */
243 u8 watchdog_state; /* watchdog status register */ 280 u8 watchdog_state; /* watchdog status register */
244 u8 watchdog_preset; /* watchdog counter preset on trigger val */ 281 u8 watchdog_preset; /* watchdog counter preset on trigger val */
245 u8 volt[3]; /* 12, 5, battery voltage */ 282 u8 volt[6]; /* voltage */
246 u8 temp_act[5]; /* temperature */ 283 u8 temp_act[11]; /* temperature */
247 u8 temp_status[5]; /* status of sensor */ 284 u8 temp_status[11]; /* status of sensor */
248 u8 temp_max[5]; /* high temp limit, notice: undocumented! */ 285 u8 temp_max[11]; /* high temp limit, notice: undocumented! */
249 u8 fan_act[6]; /* fans revolutions per second */ 286 u8 fan_act[7]; /* fans revolutions per second */
250 u8 fan_status[6]; /* fan status */ 287 u8 fan_status[7]; /* fan status */
251 u8 fan_min[6]; /* fan min value for rps */ 288 u8 fan_min[7]; /* fan min value for rps */
252 u8 fan_ripple[6]; /* divider for rps */ 289 u8 fan_ripple[7]; /* divider for rps */
253}; 290};
254 291
255/* Global variables to hold information read from special DMI tables, which are 292/* Global variables to hold information read from special DMI tables, which are
@@ -257,8 +294,8 @@ struct fschmd_data {
257 protect these with a lock as they are only modified from our attach function 294 protect these with a lock as they are only modified from our attach function
258 which always gets called with the i2c-core lock held and never accessed 295 which always gets called with the i2c-core lock held and never accessed
259 before the attach function is done with them. */ 296 before the attach function is done with them. */
260static int dmi_mult[3] = { 490, 200, 100 }; 297static int dmi_mult[6] = { 490, 200, 100, 100, 200, 100 };
261static int dmi_offset[3] = { 0, 0, 0 }; 298static int dmi_offset[6] = { 0, 0, 0, 0, 0, 0 };
262static int dmi_vref = -1; 299static int dmi_vref = -1;
263 300
264/* Somewhat ugly :( global data pointer list with all fschmd devices, so that 301/* Somewhat ugly :( global data pointer list with all fschmd devices, so that
@@ -450,10 +487,11 @@ static ssize_t show_pwm_auto_point1_pwm(struct device *dev,
450 struct device_attribute *devattr, char *buf) 487 struct device_attribute *devattr, char *buf)
451{ 488{
452 int index = to_sensor_dev_attr(devattr)->index; 489 int index = to_sensor_dev_attr(devattr)->index;
453 int val = fschmd_update_device(dev)->fan_min[index]; 490 struct fschmd_data *data = fschmd_update_device(dev);
491 int val = data->fan_min[index];
454 492
455 /* 0 = allow turning off, 1-255 = 50-100% */ 493 /* 0 = allow turning off (except on the syl), 1-255 = 50-100% */
456 if (val) 494 if (val || data->kind == fscsyl - 1)
457 val = val / 2 + 128; 495 val = val / 2 + 128;
458 496
459 return sprintf(buf, "%d\n", val); 497 return sprintf(buf, "%d\n", val);
@@ -466,8 +504,8 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
466 struct fschmd_data *data = dev_get_drvdata(dev); 504 struct fschmd_data *data = dev_get_drvdata(dev);
467 unsigned long v = simple_strtoul(buf, NULL, 10); 505 unsigned long v = simple_strtoul(buf, NULL, 10);
468 506
469 /* register: 0 = allow turning off, 1-255 = 50-100% */ 507 /* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */
470 if (v) { 508 if (v || data->kind == fscsyl - 1) {
471 v = SENSORS_LIMIT(v, 128, 255); 509 v = SENSORS_LIMIT(v, 128, 255);
472 v = (v - 128) * 2 + 1; 510 v = (v - 128) * 2 + 1;
473 } 511 }
@@ -522,11 +560,15 @@ static ssize_t store_alert_led(struct device *dev,
522 return count; 560 return count;
523} 561}
524 562
563static DEVICE_ATTR(alert_led, 0644, show_alert_led, store_alert_led);
564
525static struct sensor_device_attribute fschmd_attr[] = { 565static struct sensor_device_attribute fschmd_attr[] = {
526 SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0), 566 SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0),
527 SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1), 567 SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1),
528 SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2), 568 SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2),
529 SENSOR_ATTR(alert_led, 0644, show_alert_led, store_alert_led, 0), 569 SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3),
570 SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4),
571 SENSOR_ATTR(in5_input, 0444, show_in_value, NULL, 5),
530}; 572};
531 573
532static struct sensor_device_attribute fschmd_temp_attr[] = { 574static struct sensor_device_attribute fschmd_temp_attr[] = {
@@ -550,6 +592,30 @@ static struct sensor_device_attribute fschmd_temp_attr[] = {
550 SENSOR_ATTR(temp5_max, 0644, show_temp_max, store_temp_max, 4), 592 SENSOR_ATTR(temp5_max, 0644, show_temp_max, store_temp_max, 4),
551 SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4), 593 SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4),
552 SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4), 594 SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4),
595 SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5),
596 SENSOR_ATTR(temp6_max, 0644, show_temp_max, store_temp_max, 5),
597 SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5),
598 SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5),
599 SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6),
600 SENSOR_ATTR(temp7_max, 0644, show_temp_max, store_temp_max, 6),
601 SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6),
602 SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6),
603 SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7),
604 SENSOR_ATTR(temp8_max, 0644, show_temp_max, store_temp_max, 7),
605 SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7),
606 SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7),
607 SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8),
608 SENSOR_ATTR(temp9_max, 0644, show_temp_max, store_temp_max, 8),
609 SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8),
610 SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8),
611 SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9),
612 SENSOR_ATTR(temp10_max, 0644, show_temp_max, store_temp_max, 9),
613 SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9),
614 SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9),
615 SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10),
616 SENSOR_ATTR(temp11_max, 0644, show_temp_max, store_temp_max, 10),
617 SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10),
618 SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10),
553}; 619};
554 620
555static struct sensor_device_attribute fschmd_fan_attr[] = { 621static struct sensor_device_attribute fschmd_fan_attr[] = {
@@ -589,6 +655,12 @@ static struct sensor_device_attribute fschmd_fan_attr[] = {
589 SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5), 655 SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5),
590 SENSOR_ATTR(pwm6_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, 656 SENSOR_ATTR(pwm6_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
591 store_pwm_auto_point1_pwm, 5), 657 store_pwm_auto_point1_pwm, 5),
658 SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6),
659 SENSOR_ATTR(fan7_div, 0644, show_fan_div, store_fan_div, 6),
660 SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6),
661 SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6),
662 SENSOR_ATTR(pwm7_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
663 store_pwm_auto_point1_pwm, 6),
592}; 664};
593 665
594 666
@@ -624,10 +696,11 @@ static int watchdog_set_timeout(struct fschmd_data *data, int timeout)
624 data->watchdog_preset = DIV_ROUND_UP(timeout, resolution); 696 data->watchdog_preset = DIV_ROUND_UP(timeout, resolution);
625 697
626 /* Write new timeout value */ 698 /* Write new timeout value */
627 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_PRESET, 699 i2c_smbus_write_byte_data(data->client,
628 data->watchdog_preset); 700 FSCHMD_REG_WDOG_PRESET[data->kind], data->watchdog_preset);
629 /* Write new control register, do not trigger! */ 701 /* Write new control register, do not trigger! */
630 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, 702 i2c_smbus_write_byte_data(data->client,
703 FSCHMD_REG_WDOG_CONTROL[data->kind],
631 data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER); 704 data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER);
632 705
633 ret = data->watchdog_preset * resolution; 706 ret = data->watchdog_preset * resolution;
@@ -662,8 +735,9 @@ static int watchdog_trigger(struct fschmd_data *data)
662 } 735 }
663 736
664 data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER; 737 data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER;
665 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, 738 i2c_smbus_write_byte_data(data->client,
666 data->watchdog_control); 739 FSCHMD_REG_WDOG_CONTROL[data->kind],
740 data->watchdog_control);
667leave: 741leave:
668 mutex_unlock(&data->watchdog_lock); 742 mutex_unlock(&data->watchdog_lock);
669 return ret; 743 return ret;
@@ -682,7 +756,8 @@ static int watchdog_stop(struct fschmd_data *data)
682 data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED; 756 data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED;
683 /* Don't store the stop flag in our watchdog control register copy, as 757 /* Don't store the stop flag in our watchdog control register copy, as
684 its a write only bit (read always returns 0) */ 758 its a write only bit (read always returns 0) */
685 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, 759 i2c_smbus_write_byte_data(data->client,
760 FSCHMD_REG_WDOG_CONTROL[data->kind],
686 data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP); 761 data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP);
687leave: 762leave:
688 mutex_unlock(&data->watchdog_lock); 763 mutex_unlock(&data->watchdog_lock);
@@ -856,7 +931,7 @@ static struct file_operations watchdog_fops = {
856 931
857/* DMI decode routine to read voltage scaling factors from special DMI tables, 932/* DMI decode routine to read voltage scaling factors from special DMI tables,
858 which are available on FSC machines with an fscher or later chip. */ 933 which are available on FSC machines with an fscher or later chip. */
859static void fschmd_dmi_decode(const struct dmi_header *header) 934static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy)
860{ 935{
861 int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0; 936 int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0;
862 937
@@ -912,6 +987,15 @@ static void fschmd_dmi_decode(const struct dmi_header *header)
912 dmi_mult[i] = mult[i] * 10; 987 dmi_mult[i] = mult[i] * 10;
913 dmi_offset[i] = offset[i] * 10; 988 dmi_offset[i] = offset[i] * 10;
914 } 989 }
990 /* According to the docs there should be separate dmi entries
991 for the mult's and offsets of in3-5 of the syl, but on
992 my test machine these are not present */
993 dmi_mult[3] = dmi_mult[2];
994 dmi_mult[4] = dmi_mult[1];
995 dmi_mult[5] = dmi_mult[2];
996 dmi_offset[3] = dmi_offset[2];
997 dmi_offset[4] = dmi_offset[1];
998 dmi_offset[5] = dmi_offset[2];
915 dmi_vref = vref; 999 dmi_vref = vref;
916 } 1000 }
917} 1001}
@@ -920,8 +1004,6 @@ static int fschmd_detect(struct i2c_client *client, int kind,
920 struct i2c_board_info *info) 1004 struct i2c_board_info *info)
921{ 1005{
922 struct i2c_adapter *adapter = client->adapter; 1006 struct i2c_adapter *adapter = client->adapter;
923 const char * const client_names[5] = { "fscpos", "fscher", "fscscy",
924 "fschrc", "fschmd" };
925 1007
926 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 1008 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
927 return -ENODEV; 1009 return -ENODEV;
@@ -948,11 +1030,15 @@ static int fschmd_detect(struct i2c_client *client, int kind,
948 kind = fschrc; 1030 kind = fschrc;
949 else if (!strcmp(id, "HMD")) 1031 else if (!strcmp(id, "HMD"))
950 kind = fschmd; 1032 kind = fschmd;
1033 else if (!strcmp(id, "HDS"))
1034 kind = fschds;
1035 else if (!strcmp(id, "SYL"))
1036 kind = fscsyl;
951 else 1037 else
952 return -ENODEV; 1038 return -ENODEV;
953 } 1039 }
954 1040
955 strlcpy(info->type, client_names[kind - 1], I2C_NAME_SIZE); 1041 strlcpy(info->type, fschmd_id[kind - 1].name, I2C_NAME_SIZE);
956 1042
957 return 0; 1043 return 0;
958} 1044}
@@ -961,8 +1047,8 @@ static int fschmd_probe(struct i2c_client *client,
961 const struct i2c_device_id *id) 1047 const struct i2c_device_id *id)
962{ 1048{
963 struct fschmd_data *data; 1049 struct fschmd_data *data;
964 const char * const names[5] = { "Poseidon", "Hermes", "Scylla", 1050 const char * const names[7] = { "Poseidon", "Hermes", "Scylla",
965 "Heracles", "Heimdall" }; 1051 "Heracles", "Heimdall", "Hades", "Syleus" };
966 const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; 1052 const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
967 int i, err; 1053 int i, err;
968 enum chips kind = id->driver_data; 1054 enum chips kind = id->driver_data;
@@ -991,7 +1077,7 @@ static int fschmd_probe(struct i2c_client *client,
991 1077
992 /* Read the special DMI table for fscher and newer chips */ 1078 /* Read the special DMI table for fscher and newer chips */
993 if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) { 1079 if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) {
994 dmi_walk(fschmd_dmi_decode); 1080 dmi_walk(fschmd_dmi_decode, NULL);
995 if (dmi_vref == -1) { 1081 if (dmi_vref == -1) {
996 dev_warn(&client->dev, 1082 dev_warn(&client->dev,
997 "Couldn't get voltage scaling factors from " 1083 "Couldn't get voltage scaling factors from "
@@ -1000,21 +1086,25 @@ static int fschmd_probe(struct i2c_client *client,
1000 } 1086 }
1001 } 1087 }
1002 1088
1089 /* i2c kind goes from 1-6, we want from 0-5 to address arrays */
1090 data->kind = kind - 1;
1091
1003 /* Read in some never changing registers */ 1092 /* Read in some never changing registers */
1004 data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); 1093 data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
1005 data->global_control = i2c_smbus_read_byte_data(client, 1094 data->global_control = i2c_smbus_read_byte_data(client,
1006 FSCHMD_REG_CONTROL); 1095 FSCHMD_REG_CONTROL);
1007 data->watchdog_control = i2c_smbus_read_byte_data(client, 1096 data->watchdog_control = i2c_smbus_read_byte_data(client,
1008 FSCHMD_REG_WDOG_CONTROL); 1097 FSCHMD_REG_WDOG_CONTROL[data->kind]);
1009 data->watchdog_state = i2c_smbus_read_byte_data(client, 1098 data->watchdog_state = i2c_smbus_read_byte_data(client,
1010 FSCHMD_REG_WDOG_STATE); 1099 FSCHMD_REG_WDOG_STATE[data->kind]);
1011 data->watchdog_preset = i2c_smbus_read_byte_data(client, 1100 data->watchdog_preset = i2c_smbus_read_byte_data(client,
1012 FSCHMD_REG_WDOG_PRESET); 1101 FSCHMD_REG_WDOG_PRESET[data->kind]);
1013 1102
1014 /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ 1103 err = device_create_file(&client->dev, &dev_attr_alert_led);
1015 data->kind = kind - 1; 1104 if (err)
1105 goto exit_detach;
1016 1106
1017 for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { 1107 for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++) {
1018 err = device_create_file(&client->dev, 1108 err = device_create_file(&client->dev,
1019 &fschmd_attr[i].dev_attr); 1109 &fschmd_attr[i].dev_attr);
1020 if (err) 1110 if (err)
@@ -1027,6 +1117,16 @@ static int fschmd_probe(struct i2c_client *client,
1027 show_temp_max) 1117 show_temp_max)
1028 continue; 1118 continue;
1029 1119
1120 if (kind == fscsyl) {
1121 if (i % 4 == 0)
1122 data->temp_status[i / 4] =
1123 i2c_smbus_read_byte_data(client,
1124 FSCHMD_REG_TEMP_STATE
1125 [data->kind][i / 4]);
1126 if (data->temp_status[i / 4] & FSCHMD_TEMP_DISABLED)
1127 continue;
1128 }
1129
1030 err = device_create_file(&client->dev, 1130 err = device_create_file(&client->dev,
1031 &fschmd_temp_attr[i].dev_attr); 1131 &fschmd_temp_attr[i].dev_attr);
1032 if (err) 1132 if (err)
@@ -1040,6 +1140,16 @@ static int fschmd_probe(struct i2c_client *client,
1040 "pwm3_auto_point1_pwm")) 1140 "pwm3_auto_point1_pwm"))
1041 continue; 1141 continue;
1042 1142
1143 if (kind == fscsyl) {
1144 if (i % 5 == 0)
1145 data->fan_status[i / 5] =
1146 i2c_smbus_read_byte_data(client,
1147 FSCHMD_REG_FAN_STATE
1148 [data->kind][i / 5]);
1149 if (data->fan_status[i / 5] & FSCHMD_FAN_DISABLED)
1150 continue;
1151 }
1152
1043 err = device_create_file(&client->dev, 1153 err = device_create_file(&client->dev,
1044 &fschmd_fan_attr[i].dev_attr); 1154 &fschmd_fan_attr[i].dev_attr);
1045 if (err) 1155 if (err)
@@ -1126,7 +1236,8 @@ static int fschmd_remove(struct i2c_client *client)
1126 if (data->hwmon_dev) 1236 if (data->hwmon_dev)
1127 hwmon_device_unregister(data->hwmon_dev); 1237 hwmon_device_unregister(data->hwmon_dev);
1128 1238
1129 for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) 1239 device_remove_file(&client->dev, &dev_attr_alert_led);
1240 for (i = 0; i < (FSCHMD_NO_VOLT_SENSORS[data->kind]); i++)
1130 device_remove_file(&client->dev, &fschmd_attr[i].dev_attr); 1241 device_remove_file(&client->dev, &fschmd_attr[i].dev_attr);
1131 for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) 1242 for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++)
1132 device_remove_file(&client->dev, 1243 device_remove_file(&client->dev,
@@ -1171,7 +1282,7 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
1171 data->temp_act[i] < data->temp_max[i]) 1282 data->temp_act[i] < data->temp_max[i])
1172 i2c_smbus_write_byte_data(client, 1283 i2c_smbus_write_byte_data(client,
1173 FSCHMD_REG_TEMP_STATE[data->kind][i], 1284 FSCHMD_REG_TEMP_STATE[data->kind][i],
1174 FSCHMD_TEMP_ALERT); 1285 data->temp_status[i]);
1175 } 1286 }
1176 1287
1177 for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { 1288 for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) {
@@ -1193,12 +1304,12 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
1193 data->fan_act[i]) 1304 data->fan_act[i])
1194 i2c_smbus_write_byte_data(client, 1305 i2c_smbus_write_byte_data(client,
1195 FSCHMD_REG_FAN_STATE[data->kind][i], 1306 FSCHMD_REG_FAN_STATE[data->kind][i],
1196 FSCHMD_FAN_ALARM); 1307 data->fan_status[i]);
1197 } 1308 }
1198 1309
1199 for (i = 0; i < 3; i++) 1310 for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++)
1200 data->volt[i] = i2c_smbus_read_byte_data(client, 1311 data->volt[i] = i2c_smbus_read_byte_data(client,
1201 FSCHMD_REG_VOLT[i]); 1312 FSCHMD_REG_VOLT[data->kind][i]);
1202 1313
1203 data->last_updated = jiffies; 1314 data->last_updated = jiffies;
1204 data->valid = 1; 1315 data->valid = 1;
@@ -1220,8 +1331,8 @@ static void __exit fschmd_exit(void)
1220} 1331}
1221 1332
1222MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 1333MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
1223MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and " 1334MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles, Heimdall, Hades "
1224 "Heimdall driver"); 1335 "and Syleus driver");
1225MODULE_LICENSE("GPL"); 1336MODULE_LICENSE("GPL");
1226 1337
1227module_init(fschmd_init); 1338module_init(fschmd_init);