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

Revision 2784, 24.0 KB (checked in by khali, 8 years ago)

Restore controlling_mod argument to i2c_register_entry(). This
is needed to properly lock chip drivers in memory while anyone uses their
/proc entries. This also brings back compatibility with the 2.4 Linux
kernel.

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