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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
3
 *
4
 * Copyright (C) 2006 Corentin LABBE <corentin.labbe@geomatys.fr>
5
 *
6
 * Based on LM83 Driver by Jean Delvare <khali@linux-fr.org>
7
 *
8
 * Give only processor, motherboard temperatures and fan tachs
9
 * Very rare chip please let me know if you use it
10
 *
11
 * http://www.analog.com/UploadedFiles/Data_Sheets/ADM1029.pdf
12
 *
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation version 2 of the License
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
 */
27
 
28
#include <linux/module.h>
29
#include <linux/init.h>
30
#include <linux/slab.h>
31
#include <linux/jiffies.h>
32
#include <linux/i2c.h>
33
#include <linux/hwmon-sysfs.h>
34
#include <linux/hwmon.h>
35
#include <linux/err.h>
36
#include <linux/mutex.h>
37
 
38
/*
39
 * Addresses to scan
40
 */
41
 
42
static unsigned short normal_i2c[] = {
43
        0x28, 0x29, 0x2a,
44
        0x2b, 0x2c, 0x2d,
45
        0x2e, 0x2f, I2C_CLIENT_END
46
};
47
 
48
/*
49
 * Insmod parameters
50
 */
51
 
52
I2C_CLIENT_INSMOD_1(adm1029);
53
 
54
/*
55
 * The ADM1029 registers
56
 * Manufacturer ID is 0x41 for Analog Devices
57
 */
58
 
59
#define ADM1029_REG_MAN_ID                      0x0D
60
#define ADM1029_REG_CHIP_ID                     0x0E
61
#define ADM1029_REG_CONFIG                      0x01
62
#define ADM1029_REG_NB_FAN_SUPPORT              0x02
63
 
64
#define ADM1029_REG_TEMP_DEVICES_INSTALLED      0x06
65
 
66
#define ADM1029_REG_LOCAL_TEMP                  0xA0
67
#define ADM1029_REG_REMOTE1_TEMP                0xA1
68
#define ADM1029_REG_REMOTE2_TEMP                0xA2
69
 
70
#define ADM1029_REG_LOCAL_TEMP_HIGH             0x90
71
#define ADM1029_REG_REMOTE1_TEMP_HIGH           0x91
72
#define ADM1029_REG_REMOTE2_TEMP_HIGH           0x92
73
 
74
#define ADM1029_REG_LOCAL_TEMP_LOW              0x98
75
#define ADM1029_REG_REMOTE1_TEMP_LOW            0x99
76
#define ADM1029_REG_REMOTE2_TEMP_LOW            0x9A
77
 
78
#define ADM1029_REG_FAN1                        0x70
79
#define ADM1029_REG_FAN2                        0x71
80
 
81
#define ADM1029_REG_FAN1_MIN                    0x78
82
#define ADM1029_REG_FAN2_MIN                    0x79
83
 
84
#define ADM1029_REG_FAN1_CONFIG                 0x68
85
#define ADM1029_REG_FAN2_CONFIG                 0x69
86
 
87
#define TEMP_FROM_REG(val)      ((val) * 1000)
88
 
89
#define DIV_FROM_REG(val)       ( 1 << (((val) >> 6) - 1))
90
 
91
/* Registers to be checked by adm1029_update_device() */
92
static const u8 ADM1029_REG_TEMP[] = {
93
        ADM1029_REG_LOCAL_TEMP,
94
        ADM1029_REG_REMOTE1_TEMP,
95
        ADM1029_REG_REMOTE2_TEMP,
96
        ADM1029_REG_LOCAL_TEMP_HIGH,
97
        ADM1029_REG_REMOTE1_TEMP_HIGH,
98
        ADM1029_REG_REMOTE2_TEMP_HIGH,
99
        ADM1029_REG_LOCAL_TEMP_LOW,
100
        ADM1029_REG_REMOTE1_TEMP_LOW,
101
        ADM1029_REG_REMOTE2_TEMP_LOW,
102
};
103
 
104
static const u8 ADM1029_REG_FAN[] = {
105
        ADM1029_REG_FAN1,
106
        ADM1029_REG_FAN2,
107
        ADM1029_REG_FAN1_MIN,
108
        ADM1029_REG_FAN2_MIN,
109
};
110
 
111
static const u8 ADM1029_REG_FAN_DIV[] = {
112
        ADM1029_REG_FAN1_CONFIG,
113
        ADM1029_REG_FAN2_CONFIG,
114
};
115
 
116
/*
117
 * Functions declaration
118
 */
119
 
120
static int adm1029_attach_adapter(struct i2c_adapter *adapter);
121
static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind);
122
static int adm1029_detach_client(struct i2c_client *client);
123
static struct adm1029_data *adm1029_update_device(struct device *dev);
124
static int adm1029_init_client(struct i2c_client *client);
125
 
126
/*
127
 * Driver data (common to all clients)
128
 */
129
 
130
static struct i2c_driver adm1029_driver = {
131
        .driver = {
132
                .name = "adm1029",
133
        },
134
        .attach_adapter = adm1029_attach_adapter,
135
        .detach_client = adm1029_detach_client,
136
};
137
 
138
/*
139
 * Client data (each client gets its own)
140
 */
141
 
142
struct adm1029_data {
143
        struct i2c_client client;
144
        struct device *hwmon_dev;
145
        struct mutex update_lock;
146
        char valid;             /* zero until following fields are valid */
147
        unsigned long last_updated;     /* in jiffies */
148
 
149
        /* registers values, signed for temperature, unsigned for other stuff */
150
        s8 temp[ARRAY_SIZE(ADM1029_REG_TEMP)];
151
        u8 fan[ARRAY_SIZE(ADM1029_REG_FAN)];
152
        u8 fan_div[ARRAY_SIZE(ADM1029_REG_FAN_DIV)];
153
};
154
 
155
/*
156
 * Sysfs stuff
157
 */
158
 
159
static ssize_t
160
show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
161
{
162
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
163
        struct adm1029_data *data = adm1029_update_device(dev);
164
        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
165
}
166
 
167
static ssize_t
168
show_fan(struct device *dev, struct device_attribute *devattr, char *buf)
169
{
170
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
171
        struct adm1029_data *data = adm1029_update_device(dev);
172
        u16 val;
173
        if (data->fan[attr->index] == 0 || data->fan_div[attr->index] == 0
174
            || data->fan[attr->index] == 255) {
175
                return sprintf(buf, "0\n");
176
        }
177
 
178
        val = 1880 * 120 / DIV_FROM_REG(data->fan_div[attr->index])
179
            / data->fan[attr->index];
180
        return sprintf(buf, "%d\n", val);
181
}
182
 
183
static ssize_t
184
show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
185
{
186
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
187
        struct adm1029_data *data = adm1029_update_device(dev);
188
        if (data->fan_div[attr->index] == 0)
189
                return sprintf(buf, "0\n");
190
        return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
191
}
192
 
193
static ssize_t set_fan_div(struct device *dev,
194
            struct device_attribute *devattr, const char *buf, size_t count)
195
{
196
        struct i2c_client *client = to_i2c_client(dev);
197
        struct adm1029_data *data = i2c_get_clientdata(client);
198
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
199
        long val = simple_strtol(buf, NULL, 10);
200
        u8 reg;
201
 
202
        mutex_lock(&data->update_lock);
203
 
204
        /*Read actual config */
205
        reg = i2c_smbus_read_byte_data(client,
206
                                       ADM1029_REG_FAN_DIV[attr->index]);
207
 
208
        switch (val) {
209
        case 1:
210
                val = 1;
211
                break;
212
        case 2:
213
                val = 2;
214
                break;
215
        case 4:
216
                val = 3;
217
                break;
218
        default:
219
                mutex_unlock(&data->update_lock);
220
                dev_err(&client->dev, "fan_div value %ld not "
221
                        "supported. Choose one of 1, 2 or 4!\n", val);
222
                return -EINVAL;
223
        }
224
        /* Update the value */
225
        reg = (reg & 0x3F) | (val << 6);
226
 
227
        /* Write value */
228
        i2c_smbus_write_byte_data(client,
229
                                  ADM1029_REG_FAN_DIV[attr->index], reg);
230
        mutex_unlock(&data->update_lock);
231
 
232
        return count;
233
}
234
 
235
/*
236
Access rights on sysfs, S_IRUGO stand for Is Readable by User, Group and Others
237
                        S_IWUSR stand for Is Writable by User
238
*/
239
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
240
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
241
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
242
 
243
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3);
244
static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4);
245
static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5);
246
 
247
static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6);
248
static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7);
249
static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8);
250
 
251
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
252
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
253
 
254
static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2);
255
static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3);
256
 
257
static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
258
                          show_fan_div, set_fan_div, 0);
259
static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
260
                          show_fan_div, set_fan_div, 1);
261
 
262
static struct attribute *adm1029_attributes[] = {
263
        &sensor_dev_attr_temp1_input.dev_attr.attr,
264
        &sensor_dev_attr_temp1_min.dev_attr.attr,
265
        &sensor_dev_attr_temp1_max.dev_attr.attr,
266
        &sensor_dev_attr_temp2_input.dev_attr.attr,
267
        &sensor_dev_attr_temp2_min.dev_attr.attr,
268
        &sensor_dev_attr_temp2_max.dev_attr.attr,
269
        &sensor_dev_attr_temp3_input.dev_attr.attr,
270
        &sensor_dev_attr_temp3_min.dev_attr.attr,
271
        &sensor_dev_attr_temp3_max.dev_attr.attr,
272
        &sensor_dev_attr_fan1_input.dev_attr.attr,
273
        &sensor_dev_attr_fan2_input.dev_attr.attr,
274
        &sensor_dev_attr_fan1_min.dev_attr.attr,
275
        &sensor_dev_attr_fan2_min.dev_attr.attr,
276
        &sensor_dev_attr_fan1_div.dev_attr.attr,
277
        &sensor_dev_attr_fan2_div.dev_attr.attr,
278
        NULL
279
};
280
 
281
static const struct attribute_group adm1029_group = {
282
        .attrs = adm1029_attributes,
283
};
284
 
285
/*
286
 * Real code
287
 */
288
 
289
static int adm1029_attach_adapter(struct i2c_adapter *adapter)
290
{
291
        if (!(adapter->class & I2C_CLASS_HWMON))
292
                return 0;
293
        return i2c_probe(adapter, &addr_data, adm1029_detect);
294
}
295
 
296
/*
297
 * The following function does more than just detection. If detection
298
 * succeeds, it also registers the new chip.
299
 */
300
 
301
static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind)
302
{
303
        struct i2c_client *client;
304
        struct adm1029_data *data;
305
        int err = 0;
306
        const char *name = "";
307
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
308
                goto exit;
309
 
310
        if (!(data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL))) {
311
                err = -ENOMEM;
312
                goto exit;
313
        }
314
 
315
        client = &data->client;
316
        i2c_set_clientdata(client, data);
317
        client->addr = address;
318
        client->adapter = adapter;
319
        client->driver = &adm1029_driver;
320
 
321
        /* Now we do the detection and identification. A negative kind
322
         * means that the driver was loaded with no force parameter
323
         * (default), so we must both detect and identify the chip
324
         * (actually there is only one possible kind of chip for now, adm1029).
325
         * A zero kind means that the driver was loaded with the force
326
         * parameter, the detection step shall be skipped. A positive kind
327
         * means that the driver was loaded with the force parameter and a
328
         * given kind of chip is requested, so both the detection and the
329
         * identification steps are skipped. */
330
 
331
        /* Default to an adm1029 if forced */
332
        if (kind == 0)
333
                kind = adm1029;
334
 
335
        /* ADM1029 doesn't have CHIP ID, check just MAN ID
336
         * For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED,
337
         * ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values
338
         * documented
339
         */
340
 
341
        if (kind <= 0) { /* identification */
342
                u8 man_id, chip_id, temp_devices_installed, nb_fan_support;
343
 
344
                man_id = i2c_smbus_read_byte_data(client, ADM1029_REG_MAN_ID);
345
                chip_id = i2c_smbus_read_byte_data(client, ADM1029_REG_CHIP_ID);
346
                temp_devices_installed = i2c_smbus_read_byte_data(client,
347
                                        ADM1029_REG_TEMP_DEVICES_INSTALLED);
348
                nb_fan_support = i2c_smbus_read_byte_data(client,
349
                                                ADM1029_REG_NB_FAN_SUPPORT);
350
                /* 0x41 is Analog Devices */
351
                if (man_id == 0x41 && (temp_devices_installed & 0xf9) == 0x01
352
                    && nb_fan_support == 0x03) {
353
                        if ((chip_id & 0xF0) == 0x00) {
354
                                kind = adm1029;
355
                        } else {
356
                                /* There are no "official" CHIP ID, so actually
357
                                 * we use Major/Minor revision for that */
358
                                printk(KERN_INFO
359
                                       "adm1029: Unknown major revision %x, "
360
                                       "please let us know\n", chip_id);
361
                        }
362
                }
363
 
364
                if (kind <= 0) { /* identification failed */
365
                        pr_debug("adm1029: Unsupported chip (man_id=0x%02X, "
366
                                 "chip_id=0x%02X)\n", man_id, chip_id);
367
                        goto exit_free;
368
                }
369
        }
370
 
371
        if (kind == adm1029) {
372
                name = "adm1029";
373
        }
374
 
375
        /* We can fill in the remaining client fields */
376
        strlcpy(client->name, name, I2C_NAME_SIZE);
377
        mutex_init(&data->update_lock);
378
 
379
        /* Tell the I2C layer a new client has arrived */
380
        if ((err = i2c_attach_client(client)))
381
                goto exit_free;
382
 
383
        /*
384
         * Initialize the ADM1029 chip
385
         * Check config register
386
         */
387
        if (adm1029_init_client(client) == 0)
388
                goto exit_detach;
389
 
390
        /* Register sysfs hooks */
391
        if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group)))
392
                goto exit_detach;
393
 
394
        data->hwmon_dev = hwmon_device_register(&client->dev);
395
        if (IS_ERR(data->hwmon_dev)) {
396
                err = PTR_ERR(data->hwmon_dev);
397
                goto exit_remove_files;
398
        }
399
 
400
        return 0;
401
 
402
 exit_remove_files:
403
        sysfs_remove_group(&client->dev.kobj, &adm1029_group);
404
 exit_detach:
405
        i2c_detach_client(client);
406
 exit_free:
407
        kfree(data);
408
 exit:
409
        return err;
410
}
411
 
412
static int adm1029_init_client(struct i2c_client *client)
413
{
414
        u8 config;
415
        config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG);
416
        if ((config & 0x10) == 0) {
417
                i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG,
418
                                          config | 0x10);
419
        }
420
        /* recheck config */
421
        config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG);
422
        if ((config & 0x10) == 0) {
423
                dev_err(&client->dev, "Initialization failed!\n");
424
                return 0;
425
        }
426
        return 1;
427
}
428
 
429
static int adm1029_detach_client(struct i2c_client *client)
430
{
431
        struct adm1029_data *data = i2c_get_clientdata(client);
432
        int err;
433
 
434
        hwmon_device_unregister(data->hwmon_dev);
435
        sysfs_remove_group(&client->dev.kobj, &adm1029_group);
436
 
437
        if ((err = i2c_detach_client(client)))
438
                return err;
439
 
440
        kfree(data);
441
        return 0;
442
}
443
 
444
/*
445
function that update the status of the chips (temperature for exemple)
446
*/
447
static struct adm1029_data *adm1029_update_device(struct device *dev)
448
{
449
        struct i2c_client *client = to_i2c_client(dev);
450
        struct adm1029_data *data = i2c_get_clientdata(client);
451
 
452
        mutex_lock(&data->update_lock);
453
        /*
454
         * Use the "cache" Luke, don't recheck values
455
         * if there are already checked not a long time later
456
         */
457
        if (time_after(jiffies, data->last_updated + HZ * 2)
458
         || !data->valid) {
459
                int nr;
460
 
461
                dev_dbg(&client->dev, "Updating adm1029 data\n");
462
 
463
                for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) {
464
                        data->temp[nr] =
465
                            i2c_smbus_read_byte_data(client,
466
                                                     ADM1029_REG_TEMP[nr]);
467
                }
468
                for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) {
469
                        data->fan[nr] =
470
                            i2c_smbus_read_byte_data(client,
471
                                                     ADM1029_REG_FAN[nr]);
472
                }
473
                for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) {
474
                        data->fan_div[nr] =
475
                            i2c_smbus_read_byte_data(client,
476
                                                     ADM1029_REG_FAN_DIV[nr]);
477
                }
478
 
479
                data->last_updated = jiffies;
480
                data->valid = 1;
481
        }
482
 
483
        mutex_unlock(&data->update_lock);
484
 
485
        return data;
486
}
487
 
488
/*
489
        Common module stuff
490
*/
491
static int __init sensors_adm1029_init(void)
492
{
493
 
494
        return i2c_add_driver(&adm1029_driver);
495
}
496
 
497
static void __exit sensors_adm1029_exit(void)
498
{
499
 
500
        i2c_del_driver(&adm1029_driver);
501
}
502
 
503
MODULE_AUTHOR("Corentin LABBE <corentin.labbe@geomatys.fr>");
504
MODULE_DESCRIPTION("adm1029 driver");
505
MODULE_LICENSE("GPL v2");
506
 
507
module_init(sensors_adm1029_init);
508
module_exit(sensors_adm1029_exit);

powered by: WebSVN 2.1.0

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