root/lm-sensors/trunk/kernel/chips/vt1211.c @ 1417

Revision 1417, 23.7 KB (checked in by mds, 11 years ago)

vt1211 update; move calculations from driver to sensors.conf

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    vt1211.c - Part of lm_sensors, Linux kernel modules
3                for hardware monitoring
4               
5    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include <linux/version.h>
23#include <linux/module.h>
24#include <linux/slab.h>
25#include <linux/proc_fs.h>
26#include <linux/ioport.h>
27#include <linux/sysctl.h>
28#include <asm/errno.h>
29#include <asm/io.h>
30#include <linux/types.h>
31#include <linux/i2c.h>
32#include "version.h"
33#include "sensors.h"
34#include "sensors_vid.h"
35#include <linux/init.h>
36
37#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) || \
38    (LINUX_VERSION_CODE == KERNEL_VERSION(2,3,0))
39#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
40#endif
41
42#ifndef I2C_DRIVERID_VT1211
43#define I2C_DRIVERID_VT1211 1032
44#endif
45
46#ifndef THIS_MODULE
47#define THIS_MODULE NULL
48#endif
49
50static int force_addr = 0;
51MODULE_PARM(force_addr, "i");
52MODULE_PARM_DESC(force_addr,
53                 "Initialize the base address of the sensors");
54
55static unsigned short normal_i2c[] = { SENSORS_I2C_END };
56static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
57static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
58static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
59
60SENSORS_INSMOD_1(vt1211);
61
62/* modified from kernel/include/traps.c */
63#define REG     0x2e    /* The register to read/write */
64#define DEV     0x07    /* Register: Logical device select */
65#define VAL     0x2f    /* The value to read/write */
66#define PME     0x0b    /* The device with the hardware monitor */
67#define DEVID   0x20    /* Register: Device ID */
68
69static inline void
70superio_outb(int reg, int val)
71{
72        outb(reg, REG);
73        outb(val, VAL);
74}
75
76static inline int
77superio_inb(int reg)
78{
79        outb(reg, REG);
80        return inb(VAL);
81}
82
83static inline void
84superio_select()
85{
86        outb(DEV, REG);
87        outb(PME, VAL);
88}
89
90static inline void
91superio_enter()
92{
93        outb(0x87, REG);
94        outb(0x87, REG);
95}
96
97static inline void
98superio_exit()
99{
100        outb(0xAA, REG);
101}
102
103#define VT1211_DEVID 0x3c
104#define VT1211_ACT_REG 0x30
105#define VT1211_BASE_REG 0x60
106
107#define VT1211_EXTENT 0x80
108
109/* pwm numbered 1-2 */
110#define VT1211_REG_PWM(nr) (0x5f + (nr))
111
112/* The VT1211 registers */
113/* We define the sensors as follows. Somewhat convoluted to minimize
114   changes from via686a.
115        Sensor          Voltage Mode    Temp Mode
116        --------        ------------    ---------
117        Reading 1                       temp3
118        Reading 3                       temp1
119        UCH1/Reading2   in0             temp2
120        UCH2            in1             temp4
121        UCH3            in2             temp5
122        UCH4            in3             temp6
123        UCH5            in4             temp7
124        3.3V            in5
125        -12V            in6
126*/
127
128/* ins numbered 0-6 */
129#define VT1211_REG_IN_MAX(nr) ((nr)==0 ? 0x3d : 0x2b + (((nr)+1) * 2))
130#define VT1211_REG_IN_MIN(nr) ((nr)==0 ? 0x3e : 0x2c + (((nr)+1) * 2))
131#define VT1211_REG_IN(nr)     (0x21 + (nr))
132
133/* fans numbered 1-2 */
134#define VT1211_REG_FAN_MIN(nr) (0x3a + (nr))
135#define VT1211_REG_FAN(nr)     (0x28 + (nr))
136
137static const u8 regtemp[] = { 0x20, 0x21, 0x1f, 0x22, 0x23, 0x24, 0x25 };
138static const u8 regover[] = { 0x39, 0x3d, 0x1d, 0x2b, 0x2d, 0x2f, 0x31 };
139static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e, 0x2c, 0x2e, 0x30, 0x32 };
140
141/* temps numbered 1-7 */
142#define VT1211_REG_TEMP(nr)             (regtemp[(nr) - 1])
143#define VT1211_REG_TEMP_OVER(nr)        (regover[(nr) - 1])
144#define VT1211_REG_TEMP_HYST(nr)        (reghyst[(nr) - 1])
145#define VT1211_REG_TEMP_LOW3    0x4b    /* bits 7-6 */
146#define VT1211_REG_TEMP_LOW2    0x49    /* bits 5-4 */
147#define VT1211_REG_TEMP_LOW47   0x4d
148
149#define VT1211_REG_CONFIG 0x40
150#define VT1211_REG_ALARM1 0x41
151#define VT1211_REG_ALARM2 0x42
152#define VT1211_REG_VID    0x45
153#define VT1211_REG_FANDIV 0x47
154#define VT1211_REG_UCH_CONFIG 0x4a
155#define VT1211_REG_TEMP1_CONFIG 0x4b
156#define VT1211_REG_TEMP2_CONFIG 0x4c
157
158/* temps 1-7; voltages 0-6 */
159#define ISTEMP(i, ch_config) ((i) == 1 ? 1 : \
160                              (i) == 3 ? 1 : \
161                              (i) == 2 ? (ch_config) & 0x01 : \
162                              ((ch_config) >> ((i)-1)) & 0x01)
163#define ISVOLT(i, ch_config) ((i) > 4 ? 1 : !(((ch_config) >> ((i)+2)) & 0x01))
164
165#define DIV_FROM_REG(val) (1 << (val))
166#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
167#define PWM_FROM_REG(val) (((val) * 1005) / 2550)
168#define PWM_TO_REG(val) SENSORS_LIMIT((((val) * 2555) / 1000), 0, 255)
169
170#define TEMP_FROM_REG(val) ((val)*10)
171#define TEMP_FROM_REG10(val) (((val)*10)/4)
172#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
173                                                 ((val)+5)/10),0,255))
174#define IN_FROM_REG(val) /*(((val)*10+5)/10)*/ (val)
175#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 5)/10),0,255))
176
177
178/********* FAN RPM CONVERSIONS ********/
179/* But this chip saturates back at 0, not at 255 like all the other chips.
180   So, 0 means 0 RPM */
181extern inline u8 FAN_TO_REG(long rpm, int div)
182{
183        if (rpm == 0)
184                return 0;
185        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
186        return SENSORS_LIMIT((1310720 + rpm * div / 2) / (rpm * div), 1, 255);
187}
188
189#define MIN_TO_REG(a,b) FAN_TO_REG(a,b)
190#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1310720/((val)*(div)))
191
192#ifdef MODULE
193extern int init_module(void);
194extern int cleanup_module(void);
195#endif                          /* MODULE */
196
197struct vt1211_data {
198        struct semaphore lock;
199        int sysctl_id;
200
201        struct semaphore update_lock;
202        char valid;             /* !=0 if following fields are valid */
203        unsigned long last_updated;     /* In jiffies */
204
205        u8 in[7];               /* Register value */
206        u8 in_max[7];           /* Register value */
207        u8 in_min[7];           /* Register value */
208        u16 temp[7];            /* Register value 10 bit */
209        u8 temp_over[7];        /* Register value */
210        u8 temp_hyst[7];        /* Register value */
211        u8 fan[2];              /* Register value */
212        u8 fan_min[2];          /* Register value */
213        u8 fan_div[2];          /* Register encoding, shifted right */
214        u16 alarms;             /* Register encoding */
215        u8 pwm[2];              /* Register value */
216        u8 vid;                 /* Register encoding */
217        u8 vrm;
218        u8 uch_config;
219};
220
221#ifdef MODULE
222static
223#else
224extern
225#endif
226int __init sensors_vt1211_init(void);
227static int __init vt1211_cleanup(void);
228
229static int vt1211_attach_adapter(struct i2c_adapter *adapter);
230static int vt1211_detect(struct i2c_adapter *adapter, int address,
231                          unsigned short flags, int kind);
232static int vt1211_detach_client(struct i2c_client *client);
233static int vt1211_command(struct i2c_client *client, unsigned int cmd,
234                           void *arg);
235static void vt1211_inc_use(struct i2c_client *client);
236static void vt1211_dec_use(struct i2c_client *client);
237
238static inline int vt_rdval(struct i2c_client *client, u8 register);
239static inline void vt1211_write_value(struct i2c_client *client, u8 register,
240                               u8 value);
241static void vt1211_update_client(struct i2c_client *client);
242static void vt1211_init_client(struct i2c_client *client);
243static int vt1211_find(int *address);
244
245
246static void vt1211_fan(struct i2c_client *client, int operation,
247                        int ctl_name, int *nrels_mag, long *results);
248static void vt1211_alarms(struct i2c_client *client, int operation,
249                           int ctl_name, int *nrels_mag, long *results);
250static void vt1211_fan_div(struct i2c_client *client, int operation,
251                            int ctl_name, int *nrels_mag, long *results);
252static void vt1211_in(struct i2c_client *client, int operation,
253                        int ctl_name, int *nrels_mag, long *results);
254static void vt1211_pwm(struct i2c_client *client, int operation,
255                        int ctl_name, int *nrels_mag, long *results);
256static void vt1211_vid(struct i2c_client *client, int operation,
257                        int ctl_name, int *nrels_mag, long *results);
258static void vt1211_vrm(struct i2c_client *client, int operation,
259                        int ctl_name, int *nrels_mag, long *results);
260static void vt1211_uch(struct i2c_client *client, int operation,
261                        int ctl_name, int *nrels_mag, long *results);
262static void vt1211_temp(struct i2c_client *client, int operation,
263                        int ctl_name, int *nrels_mag, long *results);
264
265static int vt1211_id = 0;
266
267static struct i2c_driver vt1211_driver = {
268        /* name */ "SiS 5595",
269        /* id */ I2C_DRIVERID_VT1211,
270        /* flags */ I2C_DF_NOTIFY,
271        /* attach_adapter */ &vt1211_attach_adapter,
272        /* detach_client */ &vt1211_detach_client,
273        /* command */ &vt1211_command,
274        /* inc_use */ &vt1211_inc_use,
275        /* dec_use */ &vt1211_dec_use
276};
277
278static int __initdata vt1211_initialized = 0;
279
280static ctl_table vt1211_dir_table_template[] = {
281        {VT1211_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
282         &i2c_sysctl_real, NULL, &vt1211_in},
283        {VT1211_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
284         &i2c_sysctl_real, NULL, &vt1211_in},
285        {VT1211_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
286         &i2c_sysctl_real, NULL, &vt1211_in},
287        {VT1211_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
288         &i2c_sysctl_real, NULL, &vt1211_in},
289        {VT1211_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
290         &i2c_sysctl_real, NULL, &vt1211_in},
291        {VT1211_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
292         &i2c_sysctl_real, NULL, &vt1211_in},
293        {VT1211_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
294         &i2c_sysctl_real, NULL, &vt1211_in},
295        {VT1211_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
296         &i2c_sysctl_real, NULL, &vt1211_temp},
297        {VT1211_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
298         &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
299        {VT1211_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
300         &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
301        {VT1211_SYSCTL_TEMP4, "temp4", NULL, 0, 0644, NULL,
302         &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
303        {VT1211_SYSCTL_TEMP5, "temp5", NULL, 0, 0644, NULL,
304         &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
305        {VT1211_SYSCTL_TEMP6, "temp6", NULL, 0, 0644, NULL,
306         &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
307        {VT1211_SYSCTL_TEMP7, "temp7", NULL, 0, 0644, NULL,
308         &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
309        {VT1211_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
310         &i2c_sysctl_real, NULL, &vt1211_fan},
311        {VT1211_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
312         &i2c_sysctl_real, NULL, &vt1211_fan},
313        {VT1211_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
314         &i2c_sysctl_real, NULL, &vt1211_fan_div},
315        {VT1211_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
316         &i2c_sysctl_real, NULL, &vt1211_alarms},
317        {VT1211_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
318         &i2c_sysctl_real, NULL, &vt1211_pwm},
319        {VT1211_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
320         &i2c_sysctl_real, NULL, &vt1211_pwm},
321        {VT1211_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
322         &i2c_sysctl_real, NULL, &vt1211_vid},
323        {VT1211_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
324         &i2c_sysctl_real, NULL, &vt1211_vrm},
325        {VT1211_SYSCTL_UCH, "uch_config", NULL, 0, 0644, NULL, &i2c_proc_real,
326         &i2c_sysctl_real, NULL, &vt1211_uch},
327        {0}
328};
329
330int vt1211_attach_adapter(struct i2c_adapter *adapter)
331{
332        return i2c_detect(adapter, &addr_data, vt1211_detect);
333}
334
335int vt1211_find(int *address)
336{
337        u16 val;
338
339        superio_enter();
340        val= superio_inb(DEVID);
341        if(VT1211_DEVID != val) {
342                superio_exit();
343                return -ENODEV;
344        }
345
346        superio_select();
347        val = (superio_inb(VT1211_BASE_REG) << 8) |
348               superio_inb(VT1211_BASE_REG + 1);
349        *address = val & ~(VT1211_EXTENT - 1);
350        if (*address == 0 && force_addr == 0) {
351                printk("vt1211.o: base address not set - use force_addr=0xaddr\n");
352                superio_exit();
353                return -ENODEV;
354        }
355        if (force_addr)
356                *address = force_addr;  /* so detect will get called */
357
358        superio_exit();
359        return 0;
360}
361
362int vt1211_detect(struct i2c_adapter *adapter, int address,
363                   unsigned short flags, int kind)
364{
365        int i;
366        struct i2c_client *new_client;
367        struct vt1211_data *data;
368        int err = 0;
369        u8 val;
370        const char *type_name = "vt1211";
371        const char *client_name = "VT1211 chip";
372
373        if (!i2c_is_isa_adapter(adapter)) {
374                return 0;
375        }
376
377        if(force_addr)
378                address = force_addr & ~(VT1211_EXTENT - 1);
379        if (check_region(address, VT1211_EXTENT)) {
380                printk("vt1211.o: region 0x%x already in use!\n", address);
381                return -ENODEV;
382        }
383        if(force_addr) {
384                printk("vt1211.o: forcing ISA address 0x%04X\n", address);
385                superio_enter();
386                superio_select();
387                superio_outb(VT1211_BASE_REG, address >> 8);
388                superio_outb(VT1211_BASE_REG+1, address & 0xff);
389                superio_exit();
390        }
391
392        superio_enter();
393        superio_select();
394        if((val = 0x01 & superio_inb(VT1211_ACT_REG)) == 0)
395                superio_outb(VT1211_ACT_REG, 1);
396        superio_exit();
397
398        if (!(new_client = kmalloc(sizeof(struct i2c_client) +
399                                   sizeof(struct vt1211_data),
400                                   GFP_KERNEL))) {
401                return -ENOMEM;
402        }
403
404        data = (struct vt1211_data *) (new_client + 1);
405        new_client->addr = address;
406        init_MUTEX(&data->lock);
407        new_client->data = data;
408        new_client->adapter = adapter;
409        new_client->driver = &vt1211_driver;
410        new_client->flags = 0;
411
412        request_region(address, VT1211_EXTENT, "vt1211-sensors");
413        strcpy(new_client->name, client_name);
414
415        new_client->id = vt1211_id++;
416        data->valid = 0;
417        init_MUTEX(&data->update_lock);
418
419        if ((err = i2c_attach_client(new_client)))
420                goto ERROR3;
421
422        if ((i = i2c_register_entry((struct i2c_client *) new_client,
423                                        type_name,
424                                        vt1211_dir_table_template,
425                                        THIS_MODULE)) < 0) {
426                err = i;
427                goto ERROR4;
428        }
429        data->sysctl_id = i;
430
431        vt1211_init_client(new_client);
432        return 0;
433
434      ERROR4:
435        i2c_detach_client(new_client);
436      ERROR3:
437        release_region(address, VT1211_EXTENT);
438        kfree(new_client);
439        return err;
440}
441
442int vt1211_detach_client(struct i2c_client *client)
443{
444        int err;
445
446        i2c_deregister_entry(((struct vt1211_data *) (client->data))->
447                                 sysctl_id);
448
449        if ((err = i2c_detach_client(client))) {
450                printk
451                    ("vt1211.o: Client deregistration failed, client not detached.\n");
452                return err;
453        }
454
455        release_region(client->addr, VT1211_EXTENT);
456        kfree(client);
457
458        return 0;
459}
460
461int vt1211_command(struct i2c_client *client, unsigned int cmd, void *arg)
462{
463        return 0;
464}
465
466void vt1211_inc_use(struct i2c_client *client)
467{
468#ifdef MODULE
469        MOD_INC_USE_COUNT;
470#endif
471}
472
473void vt1211_dec_use(struct i2c_client *client)
474{
475#ifdef MODULE
476        MOD_DEC_USE_COUNT;
477#endif
478}
479
480static inline int vt_rdval(struct i2c_client *client, u8 reg)
481{
482        return (inb_p(client->addr + reg));
483}
484
485static inline void vt1211_write_value(struct i2c_client *client, u8 reg, u8 value)
486{
487        outb_p(value, client->addr + reg);
488}
489
490void vt1211_init_client(struct i2c_client *client)
491{
492        struct vt1211_data *data = client->data;
493
494        data->vrm = DEFAULT_VRM;
495        /* set "default" interrupt mode for alarms, which isn't the default */
496        vt1211_write_value(client, VT1211_REG_TEMP1_CONFIG, 0);
497        vt1211_write_value(client, VT1211_REG_TEMP2_CONFIG, 0);
498}
499
500void vt1211_update_client(struct i2c_client *client)
501{
502        struct vt1211_data *data = client->data;
503        int i, j;
504
505        down(&data->update_lock);
506
507        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
508            (jiffies < data->last_updated) || !data->valid) {
509                data->uch_config = vt_rdval(client, VT1211_REG_UCH_CONFIG);
510                for (i = 0; i <= 6; i++) {
511                        if(ISVOLT(i, data->uch_config)) {
512                                data->in[i] = vt_rdval(client, VT1211_REG_IN(i));
513                                data->in_min[i] = vt_rdval(client,
514                                                        VT1211_REG_IN_MIN(i));
515                                data->in_max[i] = vt_rdval(client,
516                                                        VT1211_REG_IN_MAX(i));
517                        } else {
518                                data->in[i] = 0;
519                                data->in_min[i] = 0;
520                                data->in_max[i] = 0;
521                        }
522                }
523                for (i = 1; i <= 2; i++) {
524                        data->fan[i - 1] = vt_rdval(client, VT1211_REG_FAN(i));
525                        data->fan_min[i - 1] = vt_rdval(client,
526                                                     VT1211_REG_FAN_MIN(i));
527                }
528                for (i = 1; i <= 7; i++) {
529                        if(ISTEMP(i, data->uch_config)) {
530                                data->temp[i - 1] = vt_rdval(client,
531                                                     VT1211_REG_TEMP(i)) << 2;
532                                switch(i) {
533                                        case 1:
534                                                /* ? */
535                                                j = 0;
536                                                break;
537                                        case 2:
538                                                j = (vt_rdval(client,
539                                                  VT1211_REG_TEMP_LOW2) &
540                                                                    0x30) >> 4;
541                                                break;
542                                        case 3:
543                                                j = (vt_rdval(client,
544                                                  VT1211_REG_TEMP_LOW3) &
545                                                                    0xc0) >> 6;
546                                                break;
547                                        case 4:
548                                        case 5:
549                                        case 6:
550                                        case 7:
551                                        default:
552                                                j = (vt_rdval(client,
553                                                  VT1211_REG_TEMP_LOW47) >>
554                                                            ((i-4)*2)) & 0x03; 
555                                                break;
556       
557                                }
558                                data->temp[i - 1] |= j;
559                                data->temp_over[i - 1] = vt_rdval(client,
560                                                      VT1211_REG_TEMP_OVER(i));
561                                data->temp_hyst[i - 1] = vt_rdval(client,
562                                                      VT1211_REG_TEMP_HYST(i));
563                        } else {
564                                data->temp[i - 1] = 0;
565                                data->temp_over[i - 1] = 0;
566                                data->temp_hyst[i - 1] = 0;
567                        }
568                }
569
570                for (i = 1; i <= 2; i++) {
571                        data->fan[i - 1] = vt_rdval(client, VT1211_REG_FAN(i));
572                        data->fan_min[i - 1] = vt_rdval(client,
573                                                        VT1211_REG_FAN_MIN(i));
574                        data->pwm[i - 1] = vt_rdval(client, VT1211_REG_PWM(i));
575                }
576
577                i = vt_rdval(client, VT1211_REG_FANDIV);
578                data->fan_div[0] = (i >> 4) & 0x03;
579                data->fan_div[1] = i >> 6;
580                data->alarms = vt_rdval(client, VT1211_REG_ALARM1) |
581                                    (vt_rdval(client, VT1211_REG_ALARM2) << 8);
582                data->vid= vt_rdval(client, VT1211_REG_VID) & 0x1f;
583                data->last_updated = jiffies;
584                data->valid = 1;
585        }
586
587        up(&data->update_lock);
588}
589
590
591void vt1211_in(struct i2c_client *client, int operation, int ctl_name,
592                int *nrels_mag, long *results)
593{
594        struct vt1211_data *data = client->data;
595        int nr = ctl_name - VT1211_SYSCTL_IN0;
596
597        if (operation == SENSORS_PROC_REAL_INFO)
598                *nrels_mag = 2;
599        else if (operation == SENSORS_PROC_REAL_READ) {
600                vt1211_update_client(client);
601                results[0] = IN_FROM_REG(data->in_min[nr]);
602                results[1] = IN_FROM_REG(data->in_max[nr]);
603                results[2] = IN_FROM_REG(data->in[nr]);
604                *nrels_mag = 3;
605        } else if (operation == SENSORS_PROC_REAL_WRITE) {
606                if (*nrels_mag >= 1) {
607                        data->in_min[nr] = IN_TO_REG(results[0]);
608                        vt1211_write_value(client, VT1211_REG_IN_MIN(nr),
609                                            data->in_min[nr]);
610                }
611                if (*nrels_mag >= 2) {
612                        data->in_max[nr] = IN_TO_REG(results[1]);
613                        vt1211_write_value(client, VT1211_REG_IN_MAX(nr),
614                                            data->in_max[nr]);
615                }
616        }
617}
618
619void vt1211_fan(struct i2c_client *client, int operation, int ctl_name,
620                 int *nrels_mag, long *results)
621{
622        struct vt1211_data *data = client->data;
623        int nr = ctl_name - VT1211_SYSCTL_FAN1 + 1;
624
625        if (operation == SENSORS_PROC_REAL_INFO)
626                *nrels_mag = 0;
627        else if (operation == SENSORS_PROC_REAL_READ) {
628                vt1211_update_client(client);
629                results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
630                                          DIV_FROM_REG(data->fan_div
631                                                       [nr - 1]));
632                results[1] = FAN_FROM_REG(data->fan[nr - 1],
633                                 DIV_FROM_REG(data->fan_div[nr - 1]));
634                *nrels_mag = 2;
635        } else if (operation == SENSORS_PROC_REAL_WRITE) {
636                if (*nrels_mag >= 1) {
637                        data->fan_min[nr - 1] = MIN_TO_REG(results[0],
638                                                           DIV_FROM_REG
639                                                           (data->
640                                                            fan_div[nr-1]));
641                        vt1211_write_value(client, VT1211_REG_FAN_MIN(nr),
642                                            data->fan_min[nr - 1]);
643                }
644        }
645}
646
647
648void vt1211_temp(struct i2c_client *client, int operation, int ctl_name,
649                  int *nrels_mag, long *results)
650{
651        struct vt1211_data *data = client->data;
652        int nr = ctl_name - VT1211_SYSCTL_TEMP;
653
654        if (operation == SENSORS_PROC_REAL_INFO)
655                *nrels_mag = 1;
656        else if (operation == SENSORS_PROC_REAL_READ) {
657                vt1211_update_client(client);
658                results[0] = TEMP_FROM_REG(data->temp_over[nr]);
659                results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
660                results[2] = TEMP_FROM_REG10(data->temp[nr]);
661                *nrels_mag = 3;
662        } else if (operation == SENSORS_PROC_REAL_WRITE) {
663                if (*nrels_mag >= 1) {
664                        data->temp_over[nr] = TEMP_TO_REG(results[0]);
665                        vt1211_write_value(client,
666                                            VT1211_REG_TEMP_OVER(nr + 1),
667                                            data->temp_over[nr]);
668                }
669                if (*nrels_mag >= 2) {
670                        data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
671                        vt1211_write_value(client,
672                                            VT1211_REG_TEMP_HYST(nr + 1),
673                                            data->temp_hyst[nr]);
674                }
675        }
676}
677
678void vt1211_alarms(struct i2c_client *client, int operation, int ctl_name,
679                    int *nrels_mag, long *results)
680{
681        struct vt1211_data *data = client->data;
682        if (operation == SENSORS_PROC_REAL_INFO)
683                *nrels_mag = 0;
684        else if (operation == SENSORS_PROC_REAL_READ) {
685                vt1211_update_client(client);
686                results[0] = data->alarms;
687                *nrels_mag = 1;
688        }
689}
690
691void vt1211_fan_div(struct i2c_client *client, int operation,
692                     int ctl_name, int *nrels_mag, long *results)
693{
694        struct vt1211_data *data = client->data;
695        int old;
696
697        if (operation == SENSORS_PROC_REAL_INFO)
698                *nrels_mag = 0;
699        else if (operation == SENSORS_PROC_REAL_READ) {
700                vt1211_update_client(client);
701                results[0] = DIV_FROM_REG(data->fan_div[0]);
702                results[1] = DIV_FROM_REG(data->fan_div[1]);
703                *nrels_mag = 2;
704        } else if (operation == SENSORS_PROC_REAL_WRITE) {
705                old = vt_rdval(client, VT1211_REG_FANDIV);
706                if (*nrels_mag >= 2) {
707                        data->fan_div[1] = DIV_TO_REG(results[1]);
708                        old = (old & 0x3f) | (data->fan_div[1] << 6);
709                }
710                if (*nrels_mag >= 1) {
711                        data->fan_div[0] = DIV_TO_REG(results[0]);
712                        old = (old & 0xcf) | (data->fan_div[0] << 4);
713                        vt1211_write_value(client, VT1211_REG_FANDIV, old);
714                }
715        }
716}
717
718void vt1211_pwm(struct i2c_client *client, int operation, int ctl_name,
719                 int *nrels_mag, long *results)
720{
721        struct vt1211_data *data = client->data;
722        int nr = 1 + ctl_name - VT1211_SYSCTL_PWM1;
723
724        if (operation == SENSORS_PROC_REAL_INFO)
725                *nrels_mag = 0;
726        else if (operation == SENSORS_PROC_REAL_READ) {
727                vt1211_update_client(client);
728                results[0] = PWM_FROM_REG(data->pwm[nr - 1]);
729                results[1] = 1; /* always enabled */
730                *nrels_mag = 2;
731        } else if (operation == SENSORS_PROC_REAL_WRITE) {
732                if (*nrels_mag >= 1) {
733                        data->pwm[nr - 1] = PWM_TO_REG(results[0]);
734                        if (*nrels_mag >= 2) {
735                                /* ignore enable for now */
736                        }
737                        vt1211_write_value(client, VT1211_REG_PWM(nr),
738                                            data->pwm[nr - 1]);
739                }
740        }
741}
742
743void vt1211_vid(struct i2c_client *client, int operation, int ctl_name,
744                 int *nrels_mag, long *results)
745{
746        struct vt1211_data *data = client->data;
747        if (operation == SENSORS_PROC_REAL_INFO)
748                *nrels_mag = 3;
749        else if (operation == SENSORS_PROC_REAL_READ) {
750                vt1211_update_client(client);
751                results[0] = vid_from_reg(data->vid, data->vrm);
752                *nrels_mag = 1;
753        }
754}
755
756void vt1211_vrm(struct i2c_client *client, int operation, int ctl_name,
757                 int *nrels_mag, long *results)
758{
759        struct vt1211_data *data = client->data;
760        if (operation == SENSORS_PROC_REAL_INFO)
761                *nrels_mag = 1;
762        else if (operation == SENSORS_PROC_REAL_READ) {
763                results[0] = data->vrm;
764                *nrels_mag = 1;
765        } else if (operation == SENSORS_PROC_REAL_WRITE) {
766                if (*nrels_mag >= 1)
767                        data->vrm = results[0];
768        }
769}
770
771void vt1211_uch(struct i2c_client *client, int operation, int ctl_name,
772                 int *nrels_mag, long *results)
773{
774        struct vt1211_data *data = client->data;
775        if (operation == SENSORS_PROC_REAL_INFO)
776                *nrels_mag = 0;
777        else if (operation == SENSORS_PROC_REAL_READ) {
778                results[0] = data->uch_config;
779                *nrels_mag = 1;
780        } else if (operation == SENSORS_PROC_REAL_WRITE) {
781                if (*nrels_mag >= 1) {
782                        data->uch_config = results[0] & 0x7c;
783                        vt1211_write_value(client, VT1211_REG_UCH_CONFIG,
784                                           results[0] & 0x7c);
785                }
786        }
787}
788
789int __init sensors_vt1211_init(void)
790{
791        int res, addr;
792
793        printk("vt1211.o version %s (%s)\n", LM_VERSION, LM_DATE);
794        vt1211_initialized = 0;
795
796        if (vt1211_find(&addr)) {
797                printk("vt1211.o: VT1211 not detected, module not inserted.\n");
798                return -ENODEV;
799        }
800        normal_isa[0] = addr;
801
802        if ((res = i2c_add_driver(&vt1211_driver))) {
803                printk
804                    ("vt1211.o: Driver registration failed, module not inserted.\n");
805                vt1211_cleanup();
806                return res;
807        }
808        vt1211_initialized++;
809        return 0;
810}
811
812int __init vt1211_cleanup(void)
813{
814        int res;
815
816        if (vt1211_initialized >= 1) {
817                if ((res = i2c_del_driver(&vt1211_driver))) {
818                        printk
819                            ("vt1211.o: Driver deregistration failed, module not removed.\n");
820                        return res;
821                }
822                vt1211_initialized--;
823        }
824        return 0;
825}
826
827EXPORT_NO_SYMBOLS;
828
829#ifdef MODULE
830
831MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
832MODULE_DESCRIPTION("VT1211 sensors");
833#ifdef MODULE_LICENSE
834MODULE_LICENSE("GPL");
835#endif
836
837int init_module(void)
838{
839        return sensors_vt1211_init();
840}
841
842int cleanup_module(void)
843{
844        return vt1211_cleanup();
845}
846
847#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.