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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [hwmon/] [gl520sm.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
    gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
3
                monitoring
4
    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
5
                              Kyösti Mälkki <kmalkki@cc.hut.fi>
6
    Copyright (c) 2005        Maarten Deprez <maartendeprez@users.sourceforge.net>
7
 
8
    This program is free software; you can redistribute it and/or modify
9
    it under the terms of the GNU General Public License as published by
10
    the Free Software Foundation; either version 2 of the License, or
11
    (at your option) any later version.
12
 
13
    This program is distributed in the hope that it will be useful,
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
    GNU General Public License for more details.
17
 
18
    You should have received a copy of the GNU General Public License
19
    along with this program; if not, write to the Free Software
20
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 
22
*/
23
 
24
#include <linux/module.h>
25
#include <linux/init.h>
26
#include <linux/slab.h>
27
#include <linux/jiffies.h>
28
#include <linux/i2c.h>
29
#include <linux/hwmon.h>
30
#include <linux/hwmon-vid.h>
31
#include <linux/err.h>
32
#include <linux/mutex.h>
33
#include <linux/sysfs.h>
34
 
35
/* Type of the extra sensor */
36
static unsigned short extra_sensor_type;
37
module_param(extra_sensor_type, ushort, 0);
38
MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=temperature, 2=voltage)");
39
 
40
/* Addresses to scan */
41
static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
42
 
43
/* Insmod parameters */
44
I2C_CLIENT_INSMOD_1(gl520sm);
45
 
46
/* Many GL520 constants specified below
47
One of the inputs can be configured as either temp or voltage.
48
That's why _TEMP2 and _IN4 access the same register
49
*/
50
 
51
/* The GL520 registers */
52
#define GL520_REG_CHIP_ID               0x00
53
#define GL520_REG_REVISION              0x01
54
#define GL520_REG_CONF                  0x03
55
#define GL520_REG_MASK                  0x11
56
 
57
#define GL520_REG_VID_INPUT             0x02
58
 
59
#define GL520_REG_IN0_INPUT             0x15
60
#define GL520_REG_IN0_LIMIT             0x0c
61
#define GL520_REG_IN0_MIN               GL520_REG_IN0_LIMIT
62
#define GL520_REG_IN0_MAX               GL520_REG_IN0_LIMIT
63
 
64
#define GL520_REG_IN1_INPUT             0x14
65
#define GL520_REG_IN1_LIMIT             0x09
66
#define GL520_REG_IN1_MIN               GL520_REG_IN1_LIMIT
67
#define GL520_REG_IN1_MAX               GL520_REG_IN1_LIMIT
68
 
69
#define GL520_REG_IN2_INPUT             0x13
70
#define GL520_REG_IN2_LIMIT             0x0a
71
#define GL520_REG_IN2_MIN               GL520_REG_IN2_LIMIT
72
#define GL520_REG_IN2_MAX               GL520_REG_IN2_LIMIT
73
 
74
#define GL520_REG_IN3_INPUT             0x0d
75
#define GL520_REG_IN3_LIMIT             0x0b
76
#define GL520_REG_IN3_MIN               GL520_REG_IN3_LIMIT
77
#define GL520_REG_IN3_MAX               GL520_REG_IN3_LIMIT
78
 
79
#define GL520_REG_IN4_INPUT             0x0e
80
#define GL520_REG_IN4_MAX               0x17
81
#define GL520_REG_IN4_MIN               0x18
82
 
83
#define GL520_REG_TEMP1_INPUT           0x04
84
#define GL520_REG_TEMP1_MAX             0x05
85
#define GL520_REG_TEMP1_MAX_HYST        0x06
86
 
87
#define GL520_REG_TEMP2_INPUT           0x0e
88
#define GL520_REG_TEMP2_MAX             0x17
89
#define GL520_REG_TEMP2_MAX_HYST        0x18
90
 
91
#define GL520_REG_FAN_INPUT             0x07
92
#define GL520_REG_FAN_MIN               0x08
93
#define GL520_REG_FAN_DIV               0x0f
94
#define GL520_REG_FAN_OFF               GL520_REG_FAN_DIV
95
 
96
#define GL520_REG_ALARMS                0x12
97
#define GL520_REG_BEEP_MASK             0x10
98
#define GL520_REG_BEEP_ENABLE           GL520_REG_CONF
99
 
100
/*
101
 * Function declarations
102
 */
103
 
104
static int gl520_attach_adapter(struct i2c_adapter *adapter);
105
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind);
106
static void gl520_init_client(struct i2c_client *client);
107
static int gl520_detach_client(struct i2c_client *client);
108
static int gl520_read_value(struct i2c_client *client, u8 reg);
109
static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
110
static struct gl520_data *gl520_update_device(struct device *dev);
111
 
112
/* Driver data */
113
static struct i2c_driver gl520_driver = {
114
        .driver = {
115
                .name   = "gl520sm",
116
        },
117
        .id             = I2C_DRIVERID_GL520,
118
        .attach_adapter = gl520_attach_adapter,
119
        .detach_client  = gl520_detach_client,
120
};
121
 
122
/* Client data */
123
struct gl520_data {
124
        struct i2c_client client;
125
        struct device *hwmon_dev;
126
        struct mutex update_lock;
127
        char valid;             /* zero until the following fields are valid */
128
        unsigned long last_updated;     /* in jiffies */
129
 
130
        u8 vid;
131
        u8 vrm;
132
        u8 in_input[5];         /* [0] = VVD */
133
        u8 in_min[5];           /* [0] = VDD */
134
        u8 in_max[5];           /* [0] = VDD */
135
        u8 fan_input[2];
136
        u8 fan_min[2];
137
        u8 fan_div[2];
138
        u8 fan_off;
139
        u8 temp_input[2];
140
        u8 temp_max[2];
141
        u8 temp_max_hyst[2];
142
        u8 alarms;
143
        u8 beep_enable;
144
        u8 beep_mask;
145
        u8 alarm_mask;
146
        u8 two_temps;
147
};
148
 
149
/*
150
 * Sysfs stuff
151
 */
152
 
153
#define sysfs_r(type, n, item, reg) \
154
static ssize_t get_##type##item (struct gl520_data *, char *, int); \
155
static ssize_t get_##type##n##item (struct device *, struct device_attribute *attr, char *); \
156
static ssize_t get_##type##n##item (struct device *dev, struct device_attribute *attr, char *buf) \
157
{ \
158
        struct gl520_data *data = gl520_update_device(dev); \
159
        return get_##type##item(data, buf, (n)); \
160
}
161
 
162
#define sysfs_w(type, n, item, reg) \
163
static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \
164
static ssize_t set_##type##n##item (struct device *, struct device_attribute *attr, const char *, size_t); \
165
static ssize_t set_##type##n##item (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
166
{ \
167
        struct i2c_client *client = to_i2c_client(dev); \
168
        struct gl520_data *data = i2c_get_clientdata(client); \
169
        return set_##type##item(client, data, buf, count, (n), reg); \
170
}
171
 
172
#define sysfs_rw_n(type, n, item, reg) \
173
sysfs_r(type, n, item, reg) \
174
sysfs_w(type, n, item, reg) \
175
static DEVICE_ATTR(type##n##item, S_IRUGO | S_IWUSR, get_##type##n##item, set_##type##n##item);
176
 
177
#define sysfs_ro_n(type, n, item, reg) \
178
sysfs_r(type, n, item, reg) \
179
static DEVICE_ATTR(type##n##item, S_IRUGO, get_##type##n##item, NULL);
180
 
181
#define sysfs_rw(type, item, reg) \
182
sysfs_r(type, 0, item, reg) \
183
sysfs_w(type, 0, item, reg) \
184
static DEVICE_ATTR(type##item, S_IRUGO | S_IWUSR, get_##type##0##item, set_##type##0##item);
185
 
186
#define sysfs_ro(type, item, reg) \
187
sysfs_r(type, 0, item, reg) \
188
static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL);
189
 
190
 
191
#define sysfs_vid(n) \
192
sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT)
193
 
194
#define sysfs_in(n) \
195
sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \
196
sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \
197
sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \
198
 
199
#define sysfs_fan(n) \
200
sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \
201
sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \
202
sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV)
203
 
204
#define sysfs_fan_off(n) \
205
sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \
206
 
207
#define sysfs_temp(n) \
208
sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \
209
sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \
210
sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST)
211
 
212
#define sysfs_alarms() \
213
sysfs_ro(alarms, , GL520_REG_ALARMS) \
214
sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \
215
sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK)
216
 
217
 
218
sysfs_vid(0)
219
 
220
sysfs_in(0)
221
sysfs_in(1)
222
sysfs_in(2)
223
sysfs_in(3)
224
sysfs_in(4)
225
 
226
sysfs_fan(1)
227
sysfs_fan(2)
228
sysfs_fan_off(1)
229
 
230
sysfs_temp(1)
231
sysfs_temp(2)
232
 
233
sysfs_alarms()
234
 
235
 
236
static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n)
237
{
238
        return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
239
}
240
 
241
#define VDD_FROM_REG(val) (((val)*95+2)/4)
242
#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255))
243
 
244
#define IN_FROM_REG(val) ((val)*19)
245
#define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255))
246
 
247
static ssize_t get_in_input(struct gl520_data *data, char *buf, int n)
248
{
249
        u8 r = data->in_input[n];
250
 
251
        if (n == 0)
252
                return sprintf(buf, "%d\n", VDD_FROM_REG(r));
253
        else
254
                return sprintf(buf, "%d\n", IN_FROM_REG(r));
255
}
256
 
257
static ssize_t get_in_min(struct gl520_data *data, char *buf, int n)
258
{
259
        u8 r = data->in_min[n];
260
 
261
        if (n == 0)
262
                return sprintf(buf, "%d\n", VDD_FROM_REG(r));
263
        else
264
                return sprintf(buf, "%d\n", IN_FROM_REG(r));
265
}
266
 
267
static ssize_t get_in_max(struct gl520_data *data, char *buf, int n)
268
{
269
        u8 r = data->in_max[n];
270
 
271
        if (n == 0)
272
                return sprintf(buf, "%d\n", VDD_FROM_REG(r));
273
        else
274
                return sprintf(buf, "%d\n", IN_FROM_REG(r));
275
}
276
 
277
static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
278
{
279
        long v = simple_strtol(buf, NULL, 10);
280
        u8 r;
281
 
282
        mutex_lock(&data->update_lock);
283
 
284
        if (n == 0)
285
                r = VDD_TO_REG(v);
286
        else
287
                r = IN_TO_REG(v);
288
 
289
        data->in_min[n] = r;
290
 
291
        if (n < 4)
292
                gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
293
        else
294
                gl520_write_value(client, reg, r);
295
 
296
        mutex_unlock(&data->update_lock);
297
        return count;
298
}
299
 
300
static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
301
{
302
        long v = simple_strtol(buf, NULL, 10);
303
        u8 r;
304
 
305
        if (n == 0)
306
                r = VDD_TO_REG(v);
307
        else
308
                r = IN_TO_REG(v);
309
 
310
        mutex_lock(&data->update_lock);
311
 
312
        data->in_max[n] = r;
313
 
314
        if (n < 4)
315
                gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
316
        else
317
                gl520_write_value(client, reg, r);
318
 
319
        mutex_unlock(&data->update_lock);
320
        return count;
321
}
322
 
323
#define DIV_FROM_REG(val) (1 << (val))
324
#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div))))
325
#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255));
326
 
327
static ssize_t get_fan_input(struct gl520_data *data, char *buf, int n)
328
{
329
        return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n - 1], data->fan_div[n - 1]));
330
}
331
 
332
static ssize_t get_fan_min(struct gl520_data *data, char *buf, int n)
333
{
334
        return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n - 1], data->fan_div[n - 1]));
335
}
336
 
337
static ssize_t get_fan_div(struct gl520_data *data, char *buf, int n)
338
{
339
        return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n - 1]));
340
}
341
 
342
static ssize_t get_fan_off(struct gl520_data *data, char *buf, int n)
343
{
344
        return sprintf(buf, "%d\n", data->fan_off);
345
}
346
 
347
static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
348
{
349
        unsigned long v = simple_strtoul(buf, NULL, 10);
350
        u8 r;
351
 
352
        mutex_lock(&data->update_lock);
353
        r = FAN_TO_REG(v, data->fan_div[n - 1]);
354
        data->fan_min[n - 1] = r;
355
 
356
        if (n == 1)
357
                gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
358
        else
359
                gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
360
 
361
        data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
362
        if (data->fan_min[n - 1] == 0)
363
                data->alarm_mask &= (n == 1) ? ~0x20 : ~0x40;
364
        else
365
                data->alarm_mask |= (n == 1) ? 0x20 : 0x40;
366
        data->beep_mask &= data->alarm_mask;
367
        gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
368
 
369
        mutex_unlock(&data->update_lock);
370
        return count;
371
}
372
 
373
static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
374
{
375
        unsigned long v = simple_strtoul(buf, NULL, 10);
376
        u8 r;
377
 
378
        switch (v) {
379
        case 1: r = 0; break;
380
        case 2: r = 1; break;
381
        case 4: r = 2; break;
382
        case 8: r = 3; break;
383
        default:
384
                dev_err(&client->dev, "fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", v);
385
                return -EINVAL;
386
        }
387
 
388
        mutex_lock(&data->update_lock);
389
        data->fan_div[n - 1] = r;
390
 
391
        if (n == 1)
392
                gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xc0) | (r << 6));
393
        else
394
                gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4));
395
 
396
        mutex_unlock(&data->update_lock);
397
        return count;
398
}
399
 
400
static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
401
{
402
        u8 r = simple_strtoul(buf, NULL, 10)?1:0;
403
 
404
        mutex_lock(&data->update_lock);
405
        data->fan_off = r;
406
        gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2));
407
        mutex_unlock(&data->update_lock);
408
        return count;
409
}
410
 
411
#define TEMP_FROM_REG(val) (((val) - 130) * 1000)
412
#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-500:(val)+500) / 1000)+130),0,255))
413
 
414
static ssize_t get_temp_input(struct gl520_data *data, char *buf, int n)
415
{
416
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n - 1]));
417
}
418
 
419
static ssize_t get_temp_max(struct gl520_data *data, char *buf, int n)
420
{
421
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n - 1]));
422
}
423
 
424
static ssize_t get_temp_max_hyst(struct gl520_data *data, char *buf, int n)
425
{
426
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n - 1]));
427
}
428
 
429
static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
430
{
431
        long v = simple_strtol(buf, NULL, 10);
432
 
433
        mutex_lock(&data->update_lock);
434
        data->temp_max[n - 1] = TEMP_TO_REG(v);
435
        gl520_write_value(client, reg, data->temp_max[n - 1]);
436
        mutex_unlock(&data->update_lock);
437
        return count;
438
}
439
 
440
static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
441
{
442
        long v = simple_strtol(buf, NULL, 10);
443
 
444
        mutex_lock(&data->update_lock);
445
        data->temp_max_hyst[n - 1] = TEMP_TO_REG(v);
446
        gl520_write_value(client, reg, data->temp_max_hyst[n - 1]);
447
        mutex_unlock(&data->update_lock);
448
        return count;
449
}
450
 
451
static ssize_t get_alarms(struct gl520_data *data, char *buf, int n)
452
{
453
        return sprintf(buf, "%d\n", data->alarms);
454
}
455
 
456
static ssize_t get_beep_enable(struct gl520_data *data, char *buf, int n)
457
{
458
        return sprintf(buf, "%d\n", data->beep_enable);
459
}
460
 
461
static ssize_t get_beep_mask(struct gl520_data *data, char *buf, int n)
462
{
463
        return sprintf(buf, "%d\n", data->beep_mask);
464
}
465
 
466
static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
467
{
468
        u8 r = simple_strtoul(buf, NULL, 10)?0:1;
469
 
470
        mutex_lock(&data->update_lock);
471
        data->beep_enable = !r;
472
        gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2));
473
        mutex_unlock(&data->update_lock);
474
        return count;
475
}
476
 
477
static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
478
{
479
        u8 r = simple_strtoul(buf, NULL, 10);
480
 
481
        mutex_lock(&data->update_lock);
482
        r &= data->alarm_mask;
483
        data->beep_mask = r;
484
        gl520_write_value(client, reg, r);
485
        mutex_unlock(&data->update_lock);
486
        return count;
487
}
488
 
489
static struct attribute *gl520_attributes[] = {
490
        &dev_attr_cpu0_vid.attr,
491
 
492
        &dev_attr_in0_input.attr,
493
        &dev_attr_in0_min.attr,
494
        &dev_attr_in0_max.attr,
495
        &dev_attr_in1_input.attr,
496
        &dev_attr_in1_min.attr,
497
        &dev_attr_in1_max.attr,
498
        &dev_attr_in2_input.attr,
499
        &dev_attr_in2_min.attr,
500
        &dev_attr_in2_max.attr,
501
        &dev_attr_in3_input.attr,
502
        &dev_attr_in3_min.attr,
503
        &dev_attr_in3_max.attr,
504
 
505
        &dev_attr_fan1_input.attr,
506
        &dev_attr_fan1_min.attr,
507
        &dev_attr_fan1_div.attr,
508
        &dev_attr_fan1_off.attr,
509
        &dev_attr_fan2_input.attr,
510
        &dev_attr_fan2_min.attr,
511
        &dev_attr_fan2_div.attr,
512
 
513
        &dev_attr_temp1_input.attr,
514
        &dev_attr_temp1_max.attr,
515
        &dev_attr_temp1_max_hyst.attr,
516
 
517
        &dev_attr_alarms.attr,
518
        &dev_attr_beep_enable.attr,
519
        &dev_attr_beep_mask.attr,
520
        NULL
521
};
522
 
523
static const struct attribute_group gl520_group = {
524
        .attrs = gl520_attributes,
525
};
526
 
527
static struct attribute *gl520_attributes_opt[] = {
528
        &dev_attr_in4_input.attr,
529
        &dev_attr_in4_min.attr,
530
        &dev_attr_in4_max.attr,
531
 
532
        &dev_attr_temp2_input.attr,
533
        &dev_attr_temp2_max.attr,
534
        &dev_attr_temp2_max_hyst.attr,
535
        NULL
536
};
537
 
538
static const struct attribute_group gl520_group_opt = {
539
        .attrs = gl520_attributes_opt,
540
};
541
 
542
 
543
/*
544
 * Real code
545
 */
546
 
547
static int gl520_attach_adapter(struct i2c_adapter *adapter)
548
{
549
        if (!(adapter->class & I2C_CLASS_HWMON))
550
                return 0;
551
        return i2c_probe(adapter, &addr_data, gl520_detect);
552
}
553
 
554
static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
555
{
556
        struct i2c_client *new_client;
557
        struct gl520_data *data;
558
        int err = 0;
559
 
560
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
561
                                     I2C_FUNC_SMBUS_WORD_DATA))
562
                goto exit;
563
 
564
        /* OK. For now, we presume we have a valid client. We now create the
565
           client structure, even though we cannot fill it completely yet.
566
           But it allows us to access gl520_{read,write}_value. */
567
 
568
        if (!(data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
569
                err = -ENOMEM;
570
                goto exit;
571
        }
572
 
573
        new_client = &data->client;
574
        i2c_set_clientdata(new_client, data);
575
        new_client->addr = address;
576
        new_client->adapter = adapter;
577
        new_client->driver = &gl520_driver;
578
        new_client->flags = 0;
579
 
580
        /* Determine the chip type. */
581
        if (kind < 0) {
582
                if ((gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) ||
583
                    ((gl520_read_value(new_client, GL520_REG_REVISION) & 0x7f) != 0x00) ||
584
                    ((gl520_read_value(new_client, GL520_REG_CONF) & 0x80) != 0x00)) {
585
                        dev_dbg(&new_client->dev, "Unknown chip type, skipping\n");
586
                        goto exit_free;
587
                }
588
        }
589
 
590
        /* Fill in the remaining client fields */
591
        strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE);
592
        data->valid = 0;
593
        mutex_init(&data->update_lock);
594
 
595
        /* Tell the I2C layer a new client has arrived */
596
        if ((err = i2c_attach_client(new_client)))
597
                goto exit_free;
598
 
599
        /* Initialize the GL520SM chip */
600
        gl520_init_client(new_client);
601
 
602
        /* Register sysfs hooks */
603
        if ((err = sysfs_create_group(&new_client->dev.kobj, &gl520_group)))
604
                goto exit_detach;
605
 
606
        if (data->two_temps) {
607
                if ((err = device_create_file(&new_client->dev,
608
                                              &dev_attr_temp2_input))
609
                 || (err = device_create_file(&new_client->dev,
610
                                              &dev_attr_temp2_max))
611
                 || (err = device_create_file(&new_client->dev,
612
                                              &dev_attr_temp2_max_hyst)))
613
                        goto exit_remove_files;
614
        } else {
615
                if ((err = device_create_file(&new_client->dev,
616
                                              &dev_attr_in4_input))
617
                 || (err = device_create_file(&new_client->dev,
618
                                              &dev_attr_in4_min))
619
                 || (err = device_create_file(&new_client->dev,
620
                                              &dev_attr_in4_max)))
621
                        goto exit_remove_files;
622
        }
623
 
624
 
625
        data->hwmon_dev = hwmon_device_register(&new_client->dev);
626
        if (IS_ERR(data->hwmon_dev)) {
627
                err = PTR_ERR(data->hwmon_dev);
628
                goto exit_remove_files;
629
        }
630
 
631
        return 0;
632
 
633
exit_remove_files:
634
        sysfs_remove_group(&new_client->dev.kobj, &gl520_group);
635
        sysfs_remove_group(&new_client->dev.kobj, &gl520_group_opt);
636
exit_detach:
637
        i2c_detach_client(new_client);
638
exit_free:
639
        kfree(data);
640
exit:
641
        return err;
642
}
643
 
644
 
645
/* Called when we have found a new GL520SM. */
646
static void gl520_init_client(struct i2c_client *client)
647
{
648
        struct gl520_data *data = i2c_get_clientdata(client);
649
        u8 oldconf, conf;
650
 
651
        conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
652
 
653
        data->alarm_mask = 0xff;
654
        data->vrm = vid_which_vrm();
655
 
656
        if (extra_sensor_type == 1)
657
                conf &= ~0x10;
658
        else if (extra_sensor_type == 2)
659
                conf |= 0x10;
660
        data->two_temps = !(conf & 0x10);
661
 
662
        /* If IRQ# is disabled, we can safely force comparator mode */
663
        if (!(conf & 0x20))
664
                conf &= 0xf7;
665
 
666
        /* Enable monitoring if needed */
667
        conf |= 0x40;
668
 
669
        if (conf != oldconf)
670
                gl520_write_value(client, GL520_REG_CONF, conf);
671
 
672
        gl520_update_device(&(client->dev));
673
 
674
        if (data->fan_min[0] == 0)
675
                data->alarm_mask &= ~0x20;
676
        if (data->fan_min[1] == 0)
677
                data->alarm_mask &= ~0x40;
678
 
679
        data->beep_mask &= data->alarm_mask;
680
        gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
681
}
682
 
683
static int gl520_detach_client(struct i2c_client *client)
684
{
685
        struct gl520_data *data = i2c_get_clientdata(client);
686
        int err;
687
 
688
        hwmon_device_unregister(data->hwmon_dev);
689
        sysfs_remove_group(&client->dev.kobj, &gl520_group);
690
        sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
691
 
692
        if ((err = i2c_detach_client(client)))
693
                return err;
694
 
695
        kfree(data);
696
        return 0;
697
}
698
 
699
 
700
/* Registers 0x07 to 0x0c are word-sized, others are byte-sized
701
   GL520 uses a high-byte first convention */
702
static int gl520_read_value(struct i2c_client *client, u8 reg)
703
{
704
        if ((reg >= 0x07) && (reg <= 0x0c))
705
                return swab16(i2c_smbus_read_word_data(client, reg));
706
        else
707
                return i2c_smbus_read_byte_data(client, reg);
708
}
709
 
710
static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
711
{
712
        if ((reg >= 0x07) && (reg <= 0x0c))
713
                return i2c_smbus_write_word_data(client, reg, swab16(value));
714
        else
715
                return i2c_smbus_write_byte_data(client, reg, value);
716
}
717
 
718
 
719
static struct gl520_data *gl520_update_device(struct device *dev)
720
{
721
        struct i2c_client *client = to_i2c_client(dev);
722
        struct gl520_data *data = i2c_get_clientdata(client);
723
        int val;
724
 
725
        mutex_lock(&data->update_lock);
726
 
727
        if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
728
 
729
                dev_dbg(&client->dev, "Starting gl520sm update\n");
730
 
731
                data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
732
                data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
733
                data->vid = gl520_read_value(client, GL520_REG_VID_INPUT) & 0x1f;
734
 
735
                val = gl520_read_value(client, GL520_REG_IN0_LIMIT);
736
                data->in_min[0] = val & 0xff;
737
                data->in_max[0] = (val >> 8) & 0xff;
738
                val = gl520_read_value(client, GL520_REG_IN1_LIMIT);
739
                data->in_min[1] = val & 0xff;
740
                data->in_max[1] = (val >> 8) & 0xff;
741
                val = gl520_read_value(client, GL520_REG_IN2_LIMIT);
742
                data->in_min[2] = val & 0xff;
743
                data->in_max[2] = (val >> 8) & 0xff;
744
                val = gl520_read_value(client, GL520_REG_IN3_LIMIT);
745
                data->in_min[3] = val & 0xff;
746
                data->in_max[3] = (val >> 8) & 0xff;
747
 
748
                val = gl520_read_value(client, GL520_REG_FAN_INPUT);
749
                data->fan_input[0] = (val >> 8) & 0xff;
750
                data->fan_input[1] = val & 0xff;
751
 
752
                val = gl520_read_value(client, GL520_REG_FAN_MIN);
753
                data->fan_min[0] = (val >> 8) & 0xff;
754
                data->fan_min[1] = val & 0xff;
755
 
756
                data->temp_input[0] = gl520_read_value(client, GL520_REG_TEMP1_INPUT);
757
                data->temp_max[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX);
758
                data->temp_max_hyst[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX_HYST);
759
 
760
                val = gl520_read_value(client, GL520_REG_FAN_DIV);
761
                data->fan_div[0] = (val >> 6) & 0x03;
762
                data->fan_div[1] = (val >> 4) & 0x03;
763
                data->fan_off = (val >> 2) & 0x01;
764
 
765
                data->alarms &= data->alarm_mask;
766
 
767
                val = gl520_read_value(client, GL520_REG_CONF);
768
                data->beep_enable = !((val >> 2) & 1);
769
 
770
                data->in_input[0] = gl520_read_value(client, GL520_REG_IN0_INPUT);
771
                data->in_input[1] = gl520_read_value(client, GL520_REG_IN1_INPUT);
772
                data->in_input[2] = gl520_read_value(client, GL520_REG_IN2_INPUT);
773
                data->in_input[3] = gl520_read_value(client, GL520_REG_IN3_INPUT);
774
 
775
                /* Temp1 and Vin4 are the same input */
776
                if (data->two_temps) {
777
                        data->temp_input[1] = gl520_read_value(client, GL520_REG_TEMP2_INPUT);
778
                        data->temp_max[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX);
779
                        data->temp_max_hyst[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX_HYST);
780
                } else {
781
                        data->in_input[4] = gl520_read_value(client, GL520_REG_IN4_INPUT);
782
                        data->in_min[4] = gl520_read_value(client, GL520_REG_IN4_MIN);
783
                        data->in_max[4] = gl520_read_value(client, GL520_REG_IN4_MAX);
784
                }
785
 
786
                data->last_updated = jiffies;
787
                data->valid = 1;
788
        }
789
 
790
        mutex_unlock(&data->update_lock);
791
 
792
        return data;
793
}
794
 
795
 
796
static int __init sensors_gl520sm_init(void)
797
{
798
        return i2c_add_driver(&gl520_driver);
799
}
800
 
801
static void __exit sensors_gl520sm_exit(void)
802
{
803
        i2c_del_driver(&gl520_driver);
804
}
805
 
806
 
807
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
808
        "Kyösti Mälkki <kmalkki@cc.hut.fi>, "
809
        "Maarten Deprez <maartendeprez@users.sourceforge.net>");
810
MODULE_DESCRIPTION("GL520SM driver");
811
MODULE_LICENSE("GPL");
812
 
813
module_init(sensors_gl520sm_init);
814
module_exit(sensors_gl520sm_exit);

powered by: WebSVN 2.1.0

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