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

Revision 1622, 24.3 KB (checked in by mds, 11 years ago)

remove #ifndef for DRIVERID, 2.7.0 release will require i2c-2.7.0

  • 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/* Supports VIA VT1211 Super I/O sensors via ISA (LPC) accesses only. */
23
24#include <linux/version.h>
25#include <linux/module.h>
26#include <linux/slab.h>
27#include <linux/proc_fs.h>
28#include <linux/ioport.h>
29#include <linux/sysctl.h>
30#include <asm/errno.h>
31#include <asm/io.h>
32#include <linux/types.h>
33#include <linux/i2c.h>
34#include "version.h"
35#include "sensors.h"
36#include "sensors_vid.h"
37#include <linux/init.h>
38
39#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) || \
40    (LINUX_VERSION_CODE == KERNEL_VERSION(2,3,0))
41#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
42#endif
43
44#ifndef THIS_MODULE
45#define THIS_MODULE NULL
46#endif
47
48static int force_addr = 0;
49MODULE_PARM(force_addr, "i");
50MODULE_PARM_DESC(force_addr,
51                 "Initialize the base address of the sensors");
52
53static unsigned short normal_i2c[] = { SENSORS_I2C_END };
54static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
55static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
56static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
57
58SENSORS_INSMOD_1(vt1211);
59
60/* modified from kernel/include/traps.c */
61#define REG     0x2e    /* The register to read/write */
62#define DEV     0x07    /* Register: Logical device select */
63#define VAL     0x2f    /* The value to read/write */
64#define PME     0x0b    /* The device with the hardware monitor */
65#define DEVID   0x20    /* Register: Device ID */
66
67static inline void
68superio_outb(int reg, int val)
69{
70        outb(reg, REG);
71        outb(val, VAL);
72}
73
74static inline int
75superio_inb(int reg)
76{
77        outb(reg, REG);
78        return inb(VAL);
79}
80
81static inline void
82superio_select(void)
83{
84        outb(DEV, REG);
85        outb(PME, VAL);
86}
87
88static inline void
89superio_enter(void)
90{
91        outb(0x87, REG);
92        outb(0x87, REG);
93}
94
95static inline void
96superio_exit(void)
97{
98        outb(0xAA, REG);
99}
100
101#define VT1211_DEVID 0x3c
102#define VT1211_ACT_REG 0x30
103#define VT1211_BASE_REG 0x60
104
105#define VT1211_EXTENT 0x80
106
107/* pwm numbered 1-2 */
108#define VT1211_REG_PWM(nr) (0x5f + (nr))
109#define VT1211_REG_PWM_CTL 0x51
110
111/* The VT1211 registers */
112/* We define the sensors as follows. Somewhat convoluted to minimize
113   changes from via686a.
114        Sensor          Voltage Mode    Temp Mode
115        --------        ------------    ---------
116        Reading 1                       temp3
117        Reading 3                       temp1   not in vt1211
118        UCH1/Reading2   in0             temp2
119        UCH2            in1             temp4
120        UCH3            in2             temp5
121        UCH4            in3             temp6
122        UCH5            in4             temp7
123        3.3V            in5
124        -12V            in6                     not in vt1211
125*/
126
127/* ins numbered 0-6 */
128#define VT1211_REG_IN_MAX(nr) ((nr)==0 ? 0x3d : 0x29 + ((nr) * 2))
129#define VT1211_REG_IN_MIN(nr) ((nr)==0 ? 0x3e : 0x2a + ((nr) * 2))
130#define VT1211_REG_IN(nr)     (0x21 + (nr))
131
132/* fans numbered 1-2 */
133#define VT1211_REG_FAN_MIN(nr) (0x3a + (nr))
134#define VT1211_REG_FAN(nr)     (0x28 + (nr))
135
136static const u8 regtemp[] = { 0x20, 0x21, 0x1f, 0x22, 0x23, 0x24, 0x25 };
137static const u8 regover[] = { 0x39, 0x3d, 0x1d, 0x2b, 0x2d, 0x2f, 0x31 };
138static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e, 0x2c, 0x2e, 0x30, 0x32 };
139
140/* temps numbered 1-7 */
141#define VT1211_REG_TEMP(nr)             (regtemp[(nr) - 1])
142#define VT1211_REG_TEMP_OVER(nr)        (regover[(nr) - 1])
143#define VT1211_REG_TEMP_HYST(nr)        (reghyst[(nr) - 1])
144#define VT1211_REG_TEMP_LOW3    0x4b    /* bits 7-6 */
145#define VT1211_REG_TEMP_LOW2    0x49    /* bits 5-4 */
146#define VT1211_REG_TEMP_LOW47   0x4d
147
148#define VT1211_REG_CONFIG 0x40
149#define VT1211_REG_ALARM1 0x41
150#define VT1211_REG_ALARM2 0x42
151#define VT1211_REG_VID    0x45
152#define VT1211_REG_FANDIV 0x47
153#define VT1211_REG_UCH_CONFIG 0x4a
154#define VT1211_REG_TEMP1_CONFIG 0x4b
155#define VT1211_REG_TEMP2_CONFIG 0x4c
156
157/* temps 1-7; voltages 0-6 */
158#define ISTEMP(i, ch_config) ((i) == 1 ? 1 : \
159                              (i) == 3 ? 1 : \
160                              (i) == 2 ? ((ch_config) >> 1) & 0x01 : \
161                                         ((ch_config) >> ((i)-1)) & 0x01)
162#define ISVOLT(i, ch_config) ((i) > 4 ? 1 : !(((ch_config) >> ((i)+2)) & 0x01))
163
164#define DIV_FROM_REG(val) (1 << (val))
165#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
166#define PWM_FROM_REG(val) (((val) * 1005) / 2550)
167#define PWM_TO_REG(val) SENSORS_LIMIT((((val) * 2555) / 1000), 0, 255)
168
169#define TEMP_FROM_REG(val) ((val)*10)
170#define TEMP_FROM_REG10(val) (((val)*10)/4)
171#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
172                                                 ((val)+5)/10),0,255))
173#define IN_FROM_REG(val) /*(((val)*10+5)/10)*/ (val)
174#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 5)/10),0,255))
175
176
177/********* FAN RPM CONVERSIONS ********/
178/* But this chip saturates back at 0, not at 255 like all the other chips.
179   So, 0 means 0 RPM */
180extern inline u8 FAN_TO_REG(long rpm, int div)
181{
182        if (rpm == 0)
183                return 0;
184        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
185        return SENSORS_LIMIT((1310720 + rpm * div / 2) / (rpm * div), 1, 255);
186}
187
188#define MIN_TO_REG(a,b) FAN_TO_REG(a,b)
189#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1310720/((val)*(div)))
190
191#ifdef MODULE
192extern int init_module(void);
193extern int cleanup_module(void);
194#endif                          /* MODULE */
195
196struct vt1211_data {
197        struct semaphore lock;
198        int sysctl_id;
199
200        struct semaphore update_lock;
201        char valid;             /* !=0 if following fields are valid */
202        unsigned long last_updated;     /* In jiffies */
203
204        u8 in[7];               /* Register value */
205        u8 in_max[7];           /* Register value */
206        u8 in_min[7];           /* Register value */
207        u16 temp[7];            /* Register value 10 bit */
208        u8 temp_over[7];        /* Register value */
209        u8 temp_hyst[7];        /* Register value */
210        u8 fan[2];              /* Register value */
211        u8 fan_min[2];          /* Register value */
212        u8 fan_div[2];          /* Register encoding, shifted right */
213        u16 alarms;             /* Register encoding */
214        u8 pwm[2];              /* Register value */
215        u8 pwm_ctl;             /* 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 */ "VT1211 sensors driver",
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                data->pwm_ctl = vt_rdval(client, VT1211_REG_PWM_CTL);
578                i = vt_rdval(client, VT1211_REG_FANDIV);
579                data->fan_div[0] = (i >> 4) & 0x03;
580                data->fan_div[1] = i >> 6;
581                data->alarms = vt_rdval(client, VT1211_REG_ALARM1) |
582                                    (vt_rdval(client, VT1211_REG_ALARM2) << 8);
583                data->vid= vt_rdval(client, VT1211_REG_VID) & 0x1f;
584                data->last_updated = jiffies;
585                data->valid = 1;
586        }
587
588        up(&data->update_lock);
589}
590
591
592void vt1211_in(struct i2c_client *client, int operation, int ctl_name,
593                int *nrels_mag, long *results)
594{
595        struct vt1211_data *data = client->data;
596        int nr = ctl_name - VT1211_SYSCTL_IN0;
597
598        if (operation == SENSORS_PROC_REAL_INFO)
599                *nrels_mag = 2;
600        else if (operation == SENSORS_PROC_REAL_READ) {
601                vt1211_update_client(client);
602                results[0] = IN_FROM_REG(data->in_min[nr]);
603                results[1] = IN_FROM_REG(data->in_max[nr]);
604                results[2] = IN_FROM_REG(data->in[nr]);
605                *nrels_mag = 3;
606        } else if (operation == SENSORS_PROC_REAL_WRITE) {
607                if (*nrels_mag >= 1) {
608                        data->in_min[nr] = IN_TO_REG(results[0]);
609                        vt1211_write_value(client, VT1211_REG_IN_MIN(nr),
610                                            data->in_min[nr]);
611                }
612                if (*nrels_mag >= 2) {
613                        data->in_max[nr] = IN_TO_REG(results[1]);
614                        vt1211_write_value(client, VT1211_REG_IN_MAX(nr),
615                                            data->in_max[nr]);
616                }
617        }
618}
619
620void vt1211_fan(struct i2c_client *client, int operation, int ctl_name,
621                 int *nrels_mag, long *results)
622{
623        struct vt1211_data *data = client->data;
624        int nr = ctl_name - VT1211_SYSCTL_FAN1 + 1;
625
626        if (operation == SENSORS_PROC_REAL_INFO)
627                *nrels_mag = 0;
628        else if (operation == SENSORS_PROC_REAL_READ) {
629                vt1211_update_client(client);
630                results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
631                                          DIV_FROM_REG(data->fan_div
632                                                       [nr - 1]));
633                results[1] = FAN_FROM_REG(data->fan[nr - 1],
634                                 DIV_FROM_REG(data->fan_div[nr - 1]));
635                *nrels_mag = 2;
636        } else if (operation == SENSORS_PROC_REAL_WRITE) {
637                if (*nrels_mag >= 1) {
638                        data->fan_min[nr - 1] = MIN_TO_REG(results[0],
639                                                           DIV_FROM_REG
640                                                           (data->
641                                                            fan_div[nr-1]));
642                        vt1211_write_value(client, VT1211_REG_FAN_MIN(nr),
643                                            data->fan_min[nr - 1]);
644                }
645        }
646}
647
648
649void vt1211_temp(struct i2c_client *client, int operation, int ctl_name,
650                  int *nrels_mag, long *results)
651{
652        struct vt1211_data *data = client->data;
653        int nr = ctl_name - VT1211_SYSCTL_TEMP;
654
655        if (operation == SENSORS_PROC_REAL_INFO)
656                *nrels_mag = 1;
657        else if (operation == SENSORS_PROC_REAL_READ) {
658                vt1211_update_client(client);
659                results[0] = TEMP_FROM_REG(data->temp_over[nr]);
660                results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
661                results[2] = TEMP_FROM_REG10(data->temp[nr]);
662                *nrels_mag = 3;
663        } else if (operation == SENSORS_PROC_REAL_WRITE) {
664                if (*nrels_mag >= 1) {
665                        data->temp_over[nr] = TEMP_TO_REG(results[0]);
666                        vt1211_write_value(client,
667                                            VT1211_REG_TEMP_OVER(nr + 1),
668                                            data->temp_over[nr]);
669                }
670                if (*nrels_mag >= 2) {
671                        data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
672                        vt1211_write_value(client,
673                                            VT1211_REG_TEMP_HYST(nr + 1),
674                                            data->temp_hyst[nr]);
675                }
676        }
677}
678
679void vt1211_alarms(struct i2c_client *client, int operation, int ctl_name,
680                    int *nrels_mag, long *results)
681{
682        struct vt1211_data *data = client->data;
683        if (operation == SENSORS_PROC_REAL_INFO)
684                *nrels_mag = 0;
685        else if (operation == SENSORS_PROC_REAL_READ) {
686                vt1211_update_client(client);
687                results[0] = data->alarms;
688                *nrels_mag = 1;
689        }
690}
691
692void vt1211_fan_div(struct i2c_client *client, int operation,
693                     int ctl_name, int *nrels_mag, long *results)
694{
695        struct vt1211_data *data = client->data;
696        int old;
697
698        if (operation == SENSORS_PROC_REAL_INFO)
699                *nrels_mag = 0;
700        else if (operation == SENSORS_PROC_REAL_READ) {
701                vt1211_update_client(client);
702                results[0] = DIV_FROM_REG(data->fan_div[0]);
703                results[1] = DIV_FROM_REG(data->fan_div[1]);
704                *nrels_mag = 2;
705        } else if (operation == SENSORS_PROC_REAL_WRITE) {
706                old = vt_rdval(client, VT1211_REG_FANDIV);
707                if (*nrels_mag >= 2) {
708                        data->fan_div[1] = DIV_TO_REG(results[1]);
709                        old = (old & 0x3f) | (data->fan_div[1] << 6);
710                }
711                if (*nrels_mag >= 1) {
712                        data->fan_div[0] = DIV_TO_REG(results[0]);
713                        old = (old & 0xcf) | (data->fan_div[0] << 4);
714                        vt1211_write_value(client, VT1211_REG_FANDIV, old);
715                }
716        }
717}
718
719void vt1211_pwm(struct i2c_client *client, int operation, int ctl_name,
720                 int *nrels_mag, long *results)
721{
722        struct vt1211_data *data = client->data;
723        int nr = 1 + ctl_name - VT1211_SYSCTL_PWM1;
724
725        if (operation == SENSORS_PROC_REAL_INFO)
726                *nrels_mag = 0;
727        else if (operation == SENSORS_PROC_REAL_READ) {
728                vt1211_update_client(client);
729                results[0] = PWM_FROM_REG(data->pwm[nr - 1]);
730                results[1] = (data->pwm_ctl >> (3 + (4 * (nr - 1)))) & 1;
731                *nrels_mag = 2;
732        } else if (operation == SENSORS_PROC_REAL_WRITE) {
733                if (*nrels_mag >= 1) {
734                        data->pwm[nr - 1] = PWM_TO_REG(results[0]);
735                        if (*nrels_mag >= 2) {
736                                if(results[1]) {
737                                        data->pwm_ctl |=
738                                                  (0x08 << (4 * (nr - 1)));
739                                        vt1211_write_value(client,
740                                                           VT1211_REG_PWM_CTL, 
741                                                           data->pwm_ctl);
742                                } else {
743                                        data->pwm_ctl &=
744                                                ~ (0x08 << (4 * (nr - 1)));
745                                        vt1211_write_value(client,
746                                                           VT1211_REG_PWM_CTL, 
747                                                           data->pwm_ctl);
748                                }
749                        }
750                        vt1211_write_value(client, VT1211_REG_PWM(nr),
751                                            data->pwm[nr - 1]);
752                }
753        }
754}
755
756void vt1211_vid(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 = 3;
762        else if (operation == SENSORS_PROC_REAL_READ) {
763                vt1211_update_client(client);
764                results[0] = vid_from_reg(data->vid, data->vrm);
765                *nrels_mag = 1;
766        }
767}
768
769void vt1211_vrm(struct i2c_client *client, int operation, int ctl_name,
770                 int *nrels_mag, long *results)
771{
772        struct vt1211_data *data = client->data;
773        if (operation == SENSORS_PROC_REAL_INFO)
774                *nrels_mag = 1;
775        else if (operation == SENSORS_PROC_REAL_READ) {
776                results[0] = data->vrm;
777                *nrels_mag = 1;
778        } else if (operation == SENSORS_PROC_REAL_WRITE) {
779                if (*nrels_mag >= 1)
780                        data->vrm = results[0];
781        }
782}
783
784void vt1211_uch(struct i2c_client *client, int operation, int ctl_name,
785                 int *nrels_mag, long *results)
786{
787        struct vt1211_data *data = client->data;
788        if (operation == SENSORS_PROC_REAL_INFO)
789                *nrels_mag = 0;
790        else if (operation == SENSORS_PROC_REAL_READ) {
791                results[0] = data->uch_config;
792                *nrels_mag = 1;
793        } else if (operation == SENSORS_PROC_REAL_WRITE) {
794                if (*nrels_mag >= 1) {
795                        data->uch_config = results[0] & 0x7c;
796                        vt1211_write_value(client, VT1211_REG_UCH_CONFIG,
797                                           results[0] & 0x7c);
798                }
799        }
800}
801
802int __init sensors_vt1211_init(void)
803{
804        int res, addr;
805
806        printk("vt1211.o version %s (%s)\n", LM_VERSION, LM_DATE);
807        vt1211_initialized = 0;
808
809        if (vt1211_find(&addr)) {
810                printk("vt1211.o: VT1211 not detected, module not inserted.\n");
811                return -ENODEV;
812        }
813        normal_isa[0] = addr;
814
815        if ((res = i2c_add_driver(&vt1211_driver))) {
816                printk
817                    ("vt1211.o: Driver registration failed, module not inserted.\n");
818                vt1211_cleanup();
819                return res;
820        }
821        vt1211_initialized++;
822        return 0;
823}
824
825int __init vt1211_cleanup(void)
826{
827        int res;
828
829        if (vt1211_initialized >= 1) {
830                if ((res = i2c_del_driver(&vt1211_driver))) {
831                        printk
832                            ("vt1211.o: Driver deregistration failed, module not removed.\n");
833                        return res;
834                }
835                vt1211_initialized--;
836        }
837        return 0;
838}
839
840EXPORT_NO_SYMBOLS;
841
842#ifdef MODULE
843
844MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
845MODULE_DESCRIPTION("VT1211 sensors");
846#ifdef MODULE_LICENSE
847MODULE_LICENSE("GPL");
848#endif
849
850int init_module(void)
851{
852        return sensors_vt1211_init();
853}
854
855int cleanup_module(void)
856{
857        return vt1211_cleanup();
858}
859
860#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.