OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [hwmon/] [fschmd.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* fschmd.c
2
 *
3
 * Copyright (C) 2007 Hans de Goede <j.w.r.degoede@hhs.nl>
4
 *
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
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
 
20
/*
21
 *  Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes,
22
 *  Scylla, Heracles and Heimdall chips
23
 *
24
 *  Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6
25
 *  (candidate) fschmd drivers:
26
 *  Copyright (C) 2006 Thilo Cestonaro
27
 *                      <thilo.cestonaro.external@fujitsu-siemens.com>
28
 *  Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch>
29
 *  Copyright (C) 2003, 2004 Reinhard Nissl <rnissl@gmx.de>
30
 *  Copyright (c) 2001 Martin Knoblauch <mkn@teraport.de, knobi@knobisoft.de>
31
 *  Copyright (C) 2000 Hermann Jung <hej@odn.de>
32
 */
33
 
34
#include <linux/module.h>
35
#include <linux/init.h>
36
#include <linux/slab.h>
37
#include <linux/jiffies.h>
38
#include <linux/i2c.h>
39
#include <linux/hwmon.h>
40
#include <linux/hwmon-sysfs.h>
41
#include <linux/err.h>
42
#include <linux/mutex.h>
43
#include <linux/sysfs.h>
44
 
45
/* Addresses to scan */
46
static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
47
 
48
/* Insmod parameters */
49
I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd);
50
 
51
/*
52
 * The FSCHMD registers and other defines
53
 */
54
 
55
/* chip identification */
56
#define FSCHMD_REG_IDENT_0              0x00
57
#define FSCHMD_REG_IDENT_1              0x01
58
#define FSCHMD_REG_IDENT_2              0x02
59
#define FSCHMD_REG_REVISION             0x03
60
 
61
/* global control and status */
62
#define FSCHMD_REG_EVENT_STATE          0x04
63
#define FSCHMD_REG_CONTROL              0x05
64
 
65
#define FSCHMD_CONTROL_ALERT_LED_MASK   0x01
66
 
67
/* watchdog (support to be implemented) */
68
#define FSCHMD_REG_WDOG_PRESET          0x28
69
#define FSCHMD_REG_WDOG_STATE           0x23
70
#define FSCHMD_REG_WDOG_CONTROL         0x21
71
 
72
/* voltages, weird order is to keep the same order as the old drivers */
73
static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 };
74
 
75
/* minimum pwm at which the fan is driven (pwm can by increased depending on
76
   the temp. Notice that for the scy some fans share there minimum speed.
77
   Also notice that with the scy the sensor order is different then with the
78
   other chips, this order was in the 2.4 driver and kept for consistency. */
79
static const u8 FSCHMD_REG_FAN_MIN[5][6] = {
80
        { 0x55, 0x65 },                                 /* pos */
81
        { 0x55, 0x65, 0xb5 },                           /* her */
82
        { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 },         /* scy */
83
        { 0x55, 0x65, 0xa5, 0xb5 },                     /* hrc */
84
        { 0x55, 0x65, 0xa5, 0xb5, 0xc5 },               /* hmd */
85
};
86
 
87
/* actual fan speed */
88
static const u8 FSCHMD_REG_FAN_ACT[5][6] = {
89
        { 0x0e, 0x6b, 0xab },                           /* pos */
90
        { 0x0e, 0x6b, 0xbb },                           /* her */
91
        { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb },         /* scy */
92
        { 0x0e, 0x6b, 0xab, 0xbb },                     /* hrc */
93
        { 0x5b, 0x6b, 0xab, 0xbb, 0xcb },               /* hmd */
94
};
95
 
96
/* fan status registers */
97
static const u8 FSCHMD_REG_FAN_STATE[5][6] = {
98
        { 0x0d, 0x62, 0xa2 },                           /* pos */
99
        { 0x0d, 0x62, 0xb2 },                           /* her */
100
        { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 },         /* scy */
101
        { 0x0d, 0x62, 0xa2, 0xb2 },                     /* hrc */
102
        { 0x52, 0x62, 0xa2, 0xb2, 0xc2 },               /* hmd */
103
};
104
 
105
/* fan ripple / divider registers */
106
static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = {
107
        { 0x0f, 0x6f, 0xaf },                           /* pos */
108
        { 0x0f, 0x6f, 0xbf },                           /* her */
109
        { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf },         /* scy */
110
        { 0x0f, 0x6f, 0xaf, 0xbf },                     /* hrc */
111
        { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf },               /* hmd */
112
};
113
 
114
static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 };
115
 
116
/* Fan status register bitmasks */
117
#define FSCHMD_FAN_ALARM_MASK           0x04 /* called fault by FSC! */
118
#define FSCHMD_FAN_NOT_PRESENT_MASK     0x08 /* not documented */
119
 
120
 
121
/* actual temperature registers */
122
static const u8 FSCHMD_REG_TEMP_ACT[5][5] = {
123
        { 0x64, 0x32, 0x35 },                           /* pos */
124
        { 0x64, 0x32, 0x35 },                           /* her */
125
        { 0x64, 0xD0, 0x32, 0x35 },                     /* scy */
126
        { 0x64, 0x32, 0x35 },                           /* hrc */
127
        { 0x70, 0x80, 0x90, 0xd0, 0xe0 },               /* hmd */
128
};
129
 
130
/* temperature state registers */
131
static const u8 FSCHMD_REG_TEMP_STATE[5][5] = {
132
        { 0x71, 0x81, 0x91 },                           /* pos */
133
        { 0x71, 0x81, 0x91 },                           /* her */
134
        { 0x71, 0xd1, 0x81, 0x91 },                     /* scy */
135
        { 0x71, 0x81, 0x91 },                           /* hrc */
136
        { 0x71, 0x81, 0x91, 0xd1, 0xe1 },               /* hmd */
137
};
138
 
139
/* temperature high limit registers, FSC does not document these. Proven to be
140
   there with field testing on the fscher and fschrc, already supported / used
141
   in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers
142
   at these addresses, but doesn't want to confirm they are the same as with
143
   the fscher?? */
144
static const u8 FSCHMD_REG_TEMP_LIMIT[5][5] = {
145
        { 0, 0, 0 },                                       /* pos */
146
        { 0x76, 0x86, 0x96 },                           /* her */
147
        { 0x76, 0xd6, 0x86, 0x96 },                     /* scy */
148
        { 0x76, 0x86, 0x96 },                           /* hrc */
149
        { 0x76, 0x86, 0x96, 0xd6, 0xe6 },               /* hmd */
150
};
151
 
152
/* These were found through experimenting with an fscher, currently they are
153
   not used, but we keep them around for future reference.
154
static const u8 FSCHER_REG_TEMP_AUTOP1[] =      { 0x73, 0x83, 0x93 };
155
static const u8 FSCHER_REG_TEMP_AUTOP2[] =      { 0x75, 0x85, 0x95 }; */
156
 
157
static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 };
158
 
159
/* temp status register bitmasks */
160
#define FSCHMD_TEMP_WORKING_MASK        0x01
161
#define FSCHMD_TEMP_ALERT_MASK          0x02
162
/* there only really is an alarm if the sensor is working and alert == 1 */
163
#define FSCHMD_TEMP_ALARM_MASK \
164
        (FSCHMD_TEMP_WORKING_MASK | FSCHMD_TEMP_ALERT_MASK)
165
 
166
/* our driver name */
167
#define FSCHMD_NAME "fschmd"
168
 
169
/*
170
 * Functions declarations
171
 */
172
 
173
static int fschmd_attach_adapter(struct i2c_adapter *adapter);
174
static int fschmd_detach_client(struct i2c_client *client);
175
static struct fschmd_data *fschmd_update_device(struct device *dev);
176
 
177
/*
178
 * Driver data (common to all clients)
179
 */
180
 
181
static struct i2c_driver fschmd_driver = {
182
        .driver = {
183
                .name   = FSCHMD_NAME,
184
        },
185
        .attach_adapter = fschmd_attach_adapter,
186
        .detach_client  = fschmd_detach_client,
187
};
188
 
189
/*
190
 * Client data (each client gets its own)
191
 */
192
 
193
struct fschmd_data {
194
        struct i2c_client client;
195
        struct device *hwmon_dev;
196
        struct mutex update_lock;
197
        int kind;
198
        char valid; /* zero until following fields are valid */
199
        unsigned long last_updated; /* in jiffies */
200
 
201
        /* register values */
202
        u8 global_control;      /* global control register */
203
        u8 volt[3];             /* 12, 5, battery voltage */
204
        u8 temp_act[5];         /* temperature */
205
        u8 temp_status[5];      /* status of sensor */
206
        u8 temp_max[5];         /* high temp limit, notice: undocumented! */
207
        u8 fan_act[6];          /* fans revolutions per second */
208
        u8 fan_status[6];       /* fan status */
209
        u8 fan_min[6];          /* fan min value for rps */
210
        u8 fan_ripple[6];       /* divider for rps */
211
};
212
 
213
/*
214
 * Sysfs attr show / store functions
215
 */
216
 
217
static ssize_t show_in_value(struct device *dev,
218
        struct device_attribute *devattr, char *buf)
219
{
220
        const int max_reading[3] = { 14200, 6600, 3300 };
221
        int index = to_sensor_dev_attr(devattr)->index;
222
        struct fschmd_data *data = fschmd_update_device(dev);
223
 
224
        return sprintf(buf, "%d\n", (data->volt[index] *
225
                max_reading[index] + 128) / 255);
226
}
227
 
228
 
229
#define TEMP_FROM_REG(val)      (((val) - 128) * 1000)
230
 
231
static ssize_t show_temp_value(struct device *dev,
232
        struct device_attribute *devattr, char *buf)
233
{
234
        int index = to_sensor_dev_attr(devattr)->index;
235
        struct fschmd_data *data = fschmd_update_device(dev);
236
 
237
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[index]));
238
}
239
 
240
static ssize_t show_temp_max(struct device *dev,
241
        struct device_attribute *devattr, char *buf)
242
{
243
        int index = to_sensor_dev_attr(devattr)->index;
244
        struct fschmd_data *data = fschmd_update_device(dev);
245
 
246
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[index]));
247
}
248
 
249
static ssize_t store_temp_max(struct device *dev, struct device_attribute
250
        *devattr, const char *buf, size_t count)
251
{
252
        int index = to_sensor_dev_attr(devattr)->index;
253
        struct fschmd_data *data = dev_get_drvdata(dev);
254
        long v = simple_strtol(buf, NULL, 10) / 1000;
255
 
256
        v = SENSORS_LIMIT(v, -128, 127) + 128;
257
 
258
        mutex_lock(&data->update_lock);
259
        i2c_smbus_write_byte_data(&data->client,
260
                FSCHMD_REG_TEMP_LIMIT[data->kind][index], v);
261
        data->temp_max[index] = v;
262
        mutex_unlock(&data->update_lock);
263
 
264
        return count;
265
}
266
 
267
static ssize_t show_temp_fault(struct device *dev,
268
        struct device_attribute *devattr, char *buf)
269
{
270
        int index = to_sensor_dev_attr(devattr)->index;
271
        struct fschmd_data *data = fschmd_update_device(dev);
272
 
273
        /* bit 0 set means sensor working ok, so no fault! */
274
        if (data->temp_status[index] & FSCHMD_TEMP_WORKING_MASK)
275
                return sprintf(buf, "0\n");
276
        else
277
                return sprintf(buf, "1\n");
278
}
279
 
280
static ssize_t show_temp_alarm(struct device *dev,
281
        struct device_attribute *devattr, char *buf)
282
{
283
        int index = to_sensor_dev_attr(devattr)->index;
284
        struct fschmd_data *data = fschmd_update_device(dev);
285
 
286
        if ((data->temp_status[index] & FSCHMD_TEMP_ALARM_MASK) ==
287
                        FSCHMD_TEMP_ALARM_MASK)
288
                return sprintf(buf, "1\n");
289
        else
290
                return sprintf(buf, "0\n");
291
}
292
 
293
 
294
#define RPM_FROM_REG(val)       ((val) * 60)
295
 
296
static ssize_t show_fan_value(struct device *dev,
297
        struct device_attribute *devattr, char *buf)
298
{
299
        int index = to_sensor_dev_attr(devattr)->index;
300
        struct fschmd_data *data = fschmd_update_device(dev);
301
 
302
        return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[index]));
303
}
304
 
305
static ssize_t show_fan_div(struct device *dev,
306
        struct device_attribute *devattr, char *buf)
307
{
308
        int index = to_sensor_dev_attr(devattr)->index;
309
        struct fschmd_data *data = fschmd_update_device(dev);
310
 
311
        /* bits 2..7 reserved => mask with 3 */
312
        return sprintf(buf, "%d\n", 1 << (data->fan_ripple[index] & 3));
313
}
314
 
315
static ssize_t store_fan_div(struct device *dev, struct device_attribute
316
        *devattr, const char *buf, size_t count)
317
{
318
        u8 reg;
319
        int index = to_sensor_dev_attr(devattr)->index;
320
        struct fschmd_data *data = dev_get_drvdata(dev);
321
        /* supported values: 2, 4, 8 */
322
        unsigned long v = simple_strtoul(buf, NULL, 10);
323
 
324
        switch (v) {
325
        case 2: v = 1; break;
326
        case 4: v = 2; break;
327
        case 8: v = 3; break;
328
        default:
329
                dev_err(dev, "fan_div value %lu not supported. "
330
                        "Choose one of 2, 4 or 8!\n", v);
331
                return -EINVAL;
332
        }
333
 
334
        mutex_lock(&data->update_lock);
335
 
336
        reg = i2c_smbus_read_byte_data(&data->client,
337
                FSCHMD_REG_FAN_RIPPLE[data->kind][index]);
338
 
339
        /* bits 2..7 reserved => mask with 0x03 */
340
        reg &= ~0x03;
341
        reg |= v;
342
 
343
        i2c_smbus_write_byte_data(&data->client,
344
                FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg);
345
 
346
        data->fan_ripple[index] = reg;
347
 
348
        mutex_unlock(&data->update_lock);
349
 
350
        return count;
351
}
352
 
353
static ssize_t show_fan_alarm(struct device *dev,
354
        struct device_attribute *devattr, char *buf)
355
{
356
        int index = to_sensor_dev_attr(devattr)->index;
357
        struct fschmd_data *data = fschmd_update_device(dev);
358
 
359
        if (data->fan_status[index] & FSCHMD_FAN_ALARM_MASK)
360
                return sprintf(buf, "1\n");
361
        else
362
                return sprintf(buf, "0\n");
363
}
364
 
365
static ssize_t show_fan_fault(struct device *dev,
366
        struct device_attribute *devattr, char *buf)
367
{
368
        int index = to_sensor_dev_attr(devattr)->index;
369
        struct fschmd_data *data = fschmd_update_device(dev);
370
 
371
        if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT_MASK)
372
                return sprintf(buf, "1\n");
373
        else
374
                return sprintf(buf, "0\n");
375
}
376
 
377
 
378
static ssize_t show_pwm_auto_point1_pwm(struct device *dev,
379
        struct device_attribute *devattr, char *buf)
380
{
381
        int index = to_sensor_dev_attr(devattr)->index;
382
        int val = fschmd_update_device(dev)->fan_min[index];
383
 
384
        /* 0 = allow turning off, 1-255 = 50-100% */
385
        if (val)
386
                val = val / 2 + 128;
387
 
388
        return sprintf(buf, "%d\n", val);
389
}
390
 
391
static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
392
        struct device_attribute *devattr, const char *buf, size_t count)
393
{
394
        int index = to_sensor_dev_attr(devattr)->index;
395
        struct fschmd_data *data = dev_get_drvdata(dev);
396
        unsigned long v = simple_strtoul(buf, NULL, 10);
397
 
398
        /* register: 0 = allow turning off, 1-255 = 50-100% */
399
        if (v) {
400
                v = SENSORS_LIMIT(v, 128, 255);
401
                v = (v - 128) * 2 + 1;
402
        }
403
 
404
        mutex_lock(&data->update_lock);
405
 
406
        i2c_smbus_write_byte_data(&data->client,
407
                FSCHMD_REG_FAN_MIN[data->kind][index], v);
408
        data->fan_min[index] = v;
409
 
410
        mutex_unlock(&data->update_lock);
411
 
412
        return count;
413
}
414
 
415
 
416
/* The FSC hwmon family has the ability to force an attached alert led to flash
417
   from software, we export this as an alert_led sysfs attr */
418
static ssize_t show_alert_led(struct device *dev,
419
        struct device_attribute *devattr, char *buf)
420
{
421
        struct fschmd_data *data = fschmd_update_device(dev);
422
 
423
        if (data->global_control & FSCHMD_CONTROL_ALERT_LED_MASK)
424
                return sprintf(buf, "1\n");
425
        else
426
                return sprintf(buf, "0\n");
427
}
428
 
429
static ssize_t store_alert_led(struct device *dev,
430
        struct device_attribute *devattr, const char *buf, size_t count)
431
{
432
        u8 reg;
433
        struct fschmd_data *data = dev_get_drvdata(dev);
434
        unsigned long v = simple_strtoul(buf, NULL, 10);
435
 
436
        mutex_lock(&data->update_lock);
437
 
438
        reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL);
439
 
440
        if (v)
441
                reg |= FSCHMD_CONTROL_ALERT_LED_MASK;
442
        else
443
                reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK;
444
 
445
        i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg);
446
 
447
        data->global_control = reg;
448
 
449
        mutex_unlock(&data->update_lock);
450
 
451
        return count;
452
}
453
 
454
static struct sensor_device_attribute fschmd_attr[] = {
455
        SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0),
456
        SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1),
457
        SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2),
458
        SENSOR_ATTR(alert_led, 0644, show_alert_led, store_alert_led, 0),
459
};
460
 
461
static struct sensor_device_attribute fschmd_temp_attr[] = {
462
        SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0),
463
        SENSOR_ATTR(temp1_max,   0644, show_temp_max, store_temp_max, 0),
464
        SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0),
465
        SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0),
466
        SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1),
467
        SENSOR_ATTR(temp2_max,   0644, show_temp_max, store_temp_max, 1),
468
        SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1),
469
        SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1),
470
        SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2),
471
        SENSOR_ATTR(temp3_max,   0644, show_temp_max, store_temp_max, 2),
472
        SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2),
473
        SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2),
474
        SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3),
475
        SENSOR_ATTR(temp4_max,   0644, show_temp_max, store_temp_max, 3),
476
        SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3),
477
        SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3),
478
        SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4),
479
        SENSOR_ATTR(temp5_max,   0644, show_temp_max, store_temp_max, 4),
480
        SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4),
481
        SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4),
482
};
483
 
484
static struct sensor_device_attribute fschmd_fan_attr[] = {
485
        SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0),
486
        SENSOR_ATTR(fan1_div,   0644, show_fan_div, store_fan_div, 0),
487
        SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0),
488
        SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0),
489
        SENSOR_ATTR(pwm1_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
490
                store_pwm_auto_point1_pwm, 0),
491
        SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1),
492
        SENSOR_ATTR(fan2_div,   0644, show_fan_div, store_fan_div, 1),
493
        SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1),
494
        SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1),
495
        SENSOR_ATTR(pwm2_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
496
                store_pwm_auto_point1_pwm, 1),
497
        SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2),
498
        SENSOR_ATTR(fan3_div,   0644, show_fan_div, store_fan_div, 2),
499
        SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2),
500
        SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2),
501
        SENSOR_ATTR(pwm3_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
502
                store_pwm_auto_point1_pwm, 2),
503
        SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3),
504
        SENSOR_ATTR(fan4_div,   0644, show_fan_div, store_fan_div, 3),
505
        SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3),
506
        SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3),
507
        SENSOR_ATTR(pwm4_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
508
                store_pwm_auto_point1_pwm, 3),
509
        SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4),
510
        SENSOR_ATTR(fan5_div,   0644, show_fan_div, store_fan_div, 4),
511
        SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4),
512
        SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4),
513
        SENSOR_ATTR(pwm5_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
514
                store_pwm_auto_point1_pwm, 4),
515
        SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5),
516
        SENSOR_ATTR(fan6_div,   0644, show_fan_div, store_fan_div, 5),
517
        SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5),
518
        SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5),
519
        SENSOR_ATTR(pwm6_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm,
520
                store_pwm_auto_point1_pwm, 5),
521
};
522
 
523
 
524
/*
525
 * Real code
526
 */
527
 
528
static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind)
529
{
530
        struct i2c_client *client;
531
        struct fschmd_data *data;
532
        u8 revision;
533
        const char * const names[5] = { "Poseidon", "Hermes", "Scylla",
534
                                        "Heracles", "Heimdall" };
535
        const char * const client_names[5] = { "fscpos", "fscher", "fscscy",
536
                                                "fschrc", "fschmd" };
537
        int i, err = 0;
538
 
539
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
540
                return 0;
541
 
542
        /* OK. For now, we presume we have a valid client. We now create the
543
         * client structure, even though we cannot fill it completely yet.
544
         * But it allows us to access i2c_smbus_read_byte_data. */
545
        if (!(data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL)))
546
                return -ENOMEM;
547
 
548
        client = &data->client;
549
        i2c_set_clientdata(client, data);
550
        client->addr = address;
551
        client->adapter = adapter;
552
        client->driver = &fschmd_driver;
553
        mutex_init(&data->update_lock);
554
 
555
        /* Detect & Identify the chip */
556
        if (kind <= 0) {
557
                char id[4];
558
 
559
                id[0] = i2c_smbus_read_byte_data(client,
560
                                FSCHMD_REG_IDENT_0);
561
                id[1] = i2c_smbus_read_byte_data(client,
562
                                FSCHMD_REG_IDENT_1);
563
                id[2] = i2c_smbus_read_byte_data(client,
564
                                FSCHMD_REG_IDENT_2);
565
                id[3] = '\0';
566
 
567
                if (!strcmp(id, "PEG"))
568
                        kind = fscpos;
569
                else if (!strcmp(id, "HER"))
570
                        kind = fscher;
571
                else if (!strcmp(id, "SCY"))
572
                        kind = fscscy;
573
                else if (!strcmp(id, "HRC"))
574
                        kind = fschrc;
575
                else if (!strcmp(id, "HMD"))
576
                        kind = fschmd;
577
                else
578
                        goto exit_free;
579
        }
580
 
581
        if (kind == fscpos) {
582
                /* The Poseidon has hardwired temp limits, fill these
583
                   in for the alarm resetting code */
584
                data->temp_max[0] = 70 + 128;
585
                data->temp_max[1] = 50 + 128;
586
                data->temp_max[2] = 50 + 128;
587
        }
588
 
589
        /* i2c kind goes from 1-5, we want from 0-4 to address arrays */
590
        data->kind = kind - 1;
591
        strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE);
592
 
593
        /* Tell the I2C layer a new client has arrived */
594
        if ((err = i2c_attach_client(client)))
595
                goto exit_free;
596
 
597
        for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) {
598
                err = device_create_file(&client->dev,
599
                                        &fschmd_attr[i].dev_attr);
600
                if (err)
601
                        goto exit_detach;
602
        }
603
 
604
        for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) {
605
                /* Poseidon doesn't have TEMP_LIMIT registers */
606
                if (kind == fscpos && fschmd_temp_attr[i].dev_attr.show ==
607
                                show_temp_max)
608
                        continue;
609
 
610
                err = device_create_file(&client->dev,
611
                                        &fschmd_temp_attr[i].dev_attr);
612
                if (err)
613
                        goto exit_detach;
614
        }
615
 
616
        for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++) {
617
                /* Poseidon doesn't have a FAN_MIN register for its 3rd fan */
618
                if (kind == fscpos &&
619
                                !strcmp(fschmd_fan_attr[i].dev_attr.attr.name,
620
                                        "pwm3_auto_point1_pwm"))
621
                        continue;
622
 
623
                err = device_create_file(&client->dev,
624
                                        &fschmd_fan_attr[i].dev_attr);
625
                if (err)
626
                        goto exit_detach;
627
        }
628
 
629
        data->hwmon_dev = hwmon_device_register(&client->dev);
630
        if (IS_ERR(data->hwmon_dev)) {
631
                err = PTR_ERR(data->hwmon_dev);
632
                data->hwmon_dev = NULL;
633
                goto exit_detach;
634
        }
635
 
636
        revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
637
        printk(KERN_INFO FSCHMD_NAME ": Detected FSC %s chip, revision: %d\n",
638
                names[data->kind], (int) revision);
639
 
640
        return 0;
641
 
642
exit_detach:
643
        fschmd_detach_client(client); /* will also free data for us */
644
        return err;
645
 
646
exit_free:
647
        kfree(data);
648
        return err;
649
}
650
 
651
static int fschmd_attach_adapter(struct i2c_adapter *adapter)
652
{
653
        if (!(adapter->class & I2C_CLASS_HWMON))
654
                return 0;
655
        return i2c_probe(adapter, &addr_data, fschmd_detect);
656
}
657
 
658
static int fschmd_detach_client(struct i2c_client *client)
659
{
660
        struct fschmd_data *data = i2c_get_clientdata(client);
661
        int i, err;
662
 
663
        /* Check if registered in case we're called from fschmd_detect
664
           to cleanup after an error */
665
        if (data->hwmon_dev)
666
                hwmon_device_unregister(data->hwmon_dev);
667
 
668
        for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++)
669
                device_remove_file(&client->dev, &fschmd_attr[i].dev_attr);
670
        for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++)
671
                device_remove_file(&client->dev,
672
                                        &fschmd_temp_attr[i].dev_attr);
673
        for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++)
674
                device_remove_file(&client->dev,
675
                                        &fschmd_fan_attr[i].dev_attr);
676
 
677
        if ((err = i2c_detach_client(client)))
678
                return err;
679
 
680
        kfree(data);
681
        return 0;
682
}
683
 
684
static struct fschmd_data *fschmd_update_device(struct device *dev)
685
{
686
        struct i2c_client *client = to_i2c_client(dev);
687
        struct fschmd_data *data = i2c_get_clientdata(client);
688
        int i;
689
 
690
        mutex_lock(&data->update_lock);
691
 
692
        if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
693
 
694
                for (i = 0; i < FSCHMD_NO_TEMP_SENSORS[data->kind]; i++) {
695
                        data->temp_act[i] = i2c_smbus_read_byte_data(client,
696
                                        FSCHMD_REG_TEMP_ACT[data->kind][i]);
697
                        data->temp_status[i] = i2c_smbus_read_byte_data(client,
698
                                        FSCHMD_REG_TEMP_STATE[data->kind][i]);
699
 
700
                        /* The fscpos doesn't have TEMP_LIMIT registers */
701
                        if (FSCHMD_REG_TEMP_LIMIT[data->kind][i])
702
                                data->temp_max[i] = i2c_smbus_read_byte_data(
703
                                        client,
704
                                        FSCHMD_REG_TEMP_LIMIT[data->kind][i]);
705
 
706
                        /* reset alarm if the alarm condition is gone,
707
                           the chip doesn't do this itself */
708
                        if ((data->temp_status[i] & FSCHMD_TEMP_ALARM_MASK) ==
709
                                        FSCHMD_TEMP_ALARM_MASK &&
710
                                        data->temp_act[i] < data->temp_max[i])
711
                                i2c_smbus_write_byte_data(client,
712
                                        FSCHMD_REG_TEMP_STATE[data->kind][i],
713
                                        FSCHMD_TEMP_ALERT_MASK);
714
                }
715
 
716
                for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) {
717
                        data->fan_act[i] = i2c_smbus_read_byte_data(client,
718
                                        FSCHMD_REG_FAN_ACT[data->kind][i]);
719
                        data->fan_status[i] = i2c_smbus_read_byte_data(client,
720
                                        FSCHMD_REG_FAN_STATE[data->kind][i]);
721
                        data->fan_ripple[i] = i2c_smbus_read_byte_data(client,
722
                                        FSCHMD_REG_FAN_RIPPLE[data->kind][i]);
723
 
724
                        /* The fscpos third fan doesn't have a fan_min */
725
                        if (FSCHMD_REG_FAN_MIN[data->kind][i])
726
                                data->fan_min[i] = i2c_smbus_read_byte_data(
727
                                        client,
728
                                        FSCHMD_REG_FAN_MIN[data->kind][i]);
729
 
730
                        /* reset fan status if speed is back to > 0 */
731
                        if ((data->fan_status[i] & FSCHMD_FAN_ALARM_MASK) &&
732
                                        data->fan_act[i])
733
                                i2c_smbus_write_byte_data(client,
734
                                        FSCHMD_REG_FAN_STATE[data->kind][i],
735
                                        FSCHMD_FAN_ALARM_MASK);
736
                }
737
 
738
                for (i = 0; i < 3; i++)
739
                        data->volt[i] = i2c_smbus_read_byte_data(client,
740
                                                FSCHMD_REG_VOLT[i]);
741
 
742
                data->global_control = i2c_smbus_read_byte_data(client,
743
                                                FSCHMD_REG_CONTROL);
744
 
745
                /* To be implemented in the future
746
                data->watchdog[0] = i2c_smbus_read_byte_data(client,
747
                                                FSCHMD_REG_WDOG_PRESET);
748
                data->watchdog[1] = i2c_smbus_read_byte_data(client,
749
                                                FSCHMD_REG_WDOG_STATE);
750
                data->watchdog[2] = i2c_smbus_read_byte_data(client,
751
                                                FSCHMD_REG_WDOG_CONTROL); */
752
 
753
                data->last_updated = jiffies;
754
                data->valid = 1;
755
        }
756
 
757
        mutex_unlock(&data->update_lock);
758
 
759
        return data;
760
}
761
 
762
static int __init fschmd_init(void)
763
{
764
        return i2c_add_driver(&fschmd_driver);
765
}
766
 
767
static void __exit fschmd_exit(void)
768
{
769
        i2c_del_driver(&fschmd_driver);
770
}
771
 
772
MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
773
MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and "
774
                        "Heimdall driver");
775
MODULE_LICENSE("GPL");
776
 
777
module_init(fschmd_init);
778
module_exit(fschmd_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.