diff options
Diffstat (limited to 'drivers/i2c/chips/adm1026.c')
-rw-r--r-- | drivers/i2c/chips/adm1026.c | 1754 |
1 files changed, 1754 insertions, 0 deletions
diff --git a/drivers/i2c/chips/adm1026.c b/drivers/i2c/chips/adm1026.c new file mode 100644 index 000000000000..39e2f4a900bf --- /dev/null +++ b/drivers/i2c/chips/adm1026.c | |||
@@ -0,0 +1,1754 @@ | |||
1 | /* | ||
2 | adm1026.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (C) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com> | ||
5 | Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com> | ||
6 | |||
7 | Chip details at: | ||
8 | |||
9 | <http://www.analog.com/UploadedFiles/Data_Sheets/779263102ADM1026_a.pdf> | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/jiffies.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/i2c-sensor.h> | ||
33 | #include <linux/i2c-vid.h> | ||
34 | |||
35 | /* Addresses to scan */ | ||
36 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | ||
37 | static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; | ||
38 | |||
39 | /* Insmod parameters */ | ||
40 | SENSORS_INSMOD_1(adm1026); | ||
41 | |||
42 | static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
43 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
44 | static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
45 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
46 | static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
47 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
48 | static int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
49 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
50 | static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
51 | module_param_array(gpio_input,int,NULL,0); | ||
52 | MODULE_PARM_DESC(gpio_input,"List of GPIO pins (0-16) to program as inputs"); | ||
53 | module_param_array(gpio_output,int,NULL,0); | ||
54 | MODULE_PARM_DESC(gpio_output,"List of GPIO pins (0-16) to program as " | ||
55 | "outputs"); | ||
56 | module_param_array(gpio_inverted,int,NULL,0); | ||
57 | MODULE_PARM_DESC(gpio_inverted,"List of GPIO pins (0-16) to program as " | ||
58 | "inverted"); | ||
59 | module_param_array(gpio_normal,int,NULL,0); | ||
60 | MODULE_PARM_DESC(gpio_normal,"List of GPIO pins (0-16) to program as " | ||
61 | "normal/non-inverted"); | ||
62 | module_param_array(gpio_fan,int,NULL,0); | ||
63 | MODULE_PARM_DESC(gpio_fan,"List of GPIO pins (0-7) to program as fan tachs"); | ||
64 | |||
65 | /* Many ADM1026 constants specified below */ | ||
66 | |||
67 | /* The ADM1026 registers */ | ||
68 | #define ADM1026_REG_CONFIG1 0x00 | ||
69 | #define CFG1_MONITOR 0x01 | ||
70 | #define CFG1_INT_ENABLE 0x02 | ||
71 | #define CFG1_INT_CLEAR 0x04 | ||
72 | #define CFG1_AIN8_9 0x08 | ||
73 | #define CFG1_THERM_HOT 0x10 | ||
74 | #define CFG1_DAC_AFC 0x20 | ||
75 | #define CFG1_PWM_AFC 0x40 | ||
76 | #define CFG1_RESET 0x80 | ||
77 | #define ADM1026_REG_CONFIG2 0x01 | ||
78 | /* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */ | ||
79 | #define ADM1026_REG_CONFIG3 0x07 | ||
80 | #define CFG3_GPIO16_ENABLE 0x01 | ||
81 | #define CFG3_CI_CLEAR 0x02 | ||
82 | #define CFG3_VREF_250 0x04 | ||
83 | #define CFG3_GPIO16_DIR 0x40 | ||
84 | #define CFG3_GPIO16_POL 0x80 | ||
85 | #define ADM1026_REG_E2CONFIG 0x13 | ||
86 | #define E2CFG_READ 0x01 | ||
87 | #define E2CFG_WRITE 0x02 | ||
88 | #define E2CFG_ERASE 0x04 | ||
89 | #define E2CFG_ROM 0x08 | ||
90 | #define E2CFG_CLK_EXT 0x80 | ||
91 | |||
92 | /* There are 10 general analog inputs and 7 dedicated inputs | ||
93 | * They are: | ||
94 | * 0 - 9 = AIN0 - AIN9 | ||
95 | * 10 = Vbat | ||
96 | * 11 = 3.3V Standby | ||
97 | * 12 = 3.3V Main | ||
98 | * 13 = +5V | ||
99 | * 14 = Vccp (CPU core voltage) | ||
100 | * 15 = +12V | ||
101 | * 16 = -12V | ||
102 | */ | ||
103 | static u16 ADM1026_REG_IN[] = { | ||
104 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, | ||
105 | 0x36, 0x37, 0x27, 0x29, 0x26, 0x2a, | ||
106 | 0x2b, 0x2c, 0x2d, 0x2e, 0x2f | ||
107 | }; | ||
108 | static u16 ADM1026_REG_IN_MIN[] = { | ||
109 | 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, | ||
110 | 0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a, | ||
111 | 0x4b, 0x4c, 0x4d, 0x4e, 0x4f | ||
112 | }; | ||
113 | static u16 ADM1026_REG_IN_MAX[] = { | ||
114 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, | ||
115 | 0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42, | ||
116 | 0x43, 0x44, 0x45, 0x46, 0x47 | ||
117 | }; | ||
118 | |||
119 | /* Temperatures are: | ||
120 | * 0 - Internal | ||
121 | * 1 - External 1 | ||
122 | * 2 - External 2 | ||
123 | */ | ||
124 | static u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 }; | ||
125 | static u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 }; | ||
126 | static u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 }; | ||
127 | static u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 }; | ||
128 | static u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f }; | ||
129 | static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f }; | ||
130 | |||
131 | #define ADM1026_REG_FAN(nr) (0x38 + (nr)) | ||
132 | #define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr)) | ||
133 | #define ADM1026_REG_FAN_DIV_0_3 0x02 | ||
134 | #define ADM1026_REG_FAN_DIV_4_7 0x03 | ||
135 | |||
136 | #define ADM1026_REG_DAC 0x04 | ||
137 | #define ADM1026_REG_PWM 0x05 | ||
138 | |||
139 | #define ADM1026_REG_GPIO_CFG_0_3 0x08 | ||
140 | #define ADM1026_REG_GPIO_CFG_4_7 0x09 | ||
141 | #define ADM1026_REG_GPIO_CFG_8_11 0x0a | ||
142 | #define ADM1026_REG_GPIO_CFG_12_15 0x0b | ||
143 | /* CFG_16 in REG_CFG3 */ | ||
144 | #define ADM1026_REG_GPIO_STATUS_0_7 0x24 | ||
145 | #define ADM1026_REG_GPIO_STATUS_8_15 0x25 | ||
146 | /* STATUS_16 in REG_STATUS4 */ | ||
147 | #define ADM1026_REG_GPIO_MASK_0_7 0x1c | ||
148 | #define ADM1026_REG_GPIO_MASK_8_15 0x1d | ||
149 | /* MASK_16 in REG_MASK4 */ | ||
150 | |||
151 | #define ADM1026_REG_COMPANY 0x16 | ||
152 | #define ADM1026_REG_VERSTEP 0x17 | ||
153 | /* These are the recognized values for the above regs */ | ||
154 | #define ADM1026_COMPANY_ANALOG_DEV 0x41 | ||
155 | #define ADM1026_VERSTEP_GENERIC 0x40 | ||
156 | #define ADM1026_VERSTEP_ADM1026 0x44 | ||
157 | |||
158 | #define ADM1026_REG_MASK1 0x18 | ||
159 | #define ADM1026_REG_MASK2 0x19 | ||
160 | #define ADM1026_REG_MASK3 0x1a | ||
161 | #define ADM1026_REG_MASK4 0x1b | ||
162 | |||
163 | #define ADM1026_REG_STATUS1 0x20 | ||
164 | #define ADM1026_REG_STATUS2 0x21 | ||
165 | #define ADM1026_REG_STATUS3 0x22 | ||
166 | #define ADM1026_REG_STATUS4 0x23 | ||
167 | |||
168 | #define ADM1026_FAN_ACTIVATION_TEMP_HYST -6 | ||
169 | #define ADM1026_FAN_CONTROL_TEMP_RANGE 20 | ||
170 | #define ADM1026_PWM_MAX 255 | ||
171 | |||
172 | /* Conversions. Rounding and limit checking is only done on the TO_REG | ||
173 | * variants. Note that you should be a bit careful with which arguments | ||
174 | * these macros are called: arguments may be evaluated more than once. | ||
175 | */ | ||
176 | |||
177 | /* IN are scaled acording to built-in resistors. These are the | ||
178 | * voltages corresponding to 3/4 of full scale (192 or 0xc0) | ||
179 | * NOTE: The -12V input needs an additional factor to account | ||
180 | * for the Vref pullup resistor. | ||
181 | * NEG12_OFFSET = SCALE * Vref / V-192 - Vref | ||
182 | * = 13875 * 2.50 / 1.875 - 2500 | ||
183 | * = 16000 | ||
184 | * | ||
185 | * The values in this table are based on Table II, page 15 of the | ||
186 | * datasheet. | ||
187 | */ | ||
188 | static int adm1026_scaling[] = { /* .001 Volts */ | ||
189 | 2250, 2250, 2250, 2250, 2250, 2250, | ||
190 | 1875, 1875, 1875, 1875, 3000, 3330, | ||
191 | 3330, 4995, 2250, 12000, 13875 | ||
192 | }; | ||
193 | #define NEG12_OFFSET 16000 | ||
194 | #define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from)) | ||
195 | #define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,adm1026_scaling[n],192),\ | ||
196 | 0,255)) | ||
197 | #define INS_FROM_REG(n,val) (SCALE(val,192,adm1026_scaling[n])) | ||
198 | |||
199 | /* FAN speed is measured using 22.5kHz clock and counts for 2 pulses | ||
200 | * and we assume a 2 pulse-per-rev fan tach signal | ||
201 | * 22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000 | ||
202 | */ | ||
203 | #define FAN_TO_REG(val,div) ((val)<=0 ? 0xff : SENSORS_LIMIT(1350000/((val)*\ | ||
204 | (div)),1,254)) | ||
205 | #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==0xff ? 0 : 1350000/((val)*\ | ||
206 | (div))) | ||
207 | #define DIV_FROM_REG(val) (1<<(val)) | ||
208 | #define DIV_TO_REG(val) ((val)>=8 ? 3 : (val)>=4 ? 2 : (val)>=2 ? 1 : 0) | ||
209 | |||
210 | /* Temperature is reported in 1 degC increments */ | ||
211 | #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ | ||
212 | -127,127)) | ||
213 | #define TEMP_FROM_REG(val) ((val) * 1000) | ||
214 | #define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\ | ||
215 | -127,127)) | ||
216 | #define OFFSET_FROM_REG(val) ((val) * 1000) | ||
217 | |||
218 | #define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255)) | ||
219 | #define PWM_FROM_REG(val) (val) | ||
220 | |||
221 | #define PWM_MIN_TO_REG(val) ((val) & 0xf0) | ||
222 | #define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4)) | ||
223 | |||
224 | /* Analog output is a voltage, and scaled to millivolts. The datasheet | ||
225 | * indicates that the DAC could be used to drive the fans, but in our | ||
226 | * example board (Arima HDAMA) it isn't connected to the fans at all. | ||
227 | */ | ||
228 | #define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500),0,255)) | ||
229 | #define DAC_FROM_REG(val) (((val)*2500)/255) | ||
230 | |||
231 | /* Typically used with systems using a v9.1 VRM spec ? */ | ||
232 | #define ADM1026_INIT_VRM 91 | ||
233 | |||
234 | /* Chip sampling rates | ||
235 | * | ||
236 | * Some sensors are not updated more frequently than once per second | ||
237 | * so it doesn't make sense to read them more often than that. | ||
238 | * We cache the results and return the saved data if the driver | ||
239 | * is called again before a second has elapsed. | ||
240 | * | ||
241 | * Also, there is significant configuration data for this chip | ||
242 | * So, we keep the config data up to date in the cache | ||
243 | * when it is written and only sample it once every 5 *minutes* | ||
244 | */ | ||
245 | #define ADM1026_DATA_INTERVAL (1 * HZ) | ||
246 | #define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ) | ||
247 | |||
248 | /* We allow for multiple chips in a single system. | ||
249 | * | ||
250 | * For each registered ADM1026, we need to keep state information | ||
251 | * at client->data. The adm1026_data structure is dynamically | ||
252 | * allocated, when a new client structure is allocated. */ | ||
253 | |||
254 | struct pwm_data { | ||
255 | u8 pwm; | ||
256 | u8 enable; | ||
257 | u8 auto_pwm_min; | ||
258 | }; | ||
259 | |||
260 | struct adm1026_data { | ||
261 | struct i2c_client client; | ||
262 | struct semaphore lock; | ||
263 | enum chips type; | ||
264 | |||
265 | struct semaphore update_lock; | ||
266 | int valid; /* !=0 if following fields are valid */ | ||
267 | unsigned long last_reading; /* In jiffies */ | ||
268 | unsigned long last_config; /* In jiffies */ | ||
269 | |||
270 | u8 in[17]; /* Register value */ | ||
271 | u8 in_max[17]; /* Register value */ | ||
272 | u8 in_min[17]; /* Register value */ | ||
273 | s8 temp[3]; /* Register value */ | ||
274 | s8 temp_min[3]; /* Register value */ | ||
275 | s8 temp_max[3]; /* Register value */ | ||
276 | s8 temp_tmin[3]; /* Register value */ | ||
277 | s8 temp_crit[3]; /* Register value */ | ||
278 | s8 temp_offset[3]; /* Register value */ | ||
279 | u8 fan[8]; /* Register value */ | ||
280 | u8 fan_min[8]; /* Register value */ | ||
281 | u8 fan_div[8]; /* Decoded value */ | ||
282 | struct pwm_data pwm1; /* Pwm control values */ | ||
283 | int vid; /* Decoded value */ | ||
284 | u8 vrm; /* VRM version */ | ||
285 | u8 analog_out; /* Register value (DAC) */ | ||
286 | long alarms; /* Register encoding, combined */ | ||
287 | long alarm_mask; /* Register encoding, combined */ | ||
288 | long gpio; /* Register encoding, combined */ | ||
289 | long gpio_mask; /* Register encoding, combined */ | ||
290 | u8 gpio_config[17]; /* Decoded value */ | ||
291 | u8 config1; /* Register value */ | ||
292 | u8 config2; /* Register value */ | ||
293 | u8 config3; /* Register value */ | ||
294 | }; | ||
295 | |||
296 | static int adm1026_attach_adapter(struct i2c_adapter *adapter); | ||
297 | static int adm1026_detect(struct i2c_adapter *adapter, int address, | ||
298 | int kind); | ||
299 | static int adm1026_detach_client(struct i2c_client *client); | ||
300 | static int adm1026_read_value(struct i2c_client *client, u8 register); | ||
301 | static int adm1026_write_value(struct i2c_client *client, u8 register, | ||
302 | int value); | ||
303 | static void adm1026_print_gpio(struct i2c_client *client); | ||
304 | static void adm1026_fixup_gpio(struct i2c_client *client); | ||
305 | static struct adm1026_data *adm1026_update_device(struct device *dev); | ||
306 | static void adm1026_init_client(struct i2c_client *client); | ||
307 | |||
308 | |||
309 | static struct i2c_driver adm1026_driver = { | ||
310 | .owner = THIS_MODULE, | ||
311 | .name = "adm1026", | ||
312 | .flags = I2C_DF_NOTIFY, | ||
313 | .attach_adapter = adm1026_attach_adapter, | ||
314 | .detach_client = adm1026_detach_client, | ||
315 | }; | ||
316 | |||
317 | int adm1026_attach_adapter(struct i2c_adapter *adapter) | ||
318 | { | ||
319 | if (!(adapter->class & I2C_CLASS_HWMON)) { | ||
320 | return 0; | ||
321 | } | ||
322 | return i2c_detect(adapter, &addr_data, adm1026_detect); | ||
323 | } | ||
324 | |||
325 | int adm1026_detach_client(struct i2c_client *client) | ||
326 | { | ||
327 | i2c_detach_client(client); | ||
328 | kfree(client); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | int adm1026_read_value(struct i2c_client *client, u8 reg) | ||
333 | { | ||
334 | int res; | ||
335 | |||
336 | if (reg < 0x80) { | ||
337 | /* "RAM" locations */ | ||
338 | res = i2c_smbus_read_byte_data(client, reg) & 0xff; | ||
339 | } else { | ||
340 | /* EEPROM, do nothing */ | ||
341 | res = 0; | ||
342 | } | ||
343 | return res; | ||
344 | } | ||
345 | |||
346 | int adm1026_write_value(struct i2c_client *client, u8 reg, int value) | ||
347 | { | ||
348 | int res; | ||
349 | |||
350 | if (reg < 0x80) { | ||
351 | /* "RAM" locations */ | ||
352 | res = i2c_smbus_write_byte_data(client, reg, value); | ||
353 | } else { | ||
354 | /* EEPROM, do nothing */ | ||
355 | res = 0; | ||
356 | } | ||
357 | return res; | ||
358 | } | ||
359 | |||
360 | void adm1026_init_client(struct i2c_client *client) | ||
361 | { | ||
362 | int value, i; | ||
363 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
364 | |||
365 | dev_dbg(&client->dev, "Initializing device\n"); | ||
366 | /* Read chip config */ | ||
367 | data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); | ||
368 | data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); | ||
369 | data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); | ||
370 | |||
371 | /* Inform user of chip config */ | ||
372 | dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n", | ||
373 | data->config1); | ||
374 | if ((data->config1 & CFG1_MONITOR) == 0) { | ||
375 | dev_dbg(&client->dev, "Monitoring not currently " | ||
376 | "enabled.\n"); | ||
377 | } | ||
378 | if (data->config1 & CFG1_INT_ENABLE) { | ||
379 | dev_dbg(&client->dev, "SMBALERT interrupts are " | ||
380 | "enabled.\n"); | ||
381 | } | ||
382 | if (data->config1 & CFG1_AIN8_9) { | ||
383 | dev_dbg(&client->dev, "in8 and in9 enabled. " | ||
384 | "temp3 disabled.\n"); | ||
385 | } else { | ||
386 | dev_dbg(&client->dev, "temp3 enabled. in8 and " | ||
387 | "in9 disabled.\n"); | ||
388 | } | ||
389 | if (data->config1 & CFG1_THERM_HOT) { | ||
390 | dev_dbg(&client->dev, "Automatic THERM, PWM, " | ||
391 | "and temp limits enabled.\n"); | ||
392 | } | ||
393 | |||
394 | value = data->config3; | ||
395 | if (data->config3 & CFG3_GPIO16_ENABLE) { | ||
396 | dev_dbg(&client->dev, "GPIO16 enabled. THERM" | ||
397 | "pin disabled.\n"); | ||
398 | } else { | ||
399 | dev_dbg(&client->dev, "THERM pin enabled. " | ||
400 | "GPIO16 disabled.\n"); | ||
401 | } | ||
402 | if (data->config3 & CFG3_VREF_250) { | ||
403 | dev_dbg(&client->dev, "Vref is 2.50 Volts.\n"); | ||
404 | } else { | ||
405 | dev_dbg(&client->dev, "Vref is 1.82 Volts.\n"); | ||
406 | } | ||
407 | /* Read and pick apart the existing GPIO configuration */ | ||
408 | value = 0; | ||
409 | for (i = 0;i <= 15;++i) { | ||
410 | if ((i & 0x03) == 0) { | ||
411 | value = adm1026_read_value(client, | ||
412 | ADM1026_REG_GPIO_CFG_0_3 + i/4); | ||
413 | } | ||
414 | data->gpio_config[i] = value & 0x03; | ||
415 | value >>= 2; | ||
416 | } | ||
417 | data->gpio_config[16] = (data->config3 >> 6) & 0x03; | ||
418 | |||
419 | /* ... and then print it */ | ||
420 | adm1026_print_gpio(client); | ||
421 | |||
422 | /* If the user asks us to reprogram the GPIO config, then | ||
423 | * do it now. | ||
424 | */ | ||
425 | if (gpio_input[0] != -1 || gpio_output[0] != -1 | ||
426 | || gpio_inverted[0] != -1 || gpio_normal[0] != -1 | ||
427 | || gpio_fan[0] != -1) { | ||
428 | adm1026_fixup_gpio(client); | ||
429 | } | ||
430 | |||
431 | /* WE INTENTIONALLY make no changes to the limits, | ||
432 | * offsets, pwms, fans and zones. If they were | ||
433 | * configured, we don't want to mess with them. | ||
434 | * If they weren't, the default is 100% PWM, no | ||
435 | * control and will suffice until 'sensors -s' | ||
436 | * can be run by the user. We DO set the default | ||
437 | * value for pwm1.auto_pwm_min to its maximum | ||
438 | * so that enabling automatic pwm fan control | ||
439 | * without first setting a value for pwm1.auto_pwm_min | ||
440 | * will not result in potentially dangerous fan speed decrease. | ||
441 | */ | ||
442 | data->pwm1.auto_pwm_min=255; | ||
443 | /* Start monitoring */ | ||
444 | value = adm1026_read_value(client, ADM1026_REG_CONFIG1); | ||
445 | /* Set MONITOR, clear interrupt acknowledge and s/w reset */ | ||
446 | value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET); | ||
447 | dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value); | ||
448 | data->config1 = value; | ||
449 | adm1026_write_value(client, ADM1026_REG_CONFIG1, value); | ||
450 | |||
451 | /* initialize fan_div[] to hardware defaults */ | ||
452 | value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | | ||
453 | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); | ||
454 | for (i = 0;i <= 7;++i) { | ||
455 | data->fan_div[i] = DIV_FROM_REG(value & 0x03); | ||
456 | value >>= 2; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | void adm1026_print_gpio(struct i2c_client *client) | ||
461 | { | ||
462 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
463 | int i; | ||
464 | |||
465 | dev_dbg(&client->dev, "GPIO config is:"); | ||
466 | for (i = 0;i <= 7;++i) { | ||
467 | if (data->config2 & (1 << i)) { | ||
468 | dev_dbg(&client->dev, "\t%sGP%s%d\n", | ||
469 | data->gpio_config[i] & 0x02 ? "" : "!", | ||
470 | data->gpio_config[i] & 0x01 ? "OUT" : "IN", | ||
471 | i); | ||
472 | } else { | ||
473 | dev_dbg(&client->dev, "\tFAN%d\n", i); | ||
474 | } | ||
475 | } | ||
476 | for (i = 8;i <= 15;++i) { | ||
477 | dev_dbg(&client->dev, "\t%sGP%s%d\n", | ||
478 | data->gpio_config[i] & 0x02 ? "" : "!", | ||
479 | data->gpio_config[i] & 0x01 ? "OUT" : "IN", | ||
480 | i); | ||
481 | } | ||
482 | if (data->config3 & CFG3_GPIO16_ENABLE) { | ||
483 | dev_dbg(&client->dev, "\t%sGP%s16\n", | ||
484 | data->gpio_config[16] & 0x02 ? "" : "!", | ||
485 | data->gpio_config[16] & 0x01 ? "OUT" : "IN"); | ||
486 | } else { | ||
487 | /* GPIO16 is THERM */ | ||
488 | dev_dbg(&client->dev, "\tTHERM\n"); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | void adm1026_fixup_gpio(struct i2c_client *client) | ||
493 | { | ||
494 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
495 | int i; | ||
496 | int value; | ||
497 | |||
498 | /* Make the changes requested. */ | ||
499 | /* We may need to unlock/stop monitoring or soft-reset the | ||
500 | * chip before we can make changes. This hasn't been | ||
501 | * tested much. FIXME | ||
502 | */ | ||
503 | |||
504 | /* Make outputs */ | ||
505 | for (i = 0;i <= 16;++i) { | ||
506 | if (gpio_output[i] >= 0 && gpio_output[i] <= 16) { | ||
507 | data->gpio_config[gpio_output[i]] |= 0x01; | ||
508 | } | ||
509 | /* if GPIO0-7 is output, it isn't a FAN tach */ | ||
510 | if (gpio_output[i] >= 0 && gpio_output[i] <= 7) { | ||
511 | data->config2 |= 1 << gpio_output[i]; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | /* Input overrides output */ | ||
516 | for (i = 0;i <= 16;++i) { | ||
517 | if (gpio_input[i] >= 0 && gpio_input[i] <= 16) { | ||
518 | data->gpio_config[gpio_input[i]] &= ~ 0x01; | ||
519 | } | ||
520 | /* if GPIO0-7 is input, it isn't a FAN tach */ | ||
521 | if (gpio_input[i] >= 0 && gpio_input[i] <= 7) { | ||
522 | data->config2 |= 1 << gpio_input[i]; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | /* Inverted */ | ||
527 | for (i = 0;i <= 16;++i) { | ||
528 | if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) { | ||
529 | data->gpio_config[gpio_inverted[i]] &= ~ 0x02; | ||
530 | } | ||
531 | } | ||
532 | |||
533 | /* Normal overrides inverted */ | ||
534 | for (i = 0;i <= 16;++i) { | ||
535 | if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) { | ||
536 | data->gpio_config[gpio_normal[i]] |= 0x02; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | /* Fan overrides input and output */ | ||
541 | for (i = 0;i <= 7;++i) { | ||
542 | if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) { | ||
543 | data->config2 &= ~(1 << gpio_fan[i]); | ||
544 | } | ||
545 | } | ||
546 | |||
547 | /* Write new configs to registers */ | ||
548 | adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2); | ||
549 | data->config3 = (data->config3 & 0x3f) | ||
550 | | ((data->gpio_config[16] & 0x03) << 6); | ||
551 | adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3); | ||
552 | for (i = 15, value = 0;i >= 0;--i) { | ||
553 | value <<= 2; | ||
554 | value |= data->gpio_config[i] & 0x03; | ||
555 | if ((i & 0x03) == 0) { | ||
556 | adm1026_write_value(client, | ||
557 | ADM1026_REG_GPIO_CFG_0_3 + i/4, | ||
558 | value); | ||
559 | value = 0; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /* Print the new config */ | ||
564 | adm1026_print_gpio(client); | ||
565 | } | ||
566 | |||
567 | |||
568 | static struct adm1026_data *adm1026_update_device(struct device *dev) | ||
569 | { | ||
570 | struct i2c_client *client = to_i2c_client(dev); | ||
571 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
572 | int i; | ||
573 | long value, alarms, gpio; | ||
574 | |||
575 | down(&data->update_lock); | ||
576 | if (!data->valid | ||
577 | || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { | ||
578 | /* Things that change quickly */ | ||
579 | dev_dbg(&client->dev,"Reading sensor values\n"); | ||
580 | for (i = 0;i <= 16;++i) { | ||
581 | data->in[i] = | ||
582 | adm1026_read_value(client, ADM1026_REG_IN[i]); | ||
583 | } | ||
584 | |||
585 | for (i = 0;i <= 7;++i) { | ||
586 | data->fan[i] = | ||
587 | adm1026_read_value(client, ADM1026_REG_FAN(i)); | ||
588 | } | ||
589 | |||
590 | for (i = 0;i <= 2;++i) { | ||
591 | /* NOTE: temp[] is s8 and we assume 2's complement | ||
592 | * "conversion" in the assignment */ | ||
593 | data->temp[i] = | ||
594 | adm1026_read_value(client, ADM1026_REG_TEMP[i]); | ||
595 | } | ||
596 | |||
597 | data->pwm1.pwm = adm1026_read_value(client, | ||
598 | ADM1026_REG_PWM); | ||
599 | data->analog_out = adm1026_read_value(client, | ||
600 | ADM1026_REG_DAC); | ||
601 | /* GPIO16 is MSbit of alarms, move it to gpio */ | ||
602 | alarms = adm1026_read_value(client, ADM1026_REG_STATUS4); | ||
603 | gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ | ||
604 | alarms &= 0x7f; | ||
605 | alarms <<= 8; | ||
606 | alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3); | ||
607 | alarms <<= 8; | ||
608 | alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2); | ||
609 | alarms <<= 8; | ||
610 | alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1); | ||
611 | data->alarms = alarms; | ||
612 | |||
613 | /* Read the GPIO values */ | ||
614 | gpio |= adm1026_read_value(client, | ||
615 | ADM1026_REG_GPIO_STATUS_8_15); | ||
616 | gpio <<= 8; | ||
617 | gpio |= adm1026_read_value(client, | ||
618 | ADM1026_REG_GPIO_STATUS_0_7); | ||
619 | data->gpio = gpio; | ||
620 | |||
621 | data->last_reading = jiffies; | ||
622 | }; /* last_reading */ | ||
623 | |||
624 | if (!data->valid || | ||
625 | time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) { | ||
626 | /* Things that don't change often */ | ||
627 | dev_dbg(&client->dev, "Reading config values\n"); | ||
628 | for (i = 0;i <= 16;++i) { | ||
629 | data->in_min[i] = adm1026_read_value(client, | ||
630 | ADM1026_REG_IN_MIN[i]); | ||
631 | data->in_max[i] = adm1026_read_value(client, | ||
632 | ADM1026_REG_IN_MAX[i]); | ||
633 | } | ||
634 | |||
635 | value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | ||
636 | | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) | ||
637 | << 8); | ||
638 | for (i = 0;i <= 7;++i) { | ||
639 | data->fan_min[i] = adm1026_read_value(client, | ||
640 | ADM1026_REG_FAN_MIN(i)); | ||
641 | data->fan_div[i] = DIV_FROM_REG(value & 0x03); | ||
642 | value >>= 2; | ||
643 | } | ||
644 | |||
645 | for (i = 0; i <= 2; ++i) { | ||
646 | /* NOTE: temp_xxx[] are s8 and we assume 2's | ||
647 | * complement "conversion" in the assignment | ||
648 | */ | ||
649 | data->temp_min[i] = adm1026_read_value(client, | ||
650 | ADM1026_REG_TEMP_MIN[i]); | ||
651 | data->temp_max[i] = adm1026_read_value(client, | ||
652 | ADM1026_REG_TEMP_MAX[i]); | ||
653 | data->temp_tmin[i] = adm1026_read_value(client, | ||
654 | ADM1026_REG_TEMP_TMIN[i]); | ||
655 | data->temp_crit[i] = adm1026_read_value(client, | ||
656 | ADM1026_REG_TEMP_THERM[i]); | ||
657 | data->temp_offset[i] = adm1026_read_value(client, | ||
658 | ADM1026_REG_TEMP_OFFSET[i]); | ||
659 | } | ||
660 | |||
661 | /* Read the STATUS/alarm masks */ | ||
662 | alarms = adm1026_read_value(client, ADM1026_REG_MASK4); | ||
663 | gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ | ||
664 | alarms = (alarms & 0x7f) << 8; | ||
665 | alarms |= adm1026_read_value(client, ADM1026_REG_MASK3); | ||
666 | alarms <<= 8; | ||
667 | alarms |= adm1026_read_value(client, ADM1026_REG_MASK2); | ||
668 | alarms <<= 8; | ||
669 | alarms |= adm1026_read_value(client, ADM1026_REG_MASK1); | ||
670 | data->alarm_mask = alarms; | ||
671 | |||
672 | /* Read the GPIO values */ | ||
673 | gpio |= adm1026_read_value(client, | ||
674 | ADM1026_REG_GPIO_MASK_8_15); | ||
675 | gpio <<= 8; | ||
676 | gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7); | ||
677 | data->gpio_mask = gpio; | ||
678 | |||
679 | /* Read various values from CONFIG1 */ | ||
680 | data->config1 = adm1026_read_value(client, | ||
681 | ADM1026_REG_CONFIG1); | ||
682 | if (data->config1 & CFG1_PWM_AFC) { | ||
683 | data->pwm1.enable = 2; | ||
684 | data->pwm1.auto_pwm_min = | ||
685 | PWM_MIN_FROM_REG(data->pwm1.pwm); | ||
686 | } | ||
687 | /* Read the GPIO config */ | ||
688 | data->config2 = adm1026_read_value(client, | ||
689 | ADM1026_REG_CONFIG2); | ||
690 | data->config3 = adm1026_read_value(client, | ||
691 | ADM1026_REG_CONFIG3); | ||
692 | data->gpio_config[16] = (data->config3 >> 6) & 0x03; | ||
693 | |||
694 | value = 0; | ||
695 | for (i = 0;i <= 15;++i) { | ||
696 | if ((i & 0x03) == 0) { | ||
697 | value = adm1026_read_value(client, | ||
698 | ADM1026_REG_GPIO_CFG_0_3 + i/4); | ||
699 | } | ||
700 | data->gpio_config[i] = value & 0x03; | ||
701 | value >>= 2; | ||
702 | } | ||
703 | |||
704 | data->last_config = jiffies; | ||
705 | }; /* last_config */ | ||
706 | |||
707 | dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); | ||
708 | data->vid = (data->gpio >> 11) & 0x1f; | ||
709 | data->valid = 1; | ||
710 | up(&data->update_lock); | ||
711 | return data; | ||
712 | } | ||
713 | |||
714 | static ssize_t show_in(struct device *dev, char *buf, int nr) | ||
715 | { | ||
716 | struct adm1026_data *data = adm1026_update_device(dev); | ||
717 | return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr])); | ||
718 | } | ||
719 | static ssize_t show_in_min(struct device *dev, char *buf, int nr) | ||
720 | { | ||
721 | struct adm1026_data *data = adm1026_update_device(dev); | ||
722 | return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr])); | ||
723 | } | ||
724 | static ssize_t set_in_min(struct device *dev, const char *buf, | ||
725 | size_t count, int nr) | ||
726 | { | ||
727 | struct i2c_client *client = to_i2c_client(dev); | ||
728 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
729 | int val = simple_strtol(buf, NULL, 10); | ||
730 | |||
731 | down(&data->update_lock); | ||
732 | data->in_min[nr] = INS_TO_REG(nr, val); | ||
733 | adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); | ||
734 | up(&data->update_lock); | ||
735 | return count; | ||
736 | } | ||
737 | static ssize_t show_in_max(struct device *dev, char *buf, int nr) | ||
738 | { | ||
739 | struct adm1026_data *data = adm1026_update_device(dev); | ||
740 | return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr])); | ||
741 | } | ||
742 | static ssize_t set_in_max(struct device *dev, const char *buf, | ||
743 | size_t count, int nr) | ||
744 | { | ||
745 | struct i2c_client *client = to_i2c_client(dev); | ||
746 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
747 | int val = simple_strtol(buf, NULL, 10); | ||
748 | |||
749 | down(&data->update_lock); | ||
750 | data->in_max[nr] = INS_TO_REG(nr, val); | ||
751 | adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); | ||
752 | up(&data->update_lock); | ||
753 | return count; | ||
754 | } | ||
755 | |||
756 | #define in_reg(offset) \ | ||
757 | static ssize_t show_in##offset (struct device *dev, char *buf) \ | ||
758 | { \ | ||
759 | return show_in(dev, buf, offset); \ | ||
760 | } \ | ||
761 | static ssize_t show_in##offset##_min (struct device *dev, char *buf) \ | ||
762 | { \ | ||
763 | return show_in_min(dev, buf, offset); \ | ||
764 | } \ | ||
765 | static ssize_t set_in##offset##_min (struct device *dev, \ | ||
766 | const char *buf, size_t count) \ | ||
767 | { \ | ||
768 | return set_in_min(dev, buf, count, offset); \ | ||
769 | } \ | ||
770 | static ssize_t show_in##offset##_max (struct device *dev, char *buf) \ | ||
771 | { \ | ||
772 | return show_in_max(dev, buf, offset); \ | ||
773 | } \ | ||
774 | static ssize_t set_in##offset##_max (struct device *dev, \ | ||
775 | const char *buf, size_t count) \ | ||
776 | { \ | ||
777 | return set_in_max(dev, buf, count, offset); \ | ||
778 | } \ | ||
779 | static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \ | ||
780 | static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ | ||
781 | show_in##offset##_min, set_in##offset##_min); \ | ||
782 | static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | ||
783 | show_in##offset##_max, set_in##offset##_max); | ||
784 | |||
785 | |||
786 | in_reg(0); | ||
787 | in_reg(1); | ||
788 | in_reg(2); | ||
789 | in_reg(3); | ||
790 | in_reg(4); | ||
791 | in_reg(5); | ||
792 | in_reg(6); | ||
793 | in_reg(7); | ||
794 | in_reg(8); | ||
795 | in_reg(9); | ||
796 | in_reg(10); | ||
797 | in_reg(11); | ||
798 | in_reg(12); | ||
799 | in_reg(13); | ||
800 | in_reg(14); | ||
801 | in_reg(15); | ||
802 | |||
803 | static ssize_t show_in16(struct device *dev, char *buf) | ||
804 | { | ||
805 | struct adm1026_data *data = adm1026_update_device(dev); | ||
806 | return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in[16]) - | ||
807 | NEG12_OFFSET); | ||
808 | } | ||
809 | static ssize_t show_in16_min(struct device *dev, char *buf) | ||
810 | { | ||
811 | struct adm1026_data *data = adm1026_update_device(dev); | ||
812 | return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_min[16]) | ||
813 | - NEG12_OFFSET); | ||
814 | } | ||
815 | static ssize_t set_in16_min(struct device *dev, const char *buf, size_t count) | ||
816 | { | ||
817 | struct i2c_client *client = to_i2c_client(dev); | ||
818 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
819 | int val = simple_strtol(buf, NULL, 10); | ||
820 | |||
821 | down(&data->update_lock); | ||
822 | data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); | ||
823 | adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); | ||
824 | up(&data->update_lock); | ||
825 | return count; | ||
826 | } | ||
827 | static ssize_t show_in16_max(struct device *dev, char *buf) | ||
828 | { | ||
829 | struct adm1026_data *data = adm1026_update_device(dev); | ||
830 | return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_max[16]) | ||
831 | - NEG12_OFFSET); | ||
832 | } | ||
833 | static ssize_t set_in16_max(struct device *dev, const char *buf, size_t count) | ||
834 | { | ||
835 | struct i2c_client *client = to_i2c_client(dev); | ||
836 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
837 | int val = simple_strtol(buf, NULL, 10); | ||
838 | |||
839 | down(&data->update_lock); | ||
840 | data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); | ||
841 | adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); | ||
842 | up(&data->update_lock); | ||
843 | return count; | ||
844 | } | ||
845 | |||
846 | static DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL); | ||
847 | static DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min); | ||
848 | static DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max); | ||
849 | |||
850 | |||
851 | |||
852 | |||
853 | /* Now add fan read/write functions */ | ||
854 | |||
855 | static ssize_t show_fan(struct device *dev, char *buf, int nr) | ||
856 | { | ||
857 | struct adm1026_data *data = adm1026_update_device(dev); | ||
858 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], | ||
859 | data->fan_div[nr])); | ||
860 | } | ||
861 | static ssize_t show_fan_min(struct device *dev, char *buf, int nr) | ||
862 | { | ||
863 | struct adm1026_data *data = adm1026_update_device(dev); | ||
864 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], | ||
865 | data->fan_div[nr])); | ||
866 | } | ||
867 | static ssize_t set_fan_min(struct device *dev, const char *buf, | ||
868 | size_t count, int nr) | ||
869 | { | ||
870 | struct i2c_client *client = to_i2c_client(dev); | ||
871 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
872 | int val = simple_strtol(buf, NULL, 10); | ||
873 | |||
874 | down(&data->update_lock); | ||
875 | data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); | ||
876 | adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), | ||
877 | data->fan_min[nr]); | ||
878 | up(&data->update_lock); | ||
879 | return count; | ||
880 | } | ||
881 | |||
882 | #define fan_offset(offset) \ | ||
883 | static ssize_t show_fan_##offset (struct device *dev, char *buf) \ | ||
884 | { \ | ||
885 | return show_fan(dev, buf, offset - 1); \ | ||
886 | } \ | ||
887 | static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ | ||
888 | { \ | ||
889 | return show_fan_min(dev, buf, offset - 1); \ | ||
890 | } \ | ||
891 | static ssize_t set_fan_##offset##_min (struct device *dev, \ | ||
892 | const char *buf, size_t count) \ | ||
893 | { \ | ||
894 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
895 | } \ | ||
896 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \ | ||
897 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
898 | show_fan_##offset##_min, set_fan_##offset##_min); | ||
899 | |||
900 | fan_offset(1); | ||
901 | fan_offset(2); | ||
902 | fan_offset(3); | ||
903 | fan_offset(4); | ||
904 | fan_offset(5); | ||
905 | fan_offset(6); | ||
906 | fan_offset(7); | ||
907 | fan_offset(8); | ||
908 | |||
909 | /* Adjust fan_min to account for new fan divisor */ | ||
910 | static void fixup_fan_min(struct device *dev, int fan, int old_div) | ||
911 | { | ||
912 | struct i2c_client *client = to_i2c_client(dev); | ||
913 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
914 | int new_min; | ||
915 | int new_div = data->fan_div[fan]; | ||
916 | |||
917 | /* 0 and 0xff are special. Don't adjust them */ | ||
918 | if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) { | ||
919 | return; | ||
920 | } | ||
921 | |||
922 | new_min = data->fan_min[fan] * old_div / new_div; | ||
923 | new_min = SENSORS_LIMIT(new_min, 1, 254); | ||
924 | data->fan_min[fan] = new_min; | ||
925 | adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min); | ||
926 | } | ||
927 | |||
928 | /* Now add fan_div read/write functions */ | ||
929 | static ssize_t show_fan_div(struct device *dev, char *buf, int nr) | ||
930 | { | ||
931 | struct adm1026_data *data = adm1026_update_device(dev); | ||
932 | return sprintf(buf,"%d\n", data->fan_div[nr]); | ||
933 | } | ||
934 | static ssize_t set_fan_div(struct device *dev, const char *buf, | ||
935 | size_t count, int nr) | ||
936 | { | ||
937 | struct i2c_client *client = to_i2c_client(dev); | ||
938 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
939 | int val,orig_div,new_div,shift; | ||
940 | |||
941 | val = simple_strtol(buf, NULL, 10); | ||
942 | new_div = DIV_TO_REG(val); | ||
943 | if (new_div == 0) { | ||
944 | return -EINVAL; | ||
945 | } | ||
946 | down(&data->update_lock); | ||
947 | orig_div = data->fan_div[nr]; | ||
948 | data->fan_div[nr] = DIV_FROM_REG(new_div); | ||
949 | |||
950 | if (nr < 4) { /* 0 <= nr < 4 */ | ||
951 | shift = 2 * nr; | ||
952 | adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3, | ||
953 | ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) | | ||
954 | (new_div << shift))); | ||
955 | } else { /* 3 < nr < 8 */ | ||
956 | shift = 2 * (nr - 4); | ||
957 | adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7, | ||
958 | ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) | | ||
959 | (new_div << shift))); | ||
960 | } | ||
961 | |||
962 | if (data->fan_div[nr] != orig_div) { | ||
963 | fixup_fan_min(dev,nr,orig_div); | ||
964 | } | ||
965 | up(&data->update_lock); | ||
966 | return count; | ||
967 | } | ||
968 | |||
969 | #define fan_offset_div(offset) \ | ||
970 | static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \ | ||
971 | { \ | ||
972 | return show_fan_div(dev, buf, offset - 1); \ | ||
973 | } \ | ||
974 | static ssize_t set_fan_##offset##_div (struct device *dev, \ | ||
975 | const char *buf, size_t count) \ | ||
976 | { \ | ||
977 | return set_fan_div(dev, buf, count, offset - 1); \ | ||
978 | } \ | ||
979 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | ||
980 | show_fan_##offset##_div, set_fan_##offset##_div); | ||
981 | |||
982 | fan_offset_div(1); | ||
983 | fan_offset_div(2); | ||
984 | fan_offset_div(3); | ||
985 | fan_offset_div(4); | ||
986 | fan_offset_div(5); | ||
987 | fan_offset_div(6); | ||
988 | fan_offset_div(7); | ||
989 | fan_offset_div(8); | ||
990 | |||
991 | /* Temps */ | ||
992 | static ssize_t show_temp(struct device *dev, char *buf, int nr) | ||
993 | { | ||
994 | struct adm1026_data *data = adm1026_update_device(dev); | ||
995 | return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr])); | ||
996 | } | ||
997 | static ssize_t show_temp_min(struct device *dev, char *buf, int nr) | ||
998 | { | ||
999 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1000 | return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr])); | ||
1001 | } | ||
1002 | static ssize_t set_temp_min(struct device *dev, const char *buf, | ||
1003 | size_t count, int nr) | ||
1004 | { | ||
1005 | struct i2c_client *client = to_i2c_client(dev); | ||
1006 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1007 | int val = simple_strtol(buf, NULL, 10); | ||
1008 | |||
1009 | down(&data->update_lock); | ||
1010 | data->temp_min[nr] = TEMP_TO_REG(val); | ||
1011 | adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], | ||
1012 | data->temp_min[nr]); | ||
1013 | up(&data->update_lock); | ||
1014 | return count; | ||
1015 | } | ||
1016 | static ssize_t show_temp_max(struct device *dev, char *buf, int nr) | ||
1017 | { | ||
1018 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1019 | return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr])); | ||
1020 | } | ||
1021 | static ssize_t set_temp_max(struct device *dev, const char *buf, | ||
1022 | size_t count, int nr) | ||
1023 | { | ||
1024 | struct i2c_client *client = to_i2c_client(dev); | ||
1025 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1026 | int val = simple_strtol(buf, NULL, 10); | ||
1027 | |||
1028 | down(&data->update_lock); | ||
1029 | data->temp_max[nr] = TEMP_TO_REG(val); | ||
1030 | adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], | ||
1031 | data->temp_max[nr]); | ||
1032 | up(&data->update_lock); | ||
1033 | return count; | ||
1034 | } | ||
1035 | #define temp_reg(offset) \ | ||
1036 | static ssize_t show_temp_##offset (struct device *dev, char *buf) \ | ||
1037 | { \ | ||
1038 | return show_temp(dev, buf, offset - 1); \ | ||
1039 | } \ | ||
1040 | static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \ | ||
1041 | { \ | ||
1042 | return show_temp_min(dev, buf, offset - 1); \ | ||
1043 | } \ | ||
1044 | static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \ | ||
1045 | { \ | ||
1046 | return show_temp_max(dev, buf, offset - 1); \ | ||
1047 | } \ | ||
1048 | static ssize_t set_temp_##offset##_min (struct device *dev, \ | ||
1049 | const char *buf, size_t count) \ | ||
1050 | { \ | ||
1051 | return set_temp_min(dev, buf, count, offset - 1); \ | ||
1052 | } \ | ||
1053 | static ssize_t set_temp_##offset##_max (struct device *dev, \ | ||
1054 | const char *buf, size_t count) \ | ||
1055 | { \ | ||
1056 | return set_temp_max(dev, buf, count, offset - 1); \ | ||
1057 | } \ | ||
1058 | static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \ | ||
1059 | static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ | ||
1060 | show_temp_##offset##_min, set_temp_##offset##_min); \ | ||
1061 | static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | ||
1062 | show_temp_##offset##_max, set_temp_##offset##_max); | ||
1063 | |||
1064 | |||
1065 | temp_reg(1); | ||
1066 | temp_reg(2); | ||
1067 | temp_reg(3); | ||
1068 | |||
1069 | static ssize_t show_temp_offset(struct device *dev, char *buf, int nr) | ||
1070 | { | ||
1071 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1072 | return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr])); | ||
1073 | } | ||
1074 | static ssize_t set_temp_offset(struct device *dev, const char *buf, | ||
1075 | size_t count, int nr) | ||
1076 | { | ||
1077 | struct i2c_client *client = to_i2c_client(dev); | ||
1078 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1079 | int val = simple_strtol(buf, NULL, 10); | ||
1080 | |||
1081 | down(&data->update_lock); | ||
1082 | data->temp_offset[nr] = TEMP_TO_REG(val); | ||
1083 | adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], | ||
1084 | data->temp_offset[nr]); | ||
1085 | up(&data->update_lock); | ||
1086 | return count; | ||
1087 | } | ||
1088 | |||
1089 | #define temp_offset_reg(offset) \ | ||
1090 | static ssize_t show_temp_##offset##_offset (struct device *dev, char *buf) \ | ||
1091 | { \ | ||
1092 | return show_temp_offset(dev, buf, offset - 1); \ | ||
1093 | } \ | ||
1094 | static ssize_t set_temp_##offset##_offset (struct device *dev, \ | ||
1095 | const char *buf, size_t count) \ | ||
1096 | { \ | ||
1097 | return set_temp_offset(dev, buf, count, offset - 1); \ | ||
1098 | } \ | ||
1099 | static DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ | ||
1100 | show_temp_##offset##_offset, set_temp_##offset##_offset); | ||
1101 | |||
1102 | temp_offset_reg(1); | ||
1103 | temp_offset_reg(2); | ||
1104 | temp_offset_reg(3); | ||
1105 | |||
1106 | static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, char *buf, | ||
1107 | int nr) | ||
1108 | { | ||
1109 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1110 | return sprintf(buf,"%d\n", TEMP_FROM_REG( | ||
1111 | ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr])); | ||
1112 | } | ||
1113 | static ssize_t show_temp_auto_point2_temp(struct device *dev, char *buf, | ||
1114 | int nr) | ||
1115 | { | ||
1116 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1117 | return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] + | ||
1118 | ADM1026_FAN_CONTROL_TEMP_RANGE)); | ||
1119 | } | ||
1120 | static ssize_t show_temp_auto_point1_temp(struct device *dev, char *buf, | ||
1121 | int nr) | ||
1122 | { | ||
1123 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1124 | return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr])); | ||
1125 | } | ||
1126 | static ssize_t set_temp_auto_point1_temp(struct device *dev, const char *buf, | ||
1127 | size_t count, int nr) | ||
1128 | { | ||
1129 | struct i2c_client *client = to_i2c_client(dev); | ||
1130 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1131 | int val = simple_strtol(buf, NULL, 10); | ||
1132 | |||
1133 | down(&data->update_lock); | ||
1134 | data->temp_tmin[nr] = TEMP_TO_REG(val); | ||
1135 | adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], | ||
1136 | data->temp_tmin[nr]); | ||
1137 | up(&data->update_lock); | ||
1138 | return count; | ||
1139 | } | ||
1140 | |||
1141 | #define temp_auto_point(offset) \ | ||
1142 | static ssize_t show_temp##offset##_auto_point1_temp (struct device *dev, \ | ||
1143 | char *buf) \ | ||
1144 | { \ | ||
1145 | return show_temp_auto_point1_temp(dev, buf, offset - 1); \ | ||
1146 | } \ | ||
1147 | static ssize_t set_temp##offset##_auto_point1_temp (struct device *dev, \ | ||
1148 | const char *buf, size_t count) \ | ||
1149 | { \ | ||
1150 | return set_temp_auto_point1_temp(dev, buf, count, offset - 1); \ | ||
1151 | } \ | ||
1152 | static ssize_t show_temp##offset##_auto_point1_temp_hyst (struct device \ | ||
1153 | *dev, char *buf) \ | ||
1154 | { \ | ||
1155 | return show_temp_auto_point1_temp_hyst(dev, buf, offset - 1); \ | ||
1156 | } \ | ||
1157 | static ssize_t show_temp##offset##_auto_point2_temp (struct device *dev, \ | ||
1158 | char *buf) \ | ||
1159 | { \ | ||
1160 | return show_temp_auto_point2_temp(dev, buf, offset - 1); \ | ||
1161 | } \ | ||
1162 | static DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR, \ | ||
1163 | show_temp##offset##_auto_point1_temp, \ | ||
1164 | set_temp##offset##_auto_point1_temp); \ | ||
1165 | static DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO, \ | ||
1166 | show_temp##offset##_auto_point1_temp_hyst, NULL); \ | ||
1167 | static DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \ | ||
1168 | show_temp##offset##_auto_point2_temp, NULL); | ||
1169 | |||
1170 | temp_auto_point(1); | ||
1171 | temp_auto_point(2); | ||
1172 | temp_auto_point(3); | ||
1173 | |||
1174 | static ssize_t show_temp_crit_enable(struct device *dev, char *buf) | ||
1175 | { | ||
1176 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1177 | return sprintf(buf,"%d\n", (data->config1 & CFG1_THERM_HOT) >> 4); | ||
1178 | } | ||
1179 | static ssize_t set_temp_crit_enable(struct device *dev, const char *buf, | ||
1180 | size_t count) | ||
1181 | { | ||
1182 | struct i2c_client *client = to_i2c_client(dev); | ||
1183 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1184 | int val = simple_strtol(buf, NULL, 10); | ||
1185 | |||
1186 | if ((val == 1) || (val==0)) { | ||
1187 | down(&data->update_lock); | ||
1188 | data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); | ||
1189 | adm1026_write_value(client, ADM1026_REG_CONFIG1, | ||
1190 | data->config1); | ||
1191 | up(&data->update_lock); | ||
1192 | } | ||
1193 | return count; | ||
1194 | } | ||
1195 | |||
1196 | static DEVICE_ATTR(temp1_crit_enable, S_IRUGO | S_IWUSR, | ||
1197 | show_temp_crit_enable, set_temp_crit_enable); | ||
1198 | |||
1199 | static DEVICE_ATTR(temp2_crit_enable, S_IRUGO | S_IWUSR, | ||
1200 | show_temp_crit_enable, set_temp_crit_enable); | ||
1201 | |||
1202 | static DEVICE_ATTR(temp3_crit_enable, S_IRUGO | S_IWUSR, | ||
1203 | show_temp_crit_enable, set_temp_crit_enable); | ||
1204 | |||
1205 | |||
1206 | static ssize_t show_temp_crit(struct device *dev, char *buf, int nr) | ||
1207 | { | ||
1208 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1209 | return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr])); | ||
1210 | } | ||
1211 | static ssize_t set_temp_crit(struct device *dev, const char *buf, | ||
1212 | size_t count, int nr) | ||
1213 | { | ||
1214 | struct i2c_client *client = to_i2c_client(dev); | ||
1215 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1216 | int val = simple_strtol(buf, NULL, 10); | ||
1217 | |||
1218 | down(&data->update_lock); | ||
1219 | data->temp_crit[nr] = TEMP_TO_REG(val); | ||
1220 | adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], | ||
1221 | data->temp_crit[nr]); | ||
1222 | up(&data->update_lock); | ||
1223 | return count; | ||
1224 | } | ||
1225 | |||
1226 | #define temp_crit_reg(offset) \ | ||
1227 | static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf) \ | ||
1228 | { \ | ||
1229 | return show_temp_crit(dev, buf, offset - 1); \ | ||
1230 | } \ | ||
1231 | static ssize_t set_temp_##offset##_crit (struct device *dev, \ | ||
1232 | const char *buf, size_t count) \ | ||
1233 | { \ | ||
1234 | return set_temp_crit(dev, buf, count, offset - 1); \ | ||
1235 | } \ | ||
1236 | static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ | ||
1237 | show_temp_##offset##_crit, set_temp_##offset##_crit); | ||
1238 | |||
1239 | temp_crit_reg(1); | ||
1240 | temp_crit_reg(2); | ||
1241 | temp_crit_reg(3); | ||
1242 | |||
1243 | static ssize_t show_analog_out_reg(struct device *dev, char *buf) | ||
1244 | { | ||
1245 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1246 | return sprintf(buf,"%d\n", DAC_FROM_REG(data->analog_out)); | ||
1247 | } | ||
1248 | static ssize_t set_analog_out_reg(struct device *dev, const char *buf, | ||
1249 | size_t count) | ||
1250 | { | ||
1251 | struct i2c_client *client = to_i2c_client(dev); | ||
1252 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1253 | int val = simple_strtol(buf, NULL, 10); | ||
1254 | |||
1255 | down(&data->update_lock); | ||
1256 | data->analog_out = DAC_TO_REG(val); | ||
1257 | adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); | ||
1258 | up(&data->update_lock); | ||
1259 | return count; | ||
1260 | } | ||
1261 | |||
1262 | static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, | ||
1263 | set_analog_out_reg); | ||
1264 | |||
1265 | static ssize_t show_vid_reg(struct device *dev, char *buf) | ||
1266 | { | ||
1267 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1268 | return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm)); | ||
1269 | } | ||
1270 | |||
1271 | static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL); | ||
1272 | |||
1273 | static ssize_t show_vrm_reg(struct device *dev, char *buf) | ||
1274 | { | ||
1275 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1276 | return sprintf(buf,"%d\n", data->vrm); | ||
1277 | } | ||
1278 | static ssize_t store_vrm_reg(struct device *dev, const char *buf, | ||
1279 | size_t count) | ||
1280 | { | ||
1281 | struct i2c_client *client = to_i2c_client(dev); | ||
1282 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1283 | |||
1284 | data->vrm = simple_strtol(buf, NULL, 10); | ||
1285 | return count; | ||
1286 | } | ||
1287 | |||
1288 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | ||
1289 | |||
1290 | static ssize_t show_alarms_reg(struct device *dev, char *buf) | ||
1291 | { | ||
1292 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1293 | return sprintf(buf, "%ld\n", (long) (data->alarms)); | ||
1294 | } | ||
1295 | |||
1296 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); | ||
1297 | |||
1298 | static ssize_t show_alarm_mask(struct device *dev, char *buf) | ||
1299 | { | ||
1300 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1301 | return sprintf(buf,"%ld\n", data->alarm_mask); | ||
1302 | } | ||
1303 | static ssize_t set_alarm_mask(struct device *dev, const char *buf, | ||
1304 | size_t count) | ||
1305 | { | ||
1306 | struct i2c_client *client = to_i2c_client(dev); | ||
1307 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1308 | int val = simple_strtol(buf, NULL, 10); | ||
1309 | unsigned long mask; | ||
1310 | |||
1311 | down(&data->update_lock); | ||
1312 | data->alarm_mask = val & 0x7fffffff; | ||
1313 | mask = data->alarm_mask | ||
1314 | | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); | ||
1315 | adm1026_write_value(client, ADM1026_REG_MASK1, | ||
1316 | mask & 0xff); | ||
1317 | mask >>= 8; | ||
1318 | adm1026_write_value(client, ADM1026_REG_MASK2, | ||
1319 | mask & 0xff); | ||
1320 | mask >>= 8; | ||
1321 | adm1026_write_value(client, ADM1026_REG_MASK3, | ||
1322 | mask & 0xff); | ||
1323 | mask >>= 8; | ||
1324 | adm1026_write_value(client, ADM1026_REG_MASK4, | ||
1325 | mask & 0xff); | ||
1326 | up(&data->update_lock); | ||
1327 | return count; | ||
1328 | } | ||
1329 | |||
1330 | static DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask, | ||
1331 | set_alarm_mask); | ||
1332 | |||
1333 | |||
1334 | static ssize_t show_gpio(struct device *dev, char *buf) | ||
1335 | { | ||
1336 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1337 | return sprintf(buf,"%ld\n", data->gpio); | ||
1338 | } | ||
1339 | static ssize_t set_gpio(struct device *dev, const char *buf, | ||
1340 | size_t count) | ||
1341 | { | ||
1342 | struct i2c_client *client = to_i2c_client(dev); | ||
1343 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1344 | int val = simple_strtol(buf, NULL, 10); | ||
1345 | long gpio; | ||
1346 | |||
1347 | down(&data->update_lock); | ||
1348 | data->gpio = val & 0x1ffff; | ||
1349 | gpio = data->gpio; | ||
1350 | adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff); | ||
1351 | gpio >>= 8; | ||
1352 | adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff); | ||
1353 | gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); | ||
1354 | adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff); | ||
1355 | up(&data->update_lock); | ||
1356 | return count; | ||
1357 | } | ||
1358 | |||
1359 | static DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio); | ||
1360 | |||
1361 | |||
1362 | static ssize_t show_gpio_mask(struct device *dev, char *buf) | ||
1363 | { | ||
1364 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1365 | return sprintf(buf,"%ld\n", data->gpio_mask); | ||
1366 | } | ||
1367 | static ssize_t set_gpio_mask(struct device *dev, const char *buf, | ||
1368 | size_t count) | ||
1369 | { | ||
1370 | struct i2c_client *client = to_i2c_client(dev); | ||
1371 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1372 | int val = simple_strtol(buf, NULL, 10); | ||
1373 | long mask; | ||
1374 | |||
1375 | down(&data->update_lock); | ||
1376 | data->gpio_mask = val & 0x1ffff; | ||
1377 | mask = data->gpio_mask; | ||
1378 | adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff); | ||
1379 | mask >>= 8; | ||
1380 | adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff); | ||
1381 | mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); | ||
1382 | adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff); | ||
1383 | up(&data->update_lock); | ||
1384 | return count; | ||
1385 | } | ||
1386 | |||
1387 | static DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask); | ||
1388 | |||
1389 | static ssize_t show_pwm_reg(struct device *dev, char *buf) | ||
1390 | { | ||
1391 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1392 | return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm1.pwm)); | ||
1393 | } | ||
1394 | static ssize_t set_pwm_reg(struct device *dev, const char *buf, | ||
1395 | size_t count) | ||
1396 | { | ||
1397 | struct i2c_client *client = to_i2c_client(dev); | ||
1398 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1399 | |||
1400 | if (data->pwm1.enable == 1) { | ||
1401 | int val = simple_strtol(buf, NULL, 10); | ||
1402 | |||
1403 | down(&data->update_lock); | ||
1404 | data->pwm1.pwm = PWM_TO_REG(val); | ||
1405 | adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); | ||
1406 | up(&data->update_lock); | ||
1407 | } | ||
1408 | return count; | ||
1409 | } | ||
1410 | static ssize_t show_auto_pwm_min(struct device *dev, char *buf) | ||
1411 | { | ||
1412 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1413 | return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min); | ||
1414 | } | ||
1415 | static ssize_t set_auto_pwm_min(struct device *dev, const char *buf, | ||
1416 | size_t count) | ||
1417 | { | ||
1418 | struct i2c_client *client = to_i2c_client(dev); | ||
1419 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1420 | int val = simple_strtol(buf, NULL, 10); | ||
1421 | |||
1422 | down(&data->update_lock); | ||
1423 | data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); | ||
1424 | if (data->pwm1.enable == 2) { /* apply immediately */ | ||
1425 | data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | | ||
1426 | PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); | ||
1427 | adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); | ||
1428 | } | ||
1429 | up(&data->update_lock); | ||
1430 | return count; | ||
1431 | } | ||
1432 | static ssize_t show_auto_pwm_max(struct device *dev, char *buf) | ||
1433 | { | ||
1434 | return sprintf(buf,"%d\n", ADM1026_PWM_MAX); | ||
1435 | } | ||
1436 | static ssize_t show_pwm_enable(struct device *dev, char *buf) | ||
1437 | { | ||
1438 | struct adm1026_data *data = adm1026_update_device(dev); | ||
1439 | return sprintf(buf,"%d\n", data->pwm1.enable); | ||
1440 | } | ||
1441 | static ssize_t set_pwm_enable(struct device *dev, const char *buf, | ||
1442 | size_t count) | ||
1443 | { | ||
1444 | struct i2c_client *client = to_i2c_client(dev); | ||
1445 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1446 | int val = simple_strtol(buf, NULL, 10); | ||
1447 | int old_enable; | ||
1448 | |||
1449 | if ((val >= 0) && (val < 3)) { | ||
1450 | down(&data->update_lock); | ||
1451 | old_enable = data->pwm1.enable; | ||
1452 | data->pwm1.enable = val; | ||
1453 | data->config1 = (data->config1 & ~CFG1_PWM_AFC) | ||
1454 | | ((val == 2) ? CFG1_PWM_AFC : 0); | ||
1455 | adm1026_write_value(client, ADM1026_REG_CONFIG1, | ||
1456 | data->config1); | ||
1457 | if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */ | ||
1458 | data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | | ||
1459 | PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); | ||
1460 | adm1026_write_value(client, ADM1026_REG_PWM, | ||
1461 | data->pwm1.pwm); | ||
1462 | } else if (!((old_enable == 1) && (val == 1))) { | ||
1463 | /* set pwm to safe value */ | ||
1464 | data->pwm1.pwm = 255; | ||
1465 | adm1026_write_value(client, ADM1026_REG_PWM, | ||
1466 | data->pwm1.pwm); | ||
1467 | } | ||
1468 | up(&data->update_lock); | ||
1469 | } | ||
1470 | return count; | ||
1471 | } | ||
1472 | |||
1473 | /* enable PWM fan control */ | ||
1474 | static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); | ||
1475 | static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); | ||
1476 | static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); | ||
1477 | static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, | ||
1478 | set_pwm_enable); | ||
1479 | static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, | ||
1480 | set_pwm_enable); | ||
1481 | static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, | ||
1482 | set_pwm_enable); | ||
1483 | static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, | ||
1484 | show_auto_pwm_min, set_auto_pwm_min); | ||
1485 | static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, | ||
1486 | show_auto_pwm_min, set_auto_pwm_min); | ||
1487 | static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, | ||
1488 | show_auto_pwm_min, set_auto_pwm_min); | ||
1489 | |||
1490 | static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); | ||
1491 | static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); | ||
1492 | static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); | ||
1493 | |||
1494 | int adm1026_detect(struct i2c_adapter *adapter, int address, | ||
1495 | int kind) | ||
1496 | { | ||
1497 | int company, verstep; | ||
1498 | struct i2c_client *new_client; | ||
1499 | struct adm1026_data *data; | ||
1500 | int err = 0; | ||
1501 | const char *type_name = ""; | ||
1502 | |||
1503 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
1504 | /* We need to be able to do byte I/O */ | ||
1505 | goto exit; | ||
1506 | }; | ||
1507 | |||
1508 | /* OK. For now, we presume we have a valid client. We now create the | ||
1509 | client structure, even though we cannot fill it completely yet. | ||
1510 | But it allows us to access adm1026_{read,write}_value. */ | ||
1511 | |||
1512 | if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) { | ||
1513 | err = -ENOMEM; | ||
1514 | goto exit; | ||
1515 | } | ||
1516 | |||
1517 | memset(data, 0, sizeof(struct adm1026_data)); | ||
1518 | |||
1519 | new_client = &data->client; | ||
1520 | i2c_set_clientdata(new_client, data); | ||
1521 | new_client->addr = address; | ||
1522 | new_client->adapter = adapter; | ||
1523 | new_client->driver = &adm1026_driver; | ||
1524 | new_client->flags = 0; | ||
1525 | |||
1526 | /* Now, we do the remaining detection. */ | ||
1527 | |||
1528 | company = adm1026_read_value(new_client, ADM1026_REG_COMPANY); | ||
1529 | verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP); | ||
1530 | |||
1531 | dev_dbg(&new_client->dev, "Detecting device at %d,0x%02x with" | ||
1532 | " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", | ||
1533 | i2c_adapter_id(new_client->adapter), new_client->addr, | ||
1534 | company, verstep); | ||
1535 | |||
1536 | /* If auto-detecting, Determine the chip type. */ | ||
1537 | if (kind <= 0) { | ||
1538 | dev_dbg(&new_client->dev, "Autodetecting device at %d,0x%02x " | ||
1539 | "...\n", i2c_adapter_id(adapter), address); | ||
1540 | if (company == ADM1026_COMPANY_ANALOG_DEV | ||
1541 | && verstep == ADM1026_VERSTEP_ADM1026) { | ||
1542 | kind = adm1026; | ||
1543 | } else if (company == ADM1026_COMPANY_ANALOG_DEV | ||
1544 | && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { | ||
1545 | dev_err(&adapter->dev, ": Unrecognized stepping " | ||
1546 | "0x%02x. Defaulting to ADM1026.\n", verstep); | ||
1547 | kind = adm1026; | ||
1548 | } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { | ||
1549 | dev_err(&adapter->dev, ": Found version/stepping " | ||
1550 | "0x%02x. Assuming generic ADM1026.\n", | ||
1551 | verstep); | ||
1552 | kind = any_chip; | ||
1553 | } else { | ||
1554 | dev_dbg(&new_client->dev, ": Autodetection " | ||
1555 | "failed\n"); | ||
1556 | /* Not an ADM1026 ... */ | ||
1557 | if (kind == 0) { /* User used force=x,y */ | ||
1558 | dev_err(&adapter->dev, "Generic ADM1026 not " | ||
1559 | "found at %d,0x%02x. Try " | ||
1560 | "force_adm1026.\n", | ||
1561 | i2c_adapter_id(adapter), address); | ||
1562 | } | ||
1563 | err = 0; | ||
1564 | goto exitfree; | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1568 | /* Fill in the chip specific driver values */ | ||
1569 | switch (kind) { | ||
1570 | case any_chip : | ||
1571 | type_name = "adm1026"; | ||
1572 | break; | ||
1573 | case adm1026 : | ||
1574 | type_name = "adm1026"; | ||
1575 | break; | ||
1576 | default : | ||
1577 | dev_err(&adapter->dev, ": Internal error, invalid " | ||
1578 | "kind (%d)!", kind); | ||
1579 | err = -EFAULT; | ||
1580 | goto exitfree; | ||
1581 | } | ||
1582 | strlcpy(new_client->name, type_name, I2C_NAME_SIZE); | ||
1583 | |||
1584 | /* Fill in the remaining client fields */ | ||
1585 | data->type = kind; | ||
1586 | data->valid = 0; | ||
1587 | init_MUTEX(&data->update_lock); | ||
1588 | |||
1589 | /* Tell the I2C layer a new client has arrived */ | ||
1590 | if ((err = i2c_attach_client(new_client))) | ||
1591 | goto exitfree; | ||
1592 | |||
1593 | /* Set the VRM version */ | ||
1594 | data->vrm = i2c_which_vrm(); | ||
1595 | |||
1596 | /* Initialize the ADM1026 chip */ | ||
1597 | adm1026_init_client(new_client); | ||
1598 | |||
1599 | /* Register sysfs hooks */ | ||
1600 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
1601 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
1602 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
1603 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
1604 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
1605 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
1606 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
1607 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
1608 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
1609 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
1610 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
1611 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
1612 | device_create_file(&new_client->dev, &dev_attr_in4_input); | ||
1613 | device_create_file(&new_client->dev, &dev_attr_in4_max); | ||
1614 | device_create_file(&new_client->dev, &dev_attr_in4_min); | ||
1615 | device_create_file(&new_client->dev, &dev_attr_in5_input); | ||
1616 | device_create_file(&new_client->dev, &dev_attr_in5_max); | ||
1617 | device_create_file(&new_client->dev, &dev_attr_in5_min); | ||
1618 | device_create_file(&new_client->dev, &dev_attr_in6_input); | ||
1619 | device_create_file(&new_client->dev, &dev_attr_in6_max); | ||
1620 | device_create_file(&new_client->dev, &dev_attr_in6_min); | ||
1621 | device_create_file(&new_client->dev, &dev_attr_in7_input); | ||
1622 | device_create_file(&new_client->dev, &dev_attr_in7_max); | ||
1623 | device_create_file(&new_client->dev, &dev_attr_in7_min); | ||
1624 | device_create_file(&new_client->dev, &dev_attr_in8_input); | ||
1625 | device_create_file(&new_client->dev, &dev_attr_in8_max); | ||
1626 | device_create_file(&new_client->dev, &dev_attr_in8_min); | ||
1627 | device_create_file(&new_client->dev, &dev_attr_in9_input); | ||
1628 | device_create_file(&new_client->dev, &dev_attr_in9_max); | ||
1629 | device_create_file(&new_client->dev, &dev_attr_in9_min); | ||
1630 | device_create_file(&new_client->dev, &dev_attr_in10_input); | ||
1631 | device_create_file(&new_client->dev, &dev_attr_in10_max); | ||
1632 | device_create_file(&new_client->dev, &dev_attr_in10_min); | ||
1633 | device_create_file(&new_client->dev, &dev_attr_in11_input); | ||
1634 | device_create_file(&new_client->dev, &dev_attr_in11_max); | ||
1635 | device_create_file(&new_client->dev, &dev_attr_in11_min); | ||
1636 | device_create_file(&new_client->dev, &dev_attr_in12_input); | ||
1637 | device_create_file(&new_client->dev, &dev_attr_in12_max); | ||
1638 | device_create_file(&new_client->dev, &dev_attr_in12_min); | ||
1639 | device_create_file(&new_client->dev, &dev_attr_in13_input); | ||
1640 | device_create_file(&new_client->dev, &dev_attr_in13_max); | ||
1641 | device_create_file(&new_client->dev, &dev_attr_in13_min); | ||
1642 | device_create_file(&new_client->dev, &dev_attr_in14_input); | ||
1643 | device_create_file(&new_client->dev, &dev_attr_in14_max); | ||
1644 | device_create_file(&new_client->dev, &dev_attr_in14_min); | ||
1645 | device_create_file(&new_client->dev, &dev_attr_in15_input); | ||
1646 | device_create_file(&new_client->dev, &dev_attr_in15_max); | ||
1647 | device_create_file(&new_client->dev, &dev_attr_in15_min); | ||
1648 | device_create_file(&new_client->dev, &dev_attr_in16_input); | ||
1649 | device_create_file(&new_client->dev, &dev_attr_in16_max); | ||
1650 | device_create_file(&new_client->dev, &dev_attr_in16_min); | ||
1651 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
1652 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
1653 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
1654 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
1655 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | ||
1656 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
1657 | device_create_file(&new_client->dev, &dev_attr_fan3_input); | ||
1658 | device_create_file(&new_client->dev, &dev_attr_fan3_div); | ||
1659 | device_create_file(&new_client->dev, &dev_attr_fan3_min); | ||
1660 | device_create_file(&new_client->dev, &dev_attr_fan4_input); | ||
1661 | device_create_file(&new_client->dev, &dev_attr_fan4_div); | ||
1662 | device_create_file(&new_client->dev, &dev_attr_fan4_min); | ||
1663 | device_create_file(&new_client->dev, &dev_attr_fan5_input); | ||
1664 | device_create_file(&new_client->dev, &dev_attr_fan5_div); | ||
1665 | device_create_file(&new_client->dev, &dev_attr_fan5_min); | ||
1666 | device_create_file(&new_client->dev, &dev_attr_fan6_input); | ||
1667 | device_create_file(&new_client->dev, &dev_attr_fan6_div); | ||
1668 | device_create_file(&new_client->dev, &dev_attr_fan6_min); | ||
1669 | device_create_file(&new_client->dev, &dev_attr_fan7_input); | ||
1670 | device_create_file(&new_client->dev, &dev_attr_fan7_div); | ||
1671 | device_create_file(&new_client->dev, &dev_attr_fan7_min); | ||
1672 | device_create_file(&new_client->dev, &dev_attr_fan8_input); | ||
1673 | device_create_file(&new_client->dev, &dev_attr_fan8_div); | ||
1674 | device_create_file(&new_client->dev, &dev_attr_fan8_min); | ||
1675 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
1676 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
1677 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
1678 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
1679 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
1680 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
1681 | device_create_file(&new_client->dev, &dev_attr_temp3_input); | ||
1682 | device_create_file(&new_client->dev, &dev_attr_temp3_max); | ||
1683 | device_create_file(&new_client->dev, &dev_attr_temp3_min); | ||
1684 | device_create_file(&new_client->dev, &dev_attr_temp1_offset); | ||
1685 | device_create_file(&new_client->dev, &dev_attr_temp2_offset); | ||
1686 | device_create_file(&new_client->dev, &dev_attr_temp3_offset); | ||
1687 | device_create_file(&new_client->dev, | ||
1688 | &dev_attr_temp1_auto_point1_temp); | ||
1689 | device_create_file(&new_client->dev, | ||
1690 | &dev_attr_temp2_auto_point1_temp); | ||
1691 | device_create_file(&new_client->dev, | ||
1692 | &dev_attr_temp3_auto_point1_temp); | ||
1693 | device_create_file(&new_client->dev, | ||
1694 | &dev_attr_temp1_auto_point1_temp_hyst); | ||
1695 | device_create_file(&new_client->dev, | ||
1696 | &dev_attr_temp2_auto_point1_temp_hyst); | ||
1697 | device_create_file(&new_client->dev, | ||
1698 | &dev_attr_temp3_auto_point1_temp_hyst); | ||
1699 | device_create_file(&new_client->dev, | ||
1700 | &dev_attr_temp1_auto_point2_temp); | ||
1701 | device_create_file(&new_client->dev, | ||
1702 | &dev_attr_temp2_auto_point2_temp); | ||
1703 | device_create_file(&new_client->dev, | ||
1704 | &dev_attr_temp3_auto_point2_temp); | ||
1705 | device_create_file(&new_client->dev, &dev_attr_temp1_crit); | ||
1706 | device_create_file(&new_client->dev, &dev_attr_temp2_crit); | ||
1707 | device_create_file(&new_client->dev, &dev_attr_temp3_crit); | ||
1708 | device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable); | ||
1709 | device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable); | ||
1710 | device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable); | ||
1711 | device_create_file(&new_client->dev, &dev_attr_vid); | ||
1712 | device_create_file(&new_client->dev, &dev_attr_vrm); | ||
1713 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
1714 | device_create_file(&new_client->dev, &dev_attr_alarm_mask); | ||
1715 | device_create_file(&new_client->dev, &dev_attr_gpio); | ||
1716 | device_create_file(&new_client->dev, &dev_attr_gpio_mask); | ||
1717 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
1718 | device_create_file(&new_client->dev, &dev_attr_pwm2); | ||
1719 | device_create_file(&new_client->dev, &dev_attr_pwm3); | ||
1720 | device_create_file(&new_client->dev, &dev_attr_pwm1_enable); | ||
1721 | device_create_file(&new_client->dev, &dev_attr_pwm2_enable); | ||
1722 | device_create_file(&new_client->dev, &dev_attr_pwm3_enable); | ||
1723 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm); | ||
1724 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm); | ||
1725 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm); | ||
1726 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm); | ||
1727 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm); | ||
1728 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm); | ||
1729 | device_create_file(&new_client->dev, &dev_attr_analog_out); | ||
1730 | return 0; | ||
1731 | |||
1732 | /* Error out and cleanup code */ | ||
1733 | exitfree: | ||
1734 | kfree(new_client); | ||
1735 | exit: | ||
1736 | return err; | ||
1737 | } | ||
1738 | static int __init sm_adm1026_init(void) | ||
1739 | { | ||
1740 | return i2c_add_driver(&adm1026_driver); | ||
1741 | } | ||
1742 | |||
1743 | static void __exit sm_adm1026_exit(void) | ||
1744 | { | ||
1745 | i2c_del_driver(&adm1026_driver); | ||
1746 | } | ||
1747 | |||
1748 | MODULE_LICENSE("GPL"); | ||
1749 | MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, " | ||
1750 | "Justin Thiessen <jthiessen@penguincomputing.com>"); | ||
1751 | MODULE_DESCRIPTION("ADM1026 driver"); | ||
1752 | |||
1753 | module_init(sm_adm1026_init); | ||
1754 | module_exit(sm_adm1026_exit); | ||