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

Revision 1705, 24.1 KB (checked in by kmalkki, 10 years ago)

(Kyösti) Cleanups

Copy sysctl enums to chip drivers from sensors.h for now,
as seen in drivers included in 2.5 tree. File no longer included
from kernel side.

Apply i2c-proc change in CVS tagged -km2.

Partial clean and sort of includes everywhere.

Add i2c-dev.h, as a partial copy from i2c.
Add to sensors.h from i2c-proc.h to compile things.
Remove i2c-isa.h.

Reflect header file changes to lib/ and prog/.

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