diff options
Diffstat (limited to 'drivers/hwmon/fschmd.c')
-rw-r--r-- | drivers/hwmon/fschmd.c | 229 |
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; | |||
56 | module_param(nowayout, int, 0); | 56 | module_param(nowayout, int, 0); |
57 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | 57 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
58 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 58 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
59 | I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); | 59 | I2C_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 | 78 | static 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 | 80 | static const u8 FSCHMD_REG_WDOG_STATE[7] = |
81 | { 0x23, 0x23, 0x23, 0x23, 0x23, 0x29, 0x29 }; | ||
82 | static 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 */ |
90 | static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 }; | 93 | static 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 | |||
103 | static 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. */ |
96 | static const u8 FSCHMD_REG_FAN_MIN[5][6] = { | 109 | static 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 */ |
105 | static const u8 FSCHMD_REG_FAN_ACT[5][6] = { | 120 | static 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 */ |
114 | static const u8 FSCHMD_REG_FAN_STATE[5][6] = { | 131 | static 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 */ |
123 | static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = { | 142 | static 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 | ||
131 | static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 }; | 152 | static 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 */ |
139 | static const u8 FSCHMD_REG_TEMP_ACT[5][5] = { | 161 | static 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 */ |
148 | static const u8 FSCHMD_REG_TEMP_STATE[5][5] = { | 173 | static 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?? */ |
161 | static const u8 FSCHMD_REG_TEMP_LIMIT[5][5] = { | 189 | static 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. | ||
171 | static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 }; | 205 | static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 }; |
172 | static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */ | 206 | static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */ |
173 | 207 | ||
174 | static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; | 208 | static 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 | }; |
206 | MODULE_DEVICE_TABLE(i2c, fschmd_id); | 243 | MODULE_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. */ |
260 | static int dmi_mult[3] = { 490, 200, 100 }; | 297 | static int dmi_mult[6] = { 490, 200, 100, 100, 200, 100 }; |
261 | static int dmi_offset[3] = { 0, 0, 0 }; | 298 | static int dmi_offset[6] = { 0, 0, 0, 0, 0, 0 }; |
262 | static int dmi_vref = -1; | 299 | static 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 | ||
563 | static DEVICE_ATTR(alert_led, 0644, show_alert_led, store_alert_led); | ||
564 | |||
525 | static struct sensor_device_attribute fschmd_attr[] = { | 565 | static 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 | ||
532 | static struct sensor_device_attribute fschmd_temp_attr[] = { | 574 | static 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 | ||
555 | static struct sensor_device_attribute fschmd_fan_attr[] = { | 621 | static 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); | ||
667 | leave: | 741 | leave: |
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); |
687 | leave: | 762 | leave: |
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. */ |
859 | static void fschmd_dmi_decode(const struct dmi_header *header) | 934 | static 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 | ||
1222 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | 1333 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); |
1223 | MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and " | 1334 | MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles, Heimdall, Hades " |
1224 | "Heimdall driver"); | 1335 | "and Syleus driver"); |
1225 | MODULE_LICENSE("GPL"); | 1336 | MODULE_LICENSE("GPL"); |
1226 | 1337 | ||
1227 | module_init(fschmd_init); | 1338 | module_init(fschmd_init); |