]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/linux-mtx-1-2.4.27/17-lmsensors.2.8.8.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / linux-mtx-1-2.4.27 / 17-lmsensors.2.8.8.patch
1 --- linux-old/drivers/i2c/i2c-ali1535.c Thu Jan  1 00:00:00 1970
2 +++ linux/drivers/i2c/i2c-ali1535.c     Mon Dec 13 20:18:40 2004
3 @@ -0,0 +1,601 @@
4 +/*
5 +    i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware
6 +                    monitoring
7 +    Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>, 
8 +                        Philip Edelbrock <phil@netroedge.com>, 
9 +                        Mark D. Studebaker <mdsxyz123@yahoo.com>,
10 +                        Dan Eaton <dan.eaton@rocketlogix.com> and 
11 +                        Stephen Rousset<stephen.rousset@rocketlogix.com> 
12 +
13 +    This program is free software; you can redistribute it and/or modify
14 +    it under the terms of the GNU General Public License as published by
15 +    the Free Software Foundation; either version 2 of the License, or
16 +    (at your option) any later version.
17 +
18 +    This program is distributed in the hope that it will be useful,
19 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
20 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 +    GNU General Public License for more details.
22 +
23 +    You should have received a copy of the GNU General Public License
24 +    along with this program; if not, write to the Free Software
25 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 +*/
27 +
28 +/*
29 +    This is the driver for the SMB Host controller on
30 +    Acer Labs Inc. (ALI) M1535 South Bridge.
31 +
32 +    The M1535 is a South bridge for portable systems.
33 +    It is very similar to the M15x3 South bridges also produced
34 +    by Acer Labs Inc.  Some of the registers within the part
35 +    have moved and some have been redefined slightly. Additionally,
36 +    the sequencing of the SMBus transactions has been modified
37 +    to be more consistent with the sequencing recommended by
38 +    the manufacturer and observed through testing.  These
39 +    changes are reflected in this driver and can be identified
40 +    by comparing this driver to the i2c-ali15x3 driver.
41 +    For an overview of these chips see http://www.acerlabs.com
42 +
43 +    The SMB controller is part of the 7101 device, which is an
44 +    ACPI-compliant Power Management Unit (PMU).
45 +
46 +    The whole 7101 device has to be enabled for the SMB to work.
47 +    You can't just enable the SMB alone.
48 +    The SMB and the ACPI have separate I/O spaces.
49 +    We make sure that the SMB is enabled. We leave the ACPI alone.
50 +
51 +    This driver controls the SMB Host only.
52 +
53 +    This driver does not use interrupts.
54 +*/
55 +
56 +
57 +/* Note: we assume there can only be one ALI1535, with one SMBus interface */
58 +
59 +#include <linux/module.h>
60 +#include <linux/pci.h>
61 +#include <linux/kernel.h>
62 +#include <linux/stddef.h>
63 +#include <linux/sched.h>
64 +#include <linux/ioport.h>
65 +#include <linux/i2c.h>
66 +#include <linux/init.h>
67 +#include <asm/io.h>
68 +#include <asm/semaphore.h>
69 +#define LM_DATE "20041007"
70 +#define LM_VERSION "2.8.8"
71 +
72 +
73 +/* ALI1535 SMBus address offsets */
74 +#define SMBHSTSTS (0 + ali1535_smba)
75 +#define SMBHSTTYP (1 + ali1535_smba)
76 +#define SMBHSTPORT (2 + ali1535_smba)
77 +#define SMBHSTCMD (7 + ali1535_smba)
78 +#define SMBHSTADD (3 + ali1535_smba)
79 +#define SMBHSTDAT0 (4 + ali1535_smba)
80 +#define SMBHSTDAT1 (5 + ali1535_smba)
81 +#define SMBBLKDAT (6 + ali1535_smba)
82 +
83 +/* PCI Address Constants */
84 +#define SMBCOM    0x004
85 +#define SMBREV    0x008
86 +#define SMBCFG    0x0D1
87 +#define SMBBA     0x0E2
88 +#define SMBHSTCFG 0x0F0
89 +#define SMBCLK    0x0F2
90 +
91 +/* Other settings */
92 +#define MAX_TIMEOUT 500                /* times 1/100 sec */
93 +#define ALI1535_SMB_IOSIZE 32
94 +
95 +/* 
96 +*/
97 +#define ALI1535_SMB_DEFAULTBASE 0x8040
98 +
99 +/* ALI1535 address lock bits */
100 +#define ALI1535_LOCK   0x06 < dwe >
101 +
102 +/* ALI1535 command constants */
103 +#define ALI1535_QUICK      0x00
104 +#define ALI1535_BYTE       0x10
105 +#define ALI1535_BYTE_DATA  0x20
106 +#define ALI1535_WORD_DATA  0x30
107 +#define ALI1535_BLOCK_DATA 0x40
108 +#define ALI1535_I2C_READ   0x60
109 +
110 +#define        ALI1535_DEV10B_EN       0x80    /* Enable 10-bit addressing in */
111 +                                        /*  I2C read                   */
112 +#define        ALI1535_T_OUT           0x08    /* Time-out Command (write)    */
113 +#define        ALI1535_A_HIGH_BIT9     0x08    /* Bit 9 of 10-bit address in  */
114 +                                        /* Alert-Response-Address      */
115 +                                        /* (read)                      */
116 +#define        ALI1535_KILL            0x04    /* Kill Command (write)        */
117 +#define        ALI1535_A_HIGH_BIT8     0x04    /* Bit 8 of 10-bit address in  */
118 +                                        /*  Alert-Response-Address     */
119 +                                        /*  (read)                     */
120 +
121 +#define        ALI1535_D_HI_MASK       0x03    /* Mask for isolating bits 9-8 */
122 +                                        /*  of 10-bit address in I2C   */ 
123 +                                        /*  Read Command               */
124 +
125 +/* ALI1535 status register bits */
126 +#define ALI1535_STS_IDLE       0x04
127 +#define ALI1535_STS_BUSY       0x08    /* host busy */
128 +#define ALI1535_STS_DONE       0x10    /* transaction complete */
129 +#define ALI1535_STS_DEV                0x20    /* device error */
130 +#define ALI1535_STS_BUSERR     0x40    /* bus error    */
131 +#define ALI1535_STS_FAIL       0x80    /* failed bus transaction */
132 +#define ALI1535_STS_ERR                0xE0    /* all the bad error bits */
133 +
134 +#define ALI1535_BLOCK_CLR      0x04    /* reset block data index */
135 +
136 +/* ALI1535 device address register bits */
137 +#define        ALI1535_RD_ADDR         0x01    /* Read/Write Bit in Device    */
138 +                                        /*  Address field              */
139 +                                        /*  -> Write = 0               */
140 +                                        /*  -> Read  = 1               */
141 +#define        ALI1535_SMBIO_EN        0x04    /* SMB I/O Space enable        */
142 +
143 +static int ali1535_transaction(void);
144 +
145 +static unsigned short ali1535_smba = 0;
146 +DECLARE_MUTEX(i2c_ali1535_sem);
147 +
148 +
149 +/* Detect whether a ALI1535 can be found, and initialize it, where necessary.
150 +   Note the differences between kernels with the old PCI BIOS interface and
151 +   newer kernels with the real PCI interface. In compat.h some things are
152 +   defined to make the transition easier. */
153 +int ali1535_setup(struct pci_dev *ALI1535_dev)
154 +{
155 +       int error_return = 0;
156 +       unsigned char temp;
157 +
158 +/* Check the following things:
159 +       - SMB I/O address is initialized
160 +       - Device is enabled
161 +       - We can use the addresses
162 +*/
163 +
164 +/* Determine the address of the SMBus area */
165 +       pci_read_config_word(ALI1535_dev, SMBBA, &ali1535_smba);
166 +       ali1535_smba &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1));
167 +       if (ali1535_smba == 0) {
168 +               printk
169 +                   ("i2c-ali1535.o: ALI1535_smb region uninitialized - upgrade BIOS?\n");
170 +               error_return = -ENODEV;
171 +       }
172 +
173 +       if (error_return == -ENODEV)
174 +               goto END;
175 +
176 +       if (check_region(ali1535_smba, ALI1535_SMB_IOSIZE)) {
177 +               printk
178 +                   ("i2c-ali1535.o: ALI1535_smb region 0x%x already in use!\n",
179 +                    ali1535_smba);
180 +               error_return = -ENODEV;
181 +       }
182 +
183 +       if (error_return == -ENODEV)
184 +               goto END;
185 +
186 +       /* check if whole device is enabled */
187 +       pci_read_config_byte(ALI1535_dev, SMBCFG, &temp);
188 +       if ((temp & ALI1535_SMBIO_EN) == 0) {
189 +               printk
190 +                   ("i2c-ali1535.o: SMB device not enabled - upgrade BIOS?\n");
191 +               error_return = -ENODEV;
192 +               goto END;
193 +       }
194 +
195 +/* Is SMB Host controller enabled? */
196 +       pci_read_config_byte(ALI1535_dev, SMBHSTCFG, &temp);
197 +       if ((temp & 1) == 0) {
198 +               printk
199 +                   ("i2c-ali1535.o: SMBus controller not enabled - upgrade BIOS?\n");
200 +               error_return = -ENODEV;
201 +               goto END;
202 +       }
203 +
204 +/* set SMB clock to 74KHz as recommended in data sheet */
205 +       pci_write_config_byte(ALI1535_dev, SMBCLK, 0x20);
206 +
207 +       /* Everything is happy, let's grab the memory and set things up. */
208 +       request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb");
209 +
210 +#ifdef DEBUG
211 +/*
212 +  The interrupt routing for SMB is set up in register 0x77 in the
213 +  1533 ISA Bridge device, NOT in the 7101 device.
214 +  Don't bother with finding the 1533 device and reading the register.
215 +  if ((....... & 0x0F) == 1)
216 +     printk("i2c-ali1535.o: ALI1535 using Interrupt 9 for SMBus.\n");
217 +*/
218 +       pci_read_config_byte(ALI1535_dev, SMBREV, &temp);
219 +       printk("i2c-ali1535.o: SMBREV = 0x%X\n", temp);
220 +       printk("i2c-ali1535.o: ALI1535_smba = 0x%X\n", ali1535_smba);
221 +#endif                         /* DEBUG */
222 +
223 +      END:
224 +       return error_return;
225 +}
226 +
227 +
228 +/* Another internally used function */
229 +int ali1535_transaction(void)
230 +{
231 +       int temp;
232 +       int result = 0;
233 +       int timeout = 0;
234 +
235 +#ifdef DEBUG
236 +       printk
237 +           ("i2c-ali1535.o: Transaction (pre): STS=%02x, TYP=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
238 +            "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTTYP),
239 +            inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
240 +            inb_p(SMBHSTDAT1));
241 +#endif
242 +
243 +       /* get status */
244 +       temp = inb_p(SMBHSTSTS);
245 +
246 +       /* Make sure the SMBus host is ready to start transmitting */
247 +       /* Check the busy bit first */
248 +       if (temp & ALI1535_STS_BUSY) {
249 +/*
250 +   If the host controller is still busy, it may have timed out in the previous transaction,
251 +   resulting in a "SMBus Timeout" printk.
252 +   I've tried the following to reset a stuck busy bit.
253 +       1. Reset the controller with an KILL command.
254 +          (this doesn't seem to clear the controller if an external device is hung)
255 +       2. Reset the controller and the other SMBus devices with a T_OUT command.
256 +          (this clears the host busy bit if an external device is hung,
257 +          but it comes back upon a new access to a device)
258 +       3. Disable and reenable the controller in SMBHSTCFG
259 +   Worst case, nothing seems to work except power reset.
260 +*/
261 +/* Abort - reset the host controller */
262 +/*
263 +#ifdef DEBUG
264 +    printk("i2c-ali1535.o: Resetting host controller to clear busy condition\n",temp);
265 +#endif
266 +    outb_p(ALI1535_KILL, SMBHSTTYP);
267 +    temp = inb_p(SMBHSTSTS);
268 +    if (temp & ALI1535_STS_BUSY) {
269 +*/
270 +
271 +/*
272 +   Try resetting entire SMB bus, including other devices -
273 +   This may not work either - it clears the BUSY bit but
274 +   then the BUSY bit may come back on when you try and use the chip again.
275 +   If that's the case you are stuck.
276 +*/
277 +               printk
278 +                   ("i2c-ali1535.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",
279 +                    temp);
280 +               outb_p(ALI1535_T_OUT, SMBHSTTYP);
281 +               temp = inb_p(SMBHSTSTS);
282 +       }
283 +/*
284 +  }
285 +*/
286 +
287 +       /* now check the error bits and the busy bit */
288 +       if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
289 +               /* do a clear-on-write */
290 +               outb_p(0xFF, SMBHSTSTS);
291 +               if ((temp = inb_p(SMBHSTSTS)) &
292 +                   (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {
293 +                       /* this is probably going to be correctable only by a power reset
294 +                          as one of the bits now appears to be stuck */
295 +                       /* This may be a bus or device with electrical problems. */
296 +                       printk
297 +                           ("i2c-ali1535.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n",
298 +                            temp);
299 +                       return -1;
300 +               }
301 +       } else {
302 +               /* check and clear done bit */
303 +               if (temp & ALI1535_STS_DONE) {
304 +                       outb_p(temp, SMBHSTSTS);
305 +               }
306 +       }
307 +
308 +       /* start the transaction by writing anything to the start register */
309 +       outb_p(0xFF, SMBHSTPORT);
310 +
311 +       /* We will always wait for a fraction of a second! */
312 +       timeout = 0;
313 +       do {
314 +               i2c_delay(1);
315 +               temp = inb_p(SMBHSTSTS);
316 +       } while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE))
317 +                && (timeout++ < MAX_TIMEOUT));
318 +
319 +       /* If the SMBus is still busy, we give up */
320 +       if (timeout >= MAX_TIMEOUT) {
321 +               result = -1;
322 +               printk("i2c-ali1535.o: SMBus Timeout!\n");
323 +       }
324 +
325 +       if (temp & ALI1535_STS_FAIL) {
326 +               result = -1;
327 +#ifdef DEBUG
328 +               printk("i2c-ali1535.o: Error: Failed bus transaction\n");
329 +#endif
330 +       }
331 +
332 +/*
333 +  Unfortunately the ALI SMB controller maps "no response" and "bus collision"
334 +  into a single bit. No reponse is the usual case so don't do a printk.
335 +  This means that bus collisions go unreported.
336 +*/
337 +       if (temp & ALI1535_STS_BUSERR) {
338 +               result = -1;
339 +#ifdef DEBUG
340 +               printk
341 +                   ("i2c-ali1535.o: Error: no response or bus collision ADD=%02x\n",
342 +                    inb_p(SMBHSTADD));
343 +#endif
344 +       }
345 +
346 +/* haven't ever seen this */
347 +       if (temp & ALI1535_STS_DEV) {
348 +               result = -1;
349 +               printk("i2c-ali1535.o: Error: device error\n");
350 +       }
351 +
352 +/* 
353 +   check to see if the "command complete" indication is set
354 + */
355 +       if (!(temp & ALI1535_STS_DONE)) {
356 +               result = -1;
357 +               printk("i2c-ali1535.o: Error: command never completed\n");
358 +       }
359 +#ifdef DEBUG
360 +       printk
361 +           ("i2c-ali1535.o: Transaction (post): STS=%02x, TYP=%02x, CMD=%02x, ADD=%02x, "
362 +            "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTTYP),
363 +            inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
364 +            inb_p(SMBHSTDAT1));
365 +#endif
366 +
367 +/* 
368 +    take consequent actions for error conditions
369 + */
370 +        if (!(temp & ALI1535_STS_DONE)) {
371 +         /* issue "kill" to reset host controller */
372 +         outb_p(ALI1535_KILL,SMBHSTTYP);
373 +         outb_p(0xFF,SMBHSTSTS);
374 +       }         
375 +       else if (temp & ALI1535_STS_ERR) {
376 +         /* issue "timeout" to reset all devices on bus */
377 +         outb_p(ALI1535_T_OUT,SMBHSTTYP);
378 +         outb_p(0xFF,SMBHSTSTS);
379 +       }
380 +        
381 +       return result;
382 +}
383 +
384 +/* Return -1 on error. */
385 +s32 ali1535_access(struct i2c_adapter * adap, u16 addr,
386 +                  unsigned short flags, char read_write, u8 command,
387 +                  int size, union i2c_smbus_data * data)
388 +{
389 +       int i, len;
390 +       int temp;
391 +       int timeout;
392 +       s32 result = 0;
393 +
394 +       down(&i2c_ali1535_sem);
395 +/* make sure SMBus is idle */
396 +       temp = inb_p(SMBHSTSTS);
397 +       for (timeout = 0;
398 +            (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE);
399 +            timeout++) {
400 +               i2c_delay(1);
401 +               temp = inb_p(SMBHSTSTS);
402 +       }
403 +       if (timeout >= MAX_TIMEOUT) {
404 +               printk("i2c-ali1535.o: Idle wait Timeout! STS=0x%02x\n",
405 +                      temp);
406 +       }
407 +
408 +/* clear status register (clear-on-write) */
409 +       outb_p(0xFF, SMBHSTSTS);
410 +
411 +       switch (size) {
412 +       case I2C_SMBUS_QUICK:
413 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
414 +                      SMBHSTADD);
415 +               size = ALI1535_QUICK;
416 +                outb_p(size, SMBHSTTYP);       /* output command */
417 +                break;
418 +       case I2C_SMBUS_BYTE:
419 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
420 +                      SMBHSTADD);
421 +               size = ALI1535_BYTE;
422 +                outb_p(size, SMBHSTTYP);       /* output command */
423 +               if (read_write == I2C_SMBUS_WRITE)
424 +                       outb_p(command, SMBHSTCMD);
425 +               break;
426 +       case I2C_SMBUS_BYTE_DATA:
427 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
428 +                      SMBHSTADD);
429 +               size = ALI1535_BYTE_DATA;
430 +                outb_p(size, SMBHSTTYP);       /* output command */
431 +               outb_p(command, SMBHSTCMD);
432 +               if (read_write == I2C_SMBUS_WRITE)
433 +                       outb_p(data->byte, SMBHSTDAT0);
434 +               break;
435 +       case I2C_SMBUS_WORD_DATA:
436 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
437 +                      SMBHSTADD);
438 +               size = ALI1535_WORD_DATA;
439 +                outb_p(size, SMBHSTTYP);       /* output command */
440 +               outb_p(command, SMBHSTCMD);
441 +               if (read_write == I2C_SMBUS_WRITE) {
442 +                       outb_p(data->word & 0xff, SMBHSTDAT0);
443 +                       outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
444 +               }
445 +               break;
446 +       case I2C_SMBUS_BLOCK_DATA:
447 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
448 +                      SMBHSTADD);
449 +               size = ALI1535_BLOCK_DATA;
450 +                outb_p(size, SMBHSTTYP);       /* output command */
451 +               outb_p(command, SMBHSTCMD);
452 +               if (read_write == I2C_SMBUS_WRITE) {
453 +                       len = data->block[0];
454 +                       if (len < 0) {
455 +                               len = 0;
456 +                               data->block[0] = len;
457 +                       }
458 +                       if (len > 32) {
459 +                               len = 32;
460 +                               data->block[0] = len;
461 +                       }
462 +                       outb_p(len, SMBHSTDAT0);
463 +                       outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP);        /* Reset SMBBLKDAT */
464 +                       for (i = 1; i <= len; i++)
465 +                               outb_p(data->block[i], SMBBLKDAT);
466 +               }
467 +               break;
468 +       default:
469 +               printk
470 +                   (KERN_WARNING "i2c-ali1535.o: Unsupported transaction %d\n", size);
471 +               result = -1;
472 +               goto EXIT;
473 +       }
474 +
475 +       if (ali1535_transaction())      /* Error in transaction */
476 +         {
477 +               result = -1;
478 +               goto EXIT;
479 +          }
480 +
481 +       if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK))
482 +         {
483 +               result = 0;
484 +               goto EXIT;
485 +          }
486 +
487 +       switch (size) {
488 +       case ALI1535_BYTE:      /* Result put in SMBHSTDAT0 */
489 +               data->byte = inb_p(SMBHSTDAT0);
490 +               break;
491 +       case ALI1535_BYTE_DATA:
492 +               data->byte = inb_p(SMBHSTDAT0);
493 +               break;
494 +       case ALI1535_WORD_DATA:
495 +               data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
496 +               break;
497 +       case ALI1535_BLOCK_DATA:
498 +               len = inb_p(SMBHSTDAT0);
499 +               if (len > 32)
500 +                       len = 32;
501 +               data->block[0] = len;
502 +               outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP);        /* Reset SMBBLKDAT */
503 +               for (i = 1; i <= data->block[0]; i++) {
504 +                       data->block[i] = inb_p(SMBBLKDAT);
505 +#ifdef DEBUG
506 +                       printk
507 +                           ("i2c-ali1535.o: Blk: len=%d, i=%d, data=%02x\n",
508 +                            len, i, data->block[i]);
509 +#endif /* DEBUG */
510 +               }
511 +               break;
512 +       }
513 +EXIT:
514 +       up(&i2c_ali1535_sem);
515 +       return result;
516 +}
517 +
518 +
519 +u32 ali1535_func(struct i2c_adapter *adapter)
520 +{
521 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
522 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
523 +           I2C_FUNC_SMBUS_BLOCK_DATA;
524 +}
525 +
526 +static struct i2c_algorithm smbus_algorithm = {
527 +       .name           = "Non-i2c SMBus adapter",
528 +       .id             = I2C_ALGO_SMBUS,
529 +       .smbus_xfer     = ali1535_access,
530 +       .functionality  = ali1535_func,
531 +};
532 +
533 +static struct i2c_adapter ali1535_adapter = {
534 +       .owner          = THIS_MODULE,
535 +       .name           = "unset",
536 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI1535,
537 +       .algo           = &smbus_algorithm,
538 +};
539 +
540 +
541 +static struct pci_device_id ali1535_ids[] __devinitdata = {
542 +       {
543 +       .vendor =       PCI_VENDOR_ID_AL,
544 +       .device =       PCI_DEVICE_ID_AL_M7101,
545 +       .subvendor =    PCI_ANY_ID,
546 +       .subdevice =    PCI_ANY_ID,
547 +       },
548 +       { 0, }
549 +};
550 +
551 +static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
552 +{
553 +       if (ali1535_setup(dev)) {
554 +               printk
555 +                   ("i2c-ali1535.o: ALI1535 not detected, module not inserted.\n");
556 +               return -ENODEV;
557 +       }
558 +
559 +       sprintf(ali1535_adapter.name, "SMBus ALI1535 adapter at %04x",
560 +               ali1535_smba);
561 +       return i2c_add_adapter(&ali1535_adapter);
562 +}
563 +
564 +static void __devexit ali1535_remove(struct pci_dev *dev)
565 +{
566 +       i2c_del_adapter(&ali1535_adapter);
567 +       release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
568 +}
569 +
570 +
571 +static struct pci_driver ali1535_driver = {
572 +       .name           = "ali1535 smbus",
573 +       .id_table       = ali1535_ids,
574 +       .probe          = ali1535_probe,
575 +       .remove         = __devexit_p(ali1535_remove),
576 +};
577 +
578 +static int __init i2c_ali1535_init(void)
579 +{
580 +       printk("i2c-ali1535.o version %s (%s)\n", LM_VERSION, LM_DATE);
581 +       return pci_module_init(&ali1535_driver);
582 +}
583 +
584 +
585 +static void __exit i2c_ali1535_exit(void)
586 +{
587 +       pci_unregister_driver(&ali1535_driver);
588 +}
589 +
590 +#ifdef RLX
591 +EXPORT_SYMBOL(ali1535_smba);
592 +EXPORT_SYMBOL(ali1535_access);
593 +EXPORT_SYMBOL(i2c_ali1535_sem);
594 +#endif
595 +
596 +MODULE_AUTHOR
597 +    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, "
598 +     "Mark D. Studebaker <mdsxyz123@yahoo.com> and Dan Eaton <dan.eaton@rocketlogix.com>");
599 +MODULE_DESCRIPTION("ALI1535 SMBus driver");
600 +MODULE_LICENSE("GPL");
601 +
602 +module_init(i2c_ali1535_init);
603 +module_exit(i2c_ali1535_exit);
604 +
605 --- linux-old/drivers/i2c/i2c-ali15x3.c Thu Jan  1 00:00:00 1970
606 +++ linux/drivers/i2c/i2c-ali15x3.c     Mon Dec 13 20:18:40 2004
607 @@ -0,0 +1,533 @@
608 +/*
609 +    ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
610 +              monitoring
611 +    Copyright (c) 1999  Frodo Looijaard <frodol@dds.nl> and
612 +    Philip Edelbrock <phil@netroedge.com> and
613 +    Mark D. Studebaker <mdsxyz123@yahoo.com>
614 +
615 +    This program is free software; you can redistribute it and/or modify
616 +    it under the terms of the GNU General Public License as published by
617 +    the Free Software Foundation; either version 2 of the License, or
618 +    (at your option) any later version.
619 +
620 +    This program is distributed in the hope that it will be useful,
621 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
622 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
623 +    GNU General Public License for more details.
624 +
625 +    You should have received a copy of the GNU General Public License
626 +    along with this program; if not, write to the Free Software
627 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
628 +*/
629 +
630 +/*
631 +    This is the driver for the SMB Host controller on
632 +    Acer Labs Inc. (ALI) M1541 and M1543C South Bridges.
633 +
634 +    The M1543C is a South bridge for desktop systems.
635 +    The M1533 is a South bridge for portable systems.
636 +    They are part of the following ALI chipsets:
637 +       "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge
638 +       with AGP and 100MHz CPU Front Side bus
639 +       "Aladdin V": Includes the M1541 Socket 7 North bridge
640 +       with AGP and 100MHz CPU Front Side bus
641 +       "Aladdin IV": Includes the M1541 Socket 7 North bridge
642 +       with host bus up to 83.3 MHz.
643 +    For an overview of these chips see http://www.acerlabs.com
644 +
645 +    The M1533/M1543C devices appear as FOUR separate devices
646 +    on the PCI bus. An output of lspci will show something similar
647 +    to the following:
648 +
649 +       00:02.0 USB Controller: Acer Laboratories Inc. M5237
650 +       00:03.0 Bridge: Acer Laboratories Inc. M7101
651 +       00:07.0 ISA bridge: Acer Laboratories Inc. M1533
652 +       00:0f.0 IDE interface: Acer Laboratories Inc. M5229
653 +
654 +    The SMB controller is part of the 7101 device, which is an
655 +    ACPI-compliant Power Management Unit (PMU).
656 +
657 +    The whole 7101 device has to be enabled for the SMB to work.
658 +    You can't just enable the SMB alone.
659 +    The SMB and the ACPI have separate I/O spaces.
660 +    We make sure that the SMB is enabled. We leave the ACPI alone.
661 +
662 +    This driver controls the SMB Host only.
663 +    The SMB Slave controller on the M15X3 is not enabled.
664 +
665 +    This driver does not use interrupts.
666 +*/
667 +
668 +/* Note: we assume there can only be one ALI15X3, with one SMBus interface */
669 +
670 +/* #define DEBUG 1 */
671 +
672 +#include <linux/module.h>
673 +#include <linux/pci.h>
674 +#include <linux/kernel.h>
675 +#include <linux/stddef.h>
676 +#include <linux/sched.h>
677 +#include <linux/ioport.h>
678 +#include <linux/i2c.h>
679 +#include <linux/init.h>
680 +#include <asm/io.h>
681 +#define LM_DATE "20041007"
682 +#define LM_VERSION "2.8.8"
683 +#include <linux/sensors_compat.h>
684 +
685 +/* ALI15X3 SMBus address offsets */
686 +#define SMBHSTSTS      (0 + ali15x3_smba)
687 +#define SMBHSTCNT      (1 + ali15x3_smba)
688 +#define SMBHSTSTART    (2 + ali15x3_smba)
689 +#define SMBHSTCMD      (7 + ali15x3_smba)
690 +#define SMBHSTADD      (3 + ali15x3_smba)
691 +#define SMBHSTDAT0     (4 + ali15x3_smba)
692 +#define SMBHSTDAT1     (5 + ali15x3_smba)
693 +#define SMBBLKDAT      (6 + ali15x3_smba)
694 +
695 +/* PCI Address Constants */
696 +#define SMBCOM         0x004
697 +#define SMBBA          0x014
698 +#define SMBATPC                0x05B   /* used to unlock xxxBA registers */
699 +#define SMBHSTCFG      0x0E0
700 +#define SMBSLVC                0x0E1
701 +#define SMBCLK         0x0E2
702 +#define SMBREV         0x008
703 +
704 +/* Other settings */
705 +#define MAX_TIMEOUT            200     /* times 1/100 sec */
706 +#define ALI15X3_SMB_IOSIZE     32
707 +
708 +/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB.
709 +   We don't use these here. If the bases aren't set to some value we
710 +   tell user to upgrade BIOS and we fail.
711 +*/
712 +#define ALI15X3_SMB_DEFAULTBASE        0xE800
713 +
714 +/* ALI15X3 address lock bits */
715 +#define ALI15X3_LOCK           0x06
716 +
717 +/* ALI15X3 command constants */
718 +#define ALI15X3_ABORT          0x02
719 +#define ALI15X3_T_OUT          0x04
720 +#define ALI15X3_QUICK          0x00
721 +#define ALI15X3_BYTE           0x10
722 +#define ALI15X3_BYTE_DATA      0x20
723 +#define ALI15X3_WORD_DATA      0x30
724 +#define ALI15X3_BLOCK_DATA     0x40
725 +#define ALI15X3_BLOCK_CLR      0x80
726 +
727 +/* ALI15X3 status register bits */
728 +#define ALI15X3_STS_IDLE       0x04
729 +#define ALI15X3_STS_BUSY       0x08
730 +#define ALI15X3_STS_DONE       0x10
731 +#define ALI15X3_STS_DEV                0x20    /* device error */
732 +#define ALI15X3_STS_COLL       0x40    /* collision or no response */
733 +#define ALI15X3_STS_TERM       0x80    /* terminated by abort */
734 +#define ALI15X3_STS_ERR                0xE0    /* all the bad error bits */
735 +
736 +
737 +/* If force_addr is set to anything different from 0, we forcibly enable
738 +   the device at the given address. */
739 +static int force_addr = 0;
740 +MODULE_PARM(force_addr, "i");
741 +MODULE_PARM_DESC(force_addr,
742 +                "Initialize the base address of the i2c controller");
743 +
744 +static unsigned short ali15x3_smba = 0;
745 +
746 +static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
747 +{
748 +       u16 a;
749 +       unsigned char temp;
750 +
751 +       /* Check the following things:
752 +               - SMB I/O address is initialized
753 +               - Device is enabled
754 +               - We can use the addresses
755 +       */
756 +
757 +       /* Unlock the register.
758 +          The data sheet says that the address registers are read-only
759 +          if the lock bits are 1, but in fact the address registers
760 +          are zero unless you clear the lock bits.
761 +       */
762 +       pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
763 +       if (temp & ALI15X3_LOCK) {
764 +               temp &= ~ALI15X3_LOCK;
765 +               pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
766 +       }
767 +
768 +       /* Determine the address of the SMBus area */
769 +       pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
770 +       ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
771 +       if (ali15x3_smba == 0 && force_addr == 0) {
772 +               dev_err(ALI15X3_dev, "ALI15X3_smb region uninitialized "
773 +                       "- upgrade BIOS or use force_addr=0xaddr\n");
774 +               return -ENODEV;
775 +       }
776 +
777 +       if(force_addr)
778 +               ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
779 +
780 +       if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) {
781 +               dev_err(ALI15X3_dev,
782 +                       "ALI15X3_smb region 0x%x already in use!\n",
783 +                       ali15x3_smba);
784 +               return -ENODEV;
785 +       }
786 +
787 +       if(force_addr) {
788 +               dev_info(ALI15X3_dev, "forcing ISA address 0x%04X\n",
789 +                       ali15x3_smba);
790 +               if (PCIBIOS_SUCCESSFUL !=
791 +                   pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba))
792 +                       return -ENODEV;
793 +               if (PCIBIOS_SUCCESSFUL !=
794 +                   pci_read_config_word(ALI15X3_dev, SMBBA, &a))
795 +                       return -ENODEV;
796 +               if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {
797 +                       /* make sure it works */
798 +                       dev_err(ALI15X3_dev,
799 +                               "force address failed - not supported?\n");
800 +                       return -ENODEV;
801 +               }
802 +       }
803 +       /* check if whole device is enabled */
804 +       pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
805 +       if ((temp & 1) == 0) {
806 +               dev_info(ALI15X3_dev, "enabling SMBus device\n");
807 +               pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);
808 +       }
809 +
810 +       /* Is SMB Host controller enabled? */
811 +       pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
812 +       if ((temp & 1) == 0) {
813 +               dev_info(ALI15X3_dev, "enabling SMBus controller\n");
814 +               pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);
815 +       }
816 +
817 +       /* set SMB clock to 74KHz as recommended in data sheet */
818 +       pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
819 +
820 +       /*
821 +         The interrupt routing for SMB is set up in register 0x77 in the
822 +         1533 ISA Bridge device, NOT in the 7101 device.
823 +         Don't bother with finding the 1533 device and reading the register.
824 +       if ((....... & 0x0F) == 1)
825 +               dev_dbg(ALI15X3_dev, "ALI15X3 using Interrupt 9 for SMBus.\n");
826 +       */
827 +       pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
828 +       dev_dbg(ALI15X3_dev, "SMBREV = 0x%X\n", temp);
829 +       dev_dbg(ALI15X3_dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba);
830 +
831 +       return 0;
832 +}
833 +
834 +/* Another internally used function */
835 +static int ali15x3_transaction(struct i2c_adapter *adap)
836 +{
837 +       int temp;
838 +       int result = 0;
839 +       int timeout = 0;
840 +
841 +       dev_dbg(adap, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, "
842 +               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
843 +               inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
844 +               inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
845 +
846 +       /* get status */
847 +       temp = inb_p(SMBHSTSTS);
848 +
849 +       /* Make sure the SMBus host is ready to start transmitting */
850 +       /* Check the busy bit first */
851 +       if (temp & ALI15X3_STS_BUSY) {
852 +       /*
853 +          If the host controller is still busy, it may have timed out in the
854 +          previous transaction, resulting in a "SMBus Timeout" Dev.
855 +          I've tried the following to reset a stuck busy bit.
856 +               1. Reset the controller with an ABORT command.
857 +                  (this doesn't seem to clear the controller if an external
858 +                  device is hung)
859 +               2. Reset the controller and the other SMBus devices with a
860 +                  T_OUT command.  (this clears the host busy bit if an
861 +                  external device is hung, but it comes back upon a new access
862 +                  to a device)
863 +               3. Disable and reenable the controller in SMBHSTCFG
864 +          Worst case, nothing seems to work except power reset.
865 +       */
866 +       /* Abort - reset the host controller */
867 +       /*
868 +          Try resetting entire SMB bus, including other devices -
869 +          This may not work either - it clears the BUSY bit but
870 +          then the BUSY bit may come back on when you try and use the chip again.
871 +          If that's the case you are stuck.
872 +       */
873 +               dev_info(adap, "Resetting entire SMB Bus to "
874 +                       "clear busy condition (%02x)\n", temp);
875 +               outb_p(ALI15X3_T_OUT, SMBHSTCNT);
876 +               temp = inb_p(SMBHSTSTS);
877 +       }
878 +
879 +       /* now check the error bits and the busy bit */
880 +       if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
881 +               /* do a clear-on-write */
882 +               outb_p(0xFF, SMBHSTSTS);
883 +               if ((temp = inb_p(SMBHSTSTS)) &
884 +                   (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
885 +                       /* this is probably going to be correctable only by a power reset
886 +                          as one of the bits now appears to be stuck */
887 +                       /* This may be a bus or device with electrical problems. */
888 +                       dev_err(adap, "SMBus reset failed! (0x%02x) - "
889 +                               "controller or device on bus is probably hung\n",
890 +                               temp);
891 +                       return -1;
892 +               }
893 +       } else {
894 +               /* check and clear done bit */
895 +               if (temp & ALI15X3_STS_DONE) {
896 +                       outb_p(temp, SMBHSTSTS);
897 +               }
898 +       }
899 +
900 +       /* start the transaction by writing anything to the start register */
901 +       outb_p(0xFF, SMBHSTSTART);
902 +
903 +       /* We will always wait for a fraction of a second! */
904 +       timeout = 0;
905 +       do {
906 +               i2c_delay(1);
907 +               temp = inb_p(SMBHSTSTS);
908 +       } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
909 +                && (timeout++ < MAX_TIMEOUT));
910 +
911 +       /* If the SMBus is still busy, we give up */
912 +       if (timeout >= MAX_TIMEOUT) {
913 +               result = -1;
914 +               dev_err(adap, "SMBus Timeout!\n");
915 +       }
916 +
917 +       if (temp & ALI15X3_STS_TERM) {
918 +               result = -1;
919 +               dev_dbg(adap, "Error: Failed bus transaction\n");
920 +       }
921 +
922 +       /*
923 +         Unfortunately the ALI SMB controller maps "no response" and "bus
924 +         collision" into a single bit. No reponse is the usual case so don't
925 +         do a printk.
926 +         This means that bus collisions go unreported.
927 +       */
928 +       if (temp & ALI15X3_STS_COLL) {
929 +               result = -1;
930 +               dev_dbg(adap,
931 +                       "Error: no response or bus collision ADD=%02x\n",
932 +                       inb_p(SMBHSTADD));
933 +       }
934 +
935 +       /* haven't ever seen this */
936 +       if (temp & ALI15X3_STS_DEV) {
937 +               result = -1;
938 +               dev_err(adap, "Error: device error\n");
939 +       }
940 +       dev_dbg(adap, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "
941 +               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
942 +               inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
943 +               inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
944 +       return result;
945 +}
946 +
947 +/* Return -1 on error. */
948 +static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
949 +                  unsigned short flags, char read_write, u8 command,
950 +                  int size, union i2c_smbus_data * data)
951 +{
952 +       int i, len;
953 +       int temp;
954 +       int timeout;
955 +
956 +       /* clear all the bits (clear-on-write) */
957 +       outb_p(0xFF, SMBHSTSTS);
958 +       /* make sure SMBus is idle */
959 +       temp = inb_p(SMBHSTSTS);
960 +       for (timeout = 0;
961 +            (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
962 +            timeout++) {
963 +               i2c_delay(1);
964 +               temp = inb_p(SMBHSTSTS);
965 +       }
966 +       if (timeout >= MAX_TIMEOUT) {
967 +               dev_err(adap, "Idle wait Timeout! STS=0x%02x\n", temp);
968 +       }
969 +
970 +       switch (size) {
971 +       case I2C_SMBUS_QUICK:
972 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
973 +                      SMBHSTADD);
974 +               size = ALI15X3_QUICK;
975 +               break;
976 +       case I2C_SMBUS_BYTE:
977 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
978 +                      SMBHSTADD);
979 +               if (read_write == I2C_SMBUS_WRITE)
980 +                       outb_p(command, SMBHSTCMD);
981 +               size = ALI15X3_BYTE;
982 +               break;
983 +       case I2C_SMBUS_BYTE_DATA:
984 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
985 +                      SMBHSTADD);
986 +               outb_p(command, SMBHSTCMD);
987 +               if (read_write == I2C_SMBUS_WRITE)
988 +                       outb_p(data->byte, SMBHSTDAT0);
989 +               size = ALI15X3_BYTE_DATA;
990 +               break;
991 +       case I2C_SMBUS_WORD_DATA:
992 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
993 +                      SMBHSTADD);
994 +               outb_p(command, SMBHSTCMD);
995 +               if (read_write == I2C_SMBUS_WRITE) {
996 +                       outb_p(data->word & 0xff, SMBHSTDAT0);
997 +                       outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
998 +               }
999 +               size = ALI15X3_WORD_DATA;
1000 +               break;
1001 +       case I2C_SMBUS_BLOCK_DATA:
1002 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
1003 +                      SMBHSTADD);
1004 +               outb_p(command, SMBHSTCMD);
1005 +               if (read_write == I2C_SMBUS_WRITE) {
1006 +                       len = data->block[0];
1007 +                       if (len < 0) {
1008 +                               len = 0;
1009 +                               data->block[0] = len;
1010 +                       }
1011 +                       if (len > 32) {
1012 +                               len = 32;
1013 +                               data->block[0] = len;
1014 +                       }
1015 +                       outb_p(len, SMBHSTDAT0);
1016 +                       /* Reset SMBBLKDAT */
1017 +                       outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
1018 +                       for (i = 1; i <= len; i++)
1019 +                               outb_p(data->block[i], SMBBLKDAT);
1020 +               }
1021 +               size = ALI15X3_BLOCK_DATA;
1022 +               break;
1023 +       default:
1024 +               printk
1025 +                   (KERN_WARNING "i2c-ali15x3.o: Unsupported transaction %d\n", size);
1026 +               return -1;
1027 +       }
1028 +
1029 +       outb_p(size, SMBHSTCNT);        /* output command */
1030 +
1031 +       if (ali15x3_transaction(adap))  /* Error in transaction */
1032 +               return -1;
1033 +
1034 +       if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
1035 +               return 0;
1036 +
1037 +
1038 +       switch (size) {
1039 +       case ALI15X3_BYTE:      /* Result put in SMBHSTDAT0 */
1040 +               data->byte = inb_p(SMBHSTDAT0);
1041 +               break;
1042 +       case ALI15X3_BYTE_DATA:
1043 +               data->byte = inb_p(SMBHSTDAT0);
1044 +               break;
1045 +       case ALI15X3_WORD_DATA:
1046 +               data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
1047 +               break;
1048 +       case ALI15X3_BLOCK_DATA:
1049 +               len = inb_p(SMBHSTDAT0);
1050 +               if (len > 32)
1051 +                       len = 32;
1052 +               data->block[0] = len;
1053 +               /* Reset SMBBLKDAT */
1054 +               outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
1055 +               for (i = 1; i <= data->block[0]; i++) {
1056 +                       data->block[i] = inb_p(SMBBLKDAT);
1057 +                       dev_dbg(adap, "Blk: len=%d, i=%d, data=%02x\n",
1058 +                               len, i, data->block[i]);
1059 +               }
1060 +               break;
1061 +       }
1062 +       return 0;
1063 +}
1064 +
1065 +static u32 ali15x3_func(struct i2c_adapter *adapter)
1066 +{
1067 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
1068 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
1069 +           I2C_FUNC_SMBUS_BLOCK_DATA;
1070 +}
1071 +
1072 +static struct i2c_algorithm smbus_algorithm = {
1073 +       .name           = "Non-I2C SMBus adapter",
1074 +       .id             = I2C_ALGO_SMBUS,
1075 +       .smbus_xfer     = ali15x3_access,
1076 +       .functionality  = ali15x3_func,
1077 +};
1078 +
1079 +static struct i2c_adapter ali15x3_adapter = {
1080 +       .owner          = THIS_MODULE,
1081 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
1082 +       .algo           = &smbus_algorithm,
1083 +       .name   = "unset",
1084 +};
1085 +
1086 +static struct pci_device_id ali15x3_ids[] __devinitdata = {
1087 +       {
1088 +       .vendor =       PCI_VENDOR_ID_AL,
1089 +       .device =       PCI_DEVICE_ID_AL_M7101,
1090 +       .subvendor =    PCI_ANY_ID,
1091 +       .subdevice =    PCI_ANY_ID,
1092 +       },
1093 +       { 0, }
1094 +};
1095 +
1096 +static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
1097 +{
1098 +       if (ali15x3_setup(dev)) {
1099 +               dev_err(dev,
1100 +                       "ALI15X3 not detected, module not inserted.\n");
1101 +               return -ENODEV;
1102 +       }
1103 +
1104 +       snprintf(ali15x3_adapter.name, 32,
1105 +               "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
1106 +       return i2c_add_adapter(&ali15x3_adapter);
1107 +}
1108 +
1109 +static void __devexit ali15x3_remove(struct pci_dev *dev)
1110 +{
1111 +       i2c_del_adapter(&ali15x3_adapter);
1112 +       release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
1113 +}
1114 +
1115 +static struct pci_driver ali15x3_driver = {
1116 +       .name           = "ali15x3 smbus",
1117 +       .id_table       = ali15x3_ids,
1118 +       .probe          = ali15x3_probe,
1119 +       .remove         = __devexit_p(ali15x3_remove),
1120 +};
1121 +
1122 +static int __init i2c_ali15x3_init(void)
1123 +{
1124 +       printk("i2c-ali15x3.o version %s (%s)\n", LM_VERSION, LM_DATE);
1125 +       return pci_module_init(&ali15x3_driver);
1126 +}
1127 +
1128 +static void __exit i2c_ali15x3_exit(void)
1129 +{
1130 +       pci_unregister_driver(&ali15x3_driver);
1131 +}
1132 +
1133 +MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
1134 +               "Philip Edelbrock <phil@netroedge.com>, "
1135 +               "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
1136 +MODULE_DESCRIPTION("ALI15X3 SMBus driver");
1137 +MODULE_LICENSE("GPL");
1138 +
1139 +module_init(i2c_ali15x3_init);
1140 +module_exit(i2c_ali15x3_exit);
1141 --- linux-old/drivers/i2c/i2c-amd756.c  Thu Jan  1 00:00:00 1970
1142 +++ linux/drivers/i2c/i2c-amd756.c      Mon Dec 13 20:18:41 2004
1143 @@ -0,0 +1,425 @@
1144 +/*
1145 +    amd756.c - Part of lm_sensors, Linux kernel modules for hardware
1146 +              monitoring
1147 +
1148 +    Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
1149 +
1150 +    Shamelessly ripped from i2c-piix4.c:
1151 +
1152 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
1153 +    Philip Edelbrock <phil@netroedge.com>
1154 +
1155 +    This program is free software; you can redistribute it and/or modify
1156 +    it under the terms of the GNU General Public License as published by
1157 +    the Free Software Foundation; either version 2 of the License, or
1158 +    (at your option) any later version.
1159 +
1160 +    This program is distributed in the hope that it will be useful,
1161 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
1162 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1163 +    GNU General Public License for more details.
1164 +
1165 +    You should have received a copy of the GNU General Public License
1166 +    along with this program; if not, write to the Free Software
1167 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1168 +*/
1169 +
1170 +/*
1171 +    2002-04-08: Added nForce support. (Csaba Halasz)
1172 +    2002-10-03: Fixed nForce PnP I/O port. (Michael Steil)
1173 +    2002-12-28: Rewritten into something that resembles a Linux driver (hch)
1174 +    2003-11-29: Added back AMD8111 removed by the previous rewrite.
1175 +                (Philip Pokorny)
1176 +    2004-02-15: Don't register driver to avoid driver conflicts.
1177 +                (Daniel Rune Jensen)
1178 +*/
1179 +
1180 +/*
1181 +   Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce
1182 +   Note: we assume there can only be one device, with one SMBus interface.
1183 +*/
1184 +
1185 +#include <linux/module.h>
1186 +#include <linux/pci.h>
1187 +#include <linux/kernel.h>
1188 +#include <linux/stddef.h>
1189 +#include <linux/sched.h>
1190 +#include <linux/ioport.h>
1191 +#include <linux/i2c.h>
1192 +#include <linux/init.h>
1193 +#include <asm/io.h>
1194 +#define LM_DATE "20041007"
1195 +#define LM_VERSION "2.8.8"
1196 +
1197 +#define DRV_NAME       "i2c-amd756"
1198 +
1199 +/* AMD756 SMBus address offsets */
1200 +#define SMB_ADDR_OFFSET        0xE0
1201 +#define SMB_IOSIZE             16
1202 +#define SMB_GLOBAL_STATUS      (0x0 + amd756_ioport)
1203 +#define SMB_GLOBAL_ENABLE      (0x2 + amd756_ioport)
1204 +#define SMB_HOST_ADDRESS       (0x4 + amd756_ioport)
1205 +#define SMB_HOST_DATA          (0x6 + amd756_ioport)
1206 +#define SMB_HOST_COMMAND       (0x8 + amd756_ioport)
1207 +#define SMB_HOST_BLOCK_DATA    (0x9 + amd756_ioport)
1208 +#define SMB_HAS_DATA           (0xA + amd756_ioport)
1209 +#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport)
1210 +#define SMB_HAS_HOST_ADDRESS   (0xE + amd756_ioport)
1211 +#define SMB_SNOOP_ADDRESS      (0xF + amd756_ioport)
1212 +
1213 +/* PCI Address Constants */
1214 +
1215 +/* address of I/O space */
1216 +#define SMBBA     0x058                /* mh */
1217 +#define SMBBANFORCE     0x014
1218 +
1219 +/* general configuration */
1220 +#define SMBGCFG   0x041                /* mh */
1221 +
1222 +/* silicon revision code */
1223 +#define SMBREV    0x008
1224 +
1225 +/* Other settings */
1226 +#define MAX_TIMEOUT 500
1227 +
1228 +/* AMD756 constants */
1229 +#define AMD756_QUICK        0x00
1230 +#define AMD756_BYTE         0x01
1231 +#define AMD756_BYTE_DATA    0x02
1232 +#define AMD756_WORD_DATA    0x03
1233 +#define AMD756_PROCESS_CALL 0x04
1234 +#define AMD756_BLOCK_DATA   0x05
1235 +
1236 +
1237 +static unsigned short amd756_ioport = 0;
1238 +
1239 +/* 
1240 +  SMBUS event = I/O 28-29 bit 11
1241 +     see E0 for the status bits and enabled in E2
1242 +     
1243 +*/
1244 +
1245 +#define GS_ABRT_STS (1 << 0)
1246 +#define GS_COL_STS (1 << 1)
1247 +#define GS_PRERR_STS (1 << 2)
1248 +#define GS_HST_STS (1 << 3)
1249 +#define GS_HCYC_STS (1 << 4)
1250 +#define GS_TO_STS (1 << 5)
1251 +#define GS_SMB_STS (1 << 11)
1252 +
1253 +#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \
1254 +  GS_HCYC_STS | GS_TO_STS )
1255 +
1256 +#define GE_CYC_TYPE_MASK (7)
1257 +#define GE_HOST_STC (1 << 3)
1258 +#define GE_ABORT (1 << 5)
1259 +
1260 +
1261 +static int amd756_transaction(void)
1262 +{
1263 +       int temp;
1264 +       int result = 0;
1265 +       int timeout = 0;
1266 +
1267 +       pr_debug(DRV_NAME
1268 +              ": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
1269 +              inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
1270 +              inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
1271 +
1272 +       /* Make sure the SMBus host is ready to start transmitting */
1273 +       if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) {
1274 +               pr_debug(DRV_NAME ": SMBus busy (%04x). Waiting... \n", temp);
1275 +               do {
1276 +                       i2c_delay(1);
1277 +                       temp = inw_p(SMB_GLOBAL_STATUS);
1278 +               } while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
1279 +                        (timeout++ < MAX_TIMEOUT));
1280 +               /* If the SMBus is still busy, we give up */
1281 +               if (timeout >= MAX_TIMEOUT) {
1282 +                       pr_debug(DRV_NAME ": Busy wait timeout (%04x)\n", temp);
1283 +                       goto abort;
1284 +               }
1285 +               timeout = 0;
1286 +       }
1287 +
1288 +       /* start the transaction by setting the start bit */
1289 +       outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);
1290 +
1291 +       /* We will always wait for a fraction of a second! */
1292 +       do {
1293 +               i2c_delay(1);
1294 +               temp = inw_p(SMB_GLOBAL_STATUS);
1295 +       } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
1296 +
1297 +       /* If the SMBus is still busy, we give up */
1298 +       if (timeout >= MAX_TIMEOUT) {
1299 +               pr_debug(DRV_NAME ": Completion timeout!\n");
1300 +               goto abort;
1301 +       }
1302 +
1303 +       if (temp & GS_PRERR_STS) {
1304 +               result = -1;
1305 +               pr_debug(DRV_NAME ": SMBus Protocol error (no response)!\n");
1306 +       }
1307 +
1308 +       if (temp & GS_COL_STS) {
1309 +               result = -1;
1310 +               printk(KERN_WARNING DRV_NAME ": SMBus collision!\n");
1311 +       }
1312 +
1313 +       if (temp & GS_TO_STS) {
1314 +               result = -1;
1315 +               pr_debug(DRV_NAME ": SMBus protocol timeout!\n");
1316 +       }
1317 +
1318 +       if (temp & GS_HCYC_STS)
1319 +               pr_debug(DRV_NAME ": SMBus protocol success!\n");
1320 +
1321 +       outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
1322 +
1323 +#ifdef DEBUG
1324 +       if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
1325 +               pr_debug(DRV_NAME
1326 +                        ": Failed reset at end of transaction (%04x)\n", temp);
1327 +       }
1328 +
1329 +       pr_debug(DRV_NAME
1330 +                ": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
1331 +                inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
1332 +                inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
1333 +#endif
1334 +
1335 +       return result;
1336 +
1337 + abort:
1338 +       printk(KERN_WARNING DRV_NAME ": Sending abort.\n");
1339 +       outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
1340 +       i2c_delay(100);
1341 +       outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
1342 +       return -1;
1343 +}
1344 +
1345 +/* Return -1 on error. */
1346 +
1347 +static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
1348 +                 unsigned short flags, char read_write,
1349 +                 u8 command, int size, union i2c_smbus_data * data)
1350 +{
1351 +       int i, len;
1352 +
1353 +       /** TODO: Should I supporte the 10-bit transfers? */
1354 +       switch (size) {
1355 +       /* TODO: proc call is supported, I'm just not sure what to do here... */
1356 +       case I2C_SMBUS_QUICK:
1357 +               outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
1358 +                      SMB_HOST_ADDRESS);
1359 +               size = AMD756_QUICK;
1360 +               break;
1361 +       case I2C_SMBUS_BYTE:
1362 +               outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
1363 +                      SMB_HOST_ADDRESS);
1364 +               if (read_write == I2C_SMBUS_WRITE)
1365 +                       outb_p(command, SMB_HOST_DATA);
1366 +               size = AMD756_BYTE;
1367 +               break;
1368 +       case I2C_SMBUS_BYTE_DATA:
1369 +               outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
1370 +                      SMB_HOST_ADDRESS);
1371 +               outb_p(command, SMB_HOST_COMMAND);
1372 +               if (read_write == I2C_SMBUS_WRITE)
1373 +                       outw_p(data->byte, SMB_HOST_DATA);
1374 +               size = AMD756_BYTE_DATA;
1375 +               break;
1376 +       case I2C_SMBUS_WORD_DATA:
1377 +               outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
1378 +                      SMB_HOST_ADDRESS);
1379 +               outb_p(command, SMB_HOST_COMMAND);
1380 +               if (read_write == I2C_SMBUS_WRITE)
1381 +                       outw_p(data->word, SMB_HOST_DATA);      /* TODO: endian???? */
1382 +               size = AMD756_WORD_DATA;
1383 +               break;
1384 +       case I2C_SMBUS_BLOCK_DATA:
1385 +               outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
1386 +                      SMB_HOST_ADDRESS);
1387 +               outb_p(command, SMB_HOST_COMMAND);
1388 +               if (read_write == I2C_SMBUS_WRITE) {
1389 +                       len = data->block[0];
1390 +                       if (len < 0)
1391 +                               len = 0;
1392 +                       if (len > 32)
1393 +                               len = 32;
1394 +                       outw_p(len, SMB_HOST_DATA);
1395 +                       /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
1396 +                       for (i = 1; i <= len; i++)
1397 +                               outb_p(data->block[i],
1398 +                                      SMB_HOST_BLOCK_DATA);
1399 +               }
1400 +               size = AMD756_BLOCK_DATA;
1401 +               break;
1402 +       default:
1403 +               printk
1404 +                   (KERN_WARNING "i2c-amd756.o: Unsupported transaction %d\n", size);
1405 +               return -1;
1406 +       }
1407 +
1408 +       /* How about enabling interrupts... */
1409 +       outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
1410 +
1411 +       if (amd756_transaction())       /* Error in transaction */
1412 +               return -1;
1413 +
1414 +       if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
1415 +               return 0;
1416 +
1417 +
1418 +       switch (size) {
1419 +       case AMD756_BYTE:
1420 +               data->byte = inw_p(SMB_HOST_DATA);
1421 +               break;
1422 +       case AMD756_BYTE_DATA:
1423 +               data->byte = inw_p(SMB_HOST_DATA);
1424 +               break;
1425 +       case AMD756_WORD_DATA:
1426 +               data->word = inw_p(SMB_HOST_DATA);      /* TODO: endian???? */
1427 +               break;
1428 +       case AMD756_BLOCK_DATA:
1429 +               data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f;
1430 +               if(data->block[0] > 32)
1431 +                       data->block[0] = 32;
1432 +               /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
1433 +               for (i = 1; i <= data->block[0]; i++)
1434 +                       data->block[i] = inb_p(SMB_HOST_BLOCK_DATA);
1435 +               break;
1436 +       }
1437 +
1438 +       return 0;
1439 +}
1440 +
1441 +static u32 amd756_func(struct i2c_adapter *adapter)
1442 +{
1443 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
1444 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
1445 +           I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
1446 +}
1447 +
1448 +static struct i2c_algorithm smbus_algorithm = {
1449 +       .name           = "Non-I2C SMBus adapter",
1450 +       .id             = I2C_ALGO_SMBUS,
1451 +       .smbus_xfer     = amd756_access,
1452 +       .functionality  = amd756_func,
1453 +};
1454 +
1455 +static struct i2c_adapter amd756_adapter = {
1456 +       .owner          = THIS_MODULE,
1457 +       .name           = "unset",
1458 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
1459 +       .algo           = &smbus_algorithm,
1460 +};
1461 +
1462 +enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
1463 +
1464 +static struct pci_device_id amd756_ids[] __devinitdata = {
1465 +       {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 },
1466 +       {PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 },
1467 +       {PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 },
1468 +       {PCI_VENDOR_ID_AMD, 0x746B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111 },
1469 +       {PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE },
1470 +       { 0, }
1471 +};
1472 +
1473 +static int __devinit amd756_probe(struct pci_dev *pdev,
1474 +                                 const struct pci_device_id *id)
1475 +{
1476 +       int nforce = (id->driver_data == NFORCE);
1477 +       int error;
1478 +       u8 temp;
1479 +       
1480 +       if (amd756_ioport) {
1481 +               printk(KERN_ERR DRV_NAME ": Only one device supported. "
1482 +                      "(you have a strange motherboard, btw..)\n");
1483 +               return -ENODEV;
1484 +       }
1485 +
1486 +       if (nforce) {
1487 +               if (PCI_FUNC(pdev->devfn) != 1)
1488 +                       return -ENODEV;
1489 +
1490 +               pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport);
1491 +               amd756_ioport &= 0xfffc;
1492 +       } else { /* amd */
1493 +               if (PCI_FUNC(pdev->devfn) != 3)
1494 +                       return -ENODEV;
1495 +
1496 +               pci_read_config_byte(pdev, SMBGCFG, &temp);
1497 +               if ((temp & 128) == 0) {
1498 +                       printk(KERN_ERR DRV_NAME
1499 +                              ": Error: SMBus controller I/O not enabled!\n");
1500 +                       return -ENODEV;
1501 +               }
1502 +
1503 +               /* Determine the address of the SMBus areas */
1504 +               /* Technically it is a dword but... */
1505 +               pci_read_config_word(pdev, SMBBA, &amd756_ioport);
1506 +               amd756_ioport &= 0xff00;
1507 +               amd756_ioport += SMB_ADDR_OFFSET;
1508 +       }
1509 +
1510 +       if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) {
1511 +               printk(KERN_ERR DRV_NAME
1512 +                      ": SMB region 0x%x already in use!\n", amd756_ioport);
1513 +               return -ENODEV;
1514 +       }
1515 +
1516 +#ifdef DEBUG
1517 +       pci_read_config_byte(pdev, SMBREV, &temp);
1518 +       printk(KERN_DEBUG DRV_NAME ": SMBREV = 0x%X\n", temp);
1519 +       printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport);
1520 +#endif
1521 +
1522 +       sprintf(amd756_adapter.name,
1523 +               "SMBus AMD756 adapter at %04x", amd756_ioport);
1524 +
1525 +       error = i2c_add_adapter(&amd756_adapter);
1526 +       if (error) {
1527 +               printk(KERN_ERR DRV_NAME
1528 +                      ": Adapter registration failed, module not inserted.\n");
1529 +               goto out_err;
1530 +       }
1531 +
1532 +       return 0;
1533 +
1534 + out_err:
1535 +       release_region(amd756_ioport, SMB_IOSIZE);
1536 +       return error;
1537 +}
1538 +
1539 +
1540 +static int __init i2c_amd756_init(void)
1541 +{
1542 +       struct pci_dev *dev;
1543 +       const struct pci_device_id *id;
1544 +
1545 +       printk(KERN_INFO "i2c-amd756.o version %s (%s)\n", LM_VERSION, LM_DATE);
1546 +
1547 +       pci_for_each_dev(dev) {
1548 +               id = pci_match_device(amd756_ids, dev);
1549 +               if (id && amd756_probe(dev, id) >= 0)
1550 +                       return 0; 
1551 +       }
1552 +
1553 +       return -ENODEV;
1554 +}
1555 +
1556 +
1557 +static void __exit i2c_amd756_exit(void)
1558 +{
1559 +       i2c_del_adapter(&amd756_adapter);
1560 +       release_region(amd756_ioport, SMB_IOSIZE);
1561 +}
1562 +
1563 +MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
1564 +MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver");
1565 +MODULE_LICENSE("GPL");
1566 +
1567 +module_init(i2c_amd756_init)
1568 +module_exit(i2c_amd756_exit)
1569 --- linux-old/drivers/i2c/i2c-amd8111.c Thu Jan  1 00:00:00 1970
1570 +++ linux/drivers/i2c/i2c-amd8111.c     Mon Dec 13 20:18:41 2004
1571 @@ -0,0 +1,421 @@
1572 +/*
1573 + * SMBus 2.0 driver for AMD-8111 IO-Hub.
1574 + *
1575 + * Copyright (c) 2002 Vojtech Pavlik
1576 + *
1577 + * This program is free software; you can redistribute it and/or modify
1578 + * it under the terms of the GNU General Public License as published by
1579 + * the Free Software Foundation version 2.
1580 + */
1581 +
1582 +#include <linux/module.h>
1583 +#include <linux/pci.h>
1584 +#include <linux/kernel.h>
1585 +#include <linux/stddef.h>
1586 +#include <linux/sched.h>
1587 +#include <linux/ioport.h>
1588 +#include <linux/init.h>
1589 +#include <linux/i2c.h>
1590 +#include <linux/delay.h>
1591 +#include <linux/slab.h>
1592 +#include <asm/io.h>
1593 +#define LM_DATE "20041007"
1594 +#define LM_VERSION "2.8.8"
1595 +
1596 +#ifndef I2C_HW_SMBUS_AMD8111
1597 +#error Your i2c is too old - i2c-2.7.0 or greater required!
1598 +#endif
1599 +
1600 +/* kernel 2.4.9 needs this */
1601 +#ifndef min_t
1602 +#define min_t(type,x,y) min(type,x,y)
1603 +#endif
1604 +
1605 +MODULE_LICENSE("GPL");
1606 +MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
1607 +MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
1608 +
1609 +struct amd_smbus {
1610 +       struct pci_dev *dev;
1611 +       struct i2c_adapter adapter;
1612 +       int base;
1613 +       int size;
1614 +};
1615 +
1616 +/*
1617 + * AMD PCI control registers definitions.
1618 + */
1619 +
1620 +#define AMD_PCI_MISC   0x48
1621 +
1622 +#define AMD_PCI_MISC_SCI       0x04    /* deliver SCI */
1623 +#define AMD_PCI_MISC_INT       0x02    /* deliver PCI IRQ */
1624 +#define AMD_PCI_MISC_SPEEDUP   0x01    /* 16x clock speedup */
1625 +
1626 +/*
1627 + * ACPI 2.0 chapter 13 PCI interface definitions.
1628 + */
1629 +
1630 +#define AMD_EC_DATA    0x00    /* data register */
1631 +#define AMD_EC_SC      0x04    /* status of controller */
1632 +#define AMD_EC_CMD     0x04    /* command register */
1633 +#define AMD_EC_ICR     0x08    /* interrupt control register */
1634 +
1635 +#define AMD_EC_SC_SMI  0x04    /* smi event pending */
1636 +#define AMD_EC_SC_SCI  0x02    /* sci event pending */
1637 +#define AMD_EC_SC_BURST        0x01    /* burst mode enabled */
1638 +#define AMD_EC_SC_CMD  0x08    /* byte in data reg is command */
1639 +#define AMD_EC_SC_IBF  0x02    /* data ready for embedded controller */
1640 +#define AMD_EC_SC_OBF  0x01    /* data ready for host */
1641 +
1642 +#define AMD_EC_CMD_RD  0x80    /* read EC */
1643 +#define AMD_EC_CMD_WR  0x81    /* write EC */
1644 +#define AMD_EC_CMD_BE  0x82    /* enable burst mode */
1645 +#define AMD_EC_CMD_BD  0x83    /* disable burst mode */
1646 +#define AMD_EC_CMD_QR  0x84    /* query EC */
1647 +
1648 +/*
1649 + * ACPI 2.0 chapter 13 access of registers of the EC
1650 + */
1651 +
1652 +unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
1653 +{
1654 +       int timeout = 500;
1655 +
1656 +       while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF))
1657 +               udelay(1);
1658 +
1659 +       if (!timeout) {
1660 +               printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for IBF to clear\n");
1661 +               return -1;
1662 +       }
1663 +
1664 +       return 0;
1665 +}
1666 +
1667 +unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
1668 +{
1669 +       int timeout = 500;
1670 +
1671 +       while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF))
1672 +               udelay(1);
1673 +
1674 +       if (!timeout) {
1675 +               printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for OBF to set\n");
1676 +               return -1;
1677 +       }
1678 +
1679 +       return 0;
1680 +}
1681 +
1682 +unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data)
1683 +{
1684 +       if (amd_ec_wait_write(smbus))
1685 +               return -1;
1686 +       outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
1687 +
1688 +       if (amd_ec_wait_write(smbus))
1689 +               return -1;
1690 +       outb(address, smbus->base + AMD_EC_DATA);
1691 +
1692 +       if (amd_ec_wait_read(smbus))
1693 +               return -1;
1694 +       *data = inb(smbus->base + AMD_EC_DATA);
1695 +
1696 +       return 0;
1697 +}
1698 +
1699 +unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data)
1700 +{
1701 +       if (amd_ec_wait_write(smbus))
1702 +               return -1;
1703 +       outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
1704 +
1705 +       if (amd_ec_wait_write(smbus))
1706 +               return -1;
1707 +       outb(address, smbus->base + AMD_EC_DATA);
1708 +
1709 +       if (amd_ec_wait_write(smbus))
1710 +               return -1;
1711 +       outb(data, smbus->base + AMD_EC_DATA);
1712 +
1713 +       return 0;
1714 +}
1715 +
1716 +/*
1717 + * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
1718 + */
1719 +
1720 +#define AMD_SMB_PRTCL  0x00    /* protocol, PEC */
1721 +#define AMD_SMB_STS    0x01    /* status */
1722 +#define AMD_SMB_ADDR   0x02    /* address */
1723 +#define AMD_SMB_CMD    0x03    /* command */
1724 +#define AMD_SMB_DATA   0x04    /* 32 data registers */
1725 +#define AMD_SMB_BCNT   0x24    /* number of data bytes */
1726 +#define AMD_SMB_ALRM_A 0x25    /* alarm address */
1727 +#define AMD_SMB_ALRM_D 0x26    /* 2 bytes alarm data */
1728 +
1729 +#define AMD_SMB_STS_DONE       0x80
1730 +#define AMD_SMB_STS_ALRM       0x40
1731 +#define AMD_SMB_STS_RES                0x20
1732 +#define AMD_SMB_STS_STATUS     0x1f
1733 +
1734 +#define AMD_SMB_STATUS_OK      0x00
1735 +#define AMD_SMB_STATUS_FAIL    0x07
1736 +#define AMD_SMB_STATUS_DNAK    0x10
1737 +#define AMD_SMB_STATUS_DERR    0x11
1738 +#define AMD_SMB_STATUS_CMD_DENY        0x12
1739 +#define AMD_SMB_STATUS_UNKNOWN 0x13
1740 +#define AMD_SMB_STATUS_ACC_DENY        0x17
1741 +#define AMD_SMB_STATUS_TIMEOUT 0x18
1742 +#define AMD_SMB_STATUS_NOTSUP  0x19
1743 +#define AMD_SMB_STATUS_BUSY    0x1A
1744 +#define AMD_SMB_STATUS_PEC     0x1F
1745 +
1746 +#define AMD_SMB_PRTCL_WRITE            0x00
1747 +#define AMD_SMB_PRTCL_READ             0x01
1748 +#define AMD_SMB_PRTCL_QUICK            0x02
1749 +#define AMD_SMB_PRTCL_BYTE             0x04
1750 +#define AMD_SMB_PRTCL_BYTE_DATA                0x06
1751 +#define AMD_SMB_PRTCL_WORD_DATA                0x08
1752 +#define AMD_SMB_PRTCL_BLOCK_DATA       0x0a
1753 +#define AMD_SMB_PRTCL_PROC_CALL                0x0c
1754 +#define AMD_SMB_PRTCL_BLOCK_PROC_CALL  0x0d
1755 +#define AMD_SMB_PRTCL_I2C_BLOCK_DATA   0x4a
1756 +#define AMD_SMB_PRTCL_PEC              0x80
1757 +
1758 +
1759 +s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
1760 +               char read_write, u8 command, int size, union i2c_smbus_data * data)
1761 +{
1762 +       struct amd_smbus *smbus = adap->algo_data;
1763 +       unsigned char protocol, len, pec, temp[2];
1764 +       int i;
1765 +
1766 +       protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE;
1767 +       pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0;
1768 +
1769 +       switch (size) {
1770 +
1771 +               case I2C_SMBUS_QUICK:
1772 +                       protocol |= AMD_SMB_PRTCL_QUICK;
1773 +                       read_write = I2C_SMBUS_WRITE;
1774 +                       break;
1775 +
1776 +               case I2C_SMBUS_BYTE:
1777 +                       if (read_write == I2C_SMBUS_WRITE)
1778 +                               amd_ec_write(smbus, AMD_SMB_CMD, command);
1779 +                       protocol |= AMD_SMB_PRTCL_BYTE;
1780 +                       break;
1781 +
1782 +               case I2C_SMBUS_BYTE_DATA:
1783 +                       amd_ec_write(smbus, AMD_SMB_CMD, command);
1784 +                       if (read_write == I2C_SMBUS_WRITE)
1785 +                               amd_ec_write(smbus, AMD_SMB_DATA, data->byte);
1786 +                       protocol |= AMD_SMB_PRTCL_BYTE_DATA;
1787 +                       break;
1788 +
1789 +               case I2C_SMBUS_WORD_DATA:
1790 +                       amd_ec_write(smbus, AMD_SMB_CMD, command);
1791 +                       if (read_write == I2C_SMBUS_WRITE) {
1792 +                               amd_ec_write(smbus, AMD_SMB_DATA, data->word);
1793 +                               amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
1794 +                       }
1795 +                       protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
1796 +                       break;
1797 +
1798 +               case I2C_SMBUS_BLOCK_DATA:
1799 +                       amd_ec_write(smbus, AMD_SMB_CMD, command);
1800 +                       if (read_write == I2C_SMBUS_WRITE) {
1801 +                               len = min_t(u8, data->block[0], 32);
1802 +                               amd_ec_write(smbus, AMD_SMB_BCNT, len);
1803 +                               for (i = 0; i < len; i++)
1804 +                                       amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
1805 +                       }
1806 +                       protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
1807 +                       break;
1808 +
1809 +               case I2C_SMBUS_I2C_BLOCK_DATA:
1810 +                       len = min_t(u8, data->block[0], 32);
1811 +                       amd_ec_write(smbus, AMD_SMB_CMD, command);
1812 +                       amd_ec_write(smbus, AMD_SMB_BCNT, len);
1813 +                       if (read_write == I2C_SMBUS_WRITE)
1814 +                               for (i = 0; i < len; i++)
1815 +                                       amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
1816 +                       protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
1817 +                       break;
1818 +
1819 +               case I2C_SMBUS_PROC_CALL:
1820 +                       amd_ec_write(smbus, AMD_SMB_CMD, command);
1821 +                       amd_ec_write(smbus, AMD_SMB_DATA, data->word);
1822 +                       amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
1823 +                       protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
1824 +                       read_write = I2C_SMBUS_READ;
1825 +                       break;
1826 +
1827 +               case I2C_SMBUS_BLOCK_PROC_CALL:
1828 +                       protocol |= pec;
1829 +                       len = min_t(u8, data->block[0], 31);
1830 +                       amd_ec_write(smbus, AMD_SMB_CMD, command);
1831 +                       amd_ec_write(smbus, AMD_SMB_BCNT, len);
1832 +                       for (i = 0; i < len; i++)
1833 +                               amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
1834 +                       protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
1835 +                       read_write = I2C_SMBUS_READ;
1836 +                       break;
1837 +
1838 +               case I2C_SMBUS_WORD_DATA_PEC:
1839 +               case I2C_SMBUS_BLOCK_DATA_PEC:
1840 +               case I2C_SMBUS_PROC_CALL_PEC:
1841 +               case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
1842 +                       printk(KERN_WARNING "i2c-amd8111.c: Unexpected software PEC transaction %d\n.", size);
1843 +                       return -1;
1844 +
1845 +               default:
1846 +                       printk(KERN_WARNING "i2c-amd8111.c: Unsupported transaction %d\n", size);
1847 +                       return -1;
1848 +       }
1849 +
1850 +       amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
1851 +       amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
1852 +
1853 +       amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
1854 +
1855 +       if (~temp[0] & AMD_SMB_STS_DONE) {
1856 +               udelay(500);
1857 +               amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
1858 +       }
1859 +
1860 +       if (~temp[0] & AMD_SMB_STS_DONE) {
1861 +               i2c_delay(HZ/100);
1862 +               amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
1863 +       }
1864 +
1865 +       if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
1866 +               return -1;
1867 +
1868 +       if (read_write == I2C_SMBUS_WRITE)
1869 +               return 0;
1870 +
1871 +       switch (size) {
1872 +
1873 +               case I2C_SMBUS_BYTE:
1874 +               case I2C_SMBUS_BYTE_DATA:
1875 +                       amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
1876 +                       break;
1877 +
1878 +               case I2C_SMBUS_WORD_DATA:
1879 +               case I2C_SMBUS_PROC_CALL:
1880 +                       amd_ec_read(smbus, AMD_SMB_DATA, temp + 0);
1881 +                       amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1);
1882 +                       data->word = (temp[1] << 8) | temp[0];
1883 +                       break;
1884 +
1885 +               case I2C_SMBUS_BLOCK_DATA:
1886 +               case I2C_SMBUS_BLOCK_PROC_CALL:
1887 +                       amd_ec_read(smbus, AMD_SMB_BCNT, &len);
1888 +                       len = min_t(u8, len, 32);
1889 +               case I2C_SMBUS_I2C_BLOCK_DATA:
1890 +                       for (i = 0; i < len; i++)
1891 +                               amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1);
1892 +                       data->block[0] = len;
1893 +                       break;
1894 +       }
1895 +
1896 +       return 0;
1897 +}
1898 +
1899 +
1900 +u32 amd8111_func(struct i2c_adapter *adapter)
1901 +{
1902 +       return  I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
1903 +               I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
1904 +               I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
1905 +               I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
1906 +}
1907 +
1908 +static struct i2c_algorithm smbus_algorithm = {
1909 +       .name = "Non-I2C SMBus 2.0 adapter",
1910 +       .id = I2C_ALGO_SMBUS,
1911 +       .smbus_xfer = amd8111_access,
1912 +       .functionality = amd8111_func,
1913 +};
1914 +
1915 +
1916 +static struct pci_device_id amd8111_ids[] __devinitdata = {
1917 +       { 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1918 +       { 0, }
1919 +};
1920 +
1921 +static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
1922 +{
1923 +       struct amd_smbus *smbus;
1924 +       int error;
1925 +
1926 +       if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
1927 +               return -1;
1928 +
1929 +       if (!(smbus = (void*)kmalloc(sizeof(struct amd_smbus), GFP_KERNEL)))
1930 +               return -1;
1931 +       memset(smbus, 0, sizeof(struct amd_smbus));
1932 +
1933 +       pci_set_drvdata(dev, smbus);
1934 +       smbus->dev = dev;
1935 +       smbus->base = pci_resource_start(dev, 0);
1936 +       smbus->size = pci_resource_len(dev, 0);
1937 +
1938 +       if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0")) {
1939 +               kfree(smbus);
1940 +               return -1;
1941 +       }
1942 +
1943 +       smbus->adapter.owner = THIS_MODULE;
1944 +       sprintf(smbus->adapter.name, "SMBus2 AMD8111 adapter at %04x", smbus->base);
1945 +       smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111;
1946 +       smbus->adapter.algo = &smbus_algorithm;
1947 +       smbus->adapter.algo_data = smbus;
1948 +
1949 +       error = i2c_add_adapter(&smbus->adapter);
1950 +       if (error) {
1951 +               printk(KERN_WARNING "i2c-amd8111.c: Failed to register adapter.\n");
1952 +               release_region(smbus->base, smbus->size);
1953 +               kfree(smbus);
1954 +               return -1;
1955 +       }
1956 +
1957 +       pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
1958 +
1959 +       printk(KERN_INFO "i2c-amd8111.c: AMD8111 SMBus 2.0 adapter at %#x\n", smbus->base);
1960 +       return 0;
1961 +}
1962 +
1963 +
1964 +static void __devexit amd8111_remove(struct pci_dev *dev)
1965 +{
1966 +       struct amd_smbus *smbus = (void*) pci_get_drvdata(dev);
1967 +       i2c_del_adapter(&smbus->adapter);
1968 +       release_region(smbus->base, smbus->size);
1969 +       kfree(smbus);
1970 +}
1971 +
1972 +static struct pci_driver amd8111_driver = {
1973 +       .name           = "amd8111 smbus 2.0",
1974 +       .id_table       = amd8111_ids,
1975 +       .probe          = amd8111_probe,
1976 +       .remove         = __devexit_p(amd8111_remove),
1977 +};
1978 +
1979 +static int __init i2c_amd8111_init(void)
1980 +{
1981 +       printk(KERN_INFO "i2c-amd8111.o version %s (%s)\n", LM_VERSION, LM_DATE);
1982 +       return pci_module_init(&amd8111_driver);
1983 +}
1984 +
1985 +
1986 +static void __exit i2c_amd8111_exit(void)
1987 +{
1988 +       pci_unregister_driver(&amd8111_driver);
1989 +}
1990 +
1991 +module_init(i2c_amd8111_init);
1992 +module_exit(i2c_amd8111_exit);
1993 --- linux-old/drivers/i2c/i2c-hydra.c   Thu Jan  1 00:00:00 1970
1994 +++ linux/drivers/i2c/i2c-hydra.c       Mon Dec 13 20:18:41 2004
1995 @@ -0,0 +1,175 @@
1996 +/*
1997 +    i2c-hydra.c - Part of lm_sensors,  Linux kernel modules
1998 +                  for hardware monitoring
1999 +
2000 +    i2c Support for the Apple `Hydra' Mac I/O
2001 +
2002 +    Copyright (c) 1999 Geert Uytterhoeven <geert@linux-m68k.org>
2003 +
2004 +    Based on i2c Support for Via Technologies 82C586B South Bridge
2005 +    Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
2006 +
2007 +    This program is free software; you can redistribute it and/or modify
2008 +    it under the terms of the GNU General Public License as published by
2009 +    the Free Software Foundation; either version 2 of the License, or
2010 +    (at your option) any later version.
2011 +
2012 +    This program is distributed in the hope that it will be useful,
2013 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
2014 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2015 +    GNU General Public License for more details.
2016 +
2017 +    You should have received a copy of the GNU General Public License
2018 +    along with this program; if not, write to the Free Software
2019 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2020 +*/
2021 +
2022 +#include <linux/kernel.h>
2023 +#include <linux/module.h>
2024 +#include <linux/pci.h>
2025 +#include <linux/types.h>
2026 +#include <linux/i2c.h>
2027 +#include <linux/i2c-algo-bit.h>
2028 +#include <linux/init.h>
2029 +#include <asm/io.h>
2030 +#include <asm/system.h>
2031 +#include <asm/param.h> /* for HZ */
2032 +
2033 +MODULE_LICENSE("GPL");
2034 +
2035 +
2036 +#define HYDRA_CACHE_PD 0x00000030
2037 +
2038 +#define HYDRA_CPD_PD0  0x00000001      /* CachePD lines */
2039 +#define HYDRA_CPD_PD1  0x00000002
2040 +#define HYDRA_CPD_PD2  0x00000004
2041 +#define HYDRA_CPD_PD3  0x00000008
2042 +
2043 +#define HYDRA_SCLK     HYDRA_CPD_PD0
2044 +#define HYDRA_SDAT     HYDRA_CPD_PD1
2045 +#define HYDRA_SCLK_OE  0x00000010
2046 +#define HYDRA_SDAT_OE  0x00000020
2047 +
2048 +static unsigned long hydra_base;
2049 +
2050 +static inline void pdregw(u32 val)
2051 +{
2052 +       writel(val, hydra_base + HYDRA_CACHE_PD);
2053 +}
2054 +
2055 +static inline u32 pdregr(void)
2056 +{
2057 +       u32 val = readl(hydra_base + HYDRA_CACHE_PD);
2058 +       return val;
2059 +}
2060 +
2061 +static void bit_hydra_setscl(void *data, int state)
2062 +{
2063 +       u32 val = pdregr();
2064 +       if (state)
2065 +               val &= ~HYDRA_SCLK_OE;
2066 +       else {
2067 +               val &= ~HYDRA_SCLK;
2068 +               val |= HYDRA_SCLK_OE;
2069 +       }
2070 +       pdregw(val);
2071 +       pdregr();       /* flush posted write */
2072 +}
2073 +
2074 +static void bit_hydra_setsda(void *data, int state)
2075 +{
2076 +       u32 val = pdregr();
2077 +       if (state)
2078 +               val &= ~HYDRA_SDAT_OE;
2079 +       else {
2080 +               val &= ~HYDRA_SDAT;
2081 +               val |= HYDRA_SDAT_OE;
2082 +       }
2083 +       pdregw(val);
2084 +       pdregr();       /* flush posted write */
2085 +}
2086 +
2087 +static int bit_hydra_getscl(void *data)
2088 +{
2089 +       return (pdregr() & HYDRA_SCLK) != 0;
2090 +}
2091 +
2092 +static int bit_hydra_getsda(void *data)
2093 +{
2094 +       return (pdregr() & HYDRA_SDAT) != 0;
2095 +}
2096 +
2097 +/* ------------------------------------------------------------------------ */
2098 +
2099 +static struct i2c_algo_bit_data bit_hydra_data = {
2100 +       .setsda         = bit_hydra_setsda,
2101 +       .setscl         = bit_hydra_setscl,
2102 +       .getsda         = bit_hydra_getsda,
2103 +       .getscl         = bit_hydra_getscl,
2104 +       .udelay         = 5,
2105 +       .mdelay         = 5,
2106 +       .timeout        = HZ
2107 +};
2108 +
2109 +static struct i2c_adapter bit_hydra_ops = {
2110 +       .owner          = THIS_MODULE,
2111 +       .name           = "Hydra i2c",
2112 +       .id             = I2C_HW_B_HYDRA,
2113 +       .algo_data              = &bit_hydra_data,
2114 +};
2115 +
2116 +static struct pci_device_id hydra_ids[] __devinitdata = {
2117 +       {
2118 +               .vendor =       PCI_VENDOR_ID_APPLE,
2119 +               .device =       PCI_DEVICE_ID_APPLE_HYDRA,
2120 +               .subvendor =    PCI_ANY_ID,
2121 +               .subdevice =    PCI_ANY_ID,
2122 +       },
2123 +       { 0, }
2124 +};
2125 +
2126 +static int __devinit hydra_probe(struct pci_dev *dev, const struct pci_device_id *id)
2127 +{
2128 +       unsigned int base_addr;
2129 +
2130 +       base_addr = dev->resource[0].start;
2131 +       hydra_base = (unsigned long) ioremap(base_addr, 0x100);
2132 +
2133 +       pdregw(0);              /* clear SCLK_OE and SDAT_OE */
2134 +       return i2c_bit_add_bus(&bit_hydra_ops);
2135 +}
2136 +
2137 +static void __devexit hydra_remove(struct pci_dev *dev)
2138 +{
2139 +       pdregw(0);      /* clear SCLK_OE and SDAT_OE */
2140 +       i2c_bit_del_bus(&bit_hydra_ops);
2141 +       iounmap((void *) hydra_base);
2142 +}
2143 +
2144 +
2145 +static struct pci_driver hydra_driver = {
2146 +       .name           = "hydra smbus",
2147 +       .id_table       = hydra_ids,
2148 +       .probe          = hydra_probe,
2149 +       .remove         = __devexit_p(hydra_remove),
2150 +};
2151 +
2152 +static int __init i2c_hydra_init(void)
2153 +{
2154 +       return pci_module_init(&hydra_driver);
2155 +}
2156 +
2157 +
2158 +static void __exit i2c_hydra_exit(void)
2159 +{
2160 +       pci_unregister_driver(&hydra_driver);
2161 +}
2162 +
2163 +
2164 +
2165 +MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
2166 +MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O");
2167 +
2168 +module_init(i2c_hydra_init);
2169 +module_exit(i2c_hydra_exit);
2170 +
2171 --- linux-old/drivers/i2c/i2c-i801.c    Thu Jan  1 00:00:00 1970
2172 +++ linux/drivers/i2c/i2c-i801.c        Mon Dec 13 20:18:41 2004
2173 @@ -0,0 +1,656 @@
2174 +/*
2175 +    i801.c - Part of lm_sensors, Linux kernel modules for hardware
2176 +              monitoring
2177 +    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
2178 +    Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
2179 +    <mdsxyz123@yahoo.com>
2180 +
2181 +    This program is free software; you can redistribute it and/or modify
2182 +    it under the terms of the GNU General Public License as published by
2183 +    the Free Software Foundation; either version 2 of the License, or
2184 +    (at your option) any later version.
2185 +
2186 +    This program is distributed in the hope that it will be useful,
2187 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
2188 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2189 +    GNU General Public License for more details.
2190 +
2191 +    You should have received a copy of the GNU General Public License
2192 +    along with this program; if not, write to the Free Software
2193 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2194 +*/
2195 +
2196 +/*
2197 +    SUPPORTED DEVICES  PCI ID
2198 +    82801AA            2413           
2199 +    82801AB            2423           
2200 +    82801BA            2443           
2201 +    82801CA/CAM                2483           
2202 +    82801DB            24C3   (HW PEC supported, 32 byte buffer not supported)
2203 +    82801EB            24D3   (HW PEC supported, 32 byte buffer not supported)
2204 +    6300ESB            25A4   ("")
2205 +    ICH6               266A
2206 +    This driver supports several versions of Intel's I/O Controller Hubs (ICH).
2207 +    For SMBus support, they are similar to the PIIX4 and are part
2208 +    of Intel's '810' and other chipsets.
2209 +    See the doc/busses/i2c-i801 file for details.
2210 +    I2C Block Read and Process Call are not supported.
2211 +*/
2212 +
2213 +/* Note: we assume there can only be one I801, with one SMBus interface */
2214 +
2215 +/* #define DEBUG 1 */
2216 +
2217 +#include <linux/module.h>
2218 +#include <linux/pci.h>
2219 +#include <linux/kernel.h>
2220 +#include <linux/stddef.h>
2221 +#include <linux/sched.h>
2222 +#include <linux/ioport.h>
2223 +#include <linux/init.h>
2224 +#include <linux/i2c.h>
2225 +#include <asm/io.h>
2226 +#define LM_DATE "20041007"
2227 +#define LM_VERSION "2.8.8"
2228 +#include <linux/sensors_compat.h>
2229 +
2230 +/* 82801DB is undefined before kernel 2.4.19 */
2231 +#ifndef PCI_DEVICE_ID_INTEL_82801DB_3
2232 +#define PCI_DEVICE_ID_INTEL_82801DB_3      0x24c3
2233 +#endif
2234 +
2235 +#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
2236 +#define HAVE_PEC
2237 +#endif
2238 +
2239 +/* I801 SMBus address offsets */
2240 +#define SMBHSTSTS      (0 + i801_smba)
2241 +#define SMBHSTCNT      (2 + i801_smba)
2242 +#define SMBHSTCMD      (3 + i801_smba)
2243 +#define SMBHSTADD      (4 + i801_smba)
2244 +#define SMBHSTDAT0     (5 + i801_smba)
2245 +#define SMBHSTDAT1     (6 + i801_smba)
2246 +#define SMBBLKDAT      (7 + i801_smba)
2247 +#define SMBPEC         (8 + i801_smba) /* ICH4 only */
2248 +#define SMBAUXSTS      (12 + i801_smba)        /* ICH4 only */
2249 +#define SMBAUXCTL      (13 + i801_smba)        /* ICH4 only */
2250 +
2251 +/* PCI Address Constants */
2252 +#define SMBBA          0x020
2253 +#define SMBHSTCFG      0x040
2254 +#define SMBREV         0x008
2255 +
2256 +/* Host configuration bits for SMBHSTCFG */
2257 +#define SMBHSTCFG_HST_EN       1
2258 +#define SMBHSTCFG_SMB_SMI_EN   2
2259 +#define SMBHSTCFG_I2C_EN       4
2260 +
2261 +/* Other settings */
2262 +#define MAX_TIMEOUT            100
2263 +#define ENABLE_INT9            0       /* set to 0x01 to enable - untested */
2264 +
2265 +/* I801 command constants */
2266 +#define I801_QUICK             0x00
2267 +#define I801_BYTE              0x04
2268 +#define I801_BYTE_DATA         0x08
2269 +#define I801_WORD_DATA         0x0C
2270 +#define I801_PROC_CALL         0x10    /* later chips only, unimplemented */
2271 +#define I801_BLOCK_DATA                0x14
2272 +#define I801_I2C_BLOCK_DATA    0x18    /* unimplemented */
2273 +#define I801_BLOCK_LAST                0x34
2274 +#define I801_I2C_BLOCK_LAST    0x38    /* unimplemented */
2275 +#define I801_START             0x40
2276 +#define I801_PEC_EN            0x80    /* ICH4 only */
2277 +
2278 +/* insmod parameters */
2279 +
2280 +/* If force_addr is set to anything different from 0, we forcibly enable
2281 +   the I801 at the given address. VERY DANGEROUS! */
2282 +static int force_addr = 0;
2283 +MODULE_PARM(force_addr, "i");
2284 +MODULE_PARM_DESC(force_addr,
2285 +                "Forcibly enable the I801 at the given address. "
2286 +                "EXTREMELY DANGEROUS!");
2287 +
2288 +static int i801_transaction(void);
2289 +static int i801_block_transaction(union i2c_smbus_data *data,
2290 +                                 char read_write, int command);
2291 +
2292 +static unsigned short i801_smba;
2293 +static struct pci_dev *I801_dev;
2294 +static int isich4;
2295 +
2296 +static int i801_setup(struct pci_dev *dev)
2297 +{
2298 +       int error_return = 0;
2299 +       unsigned char temp;
2300 +
2301 +       /* Note: we keep on searching until we have found 'function 3' */
2302 +       if(PCI_FUNC(dev->devfn) != 3)
2303 +               return -ENODEV;
2304 +
2305 +       I801_dev = dev;
2306 +       if (dev->device == PCI_DEVICE_ID_INTEL_82801DB_3 ||
2307 +           dev->device == 0x24d3 ||
2308 +           dev->device == 0x25a4)
2309 +               isich4 = 1;
2310 +       else
2311 +               isich4 = 0;
2312 +
2313 +       /* Determine the address of the SMBus areas */
2314 +       if (force_addr) {
2315 +               i801_smba = force_addr & 0xfff0;
2316 +       } else {
2317 +               pci_read_config_word(I801_dev, SMBBA, &i801_smba);
2318 +               i801_smba &= 0xfff0;
2319 +               if(i801_smba == 0) {
2320 +                       dev_err(dev, "SMB base address uninitialized"
2321 +                               "- upgrade BIOS or use force_addr=0xaddr\n");
2322 +                       return -ENODEV;
2323 +               }
2324 +       }
2325 +
2326 +       if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
2327 +               dev_err(dev, "I801_smb region 0x%x already in use!\n",
2328 +                       i801_smba);
2329 +               error_return = -EBUSY;
2330 +               goto END;
2331 +       }
2332 +
2333 +       pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
2334 +       temp &= ~SMBHSTCFG_I2C_EN;      /* SMBus timing */
2335 +       pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
2336 +
2337 +       /* If force_addr is set, we program the new address here. Just to make
2338 +          sure, we disable the device first. */
2339 +       if (force_addr) {
2340 +               pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
2341 +               pci_write_config_word(I801_dev, SMBBA, i801_smba);
2342 +               pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
2343 +               dev_warn(dev, "WARNING: I801 SMBus interface set to "
2344 +                       "new address %04x!\n", i801_smba);
2345 +       } else if ((temp & 1) == 0) {
2346 +               pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
2347 +               dev_warn(dev, "enabling SMBus device\n");
2348 +       }
2349 +
2350 +       if (temp & 0x02)
2351 +               dev_dbg(dev, "I801 using Interrupt SMI# for SMBus.\n");
2352 +       else
2353 +               dev_dbg(dev, "I801 using PCI Interrupt for SMBus.\n");
2354 +
2355 +       pci_read_config_byte(I801_dev, SMBREV, &temp);
2356 +       dev_dbg(dev, "SMBREV = 0x%X\n", temp);
2357 +       dev_dbg(dev, "I801_smba = 0x%X\n", i801_smba);
2358 +
2359 +END:
2360 +       return error_return;
2361 +}
2362 +
2363 +
2364 +static int i801_transaction(void)
2365 +{
2366 +       int temp;
2367 +       int result = 0;
2368 +       int timeout = 0;
2369 +
2370 +       dev_dbg(I801_dev, "Transaction (pre): CNT=%02x, CMD=%02x,"
2371 +               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
2372 +               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
2373 +               inb_p(SMBHSTDAT1));
2374 +
2375 +       /* Make sure the SMBus host is ready to start transmitting */
2376 +       /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
2377 +       if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
2378 +               dev_dbg(I801_dev, "SMBus busy (%02x). Resetting... \n",
2379 +                       temp);
2380 +               outb_p(temp, SMBHSTSTS);
2381 +               if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
2382 +                       dev_dbg(I801_dev, "Failed! (%02x)\n", temp);
2383 +                       return -1;
2384 +               } else {
2385 +                       dev_dbg(I801_dev, "Successfull!\n");
2386 +               }
2387 +       }
2388 +
2389 +       outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
2390 +
2391 +       /* We will always wait for a fraction of a second! */
2392 +       do {
2393 +               i2c_delay(1);
2394 +               temp = inb_p(SMBHSTSTS);
2395 +       } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
2396 +
2397 +       /* If the SMBus is still busy, we give up */
2398 +       if (timeout >= MAX_TIMEOUT) {
2399 +               dev_dbg(I801_dev, "SMBus Timeout!\n");
2400 +               result = -1;
2401 +       }
2402 +
2403 +       if (temp & 0x10) {
2404 +               result = -1;
2405 +               dev_dbg(I801_dev, "Error: Failed bus transaction\n");
2406 +       }
2407 +
2408 +       if (temp & 0x08) {
2409 +               result = -1;
2410 +               dev_err(I801_dev, "Bus collision! SMBus may be locked "
2411 +                       "until next hard reset. (sorry!)\n");
2412 +               /* Clock stops and slave is stuck in mid-transmission */
2413 +       }
2414 +
2415 +       if (temp & 0x04) {
2416 +               result = -1;
2417 +               dev_dbg(I801_dev, "Error: no response!\n");
2418 +       }
2419 +
2420 +       if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
2421 +               outb_p(inb(SMBHSTSTS), SMBHSTSTS);
2422 +
2423 +       if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
2424 +               dev_dbg(I801_dev, "Failed reset at end of transaction"
2425 +                       "(%02x)\n", temp);
2426 +       }
2427 +       dev_dbg(I801_dev, "Transaction (post): CNT=%02x, CMD=%02x, "
2428 +               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
2429 +               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
2430 +               inb_p(SMBHSTDAT1));
2431 +       return result;
2432 +}
2433 +
2434 +/* All-inclusive block transaction function */
2435 +static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
2436 +                                 int command)
2437 +{
2438 +       int i, len;
2439 +       int smbcmd;
2440 +       int temp;
2441 +       int result = 0;
2442 +       int timeout;
2443 +       unsigned char hostc, errmask;
2444 +
2445 +       if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
2446 +               if (read_write == I2C_SMBUS_WRITE) {
2447 +                       /* set I2C_EN bit in configuration register */
2448 +                       pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
2449 +                       pci_write_config_byte(I801_dev, SMBHSTCFG,
2450 +                                             hostc | SMBHSTCFG_I2C_EN);
2451 +               } else {
2452 +                       dev_err(I801_dev,
2453 +                               "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
2454 +                       return -1;
2455 +               }
2456 +       }
2457 +
2458 +       if (read_write == I2C_SMBUS_WRITE) {
2459 +               len = data->block[0];
2460 +               if (len < 1)
2461 +                       len = 1;
2462 +               if (len > 32)
2463 +                       len = 32;
2464 +               outb_p(len, SMBHSTDAT0);
2465 +               outb_p(data->block[1], SMBBLKDAT);
2466 +       } else {
2467 +               len = 32;       /* max for reads */
2468 +       }
2469 +
2470 +       if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
2471 +               /* set 32 byte buffer */
2472 +       }
2473 +
2474 +       for (i = 1; i <= len; i++) {
2475 +               if (i == len && read_write == I2C_SMBUS_READ)
2476 +                       smbcmd = I801_BLOCK_LAST;
2477 +               else
2478 +                       smbcmd = I801_BLOCK_DATA;
2479 +               outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
2480 +
2481 +               dev_dbg(I801_dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
2482 +                       "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
2483 +                       inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
2484 +                       inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
2485 +
2486 +               /* Make sure the SMBus host is ready to start transmitting */
2487 +               temp = inb_p(SMBHSTSTS);
2488 +               if (i == 1) {
2489 +                       /* Erronenous conditions before transaction: 
2490 +                        * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
2491 +                       errmask=0x9f; 
2492 +               } else {
2493 +                       /* Erronenous conditions during transaction: 
2494 +                        * Failed, Bus_Err, Dev_Err, Intr */
2495 +                       errmask=0x1e; 
2496 +               }
2497 +               if (temp & errmask) {
2498 +                       dev_dbg(I801_dev, "SMBus busy (%02x). "
2499 +                               "Resetting... \n", temp);
2500 +                       outb_p(temp, SMBHSTSTS);
2501 +                       if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
2502 +                               dev_err(I801_dev,
2503 +                                       "Reset failed! (%02x)\n", temp);
2504 +                               result = -1;
2505 +                                goto END;
2506 +                       }
2507 +                       if (i != 1) {
2508 +                               /* if die in middle of block transaction, fail */
2509 +                               result = -1;
2510 +                               goto END;
2511 +                       }
2512 +               }
2513 +
2514 +               if (i == 1)
2515 +                       outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
2516 +
2517 +               /* We will always wait for a fraction of a second! */
2518 +               timeout = 0;
2519 +               do {
2520 +                       temp = inb_p(SMBHSTSTS);
2521 +                       i2c_delay(1);
2522 +               }
2523 +                   while ((!(temp & 0x80))
2524 +                          && (timeout++ < MAX_TIMEOUT));
2525 +
2526 +               /* If the SMBus is still busy, we give up */
2527 +               if (timeout >= MAX_TIMEOUT) {
2528 +                       result = -1;
2529 +                       dev_dbg(I801_dev, "SMBus Timeout!\n");
2530 +               }
2531 +
2532 +               if (temp & 0x10) {
2533 +                       result = -1;
2534 +                       dev_dbg(I801_dev,
2535 +                               "Error: Failed bus transaction\n");
2536 +               } else if (temp & 0x08) {
2537 +                       result = -1;
2538 +                       dev_err(I801_dev, "Bus collision!\n");
2539 +               } else if (temp & 0x04) {
2540 +                       result = -1;
2541 +                       dev_dbg(I801_dev, "Error: no response!\n");
2542 +               }
2543 +
2544 +               if (i == 1 && read_write == I2C_SMBUS_READ) {
2545 +                       len = inb_p(SMBHSTDAT0);
2546 +                       if (len < 1)
2547 +                               len = 1;
2548 +                       if (len > 32)
2549 +                               len = 32;
2550 +                       data->block[0] = len;
2551 +               }
2552 +
2553 +               /* Retrieve/store value in SMBBLKDAT */
2554 +               if (read_write == I2C_SMBUS_READ)
2555 +                       data->block[i] = inb_p(SMBBLKDAT);
2556 +               if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
2557 +                       outb_p(data->block[i+1], SMBBLKDAT);
2558 +               if ((temp & 0x9e) != 0x00)
2559 +                       outb_p(temp, SMBHSTSTS);  /* signals SMBBLKDAT ready */
2560 +
2561 +               if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
2562 +                       dev_dbg(I801_dev,
2563 +                               "Bad status (%02x) at end of transaction\n",
2564 +                               temp);
2565 +               }
2566 +               dev_dbg(I801_dev, "Block (post %d): CNT=%02x, CMD=%02x, "
2567 +                       "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
2568 +                       inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
2569 +                       inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
2570 +
2571 +               if (result < 0)
2572 +                       goto END;
2573 +       }
2574 +
2575 +#ifdef HAVE_PEC
2576 +       if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
2577 +               /* wait for INTR bit as advised by Intel */
2578 +               timeout = 0;
2579 +               do {
2580 +                       temp = inb_p(SMBHSTSTS);
2581 +                       i2c_delay(1);
2582 +               } while ((!(temp & 0x02))
2583 +                          && (timeout++ < MAX_TIMEOUT));
2584 +
2585 +               if (timeout >= MAX_TIMEOUT) {
2586 +                       dev_dbg(I801_dev, "PEC Timeout!\n");
2587 +               }
2588 +               outb_p(temp, SMBHSTSTS); 
2589 +       }
2590 +#endif
2591 +       result = 0;
2592 +END:
2593 +       if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
2594 +               /* restore saved configuration register value */
2595 +               pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
2596 +       }
2597 +       return result;
2598 +}
2599 +
2600 +/* Return -1 on error. */
2601 +static s32 i801_access(struct i2c_adapter * adap, u16 addr,
2602 +                      unsigned short flags, char read_write, u8 command,
2603 +                      int size, union i2c_smbus_data * data)
2604 +{
2605 +       int hwpec = 0;
2606 +       int block = 0;
2607 +       int ret, xact = 0;
2608 +
2609 +#ifdef HAVE_PEC
2610 +       if(isich4)
2611 +               hwpec = (flags & I2C_CLIENT_PEC) != 0;
2612 +#endif
2613 +
2614 +       switch (size) {
2615 +       case I2C_SMBUS_QUICK:
2616 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2617 +                      SMBHSTADD);
2618 +               xact = I801_QUICK;
2619 +               break;
2620 +       case I2C_SMBUS_BYTE:
2621 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2622 +                      SMBHSTADD);
2623 +               if (read_write == I2C_SMBUS_WRITE)
2624 +                       outb_p(command, SMBHSTCMD);
2625 +               xact = I801_BYTE;
2626 +               break;
2627 +       case I2C_SMBUS_BYTE_DATA:
2628 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2629 +                      SMBHSTADD);
2630 +               outb_p(command, SMBHSTCMD);
2631 +               if (read_write == I2C_SMBUS_WRITE)
2632 +                       outb_p(data->byte, SMBHSTDAT0);
2633 +               xact = I801_BYTE_DATA;
2634 +               break;
2635 +       case I2C_SMBUS_WORD_DATA:
2636 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2637 +                      SMBHSTADD);
2638 +               outb_p(command, SMBHSTCMD);
2639 +               if (read_write == I2C_SMBUS_WRITE) {
2640 +                       outb_p(data->word & 0xff, SMBHSTDAT0);
2641 +                       outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
2642 +               }
2643 +               xact = I801_WORD_DATA;
2644 +               break;
2645 +       case I2C_SMBUS_BLOCK_DATA:
2646 +       case I2C_SMBUS_I2C_BLOCK_DATA:
2647 +#ifdef HAVE_PEC
2648 +       case I2C_SMBUS_BLOCK_DATA_PEC:
2649 +               if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
2650 +                       size = I2C_SMBUS_BLOCK_DATA_PEC;
2651 +#endif
2652 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2653 +                      SMBHSTADD);
2654 +               outb_p(command, SMBHSTCMD);
2655 +               block = 1;
2656 +               break;
2657 +       case I2C_SMBUS_PROC_CALL:
2658 +       default:
2659 +               dev_err(I801_dev, "Unsupported transaction %d\n", size);
2660 +               return -1;
2661 +       }
2662 +
2663 +#ifdef HAVE_PEC
2664 +       if(isich4 && hwpec) {
2665 +               if(size != I2C_SMBUS_QUICK &&
2666 +                  size != I2C_SMBUS_I2C_BLOCK_DATA)
2667 +                       outb_p(1, SMBAUXCTL);   /* enable HW PEC */
2668 +       }
2669 +#endif
2670 +       if(block)
2671 +               ret = i801_block_transaction(data, read_write, size);
2672 +       else {
2673 +               outb_p(xact | ENABLE_INT9, SMBHSTCNT);
2674 +               ret = i801_transaction();
2675 +       }
2676 +
2677 +#ifdef HAVE_PEC
2678 +       if(isich4 && hwpec) {
2679 +               if(size != I2C_SMBUS_QUICK &&
2680 +                  size != I2C_SMBUS_I2C_BLOCK_DATA)
2681 +                       outb_p(0, SMBAUXCTL);
2682 +       }
2683 +#endif
2684 +
2685 +       if(block)
2686 +               return ret;
2687 +       if(ret)
2688 +               return -1;
2689 +       if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
2690 +               return 0;
2691 +
2692 +       switch (xact & 0x7f) {
2693 +       case I801_BYTE: /* Result put in SMBHSTDAT0 */
2694 +       case I801_BYTE_DATA:
2695 +               data->byte = inb_p(SMBHSTDAT0);
2696 +               break;
2697 +       case I801_WORD_DATA:
2698 +               data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
2699 +               break;
2700 +       }
2701 +       return 0;
2702 +}
2703 +
2704 +
2705 +static u32 i801_func(struct i2c_adapter *adapter)
2706 +{
2707 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
2708 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
2709 +           I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
2710 +#ifdef HAVE_PEC
2711 +            | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
2712 +                        I2C_FUNC_SMBUS_HWPEC_CALC
2713 +                      : 0)
2714 +#endif
2715 +           ;
2716 +}
2717 +
2718 +static struct i2c_algorithm smbus_algorithm = {
2719 +       .name           = "Non-I2C SMBus adapter",
2720 +       .id             = I2C_ALGO_SMBUS,
2721 +       .smbus_xfer     = i801_access,
2722 +       .functionality  = i801_func,
2723 +};
2724 +
2725 +static struct i2c_adapter i801_adapter = {
2726 +       .owner          = THIS_MODULE,
2727 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
2728 +       .algo           = &smbus_algorithm,
2729 +       .name   = "unset",
2730 +};
2731 +
2732 +static struct pci_device_id i801_ids[] __devinitdata = {
2733 +       {
2734 +               .vendor =       PCI_VENDOR_ID_INTEL,
2735 +               .device =       PCI_DEVICE_ID_INTEL_82801AA_3,
2736 +               .subvendor =    PCI_ANY_ID,
2737 +               .subdevice =    PCI_ANY_ID,
2738 +       },
2739 +       {
2740 +               .vendor =       PCI_VENDOR_ID_INTEL,
2741 +               .device =       PCI_DEVICE_ID_INTEL_82801AB_3,
2742 +               .subvendor =    PCI_ANY_ID,
2743 +               .subdevice =    PCI_ANY_ID,
2744 +       },
2745 +       {
2746 +               .vendor =       PCI_VENDOR_ID_INTEL,
2747 +               .device =       PCI_DEVICE_ID_INTEL_82801BA_2,
2748 +               .subvendor =    PCI_ANY_ID,
2749 +               .subdevice =    PCI_ANY_ID,
2750 +       },
2751 +       {
2752 +               .vendor =       PCI_VENDOR_ID_INTEL,
2753 +               .device =       PCI_DEVICE_ID_INTEL_82801CA_3,
2754 +               .subvendor =    PCI_ANY_ID,
2755 +               .subdevice =    PCI_ANY_ID,
2756 +       },
2757 +       {
2758 +               .vendor =       PCI_VENDOR_ID_INTEL,
2759 +               .device =       PCI_DEVICE_ID_INTEL_82801DB_3,
2760 +               .subvendor =    PCI_ANY_ID,
2761 +               .subdevice =    PCI_ANY_ID,
2762 +       },
2763 +       {
2764 +               .vendor =       PCI_VENDOR_ID_INTEL,
2765 +               .device =       0x24d3, /* 82801EB ICH5 */
2766 +               .subvendor =    PCI_ANY_ID,
2767 +               .subdevice =    PCI_ANY_ID,
2768 +       },
2769 +       {
2770 +               .vendor =       PCI_VENDOR_ID_INTEL,
2771 +               .device =       0x25a4, /* PCI_DEVICE_ID_INTEL_ESB_4 */
2772 +               .subvendor =    PCI_ANY_ID,
2773 +               .subdevice =    PCI_ANY_ID,
2774 +       },
2775 +       {
2776 +               .vendor =       PCI_VENDOR_ID_INTEL,
2777 +               .device =       0x266a, /* PCI_DEVICE_ID_INTEL_ICH6_16 */
2778 +               .subvendor =    PCI_ANY_ID,
2779 +               .subdevice =    PCI_ANY_ID,
2780 +       },
2781 +       { 0, }
2782 +};
2783 +
2784 +static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
2785 +{
2786 +
2787 +       if (i801_setup(dev)) {
2788 +               dev_warn(dev,
2789 +                       "I801 not detected, module not inserted.\n");
2790 +               return -ENODEV;
2791 +       }
2792 +
2793 +       snprintf(i801_adapter.name, 32,
2794 +               "SMBus I801 adapter at %04x", i801_smba);
2795 +       return i2c_add_adapter(&i801_adapter);
2796 +}
2797 +
2798 +static void __devexit i801_remove(struct pci_dev *dev)
2799 +{
2800 +       i2c_del_adapter(&i801_adapter);
2801 +       release_region(i801_smba, (isich4 ? 16 : 8));
2802 +}
2803 +
2804 +static struct pci_driver i801_driver = {
2805 +       .name           = "i801 smbus",
2806 +       .id_table       = i801_ids,
2807 +       .probe          = i801_probe,
2808 +       .remove         = __devexit_p(i801_remove),
2809 +};
2810 +
2811 +static int __init i2c_i801_init(void)
2812 +{
2813 +       printk(KERN_INFO "i2c-i801 version %s (%s)\n", LM_VERSION, LM_DATE);
2814 +       return pci_module_init(&i801_driver);
2815 +}
2816 +
2817 +static void __exit i2c_i801_exit(void)
2818 +{
2819 +       pci_unregister_driver(&i801_driver);
2820 +}
2821 +
2822 +MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
2823 +               "Philip Edelbrock <phil@netroedge.com>, "
2824 +               "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
2825 +MODULE_DESCRIPTION("I801 SMBus driver");
2826 +MODULE_LICENSE("GPL");
2827 +
2828 +module_init(i2c_i801_init);
2829 +module_exit(i2c_i801_exit);
2830 --- linux-old/drivers/i2c/i2c-i810.c    Thu Jan  1 00:00:00 1970
2831 +++ linux/drivers/i2c/i2c-i810.c        Mon Dec 13 20:18:41 2004
2832 @@ -0,0 +1,310 @@
2833 +/*
2834 +    i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware
2835 +              monitoring
2836 +    Copyright (c) 1998, 1999, 2000  Frodo Looijaard <frodol@dds.nl>,
2837 +    Philip Edelbrock <phil@netroedge.com>,
2838 +    Ralph Metzler <rjkm@thp.uni-koeln.de>, and
2839 +    Mark D. Studebaker <mdsxyz123@yahoo.com>
2840 +    
2841 +    Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
2842 +    Simon Vogl
2843 +
2844 +    This program is free software; you can redistribute it and/or modify
2845 +    it under the terms of the GNU General Public License as published by
2846 +    the Free Software Foundation; either version 2 of the License, or
2847 +    (at your option) any later version.
2848 +
2849 +    This program is distributed in the hope that it will be useful,
2850 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
2851 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2852 +    GNU General Public License for more details.
2853 +
2854 +    You should have received a copy of the GNU General Public License
2855 +    along with this program; if not, write to the Free Software
2856 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2857 +*/
2858 +/*
2859 +   This interfaces to the I810/I815 to provide access to
2860 +   the DDC Bus and the I2C Bus.
2861 +
2862 +   SUPPORTED DEVICES   PCI ID
2863 +   i810AA              7121           
2864 +   i810AB              7123           
2865 +   i810E               7125           
2866 +   i815                        1132           
2867 +*/
2868 +
2869 +
2870 +#include <linux/module.h>
2871 +#include <linux/pci.h>
2872 +#include <linux/i2c.h>
2873 +#include <linux/i2c-algo-bit.h>
2874 +#include <linux/init.h>
2875 +#include <asm/io.h>
2876 +#include <asm/param.h> /* for HZ */
2877 +#define LM_DATE "20041007"
2878 +#define LM_VERSION "2.8.8"
2879 +
2880 +MODULE_LICENSE("GPL");
2881 +
2882 +#ifndef PCI_DEVICE_ID_INTEL_82815_2
2883 +#define PCI_DEVICE_ID_INTEL_82815_2   0x1132
2884 +#endif
2885 +
2886 +/* GPIO register locations */
2887 +#define I810_IOCONTROL_OFFSET 0x5000
2888 +#define I810_HVSYNC    0x00    /* not used */
2889 +#define I810_GPIOA     0x10
2890 +#define I810_GPIOB     0x14
2891 +
2892 +/* bit locations in the registers */
2893 +#define SCL_DIR_MASK   0x0001
2894 +#define SCL_DIR                0x0002
2895 +#define SCL_VAL_MASK   0x0004
2896 +#define SCL_VAL_OUT    0x0008
2897 +#define SCL_VAL_IN     0x0010
2898 +#define SDA_DIR_MASK   0x0100
2899 +#define SDA_DIR                0x0200
2900 +#define SDA_VAL_MASK   0x0400
2901 +#define SDA_VAL_OUT    0x0800
2902 +#define SDA_VAL_IN     0x1000
2903 +
2904 +/* initialization states */
2905 +#define INIT1  0x1
2906 +#define INIT2  0x2
2907 +#define INIT3  0x4
2908 +
2909 +/* delays */
2910 +#define CYCLE_DELAY            10
2911 +#define TIMEOUT                        (HZ / 2)
2912 +
2913 +
2914 +static void config_i810(struct pci_dev *dev);
2915 +
2916 +
2917 +static unsigned long ioaddr;
2918 +
2919 +/* The i810 GPIO registers have individual masks for each bit
2920 +   so we never have to read before writing. Nice. */
2921 +
2922 +static void bit_i810i2c_setscl(void *data, int val)
2923 +{
2924 +       writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
2925 +            ioaddr + I810_GPIOB);
2926 +       readl(ioaddr + I810_GPIOB);     /* flush posted write */
2927 +}
2928 +
2929 +static void bit_i810i2c_setsda(void *data, int val)
2930 +{
2931 +       writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
2932 +            ioaddr + I810_GPIOB);
2933 +       readl(ioaddr + I810_GPIOB);     /* flush posted write */
2934 +}
2935 +
2936 +/* The GPIO pins are open drain, so the pins could always remain outputs.
2937 +   However, some chip versions don't latch the inputs unless they
2938 +   are set as inputs.
2939 +   We rely on the i2c-algo-bit routines to set the pins high before
2940 +   reading the input from other chips. Following guidance in the 815
2941 +   prog. ref. guide, we do a "dummy write" of 0 to the register before
2942 +   reading which forces the input value to be latched. We presume this
2943 +   applies to the 810 as well; shouldn't hurt anyway. This is necessary to get
2944 +   i2c_algo_bit bit_test=1 to pass. */
2945 +
2946 +static int bit_i810i2c_getscl(void *data)
2947 +{
2948 +       writel(SCL_DIR_MASK, ioaddr + I810_GPIOB);
2949 +       writel(0, ioaddr + I810_GPIOB);
2950 +       return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN));
2951 +}
2952 +
2953 +static int bit_i810i2c_getsda(void *data)
2954 +{
2955 +       writel(SDA_DIR_MASK, ioaddr + I810_GPIOB);
2956 +       writel(0, ioaddr + I810_GPIOB);
2957 +       return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN));
2958 +}
2959 +
2960 +static void bit_i810ddc_setscl(void *data, int val)
2961 +{
2962 +       writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
2963 +            ioaddr + I810_GPIOA);
2964 +       readl(ioaddr + I810_GPIOA);     /* flush posted write */
2965 +}
2966 +
2967 +static void bit_i810ddc_setsda(void *data, int val)
2968 +{
2969 +       writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
2970 +            ioaddr + I810_GPIOA);
2971 +       readl(ioaddr + I810_GPIOA);     /* flush posted write */
2972 +}
2973 +
2974 +static int bit_i810ddc_getscl(void *data)
2975 +{
2976 +       writel(SCL_DIR_MASK, ioaddr + I810_GPIOA);
2977 +       writel(0, ioaddr + I810_GPIOA);
2978 +       return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN));
2979 +}
2980 +
2981 +static int bit_i810ddc_getsda(void *data)
2982 +{
2983 +       writel(SDA_DIR_MASK, ioaddr + I810_GPIOA);
2984 +       writel(0, ioaddr + I810_GPIOA);
2985 +       return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN));
2986 +}
2987 +
2988 +
2989 +/* Configures the chip */
2990 +void config_i810(struct pci_dev *dev)
2991 +{
2992 +       unsigned long cadr;
2993 +
2994 +       /* map I810 memory */
2995 +       cadr = dev->resource[1].start;
2996 +       cadr += I810_IOCONTROL_OFFSET;
2997 +       cadr &= PCI_BASE_ADDRESS_MEM_MASK;
2998 +       ioaddr = (unsigned long)ioremap_nocache(cadr, 0x1000);
2999 +       if(ioaddr) {
3000 +               bit_i810i2c_setscl(NULL, 1);
3001 +               bit_i810i2c_setsda(NULL, 1);
3002 +               bit_i810ddc_setscl(NULL, 1);
3003 +               bit_i810ddc_setsda(NULL, 1);
3004 +       }
3005 +}
3006 +
3007 +
3008 +static struct i2c_algo_bit_data i810_i2c_bit_data = {
3009 +       .setsda         = bit_i810i2c_setsda,
3010 +       .setscl         = bit_i810i2c_setscl,
3011 +       .getsda         = bit_i810i2c_getsda,
3012 +       .getscl         = bit_i810i2c_getscl,
3013 +       .udelay         = CYCLE_DELAY,
3014 +       .mdelay         = CYCLE_DELAY,
3015 +       .timeout        = TIMEOUT,
3016 +};
3017 +
3018 +static struct i2c_adapter i810_i2c_adapter = {
3019 +       .owner          = THIS_MODULE,
3020 +       .name           = "I810/I815 I2C Adapter",
3021 +       .id             = I2C_HW_B_I810,
3022 +       .algo_data      = &i810_i2c_bit_data,
3023 +};
3024 +
3025 +static struct i2c_algo_bit_data i810_ddc_bit_data = {
3026 +       .setsda         = bit_i810ddc_setsda,
3027 +       .setscl         = bit_i810ddc_setscl,
3028 +       .getsda         = bit_i810ddc_getsda,
3029 +       .getscl         = bit_i810ddc_getscl,
3030 +       .udelay         = CYCLE_DELAY,
3031 +       .mdelay         = CYCLE_DELAY,
3032 +       .timeout        = TIMEOUT,
3033 +};
3034 +
3035 +static struct i2c_adapter i810_ddc_adapter = {
3036 +       .owner          = THIS_MODULE,
3037 +       .name           = "I810/I815 DDC Adapter",
3038 +       .id             = I2C_HW_B_I810,
3039 +       .algo_data      = &i810_ddc_bit_data,
3040 +};
3041 +
3042 +
3043 +static struct pci_device_id i810_ids[] __devinitdata = {
3044 +       {
3045 +               .vendor =       PCI_VENDOR_ID_INTEL,
3046 +               .device =       PCI_DEVICE_ID_INTEL_82810_IG1,
3047 +               .subvendor =    PCI_ANY_ID,
3048 +               .subdevice =    PCI_ANY_ID,
3049 +       },
3050 +       {
3051 +               .vendor =       PCI_VENDOR_ID_INTEL,
3052 +               .device =       PCI_DEVICE_ID_INTEL_82810_IG3,
3053 +               .subvendor =    PCI_ANY_ID,
3054 +               .subdevice =    PCI_ANY_ID,
3055 +       },
3056 +       {
3057 +               .vendor =       PCI_VENDOR_ID_INTEL,
3058 +               .device =       0x7125,
3059 +               .subvendor =    PCI_ANY_ID,
3060 +               .subdevice =    PCI_ANY_ID,
3061 +       },
3062 +       {
3063 +               .vendor =       PCI_VENDOR_ID_INTEL,
3064 +               .device =       PCI_DEVICE_ID_INTEL_82815_2,
3065 +               .subvendor =    PCI_ANY_ID,
3066 +               .subdevice =    PCI_ANY_ID,
3067 +       },
3068 +       {
3069 +               .vendor =       PCI_VENDOR_ID_INTEL,
3070 +               .device =       0x2562,
3071 +               .subvendor =    PCI_ANY_ID,
3072 +               .subdevice =    PCI_ANY_ID,
3073 +       },
3074 +       { 0, }
3075 +};
3076 +
3077 +static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id)
3078 +{
3079 +       int retval;
3080 +
3081 +       config_i810(dev);
3082 +       printk("i2c-i810.o: i810/i815 found.\n");
3083 +
3084 +       retval = i2c_bit_add_bus(&i810_i2c_adapter);
3085 +       if(retval)
3086 +               return retval;
3087 +       retval = i2c_bit_add_bus(&i810_ddc_adapter);
3088 +       if(retval)
3089 +               i2c_bit_del_bus(&i810_i2c_adapter);
3090 +       return retval;
3091 +}
3092 +
3093 +static void __devexit i810_remove(struct pci_dev *dev)
3094 +{
3095 +       i2c_bit_del_bus(&i810_ddc_adapter);
3096 +       i2c_bit_del_bus(&i810_i2c_adapter);
3097 +}
3098 +
3099 +
3100 +/* Don't register driver to avoid driver conflicts */
3101 +/*
3102 +static struct pci_driver i810_driver = {
3103 +       .name           = "i810 smbus",
3104 +       .id_table       = i810_ids,
3105 +       .probe          = i810_probe,
3106 +       .remove         = __devexit_p(i810_remove),
3107 +};
3108 +*/
3109 +
3110 +static int __init i2c_i810_init(void)
3111 +{
3112 +       struct pci_dev *dev;
3113 +       const struct pci_device_id *id;
3114 +
3115 +       printk("i2c-i810.o version %s (%s)\n", LM_VERSION, LM_DATE);
3116 +/*
3117 +       return pci_module_init(&i810_driver);
3118 +*/
3119 +       pci_for_each_dev(dev) {
3120 +               id = pci_match_device(i810_ids, dev);
3121 +               if(id)
3122 +                       if(i810_probe(dev, id) >= 0)
3123 +                               return 0;
3124 +       }
3125 +       return -ENODEV;
3126 +}
3127 +
3128 +static void __exit i2c_i810_exit(void)
3129 +{
3130 +/*
3131 +       pci_unregister_driver(&i810_driver);
3132 +*/
3133 +       i810_remove(NULL);
3134 +       iounmap((void *)ioaddr);
3135 +}
3136 +
3137 +MODULE_AUTHOR
3138 +    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Ralph Metzler <rjkm@thp.uni-koeln.de>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
3139 +MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
3140 +
3141 +module_init(i2c_i810_init);
3142 +module_exit(i2c_i810_exit);
3143 --- linux-old/drivers/i2c/i2c-isa.c     Thu Jan  1 00:00:00 1970
3144 +++ linux/drivers/i2c/i2c-isa.c Mon Dec 13 20:18:41 2004
3145 @@ -0,0 +1,74 @@
3146 +/*
3147 +    i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware
3148 +            monitoring
3149 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
3150 +
3151 +    This program is free software; you can redistribute it and/or modify
3152 +    it under the terms of the GNU General Public License as published by
3153 +    the Free Software Foundation; either version 2 of the License, or
3154 +    (at your option) any later version.
3155 +
3156 +    This program is distributed in the hope that it will be useful,
3157 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
3158 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3159 +    GNU General Public License for more details.
3160 +
3161 +    You should have received a copy of the GNU General Public License
3162 +    along with this program; if not, write to the Free Software
3163 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3164 +*/
3165 +
3166 +/* This implements an i2c algorithm/adapter for ISA bus. Not that this is
3167 +   on first sight very useful; almost no functionality is preserved.
3168 +   Except that it makes writing drivers for chips which can be on both
3169 +   the SMBus and the ISA bus very much easier. See lm78.c for an example
3170 +   of this. */
3171 +
3172 +#include <linux/init.h>
3173 +#include <linux/module.h>
3174 +#include <linux/kernel.h>
3175 +#include <linux/errno.h>
3176 +#include <linux/i2c.h>
3177 +#define LM_DATE "20041007"
3178 +#define LM_VERSION "2.8.8"
3179 +
3180 +static u32 isa_func(struct i2c_adapter *adapter);
3181 +
3182 +/* This is the actual algorithm we define */
3183 +static struct i2c_algorithm isa_algorithm = {
3184 +       .name           = "ISA bus algorithm",
3185 +       .id             = I2C_ALGO_ISA,
3186 +       .functionality  = isa_func,
3187 +};
3188 +
3189 +/* There can only be one... */
3190 +static struct i2c_adapter isa_adapter = {
3191 +       .owner          = THIS_MODULE,
3192 +       .name           = "ISA main adapter",
3193 +       .id             = I2C_ALGO_ISA | I2C_HW_ISA,
3194 +       .algo           = &isa_algorithm,
3195 +};
3196 +
3197 +/* We can't do a thing... */
3198 +static u32 isa_func(struct i2c_adapter *adapter)
3199 +{
3200 +       return 0;
3201 +}
3202 +
3203 +static int __init i2c_isa_init(void)
3204 +{
3205 +       printk("i2c-isa.o version %s (%s)\n", LM_VERSION, LM_DATE);
3206 +       return i2c_add_adapter(&isa_adapter);
3207 +}
3208 +
3209 +static void __exit i2c_isa_exit(void)
3210 +{
3211 +       i2c_del_adapter(&isa_adapter);
3212 +}
3213 +
3214 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
3215 +MODULE_DESCRIPTION("ISA bus access through i2c");
3216 +MODULE_LICENSE("GPL");
3217 +
3218 +module_init(i2c_isa_init);
3219 +module_exit(i2c_isa_exit);
3220 --- linux-old/drivers/i2c/i2c-nforce2.c Thu Jan  1 00:00:00 1970
3221 +++ linux/drivers/i2c/i2c-nforce2.c     Mon Dec 13 20:18:41 2004
3222 @@ -0,0 +1,409 @@
3223 +/*
3224 +    SMBus driver for nVidia nForce2 MCP
3225 +
3226 +    Copyright (c) 2003  Hans-Frieder Vogt <hfvogt@arcor.de>,
3227 +    Based on
3228 +    SMBus 2.0 driver for AMD-8111 IO-Hub
3229 +    Copyright (c) 2002 Vojtech Pavlik
3230 +
3231 +    This program is free software; you can redistribute it and/or modify
3232 +    it under the terms of the GNU General Public License as published by
3233 +    the Free Software Foundation; either version 2 of the License, or
3234 +    (at your option) any later version.
3235 +
3236 +    This program is distributed in the hope that it will be useful,
3237 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
3238 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3239 +    GNU General Public License for more details.
3240 +
3241 +    You should have received a copy of the GNU General Public License
3242 +    along with this program; if not, write to the Free Software
3243 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3244 +*/
3245 +
3246 +/*
3247 +    SUPPORTED DEVICES  PCI ID
3248 +    nForce2 MCP                0064       
3249 +
3250 +    This driver supports the 2 SMBuses that are included in the MCP2 of the
3251 +    nForce2 chipset.
3252 +*/
3253 +
3254 +/* Note: we assume there can only be one nForce2, with two SMBus interfaces */
3255 +
3256 +#include <linux/module.h>
3257 +#include <linux/pci.h>
3258 +#include <linux/kernel.h>
3259 +#include <linux/stddef.h>
3260 +#include <linux/sched.h>
3261 +#include <linux/ioport.h>
3262 +#include <linux/init.h>
3263 +#include <linux/i2c.h>
3264 +#include <linux/delay.h>
3265 +#include <linux/slab.h>
3266 +#include <asm/io.h>
3267 +#define LM_DATE "20041007"
3268 +#define LM_VERSION "2.8.8"
3269 +
3270 +/* kernel 2.4.9 needs this */
3271 +#ifndef min_t
3272 +#define min_t(type,x,y) min(type,x,y)
3273 +#endif
3274 +
3275 +MODULE_LICENSE("GPL");
3276 +MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>");
3277 +MODULE_DESCRIPTION("nForce2 SMBus driver");
3278 +
3279 +#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS
3280 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS   0x0064
3281 +#endif
3282 +
3283 +
3284 +struct nforce2_smbus {
3285 +       struct pci_dev *dev;
3286 +       struct i2c_adapter adapter;
3287 +       int base;
3288 +       int size;
3289 +};
3290 +
3291 +
3292 +/*
3293 + * nVidia nForce2 SMBus control register definitions
3294 + */
3295 +#define NFORCE_PCI_SMB1        0x50
3296 +#define NFORCE_PCI_SMB2        0x54
3297 +
3298 +
3299 +/*
3300 + * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
3301 + */
3302 +#define NVIDIA_SMB_PRTCL       (smbus->base + 0x00)    /* protocol, PEC */
3303 +#define NVIDIA_SMB_STS         (smbus->base + 0x01)    /* status */
3304 +#define NVIDIA_SMB_ADDR                (smbus->base + 0x02)    /* address */
3305 +#define NVIDIA_SMB_CMD         (smbus->base + 0x03)    /* command */
3306 +#define NVIDIA_SMB_DATA                (smbus->base + 0x04)    /* 32 data registers */
3307 +#define NVIDIA_SMB_BCNT                (smbus->base + 0x24)    /* number of data bytes */
3308 +#define NVIDIA_SMB_ALRM_A      (smbus->base + 0x25)    /* alarm address */
3309 +#define NVIDIA_SMB_ALRM_D      (smbus->base + 0x26)    /* 2 bytes alarm data */
3310 +
3311 +#define NVIDIA_SMB_STS_DONE    0x80
3312 +#define NVIDIA_SMB_STS_ALRM    0x40
3313 +#define NVIDIA_SMB_STS_RES     0x20
3314 +#define NVIDIA_SMB_STS_STATUS  0x1f
3315 +
3316 +#define NVIDIA_SMB_PRTCL_WRITE                 0x00
3317 +#define NVIDIA_SMB_PRTCL_READ                  0x01
3318 +#define NVIDIA_SMB_PRTCL_QUICK                 0x02
3319 +#define NVIDIA_SMB_PRTCL_BYTE                  0x04
3320 +#define NVIDIA_SMB_PRTCL_BYTE_DATA             0x06
3321 +#define NVIDIA_SMB_PRTCL_WORD_DATA             0x08
3322 +#define NVIDIA_SMB_PRTCL_BLOCK_DATA            0x0a
3323 +#define NVIDIA_SMB_PRTCL_PROC_CALL             0x0c
3324 +#define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL       0x0d
3325 +#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA                0x4a
3326 +#define NVIDIA_SMB_PRTCL_PEC                   0x80
3327 +
3328 +
3329 +/* Other settings */
3330 +#define MAX_TIMEOUT 256
3331 +
3332 +
3333 +
3334 +static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
3335 +                      unsigned short flags, char read_write,
3336 +                      u8 command, int size, union i2c_smbus_data *data);
3337 +/*
3338 +static int nforce2_block_transaction(union i2c_smbus_data *data,
3339 +                                 char read_write, int i2c_enable);
3340 + */
3341 +static u32 nforce2_func(struct i2c_adapter *adapter);
3342 +
3343 +
3344 +static struct i2c_algorithm smbus_algorithm = {
3345 +       .name = "Non-I2C SMBus adapter",
3346 +       .id = I2C_ALGO_SMBUS,
3347 +       .smbus_xfer = nforce2_access,
3348 +       .functionality = nforce2_func,
3349 +};
3350 +
3351 +/* Return -1 on error. See smbus.h for more information */
3352 +s32 nforce2_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
3353 +               char read_write, u8 command, int size,
3354 +               union i2c_smbus_data * data)
3355 +{
3356 +       struct nforce2_smbus *smbus = adap->algo_data;
3357 +       unsigned char protocol, pec, temp;
3358 +       unsigned char len = 0; /* to keep the compiler quiet */
3359 +       int timeout = 0;
3360 +       int i;
3361 +
3362 +       protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : NVIDIA_SMB_PRTCL_WRITE;
3363 +       pec = (flags & I2C_CLIENT_PEC) ? NVIDIA_SMB_PRTCL_PEC : 0;
3364 +
3365 +       switch (size) {
3366 +
3367 +               case I2C_SMBUS_QUICK:
3368 +                       protocol |= NVIDIA_SMB_PRTCL_QUICK;
3369 +                       read_write = I2C_SMBUS_WRITE;
3370 +                       break;
3371 +
3372 +               case I2C_SMBUS_BYTE:
3373 +                       if (read_write == I2C_SMBUS_WRITE)
3374 +                               outb_p(command, NVIDIA_SMB_CMD);
3375 +                       protocol |= NVIDIA_SMB_PRTCL_BYTE;
3376 +                       break;
3377 +
3378 +               case I2C_SMBUS_BYTE_DATA:
3379 +                       outb_p(command, NVIDIA_SMB_CMD);
3380 +                       if (read_write == I2C_SMBUS_WRITE)
3381 +                               outb_p(data->byte, NVIDIA_SMB_DATA);
3382 +                       protocol |= NVIDIA_SMB_PRTCL_BYTE_DATA;
3383 +                       break;
3384 +
3385 +               case I2C_SMBUS_WORD_DATA:
3386 +                       outb_p(command, NVIDIA_SMB_CMD);
3387 +                       if (read_write == I2C_SMBUS_WRITE) {
3388 +                                outb_p(data->word, NVIDIA_SMB_DATA);
3389 +                                outb_p(data->word >> 8, NVIDIA_SMB_DATA+1);
3390 +                       }
3391 +                       protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
3392 +                       break;
3393 +
3394 +               case I2C_SMBUS_BLOCK_DATA:
3395 +                       outb_p(command, NVIDIA_SMB_CMD);
3396 +                       if (read_write == I2C_SMBUS_WRITE) {
3397 +                               len = min_t(u8, data->block[0], 32);
3398 +                               outb_p(len, NVIDIA_SMB_BCNT);
3399 +                               for (i = 0; i < len; i++)
3400 +                                       outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
3401 +                       }
3402 +                       protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
3403 +                       break;
3404 +
3405 +               case I2C_SMBUS_I2C_BLOCK_DATA:
3406 +                       len = min_t(u8, data->block[0], 32);
3407 +                       outb_p(command, NVIDIA_SMB_CMD);
3408 +                       outb_p(len, NVIDIA_SMB_BCNT);
3409 +                       if (read_write == I2C_SMBUS_WRITE)
3410 +                               for (i = 0; i < len; i++)
3411 +                                       outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i);
3412 +                       protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA;
3413 +                       break;
3414 +
3415 +               case I2C_SMBUS_PROC_CALL:
3416 +                       printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_PROC_CALL not supported!\n");
3417 +                       return -1;
3418 +                       /*
3419 +                       outb_p(command, NVIDIA_SMB_CMD);
3420 +                       outb_p(data->word, NVIDIA_SMB_DATA);
3421 +                       outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1);
3422 +                       protocol = NVIDIA_SMB_PRTCL_PROC_CALL | pec;
3423 +                       read_write = I2C_SMBUS_READ;
3424 +                       break;
3425 +                        */
3426 +
3427 +               case I2C_SMBUS_BLOCK_PROC_CALL:
3428 +                       printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
3429 +                       return -1;
3430 +                       /*
3431 +                       protocol |= pec;
3432 +                       len = min_t(u8, data->block[0], 31);
3433 +                       outb_p(command, NVIDIA_SMB_CMD);
3434 +                       outb_p(len, NVIDIA_SMB_BCNT);
3435 +                       for (i = 0; i < len; i++)
3436 +                               outb_p(data->block[i + 1], NVIDIA_SMB_DATA + i);
3437 +                       protocol = NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL | pec;
3438 +                       read_write = I2C_SMBUS_READ;
3439 +                       break;
3440 +                       */
3441 +
3442 +               case I2C_SMBUS_WORD_DATA_PEC:
3443 +               case I2C_SMBUS_BLOCK_DATA_PEC:
3444 +               case I2C_SMBUS_PROC_CALL_PEC:
3445 +               case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
3446 +                       printk(KERN_WARNING "i2c-nforce2.c: Unexpected software PEC transaction %d\n.", size);
3447 +                       return -1;
3448 +
3449 +               default:
3450 +                       printk(KERN_WARNING "i2c-nforce2.c: Unsupported transaction %d\n", size);
3451 +                       return -1;
3452 +       }
3453 +
3454 +       outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
3455 +       outb_p(protocol, NVIDIA_SMB_PRTCL);
3456 +
3457 +       temp = inb_p(NVIDIA_SMB_STS);
3458 +
3459 +#if 0
3460 +       do {
3461 +               i2c_delay(1);
3462 +               temp = inb_p(NVIDIA_SMB_STS);
3463 +       } while (((temp & NVIDIA_SMB_STS_DONE) == 0) && (timeout++ < MAX_TIMEOUT));
3464 +#endif
3465 +       if (~temp & NVIDIA_SMB_STS_DONE) {
3466 +               udelay(500);
3467 +               temp = inb_p(NVIDIA_SMB_STS);
3468 +       }
3469 +       if (~temp & NVIDIA_SMB_STS_DONE) {
3470 +               i2c_delay(HZ/100);
3471 +               temp = inb_p(NVIDIA_SMB_STS);
3472 +       }
3473 +
3474 +       if ((timeout >= MAX_TIMEOUT) || (~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS))
3475 +               return -1;
3476 +
3477 +       if (read_write == I2C_SMBUS_WRITE)
3478 +               return 0;
3479 +
3480 +       switch (size) {
3481 +
3482 +               case I2C_SMBUS_BYTE:
3483 +               case I2C_SMBUS_BYTE_DATA:
3484 +                       data->byte = inb_p(NVIDIA_SMB_DATA);
3485 +                       break;
3486 +
3487 +               case I2C_SMBUS_WORD_DATA:
3488 +               /* case I2C_SMBUS_PROC_CALL: not supported */
3489 +                       data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
3490 +                       break;
3491 +
3492 +               case I2C_SMBUS_BLOCK_DATA:
3493 +               /* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */
3494 +                       len = inb_p(NVIDIA_SMB_BCNT);
3495 +                       len = min_t(u8, len, 32);
3496 +               case I2C_SMBUS_I2C_BLOCK_DATA:
3497 +                       for (i = 0; i < len; i++)
3498 +                               data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
3499 +                       data->block[0] = len;
3500 +                       break;
3501 +       }
3502 +
3503 +       return 0;
3504 +}
3505 +
3506 +
3507 +u32 nforce2_func(struct i2c_adapter *adapter)
3508 +{
3509 +       /* other functionality might be possible, but is not tested */
3510 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
3511 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* |
3512 +           I2C_FUNC_SMBUS_BLOCK_DATA */;
3513 +}
3514 +
3515 +
3516 +static struct pci_device_id nforce2_ids[] = {
3517 +       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS,
3518 +               PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
3519 +       { 0 }
3520 +};
3521 +
3522 +
3523 +static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg, struct nforce2_smbus *smbus, char *name)
3524 +{
3525 +       u16 iobase;
3526 +       int error;
3527 +
3528 +       if (pci_read_config_word(dev, reg, &iobase) != PCIBIOS_SUCCESSFUL) {
3529 +               printk (KERN_ERR "i2c-nforce2.o: Error reading PCI config for %s\n", name);
3530 +               return -1;
3531 +       }
3532 +       smbus->dev  = dev;
3533 +       smbus->base = iobase & 0xfffc;
3534 +       smbus->size = 8;
3535 +
3536 +       if (!request_region(smbus->base, smbus->size, "nForce2 SMBus")) {
3537 +               printk (KERN_ERR "i2c-nforce2.o: Error requesting region %02x .. %02X for %s\n", smbus->base, smbus->base+smbus->size-1, name);
3538 +               return -1;
3539 +       }
3540 +
3541 +       /* TODO: find a better way to find out whether this file is compiled
3542 +        * with i2c 2.7.0 of earlier
3543 +        */
3544 +#ifdef I2C_HW_SMBUS_AMD8111
3545 +       smbus->adapter.owner = THIS_MODULE;
3546 +#endif
3547 +       sprintf(smbus->adapter.name, "SMBus nForce2 adapter at %04x", smbus->base);
3548 +       smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_NFORCE2;
3549 +       smbus->adapter.algo = &smbus_algorithm;
3550 +       smbus->adapter.algo_data = smbus;
3551 +
3552 +       error = i2c_add_adapter(&smbus->adapter);
3553 +       if (error) {
3554 +               printk(KERN_WARNING "i2c-nforce2.o: Failed to register adapter.\n");
3555 +               release_region(smbus->base, smbus->size);
3556 +               return -1;
3557 +       }
3558 +       printk(KERN_INFO "i2c-nforce2.o: nForce2 SMBus adapter at %#x\n", smbus->base);
3559 +       return 0;
3560 +}
3561 +
3562 +
3563 +static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
3564 +{
3565 +       struct nforce2_smbus *smbuses;
3566 +       int res1, res2;
3567 +
3568 +       /* we support 2 SMBus adapters */
3569 +       if (!(smbuses = (void *)kmalloc(2*sizeof(struct nforce2_smbus),
3570 +                                       GFP_KERNEL)))
3571 +               return -ENOMEM;
3572 +       memset (smbuses, 0, 2*sizeof(struct nforce2_smbus));
3573 +       pci_set_drvdata(dev, smbuses);
3574 +
3575 +       /* SMBus adapter 1 */
3576 +       res1 = nforce2_probe_smb (dev, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
3577 +       if (res1 < 0) {
3578 +               printk (KERN_ERR "i2c-nforce2.o: Error probing SMB1.\n");
3579 +               smbuses[0].base = 0;    /* to have a check value */
3580 +       }
3581 +       res2 = nforce2_probe_smb (dev, NFORCE_PCI_SMB2, &smbuses[1], "SMB2");
3582 +       if (res2 < 0) {
3583 +               printk (KERN_ERR "i2c-nforce2.o: Error probing SMB2.\n");
3584 +               smbuses[1].base = 0;    /* to have a check value */
3585 +       }
3586 +       if ((res1 < 0) && (res2 < 0)) {
3587 +               /* we did not find even one of the SMBuses, so we give up */
3588 +               kfree(smbuses);
3589 +               return -ENODEV;
3590 +       }
3591 +
3592 +       return 0;
3593 +}
3594 +
3595 +
3596 +static void __devexit nforce2_remove(struct pci_dev *dev)
3597 +{
3598 +       struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
3599 +
3600 +       if (smbuses[0].base) {
3601 +               i2c_del_adapter(&smbuses[0].adapter);
3602 +               release_region(smbuses[0].base, smbuses[0].size);
3603 +       }
3604 +       if (smbuses[1].base) {
3605 +               i2c_del_adapter(&smbuses[1].adapter);
3606 +               release_region(smbuses[1].base, smbuses[1].size);
3607 +       }
3608 +       kfree(smbuses);
3609 +}
3610 +
3611 +static struct pci_driver nforce2_driver = {
3612 +       .name           = "nForce2 SMBus",
3613 +       .id_table       = nforce2_ids,
3614 +       .probe          = nforce2_probe,
3615 +       .remove         = __devexit_p(nforce2_remove),
3616 +};
3617 +
3618 +int __init nforce2_init(void)
3619 +{
3620 +       printk(KERN_INFO "i2c-nforce2.o version %s (%s)\n", LM_VERSION, LM_DATE);
3621 +       return pci_module_init(&nforce2_driver);
3622 +}
3623 +
3624 +void __exit nforce2_exit(void)
3625 +{
3626 +       pci_unregister_driver(&nforce2_driver);
3627 +}
3628 +
3629 +module_init(nforce2_init);
3630 +module_exit(nforce2_exit);
3631 +
3632 --- linux-old/drivers/i2c/i2c-piix4.c   Thu Jan  1 00:00:00 1970
3633 +++ linux/drivers/i2c/i2c-piix4.c       Mon Dec 13 20:18:42 2004
3634 @@ -0,0 +1,549 @@
3635 +/*
3636 +    piix4.c - Part of lm_sensors, Linux kernel modules for hardware
3637 +              monitoring
3638 +    Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
3639 +    Philip Edelbrock <phil@netroedge.com>
3640 +
3641 +    This program is free software; you can redistribute it and/or modify
3642 +    it under the terms of the GNU General Public License as published by
3643 +    the Free Software Foundation; either version 2 of the License, or
3644 +    (at your option) any later version.
3645 +
3646 +    This program is distributed in the hope that it will be useful,
3647 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
3648 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3649 +    GNU General Public License for more details.
3650 +
3651 +    You should have received a copy of the GNU General Public License
3652 +    along with this program; if not, write to the Free Software
3653 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3654 +*/
3655 +
3656 +/*
3657 +   Supports:
3658 +       Intel PIIX4, 440MX
3659 +       Serverworks OSB4, CSB5, CSB6
3660 +       SMSC Victory66
3661 +
3662 +   Note: we assume there can only be one device, with one SMBus interface.
3663 +*/
3664 +
3665 +#include <linux/version.h>
3666 +#include <linux/module.h>
3667 +#include <linux/config.h>
3668 +#include <linux/pci.h>
3669 +#include <linux/kernel.h>
3670 +#include <linux/stddef.h>
3671 +#include <linux/sched.h>
3672 +#include <linux/ioport.h>
3673 +#include <linux/i2c.h>
3674 +#include <linux/init.h>
3675 +#include <linux/apm_bios.h>
3676 +#include <asm/io.h>
3677 +#define LM_DATE "20041007"
3678 +#define LM_VERSION "2.8.8"
3679 +
3680 +
3681 +struct sd {
3682 +       const unsigned short mfr;
3683 +       const unsigned short dev;
3684 +       const unsigned char fn;
3685 +       const char *name;
3686 +};
3687 +
3688 +/* PIIX4 SMBus address offsets */
3689 +#define SMBHSTSTS (0 + piix4_smba)
3690 +#define SMBHSLVSTS (1 + piix4_smba)
3691 +#define SMBHSTCNT (2 + piix4_smba)
3692 +#define SMBHSTCMD (3 + piix4_smba)
3693 +#define SMBHSTADD (4 + piix4_smba)
3694 +#define SMBHSTDAT0 (5 + piix4_smba)
3695 +#define SMBHSTDAT1 (6 + piix4_smba)
3696 +#define SMBBLKDAT (7 + piix4_smba)
3697 +#define SMBSLVCNT (8 + piix4_smba)
3698 +#define SMBSHDWCMD (9 + piix4_smba)
3699 +#define SMBSLVEVT (0xA + piix4_smba)
3700 +#define SMBSLVDAT (0xC + piix4_smba)
3701 +
3702 +/* count for request_region */
3703 +#define SMBIOSIZE 8
3704 +
3705 +/* PCI Address Constants */
3706 +#define SMBBA     0x090
3707 +#define SMBHSTCFG 0x0D2
3708 +#define SMBSLVC   0x0D3
3709 +#define SMBSHDW1  0x0D4
3710 +#define SMBSHDW2  0x0D5
3711 +#define SMBREV    0x0D6
3712 +
3713 +/* Other settings */
3714 +#define MAX_TIMEOUT 500
3715 +#define  ENABLE_INT9 0
3716 +
3717 +/* PIIX4 constants */
3718 +#define PIIX4_QUICK      0x00
3719 +#define PIIX4_BYTE       0x04
3720 +#define PIIX4_BYTE_DATA  0x08
3721 +#define PIIX4_WORD_DATA  0x0C
3722 +#define PIIX4_BLOCK_DATA 0x14
3723 +
3724 +/* insmod parameters */
3725 +
3726 +/* If force is set to anything different from 0, we forcibly enable the
3727 +   PIIX4. DANGEROUS! */
3728 +static int force = 0;
3729 +MODULE_PARM(force, "i");
3730 +MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
3731 +
3732 +/* If force_addr is set to anything different from 0, we forcibly enable
3733 +   the PIIX4 at the given address. VERY DANGEROUS! */
3734 +static int force_addr = 0;
3735 +MODULE_PARM(force_addr, "i");
3736 +MODULE_PARM_DESC(force_addr,
3737 +                "Forcibly enable the PIIX4 at the given address. "
3738 +                "EXTREMELY DANGEROUS!");
3739 +
3740 +static int fix_hstcfg = 0;
3741 +MODULE_PARM(fix_hstcfg, "i");
3742 +MODULE_PARM_DESC(fix_hstcfg,
3743 +                "Fix config register. Needed on some boards (Force CPCI735).");
3744 +
3745 +static int piix4_transaction(void);
3746 +
3747 +static unsigned short piix4_smba = 0;
3748 +
3749 +#ifdef CONFIG_X86
3750 +/*
3751 + * Get DMI information.
3752 + */
3753 +
3754 +static int __devinit ibm_dmi_probe(void)
3755 +{
3756 +       extern int is_unsafe_smbus;
3757 +       return is_unsafe_smbus;
3758 +}
3759 +#endif
3760 +
3761 +/* Detect whether a PIIX4 can be found, and initialize it, where necessary.
3762 +   Note the differences between kernels with the old PCI BIOS interface and
3763 +   newer kernels with the real PCI interface. In compat.h some things are
3764 +   defined to make the transition easier. */
3765 +static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
3766 +                               const struct pci_device_id *id)
3767 +{
3768 +       unsigned char temp;
3769 +
3770 +       /* match up the function */
3771 +       if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
3772 +               return -ENODEV;
3773 +
3774 +       printk(KERN_INFO "Found %s device\n", PIIX4_dev->name);
3775 +
3776 +#ifdef CONFIG_X86
3777 +       if(ibm_dmi_probe() && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
3778 +               printk(KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module "
3779 +                       "may corrupt your serial eeprom! Refusing to load "
3780 +                       "module!\n");
3781 +               return -EPERM;
3782 +       }
3783 +#endif
3784 +
3785 +       /* Determine the address of the SMBus areas */
3786 +       if (force_addr) {
3787 +               piix4_smba = force_addr & 0xfff0;
3788 +               force = 0;
3789 +       } else {
3790 +               pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
3791 +               piix4_smba &= 0xfff0;
3792 +               if(piix4_smba == 0) {
3793 +                       printk(KERN_ERR "i2c-piix4.o: SMB base address "
3794 +                               "uninitialized - upgrade BIOS or use "
3795 +                               "force_addr=0xaddr\n");
3796 +                       return -ENODEV;
3797 +               }
3798 +       }
3799 +
3800 +       if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) {
3801 +               printk(KERN_ERR "i2c-piix4.o: SMB region 0x%x already in "
3802 +                       "use!\n", piix4_smba);
3803 +               return -ENODEV;
3804 +       }
3805 +
3806 +       pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
3807 +
3808 +       /* Some BIOS will set up the chipset incorrectly and leave a register
3809 +          in an undefined state (causing I2C to act very strangely). */
3810 +       if (temp & 0x02) {
3811 +               if (fix_hstcfg) {
3812 +                       printk(KERN_INFO "i2c-piix4.o: Working around buggy "
3813 +                               "BIOS (I2C)\n");
3814 +                       temp &= 0xfd;
3815 +                       pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp);
3816 +               } else {
3817 +                       printk(KERN_INFO "i2c-piix4.o: Unusual config register "
3818 +                               "value\n");
3819 +                       printk(KERN_INFO "i2c-piix4.o: Try using fix_hstcfg=1 "
3820 +                               "if you experience problems\n");
3821 +               }
3822 +       }
3823 +
3824 +       /* If force_addr is set, we program the new address here. Just to make
3825 +          sure, we disable the PIIX4 first. */
3826 +       if (force_addr) {
3827 +               pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
3828 +               pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
3829 +               pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
3830 +               printk(KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to "
3831 +                       "new address %04x!\n", piix4_smba);
3832 +       } else if ((temp & 1) == 0) {
3833 +               if (force) {
3834 +                       /* This should never need to be done, but has been
3835 +                        * noted that many Dell machines have the SMBus
3836 +                        * interface on the PIIX4 disabled!? NOTE: This assumes
3837 +                        * I/O space and other allocations WERE done by the
3838 +                        * Bios!  Don't complain if your hardware does weird
3839 +                        * things after enabling this. :') Check for Bios
3840 +                        * updates before resorting to this.
3841 +                        */
3842 +                       pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
3843 +                                             temp | 1);
3844 +                       printk(KERN_NOTICE "i2c-piix4.o: WARNING: SMBus "
3845 +                               "interface has been FORCEFULLY ENABLED!\n");
3846 +               } else {
3847 +                       printk(KERN_ERR "i2c-piix4.o: Host SMBus controller "
3848 +                               "not enabled!\n");
3849 +                       release_region(piix4_smba, SMBIOSIZE);
3850 +                       piix4_smba = 0;
3851 +                       return -ENODEV;
3852 +               }
3853 +       }
3854 +
3855 +#ifdef DEBUG
3856 +       if ((temp & 0x0E) == 8)
3857 +               printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for "
3858 +                       "SMBus.\n");
3859 +       else if ((temp & 0x0E) == 0)
3860 +               printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# "
3861 +                       "for SMBus.\n");
3862 +       else
3863 +               printk(KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration "
3864 +                       "(or code out of date)!\n");
3865 +
3866 +       pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
3867 +       printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp);
3868 +       printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba);
3869 +#endif                         /* DEBUG */
3870 +
3871 +       return 0;
3872 +}
3873 +
3874 +
3875 +/* Another internally used function */
3876 +int piix4_transaction(void)
3877 +{
3878 +       int temp;
3879 +       int result = 0;
3880 +       int timeout = 0;
3881 +
3882 +#ifdef DEBUG
3883 +       printk
3884 +           (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
3885 +            "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
3886 +            inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
3887 +#endif
3888 +
3889 +       /* Make sure the SMBus host is ready to start transmitting */
3890 +       if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
3891 +#ifdef DEBUG
3892 +               printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n",
3893 +                      temp);
3894 +#endif
3895 +               outb_p(temp, SMBHSTSTS);
3896 +               if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
3897 +#ifdef DEBUG
3898 +                       printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp);
3899 +#endif
3900 +                       return -1;
3901 +               } else {
3902 +#ifdef DEBUG
3903 +                       printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n");
3904 +#endif
3905 +               }
3906 +       }
3907 +
3908 +       /* start the transaction by setting bit 6 */
3909 +       outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
3910 +
3911 +       /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
3912 +       do {
3913 +               i2c_delay(1);
3914 +               temp = inb_p(SMBHSTSTS);
3915 +       } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
3916 +
3917 +#ifdef DEBUG
3918 +       /* If the SMBus is still busy, we give up */
3919 +       if (timeout >= MAX_TIMEOUT) {
3920 +               printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n");
3921 +               result = -1;
3922 +       }
3923 +#endif
3924 +
3925 +       if (temp & 0x10) {
3926 +               result = -1;
3927 +#ifdef DEBUG
3928 +               printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n");
3929 +#endif
3930 +       }
3931 +
3932 +       if (temp & 0x08) {
3933 +               result = -1;
3934 +               printk
3935 +                   (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n"
3936 +                    "reset. (sorry!)\n");
3937 +               /* Clock stops and slave is stuck in mid-transmission */
3938 +       }
3939 +
3940 +       if (temp & 0x04) {
3941 +               result = -1;
3942 +#ifdef DEBUG
3943 +               printk(KERN_ERR "i2c-piix4.o: Error: no response!\n");
3944 +#endif
3945 +       }
3946 +
3947 +       if (inb_p(SMBHSTSTS) != 0x00)
3948 +               outb_p(inb(SMBHSTSTS), SMBHSTSTS);
3949 +
3950 +#ifdef DEBUG
3951 +       if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
3952 +               printk
3953 +                   (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n",
3954 +                    temp);
3955 +       }
3956 +       printk
3957 +           (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
3958 +            "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
3959 +            inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
3960 +#endif
3961 +       return result;
3962 +}
3963 +
3964 +/* Return -1 on error. */
3965 +s32 piix4_access(struct i2c_adapter * adap, u16 addr,
3966 +                unsigned short flags, char read_write,
3967 +                u8 command, int size, union i2c_smbus_data * data)
3968 +{
3969 +       int i, len;
3970 +
3971 +       switch (size) {
3972 +       case I2C_SMBUS_QUICK:
3973 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
3974 +                      SMBHSTADD);
3975 +               size = PIIX4_QUICK;
3976 +               break;
3977 +       case I2C_SMBUS_BYTE:
3978 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
3979 +                      SMBHSTADD);
3980 +               if (read_write == I2C_SMBUS_WRITE)
3981 +                       outb_p(command, SMBHSTCMD);
3982 +               size = PIIX4_BYTE;
3983 +               break;
3984 +       case I2C_SMBUS_BYTE_DATA:
3985 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
3986 +                      SMBHSTADD);
3987 +               outb_p(command, SMBHSTCMD);
3988 +               if (read_write == I2C_SMBUS_WRITE)
3989 +                       outb_p(data->byte, SMBHSTDAT0);
3990 +               size = PIIX4_BYTE_DATA;
3991 +               break;
3992 +       case I2C_SMBUS_WORD_DATA:
3993 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
3994 +                      SMBHSTADD);
3995 +               outb_p(command, SMBHSTCMD);
3996 +               if (read_write == I2C_SMBUS_WRITE) {
3997 +                       outb_p(data->word & 0xff, SMBHSTDAT0);
3998 +                       outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
3999 +               }
4000 +               size = PIIX4_WORD_DATA;
4001 +               break;
4002 +       case I2C_SMBUS_BLOCK_DATA:
4003 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
4004 +                      SMBHSTADD);
4005 +               outb_p(command, SMBHSTCMD);
4006 +               if (read_write == I2C_SMBUS_WRITE) {
4007 +                       len = data->block[0];
4008 +                       if (len < 0)
4009 +                               len = 0;
4010 +                       if (len > 32)
4011 +                               len = 32;
4012 +                       outb_p(len, SMBHSTDAT0);
4013 +                       i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
4014 +                       for (i = 1; i <= len; i++)
4015 +                               outb_p(data->block[i], SMBBLKDAT);
4016 +               }
4017 +               size = PIIX4_BLOCK_DATA;
4018 +               break;
4019 +       default:
4020 +               printk
4021 +                   (KERN_WARNING "i2c-piix4.o: Unsupported transaction %d\n", size);
4022 +               return -1;
4023 +       }
4024 +
4025 +       outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
4026 +
4027 +       if (piix4_transaction())        /* Error in transaction */
4028 +               return -1;
4029 +
4030 +       if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
4031 +               return 0;
4032 +
4033 +
4034 +       switch (size) {
4035 +       case PIIX4_BYTE:        /* Where is the result put? I assume here it is in
4036 +                                  SMBHSTDAT0 but it might just as well be in the
4037 +                                  SMBHSTCMD. No clue in the docs */
4038 +
4039 +               data->byte = inb_p(SMBHSTDAT0);
4040 +               break;
4041 +       case PIIX4_BYTE_DATA:
4042 +               data->byte = inb_p(SMBHSTDAT0);
4043 +               break;
4044 +       case PIIX4_WORD_DATA:
4045 +               data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
4046 +               break;
4047 +       case PIIX4_BLOCK_DATA:
4048 +               data->block[0] = inb_p(SMBHSTDAT0);
4049 +               i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
4050 +               for (i = 1; i <= data->block[0]; i++)
4051 +                       data->block[i] = inb_p(SMBBLKDAT);
4052 +               break;
4053 +       }
4054 +       return 0;
4055 +}
4056 +
4057 +
4058 +u32 piix4_func(struct i2c_adapter *adapter)
4059 +{
4060 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
4061 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
4062 +           I2C_FUNC_SMBUS_BLOCK_DATA;
4063 +}
4064 +
4065 +static struct i2c_algorithm smbus_algorithm = {
4066 +       .name           = "Non-I2C SMBus adapter",
4067 +       .id             = I2C_ALGO_SMBUS,
4068 +       .smbus_xfer     = piix4_access,
4069 +       .functionality  = piix4_func,
4070 +};
4071 +
4072 +static struct i2c_adapter piix4_adapter = {
4073 +       .owner          = THIS_MODULE,
4074 +       .name           = "unset",
4075 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
4076 +       .algo           = &smbus_algorithm,
4077 +};
4078 +
4079 +#ifndef PCI_DEVICE_ID_SERVERWORKS_CSB6
4080 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203
4081 +#endif
4082 +
4083 +static struct pci_device_id piix4_ids[] __devinitdata = {
4084 +       {
4085 +               .vendor =       PCI_VENDOR_ID_INTEL,
4086 +               .device =       PCI_DEVICE_ID_INTEL_82371AB_3,
4087 +               .subvendor =    PCI_ANY_ID,
4088 +               .subdevice =    PCI_ANY_ID,
4089 +               .driver_data =  3
4090 +       },
4091 +       {
4092 +               .vendor =       PCI_VENDOR_ID_SERVERWORKS,
4093 +               .device =       PCI_DEVICE_ID_SERVERWORKS_OSB4,
4094 +               .subvendor =    PCI_ANY_ID,
4095 +               .subdevice =    PCI_ANY_ID,
4096 +               .driver_data =  0,
4097 +       },
4098 +       {
4099 +               .vendor =       PCI_VENDOR_ID_SERVERWORKS,
4100 +               .device =       PCI_DEVICE_ID_SERVERWORKS_CSB5,
4101 +               .subvendor =    PCI_ANY_ID,
4102 +               .subdevice =    PCI_ANY_ID,
4103 +               .driver_data =  0,
4104 +       },
4105 +       {
4106 +               .vendor =       PCI_VENDOR_ID_SERVERWORKS,
4107 +               .device =       PCI_DEVICE_ID_SERVERWORKS_CSB6,
4108 +               .subvendor =    PCI_ANY_ID,
4109 +               .subdevice =    PCI_ANY_ID,
4110 +               .driver_data =  0,
4111 +       },
4112 +       {
4113 +               .vendor =       PCI_VENDOR_ID_INTEL,
4114 +               .device =       PCI_DEVICE_ID_INTEL_82443MX_3,
4115 +               .subvendor =    PCI_ANY_ID,
4116 +               .subdevice =    PCI_ANY_ID,
4117 +               .driver_data =  3,
4118 +       },
4119 +       {
4120 +               .vendor =       PCI_VENDOR_ID_EFAR,
4121 +               .device =       PCI_DEVICE_ID_EFAR_SLC90E66_3,
4122 +               .subvendor =    PCI_ANY_ID,
4123 +               .subdevice =    PCI_ANY_ID,
4124 +               .driver_data =  0,
4125 +       },
4126 +       { 0, }
4127 +};
4128 +
4129 +static int __devinit piix4_probe(struct pci_dev *dev,
4130 +                               const struct pci_device_id *id)
4131 +{
4132 +       int retval;
4133 +
4134 +       retval = piix4_setup(dev, id);
4135 +       if (retval)
4136 +               return retval;
4137 +
4138 +       sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
4139 +               piix4_smba);
4140 +
4141 +       if ((retval = i2c_add_adapter(&piix4_adapter))) {
4142 +               printk(KERN_ERR "i2c-piix4.o: Couldn't register adapter!\n");
4143 +               release_region(piix4_smba, SMBIOSIZE);
4144 +               piix4_smba = 0;
4145 +       }
4146 +
4147 +       return retval;
4148 +}
4149 +
4150 +static void __devexit piix4_remove(struct pci_dev *dev)
4151 +{
4152 +       if (piix4_smba) {
4153 +               i2c_del_adapter(&piix4_adapter);
4154 +               release_region(piix4_smba, SMBIOSIZE);
4155 +               piix4_smba = 0;
4156 +       }
4157 +}
4158 +
4159 +static struct pci_driver piix4_driver = {
4160 +       .name           = "piix4 smbus",
4161 +       .id_table       = piix4_ids,
4162 +       .probe          = piix4_probe,
4163 +       .remove         = __devexit_p(piix4_remove),
4164 +};
4165 +
4166 +static int __init i2c_piix4_init(void)
4167 +{
4168 +       printk("i2c-piix4.o version %s (%s)\n", LM_VERSION, LM_DATE);
4169 +       return pci_module_init(&piix4_driver);
4170 +}
4171 +
4172 +static void __exit i2c_piix4_exit(void)
4173 +{
4174 +       pci_unregister_driver(&piix4_driver);
4175 +}
4176 +
4177 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
4178 +               "Philip Edelbrock <phil@netroedge.com>");
4179 +MODULE_DESCRIPTION("PIIX4 SMBus driver");
4180 +MODULE_LICENSE("GPL");
4181 +
4182 +module_init(i2c_piix4_init);
4183 +module_exit(i2c_piix4_exit);
4184 --- linux-old/drivers/i2c/i2c-savage4.c Thu Jan  1 00:00:00 1970
4185 +++ linux/drivers/i2c/i2c-savage4.c     Mon Dec 13 20:18:42 2004
4186 @@ -0,0 +1,229 @@
4187 +/*
4188 +    i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware
4189 +              monitoring
4190 +    Copyright (C) 1998-2003  The LM Sensors Team
4191 +    Alexander Wold <awold@bigfoot.com>
4192 +    Mark D. Studebaker <mdsxyz123@yahoo.com>
4193 +    
4194 +    Based on i2c-voodoo3.c.
4195 +
4196 +    This program is free software; you can redistribute it and/or modify
4197 +    it under the terms of the GNU General Public License as published by
4198 +    the Free Software Foundation; either version 2 of the License, or
4199 +    (at your option) any later version.
4200 +
4201 +    This program is distributed in the hope that it will be useful,
4202 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
4203 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4204 +    GNU General Public License for more details.
4205 +
4206 +    You should have received a copy of the GNU General Public License
4207 +    along with this program; if not, write to the Free Software
4208 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4209 +*/
4210 +
4211 +/* This interfaces to the I2C bus of the Savage4 to gain access to
4212 +   the BT869 and possibly other I2C devices. The DDC bus is not
4213 +   yet supported because its register is not memory-mapped.
4214 +   However we leave the DDC code here, commented out, to make
4215 +   it easier to add later.
4216 +*/
4217 +
4218 +#include <linux/module.h>
4219 +#include <linux/pci.h>
4220 +#include <linux/i2c.h>
4221 +#include <linux/i2c-algo-bit.h>
4222 +#include <linux/init.h>
4223 +#include <asm/io.h>
4224 +#include <asm/param.h> /* for HZ */
4225 +#define LM_DATE "20041007"
4226 +#define LM_VERSION "2.8.8"
4227 +
4228 +/* 3DFX defines */
4229 +/* #define PCI_VENDOR_ID_S3            0x5333 */
4230 +#define PCI_CHIP_SAVAGE3D      0x8A20
4231 +#define PCI_CHIP_SAVAGE3D_MV   0x8A21
4232 +#define PCI_CHIP_SAVAGE4       0x8A22
4233 +#define PCI_CHIP_SAVAGE2000    0x9102
4234 +#define PCI_CHIP_PROSAVAGE_PM  0x8A25
4235 +#define PCI_CHIP_PROSAVAGE_KM  0x8A26
4236 +#define PCI_CHIP_SAVAGE_MX_MV  0x8c10
4237 +#define PCI_CHIP_SAVAGE_MX     0x8c11
4238 +#define PCI_CHIP_SAVAGE_IX_MV  0x8c12
4239 +#define PCI_CHIP_SAVAGE_IX     0x8c13
4240 +
4241 +#define REG 0xff20     /* Serial Port 1 Register */
4242 +
4243 +/* bit locations in the register */
4244 +//#define DDC_ENAB     0x00040000
4245 +//#define DDC_SCL_OUT  0x00080000
4246 +//#define DDC_SDA_OUT  0x00100000
4247 +//#define DDC_SCL_IN   0x00200000
4248 +//#define DDC_SDA_IN   0x00400000
4249 +#define I2C_ENAB       0x00000020
4250 +#define I2C_SCL_OUT    0x00000001
4251 +#define I2C_SDA_OUT    0x00000002
4252 +#define I2C_SCL_IN     0x00000008
4253 +#define I2C_SDA_IN     0x00000010
4254 +
4255 +/* initialization states */
4256 +#define INIT2  0x20
4257 +/* #define INIT3       0x4 */
4258 +
4259 +/* delays */
4260 +#define CYCLE_DELAY    10
4261 +#define TIMEOUT                (HZ / 2)
4262 +
4263 +
4264 +static void config_s4(struct pci_dev *dev);
4265 +
4266 +static unsigned long ioaddr;
4267 +
4268 +/* The sav GPIO registers don't have individual masks for each bit
4269 +   so we always have to read before writing. */
4270 +
4271 +static void bit_savi2c_setscl(void *data, int val)
4272 +{
4273 +       unsigned int r;
4274 +       r = readl(ioaddr + REG);
4275 +       if(val)
4276 +               r |= I2C_SCL_OUT;
4277 +       else
4278 +               r &= ~I2C_SCL_OUT;
4279 +       writel(r, ioaddr + REG);
4280 +       readl(ioaddr + REG);    /* flush posted write */
4281 +}
4282 +
4283 +static void bit_savi2c_setsda(void *data, int val)
4284 +{
4285 +       unsigned int r;
4286 +       r = readl(ioaddr + REG);
4287 +       if(val)
4288 +               r |= I2C_SDA_OUT;
4289 +       else
4290 +               r &= ~I2C_SDA_OUT;
4291 +       writel(r, ioaddr + REG);
4292 +       readl(ioaddr + REG);    /* flush posted write */
4293 +}
4294 +
4295 +/* The GPIO pins are open drain, so the pins always remain outputs.
4296 +   We rely on the i2c-algo-bit routines to set the pins high before
4297 +   reading the input from other chips. */
4298 +
4299 +static int bit_savi2c_getscl(void *data)
4300 +{
4301 +       return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
4302 +}
4303 +
4304 +static int bit_savi2c_getsda(void *data)
4305 +{
4306 +       return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
4307 +}
4308 +
4309 +/* Configures the chip */
4310 +
4311 +void config_s4(struct pci_dev *dev)
4312 +{
4313 +       unsigned int cadr;
4314 +
4315 +       /* map memory */
4316 +       cadr = dev->resource[0].start;
4317 +       cadr &= PCI_BASE_ADDRESS_MEM_MASK;
4318 +       ioaddr = (unsigned long)ioremap_nocache(cadr, 0x0080000);
4319 +       if(ioaddr) {
4320 +//             writel(0x8160, ioaddr + REG2);
4321 +               writel(0x00000020, ioaddr + REG);
4322 +               printk("i2c-savage4: Using Savage4 at 0x%lx\n", ioaddr);
4323 +       }
4324 +}
4325 +
4326 +
4327 +static struct i2c_algo_bit_data sav_i2c_bit_data = {
4328 +       .setsda         = bit_savi2c_setsda,
4329 +       .setscl         = bit_savi2c_setscl,
4330 +       .getsda         = bit_savi2c_getsda,
4331 +       .getscl         = bit_savi2c_getscl,
4332 +       .udelay         = CYCLE_DELAY,
4333 +       .mdelay         = CYCLE_DELAY,
4334 +       .timeout        = TIMEOUT
4335 +};
4336 +
4337 +static struct i2c_adapter savage4_i2c_adapter = {
4338 +       .owner          = THIS_MODULE,
4339 +       .name           = "I2C Savage4 adapter",
4340 +       .id             = I2C_HW_B_SAVG,
4341 +       .algo_data      = &sav_i2c_bit_data,
4342 +};
4343 +
4344 +static struct pci_device_id savage4_ids[] __devinitdata = {
4345 +       {
4346 +               .vendor =       PCI_VENDOR_ID_S3,
4347 +               .device =       PCI_CHIP_SAVAGE4,
4348 +               .subvendor =    PCI_ANY_ID,
4349 +               .subdevice =    PCI_ANY_ID,
4350 +       },
4351 +       {
4352 +               .vendor =       PCI_VENDOR_ID_S3,
4353 +               .device =       PCI_CHIP_SAVAGE2000,
4354 +               .subvendor =    PCI_ANY_ID,
4355 +               .subdevice =    PCI_ANY_ID,
4356 +       },
4357 +       { 0, }
4358 +};
4359 +
4360 +static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id)
4361 +{
4362 +       config_s4(dev);
4363 +       return i2c_bit_add_bus(&savage4_i2c_adapter);
4364 +}
4365 +
4366 +static void __devexit savage4_remove(struct pci_dev *dev)
4367 +{
4368 +       i2c_bit_del_bus(&savage4_i2c_adapter);
4369 +}
4370 +
4371 +
4372 +/* Don't register driver to avoid driver conflicts */
4373 +/*
4374 +static struct pci_driver savage4_driver = {
4375 +       .name           = "savage4 smbus",
4376 +       .id_table       = savage4_ids,
4377 +       .probe          = savage4_probe,
4378 +       .remove         = __devexit_p(savage4_remove),
4379 +};
4380 +*/
4381 +
4382 +static int __init i2c_savage4_init(void)
4383 +{
4384 +       struct pci_dev *dev;
4385 +       const struct pci_device_id *id;
4386 +
4387 +       printk("i2c-savage4.o version %s (%s)\n", LM_VERSION, LM_DATE);
4388 +/*
4389 +       return pci_module_init(&savage4_driver);
4390 +*/
4391 +       pci_for_each_dev(dev) {
4392 +               id = pci_match_device(savage4_ids, dev);
4393 +               if(id)
4394 +                       if(savage4_probe(dev, id) >= 0)
4395 +                               return 0;
4396 +       }
4397 +       return -ENODEV;
4398 +}
4399 +
4400 +static void __exit i2c_savage4_exit(void)
4401 +{
4402 +/*
4403 +       pci_unregister_driver(&savage4_driver);
4404 +*/
4405 +       savage4_remove(NULL);
4406 +       iounmap((void *)ioaddr);
4407 +}
4408 +
4409 +MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> "
4410 +               "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
4411 +MODULE_DESCRIPTION("Savage4 I2C/SMBus driver");
4412 +MODULE_LICENSE("GPL");
4413 +
4414 +module_init(i2c_savage4_init);
4415 +module_exit(i2c_savage4_exit);
4416 --- linux-old/drivers/i2c/i2c-sis5595.c Thu Jan  1 00:00:00 1970
4417 +++ linux/drivers/i2c/i2c-sis5595.c     Mon Dec 13 20:18:42 2004
4418 @@ -0,0 +1,481 @@
4419 +/*
4420 +    sis5595.c - Part of lm_sensors, Linux kernel modules for hardware
4421 +              monitoring
4422 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
4423 +    Philip Edelbrock <phil@netroedge.com>
4424 +
4425 +    This program is free software; you can redistribute it and/or modify
4426 +    it under the terms of the GNU General Public License as published by
4427 +    the Free Software Foundation; either version 2 of the License, or
4428 +    (at your option) any later version.
4429 +
4430 +    This program is distributed in the hope that it will be useful,
4431 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
4432 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4433 +    GNU General Public License for more details.
4434 +
4435 +    You should have received a copy of the GNU General Public License
4436 +    along with this program; if not, write to the Free Software
4437 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4438 +*/
4439 +
4440 +/* Note: we assume there can only be one SIS5595 with one SMBus interface */
4441 +
4442 +/*
4443 +   Note: all have mfr. ID 0x1039.
4444 +   SUPPORTED           PCI ID          
4445 +       5595            0008
4446 +
4447 +   Note: these chips contain a 0008 device which is incompatible with the
4448 +         5595. We recognize these by the presence of the listed
4449 +         "blacklist" PCI ID and refuse to load.
4450 +
4451 +   NOT SUPPORTED       PCI ID          BLACKLIST PCI ID        
4452 +        540            0008            0540
4453 +        550            0008            0550
4454 +       5513            0008            5511
4455 +       5581            0008            5597
4456 +       5582            0008            5597
4457 +       5597            0008            5597
4458 +       5598            0008            5597/5598
4459 +        630            0008            0630
4460 +        645            0008            0645
4461 +        646            0008            0646
4462 +        648            0008            0648
4463 +        650            0008            0650
4464 +        651            0008            0651
4465 +        730            0008            0730
4466 +        735            0008            0735
4467 +        745            0008            0745
4468 +        746            0008            0746
4469 +*/
4470 +
4471 +/* TO DO: 
4472 + * Add Block Transfers (ugly, but supported by the adapter)
4473 + * Add adapter resets
4474 + */
4475 +
4476 +#include <linux/module.h>
4477 +#include <linux/pci.h>
4478 +#include <linux/kernel.h>
4479 +#include <linux/stddef.h>
4480 +#include <linux/sched.h>
4481 +#include <linux/ioport.h>
4482 +#include <linux/i2c.h>
4483 +#include <linux/init.h>
4484 +#include <asm/io.h>
4485 +#define LM_DATE "20041007"
4486 +#define LM_VERSION "2.8.8"
4487 +
4488 +MODULE_LICENSE("GPL");
4489 +
4490 +static int blacklist[] = {
4491 +                       PCI_DEVICE_ID_SI_540,
4492 +                       PCI_DEVICE_ID_SI_550,
4493 +                       PCI_DEVICE_ID_SI_630,
4494 +                       PCI_DEVICE_ID_SI_730,
4495 +                       PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but
4496 +                                                 that ID shows up in other chips so we
4497 +                                                 use the 5511 ID for recognition */
4498 +                       PCI_DEVICE_ID_SI_5597,
4499 +                       PCI_DEVICE_ID_SI_5598,
4500 +                       0x645,
4501 +                       0x646,
4502 +                       0x648,
4503 +                       0x650,
4504 +                       0x651,
4505 +                       0x735,
4506 +                       0x745,
4507 +                       0x746,
4508 +                       0 };
4509 +
4510 +/* Length of ISA address segment */
4511 +#define SIS5595_EXTENT 8
4512 +/* SIS5595 SMBus registers */
4513 +#define SMB_STS_LO 0x00
4514 +#define SMB_STS_HI 0x01
4515 +#define SMB_CTL_LO 0x02
4516 +#define SMB_CTL_HI 0x03
4517 +#define SMB_ADDR   0x04
4518 +#define SMB_CMD    0x05
4519 +#define SMB_PCNT   0x06
4520 +#define SMB_CNT    0x07
4521 +#define SMB_BYTE   0x08
4522 +#define SMB_DEV    0x10
4523 +#define SMB_DB0    0x11
4524 +#define SMB_DB1    0x12
4525 +#define SMB_HAA    0x13
4526 +
4527 +/* PCI Address Constants */
4528 +#define SMB_INDEX  0x38
4529 +#define SMB_DAT    0x39
4530 +#define SIS5595_ENABLE_REG 0x40
4531 +#define ACPI_BASE  0x90
4532 +
4533 +/* Other settings */
4534 +#define MAX_TIMEOUT 500
4535 +
4536 +/* SIS5595 constants */
4537 +#define SIS5595_QUICK      0x00
4538 +#define SIS5595_BYTE       0x02
4539 +#define SIS5595_BYTE_DATA  0x04
4540 +#define SIS5595_WORD_DATA  0x06
4541 +#define SIS5595_PROC_CALL  0x08
4542 +#define SIS5595_BLOCK_DATA 0x0A
4543 +
4544 +/* insmod parameters */
4545 +
4546 +/* If force_addr is set to anything different from 0, we forcibly enable
4547 +   the device at the given address. */
4548 +static int force_addr = 0;
4549 +MODULE_PARM(force_addr, "i");
4550 +MODULE_PARM_DESC(force_addr,
4551 +                "Initialize the base address of the i2c controller");
4552 +
4553 +static int sis5595_transaction(void);
4554 +
4555 +static unsigned short sis5595_base = 0;
4556 +
4557 +static u8 sis5595_read(u8 reg)
4558 +{
4559 +       outb(reg, sis5595_base + SMB_INDEX);
4560 +       return inb(sis5595_base + SMB_DAT);
4561 +}
4562 +
4563 +static void sis5595_write(u8 reg, u8 data)
4564 +{
4565 +       outb(reg, sis5595_base + SMB_INDEX);
4566 +       outb(data, sis5595_base + SMB_DAT);
4567 +}
4568 +
4569 +
4570 +/* Detect whether a SIS5595 can be found, and initialize it, where necessary.
4571 +   Note the differences between kernels with the old PCI BIOS interface and
4572 +   newer kernels with the real PCI interface. In compat.h some things are
4573 +   defined to make the transition easier. */
4574 +int sis5595_setup(struct pci_dev *SIS5595_dev)
4575 +{
4576 +       u16 a;
4577 +       u8 val;
4578 +       int *i;
4579 +
4580 +       /* Look for imposters */
4581 +       for(i = blacklist; *i != 0; i++) {
4582 +               if (pci_find_device(PCI_VENDOR_ID_SI, *i, NULL)) {
4583 +                       printk("i2c-sis5595.o: Error: Looked for SIS5595 but found unsupported device %.4X\n", *i);
4584 +                       return -ENODEV;
4585 +               }
4586 +       }
4587 +
4588 +/* Determine the address of the SMBus areas */
4589 +       pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base);
4590 +       if(sis5595_base == 0 && force_addr == 0) {
4591 +               printk("i2c-sis5595.o: ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
4592 +               return -ENODEV;
4593 +       }
4594 +
4595 +       if(force_addr)
4596 +               sis5595_base = force_addr & ~(SIS5595_EXTENT - 1);
4597 +#ifdef DEBUG
4598 +       printk("ACPI Base address: %04x\n", sis5595_base);
4599 +#endif
4600 +       /* NB: We grab just the two SMBus registers here, but this may still
4601 +        * interfere with ACPI :-(  */
4602 +       if (check_region(sis5595_base + SMB_INDEX, 2)) {
4603 +               printk
4604 +                   ("i2c-sis5595.o: SMBus registers 0x%04x-0x%04x already in use!\n",
4605 +                    sis5595_base + SMB_INDEX,
4606 +                    sis5595_base + SMB_INDEX + 1);
4607 +               return -ENODEV;
4608 +       }
4609 +
4610 +       if(force_addr) {
4611 +               printk("i2c-sis5595.o: forcing ISA address 0x%04X\n", sis5595_base);
4612 +               if (PCIBIOS_SUCCESSFUL !=
4613 +                   pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base))
4614 +                       return -ENODEV;
4615 +               if (PCIBIOS_SUCCESSFUL !=
4616 +                   pci_read_config_word(SIS5595_dev, ACPI_BASE, &a))
4617 +                       return -ENODEV;
4618 +               if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) {
4619 +                       /* doesn't work for some chips! */
4620 +                       printk("i2c-sis5595.o: force address failed - not supported?\n");
4621 +                       return -ENODEV;
4622 +               }
4623 +       }
4624 +
4625 +       if (PCIBIOS_SUCCESSFUL !=
4626 +           pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val))
4627 +               return -ENODEV;
4628 +       if((val & 0x80) == 0) {
4629 +               printk("sis5595.o: enabling ACPI\n");
4630 +               if (PCIBIOS_SUCCESSFUL !=
4631 +                   pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG,
4632 +                                     val | 0x80))
4633 +                       return -ENODEV;
4634 +               if (PCIBIOS_SUCCESSFUL !=
4635 +                   pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val))
4636 +                       return -ENODEV;
4637 +               if((val & 0x80) == 0) { /* doesn't work for some chips? */
4638 +                       printk("sis5595.o: ACPI enable failed - not supported?\n");
4639 +                       return -ENODEV;
4640 +               }
4641 +       }
4642 +
4643 +       /* Everything is happy, let's grab the memory and set things up. */
4644 +       request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus");
4645 +       return(0);
4646 +}
4647 +
4648 +
4649 +/* Another internally used function */
4650 +int sis5595_transaction(void)
4651 +{
4652 +       int temp;
4653 +       int result = 0;
4654 +       int timeout = 0;
4655 +
4656 +       /* Make sure the SMBus host is ready to start transmitting */
4657 +       if (
4658 +           (temp =
4659 +            sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
4660 +           0x00) {
4661 +#ifdef DEBUG
4662 +               printk("i2c-sis5595.o: SMBus busy (%04x). Resetting... \n",
4663 +                      temp);
4664 +#endif
4665 +               sis5595_write(SMB_STS_LO, temp & 0xff);
4666 +               sis5595_write(SMB_STS_HI, temp >> 8);
4667 +               if (
4668 +                   (temp =
4669 +                    sis5595_read(SMB_STS_LO) +
4670 +                    (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
4671 +#ifdef DEBUG
4672 +                       printk("i2c-sis5595.o: Failed! (%02x)\n", temp);
4673 +#endif
4674 +                       return -1;
4675 +               } else {
4676 +#ifdef DEBUG
4677 +                       printk("i2c-sis5595.o: Successfull!\n");
4678 +#endif
4679 +               }
4680 +       }
4681 +
4682 +       /* start the transaction by setting bit 4 */
4683 +       sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
4684 +
4685 +       /* We will always wait for a fraction of a second! */
4686 +       do {
4687 +               i2c_delay(1);
4688 +               temp = sis5595_read(SMB_STS_LO);
4689 +       } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
4690 +
4691 +       /* If the SMBus is still busy, we give up */
4692 +       if (timeout >= MAX_TIMEOUT) {
4693 +#ifdef DEBUG
4694 +               printk("i2c-sis5595.o: SMBus Timeout!\n");
4695 +#endif
4696 +               result = -1;
4697 +       }
4698 +
4699 +       if (temp & 0x10) {
4700 +               result = -1;
4701 +#ifdef DEBUG
4702 +               printk("i2c-sis5595.o: Error: Failed bus transaction\n");
4703 +#endif
4704 +       }
4705 +
4706 +       if (temp & 0x20) {
4707 +               result = -1;
4708 +               printk
4709 +                   ("i2c-sis5595.o: Bus collision! SMBus may be locked until next hard\n"
4710 +                    "reset (or not...)\n");
4711 +               /* Clock stops and slave is stuck in mid-transmission */
4712 +       }
4713 +
4714 +       if (
4715 +           (temp =
4716 +            sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
4717 +           0x00) {
4718 +               sis5595_write(SMB_STS_LO, temp & 0xff);
4719 +               sis5595_write(SMB_STS_HI, temp >> 8);
4720 +       }
4721 +
4722 +       if (
4723 +           (temp =
4724 +            sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
4725 +           0x00) {
4726 +
4727 +#ifdef DEBUG
4728 +               printk
4729 +                   ("i2c-sis5595.o: Failed reset at end of transaction (%02x)\n",
4730 +                    temp);
4731 +#endif
4732 +       }
4733 +       return result;
4734 +}
4735 +
4736 +/* Return -1 on error. */
4737 +s32 sis5595_access(struct i2c_adapter * adap, u16 addr,
4738 +                  unsigned short flags, char read_write,
4739 +                  u8 command, int size, union i2c_smbus_data * data)
4740 +{
4741 +       switch (size) {
4742 +       case I2C_SMBUS_QUICK:
4743 +               sis5595_write(SMB_ADDR,
4744 +                             ((addr & 0x7f) << 1) | (read_write & 0x01));
4745 +               size = SIS5595_QUICK;
4746 +               break;
4747 +       case I2C_SMBUS_BYTE:
4748 +               sis5595_write(SMB_ADDR,
4749 +                             ((addr & 0x7f) << 1) | (read_write & 0x01));
4750 +               if (read_write == I2C_SMBUS_WRITE)
4751 +                       sis5595_write(SMB_CMD, command);
4752 +               size = SIS5595_BYTE;
4753 +               break;
4754 +       case I2C_SMBUS_BYTE_DATA:
4755 +               sis5595_write(SMB_ADDR,
4756 +                             ((addr & 0x7f) << 1) | (read_write & 0x01));
4757 +               sis5595_write(SMB_CMD, command);
4758 +               if (read_write == I2C_SMBUS_WRITE)
4759 +                       sis5595_write(SMB_BYTE, data->byte);
4760 +               size = SIS5595_BYTE_DATA;
4761 +               break;
4762 +       case I2C_SMBUS_PROC_CALL:
4763 +       case I2C_SMBUS_WORD_DATA:
4764 +               sis5595_write(SMB_ADDR,
4765 +                             ((addr & 0x7f) << 1) | (read_write & 0x01));
4766 +               sis5595_write(SMB_CMD, command);
4767 +               if (read_write == I2C_SMBUS_WRITE) {
4768 +                       sis5595_write(SMB_BYTE, data->word & 0xff);
4769 +                       sis5595_write(SMB_BYTE + 1,
4770 +                                     (data->word & 0xff00) >> 8);
4771 +               }
4772 +               size =
4773 +                   (size ==
4774 +                    I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL :
4775 +                   SIS5595_WORD_DATA;
4776 +               break;
4777 +/*
4778 +       case I2C_SMBUS_BLOCK_DATA:
4779 +               printk("sis5595.o: Block data not yet implemented!\n");
4780 +               return -1;
4781 +               break;
4782 +*/
4783 +       default:
4784 +               printk
4785 +                   (KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size);
4786 +               return -1;
4787 +       }
4788 +
4789 +       sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
4790 +
4791 +       if (sis5595_transaction())      /* Error in transaction */
4792 +               return -1;
4793 +
4794 +       if ((size != SIS5595_PROC_CALL) &&
4795 +           ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
4796 +               return 0;
4797 +
4798 +
4799 +       switch (size) {
4800 +       case SIS5595_BYTE:      /* Where is the result put? I assume here it is in
4801 +                                  SMB_DATA but it might just as well be in the
4802 +                                  SMB_CMD. No clue in the docs */
4803 +       case SIS5595_BYTE_DATA:
4804 +               data->byte = sis5595_read(SMB_BYTE);
4805 +               break;
4806 +       case SIS5595_WORD_DATA:
4807 +       case SIS5595_PROC_CALL:
4808 +               data->word =
4809 +                   sis5595_read(SMB_BYTE) +
4810 +                   (sis5595_read(SMB_BYTE + 1) << 8);
4811 +               break;
4812 +       }
4813 +       return 0;
4814 +}
4815 +
4816 +
4817 +u32 sis5595_func(struct i2c_adapter *adapter)
4818 +{
4819 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
4820 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
4821 +           I2C_FUNC_SMBUS_PROC_CALL;
4822 +}
4823 +
4824 +
4825 +static struct i2c_algorithm smbus_algorithm = {
4826 +       .name           = "Non-I2C SMBus adapter",
4827 +       .id             = I2C_ALGO_SMBUS,
4828 +       .smbus_xfer     = sis5595_access,
4829 +       .functionality  = sis5595_func,
4830 +};
4831 +
4832 +static struct i2c_adapter sis5595_adapter = {
4833 +       .owner          = THIS_MODULE,
4834 +       .name           = "unset",
4835 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS5595,
4836 +       .algo           = &smbus_algorithm,
4837 +};
4838 +
4839 +
4840 +static struct pci_device_id sis5595_ids[] __devinitdata = {
4841 +       {
4842 +               .vendor =       PCI_VENDOR_ID_SI,
4843 +               .device =       PCI_DEVICE_ID_SI_503,
4844 +               .subvendor =    PCI_ANY_ID,
4845 +               .subdevice =    PCI_ANY_ID,
4846 +       },
4847 +       { 0, }
4848 +};
4849 +
4850 +static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
4851 +{
4852 +
4853 +       if (sis5595_setup(dev)) {
4854 +               printk
4855 +                   ("i2c-sis5595.o: SIS5595 not detected, module not inserted.\n");
4856 +
4857 +               return -ENODEV;
4858 +       }
4859 +
4860 +       sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
4861 +               sis5595_base + SMB_INDEX);
4862 +       i2c_add_adapter(&sis5595_adapter);
4863 +
4864 +       return 0;
4865 +}
4866 +
4867 +static void __devexit sis5595_remove(struct pci_dev *dev)
4868 +{
4869 +       i2c_del_adapter(&sis5595_adapter);
4870 +       release_region(sis5595_base + SMB_INDEX, 2);
4871 +}
4872 +
4873 +
4874 +static struct pci_driver sis5595_driver = {
4875 +       .name           = "sis5595 smbus",
4876 +       .id_table       = sis5595_ids,
4877 +       .probe          = sis5595_probe,
4878 +       .remove         = __devexit_p(sis5595_remove),
4879 +};
4880 +
4881 +static int __init i2c_sis5595_init(void)
4882 +{
4883 +       printk("i2c-sis5595.o version %s (%s)\n", LM_VERSION, LM_DATE);
4884 +       return pci_module_init(&sis5595_driver);
4885 +}
4886 +
4887 +
4888 +static void __exit i2c_sis5595_exit(void)
4889 +{
4890 +       pci_unregister_driver(&sis5595_driver);
4891 +}
4892 +
4893 +
4894 +
4895 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
4896 +MODULE_DESCRIPTION("SIS5595 SMBus driver");
4897 +
4898 +module_init(i2c_sis5595_init);
4899 +module_exit(i2c_sis5595_exit);
4900 --- linux-old/drivers/i2c/i2c-sis630.c  Thu Jan  1 00:00:00 1970
4901 +++ linux/drivers/i2c/i2c-sis630.c      Mon Dec 13 20:18:42 2004
4902 @@ -0,0 +1,527 @@
4903 +/*
4904 +    i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware
4905 +              monitoring
4906 +
4907 +    Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
4908 +
4909 +    This program is free software; you can redistribute it and/or modify
4910 +    it under the terms of the GNU General Public License as published by
4911 +    the Free Software Foundation; either version 2 of the License, or
4912 +    (at your option) any later version.
4913 +
4914 +    This program is distributed in the hope that it will be useful,
4915 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
4916 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4917 +    GNU General Public License for more details.
4918 +
4919 +    You should have received a copy of the GNU General Public License
4920 +    along with this program; if not, write to the Free Software
4921 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4922 +*/
4923 +
4924 +/*
4925 +   Changes:
4926 +   24.08.2002
4927 +       Fixed the typo in sis630_access (Thanks to Mark M. Hoffman)
4928 +       Changed sis630_transaction.(Thanks to Mark M. Hoffman)
4929 +   18.09.2002
4930 +       Added SIS730 as supported.
4931 +   21.09.2002
4932 +       Added high_clock module option.If this option is set
4933 +       used Host Master Clock 56KHz (default 14KHz).For now we save old Host
4934 +       Master Clock and after transaction completed restore (otherwise
4935 +       it's confuse BIOS and hung Machine).
4936 +   24.09.2002
4937 +       Fixed typo in sis630_access
4938 +       Fixed logical error by restoring of Host Master Clock
4939 +   31.07.2003
4940 +       Added block data read/write support.
4941 +*/
4942 +
4943 +/*
4944 +   Status: beta
4945 +
4946 +   Supports:
4947 +       SIS 630
4948 +       SIS 730
4949 +
4950 +   Note: we assume there can only be one device, with one SMBus interface.
4951 +*/
4952 +
4953 +#include <linux/module.h>
4954 +#include <linux/kernel.h>
4955 +#include <linux/pci.h>
4956 +#include <linux/stddef.h>
4957 +#include <linux/sched.h>
4958 +#include <linux/ioport.h>
4959 +#include <linux/i2c.h>
4960 +#include <linux/init.h>
4961 +#include <asm/io.h>
4962 +#define LM_DATE "20041007"
4963 +#define LM_VERSION "2.8.8"
4964 +
4965 +
4966 +#ifdef DEBUG
4967 +#define DBG(x...) printk(KERN_DEBUG "i2c-sis630.o: " x)
4968 +#else
4969 +#define DBG(x...)
4970 +#endif
4971 +
4972 +/* SIS630 SMBus registers */
4973 +#define SMB_STS     0x80 /* status */
4974 +#define SMB_EN      0x81 /* status enable */
4975 +#define SMB_CNT     0x82
4976 +#define SMBHOST_CNT 0x83
4977 +#define SMB_ADDR    0x84
4978 +#define SMB_CMD     0x85
4979 +#define SMB_PCOUNT  0x86 /* processed count */
4980 +#define SMB_COUNT   0x87
4981 +#define SMB_BYTE    0x88 /* ~0x8F data byte field */
4982 +#define SMBDEV_ADDR 0x90
4983 +#define SMB_DB0     0x91
4984 +#define SMB_DB1     0x92
4985 +#define SMB_SAA     0x93
4986 +
4987 +/* register count for request_region */
4988 +#define SIS630_SMB_IOREGION 20
4989 +
4990 +/* PCI address constants */
4991 +/* acpi base address register  */
4992 +#define SIS630_ACPI_BASE_REG 0x74
4993 +/* bios control register */
4994 +#define SIS630_BIOS_CTL_REG  0x40
4995 +
4996 +/* Other settings */
4997 +#define MAX_TIMEOUT   500
4998 +
4999 +/* SIS630 constants */
5000 +#define SIS630_QUICK      0x00
5001 +#define SIS630_BYTE       0x01
5002 +#define SIS630_BYTE_DATA  0x02
5003 +#define SIS630_WORD_DATA  0x03
5004 +#define SIS630_PCALL      0x04
5005 +#define SIS630_BLOCK_DATA 0x05
5006 +
5007 +/* insmod parameters */
5008 +static int high_clock = 0;
5009 +static int force = 0;
5010 +MODULE_PARM(high_clock, "i");
5011 +MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
5012 +MODULE_PARM(force, "i");
5013 +MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
5014 +
5015 +/* acpi base address */
5016 +static unsigned short acpi_base = 0;
5017 +
5018 +/* supported chips */
5019 +static int supported[] = {
5020 +       PCI_DEVICE_ID_SI_630,
5021 +       PCI_DEVICE_ID_SI_730,
5022 +       0 /* terminates the list */
5023 +};
5024 +
5025 +static inline u8 sis630_read(u8 reg) {
5026 +       return inb(acpi_base + reg);
5027 +}
5028 +
5029 +static inline void sis630_write(u8 reg, u8 data) {
5030 +       outb(data, acpi_base + reg);
5031 +}
5032 +
5033 +static int sis630_transaction_start(int size, u8 *oldclock) {
5034 +        int temp;
5035 +
5036 +        /*
5037 +         Make sure the SMBus host is ready to start transmitting.
5038 +       */
5039 +       if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
5040 +                DBG("SMBus busy (%02x).Resetting...\n",temp);
5041 +               /* kill smbus transaction */
5042 +               sis630_write(SMBHOST_CNT, 0x20);
5043 +
5044 +               if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
5045 +                        DBG("Failed! (%02x)\n", temp);
5046 +                       return -1;
5047 +                } else {
5048 +                        DBG("Successfull!\n");
5049 +               }
5050 +        }
5051 +
5052 +       /* save old clock, so we can prevent machine for hung */
5053 +       *oldclock = sis630_read(SMB_CNT);
5054 +
5055 +       DBG("saved clock 0x%02x\n", *oldclock);
5056 +
5057 +       /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
5058 +       if (high_clock > 0)
5059 +               sis630_write(SMB_CNT, 0x20);
5060 +       else
5061 +               sis630_write(SMB_CNT, (*oldclock & ~0x40));
5062 +
5063 +       /* clear all sticky bits */
5064 +       temp = sis630_read(SMB_STS);
5065 +       sis630_write(SMB_STS, temp & 0x1e);
5066 +
5067 +       /* start the transaction by setting bit 4 and size */
5068 +       sis630_write(SMBHOST_CNT,0x10 | (size & 0x07));
5069 +
5070 +       return 0;
5071 +}
5072 +
5073 +static int sis630_transaction_wait(int size) {
5074 +        int temp, result = 0, timeout = 0;
5075 +
5076 +        /* We will always wait for a fraction of a second! */
5077 +        do {
5078 +                i2c_delay(1);
5079 +                temp = sis630_read(SMB_STS);
5080 +               /* check if block transmitted */
5081 +               if (size == SIS630_BLOCK_DATA && (temp & 0x10))
5082 +                   break;
5083 +        } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
5084 +
5085 +        /* If the SMBus is still busy, we give up */
5086 +        if (timeout >= MAX_TIMEOUT) {
5087 +                DBG("SMBus Timeout!\n");
5088 +               result = -1;
5089 +        }
5090 +
5091 +        if (temp & 0x02) {
5092 +                result = -1;
5093 +                DBG("Error: Failed bus transaction\n");
5094 +       }
5095 +
5096 +        if (temp & 0x04) {
5097 +                result = -1;
5098 +                printk(KERN_ERR "i2c-sis630.o: Bus collision!\n");
5099 +               /*
5100 +                  TBD: Datasheet say:
5101 +                       the software should clear this bit and restart SMBUS operation.
5102 +                       Should we do it or user start request again?
5103 +               */
5104 +        }
5105 +
5106 +       return result;
5107 +}
5108 +
5109 +static void sis630_transaction_end(u8 oldclock) {
5110 +        int temp = 0;
5111 +
5112 +        /* clear all status "sticky" bits */
5113 +       sis630_write(SMB_STS, temp);
5114 +
5115 +       DBG("SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
5116 +
5117 +       /*
5118 +       * restore old Host Master Clock if high_clock is set
5119 +       * and oldclock was not 56KHz
5120 +       */
5121 +       if (high_clock > 0 && !(oldclock & 0x20))
5122 +               sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20));
5123 +
5124 +       DBG("SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
5125 +}
5126 +
5127 +static int sis630_transaction(int size) {
5128 +        int result = 0;
5129 +       u8 oldclock = 0;
5130 +
5131 +       if (!(result = sis630_transaction_start(size, &oldclock))) {
5132 +               result = sis630_transaction_wait(size);
5133 +               sis630_transaction_end(oldclock);
5134 +       }
5135 +
5136 +        return result;
5137 +}
5138 +
5139 +static int sis630_block_data(union i2c_smbus_data * data, int read_write) {
5140 +       int i, len = 0, rc = 0;
5141 +       u8 oldclock = 0;
5142 +
5143 +       if (read_write == I2C_SMBUS_WRITE) {
5144 +               len = data->block[0];
5145 +               if (len < 0)
5146 +                       len = 0;
5147 +               else if (len > 32)
5148 +                       len = 32;
5149 +               sis630_write(SMB_COUNT, len);
5150 +               for (i=1; i <= len; i++) {
5151 +                       DBG("set data 0x%02x\n", data->block[i]);
5152 +                       /* set data */
5153 +                       sis630_write(SMB_BYTE+(i-1)%8, data->block[i]);
5154 +                       if (i==8 || (len<8 && i==len)) {
5155 +                               DBG("start trans len=%d i=%d\n",len ,i);
5156 +                               /* first transaction */
5157 +                               if (sis630_transaction_start(SIS630_BLOCK_DATA, &oldclock))
5158 +                                       return -1;
5159 +                       }
5160 +                       else if ((i-1)%8 == 7 || i==len) {
5161 +                               DBG("trans_wait len=%d i=%d\n",len,i);
5162 +                               if (i>8) {
5163 +                                       DBG("clear smbary_sts len=%d i=%d\n",len,i);
5164 +                                       /*
5165 +                                          If this is not first transaction,
5166 +                                          we must clear sticky bit.
5167 +                                          clear SMBARY_STS
5168 +                                       */
5169 +                                       sis630_write(SMB_STS,0x10);
5170 +                               }
5171 +                               if (sis630_transaction_wait(SIS630_BLOCK_DATA)) {
5172 +                                       DBG("trans_wait failed\n");
5173 +                                       rc = -1;
5174 +                                       break;
5175 +                               }
5176 +
5177 +                       }
5178 +               }
5179 +       }
5180 +       else { /* read request */
5181 +               data->block[0] = len = 0;
5182 +               if (sis630_transaction_start(SIS630_BLOCK_DATA, &oldclock)) {
5183 +                       return -1;
5184 +               }
5185 +               do {
5186 +                       if (sis630_transaction_wait(SIS630_BLOCK_DATA)) {
5187 +                               DBG("trans_wait failed\n");
5188 +                               rc = -1;
5189 +                               break;
5190 +                       }
5191 +                       /* if this first transaction then read byte count */
5192 +                       if (len == 0)
5193 +                               data->block[0] = sis630_read(SMB_COUNT);
5194 +
5195 +                       /* just to be sure */
5196 +                       if (data->block[0] > 32)
5197 +                               data->block[0] = 32;
5198 +
5199 +                       DBG("block data read len=0x%x\n", data->block[0]);
5200 +
5201 +                       for (i=0; i < 8 && len < data->block[0]; i++,len++) {
5202 +                               DBG("read i=%d len=%d\n", i, len);
5203 +                               data->block[len+1] = sis630_read(SMB_BYTE+i);
5204 +                       }
5205 +
5206 +                       DBG("clear smbary_sts len=%d i=%d\n",len,i);
5207 +
5208 +                       /* clear SMBARY_STS */
5209 +                       sis630_write(SMB_STS,0x10);
5210 +               } while(len < data->block[0]);
5211 +       }
5212 +
5213 +       sis630_transaction_end(oldclock);
5214 +
5215 +       return rc;
5216 +}
5217 +
5218 +/* Return -1 on error. */
5219 +static s32 sis630_access(struct i2c_adapter * adap, u16 addr,
5220 +                  unsigned short flags, char read_write,
5221 +                  u8 command, int size, union i2c_smbus_data * data)
5222 +{
5223 +
5224 +       switch (size) {
5225 +               case I2C_SMBUS_QUICK:
5226 +                       sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5227 +                       size = SIS630_QUICK;
5228 +                       break;
5229 +               case I2C_SMBUS_BYTE:
5230 +                       sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5231 +                       if (read_write == I2C_SMBUS_WRITE)
5232 +                               sis630_write(SMB_CMD, command);
5233 +                       size = SIS630_BYTE;
5234 +                       break;
5235 +               case I2C_SMBUS_BYTE_DATA:
5236 +                       sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5237 +                       sis630_write(SMB_CMD, command);
5238 +                       if (read_write == I2C_SMBUS_WRITE)
5239 +                               sis630_write(SMB_BYTE, data->byte);
5240 +                       size = SIS630_BYTE_DATA;
5241 +                       break;
5242 +               case I2C_SMBUS_PROC_CALL:
5243 +               case I2C_SMBUS_WORD_DATA:
5244 +                       sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
5245 +                       sis630_write(SMB_CMD, command);
5246 +                       if (read_write == I2C_SMBUS_WRITE) {
5247 +                               sis630_write(SMB_BYTE, data->word & 0xff);
5248 +                               sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8);
5249 +                       }
5250 +                       size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
5251 +                       break;
5252 +               case I2C_SMBUS_BLOCK_DATA:
5253 +                       sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
5254 +                       sis630_write(SMB_CMD, command);
5255 +                       size = SIS630_BLOCK_DATA;
5256 +                       return sis630_block_data(data, read_write);
5257 +               default:
5258 +                       printk("Unsupported I2C size\n");
5259 +                       return -1;
5260 +                       break;
5261 +       }
5262 +
5263 +
5264 +       if (sis630_transaction(size))
5265 +               return -1;
5266 +
5267 +        if ((size != SIS630_PCALL) &&
5268 +               ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
5269 +                return 0;
5270 +       }
5271 +
5272 +       switch(size) {
5273 +               case SIS630_BYTE:
5274 +               case SIS630_BYTE_DATA:
5275 +                       data->byte = sis630_read(SMB_BYTE);
5276 +                       break;
5277 +               case SIS630_PCALL:
5278 +               case SIS630_WORD_DATA:
5279 +                       data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
5280 +                       break;
5281 +               default:
5282 +                       return -1;
5283 +                       break;
5284 +       }
5285 +
5286 +       return 0;
5287 +}
5288 +
5289 +
5290 +static u32 sis630_func(struct i2c_adapter *adapter) {
5291 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
5292 +               I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
5293 +               I2C_FUNC_SMBUS_BLOCK_DATA;
5294 +}
5295 +
5296 +static int __devinit sis630_setup(struct pci_dev *sis630_dev) {
5297 +       unsigned char b;
5298 +       struct pci_dev *dummy = NULL;
5299 +       int i;
5300 +
5301 +       /* check for supported SiS devices */
5302 +       for (i=0; supported[i] > 0; i++) {
5303 +               if ((dummy = pci_find_device(PCI_VENDOR_ID_SI, supported[i], dummy)))
5304 +                       break; /* found */
5305 +       }
5306 +
5307 +       if (!dummy && force > 0) {
5308 +               printk(KERN_ERR "i2c-sis630.o: WARNING: Can't detect SIS630 compatible device, but "
5309 +                       "loading because of force option enabled\n");
5310 +       }
5311 +       else if (!dummy) {
5312 +               return -ENODEV;
5313 +       }
5314 +
5315 +       /*
5316 +          Enable ACPI first , so we can accsess reg 74-75
5317 +          in acpi io space and read acpi base addr
5318 +       */
5319 +       if (PCIBIOS_SUCCESSFUL !=
5320 +           pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
5321 +               printk(KERN_ERR "i2c-sis630.o: Error: Can't read bios ctl reg\n");
5322 +               return -ENODEV;
5323 +       }
5324 +
5325 +       /* if ACPI already enabled , do nothing */
5326 +       if (!(b & 0x80) &&
5327 +           PCIBIOS_SUCCESSFUL !=
5328 +           pci_write_config_byte(sis630_dev,SIS630_BIOS_CTL_REG,b|0x80)) {
5329 +               printk(KERN_ERR "i2c-sis630.o: Error: Can't enable ACPI\n");
5330 +               return -ENODEV;
5331 +       }
5332 +       /* Determine the ACPI base address */
5333 +       if (PCIBIOS_SUCCESSFUL !=
5334 +           pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
5335 +               printk(KERN_ERR "i2c-sis630.o: Error: Can't determine ACPI base address\n");
5336 +               return -ENODEV;
5337 +       }
5338 +
5339 +       DBG("ACPI base at 0x%04x\n", acpi_base);
5340 +
5341 +       /* Everything is happy, let's grab the memory and set things up. */
5342 +       if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")){
5343 +               printk(KERN_ERR "i2c-sis630.o: SMBus registers 0x%04x-0x%04x "
5344 +                       "already in use!\n",acpi_base + SMB_STS, acpi_base + SMB_SAA);
5345 +               acpi_base = 0; /* reset acpi_base */
5346 +               return -ENODEV;
5347 +       }
5348 +
5349 +       return 0;
5350 +}
5351 +
5352 +
5353 +static struct i2c_algorithm smbus_algorithm = {
5354 +       .name           = "Non-I2C SMBus adapter",
5355 +       .id             = I2C_ALGO_SMBUS,
5356 +       .smbus_xfer     = sis630_access,
5357 +       .functionality  = sis630_func,
5358 +};
5359 +
5360 +static struct i2c_adapter sis630_adapter = {
5361 +       .owner          = THIS_MODULE,
5362 +       .name           = "unset",
5363 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS630,
5364 +       .algo           = &smbus_algorithm,
5365 +};
5366 +
5367 +
5368 +static struct pci_device_id sis630_ids[] __devinitdata = {
5369 +       {
5370 +               .vendor =       PCI_VENDOR_ID_SI,
5371 +               .device =       PCI_DEVICE_ID_SI_503,
5372 +               .subvendor =    PCI_ANY_ID,
5373 +               .subdevice =    PCI_ANY_ID,
5374 +       },
5375 +       { 0, }
5376 +};
5377 +
5378 +static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
5379 +{
5380 +       if (sis630_setup(dev)) {
5381 +               printk(KERN_ERR "i2c-sis630.o: SIS630 comp. bus not detected, module not inserted.\n");
5382 +               return -ENODEV;
5383 +       }
5384 +
5385 +       sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
5386 +               acpi_base + SMB_STS);
5387 +
5388 +       return i2c_add_adapter(&sis630_adapter);
5389 +}
5390 +
5391 +static void __devexit sis630_remove(struct pci_dev *dev)
5392 +{
5393 +       if (acpi_base) {
5394 +               i2c_del_adapter(&sis630_adapter);
5395 +               release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
5396 +               acpi_base = 0;
5397 +       }
5398 +}
5399 +
5400 +
5401 +static struct pci_driver sis630_driver = {
5402 +       .name           = "sis630 smbus",
5403 +       .id_table       = sis630_ids,
5404 +       .probe          = sis630_probe,
5405 +       .remove         = __devexit_p(sis630_remove),
5406 +};
5407 +
5408 +static int __init i2c_sis630_init(void)
5409 +{
5410 +       printk("i2c-sis630.o version %s (%s)\n", LM_VERSION, LM_DATE);
5411 +       return pci_module_init(&sis630_driver);
5412 +}
5413 +
5414 +
5415 +static void __exit i2c_sis630_exit(void)
5416 +{
5417 +       pci_unregister_driver(&sis630_driver);
5418 +}
5419 +
5420 +
5421 +
5422 +
5423 +MODULE_LICENSE("GPL");
5424 +
5425 +MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
5426 +MODULE_DESCRIPTION("SIS630 SMBus driver");
5427 +
5428 +module_init(i2c_sis630_init);
5429 +module_exit(i2c_sis630_exit);
5430 --- linux-old/drivers/i2c/i2c-sis645.c  Thu Jan  1 00:00:00 1970
5431 +++ linux/drivers/i2c/i2c-sis645.c      Mon Dec 13 20:18:42 2004
5432 @@ -0,0 +1,590 @@
5433 +/*
5434 +    sis645.c - Part of lm_sensors, Linux kernel modules for hardware
5435 +              monitoring
5436 +
5437 +    Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
5438 +
5439 +    This program is free software; you can redistribute it and/or modify
5440 +    it under the terms of the GNU General Public License as published by
5441 +    the Free Software Foundation; either version 2 of the License, or
5442 +    (at your option) any later version.
5443 +
5444 +    This program is distributed in the hope that it will be useful,
5445 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
5446 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5447 +    GNU General Public License for more details.
5448 +
5449 +    You should have received a copy of the GNU General Public License
5450 +    along with this program; if not, write to the Free Software
5451 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5452 +*/
5453 +
5454 +/*
5455 +    This module must be considered BETA unless and until
5456 +    the chipset manufacturer releases a datasheet.
5457 +
5458 +    The register definitions are based on the SiS630.
5459 +    The method for *finding* the registers is based on trial and error.
5460 +
5461 +    A history of changes to this file is available by anonymous CVS:
5462 +    http://www2.lm-sensors.nu/~lm78/download.html
5463 +*/
5464 +
5465 +/*   25th March 2004
5466 +     Support for Sis655 chipsets added by Ken Healy
5467 +*/
5468 +
5469 +/*
5470 +    Note: we assume there can only be one SiS645 with one SMBus interface
5471 +*/
5472 +
5473 +/* #define DEBUG 1 */
5474 +
5475 +#include <linux/module.h>
5476 +#include <linux/pci.h>
5477 +#include <linux/kernel.h>
5478 +#include <linux/stddef.h>
5479 +#include <linux/sched.h>
5480 +#include <linux/ioport.h>
5481 +#include <linux/i2c.h>
5482 +#include <linux/init.h>
5483 +#include <linux/mm.h>
5484 +#include <asm/io.h>
5485 +#define LM_DATE "20041007"
5486 +#define LM_VERSION "2.8.8"
5487 +#include <linux/sensors_compat.h>
5488 +
5489 +#define DRV_NAME "i2c-sis645"
5490 +
5491 +/* SiS645DX north bridge (defined in 2.4.21) */
5492 +#ifndef PCI_DEVICE_ID_SI_646
5493 +#define PCI_DEVICE_ID_SI_646 0x0646
5494 +#endif
5495 +
5496 +/* SiS648 north bridge (defined in 2.4.21) */
5497 +#ifndef PCI_DEVICE_ID_SI_648
5498 +#define PCI_DEVICE_ID_SI_648 0x0648
5499 +#endif
5500 +
5501 +/* SiS650 north bridge (defined in 2.4.19) */
5502 +#ifndef PCI_DEVICE_ID_SI_650
5503 +#define PCI_DEVICE_ID_SI_650 0x0650
5504 +#endif
5505 +
5506 +/* SiS651 north bridge (defined in 2.4.21)*/
5507 +#ifndef PCI_DEVICE_ID_SI_651
5508 +#define PCI_DEVICE_ID_SI_651 0x0651
5509 +#endif
5510 +
5511 +/* SiS655 north bridge (defined in 2.4.22)*/
5512 +#ifndef PCI_DEVICE_ID_SI_655
5513 +#define PCI_DEVICE_ID_SI_655 0x0655
5514 +#endif
5515 +
5516 +/* SiS746 north bridge (defined in 2.4.21) */
5517 +#ifndef PCI_DEVICE_ID_SI_746
5518 +#define PCI_DEVICE_ID_SI_746 0x0746
5519 +#endif
5520 +
5521 +/* SiS85C503/5513 (LPC Bridge) */
5522 +#ifndef PCI_DEVICE_ID_SI_LPC
5523 +#define PCI_DEVICE_ID_SI_LPC 0x0018
5524 +#endif
5525 +
5526 +/* SiS961 south bridge */
5527 +#ifndef PCI_DEVICE_ID_SI_961
5528 +#define PCI_DEVICE_ID_SI_961 0x0961
5529 +#endif
5530 +
5531 +/* SiS962 south bridge */
5532 +#ifndef PCI_DEVICE_ID_SI_962
5533 +#define PCI_DEVICE_ID_SI_962 0x0962
5534 +#endif
5535 +
5536 +/* SiS963 south bridge */
5537 +#ifndef PCI_DEVICE_ID_SI_963
5538 +#define PCI_DEVICE_ID_SI_963 0x0963
5539 +#endif
5540 +
5541 +/* SMBus ID */
5542 +#ifndef PCI_DEVICE_ID_SI_SMBUS
5543 +#define PCI_DEVICE_ID_SI_SMBUS 0x16
5544 +#endif
5545 +
5546 +/* base address register in PCI config space */
5547 +#define SIS645_BAR 0x04
5548 +
5549 +/* SiS645 SMBus registers */
5550 +#define SMB_STS      0x00
5551 +#define SMB_EN       0x01
5552 +#define SMB_CNT      0x02
5553 +#define SMB_HOST_CNT 0x03
5554 +#define SMB_ADDR     0x04
5555 +#define SMB_CMD      0x05
5556 +#define SMB_PCOUNT   0x06
5557 +#define SMB_COUNT    0x07
5558 +#define SMB_BYTE     0x08
5559 +#define SMB_DEV_ADDR 0x10
5560 +#define SMB_DB0      0x11
5561 +#define SMB_DB1      0x12
5562 +#define SMB_SAA      0x13
5563 +
5564 +/* register count for request_region */
5565 +#define SMB_IOSIZE 0x20
5566 +
5567 +/* Other settings */
5568 +#define MAX_TIMEOUT 500
5569 +
5570 +/* SiS645 SMBus constants */
5571 +#define SIS645_QUICK      0x00
5572 +#define SIS645_BYTE       0x01
5573 +#define SIS645_BYTE_DATA  0x02
5574 +#define SIS645_WORD_DATA  0x03
5575 +#define SIS645_PROC_CALL  0x04
5576 +#define SIS645_BLOCK_DATA 0x05
5577 +
5578 +static struct i2c_adapter sis645_adapter;
5579 +static u16 sis645_smbus_base = 0;
5580 +
5581 +static inline u8 sis645_read(u8 reg)
5582 +{
5583 +       return inb(sis645_smbus_base + reg) ;
5584 +}
5585 +
5586 +static inline void sis645_write(u8 reg, u8 data)
5587 +{
5588 +       outb(data, sis645_smbus_base + reg) ;
5589 +}
5590 +
5591 +#ifdef CONFIG_HOTPLUG
5592 +
5593 +/* Turns on SMBus device if it is not; return 0 iff successful
5594 + */
5595 +static int __devinit sis645_enable_smbus(struct pci_dev *dev)
5596 +{
5597 +       u8 val = 0;
5598 +
5599 +       pci_read_config_byte(dev, 0x77, &val);
5600 +
5601 +#ifdef DEBUG
5602 +       printk(KERN_DEBUG DRV_NAME ": Config byte was 0x%02x.\n", val);
5603 +#endif
5604 +
5605 +       pci_write_config_byte(dev, 0x77, val & ~0x10);
5606 +
5607 +       pci_read_config_byte(dev, 0x77, &val);
5608 +
5609 +       if (val & 0x10) {
5610 +#ifdef DEBUG
5611 +               printk(KERN_DEBUG DRV_NAME ": Config byte stuck!\n");
5612 +#endif
5613 +               return -1;
5614 +       }
5615 +
5616 +       return 0;
5617 +}
5618 +
5619 +/* Builds the basic pci_dev for SiS645 SMBus
5620 + */
5621 +static int __devinit sis645_build_dev(struct pci_dev **smbus_dev,
5622 +                           struct pci_dev *bridge_dev)
5623 +{
5624 +       struct pci_dev temp_dev;
5625 +       u16 vid = 0, did = 0;
5626 +       int ret;
5627 +
5628 +       /* fill in the device structure for search */
5629 +       memset(&temp_dev, 0, sizeof(temp_dev));
5630 +       temp_dev.bus = bridge_dev->bus;
5631 +       temp_dev.sysdata = bridge_dev->bus->sysdata;
5632 +       temp_dev.hdr_type = PCI_HEADER_TYPE_NORMAL;
5633 +
5634 +       /* the SMBus device is function 1 on the same unit as the ISA bridge */
5635 +       temp_dev.devfn = bridge_dev->devfn + 1;
5636 +
5637 +       /* query to make sure */
5638 +       ret = pci_read_config_word(&temp_dev, PCI_VENDOR_ID, &vid);
5639 +       if (ret || PCI_VENDOR_ID_SI != vid) {
5640 +               printk(KERN_ERR DRV_NAME ": Couldn't find SMBus device!\n");
5641 +               return ret;
5642 +       }
5643 +       temp_dev.vendor = vid;
5644 +
5645 +       ret = pci_read_config_word(&temp_dev, PCI_DEVICE_ID, &did);
5646 +       if (ret || PCI_DEVICE_ID_SI_SMBUS != did) {
5647 +               printk(KERN_ERR DRV_NAME ": Couldn't find SMBus device!\n");
5648 +               return ret;
5649 +       }
5650 +       temp_dev.device = did;
5651 +
5652 +       /* ok, we've got it... request some memory and finish it off */
5653 +       *smbus_dev = kmalloc(sizeof(**smbus_dev), GFP_ATOMIC);
5654 +       if (NULL == *smbus_dev) {
5655 +               printk(KERN_ERR DRV_NAME ": Out of memory!\n");
5656 +               return -ENOMEM;
5657 +       }
5658 +
5659 +       **smbus_dev = temp_dev;
5660 +       
5661 +       ret = pci_setup_device(*smbus_dev);
5662 +       if (ret) {
5663 +               printk(KERN_ERR DRV_NAME ": pci_setup_device failed (0x%08x)\n",ret);
5664 +       }
5665 +       return ret;
5666 +}
5667 +
5668 +/* See if a SMBus can be found, and enable it if possible.
5669 + */
5670 +static int __devinit sis645_hotplug_smbus(void)
5671 +{
5672 +       int ret;
5673 +       struct pci_dev *smbus_dev, *bridge_dev ;
5674 +
5675 +       if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI,
5676 +                       PCI_DEVICE_ID_SI_961, NULL)))
5677 +               printk(KERN_INFO DRV_NAME ": Found SiS961 south bridge.\n");
5678 +
5679 +       else if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI,
5680 +                       PCI_DEVICE_ID_SI_962, NULL)))
5681 +               printk(KERN_INFO DRV_NAME ": Found SiS962 [MuTIOL Media IO].\n");
5682 +
5683 +       else if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI,
5684 +                       PCI_DEVICE_ID_SI_963, NULL)))
5685 +               printk(KERN_INFO DRV_NAME ": Found SiS963 [MuTIOL Media IO].\n");
5686 +               
5687 +       else if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI,
5688 +                       PCI_DEVICE_ID_SI_503, NULL)) ||
5689 +               (bridge_dev = pci_find_device(PCI_VENDOR_ID_SI,
5690 +                       PCI_DEVICE_ID_SI_LPC, NULL))) {
5691 +
5692 +               printk(KERN_INFO DRV_NAME ": Found SiS south bridge in compatability mode(?)\n");
5693 +
5694 +               /* look for known compatible north bridges */
5695 +               if ((NULL == pci_find_device(PCI_VENDOR_ID_SI, 
5696 +                               PCI_DEVICE_ID_SI_645, NULL))
5697 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5698 +                               PCI_DEVICE_ID_SI_646, NULL))
5699 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5700 +                               PCI_DEVICE_ID_SI_648, NULL))
5701 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5702 +                               PCI_DEVICE_ID_SI_650, NULL))
5703 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5704 +                               PCI_DEVICE_ID_SI_651, NULL))
5705 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5706 +                               PCI_DEVICE_ID_SI_655, NULL))
5707 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5708 +                               PCI_DEVICE_ID_SI_735, NULL))
5709 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5710 +                               PCI_DEVICE_ID_SI_745, NULL))
5711 +                       && (NULL == pci_find_device(PCI_VENDOR_ID_SI,
5712 +                               PCI_DEVICE_ID_SI_746, NULL))) {
5713 +                       printk(KERN_ERR DRV_NAME ": Can't find suitable host bridge!\n");
5714 +                       return -ENODEV;
5715 +               }
5716 +       } else {
5717 +               printk(KERN_ERR DRV_NAME ": Can't find suitable south bridge!\n");
5718 +               return -ENODEV;
5719 +       }
5720 +
5721 +       /* if we get this far, we think the smbus device is present */
5722 +
5723 +       if ((ret = sis645_enable_smbus(bridge_dev)))
5724 +               return ret;
5725 +
5726 +       if ((ret = sis645_build_dev(&smbus_dev, bridge_dev)))
5727 +               return ret;
5728 +
5729 +       if ((ret = pci_enable_device(smbus_dev))) {
5730 +               printk(KERN_ERR DRV_NAME ": Can't pci_enable SMBus device!"
5731 +                       " (0x%08x)\n", ret);
5732 +               return ret;
5733 +       }
5734 +
5735 +       pci_insert_device(smbus_dev, smbus_dev->bus);
5736 +
5737 +       return 0;
5738 +}
5739 +#endif /* CONFIG_HOTPLUG */
5740 +
5741 +/* Execute a SMBus transaction.
5742 +   int size is from SIS645_QUICK to SIS645_BLOCK_DATA
5743 + */
5744 +static int sis645_transaction(int size)
5745 +{
5746 +       int temp;
5747 +       int result = 0;
5748 +       int timeout = 0;
5749 +
5750 +       /* Make sure the SMBus host is ready to start transmitting */
5751 +       if (((temp = sis645_read(SMB_CNT)) & 0x03) != 0x00) {
5752 +#ifdef DEBUG
5753 +               printk(KERN_DEBUG DRV_NAME ": SMBus busy (0x%02x). Resetting...\n",
5754 +                               temp);
5755 +#endif
5756 +
5757 +               /* kill the transaction */
5758 +               sis645_write(SMB_HOST_CNT, 0x20);
5759 +
5760 +               /* check it again */
5761 +               if (((temp = sis645_read(SMB_CNT)) & 0x03) != 0x00) {
5762 +#ifdef DEBUG
5763 +                       printk(KERN_DEBUG DRV_NAME ": Failed! (0x%02x)\n", temp);
5764 +#endif
5765 +                       return -1;
5766 +               } else {
5767 +#ifdef DEBUG
5768 +                       printk(KERN_DEBUG DRV_NAME ": Successful!\n");
5769 +#endif
5770 +               }
5771 +       }
5772 +
5773 +       /* Turn off timeout interrupts, set fast host clock */
5774 +       sis645_write(SMB_CNT, 0x20);
5775 +
5776 +       /* clear all (sticky) status flags */
5777 +       temp = sis645_read(SMB_STS);
5778 +       sis645_write(SMB_STS, temp & 0x1e);
5779 +
5780 +       /* start the transaction by setting bit 4 and size bits */
5781 +       sis645_write(SMB_HOST_CNT, 0x10 | (size & 0x07));
5782 +
5783 +       /* We will always wait for a fraction of a second! */
5784 +       do {
5785 +               i2c_delay(1);
5786 +               temp = sis645_read(SMB_STS);
5787 +       } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
5788 +
5789 +       /* If the SMBus is still busy, we give up */
5790 +       if (timeout >= MAX_TIMEOUT) {
5791 +               printk(KERN_DEBUG DRV_NAME ": SMBus Timeout! (0x%02x)\n",temp);
5792 +               result = -1;
5793 +       }
5794 +
5795 +       /* device error - probably missing ACK */
5796 +       if (temp & 0x02) {
5797 +#ifdef DEBUG
5798 +               printk(KERN_DEBUG DRV_NAME ": Failed bus transaction!\n");
5799 +#endif
5800 +               result = -1;
5801 +       }
5802 +
5803 +       /* bus collision */
5804 +       if (temp & 0x04) {
5805 +#ifdef DEBUG
5806 +               printk(KERN_DEBUG DRV_NAME ": Bus collision!\n");
5807 +#endif
5808 +               result = -1;
5809 +       }
5810 +
5811 +       /* Finish up by resetting the bus */
5812 +       sis645_write(SMB_STS, temp);
5813 +       if ((temp = sis645_read(SMB_STS))) {
5814 +#ifdef DEBUG
5815 +               printk(KERN_DEBUG DRV_NAME ": Failed reset at end of transaction!"
5816 +                               " (0x%02x)\n", temp);
5817 +#endif
5818 +       }
5819 +
5820 +       return result;
5821 +}
5822 +
5823 +/* Return -1 on error. */
5824 +static s32 sis645_access(struct i2c_adapter * adap, u16 addr,
5825 +                  unsigned short flags, char read_write,
5826 +                  u8 command, int size, union i2c_smbus_data * data)
5827 +{
5828 +
5829 +       switch (size) {
5830 +       case I2C_SMBUS_QUICK:
5831 +               sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5832 +               size = SIS645_QUICK;
5833 +               break;
5834 +
5835 +       case I2C_SMBUS_BYTE:
5836 +               sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5837 +               if (read_write == I2C_SMBUS_WRITE)
5838 +                       sis645_write(SMB_CMD, command);
5839 +               size = SIS645_BYTE;
5840 +               break;
5841 +
5842 +       case I2C_SMBUS_BYTE_DATA:
5843 +               sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5844 +               sis645_write(SMB_CMD, command);
5845 +               if (read_write == I2C_SMBUS_WRITE)
5846 +                       sis645_write(SMB_BYTE, data->byte);
5847 +               size = SIS645_BYTE_DATA;
5848 +               break;
5849 +
5850 +       case I2C_SMBUS_PROC_CALL:
5851 +       case I2C_SMBUS_WORD_DATA:
5852 +               sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5853 +               sis645_write(SMB_CMD, command);
5854 +               if (read_write == I2C_SMBUS_WRITE) {
5855 +                       sis645_write(SMB_BYTE, data->word & 0xff);
5856 +                       sis645_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8);
5857 +               }
5858 +               size = (size == I2C_SMBUS_PROC_CALL ? SIS645_PROC_CALL : SIS645_WORD_DATA);
5859 +               break;
5860 +
5861 +       case I2C_SMBUS_BLOCK_DATA:
5862 +               /* TO DO: */
5863 +               printk(KERN_INFO DRV_NAME ": SMBus block not implemented!\n");
5864 +               return -1;
5865 +               break;
5866 +
5867 +       default:
5868 +               printk(KERN_INFO DRV_NAME ": Unsupported I2C size\n");
5869 +               return -1;
5870 +               break;
5871 +       }
5872 +
5873 +       if (sis645_transaction(size))
5874 +               return -1;
5875 +
5876 +       if ((size != SIS645_PROC_CALL) &&
5877 +                       ((read_write == I2C_SMBUS_WRITE) || (size == SIS645_QUICK)))
5878 +               return 0;
5879 +
5880 +       switch (size) {
5881 +       case SIS645_BYTE:
5882 +       case SIS645_BYTE_DATA:
5883 +               data->byte = sis645_read(SMB_BYTE);
5884 +               break;
5885 +
5886 +       case SIS645_WORD_DATA:
5887 +       case SIS645_PROC_CALL:
5888 +               data->word = sis645_read(SMB_BYTE) +
5889 +                               (sis645_read(SMB_BYTE + 1) << 8);
5890 +               break;
5891 +       }
5892 +       return 0;
5893 +}
5894 +
5895 +static u32 sis645_func(struct i2c_adapter *adapter)
5896 +{
5897 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
5898 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
5899 +           I2C_FUNC_SMBUS_PROC_CALL;
5900 +}
5901 +
5902 +static struct i2c_algorithm smbus_algorithm = {
5903 +       .name           = "Non-I2C SMBus adapter",
5904 +       .id             = I2C_ALGO_SMBUS,
5905 +       .smbus_xfer     = sis645_access,
5906 +       .functionality  = sis645_func,
5907 +};
5908 +
5909 +static struct i2c_adapter sis645_adapter = {
5910 +       .owner          = THIS_MODULE,
5911 +       .name           = "unset",
5912 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS645,
5913 +       .algo           = &smbus_algorithm,
5914 +};
5915 +
5916 +static struct pci_device_id sis645_ids[] __devinitdata = {
5917 +       {
5918 +               .vendor = PCI_VENDOR_ID_SI,
5919 +               .device = PCI_DEVICE_ID_SI_SMBUS,
5920 +               .subvendor = PCI_ANY_ID,
5921 +               .subdevice = PCI_ANY_ID,
5922 +       },
5923 +       { 0, }
5924 +};
5925 +
5926 +static int __devinit sis645_probe(struct pci_dev *dev,
5927 +                               const struct pci_device_id *id)
5928 +{
5929 +       u16 ww = 0;
5930 +       int retval;
5931 +
5932 +       if (sis645_smbus_base) {
5933 +               dev_err(dev, "Only one device supported.\n");
5934 +               return -EBUSY;
5935 +       }
5936 +
5937 +       pci_read_config_word(dev, PCI_CLASS_DEVICE, &ww);
5938 +       if (PCI_CLASS_SERIAL_SMBUS != ww) {
5939 +               dev_err(dev, "Unsupported device class 0x%04x!\n", ww);
5940 +               return -ENODEV;
5941 +       }
5942 +
5943 +       sis645_smbus_base = pci_resource_start(dev, SIS645_BAR);
5944 +       if (!sis645_smbus_base) {
5945 +               dev_err(dev, "SiS645 SMBus base address "
5946 +                       "not initialized!\n");
5947 +               return -EINVAL;
5948 +       }
5949 +       dev_info(dev, "SiS645 SMBus base address: 0x%04x\n",
5950 +                       sis645_smbus_base);
5951 +
5952 +       /* Everything is happy, let's grab the memory and set things up. */
5953 +       if (!request_region(sis645_smbus_base, SMB_IOSIZE, "sis645-smbus")) {
5954 +               dev_err(dev, "SMBus registers 0x%04x-0x%04x "
5955 +                       "already in use!\n", sis645_smbus_base,
5956 +                       sis645_smbus_base + SMB_IOSIZE - 1);
5957 +
5958 +               sis645_smbus_base = 0;
5959 +               return -EINVAL;
5960 +       }
5961 +
5962 +       sprintf(sis645_adapter.name, "SiS645 SMBus adapter at 0x%04x",
5963 +                       sis645_smbus_base);
5964 +
5965 +       if ((retval = i2c_add_adapter(&sis645_adapter))) {
5966 +               dev_err(dev, "Couldn't register adapter!\n");
5967 +               release_region(sis645_smbus_base, SMB_IOSIZE);
5968 +               sis645_smbus_base = 0;
5969 +       }
5970 +
5971 +       return retval;
5972 +}
5973 +
5974 +static void __devexit sis645_remove(struct pci_dev *dev)
5975 +{
5976 +       if (sis645_smbus_base) {
5977 +               i2c_del_adapter(&sis645_adapter);
5978 +               release_region(sis645_smbus_base, SMB_IOSIZE);
5979 +               sis645_smbus_base = 0;
5980 +       }
5981 +}
5982 +
5983 +static struct pci_driver sis645_driver = {
5984 +       .name           = "sis645 smbus",
5985 +       .id_table       = sis645_ids,
5986 +       .probe          = sis645_probe,
5987 +       .remove         = __devexit_p(sis645_remove),
5988 +};
5989 +
5990 +static int __init i2c_sis645_init(void)
5991 +{
5992 +       printk(KERN_INFO DRV_NAME ".o version %s (%s)\n", LM_VERSION, LM_DATE);
5993 +
5994 +       /* if the required device id is not present, try to HOTPLUG it first */
5995 +       if (!pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS, NULL)) {
5996 +
5997 +               printk(KERN_INFO DRV_NAME ": "
5998 +                       "Attempting to enable SiS645 SMBus device\n");
5999 +
6000 +#ifdef CONFIG_HOTPLUG
6001 +               sis645_hotplug_smbus();
6002 +#else
6003 +               printk(KERN_INFO DRV_NAME ": "
6004 +                       "Requires kernel with CONFIG_HOTPLUG, sorry!\n");
6005 +#endif
6006 +       }
6007 +
6008 +       return pci_module_init(&sis645_driver);
6009 +}
6010 +
6011 +static void __exit i2c_sis645_exit(void)
6012 +{
6013 +       pci_unregister_driver(&sis645_driver);
6014 +}
6015 +
6016 +MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
6017 +MODULE_DESCRIPTION("SiS645 SMBus driver");
6018 +MODULE_LICENSE("GPL");
6019 +
6020 +/* Register initialization functions using helper macros */
6021 +module_init(i2c_sis645_init);
6022 +module_exit(i2c_sis645_exit);
6023 --- linux-old/drivers/i2c/i2c-tsunami.c Thu Jan  1 00:00:00 1970
6024 +++ linux/drivers/i2c/i2c-tsunami.c     Mon Dec 13 20:18:42 2004
6025 @@ -0,0 +1,155 @@
6026 +/*
6027 +    i2c-tsunami.c - Part of lm_sensors, Linux kernel modules for hardware
6028 +              monitoring
6029 +    Copyright (c) 2001  Oleg Vdovikin <vdovikin@jscc.ru>
6030 +    
6031 +    Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
6032 +    Simon Vogl
6033 +
6034 +    This program is free software; you can redistribute it and/or modify
6035 +    it under the terms of the GNU General Public License as published by
6036 +    the Free Software Foundation; either version 2 of the License, or
6037 +    (at your option) any later version.
6038 +
6039 +    This program is distributed in the hope that it will be useful,
6040 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
6041 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6042 +    GNU General Public License for more details.
6043 +
6044 +    You should have received a copy of the GNU General Public License
6045 +    along with this program; if not, write to the Free Software
6046 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
6047 +*/
6048 +
6049 +/* This interfaces to the I2C bus of the Tsunami/Typhoon 21272 chipsets 
6050 +   to gain access to the on-board I2C devices. 
6051 +
6052 +   For more information refer to Compaq's 
6053 +       "Tsunami/Typhoon 21272 Chipset Hardware Reference Manual"
6054 +       Order Number: DS-0025-TE
6055 +*/ 
6056 +
6057 +#include <linux/module.h>
6058 +#include <linux/i2c.h>
6059 +#include <linux/i2c-algo-bit.h>
6060 +#include <linux/init.h>
6061 +#include <asm/io.h>
6062 +#include <asm/hwrpb.h>
6063 +#include <asm/core_tsunami.h>
6064 +#define LM_DATE "20041007"
6065 +#define LM_VERSION "2.8.8"
6066 +
6067 +MODULE_LICENSE("GPL");
6068 +
6069 +/* Memory Presence Detect Register (MPD-RW) bits 
6070 +   with except of reserved RAZ bits */
6071 +
6072 +#define MPD_DR 0x8     /* Data receive - RO */
6073 +#define MPD_CKR        0x4     /* Clock receive - RO */
6074 +#define MPD_DS 0x2     /* Data send - Must be a 1 to receive - WO */
6075 +#define MPD_CKS        0x1     /* Clock send - WO */
6076 +
6077 +static inline void writempd(unsigned long value)
6078 +{
6079 +       TSUNAMI_cchip->mpd.csr = value;
6080 +       mb();
6081 +}
6082 +
6083 +static inline unsigned long readmpd(void)
6084 +{
6085 +       return TSUNAMI_cchip->mpd.csr;
6086 +}
6087 +
6088 +static void bit_tsunami_setscl(void *data, int val)
6089 +{
6090 +       /* read currently setted bits to modify them */
6091 +       unsigned long bits = readmpd() >> 2; /* assume output == input */
6092 +
6093 +       if (val)
6094 +               bits |= MPD_CKS;
6095 +       else
6096 +               bits &= ~MPD_CKS;
6097 +
6098 +       writempd(bits);
6099 +}
6100 +
6101 +static void bit_tsunami_setsda(void *data, int val)
6102 +{
6103 +       /* read currently setted bits to modify them */
6104 +       unsigned long bits = readmpd() >> 2; /* assume output == input */
6105 +
6106 +       if (val)
6107 +               bits |= MPD_DS;
6108 +       else
6109 +               bits &= ~MPD_DS;
6110 +
6111 +       writempd(bits);
6112 +}
6113 +
6114 +/* The MPD pins are open drain, so the pins always remain outputs.
6115 +   We rely on the i2c-algo-bit routines to set the pins high before
6116 +   reading the input from other chips. */
6117 +
6118 +static int bit_tsunami_getscl(void *data)
6119 +{
6120 +       return (0 != (readmpd() & MPD_CKR));
6121 +}
6122 +
6123 +static int bit_tsunami_getsda(void *data)
6124 +{
6125 +       return (0 != (readmpd() & MPD_DR));
6126 +}
6127 +
6128 +static struct i2c_algo_bit_data tsunami_i2c_bit_data = {
6129 +       .setsda         = bit_tsunami_setsda,
6130 +       .setscl         = bit_tsunami_setscl,
6131 +       .getsda         = bit_tsunami_getsda,
6132 +       .getscl         = bit_tsunami_getscl,
6133 +       .udelay         = 10,
6134 +       .mdelay         = 10,
6135 +       .timeout        = HZ/2
6136 +};
6137 +
6138 +static struct i2c_adapter tsunami_i2c_adapter = {
6139 +       .owner          = THIS_MODULE,
6140 +       .name           = "I2C Tsunami/Typhoon adapter",
6141 +       .id             = I2C_HW_B_TSUNA,
6142 +       .algo_data      = &tsunami_i2c_bit_data,
6143 +};
6144 +
6145 +
6146 +#if 0
6147 +static struct pci_driver tsunami_driver = {
6148 +       .name           = "tsunami smbus",
6149 +       .id_table       = tsunami_ids,
6150 +       .probe          = tsunami_probe,
6151 +       .remove         = __devexit_p(tsunami_remove),
6152 +};
6153 +#endif
6154 +
6155 +static int __init i2c_tsunami_init(void)
6156 +{
6157 +       printk("i2c-tsunami.o version %s (%s)\n", LM_VERSION, LM_DATE);
6158 +
6159 +       if (hwrpb->sys_type != ST_DEC_TSUNAMI) {
6160 +               printk("i2c-tsunami.o: not Tsunami based system (%ld), module not inserted.\n", hwrpb->sys_type);
6161 +               return -ENXIO;
6162 +       } else {
6163 +               printk("i2c-tsunami.o: using Cchip MPD at 0x%lx.\n", (long) &TSUNAMI_cchip->mpd);
6164 +       }
6165 +       return i2c_bit_add_bus(&tsunami_i2c_adapter);
6166 +}
6167 +
6168 +
6169 +static void __exit i2c_tsunami_exit(void)
6170 +{
6171 +       i2c_bit_del_bus(&tsunami_i2c_adapter);
6172 +}
6173 +
6174 +
6175 +
6176 +MODULE_AUTHOR("Oleg I. Vdovikin <vdovikin@jscc.ru>");
6177 +MODULE_DESCRIPTION("Tsunami I2C/SMBus driver");
6178 +
6179 +module_init(i2c_tsunami_init);
6180 +module_exit(i2c_tsunami_exit);
6181 --- linux-old/drivers/i2c/i2c-via.c     Thu Jan  1 00:00:00 1970
6182 +++ linux/drivers/i2c/i2c-via.c Mon Dec 13 20:18:42 2004
6183 @@ -0,0 +1,207 @@
6184 +/*
6185 +    i2c-via.c - Part of lm_sensors,  Linux kernel modules
6186 +                for hardware monitoring
6187 +
6188 +    i2c Support for Via Technologies 82C586B South Bridge
6189 +
6190 +    Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
6191 +
6192 +    This program is free software; you can redistribute it and/or modify
6193 +    it under the terms of the GNU General Public License as published by
6194 +    the Free Software Foundation; either version 2 of the License, or
6195 +    (at your option) any later version.
6196 +
6197 +    This program is distributed in the hope that it will be useful,
6198 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
6199 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6200 +    GNU General Public License for more details.
6201 +
6202 +    You should have received a copy of the GNU General Public License
6203 +    along with this program; if not, write to the Free Software
6204 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
6205 +*/
6206 +
6207 +#include <linux/kernel.h>
6208 +#include <linux/ioport.h>
6209 +#include <linux/module.h>
6210 +#include <linux/pci.h>
6211 +#include <linux/types.h>
6212 +#include <linux/i2c.h>
6213 +#include <linux/i2c-algo-bit.h>
6214 +#include <linux/init.h>
6215 +#include <asm/io.h>
6216 +#include <asm/param.h> /* for HZ */
6217 +#define LM_DATE "20041007"
6218 +#define LM_VERSION "2.8.8"
6219 +
6220 +/* Power management registers */
6221 +
6222 +#define PM_CFG_REVID    0x08   /* silicon revision code */
6223 +#define PM_CFG_IOBASE0  0x20
6224 +#define PM_CFG_IOBASE1  0x48
6225 +
6226 +#define I2C_DIR                (pm_io_base+0x40)
6227 +#define I2C_OUT                (pm_io_base+0x42)
6228 +#define I2C_IN         (pm_io_base+0x44)
6229 +#define I2C_SCL                0x02    /* clock bit in DIR/OUT/IN register */
6230 +#define I2C_SDA                0x04
6231 +
6232 +/* io-region reservation */
6233 +#define IOSPACE                0x06
6234 +#define IOTEXT         "via-i2c"
6235 +
6236 +static u16 pm_io_base = 0;
6237 +
6238 +/*
6239 +   It does not appear from the datasheet that the GPIO pins are
6240 +   open drain. So a we set a low value by setting the direction to
6241 +   output and a high value by setting the direction to input and
6242 +   relying on the required I2C pullup. The data value is initialized
6243 +   to 0 in via_init() and never changed.
6244 +*/
6245 +
6246 +static void bit_via_setscl(void *data, int state)
6247 +{
6248 +       outb(state ? inb(I2C_DIR) & ~I2C_SCL : inb(I2C_DIR) | I2C_SCL,
6249 +            I2C_DIR);
6250 +}
6251 +
6252 +static void bit_via_setsda(void *data, int state)
6253 +{
6254 +       outb(state ? inb(I2C_DIR) & ~I2C_SDA : inb(I2C_DIR) | I2C_SDA,
6255 +            I2C_DIR);
6256 +}
6257 +
6258 +static int bit_via_getscl(void *data)
6259 +{
6260 +       return (0 != (inb(I2C_IN) & I2C_SCL));
6261 +}
6262 +
6263 +static int bit_via_getsda(void *data)
6264 +{
6265 +       return (0 != (inb(I2C_IN) & I2C_SDA));
6266 +}
6267 +
6268 +
6269 +static struct i2c_algo_bit_data bit_data = {
6270 +       .setsda         = bit_via_setsda,
6271 +       .setscl         = bit_via_setscl,
6272 +       .getsda         = bit_via_getsda,
6273 +       .getscl         = bit_via_getscl,
6274 +       .udelay         = 5,
6275 +       .mdelay         = 5,
6276 +       .timeout        = HZ
6277 +};
6278 +
6279 +static struct i2c_adapter vt586b_adapter = {
6280 +       .owner          = THIS_MODULE,
6281 +       .name           = "VIA i2c",
6282 +       .id             = I2C_HW_B_VIA,
6283 +       .algo_data      = &bit_data,
6284 +};
6285 +
6286 +
6287 +static struct pci_device_id vt586b_ids[] __devinitdata = {
6288 +       { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
6289 +       { 0, }
6290 +};
6291 +
6292 +static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
6293 +{
6294 +       u16 base;
6295 +       u8 rev;
6296 +       int res;
6297 +
6298 +       if (pm_io_base) {
6299 +               printk(KERN_ERR "i2c-via.o: Will only support one host\n");
6300 +               return -EBUSY;
6301 +       }
6302 +
6303 +       pci_read_config_byte(dev, PM_CFG_REVID, &rev);
6304 +
6305 +       switch (rev) {
6306 +       case 0x00:
6307 +               base = PM_CFG_IOBASE0;
6308 +               break;
6309 +       case 0x01:
6310 +       case 0x10:
6311 +               base = PM_CFG_IOBASE1;
6312 +               break;
6313 +
6314 +       default:
6315 +               base = PM_CFG_IOBASE1;
6316 +               /* later revision */
6317 +       }
6318 +
6319 +       pci_read_config_word(dev, base, &pm_io_base);
6320 +       pm_io_base &= (0xff << 8);
6321 +
6322 +       if (! request_region(I2C_DIR, IOSPACE, IOTEXT)) {
6323 +           printk("i2c-via.o: IO 0x%x-0x%x already in use\n",
6324 +                  I2C_DIR, I2C_DIR + IOSPACE);
6325 +           return -EBUSY;
6326 +       }
6327 +       outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR);
6328 +       outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT);
6329 +       
6330 +       res = i2c_bit_add_bus(&vt586b_adapter);
6331 +       if ( res < 0 ) {
6332 +               release_region(I2C_DIR, IOSPACE);
6333 +               pm_io_base = 0;
6334 +               return res;
6335 +       }
6336 +       return 0;
6337 +}
6338 +
6339 +static void __devexit vt586b_remove(struct pci_dev *dev)
6340 +{
6341 +       i2c_bit_del_bus(&vt586b_adapter);
6342 +       release_region(I2C_DIR, IOSPACE);
6343 +       pm_io_base = 0;
6344 +}
6345 +
6346 +
6347 +/* Don't register driver to avoid driver conflicts */
6348 +/*
6349 +static struct pci_driver vt586b_driver = {
6350 +       .name           = "vt586b smbus",
6351 +       .id_table       = vt586b_ids,
6352 +       .probe          = vt586b_probe,
6353 +       .remove         = __devexit_p(vt586b_remove),
6354 +};
6355 +*/
6356 +
6357 +static int __init i2c_vt586b_init(void)
6358 +{
6359 +       struct pci_dev *dev;
6360 +       const struct pci_device_id *id;
6361 +
6362 +       printk("i2c-via.o version %s (%s)\n", LM_VERSION, LM_DATE);
6363 +/*
6364 +       return pci_module_init(&vt586b_driver);
6365 +*/
6366 +       pci_for_each_dev(dev) {
6367 +               id = pci_match_device(vt586b_ids, dev);
6368 +               if(id)
6369 +                       if(vt586b_probe(dev, id) >= 0)
6370 +                               return 0;
6371 +       }
6372 +       return -ENODEV;
6373 +}
6374 +
6375 +
6376 +static void __exit i2c_vt586b_exit(void)
6377 +{
6378 +/*
6379 +       pci_unregister_driver(&vt586b_driver);
6380 +*/
6381 +       vt586b_remove(NULL);
6382 +}
6383 +
6384 +
6385 +MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
6386 +MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge");
6387 +MODULE_LICENSE("GPL");
6388 +
6389 +module_init(i2c_vt586b_init);
6390 +module_exit(i2c_vt586b_exit);
6391 --- linux-old/drivers/i2c/i2c-viapro.c  Thu Jan  1 00:00:00 1970
6392 +++ linux/drivers/i2c/i2c-viapro.c      Mon Dec 13 20:18:43 2004
6393 @@ -0,0 +1,514 @@
6394 +/*
6395 +    i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
6396 +              monitoring
6397 +    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>, 
6398 +    Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
6399 +    Mark D. Studebaker <mdsxyz123@yahoo.com>
6400 +
6401 +    This program is free software; you can redistribute it and/or modify
6402 +    it under the terms of the GNU General Public License as published by
6403 +    the Free Software Foundation; either version 2 of the License, or
6404 +    (at your option) any later version.
6405 +
6406 +    This program is distributed in the hope that it will be useful,
6407 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
6408 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6409 +    GNU General Public License for more details.
6410 +
6411 +    You should have received a copy of the GNU General Public License
6412 +    along with this program; if not, write to the Free Software
6413 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
6414 +*/
6415 +
6416 +/*
6417 +   Supports Via devices:
6418 +       82C596A/B (0x3050)
6419 +       82C596B (0x3051)
6420 +       82C686A/B
6421 +       8231
6422 +       8233
6423 +       8233A (0x3147 and 0x3177)
6424 +       8235
6425 +       8237
6426 +   Note: we assume there can only be one device, with one SMBus interface.
6427 +*/
6428 +
6429 +#include <linux/module.h>
6430 +#include <linux/pci.h>
6431 +#include <linux/kernel.h>
6432 +#include <linux/stddef.h>
6433 +#include <linux/sched.h>
6434 +#include <linux/ioport.h>
6435 +#include <linux/i2c.h>
6436 +#include <linux/init.h>
6437 +#include <asm/io.h>
6438 +#define LM_DATE "20041007"
6439 +#define LM_VERSION "2.8.8"
6440 +#include <linux/sensors_compat.h>
6441 +
6442 +#define SMBBA1          0x90
6443 +#define SMBBA2          0x80
6444 +#define SMBBA3          0xD0
6445 +
6446 +/* SMBus address offsets */
6447 +static unsigned short vt596_smba;
6448 +#define SMBHSTSTS      (vt596_smba + 0)
6449 +#define SMBHSLVSTS     (vt596_smba + 1)
6450 +#define SMBHSTCNT      (vt596_smba + 2)
6451 +#define SMBHSTCMD      (vt596_smba + 3)
6452 +#define SMBHSTADD      (vt596_smba + 4)
6453 +#define SMBHSTDAT0     (vt596_smba + 5)
6454 +#define SMBHSTDAT1     (vt596_smba + 6)
6455 +#define SMBBLKDAT      (vt596_smba + 7)
6456 +#define SMBSLVCNT      (vt596_smba + 8)
6457 +#define SMBSHDWCMD     (vt596_smba + 9)
6458 +#define SMBSLVEVT      (vt596_smba + 0xA)
6459 +#define SMBSLVDAT      (vt596_smba + 0xC)
6460 +
6461 +/* PCI Address Constants */
6462 +
6463 +/* SMBus data in configuration space can be found in two places,
6464 +   We try to select the better one*/
6465 +
6466 +static unsigned short smb_cf_hstcfg = 0xD2;
6467 +
6468 +#define SMBHSTCFG   (smb_cf_hstcfg)
6469 +#define SMBSLVC     (smb_cf_hstcfg + 1)
6470 +#define SMBSHDW1    (smb_cf_hstcfg + 2)
6471 +#define SMBSHDW2    (smb_cf_hstcfg + 3)
6472 +#define SMBREV      (smb_cf_hstcfg + 4)
6473 +
6474 +/* Other settings */
6475 +#define MAX_TIMEOUT    500
6476 +#define ENABLE_INT9    0
6477 +
6478 +/* VT82C596 constants */
6479 +#define VT596_QUICK      0x00
6480 +#define VT596_BYTE       0x04
6481 +#define VT596_BYTE_DATA  0x08
6482 +#define VT596_WORD_DATA  0x0C
6483 +#define VT596_BLOCK_DATA 0x14
6484 +
6485 +
6486 +/* If force is set to anything different from 0, we forcibly enable the
6487 +   VT596. DANGEROUS! */
6488 +static int force;
6489 +MODULE_PARM(force, "i");
6490 +MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
6491 +
6492 +/* If force_addr is set to anything different from 0, we forcibly enable
6493 +   the VT596 at the given address. VERY DANGEROUS! */
6494 +static int force_addr;
6495 +MODULE_PARM(force_addr, "i");
6496 +MODULE_PARM_DESC(force_addr,
6497 +                "Forcibly enable the SMBus at the given address. "
6498 +                "EXTREMELY DANGEROUS!");
6499 +
6500 +
6501 +static struct i2c_adapter vt596_adapter;
6502 +
6503 +/* Another internally used function */
6504 +static int vt596_transaction(void)
6505 +{
6506 +       int temp;
6507 +       int result = 0;
6508 +       int timeout = 0;
6509 +
6510 +       dev_dbg(&vt596_adapter, "Transaction (pre): CNT=%02x, CMD=%02x, "
6511 +               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), 
6512 +               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), 
6513 +               inb_p(SMBHSTDAT1));
6514 +
6515 +       /* Make sure the SMBus host is ready to start transmitting */
6516 +       if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
6517 +               dev_dbg(&vt596_adapter, "SMBus busy (0x%02x). "
6518 +                               "Resetting...\n", temp);
6519 +               
6520 +               outb_p(temp, SMBHSTSTS);
6521 +               if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
6522 +                       dev_dbg(&vt596_adapter, "Failed! (0x%02x)\n", temp);
6523 +                       
6524 +                       return -1;
6525 +               } else {
6526 +                       dev_dbg(&vt596_adapter, "Successfull!\n");
6527 +               }
6528 +       }
6529 +
6530 +       /* start the transaction by setting bit 6 */
6531 +       outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
6532 +
6533 +       /* We will always wait for a fraction of a second! 
6534 +          I don't know if VIA needs this, Intel did  */
6535 +       do {
6536 +               i2c_delay(1);
6537 +               temp = inb_p(SMBHSTSTS);
6538 +       } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
6539 +
6540 +       /* If the SMBus is still busy, we give up */
6541 +       if (timeout >= MAX_TIMEOUT) {
6542 +               result = -1;
6543 +               dev_dbg(&vt596_adapter, "SMBus Timeout!\n");
6544 +       }
6545 +
6546 +       if (temp & 0x10) {
6547 +               result = -1;
6548 +               dev_dbg(&vt596_adapter, "Error: Failed bus transaction\n");
6549 +       }
6550 +
6551 +       if (temp & 0x08) {
6552 +               result = -1;
6553 +               dev_info(&vt596_adapter, "Bus collision! SMBus may be "
6554 +                       "locked until next hard\nreset. (sorry!)\n");
6555 +               /* Clock stops and slave is stuck in mid-transmission */
6556 +       }
6557 +
6558 +       if (temp & 0x04) {
6559 +               result = -1;
6560 +               dev_dbg(&vt596_adapter, "Error: no response!\n");
6561 +       }
6562 +
6563 +       if (inb_p(SMBHSTSTS) != 0x00)
6564 +               outb_p(inb(SMBHSTSTS), SMBHSTSTS);
6565 +
6566 +       if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
6567 +               dev_dbg(&vt596_adapter, "Failed reset at end of "
6568 +                       "transaction (%02x)\n", temp);
6569 +       }
6570 +       dev_dbg(&vt596_adapter, "Transaction (post): CNT=%02x, CMD=%02x, "
6571 +               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
6572 +               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), 
6573 +               inb_p(SMBHSTDAT1));
6574 +       
6575 +       return result;
6576 +}
6577 +
6578 +/* Return -1 on error. */
6579 +static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
6580 +               unsigned short flags,  char read_write, u8 command,
6581 +               int size,  union i2c_smbus_data *data)
6582 +{
6583 +       int i, len;
6584 +
6585 +       switch (size) {
6586 +       case I2C_SMBUS_QUICK:
6587 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6588 +                      SMBHSTADD);
6589 +               size = VT596_QUICK;
6590 +               break;
6591 +       case I2C_SMBUS_BYTE:
6592 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6593 +                      SMBHSTADD);
6594 +               if (read_write == I2C_SMBUS_WRITE)
6595 +                       outb_p(command, SMBHSTCMD);
6596 +               size = VT596_BYTE;
6597 +               break;
6598 +       case I2C_SMBUS_BYTE_DATA:
6599 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6600 +                      SMBHSTADD);
6601 +               outb_p(command, SMBHSTCMD);
6602 +               if (read_write == I2C_SMBUS_WRITE)
6603 +                       outb_p(data->byte, SMBHSTDAT0);
6604 +               size = VT596_BYTE_DATA;
6605 +               break;
6606 +       case I2C_SMBUS_WORD_DATA:
6607 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6608 +                      SMBHSTADD);
6609 +               outb_p(command, SMBHSTCMD);
6610 +               if (read_write == I2C_SMBUS_WRITE) {
6611 +                       outb_p(data->word & 0xff, SMBHSTDAT0);
6612 +                       outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
6613 +               }
6614 +               size = VT596_WORD_DATA;
6615 +               break;
6616 +       case I2C_SMBUS_BLOCK_DATA:
6617 +               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6618 +                      SMBHSTADD);
6619 +               outb_p(command, SMBHSTCMD);
6620 +               if (read_write == I2C_SMBUS_WRITE) {
6621 +                       len = data->block[0];
6622 +                       if (len < 0)
6623 +                               len = 0;
6624 +                       if (len > 32)
6625 +                               len = 32;
6626 +                       outb_p(len, SMBHSTDAT0);
6627 +                       i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
6628 +                       for (i = 1; i <= len; i++)
6629 +                               outb_p(data->block[i], SMBBLKDAT);
6630 +               }
6631 +               size = VT596_BLOCK_DATA;
6632 +               break;
6633 +       default:
6634 +               dev_warn(&vt596_adapter, "Unsupported transaction %d\n", size);
6635 +               return -1;
6636 +       }
6637 +
6638 +       outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
6639 +
6640 +       if (vt596_transaction()) /* Error in transaction */
6641 +               return -1;
6642 +
6643 +       if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
6644 +               return 0;
6645 +
6646 +       switch (size) {
6647 +       case VT596_BYTE:
6648 +               /* Where is the result put? I assume here it is in
6649 +                * SMBHSTDAT0 but it might just as well be in the
6650 +                * SMBHSTCMD. No clue in the docs 
6651 +                */
6652 +               data->byte = inb_p(SMBHSTDAT0);
6653 +               break;
6654 +       case VT596_BYTE_DATA:
6655 +               data->byte = inb_p(SMBHSTDAT0);
6656 +               break;
6657 +       case VT596_WORD_DATA:
6658 +               data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
6659 +               break;
6660 +       case VT596_BLOCK_DATA:
6661 +               data->block[0] = inb_p(SMBHSTDAT0);
6662 +               if (data->block[0] > 32)
6663 +                       data->block[0] = 32;
6664 +               i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
6665 +               for (i = 1; i <= data->block[0]; i++)
6666 +                       data->block[i] = inb_p(SMBBLKDAT);
6667 +               break;
6668 +       }
6669 +       return 0;
6670 +}
6671 +
6672 +static u32 vt596_func(struct i2c_adapter *adapter)
6673 +{
6674 +       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
6675 +           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
6676 +           I2C_FUNC_SMBUS_BLOCK_DATA;
6677 +}
6678 +
6679 +static struct i2c_algorithm smbus_algorithm = {
6680 +       .name           = "Non-I2C SMBus adapter",
6681 +       .id             = I2C_ALGO_SMBUS,
6682 +       .smbus_xfer     = vt596_access,
6683 +       .functionality  = vt596_func,
6684 +};
6685 +
6686 +static struct i2c_adapter vt596_adapter = {
6687 +       .owner          = THIS_MODULE,
6688 +       .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2,
6689 +       .algo           = &smbus_algorithm,
6690 +       .name   = "unset",
6691 +};
6692 +
6693 +static int __devinit vt596_probe(struct pci_dev *pdev,
6694 +                                const struct pci_device_id *id)
6695 +{
6696 +       unsigned char temp;
6697 +       int error = -ENODEV;
6698 +       
6699 +       /* Determine the address of the SMBus areas */
6700 +       if (force_addr) {
6701 +               vt596_smba = force_addr & 0xfff0;
6702 +               force = 0;
6703 +               goto found;
6704 +       }
6705 +
6706 +       if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
6707 +           !(vt596_smba & 0x1)) {
6708 +               /* try 2nd address and config reg. for 596 */
6709 +               if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
6710 +                   !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
6711 +                   (vt596_smba & 0x1)) {
6712 +                       smb_cf_hstcfg = 0x84;
6713 +               } else {
6714 +                       /* no matches at all */
6715 +                       dev_err(pdev, "Cannot configure "
6716 +                               "SMBus I/O Base address\n");
6717 +                       return -ENODEV;
6718 +               }
6719 +       }
6720 +
6721 +       vt596_smba &= 0xfff0;
6722 +       if (vt596_smba == 0) {
6723 +               dev_err(pdev, "SMBus base address "
6724 +                       "uninitialized - upgrade BIOS or use "
6725 +                       "force_addr=0xaddr\n");
6726 +               return -ENODEV;
6727 +       }
6728 +
6729 + found:
6730 +       if (!request_region(vt596_smba, 8, "viapro-smbus")) {
6731 +               dev_err(pdev, "SMBus region 0x%x already in use!\n",
6732 +                       vt596_smba);
6733 +               return -ENODEV;
6734 +       }
6735 +
6736 +       pci_read_config_byte(pdev, SMBHSTCFG, &temp);
6737 +       /* If force_addr is set, we program the new address here. Just to make
6738 +          sure, we disable the VT596 first. */
6739 +       if (force_addr) {
6740 +               pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
6741 +               pci_write_config_word(pdev, id->driver_data, vt596_smba);
6742 +               pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
6743 +               dev_warn(pdev, "WARNING: SMBus interface set to new "
6744 +                    "address 0x%04x!\n", vt596_smba);
6745 +       } else if ((temp & 1) == 0) {
6746 +               if (force) {
6747 +                       /* NOTE: This assumes I/O space and other allocations 
6748 +                        * WERE done by the Bios!  Don't complain if your 
6749 +                        * hardware does weird things after enabling this. 
6750 +                        * :') Check for Bios updates before resorting to 
6751 +                        * this.
6752 +                        */
6753 +                       pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
6754 +                       dev_info(pdev, "Enabling SMBus device\n");
6755 +               } else {
6756 +                       dev_err(pdev, "SMBUS: Error: Host SMBus "
6757 +                               "controller not enabled! - upgrade BIOS or "
6758 +                               "use force=1\n");
6759 +                       goto release_region;
6760 +               }
6761 +       }
6762 +
6763 +       if ((temp & 0x0E) == 8)
6764 +               dev_dbg(pdev, "using Interrupt 9 for SMBus.\n");
6765 +       else if ((temp & 0x0E) == 0)
6766 +               dev_dbg(pdev, "using Interrupt SMI# for SMBus.\n");
6767 +       else
6768 +               dev_dbg(pdev, "Illegal Interrupt configuration "
6769 +                       "(or code out of date)!\n");
6770 +
6771 +       pci_read_config_byte(pdev, SMBREV, &temp);
6772 +       dev_dbg(pdev, "SMBREV = 0x%X\n", temp);
6773 +       dev_dbg(pdev, "VT596_smba = 0x%X\n", vt596_smba);
6774 +
6775 +       snprintf(vt596_adapter.name, 32,
6776 +                       "SMBus Via Pro adapter at %04x", vt596_smba);
6777 +       
6778 +       return i2c_add_adapter(&vt596_adapter);
6779 +
6780 + release_region:
6781 +       release_region(vt596_smba, 8);
6782 +       return error;
6783 +}
6784 +
6785 +static void __devexit vt596_remove(struct pci_dev *pdev)
6786 +{
6787 +       i2c_del_adapter(&vt596_adapter);
6788 +       release_region(vt596_smba, 8);
6789 +}
6790 +
6791 +/* 8233A is undefined before kernel 2.4.19 */
6792 +#ifndef PCI_DEVICE_ID_VIA_8233A
6793 +#define PCI_DEVICE_ID_VIA_8233A        0x3147
6794 +#endif
6795 +/* 8235 is undefined before kernel 2.4.20 */
6796 +#ifndef PCI_DEVICE_ID_VIA_8235
6797 +#define PCI_DEVICE_ID_VIA_8235 0x3177
6798 +#endif
6799 +/* 8237 is undefined before kernel 2.4.21 */
6800 +#ifndef PCI_DEVICE_ID_VIA_8237
6801 +#define PCI_DEVICE_ID_VIA_8237 0x3227
6802 +#endif
6803 +static struct pci_device_id vt596_ids[] __devinitdata = {
6804 +       {
6805 +               .vendor         = PCI_VENDOR_ID_VIA,
6806 +               .device         = PCI_DEVICE_ID_VIA_82C596_3,
6807 +               .subvendor      = PCI_ANY_ID,
6808 +               .subdevice      = PCI_ANY_ID,
6809 +               .driver_data    = SMBBA1,
6810 +       },
6811 +       {
6812 +               .vendor         = PCI_VENDOR_ID_VIA,
6813 +               .device         = PCI_DEVICE_ID_VIA_82C596B_3,
6814 +               .subvendor      = PCI_ANY_ID,
6815 +               .subdevice      = PCI_ANY_ID,
6816 +               .driver_data    = SMBBA1,
6817 +       },
6818 +       {
6819 +               .vendor         = PCI_VENDOR_ID_VIA,
6820 +               .device         = PCI_DEVICE_ID_VIA_82C686_4,
6821 +               .subvendor      = PCI_ANY_ID,
6822 +               .subdevice      = PCI_ANY_ID,
6823 +               .driver_data    = SMBBA1,
6824 +       },
6825 +       {
6826 +               .vendor         = PCI_VENDOR_ID_VIA,
6827 +               .device         = PCI_DEVICE_ID_VIA_8233_0,
6828 +               .subvendor      = PCI_ANY_ID,
6829 +               .subdevice      = PCI_ANY_ID,
6830 +               .driver_data    = SMBBA3
6831 +       },
6832 +       {
6833 +               .vendor         = PCI_VENDOR_ID_VIA,
6834 +               .device         = PCI_DEVICE_ID_VIA_8233A,
6835 +               .subvendor      = PCI_ANY_ID,
6836 +               .subdevice      = PCI_ANY_ID,
6837 +               .driver_data    = SMBBA3,
6838 +       },
6839 +       {
6840 +               .vendor         = PCI_VENDOR_ID_VIA,
6841 +               .device         = PCI_DEVICE_ID_VIA_8235,
6842 +               .subvendor      = PCI_ANY_ID,
6843 +               .subdevice      = PCI_ANY_ID,
6844 +               .driver_data    = SMBBA3
6845 +       },
6846 +       {
6847 +               .vendor         = PCI_VENDOR_ID_VIA,
6848 +               .device         = PCI_DEVICE_ID_VIA_8237,
6849 +               .subvendor      = PCI_ANY_ID,
6850 +               .subdevice      = PCI_ANY_ID,
6851 +               .driver_data    = SMBBA3
6852 +       },
6853 +       {
6854 +               .vendor         = PCI_VENDOR_ID_VIA,
6855 +               .device         = PCI_DEVICE_ID_VIA_8231_4,
6856 +               .subvendor      = PCI_ANY_ID,
6857 +               .subdevice      = PCI_ANY_ID,
6858 +               .driver_data    = SMBBA1,
6859 +       },
6860 +       { 0, }
6861 +};
6862 +
6863 +/* Don't register driver to avoid driver conflicts */
6864 +/*
6865 +static struct pci_driver vt596_driver = {
6866 +       .name           = "vt596 smbus",
6867 +       .id_table       = vt596_ids,
6868 +       .probe          = vt596_probe,
6869 +       .remove         = __devexit_p(vt596_remove),
6870 +};
6871 +*/
6872 +
6873 +static int __init i2c_vt596_init(void)
6874 +{
6875 +       struct pci_dev *dev;
6876 +       const struct pci_device_id *id;
6877 +
6878 +       printk("i2c-viapro.o version %s (%s)\n", LM_VERSION, LM_DATE);
6879 +/*
6880 +       return pci_module_init(&vt596_driver);
6881 +*/
6882 +       pci_for_each_dev(dev) {
6883 +               id = pci_match_device(vt596_ids, dev);
6884 +               if(id)
6885 +                       if(vt596_probe(dev, id) >= 0)
6886 +                               return 0;
6887 +       }
6888 +       return -ENODEV;
6889 +}
6890 +
6891 +
6892 +static void __exit i2c_vt596_exit(void)
6893 +{
6894 +/*
6895 +       pci_unregister_driver(&vt596_driver);
6896 +*/
6897 +       vt596_remove(NULL);
6898 +}
6899 +
6900 +MODULE_AUTHOR(
6901 +    "Frodo Looijaard <frodol@dds.nl> and "
6902 +    "Philip Edelbrock <phil@netroedge.com>");
6903 +MODULE_DESCRIPTION("vt82c596 SMBus driver");
6904 +MODULE_LICENSE("GPL");
6905 +
6906 +module_init(i2c_vt596_init);
6907 +module_exit(i2c_vt596_exit);
6908 --- linux-old/drivers/i2c/i2c-voodoo3.c Thu Jan  1 00:00:00 1970
6909 +++ linux/drivers/i2c/i2c-voodoo3.c     Mon Dec 13 20:18:43 2004
6910 @@ -0,0 +1,281 @@
6911 +/*
6912 +    voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware
6913 +              monitoring
6914 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
6915 +    Philip Edelbrock <phil@netroedge.com>,
6916 +    Ralph Metzler <rjkm@thp.uni-koeln.de>, and
6917 +    Mark D. Studebaker <mdsxyz123@yahoo.com>
6918 +    
6919 +    Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
6920 +    Simon Vogl
6921 +
6922 +    This program is free software; you can redistribute it and/or modify
6923 +    it under the terms of the GNU General Public License as published by
6924 +    the Free Software Foundation; either version 2 of the License, or
6925 +    (at your option) any later version.
6926 +
6927 +    This program is distributed in the hope that it will be useful,
6928 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
6929 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6930 +    GNU General Public License for more details.
6931 +
6932 +    You should have received a copy of the GNU General Public License
6933 +    along with this program; if not, write to the Free Software
6934 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
6935 +*/
6936 +
6937 +/* This interfaces to the I2C bus of the Voodoo3 to gain access to
6938 +    the BT869 and possibly other I2C devices. */
6939 +
6940 +#include <linux/module.h>
6941 +#include <linux/pci.h>
6942 +#include <linux/i2c.h>
6943 +#include <linux/i2c-algo-bit.h>
6944 +#include <linux/init.h>
6945 +#include <asm/io.h>
6946 +#include <asm/param.h> /* for HZ */
6947 +#define LM_DATE "20041007"
6948 +#define LM_VERSION "2.8.8"
6949 +
6950 +MODULE_LICENSE("GPL");
6951 +
6952 +/* the only registers we use */
6953 +#define REG    0x78
6954 +#define REG2   0x70
6955 +
6956 +/* bit locations in the register */
6957 +#define DDC_ENAB       0x00040000
6958 +#define DDC_SCL_OUT    0x00080000
6959 +#define DDC_SDA_OUT    0x00100000
6960 +#define DDC_SCL_IN     0x00200000
6961 +#define DDC_SDA_IN     0x00400000
6962 +#define I2C_ENAB       0x00800000
6963 +#define I2C_SCL_OUT    0x01000000
6964 +#define I2C_SDA_OUT    0x02000000
6965 +#define I2C_SCL_IN     0x04000000
6966 +#define I2C_SDA_IN     0x08000000
6967 +
6968 +/* initialization states */
6969 +#define INIT2  0x2
6970 +#define INIT3  0x4
6971 +
6972 +/* delays */
6973 +#define CYCLE_DELAY    10
6974 +#define TIMEOUT                (HZ / 2)
6975 +
6976 +
6977 +static void config_v3(struct pci_dev *dev);
6978 +
6979 +static unsigned long ioaddr;
6980 +
6981 +/* The voo GPIO registers don't have individual masks for each bit
6982 +   so we always have to read before writing. */
6983 +
6984 +static void bit_vooi2c_setscl(void *data, int val)
6985 +{
6986 +       unsigned int r;
6987 +       r = readl(ioaddr + REG);
6988 +       if(val)
6989 +               r |= I2C_SCL_OUT;
6990 +       else
6991 +               r &= ~I2C_SCL_OUT;
6992 +       writel(r, ioaddr + REG);
6993 +       readl(ioaddr + REG);    /* flush posted write */
6994 +}
6995 +
6996 +static void bit_vooi2c_setsda(void *data, int val)
6997 +{
6998 +       unsigned int r;
6999 +       r = readl(ioaddr + REG);
7000 +       if(val)
7001 +               r |= I2C_SDA_OUT;
7002 +       else
7003 +               r &= ~I2C_SDA_OUT;
7004 +       writel(r, ioaddr + REG);
7005 +       readl(ioaddr + REG);    /* flush posted write */
7006 +}
7007 +
7008 +/* The GPIO pins are open drain, so the pins always remain outputs.
7009 +   We rely on the i2c-algo-bit routines to set the pins high before
7010 +   reading the input from other chips. */
7011 +
7012 +static int bit_vooi2c_getscl(void *data)
7013 +{
7014 +       return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
7015 +}
7016 +
7017 +static int bit_vooi2c_getsda(void *data)
7018 +{
7019 +       return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
7020 +}
7021 +
7022 +static void bit_vooddc_setscl(void *data, int val)
7023 +{
7024 +       unsigned int r;
7025 +       r = readl(ioaddr + REG);
7026 +       if(val)
7027 +               r |= DDC_SCL_OUT;
7028 +       else
7029 +               r &= ~DDC_SCL_OUT;
7030 +       writel(r, ioaddr + REG);
7031 +       readl(ioaddr + REG);    /* flush posted write */
7032 +}
7033 +
7034 +static void bit_vooddc_setsda(void *data, int val)
7035 +{
7036 +       unsigned int r;
7037 +       r = readl(ioaddr + REG);
7038 +       if(val)
7039 +               r |= DDC_SDA_OUT;
7040 +       else
7041 +               r &= ~DDC_SDA_OUT;
7042 +       writel(r, ioaddr + REG);
7043 +       readl(ioaddr + REG);    /* flush posted write */
7044 +}
7045 +
7046 +static int bit_vooddc_getscl(void *data)
7047 +{
7048 +       return (0 != (readl(ioaddr + REG) & DDC_SCL_IN));
7049 +}
7050 +
7051 +static int bit_vooddc_getsda(void *data)
7052 +{
7053 +       return (0 != (readl(ioaddr + REG) & DDC_SDA_IN));
7054 +}
7055 +
7056 +
7057 +/* Configures the chip */
7058 +
7059 +void config_v3(struct pci_dev *dev)
7060 +{
7061 +       unsigned int cadr;
7062 +
7063 +       /* map Voodoo3 memory */
7064 +       cadr = dev->resource[0].start;
7065 +       cadr &= PCI_BASE_ADDRESS_MEM_MASK;
7066 +       ioaddr = (unsigned long)ioremap_nocache(cadr, 0x1000);
7067 +       if(ioaddr) {
7068 +               writel(0x8160, ioaddr + REG2);
7069 +               writel(0xcffc0020, ioaddr + REG);
7070 +               printk("i2c-voodoo3: Using Banshee/Voodoo3 at 0x%lx\n", ioaddr);
7071 +       }
7072 +}
7073 +
7074 +static struct i2c_algo_bit_data voo_i2c_bit_data = {
7075 +       .setsda         = bit_vooi2c_setsda,
7076 +       .setscl         = bit_vooi2c_setscl,
7077 +       .getsda         = bit_vooi2c_getsda,
7078 +       .getscl         = bit_vooi2c_getscl,
7079 +       .udelay         = CYCLE_DELAY,
7080 +       .mdelay         = CYCLE_DELAY,
7081 +       .timeout        = TIMEOUT
7082 +};
7083 +
7084 +static struct i2c_adapter voodoo3_i2c_adapter = {
7085 +       .owner          = THIS_MODULE,
7086 +       .name           = "I2C Voodoo3/Banshee adapter",
7087 +       .id             = I2C_HW_B_VOO,
7088 +       .algo_data              = &voo_i2c_bit_data,
7089 +};
7090 +
7091 +static struct i2c_algo_bit_data voo_ddc_bit_data = {
7092 +       .setsda         = bit_vooddc_setsda,
7093 +       .setscl         = bit_vooddc_setscl,
7094 +       .getsda         = bit_vooddc_getsda,
7095 +       .getscl         = bit_vooddc_getscl,
7096 +       .udelay         = CYCLE_DELAY,
7097 +       .mdelay         = CYCLE_DELAY,
7098 +       .timeout        = TIMEOUT
7099 +};
7100 +
7101 +static struct i2c_adapter voodoo3_ddc_adapter = {
7102 +       .owner          = THIS_MODULE,
7103 +       .name           = "DDC Voodoo3/Banshee adapter",
7104 +       .id             = I2C_HW_B_VOO,
7105 +       .algo_data      = &voo_ddc_bit_data,
7106 +};
7107 +
7108 +
7109 +static struct pci_device_id voodoo3_ids[] __devinitdata = {
7110 +       {
7111 +               .vendor =       PCI_VENDOR_ID_3DFX,
7112 +               .device =       PCI_DEVICE_ID_3DFX_VOODOO3,
7113 +               .subvendor =    PCI_ANY_ID,
7114 +               .subdevice =    PCI_ANY_ID,
7115 +       },
7116 +       {
7117 +               .vendor =       PCI_VENDOR_ID_3DFX,
7118 +               .device =       PCI_DEVICE_ID_3DFX_BANSHEE,
7119 +               .subvendor =    PCI_ANY_ID,
7120 +               .subdevice =    PCI_ANY_ID,
7121 +       },
7122 +       { 0, }
7123 +};
7124 +
7125 +static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id)
7126 +{
7127 +       int retval;
7128 +
7129 +       printk("voodoo3: in probe\n");
7130 +       config_v3(dev);
7131 +       retval = i2c_bit_add_bus(&voodoo3_i2c_adapter);
7132 +       if(retval)
7133 +               return retval;
7134 +       retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
7135 +       if(retval)
7136 +               i2c_bit_del_bus(&voodoo3_i2c_adapter);
7137 +       return retval;
7138 +}
7139 +
7140 +static void __devexit voodoo3_remove(struct pci_dev *dev)
7141 +{
7142 +       i2c_bit_del_bus(&voodoo3_i2c_adapter);
7143 +       i2c_bit_del_bus(&voodoo3_ddc_adapter);
7144 +}
7145 +
7146 +
7147 +/* Don't register driver to avoid driver conflicts */
7148 +/*
7149 +static struct pci_driver voodoo3_driver = {
7150 +       .name           = "voodoo3 smbus",
7151 +       .id_table       = voodoo3_ids,
7152 +       .probe          = voodoo3_probe,
7153 +       .remove         = __devexit_p(voodoo3_remove),
7154 +};
7155 +*/
7156 +
7157 +static int __init i2c_voodoo3_init(void)
7158 +{
7159 +       struct pci_dev *dev;
7160 +       const struct pci_device_id *id;
7161 +
7162 +       printk("i2c-voodoo3.o version %s (%s)\n", LM_VERSION, LM_DATE);
7163 +/*
7164 +       return pci_module_init(&voodoo3_driver);
7165 +*/
7166 +       pci_for_each_dev(dev) {
7167 +               id = pci_match_device(voodoo3_ids, dev);
7168 +               if(id)
7169 +                       if(voodoo3_probe(dev, id) >= 0)
7170 +                               return 0;
7171 +       }
7172 +       return -ENODEV;
7173 +}
7174 +
7175 +
7176 +static void __exit i2c_voodoo3_exit(void)
7177 +{
7178 +/*
7179 +       pci_unregister_driver(&voodoo3_driver);
7180 +*/
7181 +       voodoo3_remove(NULL);
7182 +       iounmap((void *)ioaddr);
7183 +}
7184 +
7185 +
7186 +MODULE_AUTHOR
7187 +    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Ralph Metzler <rjkm@thp.uni-koeln.de>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
7188 +MODULE_DESCRIPTION("Voodoo3 I2C/SMBus driver");
7189 +
7190 +module_init(i2c_voodoo3_init);
7191 +module_exit(i2c_voodoo3_exit);
7192 --- linux-old/drivers/sensors/adm1021.c Thu Jan  1 00:00:00 1970
7193 +++ linux/drivers/sensors/adm1021.c     Mon Dec 13 20:18:43 2004
7194 @@ -0,0 +1,594 @@
7195 +/*
7196 +    adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
7197 +             monitoring
7198 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
7199 +    Philip Edelbrock <phil@netroedge.com>
7200 +
7201 +    This program is free software; you can redistribute it and/or modify
7202 +    it under the terms of the GNU General Public License as published by
7203 +    the Free Software Foundation; either version 2 of the License, or
7204 +    (at your option) any later version.
7205 +
7206 +    This program is distributed in the hope that it will be useful,
7207 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
7208 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7209 +    GNU General Public License for more details.
7210 +
7211 +    You should have received a copy of the GNU General Public License
7212 +    along with this program; if not, write to the Free Software
7213 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
7214 +*/
7215 +
7216 +#include <linux/module.h>
7217 +#include <linux/slab.h>
7218 +#include <linux/i2c.h>
7219 +#include <linux/i2c-proc.h>
7220 +#include <linux/init.h>
7221 +#define LM_DATE "20041007"
7222 +#define LM_VERSION "2.8.8"
7223 +
7224 +/* Addresses to scan */
7225 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
7226 +static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b,
7227 +       0x4c, 0x4e, SENSORS_I2C_END
7228 +};
7229 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
7230 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
7231 +
7232 +/* Insmod parameters */
7233 +SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
7234 +
7235 +/* adm1021 constants specified below */
7236 +
7237 +/* The adm1021 registers */
7238 +/* Read-only */
7239 +#define ADM1021_REG_TEMP 0x00
7240 +#define ADM1021_REG_REMOTE_TEMP 0x01
7241 +#define ADM1021_REG_STATUS 0x02
7242 +#define ADM1021_REG_MAN_ID 0x0FE       /* 0x41 = Analog Devices, 0x49 = TI,
7243 +                                       0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
7244 +#define ADM1021_REG_DEV_ID 0x0FF       /* ADM1021 = 0x0X, ADM1021A/ADM1023 = 0x3X */
7245 +#define ADM1021_REG_DIE_CODE 0x0FF     /* MAX1617A */
7246 +/* These use different addresses for reading/writing */
7247 +#define ADM1021_REG_CONFIG_R 0x03
7248 +#define ADM1021_REG_CONFIG_W 0x09
7249 +#define ADM1021_REG_CONV_RATE_R 0x04
7250 +#define ADM1021_REG_CONV_RATE_W 0x0A
7251 +/* These are for the ADM1023's additional precision on the remote temp sensor */
7252 +#define ADM1021_REG_REM_TEMP_PREC 0x010
7253 +#define ADM1021_REG_REM_OFFSET 0x011
7254 +#define ADM1021_REG_REM_OFFSET_PREC 0x012
7255 +#define ADM1021_REG_REM_TOS_PREC 0x013
7256 +#define ADM1021_REG_REM_THYST_PREC 0x014
7257 +/* limits */
7258 +#define ADM1021_REG_TOS_R 0x05
7259 +#define ADM1021_REG_TOS_W 0x0B
7260 +#define ADM1021_REG_REMOTE_TOS_R 0x07
7261 +#define ADM1021_REG_REMOTE_TOS_W 0x0D
7262 +#define ADM1021_REG_THYST_R 0x06
7263 +#define ADM1021_REG_THYST_W 0x0C
7264 +#define ADM1021_REG_REMOTE_THYST_R 0x08
7265 +#define ADM1021_REG_REMOTE_THYST_W 0x0E
7266 +/* write-only */
7267 +#define ADM1021_REG_ONESHOT 0x0F
7268 +
7269 +#define ADM1021_ALARM_TEMP (ADM1021_ALARM_TEMP_HIGH | ADM1021_ALARM_TEMP_LOW)
7270 +#define ADM1021_ALARM_RTEMP (ADM1021_ALARM_RTEMP_HIGH | ADM1021_ALARM_RTEMP_LOW\
7271 +                             | ADM1021_ALARM_RTEMP_NA)
7272 +#define ADM1021_ALARM_ALL  (ADM1021_ALARM_TEMP | ADM1021_ALARM_RTEMP)
7273 +
7274 +/* Conversions. Rounding and limit checking is only done on the TO_REG
7275 +   variants. Note that you should be a bit careful with which arguments
7276 +   these macros are called: arguments may be evaluated more than once.
7277 +   Fixing this is just not worth it. */
7278 +/* Conversions  note: 1021 uses normal integer signed-byte format*/
7279 +#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
7280 +#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
7281 +
7282 +/* Each client has this additional data */
7283 +struct adm1021_data {
7284 +       struct i2c_client client;
7285 +       int sysctl_id;
7286 +       enum chips type;
7287 +
7288 +       struct semaphore update_lock;
7289 +       char valid;             /* !=0 if following fields are valid */
7290 +       unsigned long last_updated;     /* In jiffies */
7291 +
7292 +       u8 temp, temp_os, temp_hyst;    /* Register values */
7293 +       u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
7294 +       u8 fail;
7295 +        /* Special values for ADM1023 only */
7296 +       u8 remote_temp_prec, remote_temp_os_prec, remote_temp_hyst_prec, 
7297 +          remote_temp_offset, remote_temp_offset_prec;
7298 +};
7299 +
7300 +static int adm1021_attach_adapter(struct i2c_adapter *adapter);
7301 +static int adm1021_detect(struct i2c_adapter *adapter, int address,
7302 +                         unsigned short flags, int kind);
7303 +static void adm1021_init_client(struct i2c_client *client);
7304 +static int adm1021_detach_client(struct i2c_client *client);
7305 +static int adm1021_read_value(struct i2c_client *client, u8 reg);
7306 +static int adm1021_rd_good(u8 *val, struct i2c_client *client, u8 reg, u8 mask);
7307 +static int adm1021_write_value(struct i2c_client *client, u8 reg,
7308 +                              u16 value);
7309 +static void adm1021_temp(struct i2c_client *client, int operation,
7310 +                        int ctl_name, int *nrels_mag, long *results);
7311 +static void adm1021_remote_temp(struct i2c_client *client, int operation,
7312 +                               int ctl_name, int *nrels_mag,
7313 +                               long *results);
7314 +static void adm1021_alarms(struct i2c_client *client, int operation,
7315 +                          int ctl_name, int *nrels_mag, long *results);
7316 +static void adm1021_die_code(struct i2c_client *client, int operation,
7317 +                            int ctl_name, int *nrels_mag, long *results);
7318 +static void adm1021_update_client(struct i2c_client *client);
7319 +
7320 +/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
7321 +static int read_only = 0;
7322 +
7323 +
7324 +/* This is the driver that will be inserted */
7325 +static struct i2c_driver adm1021_driver = {
7326 +       .owner          = THIS_MODULE,
7327 +       .name           = "ADM1021, MAX1617 sensor driver",
7328 +       .id             = I2C_DRIVERID_ADM1021,
7329 +       .flags          = I2C_DF_NOTIFY,
7330 +       .attach_adapter = adm1021_attach_adapter,
7331 +       .detach_client  = adm1021_detach_client,
7332 +};
7333 +
7334 +/* -- SENSORS SYSCTL START -- */
7335 +
7336 +#define ADM1021_SYSCTL_TEMP 1200
7337 +#define ADM1021_SYSCTL_REMOTE_TEMP 1201
7338 +#define ADM1021_SYSCTL_DIE_CODE 1202
7339 +#define ADM1021_SYSCTL_ALARMS 1203
7340 +
7341 +#define ADM1021_ALARM_TEMP_HIGH 0x40
7342 +#define ADM1021_ALARM_TEMP_LOW 0x20
7343 +#define ADM1021_ALARM_RTEMP_HIGH 0x10
7344 +#define ADM1021_ALARM_RTEMP_LOW 0x08
7345 +#define ADM1021_ALARM_RTEMP_NA 0x04
7346 +
7347 +/* -- SENSORS SYSCTL END -- */
7348 +
7349 +/* These files are created for each detected adm1021. This is just a template;
7350 +   though at first sight, you might think we could use a statically
7351 +   allocated list, we need some way to get back to the parent - which
7352 +   is done through one of the 'extra' fields which are initialized
7353 +   when a new copy is allocated. */
7354 +static ctl_table adm1021_dir_table_template[] = {
7355 +       {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
7356 +        &i2c_sysctl_real, NULL, &adm1021_temp},
7357 +       {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
7358 +        &i2c_sysctl_real, NULL, &adm1021_remote_temp},
7359 +       {ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
7360 +        &i2c_sysctl_real, NULL, &adm1021_die_code},
7361 +       {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
7362 +        &i2c_sysctl_real, NULL, &adm1021_alarms},
7363 +       {0}
7364 +};
7365 +
7366 +static ctl_table adm1021_max_dir_table_template[] = {
7367 +       {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
7368 +        &i2c_sysctl_real, NULL, &adm1021_temp},
7369 +       {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
7370 +        &i2c_sysctl_real, NULL, &adm1021_remote_temp},
7371 +       {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
7372 +        &i2c_sysctl_real, NULL, &adm1021_alarms},
7373 +       {0}
7374 +};
7375 +
7376 +static int adm1021_id = 0;
7377 +
7378 +static int adm1021_attach_adapter(struct i2c_adapter *adapter)
7379 +{
7380 +       return i2c_detect(adapter, &addr_data, adm1021_detect);
7381 +}
7382 +
7383 +static int adm1021_detect(struct i2c_adapter *adapter, int address,
7384 +                         unsigned short flags, int kind)
7385 +{
7386 +       int i;
7387 +       struct i2c_client *new_client;
7388 +       struct adm1021_data *data;
7389 +       int err = 0;
7390 +       const char *type_name = "";
7391 +       const char *client_name = "";
7392 +
7393 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
7394 +          at this moment; i2c_detect really won't call us. */
7395 +#ifdef DEBUG
7396 +       if (i2c_is_isa_adapter(adapter)) {
7397 +               printk
7398 +                   ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
7399 +               return 0;
7400 +       }
7401 +#endif
7402 +
7403 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
7404 +               goto error0;
7405 +
7406 +       /* OK. For now, we presume we have a valid client. We now create the
7407 +          client structure, even though we cannot fill it completely yet.
7408 +          But it allows us to access adm1021_{read,write}_value. */
7409 +
7410 +       if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
7411 +               err = -ENOMEM;
7412 +               goto error0;
7413 +       }
7414 +
7415 +       new_client = &data->client;
7416 +       new_client->addr = address;
7417 +       new_client->data = data;
7418 +       new_client->adapter = adapter;
7419 +       new_client->driver = &adm1021_driver;
7420 +       new_client->flags = 0;
7421 +
7422 +       /* Now, we do the remaining detection. */
7423 +
7424 +       if (kind < 0) {
7425 +               if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00
7426 +                || (adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x3F) != 0x00
7427 +                || (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) & 0xF8) != 0x00) {
7428 +                       err = -ENODEV;
7429 +                       goto error1;
7430 +               }
7431 +       }
7432 +
7433 +       /* Determine the chip type. */
7434 +
7435 +       if (kind <= 0) {
7436 +               i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
7437 +               if (i == 0x41)
7438 +                 if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0xF0) == 0x30)
7439 +                       kind = adm1023;
7440 +                 else
7441 +                       kind = adm1021;
7442 +               else if (i == 0x49)
7443 +                       kind = thmc10;
7444 +               else if (i == 0x23)
7445 +                       kind = gl523sm;
7446 +               else if ((i == 0x4d) &&
7447 +                        (adm1021_read_value
7448 +                         (new_client, ADM1021_REG_DEV_ID) == 0x01))
7449 +                       kind = max1617a;
7450 +               else if (i == 0x54)
7451 +                       kind = mc1066;
7452 +               /* LM84 Mfr ID in a different place, and it has more unused bits */
7453 +               else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) == 0x00
7454 +                     && (kind == 0 /* skip extra detection */
7455 +                      || ((adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x7F) == 0x00
7456 +                       && (adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0xAB) == 0x00)))
7457 +                       kind = lm84;
7458 +               else
7459 +                       kind = max1617;
7460 +       }
7461 +
7462 +       if (kind == max1617) {
7463 +               type_name = "max1617";
7464 +               client_name = "MAX1617 chip";
7465 +       } else if (kind == max1617a) {
7466 +               type_name = "max1617a";
7467 +               client_name = "MAX1617A chip";
7468 +       } else if (kind == adm1021) {
7469 +               type_name = "adm1021";
7470 +               client_name = "ADM1021 chip";
7471 +       } else if (kind == adm1023) {
7472 +               type_name = "adm1023";
7473 +               client_name = "ADM1023 chip";
7474 +       } else if (kind == thmc10) {
7475 +               type_name = "thmc10";
7476 +               client_name = "THMC10 chip";
7477 +       } else if (kind == lm84) {
7478 +               type_name = "lm84";
7479 +               client_name = "LM84 chip";
7480 +       } else if (kind == gl523sm) {
7481 +               type_name = "gl523sm";
7482 +               client_name = "GL523SM chip";
7483 +       } else if (kind == mc1066) {
7484 +               type_name = "mc1066";
7485 +               client_name = "MC1066 chip";
7486 +       }
7487 +
7488 +       /* Fill in the remaining client fields and put it into the global list */
7489 +       strcpy(new_client->name, client_name);
7490 +       data->type = kind;
7491 +
7492 +       new_client->id = adm1021_id++;
7493 +       data->valid = 0;
7494 +       init_MUTEX(&data->update_lock);
7495 +
7496 +       /* Tell the I2C layer a new client has arrived */
7497 +       if ((err = i2c_attach_client(new_client)))
7498 +               goto error3;
7499 +
7500 +       /* Register a new directory entry with module sensors */
7501 +       if ((i = i2c_register_entry(new_client, type_name,
7502 +                                       data->type == adm1021 ? adm1021_dir_table_template :
7503 +                                       adm1021_max_dir_table_template)) < 0) {
7504 +               err = i;
7505 +               goto error4;
7506 +       }
7507 +       data->sysctl_id = i;
7508 +
7509 +       /* Initialize the ADM1021 chip */
7510 +       if (kind != lm84)
7511 +               adm1021_init_client(new_client);
7512 +       return 0;
7513 +
7514 +      error4:
7515 +       i2c_detach_client(new_client);
7516 +      error3:
7517 +      error1:
7518 +       kfree(data);
7519 +      error0:
7520 +       return err;
7521 +}
7522 +
7523 +static void adm1021_init_client(struct i2c_client *client)
7524 +{
7525 +       /* Enable ADC and disable suspend mode */
7526 +       adm1021_write_value(client, ADM1021_REG_CONFIG_W,
7527 +               adm1021_read_value(client, ADM1021_REG_CONFIG_R) & 0xBF);
7528 +       /* Set Conversion rate to 1/sec (this can be tinkered with) */
7529 +       adm1021_write_value(client, ADM1021_REG_CONV_RATE_W, 0x04);
7530 +}
7531 +
7532 +static int adm1021_detach_client(struct i2c_client *client)
7533 +{
7534 +       int err;
7535 +
7536 +       i2c_deregister_entry(((struct adm1021_data *) (client->data))->
7537 +                                sysctl_id);
7538 +
7539 +       if ((err = i2c_detach_client(client))) {
7540 +               printk
7541 +                   ("adm1021.o: Client deregistration failed, client not detached.\n");
7542 +               return err;
7543 +       }
7544 +
7545 +       kfree(client->data);
7546 +
7547 +       return 0;
7548 +}
7549 +
7550 +
7551 +/* All registers are byte-sized */
7552 +static int adm1021_read_value(struct i2c_client *client, u8 reg)
7553 +{
7554 +       return i2c_smbus_read_byte_data(client, reg);
7555 +}
7556 +
7557 +/* only update value if read succeeded; set fail bit if failed */
7558 +static int adm1021_rd_good(u8 *val, struct i2c_client *client, u8 reg, u8 mask)
7559 +{
7560 +       int i;
7561 +       struct adm1021_data *data = client->data;
7562 +
7563 +       i = i2c_smbus_read_byte_data(client, reg);
7564 +       if (i < 0) {
7565 +               data->fail |= mask;
7566 +               return i;
7567 +       }
7568 +       *val = i;
7569 +       return 0;
7570 +}
7571 +
7572 +static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
7573 +{
7574 +       if (read_only > 0)
7575 +               return 0;
7576 +
7577 +       return i2c_smbus_write_byte_data(client, reg, value);
7578 +}
7579 +
7580 +static void adm1021_update_client(struct i2c_client *client)
7581 +{
7582 +       struct adm1021_data *data = client->data;
7583 +
7584 +       down(&data->update_lock);
7585 +
7586 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
7587 +           (jiffies < data->last_updated) || !data->valid) {
7588 +
7589 +#ifdef DEBUG
7590 +               printk("Starting adm1021 update\n");
7591 +#endif
7592 +
7593 +               data->fail = 0;
7594 +               adm1021_rd_good(&(data->temp), client, ADM1021_REG_TEMP,
7595 +                               ADM1021_ALARM_TEMP);
7596 +               adm1021_rd_good(&(data->temp_os), client, ADM1021_REG_TOS_R,
7597 +                               ADM1021_ALARM_TEMP);
7598 +               adm1021_rd_good(&(data->temp_hyst), client,
7599 +                               ADM1021_REG_THYST_R, ADM1021_ALARM_TEMP);
7600 +               adm1021_rd_good(&(data->remote_temp), client,
7601 +                               ADM1021_REG_REMOTE_TEMP, ADM1021_ALARM_RTEMP);
7602 +               adm1021_rd_good(&(data->remote_temp_os), client,
7603 +                               ADM1021_REG_REMOTE_TOS_R, ADM1021_ALARM_RTEMP);
7604 +               adm1021_rd_good(&(data->remote_temp_hyst), client,
7605 +                               ADM1021_REG_REMOTE_THYST_R,
7606 +                               ADM1021_ALARM_RTEMP);
7607 +               data->alarms = ADM1021_ALARM_ALL;
7608 +               if (!adm1021_rd_good(&(data->alarms), client,
7609 +                                    ADM1021_REG_STATUS, 0))
7610 +                       data->alarms &= ADM1021_ALARM_ALL;
7611 +               if (data->type == adm1021)
7612 +                       adm1021_rd_good(&(data->die_code), client,
7613 +                                       ADM1021_REG_DIE_CODE, 0);
7614 +               if (data->type == adm1023) {
7615 +                       adm1021_rd_good(&(data->remote_temp_prec), client,
7616 +                                       ADM1021_REG_REM_TEMP_PREC,
7617 +                                       ADM1021_ALARM_TEMP);
7618 +                       adm1021_rd_good(&(data->remote_temp_os_prec), client,
7619 +                                       ADM1021_REG_REM_TOS_PREC,
7620 +                                       ADM1021_ALARM_RTEMP);
7621 +                       adm1021_rd_good(&(data->remote_temp_hyst_prec), client,
7622 +                                       ADM1021_REG_REM_THYST_PREC,
7623 +                                       ADM1021_ALARM_RTEMP);
7624 +                       adm1021_rd_good(&(data->remote_temp_offset), client,
7625 +                                       ADM1021_REG_REM_OFFSET,
7626 +                                       ADM1021_ALARM_RTEMP);
7627 +                       adm1021_rd_good(&(data->remote_temp_offset_prec),
7628 +                                       client, ADM1021_REG_REM_OFFSET_PREC,
7629 +                                       ADM1021_ALARM_RTEMP);
7630 +               }
7631 +               data->last_updated = jiffies;
7632 +               data->valid = 1;
7633 +       }
7634 +
7635 +       up(&data->update_lock);
7636 +}
7637 +
7638 +
7639 +void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
7640 +                 int *nrels_mag, long *results)
7641 +{
7642 +       struct adm1021_data *data = client->data;
7643 +       if (operation == SENSORS_PROC_REAL_INFO)
7644 +               *nrels_mag = 0;
7645 +       else if (operation == SENSORS_PROC_REAL_READ) {
7646 +               adm1021_update_client(client);
7647 +               results[0] = TEMP_FROM_REG(data->temp_os);
7648 +               results[1] = TEMP_FROM_REG(data->temp_hyst);
7649 +               results[2] = TEMP_FROM_REG(data->temp);
7650 +               *nrels_mag = 3;
7651 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
7652 +               if (*nrels_mag >= 1) {
7653 +                       data->temp_os = TEMP_TO_REG(results[0]);
7654 +                       adm1021_write_value(client, ADM1021_REG_TOS_W,
7655 +                                           data->temp_os);
7656 +               }
7657 +               if (*nrels_mag >= 2) {
7658 +                       data->temp_hyst = TEMP_TO_REG(results[1]);
7659 +                       adm1021_write_value(client, ADM1021_REG_THYST_W,
7660 +                                           data->temp_hyst);
7661 +               }
7662 +       }
7663 +}
7664 +
7665 +void adm1021_remote_temp(struct i2c_client *client, int operation,
7666 +                        int ctl_name, int *nrels_mag, long *results)
7667 +{
7668 +       struct adm1021_data *data = client->data;
7669 +       int prec = 0;
7670 +
7671 +       if (operation == SENSORS_PROC_REAL_INFO)
7672 +               if (data->type == adm1023) { *nrels_mag = 3; }
7673 +                 else { *nrels_mag = 0; }
7674 +       else if (operation == SENSORS_PROC_REAL_READ) {
7675 +               adm1021_update_client(client);
7676 +               results[0] = TEMP_FROM_REG(data->remote_temp_os);
7677 +               results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
7678 +               results[2] = TEMP_FROM_REG(data->remote_temp);
7679 +               if (data->type == adm1023) {
7680 +                 results[0]=results[0]*1000 + 
7681 +                  ((data->remote_temp_os_prec >> 5) * 125);
7682 +                 results[1]=results[1]*1000 + 
7683 +                  ((data->remote_temp_hyst_prec >> 5) * 125);
7684 +                 results[2]=(TEMP_FROM_REG(data->remote_temp_offset)*1000) + 
7685 +                   ((data->remote_temp_offset_prec >> 5) * 125);
7686 +                 results[3]=TEMP_FROM_REG(data->remote_temp)*1000 + 
7687 +                  ((data->remote_temp_prec >> 5) * 125);
7688 +                 *nrels_mag = 4;
7689 +               } else {
7690 +                 *nrels_mag = 3;
7691 +               }
7692 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
7693 +               if (*nrels_mag >= 1) {
7694 +                       if (data->type == adm1023) {
7695 +                         prec=((results[0]-((results[0]/1000)*1000))/125)<<5;
7696 +                         adm1021_write_value(client,
7697 +                                            ADM1021_REG_REM_TOS_PREC,
7698 +                                            prec);
7699 +                         results[0]=results[0]/1000;
7700 +                         data->remote_temp_os_prec=prec;
7701 +                       }
7702 +                       data->remote_temp_os = TEMP_TO_REG(results[0]);
7703 +                       adm1021_write_value(client,
7704 +                                           ADM1021_REG_REMOTE_TOS_W,
7705 +                                           data->remote_temp_os);
7706 +               }
7707 +               if (*nrels_mag >= 2) {
7708 +                       if (data->type == adm1023) {
7709 +                         prec=((results[1]-((results[1]/1000)*1000))/125)<<5;
7710 +                         adm1021_write_value(client,
7711 +                                            ADM1021_REG_REM_THYST_PREC,
7712 +                                            prec);
7713 +                         results[1]=results[1]/1000;
7714 +                         data->remote_temp_hyst_prec=prec;
7715 +                       }
7716 +                       data->remote_temp_hyst = TEMP_TO_REG(results[1]);
7717 +                       adm1021_write_value(client,
7718 +                                           ADM1021_REG_REMOTE_THYST_W,
7719 +                                           data->remote_temp_hyst);
7720 +               }
7721 +               if (*nrels_mag >= 3) {
7722 +                       if (data->type == adm1023) {
7723 +                         prec=((results[2]-((results[2]/1000)*1000))/125)<<5;
7724 +                         adm1021_write_value(client,
7725 +                                            ADM1021_REG_REM_OFFSET_PREC,
7726 +                                            prec);
7727 +                         results[2]=results[2]/1000;
7728 +                         data->remote_temp_offset_prec=prec;
7729 +                         data->remote_temp_offset=results[2];
7730 +                         adm1021_write_value(client,
7731 +                                            ADM1021_REG_REM_OFFSET,
7732 +                                            data->remote_temp_offset);
7733 +                       }
7734 +               }
7735 +       }
7736 +}
7737 +
7738 +void adm1021_die_code(struct i2c_client *client, int operation,
7739 +                     int ctl_name, int *nrels_mag, long *results)
7740 +{
7741 +       struct adm1021_data *data = client->data;
7742 +       if (operation == SENSORS_PROC_REAL_INFO)
7743 +               *nrels_mag = 0;
7744 +       else if (operation == SENSORS_PROC_REAL_READ) {
7745 +               adm1021_update_client(client);
7746 +               results[0] = data->die_code;
7747 +               *nrels_mag = 1;
7748 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
7749 +               /* Can't write to it */
7750 +       }
7751 +}
7752 +
7753 +void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
7754 +                   int *nrels_mag, long *results)
7755 +{
7756 +       struct adm1021_data *data = client->data;
7757 +       if (operation == SENSORS_PROC_REAL_INFO)
7758 +               *nrels_mag = 0;
7759 +       else if (operation == SENSORS_PROC_REAL_READ) {
7760 +               adm1021_update_client(client);
7761 +               results[0] = data->alarms | data->fail;
7762 +               *nrels_mag = 1;
7763 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
7764 +               /* Can't write to it */
7765 +       }
7766 +}
7767 +
7768 +static int __init sm_adm1021_init(void)
7769 +{
7770 +       printk(KERN_INFO "adm1021.o version %s (%s)\n", LM_VERSION, LM_DATE);
7771 +       return i2c_add_driver(&adm1021_driver);
7772 +}
7773 +
7774 +static void __exit sm_adm1021_exit(void)
7775 +{
7776 +       i2c_del_driver(&adm1021_driver);
7777 +}
7778 +
7779 +MODULE_AUTHOR
7780 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
7781 +MODULE_DESCRIPTION("adm1021 driver");
7782 +MODULE_LICENSE("GPL");
7783 +
7784 +MODULE_PARM(read_only, "i");
7785 +MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
7786 +
7787 +module_init(sm_adm1021_init)
7788 +module_exit(sm_adm1021_exit)
7789 --- linux-old/drivers/sensors/adm1024.c Thu Jan  1 00:00:00 1970
7790 +++ linux/drivers/sensors/adm1024.c     Mon Dec 13 20:18:43 2004
7791 @@ -0,0 +1,782 @@
7792 +/*
7793 +    adm1024.c - Part of lm_sensors, Linux kernel modules for hardware
7794 +             monitoring
7795 +    Add by Ken Bowley <ken@opnix.com> from the adm1025.c written by
7796 +    Gordon Wu <gwu@esoft.com> and from adm9240.c written by
7797 +    Copyright (c) 1999  Frodo Looijaard <frodol@dds.nl>
7798 +    and Philip Edelbrock <phil@netroedge.com>
7799 +
7800 +    This program is free software; you can redistribute it and/or modify
7801 +    it under the terms of the GNU General Public License as published by
7802 +    the Free Software Foundation; either version 2 of the License, or 
7803 +    (at your option) any later version.
7804 +
7805 +    This program is distributed in the hope that it will be useful,
7806 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
7807 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7808 +    GNU General Public License for more details.
7809 +
7810 +    You should have received a copy of the GNU General Public License
7811 +    along with this program; if not, write to the Free Software
7812 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
7813 +*/
7814 +
7815 +/* Supports the Analog Devices ADM1024. See doc/chips/adm1024 for details */
7816 +
7817 +#include <linux/module.h>
7818 +#include <linux/slab.h>
7819 +#include <linux/i2c.h>
7820 +#include <linux/i2c-proc.h>
7821 +#include <linux/init.h>
7822 +#define LM_DATE "20041007"
7823 +#define LM_VERSION "2.8.8"
7824 +
7825 +/* Addresses to scan */
7826 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
7827 +static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, SENSORS_I2C_END };
7828 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
7829 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
7830 +
7831 +/* Insmod parameters */
7832 +SENSORS_INSMOD_1(adm1024);
7833 +
7834 +/* Many ADM1024 constants specified below */
7835 +
7836 +#define ADM1024_REG_IN_MAX(nr) (0x2b + (nr) * 2)
7837 +#define ADM1024_REG_IN_MIN(nr) (0x2c + (nr) * 2)
7838 +#define ADM1024_REG_IN(nr) (0x20 + (nr))
7839 +
7840 +/* The ADM1024 registers */
7841 +#define ADM1024_REG_INT_TEMP_TRIP_SET 0x13
7842 +#define ADM1024_REG_EXT_TEMP_TRIP_SET 0x14
7843 +#define ADM1024_REG_TEST 0x15
7844 +#define ADM1024_REG_CHANNEL_MODE 0x16
7845 +#define ADM1024_REG_INT_TEMP_TRIP 0x17 /* read only */
7846 +#define ADM1024_REG_EXT_TEMP_TRIP 0x18 /* read only */
7847 +#define ADM1024_REG_ANALOG_OUT 0x19
7848 +#define ADM1024_REG_AIN1_LOW_LIMIT 0x1A
7849 +#define ADM1024_REG_AIN2_LOW_LIMIT 0x1B
7850 +/* These are all read-only */
7851 +#define ADM1024_REG_2_5V 0x20  /* 2.5V Measured Value/EXT Temp 2 */
7852 +#define ADM1024_REG_VCCP1 0x21
7853 +#define ADM1024_REG_3_3V 0x22  /* VCC Measured Value */
7854 +#define ADM1024_REG_5V 0x23
7855 +#define ADM1024_REG_12V 0x24
7856 +#define ADM1024_REG_VCCP2 0x25
7857 +#define ADM1024_REG_EXT_TEMP1 0x26
7858 +#define ADM1024_REG_TEMP 0x27
7859 +#define ADM1024_REG_FAN1 0x28  /* FAN1/AIN1 Value */
7860 +#define ADM1024_REG_FAN2 0x29  /* FAN2/AIN2 Value */
7861 +#define ADM1024_REG_COMPANY_ID 0x3E    /* 0x41 for ADM1024 */
7862 +#define ADM1024_REG_DIE_REV 0x3F
7863 +/* These are read/write */
7864 +#define ADM1024_REG_2_5V_HIGH 0x2B     /* 2.5V/Ext Temp2 High Limit */
7865 +#define ADM1024_REG_2_5V_LOW 0x2C      /* 2.5V/Ext Temp2 Low Limit */
7866 +#define ADM1024_REG_VCCP1_HIGH 0x2D
7867 +#define ADM1024_REG_VCCP1_LOW 0x2E
7868 +#define ADM1024_REG_3_3V_HIGH 0x2F     /* VCC High Limit */
7869 +#define ADM1024_REG_3_3V_LOW 0x30      /* VCC Low Limit */
7870 +#define ADM1024_REG_5V_HIGH 0x31
7871 +#define ADM1024_REG_5V_LOW 0x32
7872 +#define ADM1024_REG_12V_HIGH 0x33
7873 +#define ADM1024_REG_12V_LOW 0x34
7874 +#define ADM1024_REG_VCCP2_HIGH 0x35
7875 +#define ADM1024_REG_VCCP2_LOW 0x36
7876 +#define ADM1024_REG_EXT_TEMP1_HIGH 0x37
7877 +#define ADM1024_REG_EXT_TEMP1_LOW 0x38
7878 +#define ADM1024_REG_TOS 0x39
7879 +#define ADM1024_REG_THYST 0x3A
7880 +#define ADM1024_REG_FAN1_MIN 0x3B
7881 +#define ADM1024_REG_FAN2_MIN 0x3C
7882 +
7883 +#define ADM1024_REG_CONFIG 0x40
7884 +#define ADM1024_REG_INT1_STAT 0x41
7885 +#define ADM1024_REG_INT2_STAT 0x42
7886 +#define ADM1024_REG_INT1_MASK 0x43
7887 +#define ADM1024_REG_INT2_MASK 0x44
7888 +
7889 +#define ADM1024_REG_CHASSIS_CLEAR 0x46
7890 +#define ADM1024_REG_VID_FAN_DIV 0x47
7891 +#define ADM1024_REG_I2C_ADDR 0x48
7892 +#define ADM1024_REG_VID4 0x49
7893 +#define ADM1024_REG_CONFIG2 0x4A
7894 +#define ADM1024_REG_TEMP_CONFIG 0x4B
7895 +#define ADM1024_REG_EXTMODE1 0x4C      /* Interupt Status Register Mirror No. 1 */
7896 +#define ADM1024_REG_EXTMODE2 0x4D      /* Interupt Status Register Mirror No. 2 */
7897 +
7898 +/* Conversions. Rounding and limit checking is only done on the TO_REG
7899 +   variants. Note that you should be a bit careful with which arguments
7900 +   these macros are called: arguments may be evaluated more than once.
7901 +   Fixing this is just not worth it. */
7902 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT(((val) & 0xff),0,255))
7903 +#define IN_FROM_REG(val,nr) (val)
7904 +
7905 +static inline u8 FAN_TO_REG(long rpm, int div)
7906 +{
7907 +       if (rpm == 0)
7908 +               return 255;
7909 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
7910 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
7911 +                            254);
7912 +}
7913 +
7914 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
7915 +                               (val)==255?0:1350000/((div)*(val)))
7916 +
7917 +#define TEMP_FROM_REG(temp) \
7918 +   ((temp)<256?((((temp)&0x1fe) >> 1) * 10)      + ((temp) & 1) * 5:  \
7919 +               ((((temp)&0x1fe) >> 1) -255) * 10 - ((temp) & 1) * 5)  \
7920 +
7921 +#define EXT_TEMP_FROM_REG(temp) (((temp)>0x80?(temp)-0x100:(temp))*10)
7922 +   
7923 +
7924 +#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
7925 +
7926 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
7927 +                                                      ((val)+5)/10), \
7928 +                                             0,255)
7929 +
7930 +#define ALARMS_FROM_REG(val) (val)
7931 +
7932 +#define DIV_FROM_REG(val) (1 << (val))
7933 +#define DIV_TO_REG(val) ((val)==1?0:((val)==8?3:((val)==4?2:1)))
7934 +
7935 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
7936 +                           205-(val)*5)
7937 +
7938 +/* For each registered ADM1024, we need to keep some data in memory. That
7939 +   data is pointed to by adm1024_list[NR]->data. The structure itself is
7940 +   dynamically allocated, at the same time when a new adm1024 client is
7941 +   allocated. */
7942 +struct adm1024_data {
7943 +       struct i2c_client client;
7944 +       int sysctl_id;
7945 +       enum chips type;
7946 +
7947 +       struct semaphore update_lock;
7948 +       char valid;             /* !=0 if following fields are valid */
7949 +       unsigned long last_updated;     /* In jiffies */
7950 +
7951 +       u8 in[6];               /* Register value */
7952 +       u8 in_max[6];           /* Register value */
7953 +       u8 in_min[6];           /* Register value */
7954 +       u8 fan[2];              /* Register value */
7955 +       u8 fan_min[2];          /* Register value */
7956 +       u8 fan_div[2];          /* Register encoding, shifted right */
7957 +       int temp;               /* Temp, shifted right */
7958 +       u8 temp_os_max;         /* Register value */
7959 +       u8 temp_os_hyst;        /* Register value */
7960 +       int temp1;              /* Ext Temp 1 */
7961 +       u8 temp1_os_max;
7962 +       u8 temp1_os_hyst;
7963 +       int temp2;              /* Ext Temp 2 */
7964 +       u8 temp2_os_max;
7965 +       u8 temp2_os_hyst;
7966 +       u16 alarms;             /* Register encoding, combined */
7967 +       u8 analog_out;          /* Register value */
7968 +       u8 vid;                 /* Register value combined */
7969 +};
7970 +
7971 +
7972 +
7973 +static int adm1024_attach_adapter(struct i2c_adapter *adapter);
7974 +static int adm1024_detect(struct i2c_adapter *adapter, int address,
7975 +                         unsigned short flags, int kind);
7976 +static int adm1024_detach_client(struct i2c_client *client);
7977 +
7978 +static int adm1024_read_value(struct i2c_client *client, u8 register);
7979 +static int adm1024_write_value(struct i2c_client *client, u8 register,
7980 +                              u8 value);
7981 +static void adm1024_update_client(struct i2c_client *client);
7982 +static void adm1024_init_client(struct i2c_client *client);
7983 +
7984 +
7985 +static void adm1024_in(struct i2c_client *client, int operation,
7986 +                      int ctl_name, int *nrels_mag, long *results);
7987 +static void adm1024_fan(struct i2c_client *client, int operation,
7988 +                       int ctl_name, int *nrels_mag, long *results);
7989 +static void adm1024_temp(struct i2c_client *client, int operation,
7990 +                        int ctl_name, int *nrels_mag, long *results);
7991 +static void adm1024_temp1(struct i2c_client *client, int operation,
7992 +                        int ctl_name, int *nrels_mag, long *results);
7993 +static void adm1024_temp2(struct i2c_client *client, int operation,
7994 +                        int ctl_name, int *nrels_mag, long *results);
7995 +static void adm1024_alarms(struct i2c_client *client, int operation,
7996 +                          int ctl_name, int *nrels_mag, long *results);
7997 +static void adm1024_fan_div(struct i2c_client *client, int operation,
7998 +                           int ctl_name, int *nrels_mag, long *results);
7999 +static void adm1024_analog_out(struct i2c_client *client, int operation,
8000 +                              int ctl_name, int *nrels_mag,
8001 +                              long *results);
8002 +static void adm1024_vid(struct i2c_client *client, int operation,
8003 +                       int ctl_name, int *nrels_mag, long *results);
8004 +
8005 +static int adm1024_id = 0;
8006 +
8007 +static struct i2c_driver adm1024_driver = {
8008 +       .owner          = THIS_MODULE,
8009 +       .name           = "ADM1024 sensor driver",
8010 +       .id             = I2C_DRIVERID_ADM1024,
8011 +       .flags          = I2C_DF_NOTIFY,
8012 +       .attach_adapter = adm1024_attach_adapter,
8013 +       .detach_client  = adm1024_detach_client,
8014 +};
8015 +
8016 +/* The /proc/sys entries */
8017 +/* -- SENSORS SYSCTL START -- */
8018 +
8019 +#define ADM1024_SYSCTL_IN0 1000        /* Volts * 100 */
8020 +#define ADM1024_SYSCTL_IN1 1001
8021 +#define ADM1024_SYSCTL_IN2 1002
8022 +#define ADM1024_SYSCTL_IN3 1003
8023 +#define ADM1024_SYSCTL_IN4 1004
8024 +#define ADM1024_SYSCTL_IN5 1005
8025 +#define ADM1024_SYSCTL_FAN1 1101       /* Rotations/min */
8026 +#define ADM1024_SYSCTL_FAN2 1102
8027 +#define ADM1024_SYSCTL_TEMP 1250       /* Degrees Celcius * 100 */
8028 +#define ADM1024_SYSCTL_TEMP1 1290      /* Degrees Celcius */
8029 +#define ADM1024_SYSCTL_TEMP2 1295      /* Degrees Celcius */
8030 +#define ADM1024_SYSCTL_FAN_DIV 2000    /* 1, 2, 4 or 8 */
8031 +#define ADM1024_SYSCTL_ALARMS 2001     /* bitvector */
8032 +#define ADM1024_SYSCTL_ANALOG_OUT 2002
8033 +#define ADM1024_SYSCTL_VID 2003
8034 +
8035 +#define ADM1024_ALARM_IN0 0x0001
8036 +#define ADM1024_ALARM_IN1 0x0002
8037 +#define ADM1024_ALARM_IN2 0x0004
8038 +#define ADM1024_ALARM_IN3 0x0008
8039 +#define ADM1024_ALARM_IN4 0x0100
8040 +#define ADM1024_ALARM_IN5 0x0200
8041 +#define ADM1024_ALARM_FAN1 0x0040
8042 +#define ADM1024_ALARM_FAN2 0x0080
8043 +#define ADM1024_ALARM_TEMP 0x0010
8044 +#define ADM1024_ALARM_TEMP1 0x0020
8045 +#define ADM1024_ALARM_TEMP2 0x0001
8046 +#define ADM1024_ALARM_CHAS 0x1000
8047 +
8048 +/* -- SENSORS SYSCTL END -- */
8049 +
8050 +/* These files are created for each detected ADM1024. This is just a template;
8051 +   though at first sight, you might think we could use a statically
8052 +   allocated list, we need some way to get back to the parent - which
8053 +   is done through one of the 'extra' fields which are initialized 
8054 +   when a new copy is allocated. */
8055 +static ctl_table adm1024_dir_table_template[] = {
8056 +       {ADM1024_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
8057 +        &i2c_sysctl_real, NULL, &adm1024_in},
8058 +       {ADM1024_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
8059 +        &i2c_sysctl_real, NULL, &adm1024_in},
8060 +       {ADM1024_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
8061 +        &i2c_sysctl_real, NULL, &adm1024_in},
8062 +       {ADM1024_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
8063 +        &i2c_sysctl_real, NULL, &adm1024_in},
8064 +       {ADM1024_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
8065 +        &i2c_sysctl_real, NULL, &adm1024_in},
8066 +       {ADM1024_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
8067 +        &i2c_sysctl_real, NULL, &adm1024_in},
8068 +       {ADM1024_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
8069 +        &i2c_sysctl_real, NULL, &adm1024_fan},
8070 +       {ADM1024_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
8071 +        &i2c_sysctl_real, NULL, &adm1024_fan},
8072 +       {ADM1024_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
8073 +        &i2c_sysctl_real, NULL, &adm1024_temp},
8074 +       {ADM1024_SYSCTL_TEMP1, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
8075 +        &i2c_sysctl_real, NULL, &adm1024_temp1},
8076 +       {ADM1024_SYSCTL_TEMP2, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
8077 +        &i2c_sysctl_real, NULL, &adm1024_temp2},
8078 +       {ADM1024_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
8079 +        &i2c_sysctl_real, NULL, &adm1024_fan_div},
8080 +       {ADM1024_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
8081 +        &i2c_sysctl_real, NULL, &adm1024_alarms},
8082 +       {ADM1024_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL, &i2c_proc_real,
8083 +        &i2c_sysctl_real, NULL, &adm1024_analog_out},
8084 +       {ADM1024_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
8085 +        &i2c_sysctl_real, NULL, &adm1024_vid},
8086 +       {0}
8087 +};
8088 +
8089 +static int adm1024_attach_adapter(struct i2c_adapter *adapter)
8090 +{
8091 +       return i2c_detect(adapter, &addr_data, adm1024_detect);
8092 +}
8093 +
8094 +static int adm1024_detect(struct i2c_adapter *adapter, int address,
8095 +                         unsigned short flags, int kind)
8096 +{
8097 +       int i;
8098 +       struct i2c_client *new_client;
8099 +       struct adm1024_data *data;
8100 +       int err = 0;
8101 +       const char *type_name = "";
8102 +       const char *client_name = "";
8103 +
8104 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
8105 +          at this moment; i2c_detect really won't call us. */
8106 +#ifdef DEBUG
8107 +       if (i2c_is_isa_adapter(adapter)) {
8108 +               printk
8109 +                   ("adm1024.o: adm1024_detect called for an ISA bus adapter?!?\n");
8110 +               return 0;
8111 +       }
8112 +#endif
8113 +
8114 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
8115 +               goto ERROR0;
8116 +
8117 +       /* OK. For now, we presume we have a valid client. We now create the
8118 +          client structure, even though we cannot fill it completely yet.
8119 +          But it allows us to access adm1024_{read,write}_value. */
8120 +
8121 +       if (!(data = kmalloc(sizeof(struct adm1024_data), GFP_KERNEL))) {
8122 +               err = -ENOMEM;
8123 +               goto ERROR0;
8124 +       }
8125 +
8126 +       new_client = &data->client;
8127 +       new_client->addr = address;
8128 +       new_client->data = data;
8129 +       new_client->adapter = adapter;
8130 +       new_client->driver = &adm1024_driver;
8131 +       new_client->flags = 0;
8132 +
8133 +       /* Now, we do the remaining detection. */
8134 +
8135 +       if (kind < 0) {
8136 +               if((adm1024_read_value(new_client, ADM1024_REG_CONFIG) & 0x80) != 0x00)
8137 +                       goto ERROR1;
8138 +       }
8139 +
8140 +       /* Determine the chip type. */
8141 +       if (kind <= 0) {
8142 +               i = adm1024_read_value(new_client, ADM1024_REG_COMPANY_ID);
8143 +               if (i == 0x41)
8144 +                       kind = adm1024;
8145 +               else {
8146 +                       if (kind == 0)
8147 +                               printk
8148 +                                   ("adm1024.o: Ignoring 'force' parameter for unknown chip at "
8149 +                                    "adapter %d, address 0x%02x\n",
8150 +                                    i2c_adapter_id(adapter), address);
8151 +                       goto ERROR1;
8152 +               }
8153 +       }
8154 +
8155 +       if (kind == adm1024) {
8156 +               type_name = "adm1024";
8157 +               client_name = "ADM1024 chip";
8158 +       } else {
8159 +#ifdef DEBUG
8160 +               printk("adm1024.o: Internal error: unknown kind (%d)?!?",
8161 +                      kind);
8162 +#endif
8163 +               goto ERROR1;
8164 +       }
8165 +
8166 +       /* Fill in the remaining client fields and put it into the global list */
8167 +       strcpy(new_client->name, client_name);
8168 +       data->type = kind;
8169 +
8170 +       new_client->id = adm1024_id++;
8171 +       data->valid = 0;
8172 +       init_MUTEX(&data->update_lock);
8173 +
8174 +       /* Tell the I2C layer a new client has arrived */
8175 +       if ((err = i2c_attach_client(new_client)))
8176 +               goto ERROR3;
8177 +
8178 +       /* Register a new directory entry with module sensors */
8179 +       if ((i = i2c_register_entry(new_client,
8180 +                                       type_name,
8181 +                                       adm1024_dir_table_template)) < 0) {
8182 +               err = i;
8183 +               goto ERROR4;
8184 +       }
8185 +       data->sysctl_id = i;
8186 +
8187 +       /* Initialize the ADM1024 chip */
8188 +       adm1024_init_client(new_client);
8189 +       return 0;
8190 +
8191 +/* OK, this is not exactly good programming practice, usually. But it is
8192 +   very code-efficient in this case. */
8193 +
8194 +      ERROR4:
8195 +       i2c_detach_client(new_client);
8196 +      ERROR3:
8197 +      ERROR1:
8198 +       kfree(data);
8199 +      ERROR0:
8200 +       return err;
8201 +}
8202 +
8203 +static int adm1024_detach_client(struct i2c_client *client)
8204 +{
8205 +       int err;
8206 +
8207 +       i2c_deregister_entry(((struct adm1024_data *) (client->data))->
8208 +                                sysctl_id);
8209 +
8210 +       if ((err = i2c_detach_client(client))) {
8211 +               printk
8212 +                   ("adm1024.o: Client deregistration failed, client not detached.\n");
8213 +               return err;
8214 +       }
8215 +
8216 +       kfree(client->data);
8217 +
8218 +       return 0;
8219 +}
8220 +
8221 +static int adm1024_read_value(struct i2c_client *client, u8 reg)
8222 +{
8223 +       return 0xFF & i2c_smbus_read_byte_data(client, reg);
8224 +}
8225 +
8226 +static int adm1024_write_value(struct i2c_client *client, u8 reg, u8 value)
8227 +{
8228 +       return i2c_smbus_write_byte_data(client, reg, value);
8229 +}
8230 +
8231 +static void adm1024_init_client(struct i2c_client *client)
8232 +{
8233 +       /* Enable temperature channel 2 */
8234 +       adm1024_write_value(client, ADM1024_REG_CHANNEL_MODE, adm1024_read_value(client, ADM1024_REG_CHANNEL_MODE) | 0x04);
8235 +
8236 +       /* Start monitoring */
8237 +       adm1024_write_value(client, ADM1024_REG_CONFIG, 0x07);
8238 +}
8239 +
8240 +static void adm1024_update_client(struct i2c_client *client)
8241 +{
8242 +       struct adm1024_data *data = client->data;
8243 +       u8 i;
8244 +
8245 +       down(&data->update_lock);
8246 +
8247 +       if (
8248 +           (jiffies - data->last_updated >
8249 +            (data->type == adm1024 ? HZ / 2 : HZ * 2))
8250 +           || (jiffies < data->last_updated) || !data->valid) {
8251 +
8252 +#ifdef DEBUG
8253 +               printk("Starting adm1024 update\n");
8254 +#endif
8255 +               for (i = 0; i <= 5; i++) {
8256 +                       data->in[i] =
8257 +                           adm1024_read_value(client, ADM1024_REG_IN(i));
8258 +                       data->in_min[i] =
8259 +                           adm1024_read_value(client,
8260 +                                              ADM1024_REG_IN_MIN(i));
8261 +                       data->in_max[i] =
8262 +                           adm1024_read_value(client,
8263 +                                              ADM1024_REG_IN_MAX(i));
8264 +               }
8265 +               data->fan[0] =
8266 +                   adm1024_read_value(client, ADM1024_REG_FAN1);
8267 +               data->fan_min[0] =
8268 +                   adm1024_read_value(client, ADM1024_REG_FAN1_MIN);
8269 +               data->fan[1] =
8270 +                   adm1024_read_value(client, ADM1024_REG_FAN2);
8271 +               data->fan_min[1] =
8272 +                   adm1024_read_value(client, ADM1024_REG_FAN2_MIN);
8273 +               data->temp =
8274 +                   (adm1024_read_value(client, ADM1024_REG_TEMP) << 1) +
8275 +                   ((adm1024_read_value
8276 +                     (client, ADM1024_REG_TEMP_CONFIG) & 0x80) >> 7);
8277 +               data->temp_os_max =
8278 +                   adm1024_read_value(client, ADM1024_REG_TOS);
8279 +               data->temp_os_hyst =
8280 +                   adm1024_read_value(client, ADM1024_REG_THYST);
8281 +               data->temp1 =
8282 +                   adm1024_read_value(client, ADM1024_REG_EXT_TEMP1);
8283 +               data->temp1_os_max =
8284 +                   adm1024_read_value(client, ADM1024_REG_EXT_TEMP1_HIGH);
8285 +               data->temp1_os_hyst =
8286 +                   adm1024_read_value(client, ADM1024_REG_EXT_TEMP1_LOW);
8287 +               data->temp2 =
8288 +                   adm1024_read_value(client, ADM1024_REG_2_5V);
8289 +               data->temp2_os_max =
8290 +                   adm1024_read_value(client, ADM1024_REG_2_5V_HIGH);
8291 +               data->temp2_os_hyst =
8292 +                   adm1024_read_value(client, ADM1024_REG_2_5V_LOW);
8293 +
8294 +               i = adm1024_read_value(client, ADM1024_REG_VID_FAN_DIV);
8295 +               data->fan_div[0] = (i >> 4) & 0x03;
8296 +               data->fan_div[1] = (i >> 6) & 0x03;
8297 +               data->vid = i & 0x0f;
8298 +               data->vid |=
8299 +                   (adm1024_read_value(client, ADM1024_REG_VID4) & 0x01)
8300 +                   << 4;
8301 +
8302 +               data->alarms =
8303 +                   adm1024_read_value(client,
8304 +                                      ADM1024_REG_INT1_STAT) +
8305 +                   (adm1024_read_value(client, ADM1024_REG_INT2_STAT) <<
8306 +                    8);
8307 +               data->analog_out =
8308 +                   adm1024_read_value(client, ADM1024_REG_ANALOG_OUT);
8309 +               data->last_updated = jiffies;
8310 +               data->valid = 1;
8311 +       }
8312 +
8313 +       up(&data->update_lock);
8314 +}
8315 +
8316 +
8317 +/* The next few functions are the call-back functions of the /proc/sys and
8318 +   sysctl files. Which function is used is defined in the ctl_table in
8319 +   the extra1 field.
8320 +   Each function must return the magnitude (power of 10 to divide the date
8321 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
8322 +   put a maximum of *nrels elements in results reflecting the data of this
8323 +   file, and set *nrels to the number it actually put in it, if operation==
8324 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
8325 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
8326 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
8327 +   large enough (by checking the incoming value of *nrels). This is not very
8328 +   good practice, but as long as you put less than about 5 values in results,
8329 +   you can assume it is large enough. */
8330 +void adm1024_in(struct i2c_client *client, int operation, int ctl_name,
8331 +               int *nrels_mag, long *results)
8332 +{
8333 +
8334 +       int scales[6] = { 250, 225, 330, 500, 1200, 270 };
8335 +
8336 +       struct adm1024_data *data = client->data;
8337 +       int nr = ctl_name - ADM1024_SYSCTL_IN0;
8338 +
8339 +       if (operation == SENSORS_PROC_REAL_INFO)
8340 +               *nrels_mag = 2;
8341 +       else if (operation == SENSORS_PROC_REAL_READ) {
8342 +               adm1024_update_client(client);
8343 +               results[0] =
8344 +                   IN_FROM_REG(data->in_min[nr], nr) * scales[nr] / 192;
8345 +               results[1] =
8346 +                   IN_FROM_REG(data->in_max[nr], nr) * scales[nr] / 192;
8347 +               results[2] =
8348 +                   IN_FROM_REG(data->in[nr], nr) * scales[nr] / 192;
8349 +               *nrels_mag = 3;
8350 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
8351 +               if (*nrels_mag >= 1) {
8352 +                       data->in_min[nr] =
8353 +                           IN_TO_REG((results[0] * 192) / scales[nr], nr);
8354 +                       adm1024_write_value(client, ADM1024_REG_IN_MIN(nr),
8355 +                                           data->in_min[nr]);
8356 +               }
8357 +               if (*nrels_mag >= 2) {
8358 +                       data->in_max[nr] =
8359 +                           IN_TO_REG((results[1] * 192) / scales[nr], nr);
8360 +                       adm1024_write_value(client, ADM1024_REG_IN_MAX(nr),
8361 +                                           data->in_max[nr]);
8362 +               }
8363 +       }
8364 +}
8365 +
8366 +void adm1024_fan(struct i2c_client *client, int operation, int ctl_name,
8367 +                int *nrels_mag, long *results)
8368 +{
8369 +       struct adm1024_data *data = client->data;
8370 +       int nr = ctl_name - ADM1024_SYSCTL_FAN1 + 1;
8371 +
8372 +       if (operation == SENSORS_PROC_REAL_INFO)
8373 +               *nrels_mag = 0;
8374 +       else if (operation == SENSORS_PROC_REAL_READ) {
8375 +               adm1024_update_client(client);
8376 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
8377 +                                         DIV_FROM_REG(data->
8378 +                                                      fan_div[nr - 1]));
8379 +               results[1] =
8380 +                   FAN_FROM_REG(data->fan[nr - 1],
8381 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
8382 +               *nrels_mag = 2;
8383 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
8384 +               if (*nrels_mag >= 1) {
8385 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0],
8386 +                                                          DIV_FROM_REG
8387 +                                                          (data->
8388 +                                                           fan_div[nr -
8389 +                                                                   1]));
8390 +                       adm1024_write_value(client,
8391 +                                           nr ==
8392 +                                           1 ? ADM1024_REG_FAN1_MIN :
8393 +                                           ADM1024_REG_FAN2_MIN,
8394 +                                           data->fan_min[nr - 1]);
8395 +               }
8396 +       }
8397 +}
8398 +
8399 +
8400 +void adm1024_temp(struct i2c_client *client, int operation, int ctl_name,
8401 +                 int *nrels_mag, long *results)
8402 +{
8403 +       struct adm1024_data *data = client->data;
8404 +       if (operation == SENSORS_PROC_REAL_INFO)
8405 +               *nrels_mag = 1;
8406 +       else if (operation == SENSORS_PROC_REAL_READ) {
8407 +               adm1024_update_client(client);
8408 +               results[0] = TEMP_LIMIT_FROM_REG(data->temp_os_max);
8409 +               results[1] = TEMP_LIMIT_FROM_REG(data->temp_os_hyst);
8410 +               results[2] = TEMP_FROM_REG(data->temp);
8411 +               *nrels_mag = 3;
8412 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
8413 +               if (*nrels_mag >= 1) {
8414 +                       data->temp_os_max = TEMP_LIMIT_TO_REG(results[0]);
8415 +                       adm1024_write_value(client, ADM1024_REG_TOS,
8416 +                                           data->temp_os_max);
8417 +               }
8418 +               if (*nrels_mag >= 2) {
8419 +                       data->temp_os_hyst = TEMP_LIMIT_TO_REG(results[1]);
8420 +                       adm1024_write_value(client, ADM1024_REG_THYST,
8421 +                                           data->temp_os_hyst);
8422 +               }
8423 +       }
8424 +}
8425 +
8426 +void adm1024_temp1(struct i2c_client *client, int operation, int ctl_name,
8427 +                 int *nrels_mag, long *results)
8428 +{
8429 +       struct adm1024_data *data = client->data;
8430 +       if (operation == SENSORS_PROC_REAL_INFO)
8431 +               *nrels_mag = 1;
8432 +       else if (operation == SENSORS_PROC_REAL_READ) {
8433 +               adm1024_update_client(client);
8434 +               results[0] = TEMP_LIMIT_FROM_REG(data->temp1_os_max);
8435 +               results[1] = TEMP_LIMIT_FROM_REG(data->temp1_os_hyst);
8436 +               results[2] = EXT_TEMP_FROM_REG(data->temp1);
8437 +               *nrels_mag = 3;
8438 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
8439 +               if (*nrels_mag >= 1) {
8440 +                       data->temp1_os_max = TEMP_LIMIT_TO_REG(results[0]);
8441 +                       adm1024_write_value(client, ADM1024_REG_EXT_TEMP1_HIGH,
8442 +                                           data->temp1_os_max);
8443 +               }
8444 +               if (*nrels_mag >= 2) {
8445 +                       data->temp1_os_hyst = TEMP_LIMIT_TO_REG(results[1]);
8446 +                       adm1024_write_value(client, ADM1024_REG_EXT_TEMP1_LOW,
8447 +                                           data->temp1_os_hyst);
8448 +               }
8449 +       }
8450 +}
8451 +
8452 +void adm1024_temp2(struct i2c_client *client, int operation, int ctl_name,
8453 +                 int *nrels_mag, long *results)
8454 +{
8455 +       struct adm1024_data *data = client->data;
8456 +       if (operation == SENSORS_PROC_REAL_INFO)
8457 +               *nrels_mag = 1;
8458 +       else if (operation == SENSORS_PROC_REAL_READ) {
8459 +               adm1024_update_client(client);
8460 +               results[0] = TEMP_LIMIT_FROM_REG(data->temp2_os_max);
8461 +               results[1] = TEMP_LIMIT_FROM_REG(data->temp2_os_hyst);
8462 +               results[2] = EXT_TEMP_FROM_REG(data->temp2);
8463 +               *nrels_mag = 3;
8464 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
8465 +               if (*nrels_mag >= 1) {
8466 +                       data->temp2_os_max = TEMP_LIMIT_TO_REG(results[0]);
8467 +                       adm1024_write_value(client, ADM1024_REG_2_5V_HIGH,
8468 +                                           data->temp2_os_max);
8469 +               }
8470 +               if (*nrels_mag >= 2) {
8471 +                       data->temp2_os_hyst = TEMP_LIMIT_TO_REG(results[1]);
8472 +                       adm1024_write_value(client, ADM1024_REG_2_5V_LOW,
8473 +                                           data->temp2_os_hyst);
8474 +               }
8475 +       }
8476 +}
8477 +
8478 +void adm1024_alarms(struct i2c_client *client, int operation, int ctl_name,
8479 +                   int *nrels_mag, long *results)
8480 +{
8481 +       struct adm1024_data *data = client->data;
8482 +       if (operation == SENSORS_PROC_REAL_INFO)
8483 +               *nrels_mag = 0;
8484 +       else if (operation == SENSORS_PROC_REAL_READ) {
8485 +               adm1024_update_client(client);
8486 +               results[0] = ALARMS_FROM_REG(data->alarms);
8487 +               *nrels_mag = 1;
8488 +       }
8489 +}
8490 +
8491 +void adm1024_fan_div(struct i2c_client *client, int operation,
8492 +                    int ctl_name, int *nrels_mag, long *results)
8493 +{
8494 +       struct adm1024_data *data = client->data;
8495 +       int old;
8496 +
8497 +       if (operation == SENSORS_PROC_REAL_INFO)
8498 +               *nrels_mag = 0;
8499 +       else if (operation == SENSORS_PROC_REAL_READ) {
8500 +               adm1024_update_client(client);
8501 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
8502 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
8503 +               *nrels_mag = 2;
8504 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
8505 +               old = adm1024_read_value(client, ADM1024_REG_VID_FAN_DIV);
8506 +               if (*nrels_mag >= 2) {
8507 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
8508 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
8509 +               }
8510 +               if (*nrels_mag >= 1) {
8511 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
8512 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
8513 +                       adm1024_write_value(client,
8514 +                                           ADM1024_REG_VID_FAN_DIV, old);
8515 +               }
8516 +       }
8517 +}
8518 +
8519 +void adm1024_analog_out(struct i2c_client *client, int operation,
8520 +                       int ctl_name, int *nrels_mag, long *results)
8521 +{
8522 +       struct adm1024_data *data = client->data;
8523 +
8524 +       if (operation == SENSORS_PROC_REAL_INFO)
8525 +               *nrels_mag = 0;
8526 +       else if (operation == SENSORS_PROC_REAL_READ) {
8527 +               adm1024_update_client(client);
8528 +               results[0] = data->analog_out;
8529 +               *nrels_mag = 1;
8530 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
8531 +               if (*nrels_mag >= 1) {
8532 +                       data->analog_out = results[0];
8533 +                       adm1024_write_value(client, ADM1024_REG_ANALOG_OUT,
8534 +                                           data->analog_out);
8535 +               }
8536 +       }
8537 +}
8538 +
8539 +void adm1024_vid(struct i2c_client *client, int operation, int ctl_name,
8540 +                int *nrels_mag, long *results)
8541 +{
8542 +       struct adm1024_data *data = client->data;
8543 +
8544 +       if (operation == SENSORS_PROC_REAL_INFO)
8545 +               *nrels_mag = 2;
8546 +       else if (operation == SENSORS_PROC_REAL_READ) {
8547 +               adm1024_update_client(client);
8548 +               results[0] = VID_FROM_REG(data->vid);
8549 +               *nrels_mag = 1;
8550 +       }
8551 +}
8552 +
8553 +static int __init sm_adm1024_init(void)
8554 +{
8555 +       printk("adm1024.o version %s (%s)\n", LM_VERSION, LM_DATE);
8556 +       return i2c_add_driver(&adm1024_driver);
8557 +}
8558 +
8559 +static void __exit sm_adm1024_exit(void)
8560 +{
8561 +       i2c_del_driver(&adm1024_driver);
8562 +}
8563 +
8564 +
8565 +
8566 +MODULE_AUTHOR
8567 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
8568 +MODULE_DESCRIPTION("ADM1024 driver");
8569 +
8570 +MODULE_LICENSE("GPL");
8571 +
8572 +module_init(sm_adm1024_init);
8573 +module_exit(sm_adm1024_exit);
8574 --- linux-old/drivers/sensors/adm1025.c Thu Jan  1 00:00:00 1970
8575 +++ linux/drivers/sensors/adm1025.c     Mon Dec 13 20:18:43 2004
8576 @@ -0,0 +1,594 @@
8577 +/*
8578 +    adm1025.c - Part of lm_sensors, Linux kernel modules for hardware
8579 +               monitoring
8580 +    Copyright (c) 2000 Chen-Yuan Wu <gwu@esoft.com>
8581 +    Copyright (c) 2003-2004 Jean Delvare <khali@linux-fr.org>
8582 +
8583 +    Based on the adm9240 driver.
8584 +
8585 +    This program is free software; you can redistribute it and/or modify
8586 +    it under the terms of the GNU General Public License as published by
8587 +    the Free Software Foundation; either version 2 of the License, or 
8588 +    (at your option) any later version.
8589 +
8590 +    This program is distributed in the hope that it will be useful,
8591 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
8592 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8593 +    GNU General Public License for more details.
8594 +
8595 +    You should have received a copy of the GNU General Public License
8596 +    along with this program; if not, write to the Free Software
8597 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8598 +*/
8599 +
8600 +/* Supports the Analog Devices ADM1025 and the Philips NE1619.
8601 +   See doc/chips/adm1025 for details */
8602 +
8603 +#include <linux/module.h>
8604 +#include <linux/slab.h>
8605 +#include <linux/i2c.h>
8606 +#include <linux/i2c-proc.h>
8607 +#include <linux/init.h>
8608 +#define LM_DATE "20041007"
8609 +#define LM_VERSION "2.8.8"
8610 +#include <linux/sensors_vid.h>
8611 +
8612 +MODULE_LICENSE("GPL");
8613 +
8614 +/* Addresses to scan */
8615 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
8616 +static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, SENSORS_I2C_END };
8617 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
8618 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
8619 +
8620 +/* Insmod parameters */
8621 +SENSORS_INSMOD_2(adm1025, ne1619);
8622 +
8623 +/* Many ADM1025 constants specified below */
8624 +
8625 +
8626 +/* The ADM1025 registers */
8627 +
8628 +/* These are all read-only */
8629 +#define ADM1025_REG_2_5V        0x20 /* not used directly, see   */
8630 +#define ADM1025_REG_VCCP1       0x21 /* ADM1025_REG_IN(nr) below */
8631 +#define ADM1025_REG_3_3V        0x22
8632 +#define ADM1025_REG_5V          0x23
8633 +#define ADM1025_REG_12V         0x24
8634 +#define ADM1025_REG_VCC         0x25
8635 +
8636 +#define ADM1025_REG_RTEMP       0x26 /* not used directly, see     */
8637 +#define ADM1025_REG_LTEMP       0x27 /* ADM1025_REG_TEMP(nr) below */
8638 +
8639 +#define ADM1025_REG_COMPANY_ID  0x3E /* 0x41 for Analog Devices,
8640 +                                        0xA1 for Philips */
8641 +#define ADM1025_REG_DIE_REV     0x3F /* 0x20-0x2F for ADM1025 and compatible */
8642 +
8643 +#define ADM1025_REG_STATUS1     0x41
8644 +#define ADM1025_REG_STATUS2     0x42
8645 +
8646 +#define ADM1025_REG_VID         0x47
8647 +#define ADM1025_REG_VID4        0x49 /* actually R/W
8648 +                                        but we don't write to it */
8649 +
8650 +/* These are read/write */
8651 +#define ADM1025_REG_2_5V_HIGH   0x2B /* not used directly, see       */
8652 +#define ADM1025_REG_2_5V_LOW    0x2C /* ADM1025_REG_IN_MAX(nr) and   */
8653 +#define ADM1025_REG_VCCP1_HIGH  0x2D /* ADM1025_REG_IN_MIN(nr) below */
8654 +#define ADM1025_REG_VCCP1_LOW   0x2E
8655 +#define ADM1025_REG_3_3V_HIGH   0x2F
8656 +#define ADM1025_REG_3_3V_LOW    0x30
8657 +#define ADM1025_REG_5V_HIGH     0x31
8658 +#define ADM1025_REG_5V_LOW      0x32
8659 +#define ADM1025_REG_12V_HIGH    0x33
8660 +#define ADM1025_REG_12V_LOW     0x34
8661 +#define ADM1025_REG_VCC_HIGH    0x35
8662 +#define ADM1025_REG_VCC_LOW     0x36
8663 +
8664 +#define ADM1025_REG_RTEMP_HIGH  0x37 /* not used directly, see         */
8665 +#define ADM1025_REG_RTEMP_LOW   0x38 /* ADM1025_REG_TEMP_MAX(nr) and   */
8666 +#define ADM1025_REG_LTEMP_HIGH  0x39 /* ADM1025_REG_TEMP_MIN(nr) below */
8667 +#define ADM1025_REG_LTEMP_LOW   0x3A
8668 +
8669 +#define ADM1025_REG_CONFIG      0x40
8670 +
8671 +/* Useful macros */
8672 +#define ADM1025_REG_IN(nr)        (ADM1025_REG_2_5V + (nr))
8673 +#define ADM1025_REG_IN_MAX(nr)    (ADM1025_REG_2_5V_HIGH + (nr) * 2)
8674 +#define ADM1025_REG_IN_MIN(nr)    (ADM1025_REG_2_5V_LOW + (nr) * 2)
8675 +#define ADM1025_REG_TEMP(nr)      (ADM1025_REG_RTEMP + (nr))
8676 +#define ADM1025_REG_TEMP_HIGH(nr) (ADM1025_REG_RTEMP_HIGH + (nr) * 2)
8677 +#define ADM1025_REG_TEMP_LOW(nr)  (ADM1025_REG_RTEMP_LOW + (nr) * 2)
8678 +
8679 +/* Conversions. Rounding and limit checking is only done on the TO_REG
8680 +   variants. Note that you should be a bit careful with which arguments
8681 +   these macros are called: arguments may be evaluated more than once.
8682 +   Fixing this is just not worth it. */
8683 +#define IN_TO_REG(val) SENSORS_LIMIT(val, 0, 255)
8684 +#define IN_FROM_REG(val) (val)
8685 +
8686 +#define TEMP_FROM_REG(val) (((val)>=0x80?(val)-0x100:(val))*10)
8687 +#define TEMP_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
8688 +                                                 ((val)+5)/10),-128,127)
8689 +
8690 +#define ALARMS_FROM_REG(val) (val)
8691 +
8692 +/* For each registered ADM1025, we need to keep some data in memory. That
8693 +   data is pointed to by adm1025_list[NR]->data. The structure itself is
8694 +   dynamically allocated, at the same time when a new adm1025 client is
8695 +   allocated. */
8696 +struct adm1025_data {
8697 +       struct i2c_client client;
8698 +       int sysctl_id;
8699 +       enum chips type;
8700 +
8701 +       struct semaphore update_lock;
8702 +       char valid;                   /* !=0 if following fields are valid */
8703 +       unsigned long last_updated;   /* In jiffies */
8704 +
8705 +       u8 in[6];               /* Register value */
8706 +       u8 in_max[6];           /* Register value */
8707 +       u8 in_min[6];           /* Register value */
8708 +       u8 temp[2];             /* Register value */
8709 +       u8 temp_high[2];        /* Register value */
8710 +       u8 temp_low[2];         /* Register value */
8711 +       u16 alarms;             /* Register encoding, combined */
8712 +       u8 vid;                 /* Register value combined */
8713 +       u8 vrm;
8714 +};
8715 +
8716 +
8717 +static int adm1025_attach_adapter(struct i2c_adapter *adapter);
8718 +static int adm1025_detect(struct i2c_adapter *adapter, int address,
8719 +                         unsigned short flags, int kind);
8720 +static int adm1025_detach_client(struct i2c_client *client);
8721 +static void adm1025_update_client(struct i2c_client *client);
8722 +static void adm1025_init_client(struct i2c_client *client);
8723 +
8724 +
8725 +static void adm1025_in(struct i2c_client *client, int operation,
8726 +                      int ctl_name, int *nrels_mag, long *results);
8727 +static void adm1025_temp(struct i2c_client *client, int operation,
8728 +                        int ctl_name, int *nrels_mag, long *results);
8729 +static void adm1025_alarms(struct i2c_client *client, int operation,
8730 +                          int ctl_name, int *nrels_mag, long *results);
8731 +static void adm1025_vid(struct i2c_client *client, int operation,
8732 +                       int ctl_name, int *nrels_mag, long *results);
8733 +static void adm1025_vrm(struct i2c_client *client, int operation,
8734 +                       int ctl_name, int *nrels_mag, long *results);
8735 +
8736 +static int adm1025_id = 0;
8737 +
8738 +static struct i2c_driver adm1025_driver = {
8739 +       .owner          = THIS_MODULE,
8740 +       .name           = "ADM1025 sensor driver",
8741 +       .id             = I2C_DRIVERID_ADM1025,
8742 +       .flags          = I2C_DF_NOTIFY,
8743 +       .attach_adapter = adm1025_attach_adapter,
8744 +       .detach_client  = adm1025_detach_client,
8745 +};
8746 +
8747 +/* The /proc/sys entries */
8748 +/* -- SENSORS SYSCTL START -- */
8749 +
8750 +#define ADM1025_SYSCTL_IN0     1000 /* Volts * 100 */
8751 +#define ADM1025_SYSCTL_IN1     1001
8752 +#define ADM1025_SYSCTL_IN2     1002
8753 +#define ADM1025_SYSCTL_IN3     1003
8754 +#define ADM1025_SYSCTL_IN4     1004
8755 +#define ADM1025_SYSCTL_IN5     1005
8756 +
8757 +#define ADM1025_SYSCTL_RTEMP   1250 /* Degrees Celcius * 10 */
8758 +#define ADM1025_SYSCTL_TEMP    1251
8759 +
8760 +#define ADM1025_SYSCTL_ALARMS  2001 /* bitvector */
8761 +#define ADM1025_SYSCTL_VID     2003 /* Volts * 1000 */
8762 +#define ADM1025_SYSCTL_VRM     2004
8763 +
8764 +#define ADM1025_ALARM_IN0     0x0001
8765 +#define ADM1025_ALARM_IN1     0x0002
8766 +#define ADM1025_ALARM_IN2     0x0004
8767 +#define ADM1025_ALARM_IN3     0x0008
8768 +#define ADM1025_ALARM_IN4     0x0100
8769 +#define ADM1025_ALARM_IN5     0x0200
8770 +#define ADM1025_ALARM_RTEMP   0x0020
8771 +#define ADM1025_ALARM_TEMP    0x0010
8772 +#define ADM1025_ALARM_RFAULT  0x4000
8773 +
8774 +/* -- SENSORS SYSCTL END -- */
8775 +
8776 +/* These files are created for each detected ADM1025. This is just a template;
8777 +   though at first sight, you might think we could use a statically
8778 +   allocated list, we need some way to get back to the parent - which
8779 +   is done through one of the 'extra' fields which are initialized 
8780 +   when a new copy is allocated. */
8781 +static ctl_table adm1025_dir_table_template[] = {
8782 +       {ADM1025_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
8783 +        &i2c_sysctl_real, NULL, &adm1025_in},
8784 +       {ADM1025_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
8785 +        &i2c_sysctl_real, NULL, &adm1025_in},
8786 +       {ADM1025_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
8787 +        &i2c_sysctl_real, NULL, &adm1025_in},
8788 +       {ADM1025_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
8789 +        &i2c_sysctl_real, NULL, &adm1025_in},
8790 +       {ADM1025_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
8791 +        &i2c_sysctl_real, NULL, &adm1025_in},
8792 +       {ADM1025_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
8793 +        &i2c_sysctl_real, NULL, &adm1025_in},
8794 +       {ADM1025_SYSCTL_RTEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
8795 +        &i2c_sysctl_real, NULL, &adm1025_temp},
8796 +       {ADM1025_SYSCTL_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
8797 +        &i2c_sysctl_real, NULL, &adm1025_temp},
8798 +       {ADM1025_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
8799 +        &i2c_sysctl_real, NULL, &adm1025_alarms},
8800 +       {ADM1025_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
8801 +        &i2c_sysctl_real, NULL, &adm1025_vid},
8802 +       {ADM1025_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
8803 +        &i2c_sysctl_real, NULL, &adm1025_vrm},
8804 +       {0}
8805 +};
8806 +
8807 +static int adm1025_attach_adapter(struct i2c_adapter *adapter)
8808 +{
8809 +       return i2c_detect(adapter, &addr_data, adm1025_detect);
8810 +}
8811 +
8812 +static int adm1025_detect(struct i2c_adapter *adapter, int address,
8813 +                         unsigned short flags, int kind)
8814 +{
8815 +       int i;
8816 +       struct i2c_client *new_client;
8817 +       struct adm1025_data *data;
8818 +       int err = 0;
8819 +       const char *type_name = "";
8820 +       const char *client_name = "";
8821 +
8822 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
8823 +          at this moment; i2c_detect really won't call us. */
8824 +#ifdef DEBUG
8825 +       if (i2c_is_isa_adapter(adapter)) {
8826 +               printk
8827 +                   ("adm1025.o: adm1025_detect called for an ISA bus adapter?!?\n");
8828 +               return 0;
8829 +       }
8830 +#endif
8831 +
8832 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
8833 +               goto ERROR0;
8834 +
8835 +       /* OK. For now, we presume we have a valid client. We now create the
8836 +          client structure, even though we cannot fill it completely yet.
8837 +          But it allows us to access adm1025_{read,write}_value. */
8838 +
8839 +       if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
8840 +               err = -ENOMEM;
8841 +               goto ERROR0;
8842 +       }
8843 +
8844 +       new_client = &data->client;
8845 +       new_client->addr = address;
8846 +       new_client->data = data;
8847 +       new_client->adapter = adapter;
8848 +       new_client->driver = &adm1025_driver;
8849 +       new_client->flags = 0;
8850 +
8851 +       /* Now, we do the remaining detection. */
8852 +
8853 +       if (kind < 0) {
8854 +               if ((i2c_smbus_read_byte_data(new_client,
8855 +                    ADM1025_REG_CONFIG) & 0x80) != 0x00
8856 +                || (i2c_smbus_read_byte_data(new_client,
8857 +                    ADM1025_REG_STATUS1) & 0xC0) != 0x00
8858 +                || (i2c_smbus_read_byte_data(new_client,
8859 +                    ADM1025_REG_STATUS2) & 0xBC) != 0x00)
8860 +                       goto ERROR1;
8861 +       }
8862 +
8863 +       /* Determine the chip type. */
8864 +       if (kind <= 0) {
8865 +               u8 man_id, chip_id;
8866 +               
8867 +               man_id = i2c_smbus_read_byte_data(new_client,
8868 +                        ADM1025_REG_COMPANY_ID);
8869 +               chip_id = i2c_smbus_read_byte_data(new_client,
8870 +                         ADM1025_REG_DIE_REV);
8871 +               
8872 +               if (man_id == 0x41) { /* Analog Devices */
8873 +                       if ((chip_id & 0xF0) == 0x20) /* ADM1025 */
8874 +                               kind = adm1025;
8875 +               } else if (man_id == 0xA1) { /* Philips */
8876 +                       if (address != 0x2E
8877 +                        && (chip_id & 0xF0) == 0x20) /* NE1619 */
8878 +                               kind = ne1619;
8879 +               }
8880 +       }
8881 +
8882 +       if (kind <= 0) { /* Identification failed */
8883 +               printk("adm1025.o: Unsupported chip.\n");
8884 +               goto ERROR1;
8885 +       }
8886 +
8887 +       if (kind == adm1025) {
8888 +               type_name = "adm1025";
8889 +               client_name = "ADM1025 chip";
8890 +       } else if (kind == ne1619) {
8891 +               type_name = "ne1619";
8892 +               client_name = "NE1619 chip";            
8893 +       } else {
8894 +#ifdef DEBUG
8895 +               printk("adm1025.o: Internal error: unknown kind (%d)?!?",
8896 +                      kind);
8897 +#endif
8898 +               goto ERROR1;
8899 +       }
8900 +
8901 +       /* Fill in the remaining client fields and put it into the global list */
8902 +       strcpy(new_client->name, client_name);
8903 +       data->type = kind;
8904 +
8905 +       new_client->id = adm1025_id++;
8906 +       data->valid = 0;
8907 +       init_MUTEX(&data->update_lock);
8908 +
8909 +       /* Tell the I2C layer a new client has arrived */
8910 +       if ((err = i2c_attach_client(new_client)))
8911 +               goto ERROR3;
8912 +
8913 +       /* Register a new directory entry with module sensors */
8914 +       if ((i = i2c_register_entry(new_client,
8915 +                                       type_name,
8916 +                                       adm1025_dir_table_template)) < 0) {
8917 +               err = i;
8918 +               goto ERROR4;
8919 +       }
8920 +       data->sysctl_id = i;
8921 +
8922 +       /* Initialize the ADM1025 chip */
8923 +       adm1025_init_client(new_client);
8924 +       return 0;
8925 +
8926 +/* OK, this is not exactly good programming practice, usually. But it is
8927 +   very code-efficient in this case. */
8928 +
8929 +      ERROR4:
8930 +       i2c_detach_client(new_client);
8931 +      ERROR3:
8932 +      ERROR1:
8933 +       kfree(data);
8934 +      ERROR0:
8935 +       return err;
8936 +}
8937 +
8938 +static int adm1025_detach_client(struct i2c_client *client)
8939 +{
8940 +       int err;
8941 +
8942 +       i2c_deregister_entry(((struct adm1025_data *) (client->data))->
8943 +                                sysctl_id);
8944 +
8945 +       if ((err = i2c_detach_client(client))) {
8946 +               printk
8947 +                   ("adm1025.o: Client deregistration failed, client not detached.\n");
8948 +               return err;
8949 +       }
8950 +
8951 +       kfree(client->data);
8952 +
8953 +       return 0;
8954 +}
8955 +
8956 +/* Called when we have found a new ADM1025. */
8957 +static void adm1025_init_client(struct i2c_client *client)
8958 +{
8959 +       struct adm1025_data *data = client->data;
8960 +       u8 reg;
8961 +       int i;
8962 +
8963 +       data->vrm = 82;
8964 +
8965 +       /* Set high limits
8966 +          Usually we avoid setting limits on driver init, but it happens
8967 +          that the ADM1025 comes with stupid default limits (all registers
8968 +          set to 0). In case the chip has not gone through any limit
8969 +          setting yet, we better set the high limits to the max so that
8970 +          no alarm triggers. */
8971 +       for (i=0; i<6; i++) {
8972 +               reg = i2c_smbus_read_byte_data(client,
8973 +                                              ADM1025_REG_IN_MAX(i));
8974 +               if (reg == 0)
8975 +                       i2c_smbus_write_byte_data(client,
8976 +                                                 ADM1025_REG_IN_MAX(i),
8977 +                                                 0xFF);
8978 +       }
8979 +       for (i=0; i<2; i++) {
8980 +               reg = i2c_smbus_read_byte_data(client,
8981 +                                              ADM1025_REG_TEMP_HIGH(i));
8982 +               if (reg == 0)
8983 +                       i2c_smbus_write_byte_data(client,
8984 +                                                 ADM1025_REG_TEMP_HIGH(i),
8985 +                                                 0x7F);
8986 +       }
8987 +
8988 +       /* Start monitoring */
8989 +       reg = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
8990 +       i2c_smbus_write_byte_data(client, ADM1025_REG_CONFIG, (reg|0x01)&0x7F);
8991 +}
8992 +
8993 +static void adm1025_update_client(struct i2c_client *client)
8994 +{
8995 +       struct adm1025_data *data = client->data;
8996 +       u8 nr;
8997 +
8998 +       down(&data->update_lock);
8999 +
9000 +       if ((jiffies - data->last_updated > 2 * HZ)
9001 +        || (jiffies < data->last_updated) || !data->valid) {
9002 +#ifdef DEBUG
9003 +               printk("Starting adm1025 update\n");
9004 +#endif
9005 +
9006 +               /* Voltages */
9007 +               for (nr = 0; nr < 6; nr++) {
9008 +                       data->in[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN(nr));
9009 +                       data->in_min[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MIN(nr));
9010 +                       data->in_max[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MAX(nr));
9011 +               }
9012 +
9013 +               /* Temperatures */
9014 +               for (nr = 0; nr < 2; nr++) {
9015 +                       data->temp[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP(nr));
9016 +                       data->temp_high[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_HIGH(nr));
9017 +                       data->temp_low[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_LOW(nr));
9018 +               }
9019 +
9020 +               /* VID */
9021 +               data->vid = (i2c_smbus_read_byte_data(client, ADM1025_REG_VID) & 0x0f)
9022 +                        + ((i2c_smbus_read_byte_data(client, ADM1025_REG_VID4) & 0x01) << 4);
9023 +
9024 +               /* Alarms */
9025 +               data->alarms = (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) & 0x3f)
9026 +                           + ((i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) & 0x43) << 8);
9027 +
9028 +               data->last_updated = jiffies;
9029 +               data->valid = 1;
9030 +       }
9031 +
9032 +       up(&data->update_lock);
9033 +}
9034 +
9035 +
9036 +/* The next few functions are the call-back functions of the /proc/sys and
9037 +   sysctl files. Which function is used is defined in the ctl_table in
9038 +   the extra1 field.
9039 +   Each function must return the magnitude (power of 10 to divide the data
9040 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
9041 +   put a maximum of *nrels elements in results reflecting the data of this
9042 +   file, and set *nrels to the number it actually put in it, if operation==
9043 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
9044 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
9045 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
9046 +   large enough (by checking the incoming value of *nrels). This is not very
9047 +   good practice, but as long as you put less than about 5 values in results,
9048 +   you can assume it is large enough. */
9049 +void adm1025_in(struct i2c_client *client, int operation, int ctl_name,
9050 +               int *nrels_mag, long *results)
9051 +{
9052 +       int scales[6] = { 250, 225, 330, 500, 1200, 330 };
9053 +
9054 +       struct adm1025_data *data = client->data;
9055 +       int nr = ctl_name - ADM1025_SYSCTL_IN0;
9056 +
9057 +       if (operation == SENSORS_PROC_REAL_INFO)
9058 +               *nrels_mag = 2;
9059 +       else if (operation == SENSORS_PROC_REAL_READ) {
9060 +               adm1025_update_client(client);
9061 +               results[0] = (IN_FROM_REG(data->in_min[nr]) * scales[nr] + 96) / 192;
9062 +               results[1] = (IN_FROM_REG(data->in_max[nr]) * scales[nr] + 96) / 192;
9063 +               results[2] = (IN_FROM_REG(data->in[nr]) * scales[nr] + 96) / 192;
9064 +               *nrels_mag = 3;
9065 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
9066 +               if (*nrels_mag >= 1) {
9067 +                       data->in_min[nr] = IN_TO_REG((results[0] * 192 + scales[nr] / 2)
9068 +                                          / scales[nr]);
9069 +                       i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(nr),
9070 +                                           data->in_min[nr]);
9071 +               }
9072 +               if (*nrels_mag >= 2) {
9073 +                       data->in_max[nr] = IN_TO_REG((results[1] * 192 + scales[nr] / 2)
9074 +                                          / scales[nr]);
9075 +                       i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(nr),
9076 +                                           data->in_max[nr]);
9077 +               }
9078 +       }
9079 +}
9080 +
9081 +void adm1025_temp(struct i2c_client *client, int operation, int ctl_name,
9082 +                 int *nrels_mag, long *results)
9083 +{
9084 +       struct adm1025_data *data = client->data;
9085 +       int nr = ctl_name - ADM1025_SYSCTL_RTEMP;
9086 +
9087 +       if (operation == SENSORS_PROC_REAL_INFO)
9088 +               *nrels_mag = 1;
9089 +       else if (operation == SENSORS_PROC_REAL_READ) {
9090 +               adm1025_update_client(client);
9091 +               results[0] = TEMP_FROM_REG(data->temp_high[nr]);
9092 +               results[1] = TEMP_FROM_REG(data->temp_low[nr]);
9093 +               results[2] = TEMP_FROM_REG(data->temp[nr]);
9094 +               *nrels_mag = 3;
9095 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
9096 +               if (*nrels_mag >= 1) {
9097 +                       data->temp_high[nr] = TEMP_TO_REG(results[0]);
9098 +                       i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(nr),
9099 +                                           data->temp_high[nr]);
9100 +               }
9101 +               if (*nrels_mag >= 2) {
9102 +                       data->temp_low[nr] = TEMP_TO_REG(results[1]);
9103 +                       i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(nr),
9104 +                                           data->temp_low[nr]);
9105 +               }
9106 +       }
9107 +}
9108 +
9109 +void adm1025_alarms(struct i2c_client *client, int operation, int ctl_name,
9110 +                   int *nrels_mag, long *results)
9111 +{
9112 +       struct adm1025_data *data = client->data;
9113 +
9114 +       if (operation == SENSORS_PROC_REAL_INFO)
9115 +               *nrels_mag = 0;
9116 +       else if (operation == SENSORS_PROC_REAL_READ) {
9117 +               adm1025_update_client(client);
9118 +               results[0] = ALARMS_FROM_REG(data->alarms);
9119 +               *nrels_mag = 1;
9120 +       }
9121 +}
9122 +
9123 +void adm1025_vid(struct i2c_client *client, int operation, int ctl_name,
9124 +                int *nrels_mag, long *results)
9125 +{
9126 +       struct adm1025_data *data = client->data;
9127 +
9128 +       if (operation == SENSORS_PROC_REAL_INFO)
9129 +               *nrels_mag = 3;
9130 +       else if (operation == SENSORS_PROC_REAL_READ) {
9131 +               adm1025_update_client(client);
9132 +               results[0] = vid_from_reg(data->vid, data->vrm);
9133 +               *nrels_mag = 1;
9134 +       }
9135 +}
9136 +
9137 +void adm1025_vrm(struct i2c_client *client, int operation, int ctl_name,
9138 +                int *nrels_mag, long *results)
9139 +{
9140 +       struct adm1025_data *data = client->data;
9141 +       if (operation == SENSORS_PROC_REAL_INFO)
9142 +               *nrels_mag = 1;
9143 +       else if (operation == SENSORS_PROC_REAL_READ) {
9144 +               results[0] = data->vrm;
9145 +               *nrels_mag = 1;
9146 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
9147 +               if (*nrels_mag >= 1)
9148 +                       data->vrm = results[0];
9149 +       }
9150 +}
9151 +
9152 +static int __init sm_adm1025_init(void)
9153 +{
9154 +       printk("adm1025.o version %s (%s)\n", LM_VERSION, LM_DATE);
9155 +       return i2c_add_driver(&adm1025_driver);
9156 +}
9157 +
9158 +static void __exit sm_adm1025_exit(void)
9159 +{
9160 +       i2c_del_driver(&adm1025_driver);
9161 +}
9162 +
9163 +
9164 +
9165 +MODULE_AUTHOR("Chen-Yuan Wu <gwu@esoft.com>"
9166 +       " and Jean Delvare <khali@linux-fr.org>");
9167 +MODULE_DESCRIPTION("ADM1025 driver");
9168 +
9169 +module_init(sm_adm1025_init);
9170 +module_exit(sm_adm1025_exit);
9171 --- linux-old/drivers/sensors/adm1026.c Thu Jan  1 00:00:00 1970
9172 +++ linux/drivers/sensors/adm1026.c     Mon Dec 13 20:18:44 2004
9173 @@ -0,0 +1,1745 @@
9174 +/*
9175 +    adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
9176 +             monitoring
9177 +    Copyright (c) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
9178 +
9179 +    This program is free software; you can redistribute it and/or modify
9180 +    it under the terms of the GNU General Public License as published by
9181 +    the Free Software Foundation; either version 2 of the License, or
9182 +    (at your option) any later version.
9183 +
9184 +    This program is distributed in the hope that it will be useful,
9185 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
9186 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9187 +    GNU General Public License for more details.
9188 +
9189 +    You should have received a copy of the GNU General Public License
9190 +    along with this program; if not, write to the Free Software
9191 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
9192 +
9193 +    CHANGELOG
9194 +
9195 +    2003-03-13   Initial development
9196 +    2003-05-07   First Release.  Includes GPIO fixup and full
9197 +                 functionality.
9198 +    2003-05-18   Minor fixups and tweaks.
9199 +                 Print GPIO config after fixup.
9200 +                 Adjust fan MIN if DIV changes.
9201 +    2003-05-21   Fix printing of FAN/GPIO config
9202 +                 Fix silly bug in fan_div logic
9203 +                 Fix fan_min handling so that 0xff is 0 is 0xff
9204 +    2003-05-25   Fix more silly typos...
9205 +    2003-06-11   Change FAN_xx_REG macros to use different scaling
9206 +                 Most (all?) drivers assume two pulses per rev fans
9207 +                 and the old scaling was producing double the RPM's
9208 +                 Thanks to Jerome Hsiao @ Arima for pointing this out.
9209 +       2004-01-27   Remove use of temporary ID.
9210 +                 Define addresses as a range.
9211 +*/
9212 +
9213 +#include <linux/version.h>
9214 +#include <linux/module.h>
9215 +#include <linux/slab.h>
9216 +#include <linux/i2c.h>
9217 +#include <linux/i2c-proc.h>
9218 +#include <linux/init.h>
9219 +#define LM_DATE "20041007"
9220 +#define LM_VERSION "2.8.8"
9221 +#include <linux/sensors_vid.h>
9222 +
9223 +#ifndef I2C_DRIVERID_ADM1026
9224 +#define I2C_DRIVERID_ADM1026   1048
9225 +#endif
9226 +
9227 +/* Addresses to scan */
9228 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
9229 +static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, SENSORS_I2C_END };
9230 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
9231 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
9232 +
9233 +/* Insmod parameters */
9234 +SENSORS_INSMOD_1(adm1026);
9235 +
9236 +static int gpio_input[17]  = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
9237 +                               -1, -1, -1, -1, -1, -1, -1, -1 };
9238 +static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
9239 +                               -1, -1, -1, -1, -1, -1, -1, -1 };
9240 +static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
9241 +                               -1, -1, -1, -1, -1, -1, -1, -1 };
9242 +static int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
9243 +                               -1, -1, -1, -1, -1, -1, -1, -1 };
9244 +static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
9245 +MODULE_PARM(gpio_input,"1-17i");
9246 +MODULE_PARM_DESC(gpio_input,"List of GPIO pins (0-16) to program as inputs");
9247 +MODULE_PARM(gpio_output,"1-17i");
9248 +MODULE_PARM_DESC(gpio_output,"List of GPIO pins (0-16) to program as outputs");
9249 +MODULE_PARM(gpio_inverted,"1-17i");
9250 +MODULE_PARM_DESC(gpio_inverted,"List of GPIO pins (0-16) to program as inverted");
9251 +MODULE_PARM(gpio_normal,"1-17i");
9252 +MODULE_PARM_DESC(gpio_normal,"List of GPIO pins (0-16) to program as normal/non-inverted");
9253 +MODULE_PARM(gpio_fan,"1-8i");
9254 +MODULE_PARM_DESC(gpio_fan,"List of GPIO pins (0-7) to program as fan tachs");
9255 +
9256 +/* Many ADM1026 constants specified below */
9257 +
9258 +/* The ADM1026 registers */
9259 +#define ADM1026_REG_CONFIG1  (0x00)
9260 +#define CFG1_MONITOR     (0x01)
9261 +#define CFG1_INT_ENABLE  (0x02)
9262 +#define CFG1_INT_CLEAR   (0x04)
9263 +#define CFG1_AIN8_9      (0x08)
9264 +#define CFG1_THERM_HOT   (0x10)
9265 +#define CFG1_DAC_AFC     (0x20)
9266 +#define CFG1_PWM_AFC     (0x40)
9267 +#define CFG1_RESET       (0x80)
9268 +#define ADM1026_REG_CONFIG2  (0x01)
9269 +/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
9270 +#define ADM1026_REG_CONFIG3  (0x07)
9271 +#define CFG3_GPIO16_ENABLE  (0x01)
9272 +#define CFG3_CI_CLEAR  (0x02)
9273 +#define CFG3_VREF_250  (0x04)
9274 +#define CFG3_GPIO16_DIR  (0x40)
9275 +#define CFG3_GPIO16_POL  (0x80)
9276 +#define ADM1026_REG_E2CONFIG  (0x13)
9277 +#define E2CFG_READ  (0x01)
9278 +#define E2CFG_WRITE  (0x02)
9279 +#define E2CFG_ERASE  (0x04)
9280 +#define E2CFG_ROM  (0x08)
9281 +#define E2CFG_CLK_EXT  (0x80)
9282 +
9283 +/* There are 10 general analog inputs and 7 dedicated inputs
9284 + * They are:
9285 + *    0 - 9  =  AIN0 - AIN9
9286 + *       10  =  Vbat
9287 + *       11  =  3.3V Standby
9288 + *       12  =  3.3V Main
9289 + *       13  =  +5V
9290 + *       14  =  Vccp (CPU core voltage)
9291 + *       15  =  +12V
9292 + *       16  =  -12V
9293 + */
9294 +static u16 REG_IN[] = {
9295 +               0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
9296 +               0x36, 0x37, 0x27, 0x29, 0x26, 0x2a,
9297 +               0x2b, 0x2c, 0x2d, 0x2e, 0x2f
9298 +       };
9299 +static u16 REG_IN_MIN[] = {
9300 +               0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
9301 +               0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a,
9302 +               0x4b, 0x4c, 0x4d, 0x4e, 0x4f
9303 +       };
9304 +static u16 REG_IN_MAX[] = {
9305 +               0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
9306 +               0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42,
9307 +               0x43, 0x44, 0x45, 0x46, 0x47
9308 +       };
9309 +#define ADM1026_REG_IN(nr) (REG_IN[(nr)])
9310 +#define ADM1026_REG_IN_MIN(nr) (REG_IN_MIN[(nr)])
9311 +#define ADM1026_REG_IN_MAX(nr) (REG_IN_MAX[(nr)])
9312 +
9313 +/* Temperatures are:
9314 + *    0 - Internal
9315 + *    1 - External 1
9316 + *    2 - External 2
9317 + */
9318 +static u16 REG_TEMP[] = { 0x1f, 0x28, 0x29 };
9319 +static u16 REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 };
9320 +static u16 REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 };
9321 +static u16 REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 };
9322 +static u16 REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
9323 +static u16 REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
9324 +#define ADM1026_REG_TEMP(nr) (REG_TEMP[(nr)])
9325 +#define ADM1026_REG_TEMP_MIN(nr) (REG_TEMP_MIN[(nr)])
9326 +#define ADM1026_REG_TEMP_MAX(nr) (REG_TEMP_MAX[(nr)])
9327 +#define ADM1026_REG_TEMP_TMIN(nr) (REG_TEMP_TMIN[(nr)])
9328 +#define ADM1026_REG_TEMP_THERM(nr) (REG_TEMP_THERM[(nr)])
9329 +#define ADM1026_REG_TEMP_OFFSET(nr) (REG_TEMP_OFFSET[(nr)])
9330 +
9331 +#define ADM1026_REG_FAN(nr) (0x38 + (nr))
9332 +#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr))
9333 +#define ADM1026_REG_FAN_DIV_0_3 (0x02)
9334 +#define ADM1026_REG_FAN_DIV_4_7 (0x03)
9335 +
9336 +#define ADM1026_REG_DAC  (0x04)
9337 +#define ADM1026_REG_PWM  (0x05)
9338 +
9339 +#define ADM1026_REG_GPIO_CFG_0_3 (0x08)
9340 +#define ADM1026_REG_GPIO_CFG_4_7 (0x09)
9341 +#define ADM1026_REG_GPIO_CFG_8_11 (0x0a)
9342 +#define ADM1026_REG_GPIO_CFG_12_15 (0x0b)
9343 +/* CFG_16 in REG_CFG3 */
9344 +#define ADM1026_REG_GPIO_STATUS_0_7 (0x24)
9345 +#define ADM1026_REG_GPIO_STATUS_8_15 (0x25)
9346 +/* STATUS_16 in REG_STATUS4 */
9347 +#define ADM1026_REG_GPIO_MASK_0_7 (0x1c)
9348 +#define ADM1026_REG_GPIO_MASK_8_15 (0x1d)
9349 +/* MASK_16 in REG_MASK4 */
9350 +
9351 +#define ADM1026_REG_COMPANY 0x16
9352 +#define ADM1026_REG_VERSTEP 0x17
9353 +/* These are the recognized values for the above regs */
9354 +#define ADM1026_COMPANY_ANALOG_DEV 0x41
9355 +#define ADM1026_VERSTEP_GENERIC 0x40
9356 +#define ADM1026_VERSTEP_ADM1026 0x44
9357 +
9358 +#define ADM1026_REG_MASK1 0x18
9359 +#define ADM1026_REG_MASK2 0x19
9360 +#define ADM1026_REG_MASK3 0x1a
9361 +#define ADM1026_REG_MASK4 0x1b
9362 +
9363 +#define ADM1026_REG_STATUS1 0x20
9364 +#define ADM1026_REG_STATUS2 0x21
9365 +#define ADM1026_REG_STATUS3 0x22
9366 +#define ADM1026_REG_STATUS4 0x23
9367 +
9368 +/* Conversions. Rounding and limit checking is only done on the TO_REG 
9369 +   variants. Note that you should be a bit careful with which arguments
9370 +   these macros are called: arguments may be evaluated more than once.
9371 + */
9372 +
9373 +/* IN are scaled acording to built-in resistors.  These are the
9374 + *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
9375 + *   NOTE: The -12V input needs an additional factor to account
9376 + *      for the Vref pullup resistor.
9377 + *      NEG12_OFFSET = SCALE * Vref / V-192 - Vref
9378 + *                   = 13875 * 2.50 / 1.875 - 2500
9379 + *                   = 16000
9380 + */
9381 +#if 1
9382 +/* The values in this table are based on Table II, page 15 of the
9383 + *    datasheet.
9384 + */
9385 +static int adm1026_scaling[] = {  /* .001 Volts */
9386 +               2250, 2250, 2250, 2250, 2250, 2250, 
9387 +               1875, 1875, 1875, 1875, 3000, 3330, 
9388 +               3330, 4995, 2250, 12000, 13875
9389 +       };
9390 +#define NEG12_OFFSET  16000
9391 +#else
9392 +/* The values in this table are based on the resistors in 
9393 + *    Figure 5 on page 16.  But the 3.3V inputs are not in
9394 + *    the figure and the values for the 5V input are wrong.
9395 + *    For 5V, I'm guessing that R2 at 55.2k is right, but
9396 + *    the total resistance should be 1400 or 1449 like the
9397 + *    other inputs.  Using 1449, gives 4.922V at 192.
9398 + */
9399 +static int adm1026_scaling[] = {  /* .001 Volts */
9400 +               2249, 2249, 2249, 2249, 2249, 2249, 
9401 +               1875, 1875, 1875, 1875, 3329, 3329, 
9402 +               3329, 4922, 2249, 11969, 13889
9403 +       };
9404 +#define NEG12_OFFSET  16019
9405 +#endif
9406 +
9407 +#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
9408 +#define INS_TO_REG(n,val)  (SENSORS_LIMIT(SCALE(val,adm1026_scaling[n],192),0,255))
9409 +#if 0   /* If we have extended A/D bits */
9410 +#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,adm1026_scaling[n]))
9411 +#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
9412 +#else
9413 +#define INS_FROM_REG(n,val) (SCALE(val,192,adm1026_scaling[n]))
9414 +#endif
9415 +
9416 +/* FAN speed is measured using 22.5kHz clock and counts for 2 pulses
9417 + *   and we assume a 2 pulse-per-rev fan tach signal
9418 + *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
9419 + */
9420 +#define FAN_TO_REG(val,div)  ((val)<=0 ? 0xff : SENSORS_LIMIT(1350000/((val)*(div)),1,254))
9421 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==0xff ? 0 : 1350000/((val)*(div)))
9422 +#define DIV_FROM_REG(val) (1<<(val))
9423 +#define DIV_TO_REG(val) ((val)>=8 ? 3 : (val)>=4 ? 2 : (val)>=2 ? 1 : 0)
9424 +
9425 +/* Temperature is reported in 1 degC increments */
9426 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(val,-127,127))
9427 +#define TEMP_FROM_REG(val) (val)
9428 +#define OFFSET_TO_REG(val) (SENSORS_LIMIT(val,-127,127))
9429 +#define OFFSET_FROM_REG(val) (val)
9430 +
9431 +#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
9432 +#define PWM_FROM_REG(val) (val)
9433 +
9434 +/* Analog output is a voltage, but it's used like a PWM
9435 + *   Seems like this should be scaled, but to be consistent
9436 + *   with other drivers, we do it this way.
9437 + */
9438 +#define DAC_TO_REG(val) (SENSORS_LIMIT(val,0,255))
9439 +#define DAC_FROM_REG(val) (val)
9440 +
9441 +/* sensors_vid.h defines vid_from_reg() */
9442 +#define VID_FROM_REG(val,vrm) (vid_from_reg(val,vrm))
9443 +
9444 +#define ALARMS_FROM_REG(val) (val)
9445 +
9446 +/* Unlike some other drivers we DO NOT set initial limits.  Use
9447 + * the config file to set limits.
9448 + */
9449 +
9450 +/* Typically used with systems using a v9.1 VRM spec ? */
9451 +#define ADM1026_INIT_VRM  91
9452 +#define ADM1026_INIT_VID  -1
9453 +
9454 +/* Chip sampling rates
9455 + *
9456 + * Some sensors are not updated more frequently than once per second
9457 + *    so it doesn't make sense to read them more often than that.
9458 + *    We cache the results and return the saved data if the driver
9459 + *    is called again before a second has elapsed.
9460 + *
9461 + * Also, there is significant configuration data for this chip
9462 + *    So, we keep the config data up to date in the cache
9463 + *    when it is written and only sample it once every 5 *minutes*
9464 + */
9465 +#define ADM1026_DATA_INTERVAL  (1 * HZ)
9466 +#define ADM1026_CONFIG_INTERVAL  (5 * 60 * HZ)
9467 +
9468 +/* We allow for multiple chips in a single system.
9469 + *
9470 + * For each registered ADM1026, we need to keep state information
9471 + * at client->data. The adm1026_data structure is dynamically
9472 + * allocated, when a new client structure is allocated. */
9473 +
9474 +struct adm1026_data {
9475 +       struct i2c_client client;
9476 +       struct semaphore lock;
9477 +       int sysctl_id;
9478 +       enum chips type;
9479 +
9480 +       struct semaphore update_lock;
9481 +       int valid;              /* !=0 if following fields are valid */
9482 +       unsigned long last_reading;     /* In jiffies */
9483 +       unsigned long last_config;      /* In jiffies */
9484 +
9485 +       u8 in[17];              /* Register value */
9486 +       u8 in_max[17];          /* Register value */
9487 +       u8 in_min[17];          /* Register value */
9488 +       s8 temp[3];             /* Register value */
9489 +       s8 temp_min[3];         /* Register value */
9490 +       s8 temp_max[3];         /* Register value */
9491 +       s8 temp_tmin[3];        /* Register value */
9492 +       s8 temp_therm[3];       /* Register value */
9493 +       s8 temp_offset[3];      /* Register value */
9494 +       u8 fan[8];              /* Register value */
9495 +       u8 fan_min[8];          /* Register value */
9496 +       u8 fan_div[8];          /* Decoded value */
9497 +       u8 pwm;                 /* Register value */
9498 +       u8 analog_out;          /* Register value */
9499 +       int vid;                /* Decoded value */
9500 +       u8 vrm;                 /* VRM version */
9501 +       long alarms;            /* Register encoding, combined */
9502 +       long alarm_mask;        /* Register encoding, combined */
9503 +       long gpio;              /* Register encoding, combined */
9504 +       long gpio_mask;         /* Register encoding, combined */
9505 +       u8 gpio_config[17];     /* Decoded value */
9506 +       u8 config1;             /* Register value */
9507 +       u8 config2;             /* Register value */
9508 +       u8 config3;             /* Register value */
9509 +};
9510 +
9511 +static int adm1026_attach_adapter(struct i2c_adapter *adapter);
9512 +static int adm1026_detect(struct i2c_adapter *adapter, int address,
9513 +                       unsigned short flags, int kind);
9514 +static int adm1026_detach_client(struct i2c_client *client);
9515 +
9516 +static int adm1026_read_value(struct i2c_client *client, u8 register);
9517 +static int adm1026_write_value(struct i2c_client *client, u8 register, int value);
9518 +static void adm1026_print_gpio(struct i2c_client *client);
9519 +static void adm1026_fixup_gpio(struct i2c_client *client);
9520 +static void adm1026_update_client(struct i2c_client *client);
9521 +static void adm1026_init_client(struct i2c_client *client);
9522 +
9523 +
9524 +static void adm1026_in(struct i2c_client *client, int operation, int ctl_name,
9525 +                       int *nrels_mag, long *results);
9526 +static void adm1026_in16(struct i2c_client *client, int operation, int ctl_name,
9527 +                       int *nrels_mag, long *results);
9528 +static void adm1026_fan(struct i2c_client *client, int operation,
9529 +                       int ctl_name, int *nrels_mag, long *results);
9530 +static void adm1026_fixup_fan_min(struct i2c_client *client,
9531 +                        int fan, int old_div);
9532 +static void adm1026_fan_div(struct i2c_client *client, int operation,
9533 +                       int ctl_name, int *nrels_mag, long *results);
9534 +static void adm1026_temp(struct i2c_client *client, int operation,
9535 +                       int ctl_name, int *nrels_mag, long *results);
9536 +static void adm1026_temp_offset(struct i2c_client *client, int operation,
9537 +                       int ctl_name, int *nrels_mag, long *results);
9538 +static void adm1026_temp_tmin(struct i2c_client *client, int operation,
9539 +                       int ctl_name, int *nrels_mag, long *results);
9540 +static void adm1026_temp_therm(struct i2c_client *client, int operation,
9541 +                       int ctl_name, int *nrels_mag, long *results);
9542 +static void adm1026_vid(struct i2c_client *client, int operation,
9543 +                       int ctl_name, int *nrels_mag, long *results);
9544 +static void adm1026_vrm(struct i2c_client *client, int operation,
9545 +                       int ctl_name, int *nrels_mag, long *results);
9546 +static void adm1026_alarms(struct i2c_client *client, int operation,
9547 +                       int ctl_name, int *nrels_mag, long *results);
9548 +static void adm1026_alarm_mask(struct i2c_client *client, int operation,
9549 +                       int ctl_name, int *nrels_mag, long *results);
9550 +static void adm1026_gpio(struct i2c_client *client, int operation,
9551 +                       int ctl_name, int *nrels_mag, long *results);
9552 +static void adm1026_gpio_mask(struct i2c_client *client, int operation,
9553 +                       int ctl_name, int *nrels_mag, long *results);
9554 +static void adm1026_pwm(struct i2c_client *client, int operation,
9555 +                       int ctl_name, int *nrels_mag, long *results);
9556 +static void adm1026_analog_out(struct i2c_client *client, int operation,
9557 +                       int ctl_name, int *nrels_mag, long *results);
9558 +static void adm1026_afc(struct i2c_client *client, int operation,
9559 +                       int ctl_name, int *nrels_mag, long *results);
9560 +
9561 +static struct i2c_driver adm1026_driver = {
9562 +       .owner          = THIS_MODULE,
9563 +       .name           = "ADM1026 compatible sensor driver",
9564 +       .id             = I2C_DRIVERID_ADM1026,
9565 +       .flags          = I2C_DF_NOTIFY,
9566 +       .attach_adapter = &adm1026_attach_adapter,
9567 +       .detach_client  = &adm1026_detach_client,
9568 +};
9569 +
9570 +/* Unique ID assigned to each ADM1026 detected */
9571 +static int adm1026_id = 0;
9572 +
9573 +/* -- SENSORS SYSCTL START -- */
9574 +#define ADM1026_SYSCTL_FAN0                 1000
9575 +#define ADM1026_SYSCTL_FAN1                 1001
9576 +#define ADM1026_SYSCTL_FAN2                 1002
9577 +#define ADM1026_SYSCTL_FAN3                 1003
9578 +#define ADM1026_SYSCTL_FAN4                 1004
9579 +#define ADM1026_SYSCTL_FAN5                 1005
9580 +#define ADM1026_SYSCTL_FAN6                 1006
9581 +#define ADM1026_SYSCTL_FAN7                 1007
9582 +#define ADM1026_SYSCTL_FAN_DIV              1008
9583 +#define ADM1026_SYSCTL_GPIO                 1009
9584 +#define ADM1026_SYSCTL_GPIO_MASK            1010
9585 +#define ADM1026_SYSCTL_ALARMS               1011
9586 +#define ADM1026_SYSCTL_ALARM_MASK           1012
9587 +#define ADM1026_SYSCTL_IN0                  1013
9588 +#define ADM1026_SYSCTL_IN1                  1014
9589 +#define ADM1026_SYSCTL_IN2                  1015
9590 +#define ADM1026_SYSCTL_IN3                  1016
9591 +#define ADM1026_SYSCTL_IN4                  1017
9592 +#define ADM1026_SYSCTL_IN5                  1018
9593 +#define ADM1026_SYSCTL_IN6                  1019
9594 +#define ADM1026_SYSCTL_IN7                  1020
9595 +#define ADM1026_SYSCTL_IN8                  1021
9596 +#define ADM1026_SYSCTL_IN9                  1022
9597 +#define ADM1026_SYSCTL_IN10                 1023
9598 +#define ADM1026_SYSCTL_IN11                 1024
9599 +#define ADM1026_SYSCTL_IN12                 1025
9600 +#define ADM1026_SYSCTL_IN13                 1026
9601 +#define ADM1026_SYSCTL_IN14                 1027
9602 +#define ADM1026_SYSCTL_IN15                 1028
9603 +#define ADM1026_SYSCTL_IN16                 1029
9604 +#define ADM1026_SYSCTL_PWM                  1030
9605 +#define ADM1026_SYSCTL_ANALOG_OUT           1031
9606 +#define ADM1026_SYSCTL_AFC                  1032
9607 +#define ADM1026_SYSCTL_TEMP1                1033
9608 +#define ADM1026_SYSCTL_TEMP2                1034
9609 +#define ADM1026_SYSCTL_TEMP3                1035
9610 +#define ADM1026_SYSCTL_TEMP_OFFSET1         1036
9611 +#define ADM1026_SYSCTL_TEMP_OFFSET2         1037
9612 +#define ADM1026_SYSCTL_TEMP_OFFSET3         1038
9613 +#define ADM1026_SYSCTL_TEMP_THERM1          1039
9614 +#define ADM1026_SYSCTL_TEMP_THERM2          1040
9615 +#define ADM1026_SYSCTL_TEMP_THERM3          1041
9616 +#define ADM1026_SYSCTL_TEMP_TMIN1           1042
9617 +#define ADM1026_SYSCTL_TEMP_TMIN2           1043
9618 +#define ADM1026_SYSCTL_TEMP_TMIN3           1044
9619 +#define ADM1026_SYSCTL_VID                  1045
9620 +#define ADM1026_SYSCTL_VRM                  1046
9621 +
9622 +#define ADM1026_ALARM_TEMP2   (1L <<  0)
9623 +#define ADM1026_ALARM_TEMP3   (1L <<  1)
9624 +#define ADM1026_ALARM_IN9     (1L <<  1)
9625 +#define ADM1026_ALARM_IN11    (1L <<  2)
9626 +#define ADM1026_ALARM_IN12    (1L <<  3)
9627 +#define ADM1026_ALARM_IN13    (1L <<  4)
9628 +#define ADM1026_ALARM_IN14    (1L <<  5)
9629 +#define ADM1026_ALARM_IN15    (1L <<  6)
9630 +#define ADM1026_ALARM_IN16    (1L <<  7)
9631 +#define ADM1026_ALARM_IN0     (1L <<  8)
9632 +#define ADM1026_ALARM_IN1     (1L <<  9)
9633 +#define ADM1026_ALARM_IN2     (1L << 10)
9634 +#define ADM1026_ALARM_IN3     (1L << 11)
9635 +#define ADM1026_ALARM_IN4     (1L << 12)
9636 +#define ADM1026_ALARM_IN5     (1L << 13)
9637 +#define ADM1026_ALARM_IN6     (1L << 14)
9638 +#define ADM1026_ALARM_IN7     (1L << 15)
9639 +#define ADM1026_ALARM_FAN0    (1L << 16)
9640 +#define ADM1026_ALARM_FAN1    (1L << 17)
9641 +#define ADM1026_ALARM_FAN2    (1L << 18)
9642 +#define ADM1026_ALARM_FAN3    (1L << 19)
9643 +#define ADM1026_ALARM_FAN4    (1L << 20)
9644 +#define ADM1026_ALARM_FAN5    (1L << 21)
9645 +#define ADM1026_ALARM_FAN6    (1L << 22)
9646 +#define ADM1026_ALARM_FAN7    (1L << 23)
9647 +#define ADM1026_ALARM_TEMP1   (1L << 24)
9648 +#define ADM1026_ALARM_IN10    (1L << 25)
9649 +#define ADM1026_ALARM_IN8     (1L << 26)
9650 +#define ADM1026_ALARM_THERM   (1L << 27)
9651 +#define ADM1026_ALARM_AFC_FAN (1L << 28)
9652 +#define ADM1026_ALARM_UNUSED  (1L << 29)
9653 +#define ADM1026_ALARM_CI      (1L << 30)
9654 +/* -- SENSORS SYSCTL END -- */
9655 +
9656 +/* The /proc/sys entries */
9657 +/* These files are created for each detected ADM1026. This is just a template;
9658 + *    The actual list is built from this and additional per-chip
9659 + *    custom lists below.  Note the XXX_LEN macros.  These must be
9660 + *    compile time constants because they will be used to allocate
9661 + *    space for the final template passed to i2c_register_entry.
9662 + *    We depend on the ability of GCC to evaluate expressions at
9663 + *    compile time to turn these expressions into compile time
9664 + *    constants, but this can generate a warning.
9665 + */
9666 +static ctl_table adm1026_common[] = {
9667 +       {ADM1026_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
9668 +               &i2c_sysctl_real, NULL, &adm1026_in},
9669 +       {ADM1026_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
9670 +               &i2c_sysctl_real, NULL, &adm1026_in},
9671 +       {ADM1026_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
9672 +               &i2c_sysctl_real, NULL, &adm1026_in},
9673 +       {ADM1026_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
9674 +               &i2c_sysctl_real, NULL, &adm1026_in},
9675 +       {ADM1026_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
9676 +               &i2c_sysctl_real, NULL, &adm1026_in},
9677 +       {ADM1026_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
9678 +               &i2c_sysctl_real, NULL, &adm1026_in},
9679 +       {ADM1026_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
9680 +               &i2c_sysctl_real, NULL, &adm1026_in},
9681 +       {ADM1026_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
9682 +               &i2c_sysctl_real, NULL, &adm1026_in},
9683 +       {ADM1026_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
9684 +               &i2c_sysctl_real, NULL, &adm1026_in},
9685 +       {ADM1026_SYSCTL_IN9, "in9", NULL, 0, 0644, NULL, &i2c_proc_real,
9686 +               &i2c_sysctl_real, NULL, &adm1026_in},
9687 +       {ADM1026_SYSCTL_IN10, "in10", NULL, 0, 0644, NULL, &i2c_proc_real,
9688 +               &i2c_sysctl_real, NULL, &adm1026_in},
9689 +       {ADM1026_SYSCTL_IN11, "in11", NULL, 0, 0644, NULL, &i2c_proc_real,
9690 +               &i2c_sysctl_real, NULL, &adm1026_in},
9691 +       {ADM1026_SYSCTL_IN12, "in12", NULL, 0, 0644, NULL, &i2c_proc_real,
9692 +               &i2c_sysctl_real, NULL, &adm1026_in},
9693 +       {ADM1026_SYSCTL_IN13, "in13", NULL, 0, 0644, NULL, &i2c_proc_real,
9694 +               &i2c_sysctl_real, NULL, &adm1026_in},
9695 +       {ADM1026_SYSCTL_IN14, "in14", NULL, 0, 0644, NULL, &i2c_proc_real,
9696 +               &i2c_sysctl_real, NULL, &adm1026_in},
9697 +       {ADM1026_SYSCTL_IN15, "in15", NULL, 0, 0644, NULL, &i2c_proc_real,
9698 +               &i2c_sysctl_real, NULL, &adm1026_in},
9699 +       {ADM1026_SYSCTL_IN16, "in16", NULL, 0, 0644, NULL, &i2c_proc_real,
9700 +               &i2c_sysctl_real, NULL, &adm1026_in16},
9701 +
9702 +       {ADM1026_SYSCTL_FAN0, "fan0", NULL, 0, 0644, NULL, &i2c_proc_real,
9703 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9704 +       {ADM1026_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
9705 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9706 +       {ADM1026_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
9707 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9708 +       {ADM1026_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
9709 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9710 +       {ADM1026_SYSCTL_FAN4, "fan4", NULL, 0, 0644, NULL, &i2c_proc_real,
9711 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9712 +       {ADM1026_SYSCTL_FAN5, "fan5", NULL, 0, 0644, NULL, &i2c_proc_real,
9713 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9714 +       {ADM1026_SYSCTL_FAN6, "fan6", NULL, 0, 0644, NULL, &i2c_proc_real,
9715 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9716 +       {ADM1026_SYSCTL_FAN7, "fan7", NULL, 0, 0644, NULL, &i2c_proc_real,
9717 +               &i2c_sysctl_real, NULL, &adm1026_fan},
9718 +       {ADM1026_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
9719 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_fan_div},
9720 +
9721 +       {ADM1026_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
9722 +               &i2c_sysctl_real, NULL, &adm1026_temp},
9723 +       {ADM1026_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
9724 +               &i2c_sysctl_real, NULL, &adm1026_temp},
9725 +       {ADM1026_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
9726 +               &i2c_sysctl_real, NULL, &adm1026_temp},
9727 +       {ADM1026_SYSCTL_TEMP_OFFSET1, "temp1_offset", NULL, 0, 0644, NULL,
9728 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_offset},
9729 +       {ADM1026_SYSCTL_TEMP_OFFSET2, "temp2_offset", NULL, 0, 0644, NULL,
9730 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_offset},
9731 +       {ADM1026_SYSCTL_TEMP_OFFSET3, "temp3_offset", NULL, 0, 0644, NULL,
9732 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_offset},
9733 +       {ADM1026_SYSCTL_TEMP_TMIN1, "temp1_tmin", NULL, 0, 0644, NULL,
9734 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_tmin},
9735 +       {ADM1026_SYSCTL_TEMP_TMIN2, "temp2_tmin", NULL, 0, 0644, NULL,
9736 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_tmin},
9737 +       {ADM1026_SYSCTL_TEMP_TMIN3, "temp3_tmin", NULL, 0, 0644, NULL,
9738 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_tmin},
9739 +       {ADM1026_SYSCTL_TEMP_THERM1, "temp1_therm", NULL, 0, 0644, NULL,
9740 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_therm},
9741 +       {ADM1026_SYSCTL_TEMP_THERM2, "temp2_therm", NULL, 0, 0644, NULL,
9742 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_therm},
9743 +       {ADM1026_SYSCTL_TEMP_THERM3, "temp3_therm", NULL, 0, 0644, NULL,
9744 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_temp_therm},
9745 +
9746 +       {ADM1026_SYSCTL_VID, "vid", NULL, 0, 0644, NULL, &i2c_proc_real,
9747 +               &i2c_sysctl_real, NULL, &adm1026_vid},
9748 +       {ADM1026_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
9749 +               &i2c_sysctl_real, NULL, &adm1026_vrm},
9750 +
9751 +       {ADM1026_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
9752 +               &i2c_sysctl_real, NULL, &adm1026_alarms},
9753 +       {ADM1026_SYSCTL_ALARM_MASK, "alarm_mask", NULL, 0, 0644, NULL,
9754 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_alarm_mask},
9755 +
9756 +       {ADM1026_SYSCTL_GPIO, "gpio", NULL, 0, 0644, NULL, &i2c_proc_real,
9757 +               &i2c_sysctl_real, NULL, &adm1026_gpio},
9758 +       {ADM1026_SYSCTL_GPIO_MASK, "gpio_mask", NULL, 0, 0644, NULL,
9759 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_gpio_mask},
9760 +
9761 +       {ADM1026_SYSCTL_PWM, "pwm", NULL, 0, 0644, NULL, &i2c_proc_real,
9762 +               &i2c_sysctl_real, NULL, &adm1026_pwm},
9763 +       {ADM1026_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL,
9764 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1026_analog_out},
9765 +       {ADM1026_SYSCTL_AFC, "afc", NULL, 0, 0644, NULL, &i2c_proc_real,
9766 +               &i2c_sysctl_real, NULL, &adm1026_afc},
9767 +
9768 +       {0}
9769 +};
9770 +#define CTLTBL_COMMON (sizeof(adm1026_common)/sizeof(adm1026_common[0]))
9771 +
9772 +#define MAX2(a,b) ((a)>(b)?(a):(b))
9773 +#define MAX3(a,b,c) ((a)>(b)?MAX2((a),(c)):MAX2((b),(c)))
9774 +#define MAX4(a,b,c,d) ((a)>(b)?MAX3((a),(c),(d)):MAX3((b),(c),(d)))
9775 +
9776 +#define CTLTBL_MAX (CTLTBL_COMMON)
9777 +
9778 +/* This function is called when:
9779 +     * the module is loaded
9780 +     * a new adapter is loaded
9781 + */
9782 +int adm1026_attach_adapter(struct i2c_adapter *adapter)
9783 +{
9784 +       return i2c_detect(adapter, &addr_data, adm1026_detect);
9785 +}
9786 +
9787 +/* This function is called by i2c_detect */
9788 +int adm1026_detect(struct i2c_adapter *adapter, int address,
9789 +               unsigned short flags, int kind)
9790 +{
9791 +       int i;
9792 +       int company, verstep ;
9793 +       struct i2c_client *new_client;
9794 +       struct adm1026_data *data;
9795 +       int err = 0;
9796 +       const char *type_name = "";
9797 +       struct ctl_table template[CTLTBL_MAX] ;
9798 +       struct ctl_table * template_next = template ;
9799 +
9800 +       if (i2c_is_isa_adapter(adapter)) {
9801 +               /* This chip has no ISA interface */
9802 +               goto ERROR0 ;
9803 +       }
9804 +
9805 +       if (!i2c_check_functionality(adapter,
9806 +                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
9807 +               /* We need to be able to do byte I/O */
9808 +               goto ERROR0 ;
9809 +       }
9810 +
9811 +       /* OK. For now, we presume we have a valid client. We now create the
9812 +          client structure, even though we cannot fill it completely yet.
9813 +          But it allows us to access adm1026_{read,write}_value. */
9814 +
9815 +       if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
9816 +               err = -ENOMEM;
9817 +               goto ERROR0;
9818 +       }
9819 +
9820 +       new_client = &data->client;
9821 +       new_client->addr = address;
9822 +       new_client->data = data;
9823 +       new_client->adapter = adapter;
9824 +       new_client->driver = &adm1026_driver;
9825 +       new_client->flags = 0;
9826 +
9827 +       /* Now, we do the remaining detection. */
9828 +
9829 +       company = adm1026_read_value(new_client, ADM1026_REG_COMPANY);
9830 +       verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP);
9831 +
9832 +#ifdef DEBUG
9833 +       printk("adm1026: Detecting device at %d,0x%02x with"
9834 +               " COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
9835 +               i2c_adapter_id(new_client->adapter), new_client->addr,
9836 +               company, verstep
9837 +           );
9838 +#endif
9839 +
9840 +       /* If auto-detecting, Determine the chip type. */
9841 +       if (kind <= 0) {
9842 +#ifdef DEBUG
9843 +               printk("adm1026: Autodetecting device at %d,0x%02x ...\n",
9844 +                       i2c_adapter_id(adapter), address );
9845 +#endif
9846 +               if( company == ADM1026_COMPANY_ANALOG_DEV
9847 +                   && verstep == ADM1026_VERSTEP_ADM1026 ) {
9848 +                       kind = adm1026 ;
9849 +               } else if( company == ADM1026_COMPANY_ANALOG_DEV
9850 +                   && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC ) {
9851 +                       printk("adm1026: Unrecgonized stepping 0x%02x"
9852 +                           " Defaulting to ADM1026.\n", verstep );
9853 +                       kind = adm1026 ;
9854 +               } else if( (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC ) {
9855 +                       printk("adm1026: Found version/stepping 0x%02x"
9856 +                           " Assuming generic ADM1026.\n", verstep );
9857 +                       kind = any_chip ;
9858 +               } else {
9859 +#ifdef DEBUG
9860 +                       printk("adm1026: Autodetection failed\n");
9861 +#endif
9862 +                       /* Not an ADM1026 ... */
9863 +                       if( kind == 0 ) {  /* User used force=x,y */
9864 +                           printk("adm1026: Generic ADM1026 Version 6 not"
9865 +                               " found at %d,0x%02x. Try force_adm1026.\n",
9866 +                               i2c_adapter_id(adapter), address );
9867 +                       }
9868 +                       err = 0 ;
9869 +                       goto ERROR1;
9870 +               }
9871 +       }
9872 +
9873 +       /* Fill in the chip specific driver values */
9874 +       switch (kind) {
9875 +       case any_chip :
9876 +               type_name = "adm1026";
9877 +               strcpy(new_client->name, "Generic ADM1026");
9878 +               template_next = template ;  /* None used */
9879 +               break ;
9880 +       case adm1026 :
9881 +               type_name = "adm1026";
9882 +               strcpy(new_client->name, "Analog Devices ADM1026");
9883 +               template_next = template ;
9884 +               break ;
9885 +#if 0
9886 +       /* Example of another adm1026 "compatible" device */
9887 +       case adx1000 :
9888 +               type_name = "adx1000";
9889 +               strcpy(new_client->name, "Compatible ADX1000");
9890 +               memcpy( template, adx_specific, sizeof(adx_specific) );
9891 +               template_next = template + CTLTBL_ADX1000 ;
9892 +               break ;
9893 +#endif
9894 +       default :
9895 +               printk("adm1026: Internal error, invalid kind (%d)!", kind);
9896 +               err = -EFAULT ;
9897 +               goto ERROR1;
9898 +       }
9899 +
9900 +       /* Fill in the remaining client fields */
9901 +       new_client->id = adm1026_id++;
9902 +       printk("adm1026(%d): Assigning ID %d to %s at %d,0x%02x\n",
9903 +               new_client->id, new_client->id, new_client->name,
9904 +               i2c_adapter_id(new_client->adapter),
9905 +               new_client->addr
9906 +           );
9907 +
9908 +       /* Housekeeping values */
9909 +       data->type = kind;
9910 +       data->valid = 0;
9911 +
9912 +       /* Set the VRM version */
9913 +       data->vrm = ADM1026_INIT_VRM ;
9914 +       data->vid = ADM1026_INIT_VID ;
9915 +
9916 +       init_MUTEX(&data->update_lock);
9917 +
9918 +       /* Initialize the ADM1026 chip */
9919 +       adm1026_init_client(new_client);
9920 +
9921 +       /* Tell the I2C layer a new client has arrived */
9922 +       if ((err = i2c_attach_client(new_client)))
9923 +               goto ERROR1;
9924 +
9925 +       /* Finish out the template */
9926 +       memcpy(template_next, adm1026_common, sizeof(adm1026_common));
9927 +
9928 +       /* Register a new directory entry with module sensors */
9929 +       if ((i = i2c_register_entry(new_client,
9930 +                                       type_name,
9931 +                                       template)) < 0) {
9932 +               err = i;
9933 +               goto ERROR2;
9934 +       }
9935 +       data->sysctl_id = i;
9936 +
9937 +       return 0;
9938 +
9939 +       /* Error out and cleanup code */
9940 +    ERROR2:
9941 +       i2c_detach_client(new_client);
9942 +    ERROR1:
9943 +       kfree(data);
9944 +    ERROR0:
9945 +       return err;
9946 +}
9947 +
9948 +int adm1026_detach_client(struct i2c_client *client)
9949 +{
9950 +       int err;
9951 +       int id ;
9952 +
9953 +       id = client->id;
9954 +       i2c_deregister_entry(((struct adm1026_data *)(client->data))->sysctl_id);
9955 +
9956 +       if ((err = i2c_detach_client(client))) {
9957 +               printk("adm1026(%d): Client deregistration failed,"
9958 +                       " client not detached.\n", id );
9959 +               return err;
9960 +       }
9961 +
9962 +       kfree(client->data);
9963 +
9964 +       return 0;
9965 +}
9966 +
9967 +int adm1026_read_value(struct i2c_client *client, u8 reg)
9968 +{
9969 +       int res;
9970 +
9971 +       if( reg < 0x80 ) {
9972 +               /* "RAM" locations */
9973 +               res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
9974 +       } else {
9975 +               /* EEPROM, do nothing */
9976 +               res = 0 ;
9977 +       }
9978 +
9979 +       return res ;
9980 +}
9981 +
9982 +int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
9983 +{
9984 +       int res ;
9985 +
9986 +       if( reg < 0x80 ) {
9987 +               /* "RAM" locations */
9988 +               res = i2c_smbus_write_byte_data(client, reg, value);
9989 +       } else {
9990 +               /* EEPROM, do nothing */
9991 +               res = 0 ;
9992 +       }
9993 +
9994 +       return res ;
9995 +}
9996 +
9997 +/* Called when we have found a new ADM1026. */
9998 +void adm1026_init_client(struct i2c_client *client)
9999 +{
10000 +       int value ;
10001 +       int i;
10002 +       struct adm1026_data *data = client->data;
10003 +
10004 +#ifdef DEBUG
10005 +       printk("adm1026(%d): Initializing device\n", client->id);
10006 +#endif
10007 +
10008 +       /* Read chip config */
10009 +       data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
10010 +       data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
10011 +       data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
10012 +
10013 +       /* Inform user of chip config */
10014 +#ifdef DEBUG
10015 +       printk("adm1026(%d): ADM1026_REG_CONFIG1 is: 0x%02x\n",
10016 +               client->id, data->config1 );
10017 +#endif
10018 +       if( (data->config1 & CFG1_MONITOR) == 0 ) {
10019 +               printk("adm1026(%d): Monitoring not currently enabled.\n",
10020 +                           client->id );
10021 +       }
10022 +       if( data->config1 & CFG1_INT_ENABLE ) {
10023 +               printk("adm1026(%d): SMBALERT interrupts are enabled.\n",
10024 +                           client->id );
10025 +       }
10026 +       if( data->config1 & CFG1_AIN8_9 ) {
10027 +               printk("adm1026(%d): in8 and in9 enabled.  temp3 disabled.\n",
10028 +                           client->id );
10029 +       } else {
10030 +               printk("adm1026(%d): temp3 enabled.  in8 and in9 disabled.\n",
10031 +                           client->id );
10032 +       }
10033 +       if( data->config1 & CFG1_THERM_HOT ) {
10034 +               printk("adm1026(%d): Automatic THERM, PWM, and temp limits enabled.\n",
10035 +                           client->id );
10036 +       }
10037 +
10038 +       value = data->config3 ;
10039 +       if( data->config3 & CFG3_GPIO16_ENABLE ) {
10040 +               printk("adm1026(%d): GPIO16 enabled.  THERM pin disabled.\n",
10041 +                           client->id );
10042 +       } else {
10043 +               printk("adm1026(%d): THERM pin enabled.  GPIO16 disabled.\n",
10044 +                           client->id );
10045 +       }
10046 +       if( data->config3 & CFG3_VREF_250 ) {
10047 +               printk("adm1026(%d): Vref is 2.50 Volts.\n", client->id );
10048 +       } else {
10049 +               printk("adm1026(%d): Vref is 1.82 Volts.\n", client->id );
10050 +       }
10051 +
10052 +       /* Read and pick apart the existing GPIO configuration */
10053 +       value = 0 ;
10054 +       for( i = 0 ; i <= 15 ; ++i ) {
10055 +               if( (i & 0x03) == 0 ) {
10056 +                       value = adm1026_read_value(client,
10057 +                                       ADM1026_REG_GPIO_CFG_0_3 + i/4 );
10058 +               }
10059 +               data->gpio_config[i] = value & 0x03 ;
10060 +               value >>= 2 ;
10061 +       }
10062 +       data->gpio_config[16] = (data->config3 >> 6) & 0x03 ;
10063 +
10064 +       /* ... and then print it */
10065 +       adm1026_print_gpio(client);
10066 +
10067 +       /* If the user asks us to reprogram the GPIO config, then
10068 +        *   do it now.  But only if this is the first ADM1026.
10069 +        */
10070 +       if( client->id == 0
10071 +           && (gpio_input[0] != -1 || gpio_output[0] != -1
10072 +               || gpio_inverted[0] != -1 || gpio_normal[0] != -1
10073 +               || gpio_fan[0] != -1 ) ) {
10074 +               adm1026_fixup_gpio(client);
10075 +       }
10076 +
10077 +       /* WE INTENTIONALLY make no changes to the limits,
10078 +        *   offsets, pwms and fans.  If they were
10079 +        *   configured, we don't want to mess with them.
10080 +        *   If they weren't, the default is generally safe
10081 +        *   and will suffice until 'sensors -s' can be run.
10082 +        */
10083 +
10084 +       /* Start monitoring */
10085 +       value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
10086 +
10087 +       /* Set MONITOR, clear interrupt acknowledge and s/w reset */
10088 +       value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET) ;
10089 +#ifdef DEBUG
10090 +       printk("adm1026(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
10091 +#endif
10092 +       data->config1 = value ;
10093 +       adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
10094 +
10095 +}
10096 +
10097 +void adm1026_print_gpio(struct i2c_client *client)
10098 +{
10099 +       struct adm1026_data *data = client->data;
10100 +       int  i ;
10101 +
10102 +       printk("adm1026(%d): GPIO config is:\nadm1026(%d):",
10103 +                           client->id, client->id );
10104 +       for( i = 0 ; i <= 7 ; ++i ) {
10105 +               if( data->config2 & (1 << i) ) {
10106 +                       printk( " %sGP%s%d",
10107 +                               data->gpio_config[i] & 0x02 ? "" : "!",
10108 +                               data->gpio_config[i] & 0x01 ? "OUT" : "IN",
10109 +                               i );
10110 +               } else {
10111 +                       printk( " FAN%d", i );
10112 +               }
10113 +       }
10114 +       printk( "\nadm1026(%d):", client->id );
10115 +       for( i = 8 ; i <= 15 ; ++i ) {
10116 +               printk( " %sGP%s%d",
10117 +                       data->gpio_config[i] & 0x02 ? "" : "!",
10118 +                       data->gpio_config[i] & 0x01 ? "OUT" : "IN",
10119 +                       i );
10120 +       }
10121 +       if( data->config3 & CFG3_GPIO16_ENABLE ) {
10122 +               printk( " %sGP%s16\n",
10123 +                       data->gpio_config[16] & 0x02 ? "" : "!",
10124 +                       data->gpio_config[16] & 0x01 ? "OUT" : "IN" );
10125 +       } else {
10126 +               /* GPIO16 is THERM */
10127 +               printk( " THERM\n" );
10128 +       }
10129 +}
10130 +
10131 +void adm1026_fixup_gpio(struct i2c_client *client)
10132 +{
10133 +       struct adm1026_data *data = client->data;
10134 +       int  i ;
10135 +       int  value ;
10136 +
10137 +       /* Make the changes requested. */
10138 +       /* We may need to unlock/stop monitoring or soft-reset the
10139 +        *    chip before we can make changes.  This hasn't been
10140 +        *    tested much.  FIXME
10141 +        */
10142 +
10143 +       /* Make outputs */
10144 +       for( i = 0 ; i <= 16 ; ++i ) {
10145 +               if( gpio_output[i] >= 0 && gpio_output[i] <= 16 ) {
10146 +                       data->gpio_config[gpio_output[i]] |= 0x01 ;
10147 +               }
10148 +               /* if GPIO0-7 is output, it isn't a FAN tach */
10149 +               if( gpio_output[i] >= 0 && gpio_output[i] <= 7 ) {
10150 +                       data->config2 |= 1 << gpio_output[i] ;
10151 +               }
10152 +       }
10153 +
10154 +       /* Input overrides output */
10155 +       for( i = 0 ; i <= 16 ; ++i ) {
10156 +               if( gpio_input[i] >= 0 && gpio_input[i] <= 16 ) {
10157 +                       data->gpio_config[gpio_input[i]] &= ~ 0x01 ;
10158 +               }
10159 +               /* if GPIO0-7 is input, it isn't a FAN tach */
10160 +               if( gpio_input[i] >= 0 && gpio_input[i] <= 7 ) {
10161 +                       data->config2 |= 1 << gpio_input[i] ;
10162 +               }
10163 +       }
10164 +
10165 +       /* Inverted  */
10166 +       for( i = 0 ; i <= 16 ; ++i ) {
10167 +               if( gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16 ) {
10168 +                       data->gpio_config[gpio_inverted[i]] &= ~ 0x02 ;
10169 +               }
10170 +       }
10171 +
10172 +       /* Normal overrides inverted  */
10173 +       for( i = 0 ; i <= 16 ; ++i ) {
10174 +               if( gpio_normal[i] >= 0 && gpio_normal[i] <= 16 ) {
10175 +                       data->gpio_config[gpio_normal[i]] |= 0x02 ;
10176 +               }
10177 +       }
10178 +
10179 +       /* Fan overrides input and output */
10180 +       for( i = 0 ; i <= 7 ; ++i ) {
10181 +               if( gpio_fan[i] >= 0 && gpio_fan[i] <= 7 ) {
10182 +                       data->config2 &= ~( 1 << gpio_fan[i] );
10183 +               }
10184 +       }
10185 +
10186 +       /* Write new configs to registers */
10187 +       adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
10188 +       data->config3 = (data->config3 & 0x3f)
10189 +                       | ((data->gpio_config[16] & 0x03) << 6) ;
10190 +       adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
10191 +       for( i = 15, value = 0 ; i >= 0 ; --i ) {
10192 +               value <<= 2 ;
10193 +               value |= data->gpio_config[i] & 0x03 ;
10194 +               if( (i & 0x03) == 0 ) {
10195 +                       adm1026_write_value(client,
10196 +                                       ADM1026_REG_GPIO_CFG_0_3 + i/4,
10197 +                                       value );
10198 +                       value = 0 ;
10199 +               }
10200 +       }
10201 +
10202 +       /* Print the new config */
10203 +       adm1026_print_gpio(client);
10204 +}
10205 +
10206 +void adm1026_update_client(struct i2c_client *client)
10207 +{
10208 +       struct adm1026_data *data = client->data;
10209 +       int i;
10210 +       long value, alarms, gpio ;
10211 +
10212 +       down(&data->update_lock);
10213 +
10214 +       if (!data->valid
10215 +           || (jiffies - data->last_reading > ADM1026_DATA_INTERVAL )) {
10216 +               /* Things that change quickly */
10217 +
10218 +#ifdef DEBUG
10219 +               printk("adm1026(%d): Reading sensor values\n", client->id);
10220 +#endif
10221 +               for (i = 0 ; i <= 16 ; ++i) {
10222 +                       data->in[i] =
10223 +                           adm1026_read_value(client, ADM1026_REG_IN(i));
10224 +               }
10225 +
10226 +               for (i = 0 ; i <= 7 ; ++i) {
10227 +                       data->fan[i] =
10228 +                           adm1026_read_value(client, ADM1026_REG_FAN(i));
10229 +               }
10230 +
10231 +               for (i = 0 ; i <= 2 ; ++i) {
10232 +                       /* NOTE: temp[] is s8 and we assume 2's complement
10233 +                        *   "conversion" in the assignment   */
10234 +                       data->temp[i] =
10235 +                           adm1026_read_value(client, ADM1026_REG_TEMP(i));
10236 +               }
10237 +
10238 +               data->pwm = adm1026_read_value(client, ADM1026_REG_PWM);
10239 +               data->analog_out = adm1026_read_value(client, ADM1026_REG_DAC);
10240 +
10241 +               /* GPIO16 is MSbit of alarms, move it to gpio */
10242 +               alarms  = adm1026_read_value(client, ADM1026_REG_STATUS4);
10243 +               gpio = alarms & 0x80 ? 0x0100 : 0 ;  /* GPIO16 */
10244 +               alarms &= 0x7f ;
10245 +               alarms <<= 8 ;
10246 +               alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
10247 +               alarms <<= 8 ;
10248 +               alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
10249 +               alarms <<= 8 ;
10250 +               alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
10251 +               data->alarms = alarms ;
10252 +
10253 +               /* Read the GPIO values */
10254 +               gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_8_15);
10255 +               gpio <<= 8 ;
10256 +               gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_0_7);
10257 +               data->gpio = gpio ;
10258 +
10259 +               data->last_reading = jiffies ;
10260 +       };  /* last_reading */
10261 +
10262 +       if (!data->valid
10263 +           || (jiffies - data->last_config > ADM1026_CONFIG_INTERVAL) ) {
10264 +               /* Things that don't change often */
10265 +
10266 +#ifdef DEBUG
10267 +               printk("adm1026(%d): Reading config values\n", client->id);
10268 +#endif
10269 +               for (i = 0 ; i <= 16 ; ++i) {
10270 +                       data->in_min[i] =
10271 +                           adm1026_read_value(client, ADM1026_REG_IN_MIN(i));
10272 +                       data->in_max[i] =
10273 +                           adm1026_read_value(client, ADM1026_REG_IN_MAX(i));
10274 +               }
10275 +
10276 +               value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
10277 +                       | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
10278 +               for (i = 0 ; i <= 7 ; ++i) {
10279 +                       data->fan_min[i] =
10280 +                           adm1026_read_value(client, ADM1026_REG_FAN_MIN(i));
10281 +                       data->fan_div[i] = DIV_FROM_REG(value & 0x03);
10282 +                       value >>= 2 ;
10283 +               }
10284 +
10285 +               for (i = 0; i <= 2; ++i) {
10286 +                       /* NOTE: temp_xxx[] are s8 and we assume 2's complement
10287 +                        *   "conversion" in the assignment   */
10288 +                       data->temp_min[i] =
10289 +                           adm1026_read_value(client, ADM1026_REG_TEMP_MIN(i));
10290 +                       data->temp_max[i] =
10291 +                           adm1026_read_value(client, ADM1026_REG_TEMP_MAX(i));
10292 +                       data->temp_tmin[i] =
10293 +                           adm1026_read_value(client, ADM1026_REG_TEMP_TMIN(i));
10294 +                       data->temp_therm[i] =
10295 +                           adm1026_read_value(client, ADM1026_REG_TEMP_THERM(i));
10296 +                       data->temp_offset[i] =
10297 +                           adm1026_read_value(client, ADM1026_REG_TEMP_OFFSET(i));
10298 +               }
10299 +
10300 +               /* Read the STATUS/alarm masks */
10301 +               alarms  = adm1026_read_value(client, ADM1026_REG_MASK4);
10302 +               gpio    = alarms & 0x80 ? 0x0100 : 0 ;  /* GPIO16 */
10303 +               alarms  = (alarms & 0x7f) << 8 ;
10304 +               alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
10305 +               alarms <<= 8 ;
10306 +               alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
10307 +               alarms <<= 8 ;
10308 +               alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
10309 +               data->alarm_mask = alarms ;
10310 +
10311 +               /* Read the GPIO values */
10312 +               gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_8_15);
10313 +               gpio <<= 8 ;
10314 +               gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
10315 +               data->gpio_mask = gpio ;
10316 +
10317 +               /* Read the GPIO config */
10318 +               data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
10319 +               data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
10320 +               data->gpio_config[16] = (data->config3 >> 6) & 0x03 ;
10321 +
10322 +               value = 0 ;
10323 +               for( i = 0 ; i <= 15 ; ++i ) {
10324 +                       if( (i & 0x03) == 0 ) {
10325 +                               value = adm1026_read_value(client,
10326 +                                           ADM1026_REG_GPIO_CFG_0_3 + i/4 );
10327 +                       }
10328 +                       data->gpio_config[i] = value & 0x03 ;
10329 +                       value >>= 2 ;
10330 +               }
10331 +
10332 +               data->last_config = jiffies;
10333 +       };  /* last_config */
10334 +
10335 +       /* We don't know where or even _if_ the VID might be on the GPIO
10336 +        *    pins.  But the datasheet gives an example config showing
10337 +        *    GPIO11-15 being used to monitor VID0-4, so we go with that
10338 +        *    but make the vid WRITEABLE so if it's wrong, the user can
10339 +        *    set it in /etc/sensors.conf perhaps using an expression or
10340 +        *    0 to trigger a re-read from the GPIO pins.
10341 +        */
10342 +       if( data->vid == ADM1026_INIT_VID ) {
10343 +               /* Hasn't been set yet, make a bold assumption */
10344 +               printk("adm1026(%d): Setting VID from GPIO11-15.\n",
10345 +                           client->id );
10346 +               data->vid = (data->gpio >> 11) & 0x1f ;
10347 +       }
10348 +       
10349 +       data->valid = 1;
10350 +
10351 +       up(&data->update_lock);
10352 +}
10353 +
10354 +
10355 +/* The following functions are the call-back functions of the /proc/sys and
10356 +   sysctl files.  The appropriate function is referenced in the ctl_table
10357 +   extra1 field.
10358 +
10359 +   Each function must return the magnitude (power of 10 to divide the
10360 +   data with) if it is called with operation set to SENSORS_PROC_REAL_INFO.
10361 +   It must put a maximum of *nrels elements in results reflecting the
10362 +   data of this file, and set *nrels to the number it actually put in
10363 +   it, if operation is SENSORS_PROC_REAL_READ.  Finally, it must get
10364 +   up to *nrels elements from results and write them to the chip, if
10365 +   operations is SENSORS_PROC_REAL_WRITE.
10366 + */
10367 +void adm1026_in(struct i2c_client *client, int operation, int ctl_name,
10368 +            int *nrels_mag, long *results)
10369 +{
10370 +       struct adm1026_data *data = client->data;
10371 +       int nr = ctl_name - ADM1026_SYSCTL_IN0;
10372 +
10373 +       /* We handle in0 - in15 here.  in16 (-12V) is handled below */
10374 +       if (nr < 0 || nr > 15)
10375 +               return ;  /* ERROR */
10376 +
10377 +       if (operation == SENSORS_PROC_REAL_INFO)
10378 +               *nrels_mag = 3;  /* 1.000 */
10379 +       else if (operation == SENSORS_PROC_REAL_READ) {
10380 +               adm1026_update_client(client);
10381 +               results[0] = INS_FROM_REG(nr,data->in_min[nr]);
10382 +               results[1] = INS_FROM_REG(nr,data->in_max[nr]);
10383 +               results[2] = INS_FROM_REG(nr,data->in[nr]);
10384 +               *nrels_mag = 3;
10385 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10386 +               down(&data->update_lock);
10387 +               if (*nrels_mag > 1) {
10388 +                       data->in_max[nr] = INS_TO_REG(nr,results[1]);
10389 +                       adm1026_write_value(client, ADM1026_REG_IN_MAX(nr),
10390 +                                        data->in_max[nr]);
10391 +               }
10392 +               if (*nrels_mag > 0) {
10393 +                       data->in_min[nr] = INS_TO_REG(nr,results[0]);
10394 +                       adm1026_write_value(client, ADM1026_REG_IN_MIN(nr),
10395 +                                        data->in_min[nr]);
10396 +               }
10397 +               up(&data->update_lock);
10398 +       }
10399 +}
10400 +
10401 +void adm1026_in16(struct i2c_client *client, int operation, int ctl_name,
10402 +            int *nrels_mag, long *results)
10403 +{
10404 +       struct adm1026_data *data = client->data;
10405 +       int nr = ctl_name - ADM1026_SYSCTL_IN0;
10406 +
10407 +       /* We handle in16 (-12V) here */
10408 +       if (nr != 16)
10409 +               return ;  /* ERROR */
10410 +
10411 +       /* Apply offset and swap min/max so that min is 90% of
10412 +        *    target and max is 110% of target.
10413 +        */
10414 +
10415 +       if (operation == SENSORS_PROC_REAL_INFO)
10416 +               *nrels_mag = 3;  /* 1.000 */
10417 +       else if (operation == SENSORS_PROC_REAL_READ) {
10418 +               adm1026_update_client(client);
10419 +               results[0] = INS_FROM_REG(nr,data->in_max[nr])-NEG12_OFFSET ;
10420 +               results[1] = INS_FROM_REG(nr,data->in_min[nr])-NEG12_OFFSET ;
10421 +               results[2] = INS_FROM_REG(nr,data->in[nr])-NEG12_OFFSET ;
10422 +               *nrels_mag = 3;
10423 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10424 +               down(&data->update_lock);
10425 +               if (*nrels_mag > 1) {
10426 +                       data->in_min[nr] = INS_TO_REG(nr,results[1]+NEG12_OFFSET);
10427 +                       adm1026_write_value(client, ADM1026_REG_IN_MIN(nr),
10428 +                                        data->in_min[nr]);
10429 +               }
10430 +               if (*nrels_mag > 0) {
10431 +                       data->in_max[nr] = INS_TO_REG(nr,results[0]+NEG12_OFFSET);
10432 +                       adm1026_write_value(client, ADM1026_REG_IN_MAX(nr),
10433 +                                        data->in_max[nr]);
10434 +               }
10435 +               up(&data->update_lock);
10436 +       }
10437 +}
10438 +
10439 +void adm1026_fan(struct i2c_client *client, int operation, int ctl_name,
10440 +             int *nrels_mag, long *results)
10441 +{
10442 +       struct adm1026_data *data = client->data;
10443 +       int nr = ctl_name - ADM1026_SYSCTL_FAN0 ;
10444 +
10445 +       if (nr < 0 || nr > 7)
10446 +               return ;  /* ERROR */
10447 +
10448 +       if (operation == SENSORS_PROC_REAL_INFO)
10449 +               *nrels_mag = 0;
10450 +       else if (operation == SENSORS_PROC_REAL_READ) {
10451 +               adm1026_update_client(client);
10452 +               results[0] = FAN_FROM_REG(data->fan_min[nr], data->fan_div[nr]);
10453 +               results[1] = FAN_FROM_REG(data->fan[nr], data->fan_div[nr]);
10454 +               *nrels_mag = 2;
10455 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10456 +               down(&data->update_lock);
10457 +               if (*nrels_mag > 0) {
10458 +                       data->fan_min[nr] = FAN_TO_REG(results[0],
10459 +                                                       data->fan_div[nr]);
10460 +                       adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
10461 +                                        data->fan_min[nr]);
10462 +               }
10463 +               up(&data->update_lock);
10464 +       }
10465 +}
10466 +
10467 +/* Adjust fan_min to account for new fan divisor */
10468 +void adm1026_fixup_fan_min(struct i2c_client *client, int fan, int old_div)
10469 +{
10470 +       struct adm1026_data *data = client->data;
10471 +       int  new_div = data->fan_div[fan] ;
10472 +       int  new_min;
10473 +
10474 +       /* 0 and 0xff are special.  Don't adjust them */
10475 +       if( data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff ) {
10476 +               return ;
10477 +       }
10478 +
10479 +       new_min = data->fan_min[fan] * old_div / new_div ;
10480 +       new_min = SENSORS_LIMIT(new_min, 1, 254);
10481 +       data->fan_min[fan] = new_min ;
10482 +       adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
10483 +}
10484 +
10485 +void adm1026_fan_div(struct i2c_client *client, int operation, int ctl_name,
10486 +               int *nrels_mag, long *results)
10487 +{
10488 +       struct adm1026_data *data = client->data;
10489 +       int i ;
10490 +       int value, div, old ;
10491 +
10492 +       if (ctl_name != ADM1026_SYSCTL_FAN_DIV)
10493 +               return ;  /* ERROR */
10494 +
10495 +       if (operation == SENSORS_PROC_REAL_INFO)
10496 +               *nrels_mag = 0;
10497 +       else if (operation == SENSORS_PROC_REAL_READ) {
10498 +               adm1026_update_client(client);
10499 +               for( i = 0 ; i <= 7 ; ++i ) {
10500 +                       results[i] = data->fan_div[i] ;
10501 +               }
10502 +               *nrels_mag = 8;
10503 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10504 +               down(&data->update_lock);
10505 +               value = 0 ;
10506 +               for( i = 7 ; i >= 0 ; --i ) {
10507 +                       value <<= 2 ;
10508 +                       if (*nrels_mag > i) {
10509 +                               old = data->fan_div[i] ;
10510 +                               div = DIV_TO_REG(results[i]) ;
10511 +                               data->fan_div[i] = DIV_FROM_REG(div) ;
10512 +                               if( data->fan_div[i] != old ) {
10513 +                                       adm1026_fixup_fan_min(client,i,old);
10514 +                               }
10515 +                       } else {
10516 +                               div = DIV_TO_REG(data->fan_div[i]) ;
10517 +                       }
10518 +                       value |= div ;
10519 +               }
10520 +               adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
10521 +                       value & 0xff);
10522 +               adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
10523 +                       (value >> 8) & 0xff);
10524 +               up(&data->update_lock);
10525 +       }
10526 +}
10527 +
10528 +void adm1026_temp(struct i2c_client *client, int operation, int ctl_name,
10529 +              int *nrels_mag, long *results)
10530 +{
10531 +       struct adm1026_data *data = client->data;
10532 +       int nr = ctl_name - ADM1026_SYSCTL_TEMP1 ;
10533 +
10534 +       if (nr < 0 || nr > 2)
10535 +               return ;  /* ERROR */
10536 +
10537 +       if (operation == SENSORS_PROC_REAL_INFO)
10538 +               *nrels_mag = 0;
10539 +       else if (operation == SENSORS_PROC_REAL_READ) {
10540 +               adm1026_update_client(client);
10541 +               results[0] = TEMP_FROM_REG(data->temp_min[nr]);
10542 +               results[1] = TEMP_FROM_REG(data->temp_max[nr]);
10543 +               results[2] = TEMP_FROM_REG(data->temp[nr]);
10544 +               *nrels_mag = 3;
10545 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10546 +               down(&data->update_lock);
10547 +               if (*nrels_mag > 1) {
10548 +                       data->temp_max[nr] = TEMP_TO_REG(results[1]);
10549 +                       adm1026_write_value(client, ADM1026_REG_TEMP_MAX(nr),
10550 +                                        data->temp_max[nr]);
10551 +               }
10552 +               if (*nrels_mag > 0) {
10553 +                       data->temp_min[nr] = TEMP_TO_REG(results[0]);
10554 +                       adm1026_write_value(client, ADM1026_REG_TEMP_MIN(nr),
10555 +                                        data->temp_min[nr]);
10556 +               }
10557 +               up(&data->update_lock);
10558 +       }
10559 +}
10560 +
10561 +void adm1026_temp_offset(struct i2c_client *client, int operation, int ctl_name,
10562 +               int *nrels_mag, long *results)
10563 +{
10564 +       struct adm1026_data *data = client->data;
10565 +       int nr = ctl_name - ADM1026_SYSCTL_TEMP_OFFSET1 ;
10566 +
10567 +       if (nr < 0 || nr > 2)
10568 +               return ;  /* ERROR */
10569 +
10570 +       if (operation == SENSORS_PROC_REAL_INFO)
10571 +               *nrels_mag = 0;
10572 +       else if (operation == SENSORS_PROC_REAL_READ) {
10573 +               adm1026_update_client(client);
10574 +               results[0] = TEMP_FROM_REG(data->temp_offset[nr]);
10575 +               *nrels_mag = 1;
10576 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10577 +               down(&data->update_lock);
10578 +               if (*nrels_mag > 0) {
10579 +                       data->temp_offset[nr] = TEMP_TO_REG(results[0]);
10580 +                       adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET(nr),
10581 +                           data->temp_offset[nr]);
10582 +               }
10583 +               up(&data->update_lock);
10584 +       }
10585 +}
10586 +
10587 +void adm1026_temp_tmin(struct i2c_client *client, int operation, int ctl_name,
10588 +               int *nrels_mag, long *results)
10589 +{
10590 +       struct adm1026_data *data = client->data;
10591 +       int nr = ctl_name - ADM1026_SYSCTL_TEMP_TMIN1 ;
10592 +
10593 +       if (nr < 0 || nr > 2)
10594 +               return ;  /* ERROR */
10595 +
10596 +       if (operation == SENSORS_PROC_REAL_INFO)
10597 +               *nrels_mag = 0;
10598 +       else if (operation == SENSORS_PROC_REAL_READ) {
10599 +               adm1026_update_client(client);
10600 +               results[0] = TEMP_FROM_REG(data->temp_tmin[nr]);
10601 +               *nrels_mag = 1;
10602 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10603 +               down(&data->update_lock);
10604 +               if (*nrels_mag > 0) {
10605 +                       data->temp_tmin[nr] = TEMP_TO_REG(results[0]);
10606 +                       adm1026_write_value(client, ADM1026_REG_TEMP_TMIN(nr),
10607 +                           data->temp_tmin[nr]);
10608 +               }
10609 +               up(&data->update_lock);
10610 +       }
10611 +}
10612 +
10613 +void adm1026_temp_therm(struct i2c_client *client, int operation, int ctl_name,
10614 +               int *nrels_mag, long *results)
10615 +{
10616 +       struct adm1026_data *data = client->data;
10617 +       int nr = ctl_name - ADM1026_SYSCTL_TEMP_THERM1 ;
10618 +
10619 +       if (nr < 0 || nr > 2)
10620 +               return ;  /* ERROR */
10621 +
10622 +       if (operation == SENSORS_PROC_REAL_INFO)
10623 +               *nrels_mag = 0;
10624 +       else if (operation == SENSORS_PROC_REAL_READ) {
10625 +               adm1026_update_client(client);
10626 +               results[0] = TEMP_FROM_REG(data->temp_therm[nr]);
10627 +               *nrels_mag = 1;
10628 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10629 +               down(&data->update_lock);
10630 +               if (*nrels_mag > 0) {
10631 +                       data->temp_therm[nr] = TEMP_TO_REG(results[0]);
10632 +                       adm1026_write_value(client, ADM1026_REG_TEMP_THERM(nr),
10633 +                           data->temp_therm[nr]);
10634 +               }
10635 +               up(&data->update_lock);
10636 +       }
10637 +}
10638 +
10639 +void adm1026_pwm(struct i2c_client *client, int operation, int ctl_name,
10640 +             int *nrels_mag, long *results)
10641 +{
10642 +       struct adm1026_data *data = client->data;
10643 +
10644 +       if (ctl_name != ADM1026_SYSCTL_PWM)
10645 +               return ;  /* ERROR */
10646 +
10647 +       if (operation == SENSORS_PROC_REAL_INFO)
10648 +               *nrels_mag = 0;
10649 +       else if (operation == SENSORS_PROC_REAL_READ) {
10650 +               adm1026_update_client(client);
10651 +               results[0] = PWM_FROM_REG(data->pwm);
10652 +               results[1] = 1 ;  /* Always enabled */
10653 +               *nrels_mag = 2;
10654 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10655 +               down(&data->update_lock);
10656 +               /* PWM enable is read-only */
10657 +               if (*nrels_mag > 0) {
10658 +                       data->pwm = PWM_TO_REG(results[0]);
10659 +                       adm1026_write_value(client, ADM1026_REG_PWM,
10660 +                                        data->pwm);
10661 +               }
10662 +               up(&data->update_lock);
10663 +       }
10664 +}
10665 +
10666 +void adm1026_analog_out(struct i2c_client *client, int operation, int ctl_name,
10667 +             int *nrels_mag, long *results)
10668 +{
10669 +       struct adm1026_data *data = client->data;
10670 +
10671 +       if (ctl_name != ADM1026_SYSCTL_ANALOG_OUT)
10672 +               return ;  /* ERROR */
10673 +
10674 +       if (operation == SENSORS_PROC_REAL_INFO)
10675 +               *nrels_mag = 0;  /* 0 - 255 */
10676 +       else if (operation == SENSORS_PROC_REAL_READ) {
10677 +               adm1026_update_client(client);
10678 +               results[0] = DAC_FROM_REG(data->analog_out);
10679 +               *nrels_mag = 1;
10680 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10681 +               down(&data->update_lock);
10682 +               if (*nrels_mag > 0) {
10683 +                       data->analog_out = DAC_TO_REG(results[0]);
10684 +                       adm1026_write_value(client, ADM1026_REG_DAC,
10685 +                                        data->analog_out);
10686 +               }
10687 +               up(&data->update_lock);
10688 +       }
10689 +}
10690 +
10691 +void adm1026_afc(struct i2c_client *client, int operation, int ctl_name,
10692 +             int *nrels_mag, long *results)
10693 +{
10694 +       struct adm1026_data *data = client->data;
10695 +
10696 +       if (ctl_name != ADM1026_SYSCTL_AFC)
10697 +               return ;  /* ERROR */
10698 +
10699 +       /* PWM auto fan control, DAC auto fan control */
10700 +
10701 +       if (operation == SENSORS_PROC_REAL_INFO)
10702 +               *nrels_mag = 0;
10703 +       else if (operation == SENSORS_PROC_REAL_READ) {
10704 +               adm1026_update_client(client);
10705 +               results[0] = (data->config1 & CFG1_PWM_AFC) != 0 ;
10706 +               results[1] = (data->config1 & CFG1_DAC_AFC) != 0 ;
10707 +               *nrels_mag = 2;
10708 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10709 +               down(&data->update_lock);
10710 +               if (*nrels_mag > 1) {
10711 +                       data->config1 = (data->config1 & ~CFG1_DAC_AFC)
10712 +                               | (results[1] ? CFG1_DAC_AFC : 0) ;
10713 +               }
10714 +               if (*nrels_mag > 0) {
10715 +                       data->config1 = (data->config1 & ~CFG1_PWM_AFC)
10716 +                               | (results[0] ? CFG1_PWM_AFC : 0) ;
10717 +                       adm1026_write_value(client, ADM1026_REG_CONFIG1,
10718 +                                        data->config1);
10719 +               }
10720 +               up(&data->update_lock);
10721 +       }
10722 +}
10723 +
10724 +void adm1026_vid(struct i2c_client *client, int operation, int ctl_name,
10725 +             int *nrels_mag, long *results)
10726 +{
10727 +       struct adm1026_data *data = client->data;
10728 +
10729 +       if( ctl_name != ADM1026_SYSCTL_VID )
10730 +               return ;  /* ERROR */
10731 +
10732 +       if (operation == SENSORS_PROC_REAL_INFO)
10733 +               *nrels_mag = 3;
10734 +       else if (operation == SENSORS_PROC_REAL_READ) {
10735 +               adm1026_update_client(client);
10736 +               results[0] = VID_FROM_REG((data->vid)&0x3f,data->vrm);
10737 +               *nrels_mag = 1;
10738 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10739 +               down(&data->update_lock);
10740 +               /* Hmmm... There isn't a VID_TO_REG mapping */
10741 +               if (*nrels_mag > 0) {
10742 +                       if( results[0] >= 0 ) {
10743 +                               data->vid = results[0] & 0x3f ;
10744 +                       } else {
10745 +                               data->vid = ADM1026_INIT_VID ;
10746 +                       }
10747 +               }
10748 +               up(&data->update_lock);
10749 +       }
10750 +
10751 +}
10752 +
10753 +void adm1026_vrm(struct i2c_client *client, int operation, int ctl_name,
10754 +             int *nrels_mag, long *results)
10755 +{
10756 +       struct adm1026_data *data = client->data;
10757 +
10758 +       if( ctl_name != ADM1026_SYSCTL_VRM )
10759 +               return ;  /* ERROR */
10760 +
10761 +       if (operation == SENSORS_PROC_REAL_INFO)
10762 +               *nrels_mag = 1;
10763 +       else if (operation == SENSORS_PROC_REAL_READ) {
10764 +               results[0] = data->vrm ;
10765 +               *nrels_mag = 1;
10766 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10767 +               if (*nrels_mag > 0) {
10768 +                       data->vrm = results[0] ;
10769 +               }
10770 +       }
10771 +}
10772 +
10773 +void adm1026_alarms(struct i2c_client *client, int operation, int ctl_name,
10774 +               int *nrels_mag, long *results)
10775 +{
10776 +       struct adm1026_data *data = client->data;
10777 +
10778 +       if( ctl_name != ADM1026_SYSCTL_ALARMS )
10779 +               return ;  /* ERROR */
10780 +
10781 +       if (operation == SENSORS_PROC_REAL_INFO)
10782 +               *nrels_mag = 0;
10783 +       else if (operation == SENSORS_PROC_REAL_READ) {
10784 +               adm1026_update_client(client);
10785 +               results[0] = data->alarms ;
10786 +               *nrels_mag = 1;
10787 +       }
10788 +       /* FIXME: Perhaps we should implement a write function
10789 +        *   to clear an alarm?
10790 +        */
10791 +}
10792 +
10793 +void adm1026_alarm_mask(struct i2c_client *client, int operation,
10794 +               int ctl_name, int *nrels_mag, long *results)
10795 +{
10796 +       struct adm1026_data *data = client->data;
10797 +       unsigned long mask ;
10798 +
10799 +       if( ctl_name != ADM1026_SYSCTL_ALARM_MASK )
10800 +               return ;  /* ERROR */
10801 +
10802 +       if (operation == SENSORS_PROC_REAL_INFO)
10803 +               *nrels_mag = 0;
10804 +       else if (operation == SENSORS_PROC_REAL_READ) {
10805 +               adm1026_update_client(client);
10806 +               results[0] = data->alarm_mask ;
10807 +               *nrels_mag = 1;
10808 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10809 +               down(&data->update_lock);
10810 +               if (*nrels_mag > 0) {
10811 +                       data->alarm_mask = results[0] & 0x7fffffff ;
10812 +                       mask = data->alarm_mask
10813 +                               | (data->gpio_mask & 0x10000 ? 0x80000000 : 0) ;
10814 +                       adm1026_write_value(client, ADM1026_REG_MASK1,
10815 +                                       mask & 0xff);
10816 +                       mask >>= 8 ;
10817 +                       adm1026_write_value(client, ADM1026_REG_MASK2,
10818 +                                       mask & 0xff);
10819 +                       mask >>= 8 ;
10820 +                       adm1026_write_value(client, ADM1026_REG_MASK3,
10821 +                                       mask & 0xff);
10822 +                       mask >>= 8 ;
10823 +                       adm1026_write_value(client, ADM1026_REG_MASK4,
10824 +                                       mask & 0xff);
10825 +               }
10826 +               up(&data->update_lock);
10827 +       }
10828 +}
10829 +
10830 +void adm1026_gpio(struct i2c_client *client, int operation, int ctl_name,
10831 +               int *nrels_mag, long *results)
10832 +{
10833 +       struct adm1026_data *data = client->data;
10834 +       long gpio ;
10835 +
10836 +       if( ctl_name != ADM1026_SYSCTL_GPIO )
10837 +               return ;  /* ERROR */
10838 +
10839 +       if (operation == SENSORS_PROC_REAL_INFO)
10840 +               *nrels_mag = 0;
10841 +       else if (operation == SENSORS_PROC_REAL_READ) {
10842 +               adm1026_update_client(client);
10843 +               results[0] = data->gpio ;
10844 +               *nrels_mag = 1;
10845 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10846 +               down(&data->update_lock);
10847 +               if (*nrels_mag > 0) {
10848 +                       data->gpio = results[0] & 0x1ffff ;
10849 +                       gpio = data->gpio ;
10850 +                       adm1026_write_value(client,
10851 +                               ADM1026_REG_GPIO_STATUS_0_7,
10852 +                               gpio & 0xff );
10853 +                       gpio >>= 8 ;
10854 +                       adm1026_write_value(client,
10855 +                               ADM1026_REG_GPIO_STATUS_8_15,
10856 +                               gpio & 0xff );
10857 +                       gpio = ((gpio >> 1) & 0x80)
10858 +                               | (data->alarms >> 24 & 0x7f);
10859 +                       adm1026_write_value(client,
10860 +                               ADM1026_REG_STATUS4,
10861 +                               gpio & 0xff );
10862 +               }
10863 +               up(&data->update_lock);
10864 +       }
10865 +}
10866 +
10867 +void adm1026_gpio_mask(struct i2c_client *client, int operation,
10868 +               int ctl_name, int *nrels_mag, long *results)
10869 +{
10870 +       struct adm1026_data *data = client->data;
10871 +       long mask ;
10872 +
10873 +       if( ctl_name != ADM1026_SYSCTL_GPIO_MASK )
10874 +               return ;  /* ERROR */
10875 +
10876 +       if (operation == SENSORS_PROC_REAL_INFO)
10877 +               *nrels_mag = 0;
10878 +       else if (operation == SENSORS_PROC_REAL_READ) {
10879 +               adm1026_update_client(client);
10880 +               results[0] = data->gpio_mask ;
10881 +               *nrels_mag = 1;
10882 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
10883 +               down(&data->update_lock);
10884 +               if (*nrels_mag > 0) {
10885 +                       data->gpio_mask = results[0] & 0x1ffff ;
10886 +                       mask = data->gpio_mask ;
10887 +                       adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,
10888 +                                       mask & 0xff);
10889 +                       mask >>= 8 ;
10890 +                       adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,
10891 +                                       mask & 0xff);
10892 +                       mask = ((mask >> 1) & 0x80)
10893 +                               | (data->alarm_mask >> 24 & 0x7f);
10894 +                       adm1026_write_value(client, ADM1026_REG_MASK1,
10895 +                                       mask & 0xff);
10896 +               }
10897 +               up(&data->update_lock);
10898 +       }
10899 +}
10900 +
10901 +static int __init sm_adm1026_init(void)
10902 +{
10903 +       printk("adm1026: Version %s (%s)\n", LM_VERSION, LM_DATE);
10904 +       printk("adm1026: See http://www.penguincomputing.com/lm_sensors for more info.\n" );
10905 +       return i2c_add_driver(&adm1026_driver);
10906 +}
10907 +
10908 +static void __exit sm_adm1026_exit(void)
10909 +{
10910 +       i2c_del_driver(&adm1026_driver);
10911 +}
10912 +
10913 +MODULE_LICENSE("GPL");
10914 +MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com");
10915 +MODULE_DESCRIPTION("ADM1026 driver");
10916 +
10917 +module_init(sm_adm1026_init);
10918 +module_exit(sm_adm1026_exit);
10919 --- linux-old/drivers/sensors/adm9240.c Thu Jan  1 00:00:00 1970
10920 +++ linux/drivers/sensors/adm9240.c     Mon Dec 13 20:18:44 2004
10921 @@ -0,0 +1,713 @@
10922 +/*
10923 +    adm9240.c - Part of lm_sensors, Linux kernel modules for hardware
10924 +             monitoring
10925 +    Copyright (C) 1999  Frodo Looijaard <frodol@dds.nl>
10926 +    and Philip Edelbrock <phil@netroedge.com>
10927 +
10928 +    This program is free software; you can redistribute it and/or modify
10929 +    it under the terms of the GNU General Public License as published by
10930 +    the Free Software Foundation; either version 2 of the License, or 
10931 +    (at your option) any later version.
10932 +
10933 +    This program is distributed in the hope that it will be useful,
10934 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
10935 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10936 +    GNU General Public License for more details.
10937 +
10938 +    You should have received a copy of the GNU General Public License
10939 +    along with this program; if not, write to the Free Software
10940 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10941 +*/
10942 +
10943 +/* Supports ADM9240, DS1780, and LM81. See doc/chips/adm9240 for details */
10944 +
10945 +/* 
10946 +       A couple notes about the ADM9240:
10947 +
10948 +* It claims to be 'LM7x' register compatible.  This must be in reference
10949 +  to only the LM78, because it is missing stuff to emulate LM75's as well. 
10950 +  (like the Winbond W83781 does)
10951
10952 +* This driver was written from rev. 0 of the PDF, but it seems well 
10953 +  written and complete (unlike the W83781 which is horrible and has
10954 +  supposidly gone through a few revisions.. rev 0 of that one must
10955 +  have been in crayon on construction paper...)
10956 +  
10957 +* All analog inputs can range from 0 to 2.5, eventhough some inputs are
10958 +  marked as being 5V, 12V, etc.  I don't have any real voltages going 
10959 +  into my prototype, so I'm not sure that things are computed right, 
10960 +  but at least the limits seem to be working OK.
10961 +  
10962 +* Another curiousity is that the fan_div seems to be read-only.  I.e.,
10963 +  any written value to it doesn't seem to make any difference.  The
10964 +  fan_div seems to be 'stuck' at 2 (which isn't a bad value in most cases).
10965 +  
10966 +  
10967 +  --Phil
10968 +
10969 +*/
10970 +
10971 +#include <linux/module.h>
10972 +#include <linux/slab.h>
10973 +#include <linux/i2c.h>
10974 +#include <linux/i2c-proc.h>
10975 +#include <linux/init.h>
10976 +#define LM_DATE "20041007"
10977 +#define LM_VERSION "2.8.8"
10978 +
10979 +/* Addresses to scan */
10980 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
10981 +static unsigned short normal_i2c_range[] = { 0x2c, 0x2f, SENSORS_I2C_END };
10982 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
10983 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
10984 +
10985 +/* Insmod parameters */
10986 +SENSORS_INSMOD_3(adm9240, ds1780, lm81);
10987 +
10988 +/* Many ADM9240 constants specified below */
10989 +
10990 +#define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2)
10991 +#define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2)
10992 +#define ADM9240_REG_IN(nr) (0x20 + (nr))
10993 +
10994 +/* The ADM9240 registers */
10995 +#define ADM9240_REG_TEST 0x15
10996 +#define ADM9240_REG_ANALOG_OUT 0x19
10997 +/* These are all read-only */
10998 +#define ADM9240_REG_2_5V 0x20
10999 +#define ADM9240_REG_VCCP1 0x21
11000 +#define ADM9240_REG_3_3V 0x22
11001 +#define ADM9240_REG_5V 0x23
11002 +#define ADM9240_REG_12V 0x24
11003 +#define ADM9240_REG_VCCP2 0x25
11004 +#define ADM9240_REG_TEMP 0x27
11005 +#define ADM9240_REG_FAN1 0x28
11006 +#define ADM9240_REG_FAN2 0x29
11007 +#define ADM9240_REG_COMPANY_ID 0x3E    /* 0x23 for ADM9240; 0xDA for DS1780 */
11008 +                                    /* 0x01 for LM81 */
11009 +#define ADM9240_REG_DIE_REV 0x3F
11010 +/* These are read/write */
11011 +#define ADM9240_REG_2_5V_HIGH 0x2B
11012 +#define ADM9240_REG_2_5V_LOW 0x2C
11013 +#define ADM9240_REG_VCCP1_HIGH 0x2D
11014 +#define ADM9240_REG_VCCP1_LOW 0x2E
11015 +#define ADM9240_REG_3_3V_HIGH 0x2F
11016 +#define ADM9240_REG_3_3V_LOW 0x30
11017 +#define ADM9240_REG_5V_HIGH 0x31
11018 +#define ADM9240_REG_5V_LOW 0x32
11019 +#define ADM9240_REG_12V_HIGH 0x33
11020 +#define ADM9240_REG_12V_LOW 0x34
11021 +#define ADM9240_REG_VCCP2_HIGH 0x35
11022 +#define ADM9240_REG_VCCP2_LOW 0x36
11023 +#define ADM9240_REG_TCRIT_LIMIT 0x37   /* LM81 only - not supported */
11024 +#define ADM9240_REG_LOW_LIMIT 0x38     /* LM81 only - not supported */
11025 +#define ADM9240_REG_TOS 0x39
11026 +#define ADM9240_REG_THYST 0x3A
11027 +#define ADM9240_REG_FAN1_MIN 0x3B
11028 +#define ADM9240_REG_FAN2_MIN 0x3C
11029 +
11030 +#define ADM9240_REG_CONFIG 0x40
11031 +#define ADM9240_REG_INT1_STAT 0x41
11032 +#define ADM9240_REG_INT2_STAT 0x42
11033 +#define ADM9240_REG_INT1_MASK 0x43
11034 +#define ADM9240_REG_INT2_MASK 0x44
11035 +
11036 +#define ADM9240_REG_COMPAT 0x45        /* dummy compat. register for other drivers? */
11037 +#define ADM9240_REG_CHASSIS_CLEAR 0x46
11038 +#define ADM9240_REG_VID_FAN_DIV 0x47
11039 +#define ADM9240_REG_I2C_ADDR 0x48
11040 +#define ADM9240_REG_VID4 0x49
11041 +#define ADM9240_REG_TEMP_CONFIG 0x4B
11042 +#define ADM9240_REG_EXTMODE1 0x4C      /* LM81 only - not supported */
11043 +#define ADM9240_REG_EXTMODE2 0x4D      /* LM81 only - not supported */
11044 +
11045 +/* Conversions. Rounding and limit checking is only done on the TO_REG
11046 +   variants. Note that you should be a bit careful with which arguments
11047 +   these macros are called: arguments may be evaluated more than once.
11048 +   Fixing this is just not worth it. */
11049 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT((val), 0, 255))
11050 +#define IN_FROM_REG(val,nr) (val)
11051 +
11052 +static inline u8 FAN_TO_REG(long rpm, int div)
11053 +{
11054 +       if (rpm == 0)
11055 +               return 255;
11056 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
11057 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
11058 +                            254);
11059 +}
11060 +
11061 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
11062 +                               (val)==255?0:1350000/((div)*(val)))
11063 +
11064 +#define TEMP_FROM_REG(temp) ((temp)<256 ? (temp) * 5 : \
11065 +                             ((temp) - 512) * 5)
11066 +
11067 +#define TEMP_LIMIT_FROM_REG(val) (((val)>=0x80?(val)-0x100:(val))*10)
11068 +
11069 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10)+256:\
11070 +                                                      ((val)+5)/10), \
11071 +                                             0,255)
11072 +
11073 +#define ALARMS_FROM_REG(val) (val)
11074 +
11075 +#define DIV_FROM_REG(val) (1 << (val))
11076 +#define DIV_TO_REG(val) ((val)==1?0:((val)==8?3:((val)==4?2:1)))
11077 +
11078 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
11079 +                           205-(val)*5)
11080 +
11081 +/* For each registered ADM9240, we need to keep some data in memory. */
11082 +struct adm9240_data {
11083 +       struct i2c_client client;
11084 +       int sysctl_id;
11085 +       enum chips type;
11086 +
11087 +       struct semaphore update_lock;
11088 +       char valid;             /* !=0 if following fields are valid */
11089 +       unsigned long last_updated;     /* In jiffies */
11090 +
11091 +       u8 in[6];               /* Register value */
11092 +       u8 in_max[6];           /* Register value */
11093 +       u8 in_min[6];           /* Register value */
11094 +       u8 fan[2];              /* Register value */
11095 +       u8 fan_min[2];          /* Register value */
11096 +       u8 fan_div[2];          /* Register encoding, shifted right */
11097 +       int temp;               /* Temp, shifted right */
11098 +       u8 temp_os_max;         /* Register value */
11099 +       u8 temp_os_hyst;        /* Register value */
11100 +       u16 alarms;             /* Register encoding, combined */
11101 +       u8 analog_out;          /* Register value */
11102 +       u8 vid;                 /* Register value combined */
11103 +};
11104 +
11105 +
11106 +static int adm9240_attach_adapter(struct i2c_adapter *adapter);
11107 +static int adm9240_detect(struct i2c_adapter *adapter, int address,
11108 +                         unsigned short flags, int kind);
11109 +static int adm9240_detach_client(struct i2c_client *client);
11110 +
11111 +static int adm9240_read_value(struct i2c_client *client, u8 reg);
11112 +static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value);
11113 +static void adm9240_update_client(struct i2c_client *client);
11114 +static void adm9240_init_client(struct i2c_client *client);
11115 +
11116 +
11117 +static void adm9240_in(struct i2c_client *client, int operation,
11118 +                      int ctl_name, int *nrels_mag, long *results);
11119 +static void adm9240_fan(struct i2c_client *client, int operation,
11120 +                       int ctl_name, int *nrels_mag, long *results);
11121 +static void adm9240_temp(struct i2c_client *client, int operation,
11122 +                        int ctl_name, int *nrels_mag, long *results);
11123 +static void adm9240_alarms(struct i2c_client *client, int operation,
11124 +                          int ctl_name, int *nrels_mag, long *results);
11125 +static void adm9240_fan_div(struct i2c_client *client, int operation,
11126 +                           int ctl_name, int *nrels_mag, long *results);
11127 +static void adm9240_analog_out(struct i2c_client *client, int operation,
11128 +                              int ctl_name, int *nrels_mag,
11129 +                              long *results);
11130 +static void adm9240_vid(struct i2c_client *client, int operation,
11131 +                       int ctl_name, int *nrels_mag, long *results);
11132 +
11133 +static int adm9240_id = 0;
11134 +
11135 +static struct i2c_driver adm9240_driver = {
11136 +       .owner          = THIS_MODULE,
11137 +       .name           = "ADM9240 sensor driver",
11138 +       .id             = I2C_DRIVERID_ADM9240,
11139 +       .flags          = I2C_DF_NOTIFY,
11140 +       .attach_adapter = adm9240_attach_adapter,
11141 +       .detach_client  = adm9240_detach_client,
11142 +};
11143 +
11144 +/* The /proc/sys entries */
11145 +
11146 +/* -- SENSORS SYSCTL START -- */
11147 +
11148 +#define ADM9240_SYSCTL_IN0 1000        /* Volts * 100 */
11149 +#define ADM9240_SYSCTL_IN1 1001
11150 +#define ADM9240_SYSCTL_IN2 1002
11151 +#define ADM9240_SYSCTL_IN3 1003
11152 +#define ADM9240_SYSCTL_IN4 1004
11153 +#define ADM9240_SYSCTL_IN5 1005
11154 +#define ADM9240_SYSCTL_FAN1 1101       /* Rotations/min */
11155 +#define ADM9240_SYSCTL_FAN2 1102
11156 +#define ADM9240_SYSCTL_TEMP 1250       /* Degrees Celcius * 100 */
11157 +#define ADM9240_SYSCTL_FAN_DIV 2000    /* 1, 2, 4 or 8 */
11158 +#define ADM9240_SYSCTL_ALARMS 2001     /* bitvector */
11159 +#define ADM9240_SYSCTL_ANALOG_OUT 2002
11160 +#define ADM9240_SYSCTL_VID 2003
11161 +
11162 +#define ADM9240_ALARM_IN0 0x0001
11163 +#define ADM9240_ALARM_IN1 0x0002
11164 +#define ADM9240_ALARM_IN2 0x0004
11165 +#define ADM9240_ALARM_IN3 0x0008
11166 +#define ADM9240_ALARM_IN4 0x0100
11167 +#define ADM9240_ALARM_IN5 0x0200
11168 +#define ADM9240_ALARM_FAN1 0x0040
11169 +#define ADM9240_ALARM_FAN2 0x0080
11170 +#define ADM9240_ALARM_TEMP 0x0010
11171 +#define ADM9240_ALARM_CHAS 0x1000
11172 +
11173 +/* -- SENSORS SYSCTL END -- */
11174 +
11175 +/* These files are created for each detected ADM9240. This is just a template;
11176 +   though at first sight, you might think we could use a statically
11177 +   allocated list, we need some way to get back to the parent - which
11178 +   is done through one of the 'extra' fields which are initialized 
11179 +   when a new copy is allocated. */
11180 +static ctl_table adm9240_dir_table_template[] = {
11181 +       {ADM9240_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
11182 +        &i2c_sysctl_real, NULL, &adm9240_in},
11183 +       {ADM9240_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
11184 +        &i2c_sysctl_real, NULL, &adm9240_in},
11185 +       {ADM9240_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
11186 +        &i2c_sysctl_real, NULL, &adm9240_in},
11187 +       {ADM9240_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
11188 +        &i2c_sysctl_real, NULL, &adm9240_in},
11189 +       {ADM9240_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
11190 +        &i2c_sysctl_real, NULL, &adm9240_in},
11191 +       {ADM9240_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
11192 +        &i2c_sysctl_real, NULL, &adm9240_in},
11193 +       {ADM9240_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
11194 +        &i2c_sysctl_real, NULL, &adm9240_fan},
11195 +       {ADM9240_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
11196 +        &i2c_sysctl_real, NULL, &adm9240_fan},
11197 +       {ADM9240_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
11198 +        &i2c_sysctl_real, NULL, &adm9240_temp},
11199 +       {ADM9240_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
11200 +        &i2c_sysctl_real, NULL, &adm9240_fan_div},
11201 +       {ADM9240_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
11202 +        &i2c_sysctl_real, NULL, &adm9240_alarms},
11203 +       {ADM9240_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL, &i2c_proc_real,
11204 +        &i2c_sysctl_real, NULL, &adm9240_analog_out},
11205 +       {ADM9240_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
11206 +        &i2c_sysctl_real, NULL, &adm9240_vid},
11207 +       {0}
11208 +};
11209 +
11210 +static int adm9240_attach_adapter(struct i2c_adapter *adapter)
11211 +{
11212 +       return i2c_detect(adapter, &addr_data, adm9240_detect);
11213 +}
11214 +
11215 +static int adm9240_detect(struct i2c_adapter *adapter, int address,
11216 +                         unsigned short flags, int kind)
11217 +{
11218 +       int i;
11219 +       struct i2c_client *new_client;
11220 +       struct adm9240_data *data;
11221 +       int err = 0;
11222 +       const char *type_name = "";
11223 +       const char *client_name = "";
11224 +
11225 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
11226 +               goto ERROR0;
11227 +
11228 +       /* OK. For now, we presume we have a valid client. We now create the
11229 +          client structure, even though we cannot fill it completely yet.
11230 +          But it allows us to access adm9240_{read,write}_value. */
11231 +
11232 +       if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
11233 +               err = -ENOMEM;
11234 +               goto ERROR0;
11235 +       }
11236 +
11237 +
11238 +       new_client = &data->client;
11239 +       new_client->addr = address;
11240 +       new_client->data = data;
11241 +       new_client->adapter = adapter;
11242 +       new_client->driver = &adm9240_driver;
11243 +       new_client->flags = 0;
11244 +
11245 +       /* Now, we do the remaining detection. */
11246 +
11247 +       if (kind < 0) {
11248 +               if (
11249 +                   ((adm9240_read_value
11250 +                     (new_client, ADM9240_REG_CONFIG) & 0x80) != 0x00)
11251 +                   ||
11252 +                   (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
11253 +                    != address))
11254 +                       goto ERROR1;
11255 +       }
11256 +
11257 +       /* Determine the chip type. */
11258 +       if (kind <= 0) {
11259 +               i = adm9240_read_value(new_client, ADM9240_REG_COMPANY_ID);
11260 +               if (i == 0x23)
11261 +                       kind = adm9240;
11262 +               else if (i == 0xda)
11263 +                       kind = ds1780;
11264 +               else if (i == 0x01)
11265 +                       kind = lm81;
11266 +               else {
11267 +                       if (kind == 0)
11268 +                               printk
11269 +                                   ("adm9240.o: Ignoring 'force' parameter for unknown chip at "
11270 +                                    "adapter %d, address 0x%02x\n",
11271 +                                    i2c_adapter_id(adapter), address);
11272 +                       goto ERROR1;
11273 +               }
11274 +       }
11275 +
11276 +       if (kind == adm9240) {
11277 +               type_name = "adm9240";
11278 +               client_name = "ADM9240 chip";
11279 +       } else if (kind == ds1780) {
11280 +               type_name = "ds1780";
11281 +               client_name = "DS1780 chip";
11282 +       } else if (kind == lm81) {
11283 +               type_name = "lm81";
11284 +               client_name = "LM81 chip";
11285 +       } else {
11286 +#ifdef DEBUG
11287 +               printk("adm9240.o: Internal error: unknown kind (%d)?!?",
11288 +                      kind);
11289 +#endif
11290 +               goto ERROR1;
11291 +       }
11292 +
11293 +       /* Fill in the remaining client fields and put it into the global list */
11294 +       strcpy(new_client->name, client_name);
11295 +       data->type = kind;
11296 +
11297 +       new_client->id = adm9240_id++;
11298 +       data->valid = 0;
11299 +       init_MUTEX(&data->update_lock);
11300 +
11301 +       /* Tell the I2C layer a new client has arrived */
11302 +       if ((err = i2c_attach_client(new_client)))
11303 +               goto ERROR3;
11304 +
11305 +       /* Register a new directory entry with module sensors */
11306 +       if ((i = i2c_register_entry(new_client,
11307 +                                       type_name,
11308 +                                       adm9240_dir_table_template)) < 0) {
11309 +               err = i;
11310 +               goto ERROR4;
11311 +       }
11312 +       data->sysctl_id = i;
11313 +
11314 +       /* Initialize the ADM9240 chip */
11315 +       adm9240_init_client(new_client);
11316 +       return 0;
11317 +
11318 +/* OK, this is not exactly good programming practice, usually. But it is
11319 +   very code-efficient in this case. */
11320 +
11321 +      ERROR4:
11322 +       i2c_detach_client(new_client);
11323 +      ERROR3:
11324 +      ERROR1:
11325 +       kfree(data);
11326 +      ERROR0:
11327 +       return err;
11328 +}
11329 +
11330 +static int adm9240_detach_client(struct i2c_client *client)
11331 +{
11332 +       int err;
11333 +
11334 +       i2c_deregister_entry(((struct adm9240_data *) (client->data))->
11335 +                                sysctl_id);
11336 +
11337 +       if ((err = i2c_detach_client(client))) {
11338 +               printk
11339 +                   ("adm9240.o: Client deregistration failed, client not detached.\n");
11340 +               return err;
11341 +       }
11342 +
11343 +       kfree(client->data);
11344 +
11345 +       return 0;
11346 +}
11347 +
11348 +
11349 +static int adm9240_read_value(struct i2c_client *client, u8 reg)
11350 +{
11351 +       return i2c_smbus_read_byte_data(client, reg);
11352 +}
11353 +
11354 +static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
11355 +{
11356 +       return i2c_smbus_write_byte_data(client, reg, value);
11357 +}
11358 +
11359 +/* Called when we have found a new ADM9240. */
11360 +static void adm9240_init_client(struct i2c_client *client)
11361 +{
11362 +       /* Start monitoring */
11363 +       adm9240_write_value(client, ADM9240_REG_CONFIG, 0x01);
11364 +}
11365 +
11366 +static void adm9240_update_client(struct i2c_client *client)
11367 +{
11368 +       struct adm9240_data *data = client->data;
11369 +       u8 i;
11370 +
11371 +       down(&data->update_lock);
11372 +
11373 +       if (
11374 +           (jiffies - data->last_updated >
11375 +            (data->type == adm9240 ? HZ / 2 : HZ * 2))
11376 +           || (jiffies < data->last_updated) || !data->valid) {
11377 +
11378 +#ifdef DEBUG
11379 +               printk("Starting adm9240 update\n");
11380 +#endif
11381 +               for (i = 0; i <= 5; i++) {
11382 +                       data->in[i] =
11383 +                           adm9240_read_value(client, ADM9240_REG_IN(i));
11384 +                       data->in_min[i] =
11385 +                           adm9240_read_value(client,
11386 +                                              ADM9240_REG_IN_MIN(i));
11387 +                       data->in_max[i] =
11388 +                           adm9240_read_value(client,
11389 +                                              ADM9240_REG_IN_MAX(i));
11390 +               }
11391 +               data->fan[0] =
11392 +                   adm9240_read_value(client, ADM9240_REG_FAN1);
11393 +               data->fan_min[0] =
11394 +                   adm9240_read_value(client, ADM9240_REG_FAN1_MIN);
11395 +               data->fan[1] =
11396 +                   adm9240_read_value(client, ADM9240_REG_FAN2);
11397 +               data->fan_min[1] =
11398 +                   adm9240_read_value(client, ADM9240_REG_FAN2_MIN);
11399 +               data->temp =
11400 +                   (adm9240_read_value(client, ADM9240_REG_TEMP) << 1) +
11401 +                   ((adm9240_read_value
11402 +                     (client, ADM9240_REG_TEMP_CONFIG) & 0x80) >> 7);
11403 +               data->temp_os_max =
11404 +                   adm9240_read_value(client, ADM9240_REG_TOS);
11405 +               data->temp_os_hyst =
11406 +                   adm9240_read_value(client, ADM9240_REG_THYST);
11407 +
11408 +               i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
11409 +               data->fan_div[0] = (i >> 4) & 0x03;
11410 +               data->fan_div[1] = (i >> 6) & 0x03;
11411 +               data->vid = i & 0x0f;
11412 +               data->vid |=
11413 +                   (adm9240_read_value(client, ADM9240_REG_VID4) & 0x01)
11414 +                   << 4;
11415 +
11416 +               data->alarms =
11417 +                   adm9240_read_value(client,
11418 +                                      ADM9240_REG_INT1_STAT) +
11419 +                   (adm9240_read_value(client, ADM9240_REG_INT2_STAT) <<
11420 +                    8);
11421 +               data->analog_out =
11422 +                   adm9240_read_value(client, ADM9240_REG_ANALOG_OUT);
11423 +               data->last_updated = jiffies;
11424 +               data->valid = 1;
11425 +       }
11426 +
11427 +       up(&data->update_lock);
11428 +}
11429 +
11430 +
11431 +/* The next few functions are the call-back functions of the /proc/sys and
11432 +   sysctl files. Which function is used is defined in the ctl_table in
11433 +   the extra1 field.
11434 +   Each function must return the magnitude (power of 10 to divide the date
11435 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
11436 +   put a maximum of *nrels elements in results reflecting the data of this
11437 +   file, and set *nrels to the number it actually put in it, if operation==
11438 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
11439 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
11440 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
11441 +   large enough (by checking the incoming value of *nrels). This is not very
11442 +   good practice, but as long as you put less than about 5 values in results,
11443 +   you can assume it is large enough. */
11444 +void adm9240_in(struct i2c_client *client, int operation, int ctl_name,
11445 +               int *nrels_mag, long *results)
11446 +{
11447 +
11448 +       int scales[6] = { 250, 270, 330, 500, 1200, 270 };
11449 +
11450 +       struct adm9240_data *data = client->data;
11451 +       int nr = ctl_name - ADM9240_SYSCTL_IN0;
11452 +
11453 +       if (operation == SENSORS_PROC_REAL_INFO)
11454 +               *nrels_mag = 2;
11455 +       else if (operation == SENSORS_PROC_REAL_READ) {
11456 +               adm9240_update_client(client);
11457 +               results[0] =
11458 +                   IN_FROM_REG(data->in_min[nr], nr) * scales[nr] / 192;
11459 +               results[1] =
11460 +                   IN_FROM_REG(data->in_max[nr], nr) * scales[nr] / 192;
11461 +               results[2] =
11462 +                   IN_FROM_REG(data->in[nr], nr) * scales[nr] / 192;
11463 +               *nrels_mag = 3;
11464 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
11465 +               if (*nrels_mag >= 1) {
11466 +                       data->in_min[nr] =
11467 +                           IN_TO_REG((results[0] * 192) / scales[nr], nr);
11468 +                       adm9240_write_value(client, ADM9240_REG_IN_MIN(nr),
11469 +                                           data->in_min[nr]);
11470 +               }
11471 +               if (*nrels_mag >= 2) {
11472 +                       data->in_max[nr] =
11473 +                           IN_TO_REG((results[1] * 192) / scales[nr], nr);
11474 +                       adm9240_write_value(client, ADM9240_REG_IN_MAX(nr),
11475 +                                           data->in_max[nr]);
11476 +               }
11477 +       }
11478 +}
11479 +
11480 +void adm9240_fan(struct i2c_client *client, int operation, int ctl_name,
11481 +                int *nrels_mag, long *results)
11482 +{
11483 +       struct adm9240_data *data = client->data;
11484 +       int nr = ctl_name - ADM9240_SYSCTL_FAN1 + 1;
11485 +
11486 +       if (operation == SENSORS_PROC_REAL_INFO)
11487 +               *nrels_mag = 0;
11488 +       else if (operation == SENSORS_PROC_REAL_READ) {
11489 +               adm9240_update_client(client);
11490 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
11491 +                                         DIV_FROM_REG(data->
11492 +                                                      fan_div[nr - 1]));
11493 +               results[1] =
11494 +                   FAN_FROM_REG(data->fan[nr - 1],
11495 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
11496 +               *nrels_mag = 2;
11497 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
11498 +               if (*nrels_mag >= 1) {
11499 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0],
11500 +                                                          DIV_FROM_REG
11501 +                                                          (data->
11502 +                                                           fan_div[nr -
11503 +                                                                   1]));
11504 +                       adm9240_write_value(client,
11505 +                                           nr ==
11506 +                                           1 ? ADM9240_REG_FAN1_MIN :
11507 +                                           ADM9240_REG_FAN2_MIN,
11508 +                                           data->fan_min[nr - 1]);
11509 +               }
11510 +       }
11511 +}
11512 +
11513 +
11514 +void adm9240_temp(struct i2c_client *client, int operation, int ctl_name,
11515 +                 int *nrels_mag, long *results)
11516 +{
11517 +       struct adm9240_data *data = client->data;
11518 +       if (operation == SENSORS_PROC_REAL_INFO)
11519 +               *nrels_mag = 1;
11520 +       else if (operation == SENSORS_PROC_REAL_READ) {
11521 +               adm9240_update_client(client);
11522 +               results[0] = TEMP_LIMIT_FROM_REG(data->temp_os_max);
11523 +               results[1] = TEMP_LIMIT_FROM_REG(data->temp_os_hyst);
11524 +               results[2] = TEMP_FROM_REG(data->temp);
11525 +               *nrels_mag = 3;
11526 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
11527 +               if (*nrels_mag >= 1) {
11528 +                       data->temp_os_max = TEMP_LIMIT_TO_REG(results[0]);
11529 +                       adm9240_write_value(client, ADM9240_REG_TOS,
11530 +                                           data->temp_os_max);
11531 +               }
11532 +               if (*nrels_mag >= 2) {
11533 +                       data->temp_os_hyst = TEMP_LIMIT_TO_REG(results[1]);
11534 +                       adm9240_write_value(client, ADM9240_REG_THYST,
11535 +                                           data->temp_os_hyst);
11536 +               }
11537 +       }
11538 +}
11539 +
11540 +void adm9240_alarms(struct i2c_client *client, int operation, int ctl_name,
11541 +                   int *nrels_mag, long *results)
11542 +{
11543 +       struct adm9240_data *data = client->data;
11544 +       if (operation == SENSORS_PROC_REAL_INFO)
11545 +               *nrels_mag = 0;
11546 +       else if (operation == SENSORS_PROC_REAL_READ) {
11547 +               adm9240_update_client(client);
11548 +               results[0] = ALARMS_FROM_REG(data->alarms);
11549 +               *nrels_mag = 1;
11550 +       }
11551 +}
11552 +
11553 +void adm9240_fan_div(struct i2c_client *client, int operation,
11554 +                    int ctl_name, int *nrels_mag, long *results)
11555 +{
11556 +       struct adm9240_data *data = client->data;
11557 +       int old;
11558 +
11559 +       if (operation == SENSORS_PROC_REAL_INFO)
11560 +               *nrels_mag = 0;
11561 +       else if (operation == SENSORS_PROC_REAL_READ) {
11562 +               adm9240_update_client(client);
11563 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
11564 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
11565 +               *nrels_mag = 2;
11566 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
11567 +               old = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
11568 +               if (*nrels_mag >= 2) {
11569 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
11570 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
11571 +               }
11572 +               if (*nrels_mag >= 1) {
11573 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
11574 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
11575 +                       adm9240_write_value(client,
11576 +                                           ADM9240_REG_VID_FAN_DIV, old);
11577 +               }
11578 +       }
11579 +}
11580 +
11581 +void adm9240_analog_out(struct i2c_client *client, int operation,
11582 +                       int ctl_name, int *nrels_mag, long *results)
11583 +{
11584 +       struct adm9240_data *data = client->data;
11585 +
11586 +       if (operation == SENSORS_PROC_REAL_INFO)
11587 +               *nrels_mag = 0;
11588 +       else if (operation == SENSORS_PROC_REAL_READ) {
11589 +               adm9240_update_client(client);
11590 +               results[0] = data->analog_out;
11591 +               *nrels_mag = 1;
11592 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
11593 +               if (*nrels_mag >= 1) {
11594 +                       data->analog_out = results[0];
11595 +                       adm9240_write_value(client, ADM9240_REG_ANALOG_OUT,
11596 +                                           data->analog_out);
11597 +               }
11598 +       }
11599 +}
11600 +
11601 +void adm9240_vid(struct i2c_client *client, int operation, int ctl_name,
11602 +                int *nrels_mag, long *results)
11603 +{
11604 +       struct adm9240_data *data = client->data;
11605 +
11606 +       if (operation == SENSORS_PROC_REAL_INFO)
11607 +               *nrels_mag = 2;
11608 +       else if (operation == SENSORS_PROC_REAL_READ) {
11609 +               adm9240_update_client(client);
11610 +               results[0] = VID_FROM_REG(data->vid);
11611 +               *nrels_mag = 1;
11612 +       }
11613 +}
11614 +
11615 +static int __init sm_adm9240_init(void)
11616 +{
11617 +       printk("adm9240.o version %s (%s)\n", LM_VERSION, LM_DATE);
11618 +       return i2c_add_driver(&adm9240_driver);
11619 +}
11620 +
11621 +static void __exit sm_adm9240_exit(void)
11622 +{
11623 +       i2c_del_driver(&adm9240_driver);
11624 +}
11625 +
11626 +
11627 +
11628 +MODULE_AUTHOR
11629 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
11630 +MODULE_LICENSE("GPL");
11631 +MODULE_DESCRIPTION("ADM9240 driver");
11632 +
11633 +module_init(sm_adm9240_init);
11634 +module_exit(sm_adm9240_exit);
11635 --- linux-old/drivers/sensors/asb100.c  Thu Jan  1 00:00:00 1970
11636 +++ linux/drivers/sensors/asb100.c      Mon Dec 13 20:18:45 2004
11637 @@ -0,0 +1,1025 @@
11638 +/*
11639 +    asb100.c - Part of lm_sensors, Linux kernel modules for hardware
11640 +                monitoring
11641 +
11642 +    Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
11643 +
11644 +       (derived from w83781d.c)
11645 +
11646 +    Copyright (c) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
11647 +    Philip Edelbrock <phil@netroedge.com>, and
11648 +    Mark Studebaker <mdsxyz123@yahoo.com>
11649 +
11650 +    This program is free software; you can redistribute it and/or modify
11651 +    it under the terms of the GNU General Public License as published by
11652 +    the Free Software Foundation; either version 2 of the License, or
11653 +    (at your option) any later version.
11654 +
11655 +    This program is distributed in the hope that it will be useful,
11656 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
11657 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11658 +    GNU General Public License for more details.
11659 +
11660 +    You should have received a copy of the GNU General Public License
11661 +    along with this program; if not, write to the Free Software
11662 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11663 +*/
11664 +
11665 +/*
11666 +    This driver supports the hardware sensor chips: Asus ASB100 and
11667 +    ASB100-A "BACH".
11668 +
11669 +    ASB100-A supports pwm1, while plain ASB100 does not.  There is no known
11670 +    way for the driver to tell which one is there.
11671 +
11672 +    Chip       #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
11673 +    asb100     7       3       1       4       0x31    0x0694  yes     no
11674 +*/
11675 +
11676 +//#define DEBUG 1
11677 +
11678 +#include <linux/module.h>
11679 +#include <linux/slab.h>
11680 +#include <linux/i2c.h>
11681 +#include <linux/i2c-proc.h>
11682 +#include <linux/init.h>
11683 +#define LM_DATE "20041007"
11684 +#define LM_VERSION "2.8.8"
11685 +#include <linux/sensors_vid.h>
11686 +#include "lm75.h"
11687 +
11688 +#ifndef I2C_DRIVERID_ASB100
11689 +#define I2C_DRIVERID_ASB100            1043
11690 +#endif
11691 +
11692 +/* I2C addresses to scan */
11693 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
11694 +static unsigned short normal_i2c_range[] = { 0x28, 0x2f, SENSORS_I2C_END };
11695 +
11696 +/* ISA addresses to scan (none) */
11697 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
11698 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
11699 +
11700 +/* default VRM to 9.0 instead of 8.2 */
11701 +#define ASB100_DEFAULT_VRM 90
11702 +
11703 +/* Insmod parameters */
11704 +SENSORS_INSMOD_1(asb100);
11705 +SENSORS_MODULE_PARM(force_subclients, "List of subclient addresses: " \
11706 +       "{bus, clientaddr, subclientaddr1, subclientaddr2}");
11707 +
11708 +/* Voltage IN registers 0-6 */
11709 +#define ASB100_REG_IN(nr)     (0x20 + (nr))
11710 +#define ASB100_REG_IN_MAX(nr) (0x2b + (nr * 2))
11711 +#define ASB100_REG_IN_MIN(nr) (0x2c + (nr * 2))
11712 +
11713 +/* FAN IN registers 1-3 */
11714 +#define ASB100_REG_FAN(nr)     (0x27 + (nr))
11715 +#define ASB100_REG_FAN_MIN(nr) (0x3a + (nr))
11716 +
11717 +/* TEMPERATURE registers 1-4 */
11718 +static const u16 asb100_reg_temp[]     = {0, 0x27, 0x150, 0x250, 0x17};
11719 +static const u16 asb100_reg_temp_max[] = {0, 0x39, 0x155, 0x255, 0x18};
11720 +static const u16 asb100_reg_temp_hyst[]        = {0, 0x3a, 0x153, 0x253, 0x19};
11721 +
11722 +#define ASB100_REG_TEMP(nr) (asb100_reg_temp[nr])
11723 +#define ASB100_REG_TEMP_MAX(nr) (asb100_reg_temp_max[nr])
11724 +#define ASB100_REG_TEMP_HYST(nr) (asb100_reg_temp_hyst[nr])
11725 +
11726 +#define ASB100_REG_TEMP2_CONFIG        0x0152
11727 +#define ASB100_REG_TEMP3_CONFIG        0x0252
11728 +
11729 +
11730 +#define ASB100_REG_CONFIG      0x40
11731 +#define ASB100_REG_ALARM1      0x41
11732 +#define ASB100_REG_ALARM2      0x42
11733 +#define ASB100_REG_SMIM1       0x43
11734 +#define ASB100_REG_SMIM2       0x44
11735 +#define ASB100_REG_VID_FANDIV  0x47
11736 +#define ASB100_REG_I2C_ADDR    0x48
11737 +#define ASB100_REG_CHIPID      0x49
11738 +#define ASB100_REG_I2C_SUBADDR 0x4a
11739 +#define ASB100_REG_PIN         0x4b
11740 +#define ASB100_REG_IRQ         0x4c
11741 +#define ASB100_REG_BANK                0x4e
11742 +#define ASB100_REG_CHIPMAN     0x4f
11743 +
11744 +#define ASB100_REG_WCHIPID     0x58
11745 +
11746 +/* bit 7 -> enable, bits 0-3 -> duty cycle */
11747 +#define ASB100_REG_PWM1                0x59
11748 +
11749 +/* CONVERSIONS
11750 +   Rounding and limit checking is only done on the TO_REG variants. */
11751 +
11752 +/* These constants are a guess, consistent w/ w83781d */
11753 +#define ASB100_IN_MIN (  0)
11754 +#define ASB100_IN_MAX (408)
11755 +
11756 +/* IN: 1/100 V (0V to 4.08V)
11757 +   REG: 16mV/bit */
11758 +static u8 IN_TO_REG(unsigned val)
11759 +{
11760 +       unsigned nval = SENSORS_LIMIT(val, ASB100_IN_MIN, ASB100_IN_MAX);
11761 +       return (nval * 10 + 8) / 16;
11762 +}
11763 +
11764 +static unsigned IN_FROM_REG(u8 reg)
11765 +{
11766 +       return (reg * 16 + 5) / 10;
11767 +}
11768 +
11769 +static u8 FAN_TO_REG(long rpm, int div)
11770 +{
11771 +       if (rpm == 0)
11772 +               return 255;
11773 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
11774 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
11775 +}
11776 +
11777 +static int FAN_FROM_REG(u8 val, int div)
11778 +{
11779 +       return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
11780 +}
11781 +
11782 +/* These constants are a guess, consistent w/ w83781d */
11783 +#define ASB100_TEMP_MIN (-1280)
11784 +#define ASB100_TEMP_MAX ( 1270)
11785 +
11786 +/* TEMP: 1/10 degrees C (-128C to +127C)
11787 +   REG: 1C/bit, two's complement */
11788 +static u8 TEMP_TO_REG(int temp)
11789 +{
11790 +       int ntemp = SENSORS_LIMIT(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX);
11791 +       ntemp += (ntemp<0 ? -5 : 5);
11792 +       return (u8)(ntemp / 10);
11793 +}
11794 +
11795 +static int TEMP_FROM_REG(u8 reg)
11796 +{
11797 +       return (s8)reg * 10;
11798 +}
11799 +
11800 +/* PWM: 0 - 255 per sensors documentation
11801 +   REG: (6.25% duty cycle per bit) */
11802 +static u8 ASB100_PWM_TO_REG(int pwm)
11803 +{
11804 +       pwm = SENSORS_LIMIT(pwm, 0, 255);
11805 +       return (u8)(pwm / 16);
11806 +}
11807 +
11808 +static int ASB100_PWM_FROM_REG(u8 reg)
11809 +{
11810 +       return reg * 16;
11811 +}
11812 +
11813 +#define ALARMS_FROM_REG(val) (val)
11814 +
11815 +#define DIV_FROM_REG(val) (1 << (val))
11816 +
11817 +/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
11818 +   REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
11819 +static u8 DIV_TO_REG(long val)
11820 +{
11821 +       return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
11822 +}
11823 +
11824 +/* For each registered client, we need to keep some data in memory. That
11825 +   data is pointed to by client->data. The structure itself is
11826 +   dynamically allocated, at the same time the client itself is allocated. */
11827 +struct asb100_data {
11828 +       struct i2c_client client;
11829 +       struct semaphore lock;
11830 +       int sysctl_id;
11831 +       enum chips type;
11832 +
11833 +       struct semaphore update_lock;
11834 +       unsigned long last_updated;     /* In jiffies */
11835 +
11836 +       /* array of 2 pointers to subclients */
11837 +       struct i2c_client *lm75[2];
11838 +
11839 +       char valid;             /* !=0 if following fields are valid */
11840 +       u8 in[7];               /* Register value */
11841 +       u8 in_max[7];           /* Register value */
11842 +       u8 in_min[7];           /* Register value */
11843 +       u8 fan[3];              /* Register value */
11844 +       u8 fan_min[3];          /* Register value */
11845 +       u16 temp[4];            /* Register value (0 and 3 are u8 only) */
11846 +       u16 temp_max[4];        /* Register value (0 and 3 are u8 only) */
11847 +       u16 temp_hyst[4];       /* Register value (0 and 3 are u8 only) */
11848 +       u8 fan_div[3];          /* Register encoding, right justified */
11849 +       u8 pwm;                 /* Register encoding */
11850 +       u8 vid;                 /* Register encoding, combined */
11851 +       u32 alarms;             /* Register encoding, combined */
11852 +       u8 vrm;
11853 +};
11854 +
11855 +static int asb100_attach_adapter(struct i2c_adapter *adapter);
11856 +static int asb100_detect(struct i2c_adapter *adapter, int address,
11857 +               unsigned short flags, int kind);
11858 +static int asb100_detach_client(struct i2c_client *client);
11859 +
11860 +static int asb100_read_value(struct i2c_client *client, u16 reg);
11861 +static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val);
11862 +static void asb100_update_client(struct i2c_client *client);
11863 +static void asb100_init_client(struct i2c_client *client);
11864 +
11865 +static void asb100_in(struct i2c_client *client, int operation,
11866 +               int ctl_name, int *nrels_mag, long *results);
11867 +static void asb100_fan(struct i2c_client *client, int operation,
11868 +               int ctl_name, int *nrels_mag, long *results);
11869 +static void asb100_temp(struct i2c_client *client, int operation,
11870 +               int ctl_name, int *nrels_mag, long *results);
11871 +static void asb100_temp_add(struct i2c_client *client, int operation,
11872 +               int ctl_name, int *nrels_mag, long *results);
11873 +static void asb100_vid(struct i2c_client *client, int operation,
11874 +               int ctl_name, int *nrels_mag, long *results);
11875 +static void asb100_vrm(struct i2c_client *client, int operation,
11876 +               int ctl_name, int *nrels_mag, long *results);
11877 +static void asb100_alarms(struct i2c_client *client, int operation,
11878 +               int ctl_name, int *nrels_mag, long *results);
11879 +static void asb100_fan_div(struct i2c_client *client, int operation,
11880 +               int ctl_name, int *nrels_mag, long *results);
11881 +static void asb100_pwm(struct i2c_client *client, int operation,
11882 +               int ctl_name, int *nrels_mag, long *results);
11883 +
11884 +static struct i2c_driver asb100_driver = {
11885 +       .owner          = THIS_MODULE,
11886 +       .name           = "asb100",
11887 +       .id             = I2C_DRIVERID_ASB100,
11888 +       .flags          = I2C_DF_NOTIFY,
11889 +       .attach_adapter = asb100_attach_adapter,
11890 +       .detach_client  = asb100_detach_client,
11891 +};
11892 +
11893 +/* The /proc/sys entries */
11894 +/* -- SENSORS SYSCTL START -- */
11895 +
11896 +#define ASB100_SYSCTL_IN0      1000    /* Volts * 100 */
11897 +#define ASB100_SYSCTL_IN1      1001
11898 +#define ASB100_SYSCTL_IN2      1002
11899 +#define ASB100_SYSCTL_IN3      1003
11900 +#define ASB100_SYSCTL_IN4      1004
11901 +#define ASB100_SYSCTL_IN5      1005
11902 +#define ASB100_SYSCTL_IN6      1006
11903 +
11904 +#define ASB100_SYSCTL_FAN1     1101    /* Rotations/min */
11905 +#define ASB100_SYSCTL_FAN2     1102
11906 +#define ASB100_SYSCTL_FAN3     1103
11907 +
11908 +#define ASB100_SYSCTL_TEMP1    1200    /* Degrees Celcius * 10 */
11909 +#define ASB100_SYSCTL_TEMP2    1201
11910 +#define ASB100_SYSCTL_TEMP3    1202
11911 +#define ASB100_SYSCTL_TEMP4    1203
11912 +
11913 +#define ASB100_SYSCTL_VID      1300    /* Volts * 1000 */
11914 +#define ASB100_SYSCTL_VRM      1301
11915 +
11916 +#define ASB100_SYSCTL_PWM1     1401    /* 0-255 => 0-100% duty cycle */
11917 +
11918 +#define ASB100_SYSCTL_FAN_DIV  2000    /* 1, 2, 4 or 8 */
11919 +#define ASB100_SYSCTL_ALARMS   2001    /* bitvector */
11920 +
11921 +#define ASB100_ALARM_IN0       0x0001  /* ? */
11922 +#define ASB100_ALARM_IN1       0x0002  /* ? */
11923 +#define ASB100_ALARM_IN2       0x0004
11924 +#define ASB100_ALARM_IN3       0x0008
11925 +#define ASB100_ALARM_TEMP1     0x0010
11926 +#define ASB100_ALARM_TEMP2     0x0020
11927 +#define ASB100_ALARM_FAN1      0x0040
11928 +#define ASB100_ALARM_FAN2      0x0080
11929 +#define ASB100_ALARM_IN4       0x0100
11930 +#define ASB100_ALARM_IN5       0x0200  /* ? */
11931 +#define ASB100_ALARM_IN6       0x0400  /* ? */
11932 +#define ASB100_ALARM_FAN3      0x0800
11933 +#define ASB100_ALARM_CHAS      0x1000
11934 +#define ASB100_ALARM_TEMP3     0x2000
11935 +
11936 +#define ASB100_ALARM_IN7       0x10000 /* ? */
11937 +#define ASB100_ALARM_IN8       0x20000 /* ? */
11938 +
11939 +/* -- SENSORS SYSCTL END -- */
11940 +
11941 +/* These files are created for each detected chip. This is just a template;
11942 +   though at first sight, you might think we could use a statically
11943 +   allocated list, we need some way to get back to the parent - which
11944 +   is done through one of the 'extra' fields which are initialized 
11945 +   when a new copy is allocated. */
11946 +
11947 +/* no datasheet - but we did get some hints from someone who 
11948 +   claimed to have the datasheet */
11949 +#define ASB100_SYSCTL_IN(nr) {ASB100_SYSCTL_IN##nr, "in" #nr, NULL, 0, \
11950 +       0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &asb100_in}
11951 +#define ASB100_SYSCTL_FAN(nr) {ASB100_SYSCTL_FAN##nr, "fan" #nr, NULL, 0, \
11952 +       0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &asb100_fan}
11953 +#define ASB100_SYSCTL_TEMP(nr, func) {ASB100_SYSCTL_TEMP##nr, "temp" #nr, \
11954 +       NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, func}
11955 +static ctl_table asb100_dir_table_template[] = {
11956 +       ASB100_SYSCTL_IN(0),
11957 +       ASB100_SYSCTL_IN(1),
11958 +       ASB100_SYSCTL_IN(2),
11959 +       ASB100_SYSCTL_IN(3),
11960 +       ASB100_SYSCTL_IN(4),
11961 +       ASB100_SYSCTL_IN(5),
11962 +       ASB100_SYSCTL_IN(6),
11963 +
11964 +       ASB100_SYSCTL_FAN(1),
11965 +       ASB100_SYSCTL_FAN(2),
11966 +       ASB100_SYSCTL_FAN(3),
11967 +
11968 +       ASB100_SYSCTL_TEMP(1, &asb100_temp),
11969 +       ASB100_SYSCTL_TEMP(2, &asb100_temp_add),
11970 +       ASB100_SYSCTL_TEMP(3, &asb100_temp_add),
11971 +       ASB100_SYSCTL_TEMP(4, &asb100_temp),
11972 +
11973 +       {ASB100_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
11974 +        &i2c_sysctl_real, NULL, &asb100_vid},
11975 +       {ASB100_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
11976 +        &i2c_sysctl_real, NULL, &asb100_vrm},
11977 +       {ASB100_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
11978 +        &i2c_sysctl_real, NULL, &asb100_fan_div},
11979 +       {ASB100_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
11980 +        &i2c_sysctl_real, NULL, &asb100_alarms},
11981 +       {ASB100_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
11982 +        &i2c_sysctl_real, NULL, &asb100_pwm},
11983 +       {0}
11984 +};
11985 +
11986 +/* This function is called when:
11987 +       asb100_driver is inserted (when this module is loaded), for each
11988 +               available adapter
11989 +       when a new adapter is inserted (and asb100_driver is still present)
11990 + */
11991 +static int asb100_attach_adapter(struct i2c_adapter *adapter)
11992 +{
11993 +       return i2c_detect(adapter, &addr_data, asb100_detect);
11994 +}
11995 +
11996 +static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
11997 +               int kind, struct i2c_client *new_client)
11998 +{
11999 +       int i, id, err;
12000 +       struct asb100_data *data = new_client->data;
12001 +
12002 +       data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
12003 +       if (!(data->lm75[0])) {
12004 +               err = -ENOMEM;
12005 +               goto ERROR_SC_0;
12006 +       }
12007 +       memset(data->lm75[0], 0x00, sizeof(struct i2c_client));
12008 +
12009 +       data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
12010 +       if (!(data->lm75[1])) {
12011 +               err = -ENOMEM;
12012 +               goto ERROR_SC_1;
12013 +       }
12014 +       memset(data->lm75[1], 0x00, sizeof(struct i2c_client));
12015 +
12016 +       id = i2c_adapter_id(adapter);
12017 +
12018 +       if (force_subclients[0] == id && force_subclients[1] == address) {
12019 +               for (i = 2; i <= 3; i++) {
12020 +                       if (force_subclients[i] < 0x48 ||
12021 +                               force_subclients[i] > 0x4f) {
12022 +                               printk(KERN_ERR "asb100.o: invalid subclient "
12023 +                                       "address %d; must be 0x48-0x4f\n",
12024 +                                       force_subclients[i]);
12025 +                               err = -ENODEV;
12026 +                               goto ERROR_SC_2;
12027 +                       }
12028 +               }
12029 +               asb100_write_value(new_client, ASB100_REG_I2C_SUBADDR,
12030 +                                   (force_subclients[2] & 0x07) |
12031 +                                   ((force_subclients[3] & 0x07) <<4));
12032 +               data->lm75[0]->addr = force_subclients[2];
12033 +               data->lm75[1]->addr = force_subclients[3];
12034 +       } else {
12035 +               int val = asb100_read_value(new_client, ASB100_REG_I2C_SUBADDR);
12036 +               data->lm75[0]->addr = 0x48 + (val & 0x07);
12037 +               data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07);
12038 +       }
12039 +
12040 +       if(data->lm75[0]->addr == data->lm75[1]->addr) {
12041 +               printk(KERN_ERR "asb100.o: duplicate addresses 0x%x "
12042 +                               "for subclients\n", data->lm75[0]->addr);
12043 +               err = -ENODEV;
12044 +               goto ERROR_SC_2;
12045 +       }
12046 +
12047 +       for (i = 0; i <= 1; i++) {
12048 +               data->lm75[i]->data = NULL;
12049 +               data->lm75[i]->adapter = adapter;
12050 +               data->lm75[i]->driver = &asb100_driver;
12051 +               data->lm75[i]->flags = 0;
12052 +               strcpy(data->lm75[i]->name, "asb100 subclient");
12053 +       }
12054 +
12055 +       if ((err = i2c_attach_client(data->lm75[0]))) {
12056 +               printk(KERN_ERR "asb100.o: Subclient %d registration "
12057 +                       "at address 0x%x failed.\n", i, data->lm75[0]->addr);
12058 +               goto ERROR_SC_2;
12059 +       }
12060 +
12061 +       if ((err = i2c_attach_client(data->lm75[1]))) {
12062 +               printk(KERN_ERR "asb100.o: Subclient %d registration "
12063 +                       "at address 0x%x failed.\n", i, data->lm75[1]->addr);
12064 +               goto ERROR_SC_3;
12065 +       }
12066 +
12067 +       return 0;
12068 +
12069 +/* Undo inits in case of errors */
12070 +ERROR_SC_3:
12071 +       i2c_detach_client(data->lm75[0]);
12072 +ERROR_SC_2:
12073 +       kfree(data->lm75[1]);
12074 +ERROR_SC_1:
12075 +       kfree(data->lm75[0]);
12076 +ERROR_SC_0:
12077 +       return err;
12078 +}
12079 +
12080 +static int asb100_detect(struct i2c_adapter *adapter, int address,
12081 +               unsigned short flags, int kind)
12082 +{
12083 +       int err;
12084 +       struct i2c_client *new_client;
12085 +       struct asb100_data *data;
12086 +
12087 +       /* asb100 is SMBus only */
12088 +       if (i2c_is_isa_adapter(adapter)) {
12089 +               pr_debug("asb100.o: detect failed, "
12090 +                               "cannot attach to legacy adapter!\n");
12091 +               err = -ENODEV;
12092 +               goto ERROR0;
12093 +       }
12094 +
12095 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
12096 +               pr_debug("asb100.o: detect failed, "
12097 +                               "smbus byte data not supported!\n");
12098 +               err = -ENODEV;
12099 +               goto ERROR0;
12100 +       }
12101 +
12102 +       /* OK. For now, we presume we have a valid client. We now create the
12103 +          client structure, even though we cannot fill it completely yet.
12104 +          But it allows us to access asb100_{read,write}_value. */
12105 +
12106 +       if (!(data = kmalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
12107 +               pr_debug("asb100.o: detect failed, kmalloc failed!\n");
12108 +               err = -ENOMEM;
12109 +               goto ERROR0;
12110 +       }
12111 +
12112 +       new_client = &data->client;
12113 +       new_client->addr = address;
12114 +       init_MUTEX(&data->lock);
12115 +       new_client->data = data;
12116 +       new_client->adapter = adapter;
12117 +       new_client->driver = &asb100_driver;
12118 +       new_client->flags = 0;
12119 +
12120 +       /* Now, we do the remaining detection. */
12121 +
12122 +       /* The chip may be stuck in some other bank than bank 0. This may
12123 +          make reading other information impossible. Specify a force=... or
12124 +          force_*=... parameter, and the chip will be reset to the right
12125 +          bank. */
12126 +       if (kind < 0) {
12127 +
12128 +               int val1 = asb100_read_value(new_client, ASB100_REG_BANK);
12129 +               int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN);
12130 +
12131 +               /* If we're in bank 0 */
12132 +               if ( (!(val1 & 0x07)) &&
12133 +                               /* Check for ASB100 ID (low byte) */
12134 +                               ( ((!(val1 & 0x80)) && (val2 != 0x94)) ||
12135 +                               /* Check for ASB100 ID (high byte ) */
12136 +                               ((val1 & 0x80) && (val2 != 0x06)) ) ) {
12137 +                       pr_debug("asb100.o: detect failed, "
12138 +                                       "bad chip id 0x%02x!\n", val2);
12139 +                       err = -ENODEV;
12140 +                       goto ERROR1;
12141 +               }
12142 +
12143 +       } /* kind < 0 */
12144 +
12145 +       /* We have either had a force parameter, or we have already detected
12146 +          Winbond. Put it now into bank 0 and Vendor ID High Byte */
12147 +       asb100_write_value(new_client, ASB100_REG_BANK,
12148 +               (asb100_read_value(new_client, ASB100_REG_BANK) & 0x78) | 0x80);
12149 +
12150 +       /* Determine the chip type. */
12151 +       if (kind <= 0) {
12152 +               int val1 = asb100_read_value(new_client, ASB100_REG_WCHIPID);
12153 +               int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN);
12154 +
12155 +               if ((val1 == 0x31) && (val2 == 0x06))
12156 +                       kind = asb100;
12157 +               else {
12158 +                       if (kind == 0)
12159 +                               printk (KERN_WARNING "asb100.o: Ignoring "
12160 +                                       "'force' parameter for unknown chip "
12161 +                                       "at adapter %d, address 0x%02x.\n",
12162 +                                       i2c_adapter_id(adapter), address);
12163 +                       err = -ENODEV;
12164 +                       goto ERROR1;
12165 +               }
12166 +       }
12167 +
12168 +       /* Fill in remaining client fields and put it into the global list */
12169 +       strcpy(new_client->name, "ASB100 chip");
12170 +       data->type = kind;
12171 +
12172 +       data->valid = 0;
12173 +       init_MUTEX(&data->update_lock);
12174 +
12175 +       /* Tell the I2C layer a new client has arrived */
12176 +       if ((err = i2c_attach_client(new_client)))
12177 +               goto ERROR1;
12178 +
12179 +       /* Attach secondary lm75 clients */
12180 +       if ((err = asb100_detect_subclients(adapter, address, kind,
12181 +                       new_client)))
12182 +               goto ERROR2;
12183 +
12184 +       /* Initialize the chip */
12185 +       asb100_init_client(new_client);
12186 +
12187 +       /* Register a new directory entry with module sensors */
12188 +       if ((data->sysctl_id = i2c_register_entry(new_client, "asb100",
12189 +                       asb100_dir_table_template)) < 0) {
12190 +               err = data->sysctl_id;
12191 +               goto ERROR3;
12192 +       }
12193 +
12194 +       return 0;
12195 +
12196 +ERROR3:
12197 +       i2c_detach_client(data->lm75[0]);
12198 +       kfree(data->lm75[1]);
12199 +       kfree(data->lm75[0]);
12200 +ERROR2:
12201 +       i2c_detach_client(new_client);
12202 +ERROR1:
12203 +       kfree(data);
12204 +ERROR0:
12205 +       return err;
12206 +}
12207 +
12208 +static int asb100_detach_client(struct i2c_client *client)
12209 +{
12210 +       int err;
12211 +       struct asb100_data *data = client->data;
12212 +
12213 +       /* remove sysctl table (primary client only) */
12214 +       if ((data))
12215 +               i2c_deregister_entry(data->sysctl_id);
12216 +
12217 +       if ((err = i2c_detach_client(client))) {
12218 +               printk (KERN_ERR "asb100.o: Client deregistration failed; "
12219 +                       "client not detached.\n");
12220 +               return err;
12221 +       }
12222 +
12223 +       if (data) {
12224 +               /* primary client */
12225 +               kfree(data);
12226 +       } else {
12227 +               /* subclients */
12228 +               kfree(client);
12229 +       }
12230 +
12231 +       return 0;
12232 +}
12233 +
12234 +/* The SMBus locks itself, usually, but nothing may access the Winbond between
12235 +   bank switches. ISA access must always be locked explicitly! 
12236 +   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
12237 +   would slow down the W83781D access and should not be necessary. 
12238 +   There are some ugly typecasts here, but the good news is - they should
12239 +   nowhere else be necessary! */
12240 +static int asb100_read_value(struct i2c_client *client, u16 reg)
12241 +{
12242 +       struct asb100_data *data = client->data;
12243 +       struct i2c_client *cl;
12244 +       int res, bank;
12245 +
12246 +       down(&data->lock);
12247 +
12248 +       bank = (reg >> 8) & 0x0f;
12249 +       if (bank > 2)
12250 +               /* switch banks */
12251 +               i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank);
12252 +
12253 +       if (bank == 0 || bank > 2) {
12254 +               res = i2c_smbus_read_byte_data(client, reg & 0xff);
12255 +       } else {
12256 +               /* switch to subclient */
12257 +               cl = data->lm75[bank - 1];
12258 +
12259 +               /* convert from ISA to LM75 I2C addresses */
12260 +               switch (reg & 0xff) {
12261 +               case 0x50: /* TEMP */
12262 +                       res = swab16(i2c_smbus_read_word_data (cl, 0));
12263 +                       break;
12264 +               case 0x52: /* CONFIG */
12265 +                       res = i2c_smbus_read_byte_data(cl, 1);
12266 +                       break;
12267 +               case 0x53: /* HYST */
12268 +                       res = swab16(i2c_smbus_read_word_data (cl, 2));
12269 +                       break;
12270 +               case 0x55: /* MAX */
12271 +               default:
12272 +                       res = swab16(i2c_smbus_read_word_data (cl, 3));
12273 +                       break;
12274 +               }
12275 +       }
12276 +
12277 +       if (bank > 2)
12278 +               i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
12279 +
12280 +       up(&data->lock);
12281 +
12282 +       return res;
12283 +}
12284 +
12285 +static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value)
12286 +{
12287 +       struct asb100_data *data = client->data;
12288 +       struct i2c_client *cl;
12289 +       int bank;
12290 +
12291 +       down(&data->lock);
12292 +
12293 +       bank = (reg >> 8) & 0x0f;
12294 +       if (bank > 2)
12295 +               /* switch banks */
12296 +               i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank);
12297 +
12298 +       if (bank == 0 || bank > 2) {
12299 +               i2c_smbus_write_byte_data(client, reg & 0xff, value & 0xff);
12300 +       } else {
12301 +               /* switch to subclient */
12302 +               cl = data->lm75[bank - 1];
12303 +
12304 +               /* convert from ISA to LM75 I2C addresses */
12305 +               switch (reg & 0xff) {
12306 +               case 0x52: /* CONFIG */
12307 +                       i2c_smbus_write_byte_data(cl, 1, value & 0xff);
12308 +                       break;
12309 +               case 0x53: /* HYST */
12310 +                       i2c_smbus_write_word_data(cl, 2, swab16(value));
12311 +                       break;
12312 +               case 0x55: /* MAX */
12313 +                       i2c_smbus_write_word_data(cl, 3, swab16(value));
12314 +                       break;
12315 +               }
12316 +       }
12317 +
12318 +       if (bank > 2)
12319 +               i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
12320 +
12321 +       up(&data->lock);
12322 +}
12323 +
12324 +static void asb100_init_client(struct i2c_client *client)
12325 +{
12326 +       struct asb100_data *data = client->data;
12327 +       int vid = 0;
12328 +
12329 +       vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
12330 +       vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
12331 +       data->vrm = ASB100_DEFAULT_VRM;
12332 +       vid = vid_from_reg(vid, data->vrm);
12333 +
12334 +       /* Start monitoring */
12335 +       asb100_write_value(client, ASB100_REG_CONFIG, 
12336 +               (asb100_read_value(client, ASB100_REG_CONFIG) & 0xf7) | 0x01);
12337 +}
12338 +
12339 +static void asb100_update_client(struct i2c_client *client)
12340 +{
12341 +       struct asb100_data *data = client->data;
12342 +       int i;
12343 +
12344 +       down(&data->update_lock);
12345 +
12346 +       if (time_after(jiffies - data->last_updated, HZ + HZ / 2) ||
12347 +               time_before(jiffies, data->last_updated) || !data->valid) {
12348 +
12349 +               pr_debug("asb100.o: starting device update...\n");
12350 +
12351 +               /* 7 voltage inputs */
12352 +               for (i = 0; i < 7; i++) {
12353 +                       data->in[i] = asb100_read_value(client,
12354 +                               ASB100_REG_IN(i));
12355 +                       data->in_min[i] = asb100_read_value(client,
12356 +                               ASB100_REG_IN_MIN(i));
12357 +                       data->in_max[i] = asb100_read_value(client,
12358 +                               ASB100_REG_IN_MAX(i));
12359 +               }
12360 +
12361 +               /* 3 fan inputs */
12362 +               for (i = 1; i <= 3; i++) {
12363 +                       data->fan[i-1] = asb100_read_value(client,
12364 +                                       ASB100_REG_FAN(i));
12365 +                       data->fan_min[i-1] = asb100_read_value(client,
12366 +                                       ASB100_REG_FAN_MIN(i));
12367 +               }
12368 +
12369 +               /* 4 temperature inputs */
12370 +               for (i = 1; i <= 4; i++) {
12371 +                       data->temp[i-1] = asb100_read_value(client,
12372 +                                       ASB100_REG_TEMP(i));
12373 +                       data->temp_max[i-1] = asb100_read_value(client,
12374 +                                       ASB100_REG_TEMP_MAX(i));
12375 +                       data->temp_hyst[i-1] = asb100_read_value(client,
12376 +                                       ASB100_REG_TEMP_HYST(i));
12377 +               }
12378 +
12379 +               /* VID and fan divisors */
12380 +               i = asb100_read_value(client, ASB100_REG_VID_FANDIV);
12381 +               data->vid = i & 0x0f;
12382 +               data->vid |= (asb100_read_value(client,
12383 +                               ASB100_REG_CHIPID) & 0x01) << 4;
12384 +               data->fan_div[0] = (i >> 4) & 0x03;
12385 +               data->fan_div[1] = (i >> 6) & 0x03;
12386 +               data->fan_div[2] = (asb100_read_value(client,
12387 +                               ASB100_REG_PIN) >> 6) & 0x03;
12388 +
12389 +               /* PWM */
12390 +               data->pwm = asb100_read_value(client, ASB100_REG_PWM1);
12391 +
12392 +               /* alarms */
12393 +               data->alarms = asb100_read_value(client, ASB100_REG_ALARM1) +
12394 +                       (asb100_read_value(client, ASB100_REG_ALARM2) << 8);
12395 +
12396 +               data->last_updated = jiffies;
12397 +               data->valid = 1;
12398 +
12399 +               pr_debug("asb100.o: ... update complete.\n");
12400 +       }
12401 +
12402 +       up(&data->update_lock);
12403 +}
12404 +
12405 +
12406 +/* The next few functions are the call-back functions of the /proc/sys and
12407 +   sysctl files. Which function is used is defined in the ctl_table in
12408 +   the extra1 field.
12409 +   Each function must return the magnitude (power of 10 to divide the date
12410 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
12411 +   put a maximum of *nrels elements in results reflecting the data of this
12412 +   file, and set *nrels to the number it actually put in it, if operation==
12413 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
12414 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
12415 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
12416 +   large enough (by checking the incoming value of *nrels). This is not very
12417 +   good practice, but as long as you put less than about 5 values in results,
12418 +   you can assume it is large enough. */
12419 +static void asb100_in(struct i2c_client *client, int operation, int ctl_name,
12420 +               int *nrels_mag, long *results)
12421 +{
12422 +       struct asb100_data *data = client->data;
12423 +       int nr = ctl_name - ASB100_SYSCTL_IN0;
12424 +
12425 +       if (operation == SENSORS_PROC_REAL_INFO)
12426 +               *nrels_mag = 2;
12427 +       else if (operation == SENSORS_PROC_REAL_READ) {
12428 +               asb100_update_client(client);
12429 +               results[0] = IN_FROM_REG(data->in_min[nr]);
12430 +               results[1] = IN_FROM_REG(data->in_max[nr]);
12431 +               results[2] = IN_FROM_REG(data->in[nr]);
12432 +               *nrels_mag = 3;
12433 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
12434 +               if (*nrels_mag >= 1) {
12435 +                       data->in_min[nr] = IN_TO_REG(results[0]);
12436 +                       asb100_write_value(client, ASB100_REG_IN_MIN(nr),
12437 +                                           data->in_min[nr]);
12438 +               }
12439 +               if (*nrels_mag >= 2) {
12440 +                       data->in_max[nr] = IN_TO_REG(results[1]);
12441 +                       asb100_write_value(client, ASB100_REG_IN_MAX(nr),
12442 +                                           data->in_max[nr]);
12443 +               }
12444 +       }
12445 +}
12446 +
12447 +void asb100_fan(struct i2c_client *client, int operation, int ctl_name,
12448 +                int *nrels_mag, long *results)
12449 +{
12450 +       struct asb100_data *data = client->data;
12451 +       int nr = ctl_name - ASB100_SYSCTL_FAN1 + 1;
12452 +
12453 +       if (operation == SENSORS_PROC_REAL_INFO)
12454 +               *nrels_mag = 0;
12455 +       else if (operation == SENSORS_PROC_REAL_READ) {
12456 +               asb100_update_client(client);
12457 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
12458 +                                 DIV_FROM_REG(data->fan_div[nr - 1]));
12459 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
12460 +                                 DIV_FROM_REG(data->fan_div[nr - 1]));
12461 +               *nrels_mag = 2;
12462 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
12463 +               if (*nrels_mag >= 1) {
12464 +                       data->fan_min[nr - 1] =
12465 +                            FAN_TO_REG(results[0],
12466 +                                   DIV_FROM_REG(data->fan_div[nr-1]));
12467 +                       asb100_write_value(client,
12468 +                                           ASB100_REG_FAN_MIN(nr),
12469 +                                           data->fan_min[nr - 1]);
12470 +               }
12471 +       }
12472 +}
12473 +
12474 +void asb100_temp(struct i2c_client *client, int operation, int ctl_name,
12475 +                 int *nrels_mag, long *results)
12476 +{
12477 +       struct asb100_data *data = client->data;
12478 +       int nr = ctl_name - ASB100_SYSCTL_TEMP1;
12479 +
12480 +       if (operation == SENSORS_PROC_REAL_INFO)
12481 +               *nrels_mag = 1;
12482 +
12483 +       else if (operation == SENSORS_PROC_REAL_READ) {
12484 +               asb100_update_client(client);
12485 +               results[0] = TEMP_FROM_REG(data->temp_max[nr]);
12486 +               results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
12487 +               results[2] = TEMP_FROM_REG(data->temp[nr]);
12488 +               *nrels_mag = 3;
12489 +
12490 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
12491 +               if (*nrels_mag >= 1) {
12492 +                       data->temp_max[nr] = TEMP_TO_REG(results[0]);
12493 +                       asb100_write_value(client, ASB100_REG_TEMP_MAX(nr+1),
12494 +                               data->temp_max[nr]);
12495 +               }
12496 +               if (*nrels_mag >= 2) {
12497 +                       data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
12498 +                       asb100_write_value(client, ASB100_REG_TEMP_HYST(nr+1),
12499 +                               data->temp_hyst[nr]);
12500 +               }
12501 +       }
12502 +}
12503 +
12504 +void asb100_temp_add(struct i2c_client *client, int operation,
12505 +                     int ctl_name, int *nrels_mag, long *results)
12506 +{
12507 +       struct asb100_data *data = client->data;
12508 +       int nr = ctl_name - ASB100_SYSCTL_TEMP1;
12509 +
12510 +       if (operation == SENSORS_PROC_REAL_INFO)
12511 +               *nrels_mag = 1;
12512 +
12513 +       else if (operation == SENSORS_PROC_REAL_READ) {
12514 +               asb100_update_client(client);
12515 +
12516 +               results[0] = LM75_TEMP_FROM_REG(data->temp_max[nr]);
12517 +               results[1] = LM75_TEMP_FROM_REG(data->temp_hyst[nr]);
12518 +               results[2] = LM75_TEMP_FROM_REG(data->temp[nr]);
12519 +               *nrels_mag = 3;
12520 +
12521 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
12522 +               if (*nrels_mag >= 1) {
12523 +                       data->temp_max[nr] =
12524 +                               LM75_TEMP_TO_REG(results[0]);
12525 +                       asb100_write_value(client, ASB100_REG_TEMP_MAX(nr+1),
12526 +                               data->temp_max[nr]);
12527 +               }
12528 +               if (*nrels_mag >= 2) {
12529 +                       data->temp_hyst[nr] =
12530 +                               LM75_TEMP_TO_REG(results[1]);
12531 +                       asb100_write_value(client, ASB100_REG_TEMP_HYST(nr+1),
12532 +                               data->temp_hyst[nr]);
12533 +               }
12534 +       }
12535 +}
12536 +
12537 +void asb100_vid(struct i2c_client *client, int operation, int ctl_name,
12538 +                int *nrels_mag, long *results)
12539 +{
12540 +       struct asb100_data *data = client->data;
12541 +       if (operation == SENSORS_PROC_REAL_INFO)
12542 +               *nrels_mag = 3;
12543 +       else if (operation == SENSORS_PROC_REAL_READ) {
12544 +               asb100_update_client(client);
12545 +               results[0] = vid_from_reg(data->vid, data->vrm);
12546 +               *nrels_mag = 1;
12547 +       }
12548 +}
12549 +
12550 +void asb100_vrm(struct i2c_client *client, int operation, int ctl_name,
12551 +                int *nrels_mag, long *results)
12552 +{
12553 +       struct asb100_data *data = client->data;
12554 +       if (operation == SENSORS_PROC_REAL_INFO)
12555 +               *nrels_mag = 1;
12556 +       else if (operation == SENSORS_PROC_REAL_READ) {
12557 +               results[0] = data->vrm;
12558 +               *nrels_mag = 1;
12559 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
12560 +               if (*nrels_mag >= 1)
12561 +                       data->vrm = results[0];
12562 +       }
12563 +}
12564 +
12565 +void asb100_alarms(struct i2c_client *client, int operation, int ctl_name,
12566 +                   int *nrels_mag, long *results)
12567 +{
12568 +       struct asb100_data *data = client->data;
12569 +       if (operation == SENSORS_PROC_REAL_INFO)
12570 +               *nrels_mag = 0;
12571 +       else if (operation == SENSORS_PROC_REAL_READ) {
12572 +               asb100_update_client(client);
12573 +               results[0] = ALARMS_FROM_REG(data->alarms);
12574 +               *nrels_mag = 1;
12575 +       }
12576 +}
12577 +
12578 +void asb100_fan_div(struct i2c_client *client, int operation,
12579 +                    int ctl_name, int *nrels_mag, long *results)
12580 +{
12581 +       struct asb100_data *data = client->data;
12582 +       int old, old2;
12583 +
12584 +       if (operation == SENSORS_PROC_REAL_INFO)
12585 +               *nrels_mag = 0;
12586 +
12587 +       else if (operation == SENSORS_PROC_REAL_READ) {
12588 +               asb100_update_client(client);
12589 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
12590 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
12591 +               results[2] = DIV_FROM_REG(data->fan_div[2]);
12592 +               *nrels_mag = 3;
12593 +
12594 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
12595 +               old = asb100_read_value(client, ASB100_REG_VID_FANDIV);
12596 +               if (*nrels_mag >= 3) {
12597 +                       data->fan_div[2] = DIV_TO_REG(results[2]);
12598 +                       old2 = asb100_read_value(client, ASB100_REG_PIN);
12599 +                       old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
12600 +                       asb100_write_value(client, ASB100_REG_PIN, old2);
12601 +               }
12602 +               if (*nrels_mag >= 2) {
12603 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
12604 +                       old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
12605 +               }
12606 +               if (*nrels_mag >= 1) {
12607 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
12608 +                       old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
12609 +                       asb100_write_value(client, ASB100_REG_VID_FANDIV, old);
12610 +               }
12611 +       }
12612 +}
12613 +
12614 +void asb100_pwm(struct i2c_client *client, int operation, int ctl_name,
12615 +               int *nrels_mag, long *results)
12616 +{
12617 +       struct asb100_data *data = client->data;
12618 +
12619 +       if (operation == SENSORS_PROC_REAL_INFO)
12620 +               *nrels_mag = 0;
12621 +       else if (operation == SENSORS_PROC_REAL_READ) {
12622 +               asb100_update_client(client);
12623 +               results[0] = ASB100_PWM_FROM_REG(data->pwm & 0x0f);
12624 +               results[1] = (data->pwm & 0x80) ? 1 : 0;
12625 +               *nrels_mag = 2;
12626 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
12627 +               u8 val = data->pwm;
12628 +               if (*nrels_mag >= 1) {
12629 +                       val = 0x0f & ASB100_PWM_TO_REG(results[0]);
12630 +                       if (*nrels_mag >= 2) {
12631 +                               if (results[1])
12632 +                                       val |= 0x80;
12633 +                               else
12634 +                                       val &= ~0x80;
12635 +                       }
12636 +                       asb100_write_value(client, ASB100_REG_PWM1, val);
12637 +               }
12638 +       }
12639 +}
12640 +
12641 +static int __init asb100_init(void)
12642 +{
12643 +       printk(KERN_INFO "asb100.o version %s (%s)\n", LM_VERSION, LM_DATE);
12644 +       return i2c_add_driver(&asb100_driver);
12645 +}
12646 +
12647 +static void __exit asb100_exit(void)
12648 +{
12649 +       i2c_del_driver(&asb100_driver);
12650 +}
12651 +
12652 +MODULE_AUTHOR( "Mark M. Hoffman <mhoffman@lightlink.com>, "
12653 +               "Frodo Looijaard <frodol@dds.nl>, "
12654 +               "Philip Edelbrock <phil@netroedge.com>, and"
12655 +               "Mark Studebaker <mdsxyz123@yahoo.com>");
12656 +
12657 +MODULE_DESCRIPTION("ASB100 'Bach' driver");
12658 +MODULE_LICENSE("GPL");
12659 +
12660 +module_init(asb100_init);
12661 +module_exit(asb100_exit);
12662 +
12663 --- linux-old/drivers/sensors/bt869.c   Thu Jan  1 00:00:00 1970
12664 +++ linux/drivers/sensors/bt869.c       Mon Dec 13 20:18:45 2004
12665 @@ -0,0 +1,891 @@
12666 +/*
12667 +    bt869.c - Part of lm_sensors, Linux kernel modules for hardware
12668 +             monitoring
12669 +
12670 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
12671 +    Copyright (c) 2001, 2002  Stephen Davies  <steve@daviesfam.org>
12672 +
12673 +    This program is free software; you can redistribute it and/or modify
12674 +    it under the terms of the GNU General Public License as published by
12675 +    the Free Software Foundation; either version 2 of the License, or
12676 +    (at your option) any later version.
12677 +
12678 +    This program is distributed in the hope that it will be useful,
12679 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
12680 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12681 +    GNU General Public License for more details.
12682 +
12683 +    You should have received a copy of the GNU General Public License
12684 +    along with this program; if not, write to the Free Software
12685 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12686 +*/
12687 +
12688 +
12689 +#define DEBUG 1
12690 +
12691 +#include <linux/module.h>
12692 +#include <linux/slab.h>
12693 +#include <linux/i2c.h>
12694 +#include <linux/i2c-proc.h>
12695 +#include <linux/init.h>
12696 +#define LM_DATE "20041007"
12697 +#define LM_VERSION "2.8.8"
12698 +
12699 +MODULE_LICENSE("GPL");
12700 +
12701 +/* Addresses to scan */
12702 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
12703 +
12704 +/* found only at 0x44 or 0x45 */
12705 +static unsigned short normal_i2c_range[] = { 0x44, 0x45, SENSORS_I2C_END };
12706 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
12707 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
12708 +
12709 +/* Insmod parameters */
12710 +SENSORS_INSMOD_1(bt869);
12711 +
12712 +/* Many bt869 constants specified below */
12713 +
12714 +/* The bt869 registers */
12715 +/* Coming soon: Many, many registers */
12716 +
12717 +/* Conversions. Rounding and limit checking is only done on the TO_REG
12718 +   variants. Note that you should be a bit careful with which arguments
12719 +   these macros are called: arguments may be evaluated more than once.
12720 +   Fixing this is just not worth it. */
12721 +
12722 +   /*none */
12723 +
12724 +/* Initial values */
12725 +/*none*/
12726 +
12727 +/* Each client has this additional data */
12728 +struct bt869_data {
12729 +       struct i2c_client client;
12730 +       int sysctl_id;
12731 +
12732 +       struct semaphore update_lock;
12733 +       char valid;             /* !=0 if following fields are valid */
12734 +       unsigned long last_updated;     /* In jiffies */
12735 +
12736 +       u8 status[3];           /* Register values */
12737 +       u16 res[2];             /* Resolution XxY */
12738 +       u8 ntsc;                /* 1=NTSC, 0=PAL */
12739 +       u8 half;                /* go half res */
12740 +       u8 depth;               /* screen depth */
12741 +       u8 colorbars;           /* turn on/off colorbar calibration screen */
12742 +        u8 svideo;              /* output format: (2=RGB) 1=SVIDEO, 0=Composite */
12743 +};
12744 +
12745 +static int bt869_attach_adapter(struct i2c_adapter *adapter);
12746 +static int bt869_detect(struct i2c_adapter *adapter, int address,
12747 +                       unsigned short flags, int kind);
12748 +static void bt869_init_client(struct i2c_client *client);
12749 +static int bt869_detach_client(struct i2c_client *client);
12750 +static int bt869_read_value(struct i2c_client *client, u8 reg);
12751 +static int bt869_write_value(struct i2c_client *client, u8 reg, u16 value);
12752 +static void bt869_write_values(struct i2c_client *client, u16 *values);
12753 +static void bt869_status(struct i2c_client *client, int operation,
12754 +                        int ctl_name, int *nrels_mag, long *results);
12755 +static void bt869_ntsc(struct i2c_client *client, int operation,
12756 +                      int ctl_name, int *nrels_mag, long *results);
12757 +static void bt869_res(struct i2c_client *client, int operation,
12758 +                     int ctl_name, int *nrels_mag, long *results);
12759 +static void bt869_half(struct i2c_client *client, int operation,
12760 +                      int ctl_name, int *nrels_mag, long *results);
12761 +static void bt869_colorbars(struct i2c_client *client, int operation,
12762 +                           int ctl_name, int *nrels_mag, long *results);
12763 +static void bt869_svideo(struct i2c_client *client, int operation,
12764 +                           int ctl_name, int *nrels_mag, long *results);
12765 +static void bt869_depth(struct i2c_client *client, int operation,
12766 +                       int ctl_name, int *nrels_mag, long *results);
12767 +static void bt869_update_client(struct i2c_client *client);
12768 +
12769 +
12770 +/* This is the driver that will be inserted */
12771 +static struct i2c_driver bt869_driver = {
12772 +       .owner          = THIS_MODULE,
12773 +       .name           = "BT869 video-output chip driver",
12774 +       .id             = I2C_DRIVERID_BT869,
12775 +       .flags          = I2C_DF_NOTIFY,
12776 +       .attach_adapter = bt869_attach_adapter,
12777 +       .detach_client  = bt869_detach_client,
12778 +};
12779 +
12780 +/* -- SENSORS SYSCTL START -- */
12781 +#define BT869_SYSCTL_STATUS 1000
12782 +#define BT869_SYSCTL_NTSC   1001
12783 +#define BT869_SYSCTL_HALF   1002
12784 +#define BT869_SYSCTL_RES    1003
12785 +#define BT869_SYSCTL_COLORBARS    1004
12786 +#define BT869_SYSCTL_DEPTH  1005
12787 +#define BT869_SYSCTL_SVIDEO 1006
12788 +
12789 +/* -- SENSORS SYSCTL END -- */
12790 +
12791 +/* These files are created for each detected bt869. This is just a template;
12792 +   though at first sight, you might think we could use a statically
12793 +   allocated list, we need some way to get back to the parent - which
12794 +   is done through one of the 'extra' fields which are initialized
12795 +   when a new copy is allocated. */
12796 +static ctl_table bt869_dir_table_template[] = {
12797 +       {BT869_SYSCTL_STATUS, "status", NULL, 0, 0444, NULL, &i2c_proc_real,
12798 +        &i2c_sysctl_real, NULL, &bt869_status},
12799 +       {BT869_SYSCTL_NTSC, "ntsc", NULL, 0, 0644, NULL, &i2c_proc_real,
12800 +        &i2c_sysctl_real, NULL, &bt869_ntsc},
12801 +       {BT869_SYSCTL_RES, "res", NULL, 0, 0644, NULL, &i2c_proc_real,
12802 +        &i2c_sysctl_real, NULL, &bt869_res},
12803 +       {BT869_SYSCTL_HALF, "half", NULL, 0, 0644, NULL, &i2c_proc_real,
12804 +        &i2c_sysctl_real, NULL, &bt869_half},
12805 +       {BT869_SYSCTL_COLORBARS, "colorbars", NULL, 0, 0644, NULL, &i2c_proc_real,
12806 +        &i2c_sysctl_real, NULL, &bt869_colorbars},
12807 +       {BT869_SYSCTL_DEPTH, "depth", NULL, 0, 0644, NULL, &i2c_proc_real,
12808 +        &i2c_sysctl_real, NULL, &bt869_depth},
12809 +       {BT869_SYSCTL_SVIDEO, "svideo", NULL, 0, 0644, NULL, &i2c_proc_real,
12810 +        &i2c_sysctl_real, NULL, &bt869_svideo},
12811 +       {0}
12812 +};
12813 +
12814 +/* ******************
12815 +
12816 +720x576, 27.5MHz, PAL, no overscan compensation.
12817 +
12818 +This mode should be use for digital video, DVD playback etc.
12819 +
12820 +NOTE: This mode for PAL, see 720x480 for an equivalent NTSC mode
12821 +NOTE:    -- Steve Davies <steve@daviesfam.org>
12822 +
12823 +
12824 +Compatible X modeline:
12825 +
12826 +    Mode        "720x576-BT869"
12827 +        DotClock        27.5
12828 +        HTimings        720 744 800 880
12829 +        VTimings        576 581 583 625
12830 +    EndMode
12831 +
12832 +
12833 +625LINE=1                                                      625 line output format
12834 +BST_AMP[7:0]=x57 87                                            Burst ampl. multiplication factor (PAL std??)
12835 +BY_PLL=0                                                       Use the PLL
12836 +CATTENUATE[2:0]=0                                              No chroma attenuation
12837 +CCF1B1[7:0]=0                                                  close caption stuff
12838 +CCF1B2[7:0]=0                                                  close caption stuff
12839 +CCF2B1[7:0]=0                                                  close caption stuff
12840 +CCF2B2[7:0]=0                                                  close caption stuff
12841 +CCORING[2:0]=0                                                 Bypass chroma coring
12842 +CCR_START[8:0]=0 [CCR_START[8]=0; CCR_START[7:0]=0]            Close-caption clock runin start from hsync
12843 +CC_ADD[11:0]=xD2 210  [CC_ADD[11:8]=0; CC_ADD[7:0]=xD2]                Close-caption DTO increment
12844 +CHECK_STAT=0                                                   Don't check monitor status
12845 +CLPF[1:0]=0                                                    Hoz chroma lowpass filter=Bypass
12846 +DACDISA=1                                                      Disable DACA
12847 +DACDISB=0                                                      Don't disable DACB
12848 +DACDISC=0                                                      Don't disable DACC
12849 +DACOFF=0                                                       Don't disable the DACs
12850 +DATDLY = 0                                                     normal
12851 +DATSWP=0                                                       normal
12852 +DCHROMA=0                                                      Don't blank chroma
12853 +DIS_FFILT=1                                                    Disable flickerfilter
12854 +DIS_GMSHC=1                                                    Disable chroma psuedo-gamma removal
12855 +DIS_GMSHY=1                                                    Disable luma pseudo gamma removal
12856 +DIS_GMUSHC=1                                                   Disable chroma anti-pseudo gamma removal
12857 +DIS_GMUSHY=1                                                   Disable luma anti-pseudo gamma removal
12858 +DIS_SCRESET=0                                                  Normal subcarrier phase resets
12859 +DIS_YFLPF=0                                                    Disable Luma initial hoz low pass filter
12860 +DIV2=0                                                         Input pixel rate not divided by 2
12861 +ECBAR=0                                                                No colour bars
12862 +ECCF1=0                                                                Disable closed caption
12863 +ECCF2=0                                                                Disable closed caption
12864 +ECCGATE=0                                                      Normal close caption encoding
12865 +ECLIP=0                                                                0=disable clipping
12866 +EN_ASYNC=0                                                     set to 0 for normal operation
12867 +EN_BLANKO=0                                                    BLANK is an input
12868 +EN_DOT=0                                                       Disables dot clock sync on BLANK pin
12869 +EN_OUT=1                                                       Allows outputs to be enabled
12870 +EN_XCLK=1                                                      Use CLKI pin as clock source
12871 +ESTATUS[1:0]=0                                                 Used to select readback register
12872 +FIELDI=0                                                       Logical 1 on FIELD indicates even field
12873 +F_SELC[2:0]=0                                                  5 line chroma flickerfilter
12874 +F_SELY[2:0]=0                                                  5 line luma flickerfilter
12875 +HBURST_BEGIN[7:0]=x98 152                                      Chroma burst start point in clocks
12876 +HBURST_END[7:0]=x58 88                                         Chroma burst end point in clocks - 128
12877 +HSYNCI=0                                                       Active low HSYNC
12878 +HSYNC_WIDTH[7:0]=x80 128                                       Analogue sync width in clocks
12879 +HSYNOFFSET[9:0]=0  [HSYNOFFSET[9:8]=0; HSYNOFFSET[7:0]=0]      hsync in "standard position"
12880 +HSYNWIDTH[5:0]=2                                               2 pixel hsync width
12881 +H_ACTIVE[9:0]=x2D0 720  [H_ACTIVE[9:8]=2; H_ACTIVE[7:0]=xD0]   Active pixels per line
12882 +H_BLANKI[8:0]=x84 132  [H_BLANKI[8]=0; H_BLANKI[7:0]=x84]      End of blanking of input video
12883 +H_BLANKO[9:0]=x120 288  [H_BLANKO[9:8]=1; H_BLANKO[7:0]=x20]   End of blanking from hoz sync leading edge
12884 +H_CLKI[10:0]=x378 888  [H_CLKI[10:8]=3; H_CLKI[7:0]=x78]       Input line length total in clocks
12885 +H_CLKO[11:0]=x6e0 1760  [H_CLKO[11:8]=6; H_CLKO[7:0]=xe0]      Output clocks per line
12886 +H_FRACT[7:0]=0                                                 0 fractional input clocks per line
12887 +IN_MODE[2:0]=0                                                 24Bit RGB muxed
12888 +LUMADLY[1:0]=0                                                 0 pixel delay on Y_DLY luma
12889 +MCB[7:0]=x49 73                                                        Mult factor for CB prior to subcarrier mod.
12890 +MCR[7:0]=x82 130                                               Mult factor for CR prior to subcarrier mod.
12891 +MODE2X=0                                                       Don't divide clock input by 2
12892 +MSC[31:0]=x2945E0B4 692445365  [MSC[31:24]=x29; MSC[23:16]=x45; MSC[15:8]=xE0; MSC[7:0]=xB4] Subcarrier incr.
12893 +MY[7:0]=x8C 140                                                        Mult factor for Y
12894 +NI_OUT=0                                                       Normal interlaced output
12895 +OUT_MODE[1:0]=0                                                        video0-3 is CVBS, Y, C, Y_DLY
12896 +OUT_MUXA[1:0]=0                                                        Don't care as DACA is disabled
12897 +OUT_MUXB[1:0]=1                                                        Output video[1] (Y) on DACB
12898 +OUT_MUXC[1:0]=2                                                        Output video[2] (C) on DACC
12899 +PAL_MD=1                                                       Video output in PAL mode
12900 +PHASE_OFF[7:0]=0                                               Subcarrier phase offset
12901 +PLL_FRACT[15:0]=x30 48  [PLL_FRACT[15:8]=0x0; PLL_FRACT[7:0]=x30] frac portion of pll multiplier
12902 +PLL_INT[5:0]=0x0C 12                                           Int portion of pll multiplier
12903 +SETUP=0                                                                7.5-IRE setup disabled
12904 +SLAVER=1                                                       
12905 +SRESET=0                                                       Don't do a software reset
12906 +SYNC_AMP[7:0]=xF0 240                                          Sync amp mult. factor (PAL std???)
12907 +VBLANKDLY=0                                                    Extra line of blanking in 2nd field?
12908 +VSYNCI=0                                                       Active low VSYNC
12909 +VSYNC_DUR=0                                                    2.5line VSYNC duration on output
12910 +VSYNCOFFSET[10:0]=0  [VSYNOFFSET[10:8]=0; VSYNOFFSET[7:0]=0]   VSYNC in standard position
12911 +VSYNWIDTH[2:0]=1                                               1 line of vsync width
12912 +V_ACTIVEI[9:0]=x240 576  [V_ACTIVEI[9:0]=2; V_ACTIVEI[7:0]=x40]        Active input lines
12913 +V_ACTIVEO[8:0]=x122 290  [V_ACTIVE0[8]=1; V_ACTIVEO[7:0]=x22]
12914 +V_BLANKI[7:0]=x2A 42                                           Input lines from vsync to first active line
12915 +V_BLANKO[7:0]=x16 22
12916 +V_LINESI[9:0]=x271 625  [V_LINESI[9:8]=2; V_LINESI[7:0]=x71]   Number of input lines
12917 +V_SCALE[13:0]=x1000 4096  [V_SCALE[13:8]=x10; V_SCALE[7:0]=0]  Vert scale coefficient="none"?
12918 +YATTENUATE[2:0]=0                                              no luma attenuation
12919 +YCORING[2:0]=0                                                 Luma-coring bypass
12920 +YLPF[1:0]=0                                                    Luma hoz low pass filter=bypass
12921 +
12922 +***************** */
12923 +
12924 +static u16 registers_720_576[] =
12925 +    {
12926 +      0x6e, 0x00,      /* HSYNOFFSET[7:0]=0 */
12927 +      0x70, 0x02,      /* HSYNOFFSET[9:8]=0; HSYNWIDTH[5:0]=2 */
12928 +      0x72, 0x00,      /* VSYNOFFSET[7:0]=0 */
12929 +      0x74, 0x01,      /* DATDLY = 0; DATSWP=0; VSYNOFFSET[10:8]=0; VSYNWIDTH[2:0]=1 */
12930 +      0x76, 0xe0,      /* H_CLKO[7:0]=xe0 */
12931 +      0x78, 0xd0,      /* H_ACTIVE[7:0]=xD0 */
12932 +      0x7a, 0x80,      /* HSYNC_WIDTH[7:0]=x80 */
12933 +      0x7c, 0x98,      /* HBURST_BEGIN[7:0]=x98 */
12934 +      0x7e, 0x58,      /* HBURST_END[7:0]=x58 */
12935 +      0x80, 0x20,      /* H_BLANKO[7:0]=x20 */
12936 +      0x82, 0x16,      /* V_BLANKO[7:0]=x16 */
12937 +      0x84, 0x22,      /* V_ACTIVEO[7:0]=x22 */
12938 +      0x86, 0xa6,      /* V_ACTIVE0[8]=1; H_ACTIVE[9:8]=2; H_CLKO[11:8]=6 */
12939 +      0x88, 0x00,      /* H_FRACT[7:0]=0 */
12940 +      0x8a, 0x78,      /* H_CLKI[7:0]=x78 */
12941 +      0x8c, 0x80,      /* H_BLANKI[7:0]=x84 */
12942 +      0x8e, 0x03,      /* VBLANKDLY=0; H_BLANKI[8]=0; H_CLKI[10:8]=3 */
12943 +      0x90, 0x71,      /* V_LINESI[7:0]=x71 */
12944 +      0x92, 0x2a,      /* V_BLANKI[7:0]=x2A */
12945 +      0x94, 0x40,      /* V_ACTIVEI[7:0]=x40 */
12946 +      0x96, 0x0a,      /* CLPF[1:0]=0; YLPF[1:0]=0; V_ACTIVEI[9:0]=2; V_LINESI[9:8]=2 */
12947 +      0x98, 0x00,      /* V_SCALE[7:0]=0 */
12948 +      0x9a, 0x50,      /* H_BLANKO[9:8]=1; V_SCALE[13:8]=x10 */
12949 +      0x9c, 0x30,      /* PLL_FRACT[7:0]=x30 */
12950 +      0x9e, 0x0,       /* PLL_FRACT[15:8]=0x0 */
12951 +      0xa0, 0x8c,      /* EN_XCLK=1; BY_PLL=0; PLL_INT[5:0]=0x0C */
12952 +      0xa2, 0x24,      /* ECLIP=0; PAL_MD=1; DIS_SCRESET=0; VSYNC_DUR=0; 625LINE=1; SETUP=0; NI_OUT=0 */
12953 +      0xa4, 0xf0,      /* SYNC_AMP[7:0]=xF0 */
12954 +      0xa6, 0x57,      /* BST_AMP[7:0]=x57 */
12955 +      0xa8, 0x82,      /* MCR[7:0]=x82 */
12956 +      0xaa, 0x49,      /* MCB[7:0]=x49 */
12957 +      0xac, 0x8c,      /* MY[7:0]=x8C */
12958 +      0xae, 0xb4,      /* MSC[7:0]=xb4 */
12959 +      0xb0, 0xe0,      /* MSC[15:8]=xe0 */
12960 +      0xb2, 0x45,      /* MSC[23:16]=x45 */
12961 +      0xb4, 0x29,      /* MSC[31:24]=x29 */
12962 +      0xb6, 0x00,      /* PHASE_OFF[7:0]=0 */
12963 +      //0xba, 0x21,    /* SRESET=0; CHECK_STAT=0; SLAVER=1; DACOFF=0; DACDISC=0; DACDISB=0; DACDISA=1 */
12964 +      0xc4, 0x01,      /* ESTATUS[1:0]=0; ECCF2=0; ECCF1=0; ECCGATE=0; ECBAR=0; DCHROMA=0; EN_OUT=1 */
12965 +      0xc6, 0x00,      /* EN_BLANKO=0; EN_DOT=0; FIELDI=0; VSYNCI=0; HSYNCI=0; IN_MODE[2:0]=0(24bRGB) */
12966 +      0xc8, 0x40,      /* DIS_YFLPF=0; DIS_FFILT=1; F_SELC[2:0]=0; F_SELY[2:0]=0 */
12967 +      0xca, 0xc0,      /* DIS_GMUSHY=1; DIS_GMSHY=1; YCORING[2:0]=0; YATTENUATE[2:0]=0 */
12968 +      0xcc, 0xc0,      /* DIS_GMUSHC=1; DIS_GMSHC=1; CCORING[2:0]=0; CATTENUATE[2:0]=0 */
12969 +      //0xce, 0x24,       /* OUT_MUXC=2 [C]; OUT_MUXB=1 [Y]; OUT_MUXA=0 [CVBS, but disabled]*/
12970 +      //0xce, 0x04,       /* OUT_MUXC=0 [CVBS]; OUT_MUXB=1 [Y]; OUT_MUXA=0 [CVBS, but disabled]*/
12971 +      0xd6, 0x00,      /* OUT_MODE[1:0]=0; LUMADLY[1:0]=0 */
12972 +      0, 0
12973 +    };
12974 +
12975 +
12976 +/* ******************
12977 +
12978 +720x480, 27.5MHz, NTSC no overscan compensation.
12979 +
12980 +This mode should be use for digital video, DVD playback etc.
12981 +
12982 +NOTE: This mode for NTSC, see 720x576 for an equivalent PAL mode
12983 +NOTE:    -- Steve Davies <steve@daviesfam.org>
12984 +
12985 +Compatible X modeline:
12986 +
12987 +    Mode        "720x480-BT869"
12988 +        DotClock        27.5
12989 +        HTimings        720 744 800 872
12990 +        VTimings        480 483 485 525
12991 +    EndMode
12992 +
12993 +
12994 +625LINE=0                                                      not 625 line output format
12995 +BST_AMP[7:0]=x74 116                                           Burst ampl. multiplication factor (NTSC std??)
12996 +BY_PLL=0                                                       Use the PLL
12997 +CATTENUATE[2:0]=0                                              No chroma attenuation
12998 +CCF1B1[7:0]=0                                                  close caption stuff
12999 +CCF1B2[7:0]=0                                                  close caption stuff
13000 +CCF2B1[7:0]=0                                                  close caption stuff
13001 +CCF2B2[7:0]=0                                                  close caption stuff
13002 +CCORING[2:0]=0                                                 Bypass chroma coring
13003 +CCR_START[8:0]=0 [CCR_START[8]=0; CCR_START[7:0]=0]            Close-caption clock runin start from hsync
13004 +CC_ADD[11:0]=xD2 210  [CC_ADD[11:8]=0; CC_ADD[7:0]=xD2]                Close-caption DTO increment
13005 +CHECK_STAT=0                                                   Don't check monitor status
13006 +CLPF[1:0]=0                                                    Hoz chroma lowpass filter=Bypass
13007 +DACDISA=1                                                      Disable DACA
13008 +DACDISB=0                                                      Don't disable DACB
13009 +DACDISC=0                                                      Don't disable DACC
13010 +DACOFF=0                                                       Don't disable the DACs
13011 +DATDLY = 0                                                     normal
13012 +DATSWP=0                                                       normal
13013 +DCHROMA=0                                                      Don't blank chroma
13014 +DIS_FFILT=1                                                    Disable flickerfilter
13015 +DIS_GMSHC=1                                                    Disable chroma psuedo-gamma removal
13016 +DIS_GMSHY=1                                                    Disable luma pseudo gamma removal
13017 +DIS_GMUSHC=1                                                   Disable chroma anti-pseudo gamma removal
13018 +DIS_GMUSHY=1                                                   Disable luma anti-pseudo gamma removal
13019 +DIS_SCRESET=0                                                  Normal subcarrier phase resets
13020 +DIS_YFLPF=0                                                    Disable Luma initial hoz low pass filter
13021 +DIV2=0                                                         Input pixel rate not divided by 2
13022 +ECBAR=0                                                                No colour bars
13023 +ECCF1=0                                                                Disable closed caption
13024 +ECCF2=0                                                                Disable closed caption
13025 +ECCGATE=0                                                      Normal close caption encoding
13026 +ECLIP=0                                                                0=disable clipping
13027 +EN_ASYNC=0                                                     set to 0 for normal operation
13028 +EN_BLANKO=0                                                    BLANK is an input
13029 +EN_DOT=0                                                       Disables dot clock sync on BLANK pin
13030 +EN_OUT=1                                                       Allows outputs to be enabled
13031 +EN_XCLK=1                                                      Use CLKI pin as clock source
13032 +ESTATUS[1:0]=0                                                 Used to select readback register
13033 +FIELDI=0                                                       Logical 1 on FIELD indicates even field
13034 +F_SELC[2:0]=0                                                  5 line chroma flickerfilter
13035 +F_SELY[2:0]=0                                                  5 line luma flickerfilter
13036 +HBURST_BEGIN[7:0]=x92 146                                      Chroma burst start point in clocks
13037 +HBURST_END[7:0]=x57 87                                         Chroma burst end point in clocks - 128
13038 +HSYNCI=0                                                       Active low HSYNC
13039 +HSYNC_WIDTH[7:0]=x80 128                                       Analogue sync width in clocks
13040 +HSYNOFFSET[9:0]=0  [HSYNOFFSET[9:8]=0; HSYNOFFSET[7:0]=0]      hsync in "standard position"
13041 +HSYNWIDTH[5:0]=2                                               2 pixel hsync width
13042 +H_ACTIVE[9:0]=x2D0 720  [H_ACTIVE[9:8]=2; H_ACTIVE[7:0]=xD0]   Active pixels per line
13043 +H_BLANKI[8:0]=x80 128  [H_BLANKI[8]=0; H_BLANKI[7:0]=x80]      End of blanking of input video
13044 +H_BLANKO[9:0]=x102 258  [H_BLANKO[9:8]=1; H_BLANKO[7:0]=x2]    End of blanking from hoz sync leading edge
13045 +H_CLKI[10:0]=x368 872  [H_CLKI[10:8]=3; H_CLKI[7:0]=x68]       Input line length total in clocks
13046 +H_CLKO[11:0]=x6d0 1744  [H_CLKO[11:8]=6; H_CLKO[7:0]=xD0]      Output clocks per line
13047 +H_FRACT[7:0]=0                                                 0 fractional input clocks per line
13048 +IN_MODE[2:0]=0                                                 24Bit RGB muxed
13049 +LUMADLY[1:0]=0                                                 0 pixel delay on Y_DLY luma
13050 +MCB[7:0]=x43 67                                                        Mult factor for CB prior to subcarrier mod.
13051 +MCR[7:0]=x77 119                                               Mult factor for CR prior to subcarrier mod.
13052 +MODE2X=0                                                       Don't divide clock input by 2
13053 +MSC[31:0]=x215282E5 559055589  [MSC[31:24]=x21; MSC[23:16]=x52; MSC[15:8]=x82; MSC[7:0]=xE5] Subcarrier incr.
13054 +MY[7:0]=x85 133                                                        Mult factor for Y
13055 +NI_OUT=0                                                       Normal interlaced output
13056 +OUT_MODE[1:0]=0                                                        video0-3 is CVBS, Y, C, Y_DLY
13057 +OUT_MUXA[1:0]=0                                                        Don't care as DACA is disabled
13058 +OUT_MUXB[1:0]=1                                                        Output video[1] (Y) on DACB
13059 +OUT_MUXC[1:0]=2                                                        Output video[2] (C) on DACC
13060 +PAL_MD=0                                                       Video output in PAL mode? No.
13061 +PHASE_OFF[7:0]=0                                               Subcarrier phase offset
13062 +PLL_FRACT[15:0]=x30 48  [PLL_FRACT[15:8]=0x0; PLL_FRACT[7:0]=x30] frac portion of pll multiplier
13063 +PLL_INT[5:0]=0x0C 12                                           Int portion of pll multiplier
13064 +SETUP=1                                                                7.5-IRE enabled for NTSC
13065 +SLAVER=1                                                       
13066 +SRESET=0                                                       Don't do a software reset
13067 +SYNC_AMP[7:0]=xE5 229                                          Sync amp mult. factor (PAL std???)
13068 +VBLANKDLY=0                                                    Extra line of blanking in 2nd field?
13069 +VSYNCI=0                                                       Active low VSYNC
13070 +VSYNC_DUR=1                                                    2.5line VSYNC duration on output (Yes for NTSC)
13071 +VSYNCOFFSET[10:0]=0  [VSYNOFFSET[10:8]=0; VSYNOFFSET[7:0]=0]   VSYNC in standard position
13072 +VSYNWIDTH[2:0]=1                                               1 line of vsync width
13073 +V_ACTIVEI[9:0]=x1E0 480  [V_ACTIVEI[9:0]=1; V_ACTIVEI[7:0]=xE0]        Active input lines
13074 +V_ACTIVEO[8:0]=xF0 240  [V_ACTIVE0[8]=0; V_ACTIVEO[7:0]=xF0]
13075 +V_BLANKI[7:0]=x2A 42                                           Input lines from vsync to first active line
13076 +V_BLANKO[7:0]=x16 22
13077 +V_LINESI[9:0]=x20D 525  [V_LINESI[9:8]=2; V_LINESI[7:0]=x0D]   Number of input lines
13078 +V_SCALE[13:0]=x1000 4096  [V_SCALE[13:8]=x10; V_SCALE[7:0]=0]  Vert scale coefficient="none"?
13079 +YATTENUATE[2:0]=0                                              no luma attenuation
13080 +YCORING[2:0]=0                                                 Luma-coring bypass
13081 +YLPF[1:0]=0                                                    Luma hoz low pass filter=bypass
13082 +
13083 +***************** */
13084 +
13085 +static u16 registers_720_480[] =
13086 +    {
13087 +      0x6e, 0x00,      /* HSYNOFFSET[7:0]=0 */
13088 +      0x70, 0x02,      /* HSYNOFFSET[9:8]=0; HSYNWIDTH[5:0]=2 */
13089 +      0x72, 0x00,      /* VSYNOFFSET[7:0]=0 */
13090 +      0x74, 0x01,      /* DATDLY = 0; DATSWP=0; VSYNOFFSET[10:8]=0; VSYNWIDTH[2:0]=1 */
13091 +      0x76, 0xD0,      /* H_CLKO[7:0]=xD0 */
13092 +      0x78, 0xD0,      /* H_ACTIVE[7:0]=xD0 */
13093 +      0x7a, 0x80,      /* HSYNC_WIDTH[7:0]=x80 */
13094 +      0x7c, 0x92,      /* HBURST_BEGIN[7:0]=x92 */
13095 +      0x7e, 0x57,      /* HBURST_END[7:0]=x57 */
13096 +      0x80, 0x02,      /* H_BLANKO[7:0]=x2 */
13097 +      0x82, 0x16,      /* V_BLANKO[7:0]=x16 */
13098 +      0x84, 0xF0,      /* V_ACTIVEO[7:0]=xF0 */
13099 +      0x86, 0x26,      /* V_ACTIVE0[8]=0; H_ACTIVE[9:8]=2; H_CLKO[11:8]=6 */
13100 +      0x88, 0x00,      /* H_FRACT[7:0]=0 */
13101 +      0x8a, 0xD0,      /* H_CLKI[7:0]=xD0 */
13102 +      0x8c, 0x80,      /* H_BLANKI[7:0]=x80 */
13103 +      0x8e, 0x03,      /* VBLANKDLY=0; H_BLANKI[8]=0; H_CLKI[10:8]=3 */
13104 +      0x90, 0x0D,      /* V_LINESI[7:0]=x0D */
13105 +      0x92, 0x2A,      /* V_BLANKI[7:0]=x2A */
13106 +      0x94, 0xE0,      /* V_ACTIVEI[7:0]=xE0 */
13107 +      0x96, 0x06,      /* CLPF[1:0]=0; YLPF[1:0]=0; V_ACTIVEI[9:8]=1; V_LINESI[9:8]=2 */
13108 +      0x98, 0x00,      /* V_SCALE[7:0]=0 */
13109 +      0x9a, 0x50,      /* H_BLANKO[9:8]=1; V_SCALE[13:8]=x10 */
13110 +      0x9c, 0x30,      /* PLL_FRACT[7:0]=x30 */
13111 +      0x9e, 0x0,       /* PLL_FRACT[15:8]=0x0 */
13112 +      0xa0, 0x8c,      /* EN_XCLK=1; BY_PLL=0; PLL_INT[5:0]=0x0C */
13113 +      0xa2, 0x0A,      /* ECLIP=0; PAL_MD=0; DIS_SCRESET=0; VSYNC_DUR=1; 625LINE=0; SETUP=1; NI_OUT=0 */
13114 +      0xa4, 0xE5,      /* SYNC_AMP[7:0]=xE5 */
13115 +      0xa6, 0x74,      /* BST_AMP[7:0]=x74 */
13116 +      0xa8, 0x77,      /* MCR[7:0]=x77 */
13117 +      0xaa, 0x43,      /* MCB[7:0]=x43 */
13118 +      0xac, 0x85,      /* MY[7:0]=x85 */
13119 +      0xae, 0xE5,      /* MSC[7:0]=xE5 */
13120 +      0xb0, 0x82,      /* MSC[15:8]=x82 */
13121 +      0xb2, 0x52,      /* MSC[23:16]=x52 */
13122 +      0xb4, 0x21,      /* MSC[31:24]=x21 */
13123 +      0xb6, 0x00,      /* PHASE_OFF[7:0]=0 */
13124 +      //0xba, 0x21,    /* SRESET=0; CHECK_STAT=0; SLAVER=1; DACOFF=0; DACDISC=0; DACDISB=0; DACDISA=1 */
13125 +      0xc4, 0x01,      /* ESTATUS[1:0]=0; ECCF2=0; ECCF1=0; ECCGATE=0; ECBAR=0; DCHROMA=0; EN_OUT=1 */
13126 +      0xc6, 0x00,      /* EN_BLANKO=0; EN_DOT=0; FIELDI=0; VSYNCI=0; HSYNCI=0; IN_MODE[2:0]=0(24bRGB) */
13127 +      0xc8, 0x40,      /* DIS_YFLPF=0; DIS_FFILT=1; F_SELC[2:0]=0; F_SELY[2:0]=0 */
13128 +      0xca, 0xc0,      /* DIS_GMUSHY=1; DIS_GMSHY=1; YCORING[2:0]=0; YATTENUATE[2:0]=0 */
13129 +      0xcc, 0xc0,      /* DIS_GMUSHC=1; DIS_GMSHC=1; CCORING[2:0]=0; CATTENUATE[2:0]=0 */
13130 +      //0xce, 0x24,       /* OUT_MUXC=2 [C]; OUT_MUXB=1 [Y]; OUT_MUXA=0 [CVBS, but disabled]*/
13131 +      //0xce, 0x04,       /* OUT_MUXC=0 [CVBS]; OUT_MUXB=1 [Y]; OUT_MUXA=0 [CVBS, but disabled]*/
13132 +      0xd6, 0x00,      /* OUT_MODE[1:0]=0; LUMADLY[1:0]=0 */
13133 +      0, 0
13134 +    };
13135 +
13136 +
13137 +int bt869_id = 0;
13138 +
13139 +static int bt869_attach_adapter(struct i2c_adapter *adapter)
13140 +{
13141 +       return i2c_detect(adapter, &addr_data, bt869_detect);
13142 +}
13143 +
13144 +/* This function is called by i2c_detect */
13145 +int bt869_detect(struct i2c_adapter *adapter, int address,
13146 +                unsigned short flags, int kind)
13147 +{
13148 +       int i, cur;
13149 +       struct i2c_client *new_client;
13150 +       struct bt869_data *data;
13151 +       int err = 0;
13152 +       const char *type_name, *client_name;
13153 +
13154 +
13155 +       printk("bt869.o:  probing address %d .\n", address);
13156 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
13157 +          at this moment; i2c_detect really won't call us. */
13158 +#ifdef DEBUG
13159 +       if (i2c_is_isa_adapter(adapter)) {
13160 +               printk
13161 +                   ("bt869.o: bt869_detect called for an ISA bus adapter?!?\n");
13162 +               return 0;
13163 +       }
13164 +#endif
13165 +
13166 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE |
13167 +                                    I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
13168 +                   goto ERROR0;
13169 +
13170 +       /* OK. For now, we presume we have a valid client. We now create the
13171 +          client structure, even though we cannot fill it completely yet.
13172 +          But it allows us to access bt869_{read,write}_value. */
13173 +       if (!(data = kmalloc(sizeof(struct bt869_data), GFP_KERNEL))) {
13174 +               err = -ENOMEM;
13175 +               goto ERROR0;
13176 +       }
13177 +
13178 +       new_client = &data->client;
13179 +       new_client->addr = address;
13180 +       new_client->data = data;
13181 +       new_client->adapter = adapter;
13182 +       new_client->driver = &bt869_driver;
13183 +       new_client->flags = 0;
13184 +
13185 +       /* Now, we do the remaining detection. It is lousy. */
13186 +       i2c_smbus_write_byte_data(new_client, 0xC4, 0); /* set status bank 0 */
13187 +       cur = i2c_smbus_read_byte(new_client);
13188 +       printk("bt869.o: address 0x%X testing-->0x%X\n", address, cur);
13189 +       if ((cur & 0xE0) != 0x20)
13190 +               goto ERROR1;
13191 +
13192 +       /* Determine the chip type */
13193 +       kind = ((cur & 0x20) >> 5);
13194 +
13195 +       if (kind) {
13196 +               type_name = "bt869";
13197 +               client_name = "bt869 chip";
13198 +               printk("bt869.o: BT869 detected\n");
13199 +       } else {
13200 +               type_name = "bt868";
13201 +               client_name = "bt868 chip";
13202 +               printk("bt869.o: BT868 detected\n");
13203 +       }
13204 +
13205 +       /* Fill in the remaining client fields and put it into the global list */
13206 +       strcpy(new_client->name, client_name);
13207 +
13208 +       new_client->id = bt869_id++;
13209 +       data->valid = 0;
13210 +       init_MUTEX(&data->update_lock);
13211 +
13212 +       /* Tell the I2C layer a new client has arrived */
13213 +       if ((err = i2c_attach_client(new_client)))
13214 +               goto ERROR3;
13215 +
13216 +       /* Register a new directory entry with module sensors */
13217 +       if ((i = i2c_register_entry(new_client, type_name,
13218 +                                       bt869_dir_table_template)) < 0) {
13219 +               err = i;
13220 +               goto ERROR4;
13221 +       }
13222 +       data->sysctl_id = i;
13223 +
13224 +       bt869_init_client((struct i2c_client *) new_client);
13225 +       return 0;
13226 +
13227 +/* OK, this is not exactly good programming practice, usually. But it is
13228 +   very code-efficient in this case. */
13229 +
13230 +      ERROR4:
13231 +       i2c_detach_client(new_client);
13232 +      ERROR3:
13233 +      ERROR1:
13234 +       kfree(data);
13235 +      ERROR0:
13236 +       return err;
13237 +}
13238 +
13239 +static int bt869_detach_client(struct i2c_client *client)
13240 +{
13241 +       int err;
13242 +
13243 +       i2c_deregister_entry(((struct bt869_data *) (client->data))->
13244 +                                sysctl_id);
13245 +
13246 +       if ((err = i2c_detach_client(client))) {
13247 +               printk
13248 +                   ("bt869.o: Client deregistration failed, client not detached.\n");
13249 +               return err;
13250 +       }
13251 +
13252 +       kfree(client->data);
13253 +
13254 +       return 0;
13255 +}
13256 +
13257 +
13258 +/* All registers are byte-sized.
13259 +   bt869 uses a high-byte first convention, which is exactly opposite to
13260 +   the usual practice. */
13261 +static int bt869_read_value(struct i2c_client *client, u8 reg)
13262 +{
13263 +       return i2c_smbus_read_byte(client);
13264 +}
13265 +
13266 +/* All registers are byte-sized.
13267 +   bt869 uses a high-byte first convention, which is exactly opposite to
13268 +   the usual practice. */
13269 +static int bt869_write_value(struct i2c_client *client, u8 reg, u16 value)
13270 +{
13271 +#ifdef DEBUG
13272 +        printk("bt869.o: write_value(0x%X, 0x%X)\n", reg, value);
13273 +#endif
13274 +       return i2c_smbus_write_byte_data(client, reg, value);
13275 +}
13276 +
13277 +static void bt869_write_values(struct i2c_client *client, u16 *values)
13278 +{
13279 +  /* writes set of registers from array.  0,0 marks end of table */
13280 +  while (*values) {
13281 +    bt869_write_value(client, values[0], values[1]);
13282 +    values += 2;
13283 +  }
13284 +}
13285 +
13286 +static void bt869_init_client(struct i2c_client *client)
13287 +{
13288 +       struct bt869_data *data = client->data;
13289 +
13290 +       /* Initialize the bt869 chip */
13291 +       bt869_write_value(client, 0x0ba, 0x80);
13292 +       //   bt869_write_value(client,0x0D6, 0x00);
13293 +       /* Be a slave to the clock on the Voodoo3 */
13294 +       bt869_write_value(client, 0xa0, 0x80);
13295 +       bt869_write_value(client, 0xba, 0x20);
13296 +       /* depth =16bpp */
13297 +       bt869_write_value(client, 0x0C6, 0x001);
13298 +       bt869_write_value(client, 0xC4, 1);
13299 +       /* Flicker free enable and config */
13300 +       bt869_write_value(client, 0xC8, 0);
13301 +       data->res[0] = 640;
13302 +       data->res[1] = 480;
13303 +       data->ntsc = 1;
13304 +       data->half = 0;
13305 +       data->colorbars = 0;
13306 +       data->svideo = 0;
13307 +       data->depth = 16;
13308 +
13309 +}
13310 +
13311 +static void bt869_update_client(struct i2c_client *client)
13312 +{
13313 +       struct bt869_data *data = client->data;
13314 +
13315 +       down(&data->update_lock);
13316 +
13317 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
13318 +           (jiffies < data->last_updated) || !data->valid) {
13319 +#ifdef DEBUG
13320 +               printk("Starting bt869 update\n");
13321 +#endif
13322 +               if ((data->res[0] == 800) && (data->res[1] == 600)) {
13323 +                       /* 800x600 built-in mode */
13324 +                       bt869_write_value(client, 0xB8,
13325 +                                         (2 + (!data->ntsc)));
13326 +                       bt869_write_value(client, 0xa0, 0x80 + 0x11);
13327 +                       printk("bt869.o: writing into config -->0x%X\n",
13328 +                              (2 + (!data->ntsc)));
13329 +               }
13330 +               else if ((data->res[0] == 720) && (data->res[1] == 576)) {
13331 +                       /* 720x576 no-overscan-compensation mode suitable for PAL DVD playback */
13332 +                       data->ntsc = 0; /* This mode always PAL */
13333 +                       bt869_write_values(client,  registers_720_576);
13334 +               }
13335 +               else if ((data->res[0] == 720) && (data->res[1] == 480)) {
13336 +                       /* 720x480 no-overscan-compensation mode suitable for NTSC DVD playback */
13337 +                       data->ntsc = 1; /* This mode always NTSC */
13338 +                       bt869_write_values(client,  registers_720_480);
13339 +               }
13340 +               else {
13341 +                       /* 640x480 built-in mode */
13342 +                       bt869_write_value(client, 0xB8, (!data->ntsc));
13343 +                       bt869_write_value(client, 0xa0, 0x80 + 0x0C);
13344 +                       printk("bt869.o: writing into config -->0x%X\n",
13345 +                              (0 + (!data->ntsc)));
13346 +                       if ((data->res[0] != 640) || (data->res[1] != 480)) {
13347 +                         printk
13348 +                           ("bt869.o:  Warning: arbitrary resolutions not supported yet.  Using 640x480.\n");
13349 +                         data->res[0] = 640;
13350 +                         data->res[1] = 480;
13351 +                       }
13352 +               }
13353 +               /* Set colour depth */
13354 +               if ((data->depth != 24) && (data->depth != 16))
13355 +                       data->depth = 16;
13356 +               if (data->depth == 16)
13357 +                       bt869_write_value(client, 0x0C6, 0x001);
13358 +               if (data->depth == 24)
13359 +                       bt869_write_value(client, 0x0C6, 0x000);
13360 +               /* set "half" resolution mode */
13361 +               bt869_write_value(client, 0xd4, data->half << 6);
13362 +               /* Set composite/svideo mode, also enable the right dacs */
13363 +               switch (data->svideo) {
13364 +               case 2:  /* RGB */
13365 +                 /* requires hardware mod on Voodoo3 to get all outputs,
13366 +                    untested in practice... Feedback to steve@daviesfam.org please */
13367 +                 bt869_write_value(client, 0xd6, 0x0c);
13368 +                 bt869_write_value(client, 0xce, 0x24);
13369 +                 bt869_write_value(client, 0xba, 0x20);
13370 +                 break;
13371 +               case 1:  /* Svideo*/
13372 +                 bt869_write_value(client, 0xce, 0x24);
13373 +                 bt869_write_value(client, 0xba, 0x21);
13374 +                 break;
13375 +               default:  /* Composite */
13376 +                 bt869_write_value(client, 0xce, 0x0);
13377 +                 bt869_write_value(client, 0xba, 0x21);
13378 +                 break;
13379 +               }
13380 +               /* Enable outputs */
13381 +               bt869_write_value(client, 0xC4, 1);
13382 +               /* Issue timing reset */
13383 +               bt869_write_value(client, 0x6c, 0x80);
13384 +
13385 +/* Read back status registers */
13386 +               bt869_write_value(client, 0xC4,
13387 +                                 1 | (data->colorbars << 2));
13388 +               data->status[0] = bt869_read_value(client, 1);
13389 +               bt869_write_value(client, 0xC4,
13390 +                                 0x41 | (data->colorbars << 2));
13391 +               data->status[1] = bt869_read_value(client, 1);
13392 +               bt869_write_value(client, 0xC4,
13393 +                                 0x81 | (data->colorbars << 2));
13394 +               data->status[2] = bt869_read_value(client, 1);
13395 +               bt869_write_value(client, 0xC4,
13396 +                                 0x0C1 | (data->colorbars << 2));
13397 +               data->last_updated = jiffies;
13398 +               data->valid = 1;
13399 +       }
13400 +       up(&data->update_lock);
13401 +}
13402 +
13403 +
13404 +void bt869_status(struct i2c_client *client, int operation, int ctl_name,
13405 +                 int *nrels_mag, long *results)
13406 +{
13407 +       struct bt869_data *data = client->data;
13408 +       if (operation == SENSORS_PROC_REAL_INFO)
13409 +               *nrels_mag = 0;
13410 +       else if (operation == SENSORS_PROC_REAL_READ) {
13411 +               bt869_update_client(client);
13412 +               results[0] = data->status[0];
13413 +               results[1] = data->status[1];
13414 +               results[2] = data->status[2];
13415 +               *nrels_mag = 3;
13416 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
13417 +               printk
13418 +                   ("bt869.o: Warning: write was requested on read-only proc file: status\n");
13419 +       }
13420 +}
13421 +
13422 +
13423 +void bt869_ntsc(struct i2c_client *client, int operation, int ctl_name,
13424 +               int *nrels_mag, long *results)
13425 +{
13426 +       struct bt869_data *data = client->data;
13427 +       if (operation == SENSORS_PROC_REAL_INFO)
13428 +               *nrels_mag = 0;
13429 +       else if (operation == SENSORS_PROC_REAL_READ) {
13430 +               bt869_update_client(client);
13431 +               results[0] = data->ntsc;
13432 +               *nrels_mag = 1;
13433 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
13434 +               if (*nrels_mag >= 1) {
13435 +                       data->ntsc = (results[0] > 0);
13436 +               }
13437 +               bt869_update_client(client);
13438 +       }
13439 +}
13440 +
13441 +
13442 +void bt869_svideo(struct i2c_client *client, int operation, int ctl_name,
13443 +               int *nrels_mag, long *results)
13444 +{
13445 +       struct bt869_data *data = client->data;
13446 +       if (operation == SENSORS_PROC_REAL_INFO)
13447 +               *nrels_mag = 0;
13448 +       else if (operation == SENSORS_PROC_REAL_READ) {
13449 +               bt869_update_client(client);
13450 +               results[0] = data->svideo;
13451 +               *nrels_mag = 1;
13452 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
13453 +               if (*nrels_mag >= 1) {
13454 +                       data->svideo = results[0];
13455 +               }
13456 +               bt869_update_client(client);
13457 +       }
13458 +}
13459 +
13460 +
13461 +void bt869_res(struct i2c_client *client, int operation, int ctl_name,
13462 +              int *nrels_mag, long *results)
13463 +{
13464 +       struct bt869_data *data = client->data;
13465 +       if (operation == SENSORS_PROC_REAL_INFO)
13466 +               *nrels_mag = 0;
13467 +       else if (operation == SENSORS_PROC_REAL_READ) {
13468 +               bt869_update_client(client);
13469 +               results[0] = data->res[0];
13470 +               results[1] = data->res[1];
13471 +               *nrels_mag = 2;
13472 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
13473 +               if (*nrels_mag >= 1) {
13474 +                       data->res[0] = results[0];
13475 +               }
13476 +               if (*nrels_mag >= 2) {
13477 +                       data->res[1] = results[1];
13478 +               }
13479 +               bt869_update_client(client);
13480 +       }
13481 +}
13482 +
13483 +
13484 +void bt869_half(struct i2c_client *client, int operation, int ctl_name,
13485 +               int *nrels_mag, long *results)
13486 +{
13487 +       struct bt869_data *data = client->data;
13488 +       if (operation == SENSORS_PROC_REAL_INFO)
13489 +               *nrels_mag = 0;
13490 +       else if (operation == SENSORS_PROC_REAL_READ) {
13491 +               bt869_update_client(client);
13492 +               results[0] = data->half;
13493 +               *nrels_mag = 1;
13494 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
13495 +               if (*nrels_mag >= 1) {
13496 +                       data->half = (results[0] > 0);
13497 +                       bt869_update_client(client);
13498 +               }
13499 +       }
13500 +}
13501 +
13502 +void bt869_colorbars(struct i2c_client *client, int operation,
13503 +                    int ctl_name, int *nrels_mag, long *results)
13504 +{
13505 +       struct bt869_data *data = client->data;
13506 +       if (operation == SENSORS_PROC_REAL_INFO)
13507 +               *nrels_mag = 0;
13508 +       else if (operation == SENSORS_PROC_REAL_READ) {
13509 +               bt869_update_client(client);
13510 +               results[0] = data->colorbars;
13511 +               *nrels_mag = 1;
13512 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
13513 +               if (*nrels_mag >= 1) {
13514 +                       data->colorbars = (results[0] > 0);
13515 +                       bt869_update_client(client);
13516 +               }
13517 +       }
13518 +}
13519 +
13520 +void bt869_depth(struct i2c_client *client, int operation, int ctl_name,
13521 +                int *nrels_mag, long *results)
13522 +{
13523 +       struct bt869_data *data = client->data;
13524 +       if (operation == SENSORS_PROC_REAL_INFO)
13525 +               *nrels_mag = 0;
13526 +       else if (operation == SENSORS_PROC_REAL_READ) {
13527 +               bt869_update_client(client);
13528 +               results[0] = data->depth;
13529 +               *nrels_mag = 1;
13530 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
13531 +               if (*nrels_mag >= 1) {
13532 +                       data->depth = results[0];
13533 +                       bt869_update_client(client);
13534 +               }
13535 +       }
13536 +}
13537 +
13538 +static int __init sm_bt869_init(void)
13539 +{
13540 +       printk("bt869.o version %s (%s)\n", LM_VERSION, LM_DATE);
13541 +       return i2c_add_driver(&bt869_driver);
13542 +}
13543 +
13544 +static void __exit sm_bt869_exit(void)
13545 +{
13546 +       i2c_del_driver(&bt869_driver);
13547 +}
13548 +
13549 +
13550 +
13551 +MODULE_AUTHOR
13552 +    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Stephen Davies <steve@daviesfam.org>");
13553 +MODULE_DESCRIPTION("bt869 driver");
13554 +
13555 +module_init(sm_bt869_init);
13556 +module_exit(sm_bt869_exit);
13557 --- linux-old/drivers/sensors/ddcmon.c  Thu Jan  1 00:00:00 1970
13558 +++ linux/drivers/sensors/ddcmon.c      Mon Dec 13 20:18:45 2004
13559 @@ -0,0 +1,591 @@
13560 +/*
13561 +    ddcmon.c - Part of lm_sensors, Linux kernel modules for hardware
13562 +               monitoring
13563 +    Copyright (c) 1998, 1999, 2000  Frodo Looijaard <frodol@dds.nl>,
13564 +    Philip Edelbrock <phil@netroedge.com>,
13565 +    and Mark Studebaker <mdsxyz123@yahoo.com>
13566 +    Copyright (c) 2003  Jean Delvare <khali@linux-fr.org>
13567 +
13568 +    This program is free software; you can redistribute it and/or modify
13569 +    it under the terms of the GNU General Public License as published by
13570 +    the Free Software Foundation; either version 2 of the License, or
13571 +    (at your option) any later version.
13572 +
13573 +    This program is distributed in the hope that it will be useful,
13574 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
13575 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13576 +    GNU General Public License for more details.
13577 +
13578 +    You should have received a copy of the GNU General Public License
13579 +    along with this program; if not, write to the Free Software
13580 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13581 +*/
13582 +
13583 +#include <linux/module.h>
13584 +#include <linux/slab.h>
13585 +#include <linux/i2c.h>
13586 +#include <linux/i2c-proc.h>
13587 +#include <linux/init.h>
13588 +#define LM_DATE "20041007"
13589 +#define LM_VERSION "2.8.8"
13590 +
13591 +MODULE_LICENSE("GPL");
13592 +
13593 +/* Addresses to scan */
13594 +static unsigned short normal_i2c[] = { 0x50, SENSORS_I2C_END };
13595 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
13596 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
13597 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
13598 +
13599 +/* Insmod parameters */
13600 +SENSORS_INSMOD_1(ddcmon);
13601 +
13602 +static int checksum = 0;
13603 +MODULE_PARM(checksum, "i");
13604 +MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
13605 +
13606 +/* Many constants specified below */
13607 +
13608 +/* DDCMON registers */
13609 +/* vendor section */
13610 +#define DDCMON_REG_MAN_ID 0x08
13611 +#define DDCMON_REG_PROD_ID 0x0A
13612 +#define DDCMON_REG_SERIAL 0x0C
13613 +#define DDCMON_REG_WEEK 0x10
13614 +#define DDCMON_REG_YEAR 0x11
13615 +/* EDID version */
13616 +#define DDCMON_REG_EDID_VER 0x12
13617 +#define DDCMON_REG_EDID_REV 0x13
13618 +/* display information */
13619 +#define DDCMON_REG_HORSIZE 0x15
13620 +#define DDCMON_REG_VERSIZE 0x16
13621 +#define DDCMON_REG_GAMMA 0x17
13622 +#define DDCMON_REG_DPMS_FLAGS 0x18
13623 +/* supported timings */
13624 +#define DDCMON_REG_ESTABLISHED_TIMINGS 0x23
13625 +#define DDCMON_REG_STANDARD_TIMINGS 0x26
13626 +#define DDCMON_REG_TIMBASE 0x36
13627 +#define DDCMON_REG_TIMINCR 18
13628 +#define DDCMON_REG_TIMNUM   4
13629 +
13630 +#define DDCMON_REG_CHECKSUM 0x7f
13631 +
13632 +/* Size of DDCMON in bytes */
13633 +#define DDCMON_SIZE 128
13634 +
13635 +/* Each client has this additional data */
13636 +struct ddcmon_data {
13637 +       struct i2c_client client;
13638 +       int sysctl_id;
13639 +
13640 +       struct semaphore update_lock;
13641 +       char valid;             /* !=0 if following fields are valid */
13642 +       unsigned long last_updated;     /* In jiffies */
13643 +
13644 +       u8 data[DDCMON_SIZE];   /* Register values */
13645 +};
13646 +
13647 +
13648 +static int ddcmon_attach_adapter(struct i2c_adapter *adapter);
13649 +static int ddcmon_detect(struct i2c_adapter *adapter, int address,
13650 +                        unsigned short flags, int kind);
13651 +static int ddcmon_detach_client(struct i2c_client *client);
13652 +
13653 +static void ddcmon_idcall(struct i2c_client *client, int operation,
13654 +                           int ctl_name, int *nrels_mag, long *results);
13655 +static void ddcmon_size(struct i2c_client *client, int operation,
13656 +                           int ctl_name, int *nrels_mag, long *results);
13657 +static void ddcmon_sync(struct i2c_client *client, int operation,
13658 +                           int ctl_name, int *nrels_mag, long *results);
13659 +static void ddcmon_maxclock(struct i2c_client *client, int operation,
13660 +                           int ctl_name, int *nrels_mag, long *results);
13661 +static void ddcmon_timings(struct i2c_client *client, int operation,
13662 +                           int ctl_name, int *nrels_mag, long *results);
13663 +static void ddcmon_serial(struct i2c_client *client, int operation,
13664 +                           int ctl_name, int *nrels_mag, long *results);
13665 +static void ddcmon_time(struct i2c_client *client, int operation,
13666 +                           int ctl_name, int *nrels_mag, long *results);
13667 +static void ddcmon_edid(struct i2c_client *client, int operation,
13668 +                           int ctl_name, int *nrels_mag, long *results);
13669 +static void ddcmon_gamma(struct i2c_client *client, int operation,
13670 +                           int ctl_name, int *nrels_mag, long *results);
13671 +static void ddcmon_dpms(struct i2c_client *client, int operation,
13672 +                           int ctl_name, int *nrels_mag, long *results);
13673 +static void ddcmon_standard_timing(struct i2c_client *client, int operation,
13674 +                           int ctl_name, int *nrels_mag, long *results);
13675 +static void ddcmon_update_client(struct i2c_client *client);
13676 +
13677 +
13678 +/* This is the driver that will be inserted */
13679 +static struct i2c_driver ddcmon_driver = {
13680 +       .owner          = THIS_MODULE,
13681 +       .name           = "DDCMON READER",
13682 +       .id             = I2C_DRIVERID_DDCMON,
13683 +       .flags          = I2C_DF_NOTIFY,
13684 +       .attach_adapter = ddcmon_attach_adapter,
13685 +       .detach_client  = ddcmon_detach_client,
13686 +};
13687 +
13688 +/* -- SENSORS SYSCTL START -- */
13689 +
13690 +#define DDCMON_SYSCTL_ID 1010
13691 +#define DDCMON_SYSCTL_SIZE 1011
13692 +#define DDCMON_SYSCTL_SYNC 1012
13693 +#define DDCMON_SYSCTL_TIMINGS 1013
13694 +#define DDCMON_SYSCTL_SERIAL 1014
13695 +#define DDCMON_SYSCTL_TIME 1015
13696 +#define DDCMON_SYSCTL_EDID 1016
13697 +#define DDCMON_SYSCTL_GAMMA 1017
13698 +#define DDCMON_SYSCTL_DPMS 1018
13699 +#define DDCMON_SYSCTL_TIMING1 1021
13700 +#define DDCMON_SYSCTL_TIMING2 1022
13701 +#define DDCMON_SYSCTL_TIMING3 1023
13702 +#define DDCMON_SYSCTL_TIMING4 1024
13703 +#define DDCMON_SYSCTL_TIMING5 1025
13704 +#define DDCMON_SYSCTL_TIMING6 1026
13705 +#define DDCMON_SYSCTL_TIMING7 1027
13706 +#define DDCMON_SYSCTL_TIMING8 1028
13707 +#define DDCMON_SYSCTL_MAXCLOCK 1029
13708 +
13709 +/* -- SENSORS SYSCTL END -- */
13710 +
13711 +/* These files are created for each detected DDCMON. This is just a template;
13712 +   though at first sight, you might think we could use a statically
13713 +   allocated list, we need some way to get back to the parent - which
13714 +   is done through one of the 'extra' fields which are initialized
13715 +   when a new copy is allocated. */
13716 +static ctl_table ddcmon_dir_table_template[] = {
13717 +       {DDCMON_SYSCTL_ID, "id", NULL, 0, 0444, NULL, &i2c_proc_real,
13718 +        &i2c_sysctl_real, NULL, &ddcmon_idcall},
13719 +       {DDCMON_SYSCTL_SIZE, "size", NULL, 0, 0444, NULL, &i2c_proc_real,
13720 +        &i2c_sysctl_real, NULL, &ddcmon_size},
13721 +       {DDCMON_SYSCTL_SYNC, "sync", NULL, 0, 0444, NULL,
13722 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_sync},
13723 +       {DDCMON_SYSCTL_TIMINGS, "timings", NULL, 0, 0444, NULL,
13724 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_timings},
13725 +       {DDCMON_SYSCTL_SERIAL, "serial", NULL, 0, 0444, NULL,
13726 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_serial},
13727 +       {DDCMON_SYSCTL_TIME, "time", NULL, 0, 0444, NULL,
13728 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_time},
13729 +       {DDCMON_SYSCTL_EDID, "edid", NULL, 0, 0444, NULL,
13730 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_edid},
13731 +       {DDCMON_SYSCTL_GAMMA, "gamma", NULL, 0, 0444, NULL,
13732 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_gamma},
13733 +       {DDCMON_SYSCTL_DPMS, "dpms", NULL, 0, 0444, NULL,
13734 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_dpms},
13735 +       {DDCMON_SYSCTL_TIMING1, "timing1", NULL, 0, 0444, NULL,
13736 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13737 +       {DDCMON_SYSCTL_TIMING2, "timing2", NULL, 0, 0444, NULL,
13738 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13739 +       {DDCMON_SYSCTL_TIMING3, "timing3", NULL, 0, 0444, NULL,
13740 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13741 +       {DDCMON_SYSCTL_TIMING4, "timing4", NULL, 0, 0444, NULL,
13742 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13743 +       {DDCMON_SYSCTL_TIMING5, "timing5", NULL, 0, 0444, NULL,
13744 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13745 +       {DDCMON_SYSCTL_TIMING6, "timing6", NULL, 0, 0444, NULL,
13746 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13747 +       {DDCMON_SYSCTL_TIMING7, "timing7", NULL, 0, 0444, NULL,
13748 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13749 +       {DDCMON_SYSCTL_TIMING8, "timing8", NULL, 0, 0444, NULL,
13750 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
13751 +       {DDCMON_SYSCTL_MAXCLOCK, "maxclock", NULL, 0, 0444, NULL,
13752 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_maxclock},
13753 +       {0}
13754 +};
13755 +
13756 +static int ddcmon_id = 0;
13757 +
13758 +static int ddcmon_attach_adapter(struct i2c_adapter *adapter)
13759 +{
13760 +       return i2c_detect(adapter, &addr_data, ddcmon_detect);
13761 +}
13762 +
13763 +/* This function is called by i2c_detect */
13764 +int ddcmon_detect(struct i2c_adapter *adapter, int address,
13765 +                 unsigned short flags, int kind)
13766 +{
13767 +       int i, cs;
13768 +       struct i2c_client *new_client;
13769 +       struct ddcmon_data *data;
13770 +       int err = 0;
13771 +       const char *type_name, *client_name;
13772 +
13773 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
13774 +                   goto ERROR0;
13775 +
13776 +       /* OK. For now, we presume we have a valid client. We now create the
13777 +          client structure, even though we cannot fill it completely yet.
13778 +          But it allows us to access ddcmon_{read,write}_value. */
13779 +       if (!(data = kmalloc(sizeof(struct ddcmon_data), GFP_KERNEL))) {
13780 +               err = -ENOMEM;
13781 +               goto ERROR0;
13782 +       }
13783 +
13784 +       new_client = &data->client;
13785 +       memset(data->data, 0xff, DDCMON_SIZE);
13786 +       new_client->addr = address;
13787 +       new_client->data = data;
13788 +       new_client->adapter = adapter;
13789 +       new_client->driver = &ddcmon_driver;
13790 +       new_client->flags = 0;
13791 +
13792 +       /* prevent 24RF08 corruption (just in case) */
13793 +       i2c_smbus_write_quick(new_client, 0);
13794 +
13795 +       /* Now, we do the remaining detection. */
13796 +       if (checksum) {
13797 +               int cs = 0;
13798 +               for (i = 0; i < 0x80; i++)
13799 +                       cs += i2c_smbus_read_byte_data(new_client, i);
13800 +               if ((cs & 0xff) != 0)
13801 +                       goto ERROR1;
13802 +       }
13803 +
13804 +       /* Verify the first 8 locations 0x00FFFFFFFFFFFF00 */
13805 +       /* Allow force and force_ddcmon arguments */
13806 +       if(kind < 0)
13807 +       {
13808 +               for(i = 0; i < 8; i++) {
13809 +                       cs = i2c_smbus_read_byte_data(new_client, i);
13810 +                       if(i == 0 || i == 7) {
13811 +                               if(cs != 0)
13812 +                                       goto ERROR1;
13813 +                       } else if(cs != 0xff)
13814 +                               goto ERROR1;
13815 +               }
13816 +       }
13817 +
13818 +       type_name = "ddcmon";
13819 +       client_name = "DDC Monitor";
13820 +
13821 +       /* Fill in the remaining client fields and put it in the global list */
13822 +       strcpy(new_client->name, client_name);
13823 +
13824 +       new_client->id = ddcmon_id++;
13825 +       data->valid = 0;
13826 +       init_MUTEX(&data->update_lock);
13827 +
13828 +       /* Tell the I2C layer a new client has arrived */
13829 +       if ((err = i2c_attach_client(new_client)))
13830 +               goto ERROR3;
13831 +
13832 +       /* Register a new directory entry with module sensors */
13833 +       if ((i = i2c_register_entry(new_client, type_name,
13834 +                                       ddcmon_dir_table_template)) < 0) {
13835 +               err = i;
13836 +               goto ERROR4;
13837 +       }
13838 +       data->sysctl_id = i;
13839 +
13840 +       return 0;
13841 +
13842 +      ERROR4:
13843 +       i2c_detach_client(new_client);
13844 +      ERROR3:
13845 +      ERROR1:
13846 +       kfree(data);
13847 +      ERROR0:
13848 +       return err;
13849 +}
13850 +
13851 +static int ddcmon_detach_client(struct i2c_client *client)
13852 +{
13853 +       int err;
13854 +
13855 +       i2c_deregister_entry(((struct ddcmon_data *) (client->data))->
13856 +                                sysctl_id);
13857 +       if ((err = i2c_detach_client(client))) {
13858 +               printk
13859 +                   ("ddcmon.o: Client deregistration failed, client not detached.\n");
13860 +               return err;
13861 +       }
13862 +       kfree(client->data);
13863 +       return 0;
13864 +}
13865 +
13866 +static void ddcmon_update_client(struct i2c_client *client)
13867 +{
13868 +       struct ddcmon_data *data = client->data;
13869 +       int i, j;
13870 +
13871 +       down(&data->update_lock);
13872 +
13873 +       if ((jiffies - data->last_updated > 300 * HZ) ||
13874 +           (jiffies < data->last_updated) || !data->valid) {
13875 +               if (i2c_check_functionality(client->adapter,
13876 +                                           I2C_FUNC_SMBUS_READ_I2C_BLOCK))
13877 +               {
13878 +                       for (i=0; i<DDCMON_SIZE; i+=I2C_SMBUS_I2C_BLOCK_MAX)
13879 +                               if (i2c_smbus_read_i2c_block_data(client,
13880 +                                                          i, data->data + i)
13881 +                                                   != I2C_SMBUS_I2C_BLOCK_MAX) {
13882 +                                       printk(KERN_WARNING "ddcmon.o: block read fail at 0x%.2x!\n", i);
13883 +                                       goto DONE;
13884 +                               }
13885 +               } else {
13886 +                       if (i2c_smbus_write_byte(client, 0)) {
13887 +                               printk(KERN_WARNING "ddcmon.o: read start fail at 0!\n");
13888 +                               goto DONE;
13889 +                       }
13890 +                       for (i = 0; i < DDCMON_SIZE; i++) {
13891 +                               j = i2c_smbus_read_byte(client);
13892 +                               if (j < 0) {
13893 +                                       printk(KERN_WARNING "eeprom.o: read fail at 0x%.2x!\n", i);
13894 +                                       goto DONE;
13895 +                               }
13896 +                               data->data[i] = (u8) j;
13897 +                       }
13898 +               }
13899 +               data->last_updated = jiffies;
13900 +               data->valid = 1;
13901 +       }
13902 +DONE:
13903 +       up(&data->update_lock);
13904 +}
13905 +
13906 +
13907 +void ddcmon_idcall(struct i2c_client *client, int operation,
13908 +                  int ctl_name, int *nrels_mag, long *results)
13909 +{
13910 +       struct ddcmon_data *data = client->data;
13911 +
13912 +       if (operation == SENSORS_PROC_REAL_INFO)
13913 +               *nrels_mag = 0;
13914 +       else if (operation == SENSORS_PROC_REAL_READ) {
13915 +               ddcmon_update_client(client);
13916 +               results[0] = data->data[DDCMON_REG_MAN_ID + 1] |
13917 +                            (data->data[DDCMON_REG_MAN_ID] << 8);
13918 +               results[1] = data->data[DDCMON_REG_PROD_ID + 1] |
13919 +                            (data->data[DDCMON_REG_PROD_ID] << 8);
13920 +               *nrels_mag = 2;
13921 +       }
13922 +}
13923 +
13924 +void ddcmon_size(struct i2c_client *client, int operation,
13925 +                int ctl_name, int *nrels_mag, long *results)
13926 +{
13927 +       struct ddcmon_data *data = client->data;
13928 +
13929 +       if (operation == SENSORS_PROC_REAL_INFO)
13930 +               *nrels_mag = 0;
13931 +       else if (operation == SENSORS_PROC_REAL_READ) {
13932 +               ddcmon_update_client(client);
13933 +               results[0] = data->data[DDCMON_REG_VERSIZE];
13934 +               results[1] = data->data[DDCMON_REG_HORSIZE];
13935 +               *nrels_mag = 2;
13936 +       }
13937 +}
13938 +
13939 +void ddcmon_sync(struct i2c_client *client, int operation,
13940 +                   int ctl_name, int *nrels_mag, long *results)
13941 +{
13942 +       int i, j;
13943 +       struct ddcmon_data *data = client->data;
13944 +
13945 +       if (operation == SENSORS_PROC_REAL_INFO)
13946 +               *nrels_mag = 0;
13947 +       else if (operation == SENSORS_PROC_REAL_READ) {
13948 +               ddcmon_update_client(client);
13949 +               *nrels_mag = 4;
13950 +               /* look for monitor limits entry */
13951 +               for(i = DDCMON_REG_TIMBASE;
13952 +                   i < DDCMON_REG_TIMBASE +
13953 +                       (DDCMON_REG_TIMNUM * DDCMON_REG_TIMINCR);
13954 +                   i += DDCMON_REG_TIMINCR) {
13955 +                       if (data->data[i] == 0x00
13956 +                        && data->data[i + 1] == 0x00
13957 +                        && data->data[i + 2] == 0x00
13958 +                        && data->data[i + 3] == 0xfd) {
13959 +                               for(j = 0; j < 4; j++)
13960 +                                       results[j] = data->data[i + j + 5];
13961 +                               return;
13962 +                       }
13963 +               }
13964 +               for(j = 0; j < 4; j++)
13965 +                       results[j] = 0;
13966 +       }
13967 +}
13968 +
13969 +void ddcmon_maxclock(struct i2c_client *client, int operation,
13970 +                   int ctl_name, int *nrels_mag, long *results)
13971 +{
13972 +       int i;
13973 +       struct ddcmon_data *data = client->data;
13974 +
13975 +       if (operation == SENSORS_PROC_REAL_INFO)
13976 +               *nrels_mag = 0;
13977 +       else if (operation == SENSORS_PROC_REAL_READ) {
13978 +               ddcmon_update_client(client);
13979 +               *nrels_mag = 1;
13980 +               /* look for monitor limits entry */
13981 +               for(i = DDCMON_REG_TIMBASE;
13982 +                   i < DDCMON_REG_TIMBASE +
13983 +                       (DDCMON_REG_TIMNUM * DDCMON_REG_TIMINCR);
13984 +                   i += DDCMON_REG_TIMINCR) {
13985 +                       if (data->data[i] == 0x00
13986 +                        && data->data[i + 1] == 0x00
13987 +                        && data->data[i + 2] == 0x00
13988 +                        && data->data[i + 3] == 0xfd) {
13989 +                               results[0] = (data->data[i + 9] == 0xff ?
13990 +                                            0 : data->data[i + 9] * 10);
13991 +                               return;
13992 +                       }
13993 +               }
13994 +               results[0] = 0;
13995 +       }
13996 +}
13997 +
13998 +void ddcmon_timings(struct i2c_client *client, int operation,
13999 +                   int ctl_name, int *nrels_mag, long *results)
14000 +{
14001 +       struct ddcmon_data *data = client->data;
14002 +
14003 +       if (operation == SENSORS_PROC_REAL_INFO)
14004 +               *nrels_mag = 0;
14005 +       else if (operation == SENSORS_PROC_REAL_READ) {
14006 +               ddcmon_update_client(client);
14007 +               results[0] = data->data[DDCMON_REG_ESTABLISHED_TIMINGS] |
14008 +                            (data->data[DDCMON_REG_ESTABLISHED_TIMINGS + 1] << 8) |
14009 +                            (data->data[DDCMON_REG_ESTABLISHED_TIMINGS + 2] << 16);
14010 +               *nrels_mag = 1;
14011 +       }
14012 +}
14013 +
14014 +void ddcmon_serial(struct i2c_client *client, int operation,
14015 +                   int ctl_name, int *nrels_mag, long *results)
14016 +{
14017 +       struct ddcmon_data *data = client->data;
14018 +
14019 +       if (operation == SENSORS_PROC_REAL_INFO)
14020 +               *nrels_mag = 0;
14021 +       else if (operation == SENSORS_PROC_REAL_READ) {
14022 +               ddcmon_update_client(client);
14023 +               results[0] = data->data[DDCMON_REG_SERIAL] |
14024 +                            (data->data[DDCMON_REG_SERIAL + 1] << 8) |
14025 +                            (data->data[DDCMON_REG_SERIAL + 2] << 16) |
14026 +                            (data->data[DDCMON_REG_SERIAL + 3] << 24);
14027 +               *nrels_mag = 1;
14028 +       }
14029 +}
14030 +
14031 +void ddcmon_time(struct i2c_client *client, int operation,
14032 +                int ctl_name, int *nrels_mag, long *results)
14033 +{
14034 +       struct ddcmon_data *data = client->data;
14035 +
14036 +       if (operation == SENSORS_PROC_REAL_INFO)
14037 +               *nrels_mag = 0;
14038 +       else if (operation == SENSORS_PROC_REAL_READ) {
14039 +               ddcmon_update_client(client);
14040 +               results[0] = data->data[DDCMON_REG_YEAR] + 1990;
14041 +               results[1] = data->data[DDCMON_REG_WEEK];
14042 +               *nrels_mag = 2;
14043 +       }
14044 +}
14045 +
14046 +void ddcmon_edid(struct i2c_client *client, int operation,
14047 +                int ctl_name, int *nrels_mag, long *results)
14048 +{
14049 +       struct ddcmon_data *data = client->data;
14050 +
14051 +       if (operation == SENSORS_PROC_REAL_INFO)
14052 +               *nrels_mag = 0;
14053 +       else if (operation == SENSORS_PROC_REAL_READ) {
14054 +               ddcmon_update_client(client);
14055 +               results[0] = data->data[DDCMON_REG_EDID_VER];
14056 +               results[1] = data->data[DDCMON_REG_EDID_REV];
14057 +               *nrels_mag = 2;
14058 +       }
14059 +}
14060 +
14061 +void ddcmon_gamma(struct i2c_client *client, int operation,
14062 +                int ctl_name, int *nrels_mag, long *results)
14063 +{
14064 +       struct ddcmon_data *data = client->data;
14065 +
14066 +       if (operation == SENSORS_PROC_REAL_INFO)
14067 +               *nrels_mag = 2;
14068 +       else if (operation == SENSORS_PROC_REAL_READ) {
14069 +               ddcmon_update_client(client);
14070 +               results[0] = 100 + data->data[DDCMON_REG_GAMMA];
14071 +               *nrels_mag = 1;
14072 +       }
14073 +}
14074 +
14075 +void ddcmon_dpms(struct i2c_client *client, int operation,
14076 +                int ctl_name, int *nrels_mag, long *results)
14077 +{
14078 +       struct ddcmon_data *data = client->data;
14079 +
14080 +       if (operation == SENSORS_PROC_REAL_INFO)
14081 +               *nrels_mag = 0;
14082 +       else if (operation == SENSORS_PROC_REAL_READ) {
14083 +               ddcmon_update_client(client);
14084 +               results[0] = data->data[DDCMON_REG_DPMS_FLAGS];
14085 +               *nrels_mag = 1;
14086 +       }
14087 +}
14088 +
14089 +void ddcmon_standard_timing(struct i2c_client *client, int operation,
14090 +                int ctl_name, int *nrels_mag, long *results)
14091 +{
14092 +       struct ddcmon_data *data = client->data;
14093 +       int nr = ctl_name - DDCMON_SYSCTL_TIMING1;
14094 +
14095 +       if (operation == SENSORS_PROC_REAL_INFO)
14096 +               *nrels_mag = 0;
14097 +       else if (operation == SENSORS_PROC_REAL_READ) {
14098 +               ddcmon_update_client(client);
14099 +               /* If both bytes of the timing are 0x00 or 0x01, then the timing
14100 +                  slot is unused. */
14101 +               if ((data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2]
14102 +                   | data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2 + 1]) & 0xfe) {
14103 +                       results[0] = (data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2] + 31) * 8;
14104 +                       switch (data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2 + 1] >> 6) {
14105 +                               /* We don't care about rounding issues there, it really
14106 +                                  should be OK without it. */
14107 +                               case 0x00:
14108 +                                       results[1] = results[0]; /* unconfirmed */
14109 +                                       break;
14110 +                               case 0x01:
14111 +                                       results[1] = results[0] * 3 / 4;
14112 +                                       break;
14113 +                               case 0x02:
14114 +                                       results[1] = results[0] * 4 / 5;
14115 +                                       break;
14116 +                               case 0x03:
14117 +                                       results[1] = results[0] * 9 / 16;
14118 +                                       break;
14119 +                       }
14120 +                       results[2] = (data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2 + 1] & 0x3f) + 60;
14121 +               } else {
14122 +                       results[0] = 0;
14123 +                       results[1] = 0;
14124 +                       results[2] = 0;
14125 +               }
14126 +               *nrels_mag = 3;
14127 +       }
14128 +}
14129 +
14130 +static int __init sm_ddcmon_init(void)
14131 +{
14132 +       printk("ddcmon.o version %s (%s)\n", LM_VERSION, LM_DATE);
14133 +       return i2c_add_driver(&ddcmon_driver);
14134 +}
14135 +
14136 +static void __exit sm_ddcmon_exit(void)
14137 +{
14138 +       i2c_del_driver(&ddcmon_driver);
14139 +}
14140 +
14141 +
14142 +
14143 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
14144 +             "Philip Edelbrock <phil@netroedge.com>, "
14145 +             "Mark Studebaker <mdsxyz123@yahoo.com> "
14146 +                 "and Jean Delvare <khali@linux-fr.org>");
14147 +MODULE_DESCRIPTION("DDCMON driver");
14148 +
14149 +module_init(sm_ddcmon_init);
14150 +module_exit(sm_ddcmon_exit);
14151 --- linux-old/drivers/sensors/ds1621.c  Thu Jan  1 00:00:00 1970
14152 +++ linux/drivers/sensors/ds1621.c      Mon Dec 13 20:18:45 2004
14153 @@ -0,0 +1,528 @@
14154 +/*
14155 +    ds1621.c - Part of lm_sensors, Linux kernel modules for hardware
14156 +             monitoring
14157 +    Christian W. Zuckschwerdt  <zany@triq.net>  2000-11-23
14158 +    based on lm75.c by Frodo Looijaard <frodol@dds.nl>
14159 +
14160 +    This program is free software; you can redistribute it and/or modify
14161 +    it under the terms of the GNU General Public License as published by
14162 +    the Free Software Foundation; either version 2 of the License, or
14163 +    (at your option) any later version.
14164 +
14165 +    This program is distributed in the hope that it will be useful,
14166 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
14167 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14168 +    GNU General Public License for more details.
14169 +
14170 +    You should have received a copy of the GNU General Public License
14171 +    along with this program; if not, write to the Free Software
14172 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
14173 +*/
14174 +
14175 +/* Supports DS1621. See doc/chips/ds1621 for details */
14176 +
14177 +#include <linux/module.h>
14178 +#include <linux/slab.h>
14179 +#include <linux/i2c.h>
14180 +#include <linux/i2c-proc.h>
14181 +#include <linux/init.h>
14182 +#define LM_DATE "20041007"
14183 +#define LM_VERSION "2.8.8"
14184 +
14185 +MODULE_LICENSE("GPL");
14186 +
14187 +/* Addresses to scan */
14188 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
14189 +static unsigned short normal_i2c_range[] = { 0x48, 0x4f, SENSORS_I2C_END };
14190 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
14191 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
14192 +
14193 +/* Insmod parameters */
14194 +SENSORS_INSMOD_1(ds1621);
14195 +
14196 +/* Many DS1621 constants specified below */
14197 +
14198 +/* Config register used for detection         */
14199 +/*  7    6    5    4    3    2    1    0      */
14200 +/* |Done|THF |TLF |NVB | 1  | 0  |POL |1SHOT| */
14201 +#define DS1621_REG_CONFIG_MASK 0x0C
14202 +#define DS1621_REG_CONFIG_VAL 0x08
14203 +#define DS1621_REG_CONFIG_POLARITY 0x02
14204 +#define DS1621_REG_CONFIG_1SHOT 0x01
14205 +#define DS1621_REG_CONFIG_DONE 0x80
14206 +
14207 +/* Note: the done bit is always unset if continuous conversion is in progress.
14208 +         We need to stop the continuous conversion or switch to single shot
14209 +         before this bit becomes available!
14210 + */
14211 +
14212 +/* The DS1621 registers */
14213 +#define DS1621_REG_TEMP 0xAA /* word, RO */
14214 +#define DS1621_REG_TEMP_OVER 0xA1 /* word, RW */
14215 +#define DS1621_REG_TEMP_HYST 0xA2 /* word, RW -- it's a low temp trigger */
14216 +#define DS1621_REG_CONF 0xAC /* byte, RW */
14217 +#define DS1621_REG_TEMP_COUNTER 0xA8 /* byte, RO */
14218 +#define DS1621_REG_TEMP_SLOPE 0xA9 /* byte, RO */
14219 +#define DS1621_COM_START 0xEE /* no data */
14220 +#define DS1621_COM_STOP 0x22 /* no data */
14221 +
14222 +/* Conversions. Rounding and limit checking is only done on the TO_REG
14223 +   variants. Note that you should be a bit careful with which arguments
14224 +   these macros are called: arguments may be evaluated more than once.
14225 +   Fixing this is just not worth it. */
14226 +#define TEMP_FROM_REG(val) ((((val & 0x7fff) >> 7) * 5) | \
14227 +                            ((val & 0x8000)?-256:0))
14228 +#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val<0 ? (0x200+((val)/5))<<7 : \
14229 +                                          (((val) + 2) / 5) << 7),0,0xffff))
14230 +#define ALARMS_FROM_REG(val) ((val) & \
14231 +                              (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
14232 +#define ITEMP_FROM_REG(val) ((((val & 0x7fff) >> 8)) | \
14233 +                            ((val & 0x8000)?-256:0))
14234 +
14235 +/* Each client has this additional data */
14236 +struct ds1621_data {
14237 +       struct i2c_client client;
14238 +       int sysctl_id;
14239 +
14240 +       struct semaphore update_lock;
14241 +       char valid;             /* !=0 if following fields are valid */
14242 +       unsigned long last_updated;     /* In jiffies */
14243 +
14244 +       u16 temp, temp_over, temp_hyst; /* Register values, word */
14245 +       u8 conf;                        /* Register encoding, combined */
14246 +
14247 +       char enable;    /* !=0 if we're expected to restart the conversion */
14248 +       u8 temp_int, temp_counter, temp_slope;  /* Register values, byte */
14249 +};
14250 +
14251 +static int ds1621_attach_adapter(struct i2c_adapter *adapter);
14252 +static int ds1621_detect(struct i2c_adapter *adapter, int address,
14253 +                        unsigned short flags, int kind);
14254 +static void ds1621_init_client(struct i2c_client *client);
14255 +static int ds1621_detach_client(struct i2c_client *client);
14256 +
14257 +static int ds1621_read_value(struct i2c_client *client, u8 reg);
14258 +static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value);
14259 +static void ds1621_temp(struct i2c_client *client, int operation,
14260 +                       int ctl_name, int *nrels_mag, long *results);
14261 +static void ds1621_alarms(struct i2c_client *client, int operation,
14262 +                         int ctl_name, int *nrels_mag, long *results);
14263 +static void ds1621_enable(struct i2c_client *client, int operation,
14264 +                         int ctl_name, int *nrels_mag, long *results);
14265 +static void ds1621_continuous(struct i2c_client *client, int operation,
14266 +                             int ctl_name, int *nrels_mag, long *results);
14267 +static void ds1621_polarity(struct i2c_client *client, int operation,
14268 +                           int ctl_name, int *nrels_mag, long *results);
14269 +static void ds1621_update_client(struct i2c_client *client);
14270 +
14271 +
14272 +/* This is the driver that will be inserted */
14273 +static struct i2c_driver ds1621_driver = {
14274 +       .owner          = THIS_MODULE,
14275 +       .name           = "DS1621 sensor driver",
14276 +       .id             = I2C_DRIVERID_DS1621,
14277 +       .flags          = I2C_DF_NOTIFY,
14278 +       .attach_adapter = ds1621_attach_adapter,
14279 +       .detach_client  = ds1621_detach_client,
14280 +};
14281 +
14282 +/* -- SENSORS SYSCTL START -- */
14283 +#define DS1621_SYSCTL_TEMP 1200        /* Degrees Celcius * 10 */
14284 +#define DS1621_SYSCTL_ALARMS 2001      /* bitvector */
14285 +#define DS1621_ALARM_TEMP_HIGH 0x40
14286 +#define DS1621_ALARM_TEMP_LOW 0x20
14287 +#define DS1621_SYSCTL_ENABLE 2002
14288 +#define DS1621_SYSCTL_CONTINUOUS 2003
14289 +#define DS1621_SYSCTL_POLARITY 2004
14290 +
14291 +/* -- SENSORS SYSCTL END -- */
14292 +
14293 +/* These files are created for each detected DS1621. This is just a template;
14294 +   though at first sight, you might think we could use a statically
14295 +   allocated list, we need some way to get back to the parent - which
14296 +   is done through one of the 'extra' fields which are initialized
14297 +   when a new copy is allocated. */
14298 +static ctl_table ds1621_dir_table_template[] = {
14299 +       {DS1621_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL,
14300 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ds1621_temp},
14301 +       {DS1621_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
14302 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ds1621_alarms},
14303 +       {DS1621_SYSCTL_ENABLE, "enable", NULL, 0, 0644, NULL,
14304 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ds1621_enable},
14305 +       {DS1621_SYSCTL_CONTINUOUS, "continuous", NULL, 0, 0644, NULL,
14306 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ds1621_continuous},
14307 +       {DS1621_SYSCTL_POLARITY, "polarity", NULL, 0, 0644, NULL,
14308 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &ds1621_polarity},
14309 +       {0}
14310 +};
14311 +
14312 +static int ds1621_id = 0;
14313 +
14314 +static int ds1621_attach_adapter(struct i2c_adapter *adapter)
14315 +{
14316 +       return i2c_detect(adapter, &addr_data, ds1621_detect);
14317 +}
14318 +
14319 +/* This function is called by i2c_detect */
14320 +int ds1621_detect(struct i2c_adapter *adapter, int address,
14321 +               unsigned short flags, int kind)
14322 +{
14323 +       int i, conf;
14324 +       struct i2c_client *new_client;
14325 +       struct ds1621_data *data;
14326 +       int err = 0;
14327 +       const char *type_name, *client_name;
14328 +
14329 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
14330 +          at this moment; i2c_detect really won't call us. */
14331 +#ifdef DEBUG
14332 +       if (i2c_is_isa_adapter(adapter)) {
14333 +               printk
14334 +                ("ds1621.o: ds1621_detect called for an ISA bus adapter?!?\n");
14335 +               return 0;
14336 +       }
14337 +#endif
14338 +
14339 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
14340 +                                    I2C_FUNC_SMBUS_WORD_DATA |
14341 +                                    I2C_FUNC_SMBUS_WRITE_BYTE))
14342 +                   goto ERROR0;
14343 +
14344 +       /* OK. For now, we presume we have a valid client. We now create the
14345 +          client structure, even though we cannot fill it completely yet.
14346 +          But it allows us to access ds1621_{read,write}_value. */
14347 +       if (!(data = kmalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
14348 +               err = -ENOMEM;
14349 +               goto ERROR0;
14350 +       }
14351 +
14352 +       new_client = &data->client;
14353 +       new_client->addr = address;
14354 +       new_client->data = data;
14355 +       new_client->adapter = adapter;
14356 +       new_client->driver = &ds1621_driver;
14357 +       new_client->flags = 0;
14358 +
14359 +       /* Now, we do the remaining detection. It is lousy. */
14360 +       if (kind < 0) {
14361 +               conf = i2c_smbus_read_byte_data(new_client,
14362 +                                               DS1621_REG_CONF);
14363 +               if ((conf & DS1621_REG_CONFIG_MASK)
14364 +                   != DS1621_REG_CONFIG_VAL)
14365 +                       goto ERROR1;
14366 +       }
14367 +
14368 +       /* Determine the chip type - only one kind supported! */
14369 +       if (kind <= 0)
14370 +               kind = ds1621;
14371 +
14372 +       if (kind == ds1621) {
14373 +               type_name = "ds1621";
14374 +               client_name = "DS1621 chip";
14375 +       } else {
14376 +#ifdef DEBUG
14377 +               printk("ds1621.o: Internal error: unknown kind (%d)?!?",
14378 +                      kind);
14379 +#endif
14380 +               goto ERROR1;
14381 +       }
14382 +
14383 +       /* Fill in remaining client fields and put it into the global list */
14384 +       strcpy(new_client->name, client_name);
14385 +
14386 +       new_client->id = ds1621_id++;
14387 +       data->valid = 0;
14388 +       init_MUTEX(&data->update_lock);
14389 +
14390 +       /* Tell the I2C layer a new client has arrived */
14391 +       if ((err = i2c_attach_client(new_client)))
14392 +               goto ERROR3;
14393 +
14394 +       /* Register a new directory entry with module sensors */
14395 +       if ((i = i2c_register_entry(new_client, type_name,
14396 +                                       ds1621_dir_table_template)) < 0) {
14397 +               err = i;
14398 +               goto ERROR4;
14399 +       }
14400 +       data->sysctl_id = i;
14401 +
14402 +       ds1621_init_client(new_client);
14403 +       return 0;
14404 +
14405 +/* OK, this is not exactly good programming practice, usually. But it is
14406 +   very code-efficient in this case. */
14407 +
14408 +      ERROR4:
14409 +       i2c_detach_client(new_client);
14410 +      ERROR3:
14411 +      ERROR1:
14412 +       kfree(data);
14413 +      ERROR0:
14414 +       return err;
14415 +}
14416 +
14417 +static int ds1621_detach_client(struct i2c_client *client)
14418 +{
14419 +       int err;
14420 +
14421 +       i2c_deregister_entry(((struct ds1621_data *) (client->data))->
14422 +                                sysctl_id);
14423 +
14424 +       if ((err = i2c_detach_client(client))) {
14425 +               printk
14426 +          ("ds1621.o: Client deregistration failed, client not detached.\n");
14427 +               return err;
14428 +       }
14429 +
14430 +       kfree(client->data);
14431 +
14432 +       return 0;
14433 +}
14434 +
14435 +
14436 +/* All registers are word-sized, except for the configuration register.
14437 +   DS1621 uses a high-byte first convention, which is exactly opposite to
14438 +   the usual practice. */
14439 +static int ds1621_read_value(struct i2c_client *client, u8 reg)
14440 +{
14441 +       if ((reg == DS1621_REG_CONF) || (reg == DS1621_REG_TEMP_COUNTER)
14442 +           || (reg == DS1621_REG_TEMP_SLOPE))
14443 +               return i2c_smbus_read_byte_data(client, reg);
14444 +       else
14445 +               return swab16(i2c_smbus_read_word_data(client, reg));
14446 +}
14447 +
14448 +/* All registers are word-sized, except for the configuration register.
14449 +   DS1621 uses a high-byte first convention, which is exactly opposite to
14450 +   the usual practice. */
14451 +static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value)
14452 +{
14453 +       if ( (reg == DS1621_COM_START) || (reg == DS1621_COM_STOP) )
14454 +               return i2c_smbus_write_byte(client, reg);
14455 +       else
14456 +       if ((reg == DS1621_REG_CONF) || (reg == DS1621_REG_TEMP_COUNTER)
14457 +           || (reg == DS1621_REG_TEMP_SLOPE))
14458 +               return i2c_smbus_write_byte_data(client, reg, value);
14459 +       else
14460 +               return i2c_smbus_write_word_data(client, reg, swab16(value));
14461 +}
14462 +
14463 +static void ds1621_init_client(struct i2c_client *client)
14464 +{
14465 +       int reg;
14466 +
14467 +       reg = ds1621_read_value(client, DS1621_REG_CONF);
14468 +       /* start the continous conversion */
14469 +       if(reg & 0x01)
14470 +               ds1621_write_value(client, DS1621_REG_CONF, reg & 0xfe);
14471 +}
14472 +
14473 +static void ds1621_update_client(struct i2c_client *client)
14474 +{
14475 +       struct ds1621_data *data = client->data;
14476 +       u8 new_conf;
14477 +
14478 +       down(&data->update_lock);
14479 +
14480 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
14481 +           (jiffies < data->last_updated) || !data->valid) {
14482 +
14483 +#ifdef DEBUG
14484 +               printk("Starting ds1621 update\n");
14485 +#endif
14486 +
14487 +               data->conf = ds1621_read_value(client, DS1621_REG_CONF);
14488 +
14489 +               data->temp = ds1621_read_value(client,
14490 +                                              DS1621_REG_TEMP);
14491 +               data->temp_over = ds1621_read_value(client,
14492 +                                                   DS1621_REG_TEMP_OVER);
14493 +               data->temp_hyst = ds1621_read_value(client,
14494 +                                                   DS1621_REG_TEMP_HYST);
14495 +
14496 +               /* wait for the DONE bit before reading extended values */
14497 +
14498 +               if (data->conf & DS1621_REG_CONFIG_DONE) {
14499 +                       data->temp_counter = ds1621_read_value(client,
14500 +                                                    DS1621_REG_TEMP_COUNTER);
14501 +                       data->temp_slope = ds1621_read_value(client,
14502 +                                                    DS1621_REG_TEMP_SLOPE);
14503 +                       data->temp_int = ITEMP_FROM_REG(data->temp);
14504 +                       /* restart the conversion */
14505 +                       if (data->enable)
14506 +                               ds1621_write_value(client, DS1621_COM_START, 0);
14507 +               }
14508 +
14509 +               /* reset alarms if neccessary */
14510 +               new_conf = data->conf;
14511 +               if (data->temp < data->temp_over)
14512 +                       new_conf &= ~DS1621_ALARM_TEMP_HIGH;
14513 +               if (data->temp > data->temp_hyst)
14514 +                       new_conf &= ~DS1621_ALARM_TEMP_LOW;
14515 +               if (data->conf != new_conf)
14516 +                       ds1621_write_value(client, DS1621_REG_CONF,
14517 +                                          new_conf);
14518 +
14519 +               data->last_updated = jiffies;
14520 +               data->valid = 1;
14521 +       }
14522 +
14523 +       up(&data->update_lock);
14524 +}
14525 +
14526 +
14527 +void ds1621_temp(struct i2c_client *client, int operation, int ctl_name,
14528 +                int *nrels_mag, long *results)
14529 +{
14530 +       struct ds1621_data *data = client->data;
14531 +       if (operation == SENSORS_PROC_REAL_INFO)
14532 +               if (!(data->conf & DS1621_REG_CONFIG_DONE) ||
14533 +                   (data->temp_counter > data->temp_slope) ||
14534 +                   (data->temp_slope == 0)) {
14535 +                       *nrels_mag = 1;
14536 +               } else {
14537 +                       *nrels_mag = 2;
14538 +               }
14539 +       else if (operation == SENSORS_PROC_REAL_READ) {
14540 +               ds1621_update_client(client);
14541 +               /* decide wether to calculate more precise temp */
14542 +               if (!(data->conf & DS1621_REG_CONFIG_DONE) ||
14543 +                   (data->temp_counter > data->temp_slope) ||
14544 +                   (data->temp_slope == 0)) {
14545 +                       results[0] = TEMP_FROM_REG(data->temp_over);
14546 +                       results[1] = TEMP_FROM_REG(data->temp_hyst);
14547 +                       results[2] = TEMP_FROM_REG(data->temp);
14548 +               } else {
14549 +                       results[0] = TEMP_FROM_REG(data->temp_over)*10;
14550 +                       results[1] = TEMP_FROM_REG(data->temp_hyst)*10;
14551 +                       results[2] = data->temp_int * 100 - 25 +
14552 +                               ((data->temp_slope - data->temp_counter) *
14553 +                                100 / data->temp_slope);
14554 +               }
14555 +               *nrels_mag = 3;
14556 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
14557 +               if (*nrels_mag >= 1) {
14558 +                       data->temp_over = TEMP_TO_REG(results[0]);
14559 +                       ds1621_write_value(client, DS1621_REG_TEMP_OVER,
14560 +                                        data->temp_over);
14561 +               }
14562 +               if (*nrels_mag >= 2) {
14563 +                       data->temp_hyst = TEMP_TO_REG(results[1]);
14564 +                       ds1621_write_value(client, DS1621_REG_TEMP_HYST,
14565 +                                        data->temp_hyst);
14566 +               }
14567 +       }
14568 +}
14569 +
14570 +void ds1621_alarms(struct i2c_client *client, int operation, int ctl_name,
14571 +                  int *nrels_mag, long *results)
14572 +{
14573 +       struct ds1621_data *data = client->data;
14574 +       if (operation == SENSORS_PROC_REAL_INFO)
14575 +               *nrels_mag = 0;
14576 +       else if (operation == SENSORS_PROC_REAL_READ) {
14577 +               ds1621_update_client(client);
14578 +               results[0] = ALARMS_FROM_REG(data->conf);
14579 +               *nrels_mag = 1;
14580 +       }
14581 +}
14582 +
14583 +void ds1621_enable(struct i2c_client *client, int operation, int ctl_name,
14584 +                  int *nrels_mag, long *results)
14585 +{
14586 +       /* If you really screw up your chip (like I did) this is */
14587 +       /* sometimes needed to (re)start the continous conversion */
14588 +       /* there is no data to read so this might hang your SMBus! */
14589 +
14590 +       struct ds1621_data *data = client->data;
14591 +       if (operation == SENSORS_PROC_REAL_INFO)
14592 +               *nrels_mag = 0;
14593 +       else if (operation == SENSORS_PROC_REAL_READ) {
14594 +               ds1621_update_client(client);
14595 +               results[0] = !(data->conf & DS1621_REG_CONFIG_DONE);
14596 +               *nrels_mag = 1;
14597 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
14598 +               if (*nrels_mag >= 1) {
14599 +                       if (results[0]) {
14600 +                               ds1621_write_value(client, DS1621_COM_START, 0);
14601 +                               data->enable=1;
14602 +                       } else {
14603 +                               ds1621_write_value(client, DS1621_COM_STOP, 0);
14604 +                               data->enable=0;
14605 +                       }
14606 +               } else {
14607 +                       ds1621_write_value(client, DS1621_COM_START, 0);
14608 +                       data->enable=1;
14609 +               }
14610 +       }
14611 +}
14612 +
14613 +void ds1621_continuous(struct i2c_client *client, int operation, int ctl_name,
14614 +                      int *nrels_mag, long *results)
14615 +{
14616 +       struct ds1621_data *data = client->data;
14617 +       if (operation == SENSORS_PROC_REAL_INFO)
14618 +               *nrels_mag = 0;
14619 +       else if (operation == SENSORS_PROC_REAL_READ) {
14620 +               ds1621_update_client(client);
14621 +               results[0] = !(data->conf & DS1621_REG_CONFIG_1SHOT);
14622 +               *nrels_mag = 1;
14623 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
14624 +               ds1621_update_client(client);
14625 +               if (*nrels_mag >= 1) {
14626 +                       if (results[0]) {
14627 +                               ds1621_write_value(client, DS1621_REG_CONF,
14628 +                                                  data->conf & ~DS1621_REG_CONFIG_1SHOT);
14629 +                       } else {
14630 +                               ds1621_write_value(client, DS1621_REG_CONF,
14631 +                                                  data->conf | DS1621_REG_CONFIG_1SHOT);
14632 +                       }
14633 +               } else {
14634 +                       ds1621_write_value(client, DS1621_REG_CONF,
14635 +                                          data->conf & ~DS1621_REG_CONFIG_1SHOT);
14636 +               }
14637 +       }
14638 +}
14639 +
14640 +void ds1621_polarity(struct i2c_client *client, int operation, int ctl_name,
14641 +                    int *nrels_mag, long *results)
14642 +{
14643 +       struct ds1621_data *data = client->data;
14644 +       if (operation == SENSORS_PROC_REAL_INFO)
14645 +               *nrels_mag = 0;
14646 +       else if (operation == SENSORS_PROC_REAL_READ) {
14647 +               ds1621_update_client(client);
14648 +               results[0] = !(!(data->conf & DS1621_REG_CONFIG_POLARITY));
14649 +               *nrels_mag = 1;
14650 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
14651 +               ds1621_update_client(client);
14652 +               if (*nrels_mag >= 1) {
14653 +                       if (results[0]) {
14654 +                               ds1621_write_value(client, DS1621_REG_CONF,
14655 +                                                  data->conf | DS1621_REG_CONFIG_POLARITY);
14656 +                       } else {
14657 +                               ds1621_write_value(client, DS1621_REG_CONF,
14658 +                                                  data->conf & ~DS1621_REG_CONFIG_POLARITY);
14659 +                       }
14660 +               }
14661 +       }
14662 +}
14663 +
14664 +static int __init sm_ds1621_init(void)
14665 +{
14666 +       printk("ds1621.o version %s (%s)\n", LM_VERSION, LM_DATE);
14667 +       return i2c_add_driver(&ds1621_driver);
14668 +}
14669 +
14670 +static void __exit sm_ds1621_exit(void)
14671 +{
14672 +       i2c_del_driver(&ds1621_driver);
14673 +}
14674 +
14675 +
14676 +
14677 +MODULE_AUTHOR("Christian W. Zuckschwerdt <zany@triq.net>");
14678 +MODULE_DESCRIPTION("DS1621 driver");
14679 +
14680 +module_init(sm_ds1621_init);
14681 +module_exit(sm_ds1621_exit);
14682 --- linux-old/drivers/sensors/eeprom.c  Thu Jan  1 00:00:00 1970
14683 +++ linux/drivers/sensors/eeprom.c      Mon Dec 13 20:18:45 2004
14684 @@ -0,0 +1,418 @@
14685 +/*
14686 +    eeprom.c - Part of lm_sensors, Linux kernel modules for hardware
14687 +               monitoring
14688 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
14689 +    Philip Edelbrock <phil@netroedge.com>
14690 +
14691 +    2003-08-18  Jean Delvare <khali@linux-fr.org>
14692 +    Divide the eeprom in 2-row (arbitrary) slices. This significantly
14693 +    speeds sensors up, as well as various scripts using the eeprom
14694 +    module.
14695 +
14696 +    This program is free software; you can redistribute it and/or modify
14697 +    it under the terms of the GNU General Public License as published by
14698 +    the Free Software Foundation; either version 2 of the License, or
14699 +    (at your option) any later version.
14700 +
14701 +    This program is distributed in the hope that it will be useful,
14702 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
14703 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14704 +    GNU General Public License for more details.
14705 +
14706 +    You should have received a copy of the GNU General Public License
14707 +    along with this program; if not, write to the Free Software
14708 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
14709 +*/
14710 +
14711 +#include <linux/module.h>
14712 +#include <linux/slab.h>
14713 +#include <linux/i2c.h>
14714 +#include <linux/i2c-proc.h>
14715 +#include <linux/init.h>
14716 +#include <linux/sched.h> /* for capable() */
14717 +#define LM_DATE "20041007"
14718 +#define LM_VERSION "2.8.8"
14719 +
14720 +MODULE_LICENSE("GPL");
14721 +
14722 +/* Addresses to scan */
14723 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
14724 +static unsigned short normal_i2c_range[] = { 0x50, 0x57, SENSORS_I2C_END };
14725 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
14726 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
14727 +
14728 +/* Insmod parameters */
14729 +SENSORS_INSMOD_1(eeprom);
14730 +
14731 +static int checksum = 0;
14732 +MODULE_PARM(checksum, "i");
14733 +MODULE_PARM_DESC(checksum,
14734 +                "Only accept eeproms whose checksum is correct");
14735 +
14736 +
14737 +/* Many constants specified below */
14738 +
14739 +/* EEPROM registers */
14740 +#define EEPROM_REG_CHECKSUM 0x3f
14741 +
14742 +/* possible natures */
14743 +#define NATURE_UNKNOWN 0
14744 +#define NATURE_VAIO 1
14745 +
14746 +/* Size of EEPROM in bytes */
14747 +#define EEPROM_SIZE 256
14748 +
14749 +/* Each client has this additional data */
14750 +struct eeprom_data {
14751 +       struct i2c_client client;
14752 +       int sysctl_id;
14753 +
14754 +       struct semaphore update_lock;
14755 +       u8 valid;               /* bitfield, bit!=0 if slice is valid */
14756 +       unsigned long last_updated[8];  /* In jiffies, 8 slices */
14757 +
14758 +       u8 data[EEPROM_SIZE];   /* Register values */
14759 +       u8 nature;
14760 +};
14761 +
14762 +
14763 +static int eeprom_attach_adapter(struct i2c_adapter *adapter);
14764 +static int eeprom_detect(struct i2c_adapter *adapter, int address,
14765 +                        unsigned short flags, int kind);
14766 +static int eeprom_detach_client(struct i2c_client *client);
14767 +
14768 +#if 0
14769 +static int eeprom_write_value(struct i2c_client *client, u8 reg,
14770 +                             u8 value);
14771 +#endif
14772 +
14773 +static void eeprom_contents(struct i2c_client *client, int operation,
14774 +                           int ctl_name, int *nrels_mag, long *results);
14775 +static void eeprom_update_client(struct i2c_client *client, u8 slice);
14776 +
14777 +
14778 +/* This is the driver that will be inserted */
14779 +static struct i2c_driver eeprom_driver = {
14780 +       .owner          = THIS_MODULE,
14781 +       .name           = "EEPROM READER",
14782 +       .id             = I2C_DRIVERID_EEPROM,
14783 +       .flags          = I2C_DF_NOTIFY,
14784 +       .attach_adapter = eeprom_attach_adapter,
14785 +       .detach_client  = eeprom_detach_client,
14786 +};
14787 +
14788 +/* -- SENSORS SYSCTL START -- */
14789 +
14790 +#define EEPROM_SYSCTL1 1000
14791 +#define EEPROM_SYSCTL2 1001
14792 +#define EEPROM_SYSCTL3 1002
14793 +#define EEPROM_SYSCTL4 1003
14794 +#define EEPROM_SYSCTL5 1004
14795 +#define EEPROM_SYSCTL6 1005
14796 +#define EEPROM_SYSCTL7 1006
14797 +#define EEPROM_SYSCTL8 1007
14798 +#define EEPROM_SYSCTL9 1008
14799 +#define EEPROM_SYSCTL10 1009
14800 +#define EEPROM_SYSCTL11 1010
14801 +#define EEPROM_SYSCTL12 1011
14802 +#define EEPROM_SYSCTL13 1012
14803 +#define EEPROM_SYSCTL14 1013
14804 +#define EEPROM_SYSCTL15 1014
14805 +#define EEPROM_SYSCTL16 1015
14806 +
14807 +/* -- SENSORS SYSCTL END -- */
14808 +
14809 +/* These files are created for each detected EEPROM. This is just a template;
14810 +   though at first sight, you might think we could use a statically
14811 +   allocated list, we need some way to get back to the parent - which
14812 +   is done through one of the 'extra' fields which are initialized
14813 +   when a new copy is allocated. */
14814 +static ctl_table eeprom_dir_table_template[] = {
14815 +       {EEPROM_SYSCTL1, "00", NULL, 0, 0444, NULL, &i2c_proc_real,
14816 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14817 +       {EEPROM_SYSCTL2, "10", NULL, 0, 0444, NULL, &i2c_proc_real,
14818 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14819 +       {EEPROM_SYSCTL3, "20", NULL, 0, 0444, NULL, &i2c_proc_real,
14820 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14821 +       {EEPROM_SYSCTL4, "30", NULL, 0, 0444, NULL, &i2c_proc_real,
14822 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14823 +       {EEPROM_SYSCTL5, "40", NULL, 0, 0444, NULL, &i2c_proc_real,
14824 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14825 +       {EEPROM_SYSCTL6, "50", NULL, 0, 0444, NULL, &i2c_proc_real,
14826 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14827 +       {EEPROM_SYSCTL7, "60", NULL, 0, 0444, NULL, &i2c_proc_real,
14828 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14829 +       {EEPROM_SYSCTL8, "70", NULL, 0, 0444, NULL, &i2c_proc_real,
14830 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14831 +       {EEPROM_SYSCTL9, "80", NULL, 0, 0444, NULL, &i2c_proc_real,
14832 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14833 +       {EEPROM_SYSCTL10, "90", NULL, 0, 0444, NULL, &i2c_proc_real,
14834 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14835 +       {EEPROM_SYSCTL11, "a0", NULL, 0, 0444, NULL, &i2c_proc_real,
14836 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14837 +       {EEPROM_SYSCTL12, "b0", NULL, 0, 0444, NULL, &i2c_proc_real,
14838 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14839 +       {EEPROM_SYSCTL13, "c0", NULL, 0, 0444, NULL, &i2c_proc_real,
14840 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14841 +       {EEPROM_SYSCTL14, "d0", NULL, 0, 0444, NULL, &i2c_proc_real,
14842 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14843 +       {EEPROM_SYSCTL15, "e0", NULL, 0, 0444, NULL, &i2c_proc_real,
14844 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14845 +       {EEPROM_SYSCTL16, "f0", NULL, 0, 0444, NULL, &i2c_proc_real,
14846 +        &i2c_sysctl_real, NULL, &eeprom_contents},
14847 +       {0}
14848 +};
14849 +
14850 +static int eeprom_id = 0;
14851 +
14852 +static int eeprom_attach_adapter(struct i2c_adapter *adapter)
14853 +{
14854 +       return i2c_detect(adapter, &addr_data, eeprom_detect);
14855 +}
14856 +
14857 +/* This function is called by i2c_detect */
14858 +int eeprom_detect(struct i2c_adapter *adapter, int address,
14859 +                 unsigned short flags, int kind)
14860 +{
14861 +       int i;
14862 +       struct i2c_client *new_client;
14863 +       struct eeprom_data *data;
14864 +       int err = 0;
14865 +       const char *type_name, *client_name;
14866 +
14867 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
14868 +          at this moment; i2c_detect really won't call us. */
14869 +#ifdef DEBUG
14870 +       if (i2c_is_isa_adapter(adapter)) {
14871 +               printk
14872 +                   ("eeprom.o: eeprom_detect called for an ISA bus adapter?!?\n");
14873 +               return 0;
14874 +       }
14875 +#endif
14876 +
14877 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
14878 +                   goto ERROR0;
14879 +
14880 +       /* OK. For now, we presume we have a valid client. We now create the
14881 +          client structure, even though we cannot fill it completely yet.
14882 +          But it allows us to access eeprom_{read,write}_value. */
14883 +       if (!(data = kmalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
14884 +               err = -ENOMEM;
14885 +               goto ERROR0;
14886 +       }
14887 +
14888 +       new_client = &data->client;
14889 +       memset(data->data, 0xff, EEPROM_SIZE);
14890 +       new_client->addr = address;
14891 +       new_client->data = data;
14892 +       new_client->adapter = adapter;
14893 +       new_client->driver = &eeprom_driver;
14894 +       new_client->flags = 0;
14895 +
14896 +       /* prevent 24RF08 corruption */
14897 +       i2c_smbus_write_quick(new_client, 0);
14898 +
14899 +       /* Now, we do the remaining detection. It is not there, unless you force
14900 +          the checksum to work out. */
14901 +       if (checksum) {
14902 +               int cs = 0;
14903 +               for (i = 0; i <= 0x3e; i++)
14904 +                       cs += i2c_smbus_read_byte_data(new_client, i);
14905 +               cs &= 0xff;
14906 +               if (i2c_smbus_read_byte_data
14907 +                   (new_client, EEPROM_REG_CHECKSUM) != cs)
14908 +                       goto ERROR1;
14909 +       }
14910 +
14911 +       data->nature = NATURE_UNKNOWN;
14912 +       /* Detect the Vaio nature of EEPROMs.
14913 +          We use the "PCG-" prefix as the signature. */
14914 +       if (address == 0x57)
14915 +       {
14916 +               if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
14917 +                && i2c_smbus_read_byte_data(new_client, 0x81) == 'C'
14918 +                && i2c_smbus_read_byte_data(new_client, 0x82) == 'G'
14919 +                && i2c_smbus_read_byte_data(new_client, 0x83) == '-')
14920 +                       data->nature = NATURE_VAIO;
14921 +       }
14922 +
14923 +       /* Determine the chip type - only one kind supported! */
14924 +       if (kind <= 0)
14925 +               kind = eeprom;
14926 +
14927 +       if (kind == eeprom) {
14928 +               type_name = "eeprom";
14929 +               client_name = "EEPROM chip";
14930 +       } else {
14931 +#ifdef DEBUG
14932 +               printk("eeprom.o: Internal error: unknown kind (%d)?!?",
14933 +                      kind);
14934 +#endif
14935 +               goto ERROR1;
14936 +       }
14937 +
14938 +       /* Fill in the remaining client fields and put it into the global list */
14939 +       strcpy(new_client->name, client_name);
14940 +
14941 +       new_client->id = eeprom_id++;
14942 +       data->valid = 0;
14943 +       init_MUTEX(&data->update_lock);
14944 +
14945 +       /* Tell the I2C layer a new client has arrived */
14946 +       if ((err = i2c_attach_client(new_client)))
14947 +               goto ERROR3;
14948 +
14949 +       /* Register a new directory entry with module sensors */
14950 +       if ((i = i2c_register_entry(new_client, type_name,
14951 +                                       eeprom_dir_table_template)) < 0) {
14952 +               err = i;
14953 +               goto ERROR4;
14954 +       }
14955 +       data->sysctl_id = i;
14956 +
14957 +       return 0;
14958 +
14959 +/* OK, this is not exactly good programming practice, usually. But it is
14960 +   very code-efficient in this case. */
14961 +
14962 +      ERROR4:
14963 +       i2c_detach_client(new_client);
14964 +      ERROR3:
14965 +      ERROR1:
14966 +       kfree(data);
14967 +      ERROR0:
14968 +       return err;
14969 +}
14970 +
14971 +static int eeprom_detach_client(struct i2c_client *client)
14972 +{
14973 +       int err;
14974 +
14975 +       i2c_deregister_entry(((struct eeprom_data *) (client->data))->
14976 +                                sysctl_id);
14977 +
14978 +       if ((err = i2c_detach_client(client))) {
14979 +               printk
14980 +                   ("eeprom.o: Client deregistration failed, client not detached.\n");
14981 +               return err;
14982 +       }
14983 +
14984 +       kfree(client->data);
14985 +
14986 +       return 0;
14987 +}
14988 +
14989 +
14990 +#if 0
14991 +/* No writes yet (PAE) */
14992 +static int eeprom_write_value(struct i2c_client *client, u8 reg, u8 value)
14993 +{
14994 +       return i2c_smbus_write_byte_data(client, reg, value);
14995 +}
14996 +#endif
14997 +
14998 +static void eeprom_update_client(struct i2c_client *client, u8 slice)
14999 +{
15000 +       struct eeprom_data *data = client->data;
15001 +       int i, j;
15002 +
15003 +       down(&data->update_lock);
15004 +
15005 +       if (!(data->valid & (1 << slice))
15006 +        || (jiffies - data->last_updated[slice] > 300 * HZ)
15007 +        || (jiffies < data->last_updated[slice])) {
15008 +
15009 +#ifdef DEBUG
15010 +               printk("Starting eeprom update, slice %u\n", slice);
15011 +#endif
15012 +
15013 +               if (i2c_check_functionality(client->adapter,
15014 +                                           I2C_FUNC_SMBUS_READ_I2C_BLOCK))
15015 +               {
15016 +                       for (i = slice << 5; i < (slice + 1) << 5;
15017 +                                                   i += I2C_SMBUS_I2C_BLOCK_MAX)
15018 +                               if (i2c_smbus_read_i2c_block_data(client,
15019 +                                                          i, data->data + i)
15020 +                                                   != I2C_SMBUS_I2C_BLOCK_MAX) {
15021 +                                       printk(KERN_WARNING "eeprom.o: block read fail at 0x%.2x!\n", i);
15022 +                                       goto DONE;
15023 +                               }
15024 +               } else {
15025 +                       if (i2c_smbus_write_byte(client, slice << 5)) {
15026 +                               printk(KERN_WARNING "eeprom.o: read start fail at 0x%.2x!\n", slice << 5);
15027 +                               goto DONE;
15028 +                       }
15029 +                       for (i = slice << 5; i < (slice + 1) << 5; i++) {
15030 +                               j = i2c_smbus_read_byte(client);
15031 +                               if (j < 0) {
15032 +                                       printk(KERN_WARNING "eeprom.o: read fail at 0x%.2x!\n", i);
15033 +                                       goto DONE;
15034 +                               }
15035 +                               data->data[i] = (u8) j;
15036 +                       }
15037 +               }
15038 +               data->last_updated[slice] = jiffies;
15039 +               data->valid |= (1 << slice);
15040 +       }
15041 +DONE:
15042 +       up(&data->update_lock);
15043 +}
15044 +
15045 +
15046 +void eeprom_contents(struct i2c_client *client, int operation,
15047 +                    int ctl_name, int *nrels_mag, long *results)
15048 +{
15049 +       int i;
15050 +       int nr = ctl_name - EEPROM_SYSCTL1;
15051 +       struct eeprom_data *data = client->data;
15052 +
15053 +       if (operation == SENSORS_PROC_REAL_INFO)
15054 +               *nrels_mag = 0;
15055 +       else if (operation == SENSORS_PROC_REAL_READ) {
15056 +               eeprom_update_client(client, nr >> 1);
15057 +               /* Hide Vaio security settings to regular users */
15058 +               if (nr == 0 && data->nature == NATURE_VAIO
15059 +                && !capable(CAP_SYS_ADMIN))
15060 +                       for (i = 0; i < 16; i++)
15061 +                               results[i] = 0;
15062 +               else
15063 +                       for (i = 0; i < 16; i++)
15064 +                               results[i] = data->data[i + nr * 16];
15065 +#ifdef DEBUG
15066 +               printk("eeprom.o: 0x%X EEPROM contents (row %d):",
15067 +                      client->addr, nr + 1);
15068 +               if (nr == 0 && data->nature == NATURE_VAIO)
15069 +                       printk(" <hidden for security reasons>\n");
15070 +               else {
15071 +                       for (i = 0; i < 16; i++)
15072 +                               printk(" 0x%02X", data->data[i + nr * 16]);
15073 +                       printk("\n");
15074 +               }
15075 +#endif
15076 +               *nrels_mag = 16;
15077 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
15078 +
15079 +/* No writes to the EEPROM (yet, anyway) (PAE) */
15080 +               printk("eeprom.o: No writes to EEPROMs supported!\n");
15081 +       }
15082 +}
15083 +
15084 +static int __init sm_eeprom_init(void)
15085 +{
15086 +       printk("eeprom.o version %s (%s)\n", LM_VERSION, LM_DATE);
15087 +       return i2c_add_driver(&eeprom_driver);
15088 +}
15089 +
15090 +static void __exit sm_eeprom_exit(void)
15091 +{
15092 +       i2c_del_driver(&eeprom_driver);
15093 +}
15094 +
15095 +
15096 +
15097 +MODULE_AUTHOR
15098 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
15099 +MODULE_DESCRIPTION("EEPROM driver");
15100 +
15101 +module_init(sm_eeprom_init);
15102 +module_exit(sm_eeprom_exit);
15103 --- linux-old/drivers/sensors/fscpos.c  Thu Jan  1 00:00:00 1970
15104 +++ linux/drivers/sensors/fscpos.c      Mon Dec 13 20:18:46 2004
15105 @@ -0,0 +1,690 @@
15106 +/*
15107 +    fscpos.c - Part of lm_sensors, Linux kernel modules for hardware
15108 +             monitoring
15109 +    Copyright (c) 2001 Hermann Jung <hej@odn.de>
15110 +
15111 +    This program is free software; you can redistribute it and/or modify
15112 +    it under the terms of the GNU General Public License as published by
15113 +    the Free Software Foundation; either version 2 of the License, or
15114 +    (at your option) any later version.
15115 +
15116 +    This program is distributed in the hope that it will be useful,
15117 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
15118 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15119 +    GNU General Public License for more details.
15120 +
15121 +    You should have received a copy of the GNU General Public License
15122 +    along with this program; if not, write to the Free Software
15123 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15124 +*/
15125 +
15126 +/* 
15127 +    fujitsu siemens poseidon chip, 
15128 +    module based on lm80.c 
15129 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
15130 +    and Philip Edelbrock <phil@netroedge.com>
15131 +*/
15132 +
15133 +#include <linux/module.h>
15134 +#include <linux/slab.h>
15135 +#include <linux/i2c.h>
15136 +#include <linux/i2c-proc.h>
15137 +#include <linux/init.h>
15138 +#define LM_DATE "20041007"
15139 +#define LM_VERSION "2.8.8"
15140 +
15141 +/* Addresses to scan */
15142 +static unsigned short normal_i2c[] = { 0x73, SENSORS_I2C_END };
15143 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
15144 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
15145 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
15146 +
15147 +/* Insmod parameters */
15148 +SENSORS_INSMOD_1(fscpos);
15149 +
15150 +/* The FSCPOS registers */
15151 +
15152 +/* chip identification */
15153 +#define FSCPOS_REG_IDENT_0    0x00
15154 +#define FSCPOS_REG_IDENT_1    0x01
15155 +#define FSCPOS_REG_IDENT_2    0x02
15156 +#define FSCPOS_REG_REVISION   0x03
15157 +
15158 +/* global control and status */
15159 +#define FSCPOS_REG_EVENT_STATE  0x04
15160 +#define FSCPOS_REG_CONTROL       0x05
15161 +
15162 +/* watchdog */
15163 +#define FSCPOS_REG_WDOG_PRESET      0x28
15164 +#define FSCPOS_REG_WDOG_STATE       0x23
15165 +#define FSCPOS_REG_WDOG_CONTROL     0x21
15166 +
15167 +/* fan 0  */
15168 +#define FSCPOS_REG_FAN0_MIN      0x55
15169 +#define FSCPOS_REG_FAN0_ACT      0x0e
15170 +#define FSCPOS_REG_FAN0_STATE   0x0d
15171 +#define FSCPOS_REG_FAN0_RIPPLE   0x0f
15172 +
15173 +/* fan 1  */
15174 +#define FSCPOS_REG_FAN1_MIN      0x65
15175 +#define FSCPOS_REG_FAN1_ACT      0x6b
15176 +#define FSCPOS_REG_FAN1_STATE   0x62
15177 +#define FSCPOS_REG_FAN1_RIPPLE   0x6f
15178 +
15179 +/* fan 2  */
15180 +/* min speed fan2 not supported */
15181 +#define FSCPOS_REG_FAN2_ACT      0xab
15182 +#define FSCPOS_REG_FAN2_STATE   0xa2
15183 +#define FSCPOS_REG_FAN2_RIPPLE   0x0af
15184 +
15185 +/* voltage supervision */
15186 +#define FSCPOS_REG_VOLT_12       0x45
15187 +#define FSCPOS_REG_VOLT_5        0x42
15188 +#define FSCPOS_REG_VOLT_BATT     0x48
15189 +
15190 +/* temperatures */
15191 +/* sensor 0 */
15192 +#define FSCPOS_REG_TEMP0_ACT       0x64
15193 +#define FSCPOS_REG_TEMP0_STATE    0x71
15194 +
15195 +/* sensor 1 */
15196 +#define FSCPOS_REG_TEMP1_ACT       0x32
15197 +#define FSCPOS_REG_TEMP1_STATE    0x81
15198 +
15199 +/* sensor 2 */
15200 +#define FSCPOS_REG_TEMP2_ACT       0x35
15201 +#define FSCPOS_REG_TEMP2_STATE    0x91
15202 +
15203 +
15204 +
15205 +
15206 +/* Conversions. Rounding and limit checking is only done on the TO_REG
15207 +   variants. Note that you should be a bit careful with which arguments
15208 +   these macros are called: arguments may be evaluated more than once.
15209 +   Fixing this is just not worth it. */
15210 +
15211 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT((val),0,255))
15212 +#define IN_FROM_REG(val,nr) (val)
15213 +
15214 +/* Initial limits */
15215 +
15216 +/* For each registered FSCPOS, we need to keep some data in memory. That
15217 +   data is pointed to by fscpos_list[NR]->data. The structure itself is
15218 +   dynamically allocated, at the same time when a new fscpos client is
15219 +   allocated. */
15220 +struct fscpos_data {
15221 +       struct i2c_client client;
15222 +       int sysctl_id;
15223 +
15224 +       struct semaphore update_lock;
15225 +       char valid;             /* !=0 if following fields are valid */
15226 +       unsigned long last_updated;     /* In jiffies */
15227 +
15228 +       u8  revision;        /* revision of chip */
15229 +       u8  global_event;    /* global event status */
15230 +       u8  global_control;  /* global control register */
15231 +       u8  watchdog[3];     /* watchdog */
15232 +       u8  volt[3];         /* 12, 5, battery current */ 
15233 +       u8  temp_act[3];     /* temperature */
15234 +       u8  temp_status[3];  /* status of sensor */
15235 +       u8  fan_act[3];      /* fans revolutions per second */
15236 +       u8  fan_status[3];   /* fan status */
15237 +       u8  fan_min[3];      /* fan min value for rps */
15238 +       u8  fan_ripple[3];   /* divider for rps */
15239 +};
15240 +
15241 +
15242 +static int fscpos_attach_adapter(struct i2c_adapter *adapter);
15243 +static int fscpos_detect(struct i2c_adapter *adapter, int address,
15244 +                      unsigned short flags, int kind);
15245 +static int fscpos_detach_client(struct i2c_client *client);
15246 +
15247 +static int fscpos_read_value(struct i2c_client *client, u8 register);
15248 +static int fscpos_write_value(struct i2c_client *client, u8 register,
15249 +                           u8 value);
15250 +static void fscpos_update_client(struct i2c_client *client);
15251 +static void fscpos_init_client(struct i2c_client *client);
15252 +
15253 +
15254 +static void fscpos_in(struct i2c_client *client, int operation, int ctl_name,
15255 +                       int *nrels_mag, long *results);
15256 +static void fscpos_fan(struct i2c_client *client, int operation,
15257 +                       int ctl_name, int *nrels_mag, long *results);
15258 +static void fscpos_fan_internal(struct i2c_client *client, int operation,
15259 +                       int ctl_name, int *nrels_mag, long *results, 
15260 +                       int nr, int reg_state, int reg_min, int res_ripple);
15261 +static void fscpos_temp(struct i2c_client *client, int operation,
15262 +                       int ctl_name, int *nrels_mag, long *results);
15263 +static void fscpos_volt(struct i2c_client *client, int operation,
15264 +                       int ctl_name, int *nrels_mag, long *results);
15265 +static void fscpos_wdog(struct i2c_client *client, int operation,
15266 +                       int ctl_name, int *nrels_mag, long *results);
15267 +
15268 +static int fscpos_id = 0;
15269 +
15270 +static struct i2c_driver fscpos_driver = {
15271 +       .owner          = THIS_MODULE,
15272 +       .name           = "FSCPOS sensor driver",
15273 +       .id             = I2C_DRIVERID_FSCPOS,
15274 +       .flags          = I2C_DF_NOTIFY,
15275 +       .attach_adapter = fscpos_attach_adapter,
15276 +       .detach_client  = fscpos_detach_client,
15277 +};
15278 +
15279 +/* -- SENSORS SYSCTL START -- */
15280 +#define FSCPOS_SYSCTL_VOLT0    1000       /* 12 volt supply */
15281 +#define FSCPOS_SYSCTL_VOLT1    1001       /* 5 volt supply */
15282 +#define FSCPOS_SYSCTL_VOLT2    1002       /* batterie voltage*/
15283 +#define FSCPOS_SYSCTL_FAN0     1101       /* state, min, ripple, actual value fan 0 */
15284 +#define FSCPOS_SYSCTL_FAN1     1102       /* state, min, ripple, actual value fan 1 */
15285 +#define FSCPOS_SYSCTL_FAN2     1103       /* state, min, ripple, actual value fan 2 */
15286 +#define FSCPOS_SYSCTL_TEMP0    1201       /* state and value of sensor 0, cpu die */
15287 +#define FSCPOS_SYSCTL_TEMP1    1202       /* state and value of sensor 1, motherboard */
15288 +#define FSCPOS_SYSCTL_TEMP2    1203       /* state and value of sensor 2, chassis */
15289 +#define FSCPOS_SYSCTL_REV     2000        /* Revision */
15290 +#define FSCPOS_SYSCTL_EVENT   2001        /* global event status */
15291 +#define FSCPOS_SYSCTL_CONTROL 2002        /* global control byte */
15292 +#define FSCPOS_SYSCTL_WDOG     2003       /* state, min, ripple, actual value fan 2 */
15293 +/* -- SENSORS SYSCTL END -- */
15294 +
15295 +/* These files are created for each detected FSCPOS. This is just a template;
15296 +   though at first sight, you might think we could use a statically
15297 +   allocated list, we need some way to get back to the parent - which
15298 +   is done through one of the 'extra' fields which are initialized 
15299 +   when a new copy is allocated. */
15300 +static ctl_table fscpos_dir_table_template[] = {
15301 +       {FSCPOS_SYSCTL_REV, "rev", NULL, 0, 0444, NULL, &i2c_proc_real,
15302 +        &i2c_sysctl_real, NULL, &fscpos_in},
15303 +       {FSCPOS_SYSCTL_EVENT, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
15304 +        &i2c_sysctl_real, NULL, &fscpos_in},
15305 +       {FSCPOS_SYSCTL_CONTROL, "control", NULL, 0, 0644, NULL, &i2c_proc_real,
15306 +        &i2c_sysctl_real, NULL, &fscpos_in},
15307 +       {FSCPOS_SYSCTL_TEMP0, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
15308 +        &i2c_sysctl_real, NULL, &fscpos_temp},
15309 +       {FSCPOS_SYSCTL_TEMP1, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
15310 +        &i2c_sysctl_real, NULL, &fscpos_temp},
15311 +       {FSCPOS_SYSCTL_TEMP2, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
15312 +        &i2c_sysctl_real, NULL, &fscpos_temp},
15313 +       {FSCPOS_SYSCTL_VOLT0, "in0", NULL, 0, 0444, NULL, &i2c_proc_real,
15314 +        &i2c_sysctl_real, NULL, &fscpos_volt},
15315 +       {FSCPOS_SYSCTL_VOLT1, "in1", NULL, 0, 0444, NULL, &i2c_proc_real,
15316 +        &i2c_sysctl_real, NULL, &fscpos_volt},
15317 +       {FSCPOS_SYSCTL_VOLT2, "in2", NULL, 0, 0444, NULL, &i2c_proc_real,
15318 +        &i2c_sysctl_real, NULL, &fscpos_volt},
15319 +       {FSCPOS_SYSCTL_FAN0, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
15320 +        &i2c_sysctl_real, NULL, &fscpos_fan},
15321 +       {FSCPOS_SYSCTL_FAN1, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
15322 +        &i2c_sysctl_real, NULL, &fscpos_fan},
15323 +       {FSCPOS_SYSCTL_FAN2, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
15324 +        &i2c_sysctl_real, NULL, &fscpos_fan},
15325 +       {FSCPOS_SYSCTL_WDOG, "wdog", NULL, 0, 0644, NULL, &i2c_proc_real,
15326 +        &i2c_sysctl_real, NULL, &fscpos_wdog},
15327 +       {0}
15328 +};
15329 +
15330 +static int fscpos_attach_adapter(struct i2c_adapter *adapter)
15331 +{
15332 +       return i2c_detect(adapter, &addr_data, fscpos_detect);
15333 +}
15334 +
15335 +int fscpos_detect(struct i2c_adapter *adapter, int address,
15336 +               unsigned short flags, int kind)
15337 +{
15338 +       int i;
15339 +       struct i2c_client *new_client;
15340 +       struct fscpos_data *data;
15341 +       int err = 0;
15342 +       const char *type_name, *client_name;
15343 +
15344 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
15345 +          at this moment; i2c_detect really won't call us. */
15346 +#ifdef DEBUG
15347 +       if (i2c_is_isa_adapter(adapter)) {
15348 +               printk
15349 +                   ("fscpos.o: fscpos_detect called for an ISA bus adapter?!?\n");
15350 +               return 0;
15351 +       }
15352 +#endif
15353 +
15354 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
15355 +               goto ERROR0;
15356 +
15357 +       /* OK. For now, we presume we have a valid client. We now create the
15358 +          client structure, even though we cannot fill it completely yet.
15359 +          But it allows us to access fscpos_{read,write}_value. */
15360 +       if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
15361 +               err = -ENOMEM;
15362 +               goto ERROR0;
15363 +       }
15364 +
15365 +       new_client = &data->client;
15366 +       new_client->addr = address;
15367 +       new_client->data = data;
15368 +       new_client->adapter = adapter;
15369 +       new_client->driver = &fscpos_driver;
15370 +       new_client->flags = 0;
15371 +
15372 +       /* Do the remaining detection unless force or force_fscpos parameter */
15373 +       if (kind < 0) {
15374 +               if (fscpos_read_value(new_client, FSCPOS_REG_IDENT_0) != 0x50)
15375 +                       goto ERROR1;
15376 +               if (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1) != 0x45)
15377 +                       goto ERROR1;
15378 +               if (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2) != 0x47)
15379 +                       goto ERROR1;
15380 +       }
15381 +
15382 +       kind = fscpos;
15383 +
15384 +       type_name = "fscpos";
15385 +       client_name = "fsc poseidon chip";
15386 +
15387 +       /* Fill in the remaining client fields and put it into the global list */
15388 +       strcpy(new_client->name, client_name);
15389 +
15390 +       new_client->id = fscpos_id++;
15391 +       data->valid = 0;
15392 +       init_MUTEX(&data->update_lock);
15393 +
15394 +       /* Tell the I2C layer a new client has arrived */
15395 +       if ((err = i2c_attach_client(new_client)))
15396 +               goto ERROR3;
15397 +
15398 +       /* Register a new directory entry with module sensors */
15399 +       if ((i = i2c_register_entry(new_client, type_name,
15400 +                                       fscpos_dir_table_template)) < 0) {
15401 +               err = i;
15402 +               goto ERROR4;
15403 +       }
15404 +       data->sysctl_id = i;
15405 +
15406 +       fscpos_init_client(new_client);
15407 +       return 0;
15408 +
15409 +/* OK, this is not exactly good programming practice, usually. But it is
15410 +   very code-efficient in this case. */
15411 +      ERROR4:
15412 +       i2c_detach_client(new_client);
15413 +      ERROR3:
15414 +      ERROR1:
15415 +       kfree(data);
15416 +      ERROR0:
15417 +       return err;
15418 +}
15419 +
15420 +static int fscpos_detach_client(struct i2c_client *client)
15421 +{
15422 +       int err;
15423 +
15424 +       i2c_deregister_entry(((struct fscpos_data *) (client->data))->
15425 +                                sysctl_id);
15426 +
15427 +       if ((err = i2c_detach_client(client))) {
15428 +               printk
15429 +                   ("fscpos.o: Client deregistration failed, client not detached.\n");
15430 +               return err;
15431 +       }
15432 +
15433 +       kfree(client->data);
15434 +
15435 +       return 0;
15436 +}
15437 +
15438 +static int fscpos_read_value(struct i2c_client *client, u8 reg)
15439 +{
15440 +#ifdef DEBUG
15441 +       printk("fscpos: read reg 0x%02x\n",reg);
15442 +#endif
15443 +       return i2c_smbus_read_byte_data(client, reg);
15444 +}
15445 +
15446 +static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value)
15447 +{
15448 +#ifdef DEBUG
15449 +       printk("fscpos: write reg 0x%02x, val 0x%02x\n",reg, value);
15450 +#endif
15451 +       return i2c_smbus_write_byte_data(client, reg, value);
15452 +}
15453 +
15454 +/* Called when we have found a new FSCPOS. It should set limits, etc. */
15455 +static void fscpos_init_client(struct i2c_client *client)
15456 +{
15457 +       struct fscpos_data *data = client->data;
15458 +
15459 +       /* read revision from chip */
15460 +       data->revision =  fscpos_read_value(client,FSCPOS_REG_REVISION);
15461 +       /* setup missing fan2_min value */
15462 +       data->fan_min[2] = 0xff;
15463 +}
15464 +
15465 +static void fscpos_update_client(struct i2c_client *client)
15466 +{
15467 +       struct fscpos_data *data = client->data;
15468 +
15469 +       down(&data->update_lock);
15470 +
15471 +       if ((jiffies - data->last_updated > 2 * HZ) ||
15472 +           (jiffies < data->last_updated) || !data->valid) {
15473 +
15474 +#ifdef DEBUG
15475 +               printk("Starting fscpos update\n");
15476 +#endif
15477 +               data->temp_act[0] = fscpos_read_value(client, FSCPOS_REG_TEMP0_ACT);
15478 +               data->temp_act[1] = fscpos_read_value(client, FSCPOS_REG_TEMP1_ACT);
15479 +               data->temp_act[2] = fscpos_read_value(client, FSCPOS_REG_TEMP2_ACT);
15480 +               data->temp_status[0] = fscpos_read_value(client, FSCPOS_REG_TEMP0_STATE);
15481 +               data->temp_status[1] = fscpos_read_value(client, FSCPOS_REG_TEMP1_STATE);
15482 +               data->temp_status[2] = fscpos_read_value(client, FSCPOS_REG_TEMP2_STATE);
15483 +
15484 +               data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12);
15485 +               data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5);
15486 +               data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT);
15487 +
15488 +               data->fan_act[0] = fscpos_read_value(client, FSCPOS_REG_FAN0_ACT);
15489 +               data->fan_act[1] = fscpos_read_value(client, FSCPOS_REG_FAN1_ACT);
15490 +               data->fan_act[2] = fscpos_read_value(client, FSCPOS_REG_FAN2_ACT);
15491 +               data->fan_status[0] = fscpos_read_value(client, FSCPOS_REG_FAN0_STATE);
15492 +               data->fan_status[1] = fscpos_read_value(client, FSCPOS_REG_FAN1_STATE);
15493 +               data->fan_status[2] = fscpos_read_value(client, FSCPOS_REG_FAN2_STATE);
15494 +               data->fan_min[0] = fscpos_read_value(client, FSCPOS_REG_FAN0_MIN);
15495 +               data->fan_min[1] = fscpos_read_value(client, FSCPOS_REG_FAN1_MIN);
15496 +               /* fan2_min is not supported */
15497 +               data->fan_ripple[0] = fscpos_read_value(client, FSCPOS_REG_FAN0_RIPPLE);
15498 +               data->fan_ripple[1] = fscpos_read_value(client, FSCPOS_REG_FAN1_RIPPLE);
15499 +               data->fan_ripple[2] = fscpos_read_value(client, FSCPOS_REG_FAN2_RIPPLE);
15500 +
15501 +               data->watchdog[0] = fscpos_read_value(client, FSCPOS_REG_WDOG_PRESET);
15502 +               data->watchdog[1] = fscpos_read_value(client, FSCPOS_REG_WDOG_STATE);
15503 +               data->watchdog[2] = fscpos_read_value(client, FSCPOS_REG_WDOG_CONTROL);
15504 +
15505 +               data->global_event = fscpos_read_value(client, FSCPOS_REG_EVENT_STATE);
15506 +
15507 +                data->last_updated = jiffies;
15508 +                data->valid = 1;                 
15509 +       }
15510 +
15511 +       up(&data->update_lock);
15512 +}
15513 +
15514 +
15515 +/* The next few functions are the call-back functions of the /proc/sys and
15516 +   sysctl files. Which function is used is defined in the ctl_table in
15517 +   the extra1 field.
15518 +   Each function must return the magnitude (power of 10 to divide the date
15519 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
15520 +   put a maximum of *nrels elements in results reflecting the data of this
15521 +   file, and set *nrels to the number it actually put in it, if operation==
15522 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
15523 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
15524 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
15525 +   large enough (by checking the incoming value of *nrels). This is not very
15526 +   good practice, but as long as you put less than about 5 values in results,
15527 +   you can assume it is large enough. */
15528 +void fscpos_in(struct i2c_client *client, int operation, int ctl_name,
15529 +            int *nrels_mag, long *results)
15530 +{
15531 +       struct fscpos_data *data = client->data;
15532 +
15533 +       if (operation == SENSORS_PROC_REAL_INFO)
15534 +               *nrels_mag = 0;
15535 +       else if (operation == SENSORS_PROC_REAL_READ) {
15536 +               fscpos_update_client(client);
15537 +               switch(ctl_name) {
15538 +                       case FSCPOS_SYSCTL_REV:
15539 +                               results[0] = data->revision ;
15540 +                               break;
15541 +                       case FSCPOS_SYSCTL_EVENT:
15542 +                               results[0] = data->global_event & 0x1f;
15543 +                               break;
15544 +                       case FSCPOS_SYSCTL_CONTROL:
15545 +                               results[0] = data->global_control & 0x01;
15546 +                               break;
15547 +                       default:
15548 +                               printk("fscpos: ctl_name %d not supported\n",
15549 +                                       ctl_name);
15550 +                               *nrels_mag = 0;
15551 +                               return;
15552 +               }
15553 +               *nrels_mag = 1;
15554 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
15555 +               if((ctl_name == FSCPOS_SYSCTL_CONTROL) && (*nrels_mag >= 1)) {
15556 +                       data->global_control = (results[0] & 0x01);
15557 +                       printk("fscpos: writing 0x%02x to global_control\n",
15558 +                               data->global_control);
15559 +                       fscpos_write_value(client,FSCPOS_REG_CONTROL,
15560 +                               data->global_control);
15561 +               }
15562 +               else
15563 +                       printk("fscpos: writing to chip not supported\n");
15564 +       }
15565 +}
15566 +
15567 +#define TEMP_FROM_REG(val)    (val-128)
15568 +
15569 +
15570 +void fscpos_temp(struct i2c_client *client, int operation, int ctl_name,
15571 +              int *nrels_mag, long *results)
15572 +{
15573 +       struct fscpos_data *data = client->data;
15574 +
15575 +       if (operation == SENSORS_PROC_REAL_INFO)
15576 +               *nrels_mag = 0;
15577 +       else if (operation == SENSORS_PROC_REAL_READ) {
15578 +               fscpos_update_client(client);
15579 +               switch(ctl_name) {
15580 +                       case FSCPOS_SYSCTL_TEMP0:
15581 +                               results[0] = data->temp_status[0] & 0x03;
15582 +                               results[1] = TEMP_FROM_REG(data->temp_act[0]);
15583 +                               break;
15584 +                       case FSCPOS_SYSCTL_TEMP1:
15585 +                               results[0] = data->temp_status[1] & 0x03;
15586 +                               results[1] = TEMP_FROM_REG(data->temp_act[1]);
15587 +                               break;
15588 +                       case FSCPOS_SYSCTL_TEMP2:
15589 +                               results[0] = data->temp_status[2] & 0x03;
15590 +                               results[1] = TEMP_FROM_REG(data->temp_act[2]);
15591 +                               break;
15592 +                       default:
15593 +                               printk("fscpos: ctl_name %d not supported\n",
15594 +                                       ctl_name);
15595 +                               *nrels_mag = 0;
15596 +                               return;
15597 +               }
15598 +               *nrels_mag = 2;
15599 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
15600 +               if(*nrels_mag >= 1) {
15601 +                       switch(ctl_name) {
15602 +                               case FSCPOS_SYSCTL_TEMP0:
15603 +                                       data->temp_status[0] = 
15604 +                                               (data->temp_status[0] & ~0x02) 
15605 +                                               | (results[0] & 0x02);
15606 +                                       printk("fscpos: writing value 0x%02x "
15607 +                                               "to temp0_status\n",
15608 +                                               data->temp_status[0]);
15609 +                                       fscpos_write_value(client,
15610 +                                               FSCPOS_REG_TEMP0_STATE,
15611 +                                               data->temp_status[0] & 0x02);
15612 +                                       break;
15613 +                               case FSCPOS_SYSCTL_TEMP1:
15614 +                                       data->temp_status[1] = (data->temp_status[1] & ~0x02) | (results[0] & 0x02);
15615 +                                       printk("fscpos: writing value 0x%02x to temp1_status\n", data->temp_status[1]);
15616 +                                       fscpos_write_value(client,FSCPOS_REG_TEMP1_STATE,
15617 +                                               data->temp_status[1] & 0x02);
15618 +                                       break;
15619 +                               case FSCPOS_SYSCTL_TEMP2:
15620 +                                       data->temp_status[2] = (data->temp_status[2] & ~0x02) | (results[0] & 0x02);
15621 +                                       printk("fscpos: writing value 0x%02x to temp2_status\n", data->temp_status[2]);
15622 +                                       fscpos_write_value(client,FSCPOS_REG_TEMP2_STATE,
15623 +                                               data->temp_status[2] & 0x02);
15624 +                                       break;
15625 +                               default:
15626 +                                       printk("fscpos: ctl_name %d not supported\n",ctl_name);
15627 +                       }
15628 +               }
15629 +               else
15630 +                       printk("fscpos: writing to chip not supported\n");
15631 +       }
15632 +}
15633 +
15634 +#define VOLT_FROM_REG(val,mult)    (val*mult/255)
15635 +
15636 +void fscpos_volt(struct i2c_client *client, int operation, int ctl_name,
15637 +              int *nrels_mag, long *results)
15638 +{
15639 +       struct fscpos_data *data = client->data;
15640 +       if (operation == SENSORS_PROC_REAL_INFO)
15641 +               *nrels_mag = 2;
15642 +       else if (operation == SENSORS_PROC_REAL_READ) {
15643 +               fscpos_update_client(client);
15644 +               switch(ctl_name) {
15645 +                       case FSCPOS_SYSCTL_VOLT0:
15646 +                               results[0] = VOLT_FROM_REG(data->volt[0],1420);
15647 +                               break;
15648 +                       case FSCPOS_SYSCTL_VOLT1:
15649 +                               results[0] = VOLT_FROM_REG(data->volt[1],660);
15650 +                               break;
15651 +                       case FSCPOS_SYSCTL_VOLT2:
15652 +                               results[0] = VOLT_FROM_REG(data->volt[2],330);
15653 +                               break;
15654 +                       default:
15655 +                               printk("fscpos: ctl_name %d not supported\n",
15656 +                                       ctl_name);
15657 +                               *nrels_mag = 0;
15658 +                               return;
15659 +               }
15660 +               *nrels_mag = 1;
15661 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
15662 +                       printk("fscpos: writing to chip not supported\n");
15663 +       }
15664 +}
15665 +
15666 +void fscpos_fan(struct i2c_client *client, int operation, int ctl_name,
15667 +              int *nrels_mag, long *results)
15668 +{
15669 +
15670 +       switch(ctl_name) {
15671 +               case FSCPOS_SYSCTL_FAN0:
15672 +                       fscpos_fan_internal(client,operation,ctl_name,nrels_mag,results,
15673 +                               0,FSCPOS_REG_FAN0_STATE,FSCPOS_REG_FAN0_MIN,
15674 +                               FSCPOS_REG_FAN0_RIPPLE);
15675 +                       break;
15676 +               case FSCPOS_SYSCTL_FAN1:
15677 +                       fscpos_fan_internal(client,operation,ctl_name,nrels_mag,results,
15678 +                               1,FSCPOS_REG_FAN1_STATE,FSCPOS_REG_FAN1_MIN,
15679 +                               FSCPOS_REG_FAN1_RIPPLE);
15680 +                       break;
15681 +               case FSCPOS_SYSCTL_FAN2:
15682 +                       fscpos_fan_internal(client,operation,ctl_name,nrels_mag,results,
15683 +                               2,FSCPOS_REG_FAN2_STATE,0xff,
15684 +                               FSCPOS_REG_FAN2_RIPPLE);
15685 +                       break;
15686 +               default:
15687 +                       printk("fscpos: illegal fan nr %d\n",ctl_name);
15688 +       }
15689 +}
15690 +                       
15691 +#define RPM_FROM_REG(val)   (val*60)
15692 +
15693 +void fscpos_fan_internal(struct i2c_client *client, int operation, int ctl_name,
15694 +              int *nrels_mag, long *results, int nr,
15695 +              int reg_state, int reg_min, int reg_ripple )
15696 +{
15697 +       struct fscpos_data *data = client->data;
15698 +
15699 +       if (operation == SENSORS_PROC_REAL_INFO)
15700 +               *nrels_mag = 0;
15701 +       else if (operation == SENSORS_PROC_REAL_READ) {
15702 +               fscpos_update_client(client);
15703 +               results[0] = data->fan_status[nr] & 0x04;
15704 +               results[1] = data->fan_min[nr];
15705 +               results[2] = data->fan_ripple[nr] & 0x03;
15706 +               results[3] = RPM_FROM_REG(data->fan_act[nr]);
15707 +               *nrels_mag = 4;
15708 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
15709 +               if(*nrels_mag >= 1) {
15710 +                       data->fan_status[nr] = results[0] & 0x04;
15711 +                       printk("fscpos: writing value 0x%02x to fan%d_status\n",
15712 +                               data->fan_status[nr],nr);
15713 +                       fscpos_write_value(client,reg_state,
15714 +                               data->fan_status[nr]);
15715 +               }
15716 +               if((*nrels_mag >= 2) && (nr < 2)) {  
15717 +                       /* minimal speed for fan2 not supported */
15718 +                       data->fan_min[nr] = results[1];
15719 +                       printk("fscpos: writing value 0x%02x to fan%d_min\n",
15720 +                               data->fan_min[nr],nr);
15721 +                       fscpos_write_value(client,reg_min,
15722 +                               data->fan_min[nr]);
15723 +               }
15724 +               if(*nrels_mag >= 3) {
15725 +                       if((results[2] & 0x03) == 0) {
15726 +                               printk("fscpos: fan%d ripple 0 not allowed\n",nr);
15727 +                               return;
15728 +                       }
15729 +                       data->fan_ripple[nr] = results[2] & 0x03;
15730 +                       printk("fscpos: writing value 0x%02x to fan%d_ripple\n",
15731 +                               data->fan_ripple[nr],nr);
15732 +                       fscpos_write_value(client,reg_ripple,
15733 +                               data->fan_ripple[nr]);
15734 +               }       
15735 +       }
15736 +}
15737 +
15738 +void fscpos_wdog(struct i2c_client *client, int operation, int ctl_name,
15739 +            int *nrels_mag, long *results)
15740 +{
15741 +       struct fscpos_data *data = client->data;
15742 +
15743 +       if (operation == SENSORS_PROC_REAL_INFO)
15744 +               *nrels_mag = 0;
15745 +       else if (operation == SENSORS_PROC_REAL_READ) {
15746 +               fscpos_update_client(client);
15747 +               results[0] = data->watchdog[0] ;
15748 +               results[1] = data->watchdog[1] & 0x02;
15749 +               results[2] = data->watchdog[2] & 0xb0;
15750 +               *nrels_mag = 3;
15751 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
15752 +               if (*nrels_mag >= 1) {
15753 +                       data->watchdog[0] = results[0] & 0xff;
15754 +                       printk("fscpos: writing value 0x%02x to wdog_preset\n",
15755 +                               data->watchdog[0]); 
15756 +                       fscpos_write_value(client,FSCPOS_REG_WDOG_PRESET,
15757 +                               data->watchdog[0]);
15758 +               } 
15759 +               if (*nrels_mag >= 2) {
15760 +                       data->watchdog[1] = results[1] & 0x02;
15761 +                       printk("fscpos: writing value 0x%02x to wdog_state\n",
15762 +                               data->watchdog[1]); 
15763 +                       fscpos_write_value(client,FSCPOS_REG_WDOG_STATE,
15764 +                               data->watchdog[1]);
15765 +               }
15766 +               if (*nrels_mag >= 3) {
15767 +                       data->watchdog[2] = results[2] & 0xb0;
15768 +                       printk("fscpos: writing value 0x%02x to wdog_control\n",
15769 +                               data->watchdog[2]); 
15770 +                       fscpos_write_value(client,FSCPOS_REG_WDOG_CONTROL,
15771 +                               data->watchdog[2]);
15772 +               }
15773 +       }
15774 +}
15775 +
15776 +static int __init sm_fscpos_init(void)
15777 +{
15778 +       printk("fscpos.o version %s (%s)\n", LM_VERSION, LM_DATE);
15779 +       return i2c_add_driver(&fscpos_driver);
15780 +}
15781 +
15782 +static void __exit sm_fscpos_exit(void)
15783 +{
15784 +       i2c_del_driver(&fscpos_driver);
15785 +}
15786 +
15787 +
15788 +
15789 +MODULE_AUTHOR
15790 +    ("Hermann Jung <hej@odn.de> based on work from Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
15791 +MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver");
15792 +MODULE_LICENSE("GPL");
15793 +
15794 +module_init(sm_fscpos_init);
15795 +module_exit(sm_fscpos_exit);
15796 --- linux-old/drivers/sensors/fscscy.c  Thu Jan  1 00:00:00 1970
15797 +++ linux/drivers/sensors/fscscy.c      Mon Dec 13 20:18:46 2004
15798 @@ -0,0 +1,915 @@
15799 +/*
15800 +    fscscy.c - Part of lm_sensors, Linux kernel modules for hardware
15801 +             monitoring
15802 +    Copyright (c) 2001 Martin Knoblauch <mkn@teraport.de, knobi@knobisoft.de>
15803 +
15804 +    This program is free software; you can redistribute it and/or modify
15805 +    it under the terms of the GNU General Public License as published by
15806 +    the Free Software Foundation; either version 2 of the License, or
15807 +    (at your option) any later version.
15808 +
15809 +    This program is distributed in the hope that it will be useful,
15810 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
15811 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15812 +    GNU General Public License for more details.
15813 +
15814 +    You should have received a copy of the GNU General Public License
15815 +    along with this program; if not, write to the Free Software
15816 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15817 +*/
15818 +
15819 +/* 
15820 +    fujitsu siemens scylla chip, 
15821 +    module based on lm80.c, fscpos.c
15822 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
15823 +    and Philip Edelbrock <phil@netroedge.com>
15824 +*/
15825 +
15826 +#include <linux/module.h>
15827 +#include <linux/slab.h>
15828 +#include <linux/i2c.h>
15829 +#include <linux/i2c-proc.h>
15830 +#include <linux/init.h>
15831 +#define LM_DATE "20041007"
15832 +#define LM_VERSION "2.8.8"
15833 +
15834 +MODULE_LICENSE("GPL");
15835 +
15836 +/* Addresses to scan */
15837 +static unsigned short normal_i2c[] = { 0x73, SENSORS_I2C_END };
15838 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
15839 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
15840 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
15841 +
15842 +/* Insmod parameters */
15843 +SENSORS_INSMOD_1(fscscy);
15844 +
15845 +/* The FSCSCY registers */
15846 +
15847 +/* chip identification */
15848 +#define FSCSCY_REG_IDENT_0    0x00
15849 +#define FSCSCY_REG_IDENT_1    0x01
15850 +#define FSCSCY_REG_IDENT_2    0x02
15851 +#define FSCSCY_REG_REVISION   0x03
15852 +
15853 +/* global control and status */
15854 +#define FSCSCY_REG_EVENT_STATE  0x04
15855 +#define FSCSCY_REG_CONTROL       0x05
15856 +
15857 +/* watchdog */
15858 +#define FSCSCY_REG_WDOG_PRESET      0x28
15859 +#define FSCSCY_REG_WDOG_STATE       0x23
15860 +#define FSCSCY_REG_WDOG_CONTROL     0x21
15861 +
15862 +/*
15863 +** Fan definitions
15864 +**
15865 +** _RPMMIN: Minimum speed. Can be set via interface, but only for three of the fans
15866 +**          FAN1_RPMMIN is wired to Fan 0 (CPU Fans)
15867 +**          FAN4_RPMMIN is wired to Fan 2 (PS Fans ??)
15868 +**          FAN5_RPMMIN is wired to Fan 3 (AUX Fans ??)
15869 +** _ACT:    Actual Fan Speed
15870 +** _STATE:  Fan status register
15871 +** _RIPPLE: Fan speed multiplier
15872 +*/
15873 +
15874 +/* fan 0  */
15875 +#define FSCSCY_REG_FAN0_RPMMIN 0x65
15876 +#define FSCSCY_REG_FAN0_ACT    0x6b
15877 +#define FSCSCY_REG_FAN0_STATE  0x62
15878 +#define FSCSCY_REG_FAN0_RIPPLE 0x6f
15879 +
15880 +/* fan 1  */
15881 +#define FSCSCY_REG_FAN1_RPMMIN     FSCSCY_REG_FAN0_RPMMIN
15882 +#define FSCSCY_REG_FAN1_ACT     0x6c
15883 +#define FSCSCY_REG_FAN1_STATE   0x61
15884 +#define FSCSCY_REG_FAN1_RIPPLE  0x6f
15885 +
15886 +/* fan 2  */
15887 +#define FSCSCY_REG_FAN2_RPMMIN     0x55
15888 +#define FSCSCY_REG_FAN2_ACT     0x0e
15889 +#define FSCSCY_REG_FAN2_STATE   0x0d
15890 +#define FSCSCY_REG_FAN2_RIPPLE  0x0f
15891 +
15892 +/* fan 3  */
15893 +#define FSCSCY_REG_FAN3_RPMMIN     0xa5
15894 +#define FSCSCY_REG_FAN3_ACT     0xab
15895 +#define FSCSCY_REG_FAN3_STATE   0xa2
15896 +#define FSCSCY_REG_FAN3_RIPPLE  0xaf
15897 +
15898 +/* fan 4  */
15899 +#define FSCSCY_REG_FAN4_RPMMIN     FSCSCY_REG_FAN2_RPMMIN
15900 +#define FSCSCY_REG_FAN4_ACT    0x5c
15901 +#define FSCSCY_REG_FAN4_STATE   0x52
15902 +#define FSCSCY_REG_FAN4_RIPPLE  0x0f
15903 +
15904 +/* fan 5  */
15905 +#define FSCSCY_REG_FAN5_RPMMIN     FSCSCY_REG_FAN3_RPMMIN
15906 +#define FSCSCY_REG_FAN5_ACT     0xbb
15907 +#define FSCSCY_REG_FAN5_STATE   0xb2
15908 +#define FSCSCY_REG_FAN5_RIPPLE  0xbf
15909 +
15910 +/* voltage supervision */
15911 +#define FSCSCY_REG_VOLT_12       0x45
15912 +#define FSCSCY_REG_VOLT_5        0x42
15913 +#define FSCSCY_REG_VOLT_BATT     0x48
15914 +
15915 +/* temperatures */
15916 +/* sensor 0 */
15917 +#define FSCSCY_REG_TEMP0_ACT   0x64
15918 +#define FSCSCY_REG_TEMP0_STATE 0x71
15919 +#define FSCSCY_REG_TEMP0_LIM   0x76
15920 +
15921 +/* sensor 1 */
15922 +#define FSCSCY_REG_TEMP1_ACT   0xD0
15923 +#define FSCSCY_REG_TEMP1_STATE 0xD1
15924 +#define FSCSCY_REG_TEMP1_LIM   0xD6
15925 +
15926 +/* sensor 2 */
15927 +#define FSCSCY_REG_TEMP2_ACT   0x32
15928 +#define FSCSCY_REG_TEMP2_STATE 0x81
15929 +#define FSCSCY_REG_TEMP2_LIM   0x86
15930 +
15931 +/* sensor3 */
15932 +#define FSCSCY_REG_TEMP3_ACT   0x35
15933 +#define FSCSCY_REG_TEMP3_STATE 0x91
15934 +#define FSCSCY_REG_TEMP3_LIM   0x96
15935 +
15936 +/* PCI Load */
15937 +#define FSCSCY_REG_PCILOAD     0x1a
15938 +
15939 +/* Intrusion Sensor */
15940 +#define FSCSCY_REG_INTR_STATE  0x13
15941 +#define FSCSCY_REG_INTR_CTRL   0x12
15942 +
15943 +/* Conversions. Rounding and limit checking is only done on the TO_REG
15944 +   variants. Note that you should be a bit careful with which arguments
15945 +   these macros are called: arguments may be evaluated more than once.
15946 +   Fixing this is just not worth it. */
15947 +
15948 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT((val),0,255))
15949 +#define IN_FROM_REG(val,nr) (val)
15950 +
15951 +/* Initial limits */
15952 +
15953 +/* For each registered FSCSCY, we need to keep some data in memory. That
15954 +   data is pointed to by fscscy_list[NR]->data. The structure itself is
15955 +   dynamically allocated, at the same time when a new fscscy client is
15956 +   allocated. */
15957 +struct fscscy_data {
15958 +       struct i2c_client client;
15959 +       int sysctl_id;
15960 +
15961 +       struct semaphore update_lock;
15962 +       char valid;             /* !=0 if following fields are valid */
15963 +       unsigned long last_updated;     /* In jiffies */
15964 +
15965 +       u8  revision;        /* revision of chip */
15966 +       u8  global_event;    /* global event status */
15967 +       u8  global_control;  /* global control register */
15968 +       u8  watchdog[3];     /* watchdog */
15969 +       u8  volt[3];         /* 12, 5, battery current */ 
15970 +       u8  volt_min[3];     /* minimum voltages over module "lifetime" */
15971 +       u8  volt_max[3];     /* maximum voltages over module "lifetime" */
15972 +       u8  temp_act[4];     /* temperature */
15973 +       u8  temp_status[4];  /* status of temp. sensor */
15974 +       u8  temp_lim[4];     /* limit temperature of temp. sensor */
15975 +       u8  temp_min[4];     /* minimum of temp. sensor, this is just calculated by the module */
15976 +       u8  temp_max[4];     /* maximum of temp. sensor, this is just calculsted by the module */
15977 +       u8  fan_act[6];      /* fans revolutions per second */
15978 +       u8  fan_status[6];   /* fan status */
15979 +       u8  fan_rpmmin[6];   /* fan min value for rps */
15980 +       u8  fan_ripple[6];   /* divider for rps */
15981 +       u8  fan_min[6];      /* minimum RPM over module "lifetime" */
15982 +       u8  fan_max[6];      /* maximum RPM over module "lifetime" */
15983 +       u8  pciload;         /* PCILoad value */
15984 +       u8  intr_status;     /* Intrusion Status */
15985 +       u8  intr_control;    /* Intrusion Control */
15986 +};
15987 +
15988 +
15989 +static int fscscy_attach_adapter(struct i2c_adapter *adapter);
15990 +static int fscscy_detect(struct i2c_adapter *adapter, int address,
15991 +                      unsigned short flags, int kind);
15992 +static int fscscy_detach_client(struct i2c_client *client);
15993 +
15994 +static int fscscy_read_value(struct i2c_client *client, u8 register);
15995 +static int fscscy_write_value(struct i2c_client *client, u8 register,
15996 +                           u8 value);
15997 +static void fscscy_update_client(struct i2c_client *client);
15998 +static void fscscy_init_client(struct i2c_client *client);
15999 +
16000 +
16001 +static void fscscy_in(struct i2c_client *client, int operation, int ctl_name,
16002 +                       int *nrels_mag, long *results);
16003 +static void fscscy_fan(struct i2c_client *client, int operation,
16004 +                       int ctl_name, int *nrels_mag, long *results);
16005 +static void fscscy_fan_internal(struct i2c_client *client, int operation,
16006 +                       int ctl_name, int *nrels_mag, long *results, 
16007 +                       int nr, int reg_state, int reg_min, int res_ripple);
16008 +static void fscscy_temp(struct i2c_client *client, int operation,
16009 +                       int ctl_name, int *nrels_mag, long *results);
16010 +static void fscscy_volt(struct i2c_client *client, int operation,
16011 +                       int ctl_name, int *nrels_mag, long *results);
16012 +static void fscscy_wdog(struct i2c_client *client, int operation,
16013 +                       int ctl_name, int *nrels_mag, long *results);
16014 +static void fscscy_pciload(struct i2c_client *client, int operation,
16015 +                       int ctl_name, int *nrels_mag, long *results);
16016 +static void fscscy_intrusion(struct i2c_client *client, int operation,
16017 +                       int ctl_name, int *nrels_mag, long *results);
16018 +
16019 +static int fscscy_id = 0;
16020 +
16021 +static struct i2c_driver fscscy_driver = {
16022 +       .owner          = THIS_MODULE,
16023 +       .name           = "FSCSCY sensor driver",
16024 +       .id             = I2C_DRIVERID_FSCSCY,
16025 +       .flags          = I2C_DF_NOTIFY,
16026 +       .attach_adapter = fscscy_attach_adapter,
16027 +       .detach_client  = fscscy_detach_client,
16028 +};
16029 +
16030 +/* The /proc/sys entries */
16031 +
16032 +/* -- SENSORS SYSCTL START -- */
16033 +#define FSCSCY_SYSCTL_VOLT0    1000       /* 12 volt supply */
16034 +#define FSCSCY_SYSCTL_VOLT1    1001       /* 5 volt supply */
16035 +#define FSCSCY_SYSCTL_VOLT2    1002       /* batterie voltage*/
16036 +#define FSCSCY_SYSCTL_FAN0     1101       /* state, min, ripple, actual value fan 0 */
16037 +#define FSCSCY_SYSCTL_FAN1     1102       /* state, min, ripple, actual value fan 1 */
16038 +#define FSCSCY_SYSCTL_FAN2     1103       /* state, min, ripple, actual value fan 2 */
16039 +#define FSCSCY_SYSCTL_FAN3     1104       /* state, min, ripple, actual value fan 3 */
16040 +#define FSCSCY_SYSCTL_FAN4     1105       /* state, min, ripple, actual value fan 4 */
16041 +#define FSCSCY_SYSCTL_FAN5     1106       /* state, min, ripple, actual value fan 5 */
16042 +#define FSCSCY_SYSCTL_TEMP0    1201       /* state and value of sensor 0, cpu die */
16043 +#define FSCSCY_SYSCTL_TEMP1    1202       /* state and value of sensor 1, motherboard */
16044 +#define FSCSCY_SYSCTL_TEMP2    1203       /* state and value of sensor 2, chassis */
16045 +#define FSCSCY_SYSCTL_TEMP3    1204       /* state and value of sensor 3, chassis */
16046 +#define FSCSCY_SYSCTL_REV     2000        /* Revision */
16047 +#define FSCSCY_SYSCTL_EVENT   2001        /* global event status */
16048 +#define FSCSCY_SYSCTL_CONTROL 2002        /* global control byte */
16049 +#define FSCSCY_SYSCTL_WDOG     2003       /* state, min, ripple, actual value fan 2 */
16050 +#define FSCSCY_SYSCTL_PCILOAD  2004       /* PCILoad value */
16051 +#define FSCSCY_SYSCTL_INTRUSION 2005      /* state, control for intrusion sensor */
16052 +
16053 +/* -- SENSORS SYSCTL END -- */
16054 +
16055 +/* These files are created for each detected FSCSCY. This is just a template;
16056 +   though at first sight, you might think we could use a statically
16057 +   allocated list, we need some way to get back to the parent - which
16058 +   is done through one of the 'extra' fields which are initialized 
16059 +   when a new copy is allocated. */
16060 +static ctl_table fscscy_dir_table_template[] = {
16061 +       {FSCSCY_SYSCTL_REV, "rev", NULL, 0, 0444, NULL, &i2c_proc_real,
16062 +        &i2c_sysctl_real, NULL, &fscscy_in},
16063 +       {FSCSCY_SYSCTL_EVENT, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
16064 +        &i2c_sysctl_real, NULL, &fscscy_in},
16065 +       {FSCSCY_SYSCTL_CONTROL, "control", NULL, 0, 0644, NULL, &i2c_proc_real,
16066 +        &i2c_sysctl_real, NULL, &fscscy_in},
16067 +       {FSCSCY_SYSCTL_TEMP0, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
16068 +        &i2c_sysctl_real, NULL, &fscscy_temp},
16069 +       {FSCSCY_SYSCTL_TEMP1, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
16070 +        &i2c_sysctl_real, NULL, &fscscy_temp},
16071 +       {FSCSCY_SYSCTL_TEMP2, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
16072 +        &i2c_sysctl_real, NULL, &fscscy_temp},
16073 +       {FSCSCY_SYSCTL_TEMP3, "temp4", NULL, 0, 0644, NULL, &i2c_proc_real,
16074 +        &i2c_sysctl_real, NULL, &fscscy_temp},
16075 +       {FSCSCY_SYSCTL_VOLT0, "in0", NULL, 0, 0444, NULL, &i2c_proc_real,
16076 +        &i2c_sysctl_real, NULL, &fscscy_volt},
16077 +       {FSCSCY_SYSCTL_VOLT1, "in1", NULL, 0, 0444, NULL, &i2c_proc_real,
16078 +        &i2c_sysctl_real, NULL, &fscscy_volt},
16079 +       {FSCSCY_SYSCTL_VOLT2, "in2", NULL, 0, 0444, NULL, &i2c_proc_real,
16080 +        &i2c_sysctl_real, NULL, &fscscy_volt},
16081 +       {FSCSCY_SYSCTL_FAN0, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
16082 +        &i2c_sysctl_real, NULL, &fscscy_fan},
16083 +       {FSCSCY_SYSCTL_FAN1, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
16084 +        &i2c_sysctl_real, NULL, &fscscy_fan},
16085 +       {FSCSCY_SYSCTL_FAN2, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
16086 +        &i2c_sysctl_real, NULL, &fscscy_fan},
16087 +       {FSCSCY_SYSCTL_FAN3, "fan4", NULL, 0, 0644, NULL, &i2c_proc_real,
16088 +        &i2c_sysctl_real, NULL, &fscscy_fan},
16089 +       {FSCSCY_SYSCTL_FAN4, "fan5", NULL, 0, 0644, NULL, &i2c_proc_real,
16090 +        &i2c_sysctl_real, NULL, &fscscy_fan},
16091 +       {FSCSCY_SYSCTL_FAN5, "fan6", NULL, 0, 0644, NULL, &i2c_proc_real,
16092 +        &i2c_sysctl_real, NULL, &fscscy_fan},
16093 +       {FSCSCY_SYSCTL_WDOG, "wdog", NULL, 0, 0644, NULL, &i2c_proc_real,
16094 +        &i2c_sysctl_real, NULL, &fscscy_wdog},
16095 +       {FSCSCY_SYSCTL_PCILOAD, "pciload", NULL, 0, 0444, NULL, &i2c_proc_real,
16096 +        &i2c_sysctl_real, NULL, &fscscy_pciload},
16097 +       {FSCSCY_SYSCTL_INTRUSION, "intrusion", NULL, 0, 0644, NULL, &i2c_proc_real,
16098 +        &i2c_sysctl_real, NULL, &fscscy_intrusion},
16099 +       {0}
16100 +};
16101 +
16102 +static int fscscy_attach_adapter(struct i2c_adapter *adapter)
16103 +{
16104 +       return i2c_detect(adapter, &addr_data, fscscy_detect);
16105 +}
16106 +
16107 +int fscscy_detect(struct i2c_adapter *adapter, int address,
16108 +               unsigned short flags, int kind)
16109 +{
16110 +       int i;
16111 +       struct i2c_client *new_client;
16112 +       struct fscscy_data *data;
16113 +       int err = 0;
16114 +       const char *type_name, *client_name;
16115 +
16116 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
16117 +          at this moment; i2c_detect really won't call us. */
16118 +#ifdef DEBUG
16119 +       if (i2c_is_isa_adapter(adapter)) {
16120 +               printk
16121 +                   ("fscscy.o: fscscy_detect called for an ISA bus adapter?!?\n");
16122 +               return 0;
16123 +       }
16124 +#endif
16125 +
16126 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
16127 +               goto ERROR0;
16128 +
16129 +       /* OK. For now, we presume we have a valid client. We now create the
16130 +          client structure, even though we cannot fill it completely yet.
16131 +          But it allows us to access fscscy_{read,write}_value. */
16132 +       if (!(data = kmalloc(sizeof(struct fscscy_data), GFP_KERNEL))) {
16133 +               err = -ENOMEM;
16134 +               goto ERROR0;
16135 +       }
16136 +
16137 +       new_client = &data->client;
16138 +       new_client->addr = address;
16139 +       new_client->data = data;
16140 +       new_client->adapter = adapter;
16141 +       new_client->driver = &fscscy_driver;
16142 +       new_client->flags = 0;
16143 +
16144 +       /* Do the remaining detection unless force or force_fscscy parameter */
16145 +       if (kind < 0) {
16146 +               if (fscscy_read_value(new_client, FSCSCY_REG_IDENT_0) != 0x53)
16147 +                       goto ERROR1;
16148 +               if (fscscy_read_value(new_client, FSCSCY_REG_IDENT_1) != 0x43)
16149 +                       goto ERROR1;
16150 +               if (fscscy_read_value(new_client, FSCSCY_REG_IDENT_2) != 0x59)
16151 +                       goto ERROR1;
16152 +       }
16153 +
16154 +       kind = fscscy;
16155 +
16156 +       type_name = "fscscy";
16157 +       client_name = "fsc scylla chip";
16158 +
16159 +       /* Fill in the remaining client fields and put it into the global list */
16160 +       strcpy(new_client->name, client_name);
16161 +
16162 +       new_client->id = fscscy_id++;
16163 +       data->valid = 0;
16164 +       init_MUTEX(&data->update_lock);
16165 +
16166 +       /* Tell the I2C layer a new client has arrived */
16167 +       if ((err = i2c_attach_client(new_client)))
16168 +               goto ERROR3;
16169 +
16170 +       /* Register a new directory entry with module sensors */
16171 +       if ((i = i2c_register_entry(new_client, type_name,
16172 +                                       fscscy_dir_table_template)) < 0) {
16173 +               err = i;
16174 +               goto ERROR4;
16175 +       }
16176 +       data->sysctl_id = i;
16177 +
16178 +       fscscy_init_client(new_client);
16179 +       return 0;
16180 +
16181 +/* OK, this is not exactly good programming practice, usually. But it is
16182 +   very code-efficient in this case. */
16183 +      ERROR4:
16184 +       i2c_detach_client(new_client);
16185 +      ERROR3:
16186 +      ERROR1:
16187 +       kfree(data);
16188 +      ERROR0:
16189 +       return err;
16190 +}
16191 +
16192 +static int fscscy_detach_client(struct i2c_client *client)
16193 +{
16194 +       int err;
16195 +
16196 +       i2c_deregister_entry(((struct fscscy_data *) (client->data))->
16197 +                                sysctl_id);
16198 +
16199 +       if ((err = i2c_detach_client(client))) {
16200 +               printk
16201 +                   ("fscscy.o: Client deregistration failed, client not detached.\n");
16202 +               return err;
16203 +       }
16204 +
16205 +       kfree(client->data);
16206 +
16207 +       return 0;
16208 +}
16209 +
16210 +static int fscscy_read_value(struct i2c_client *client, u8 reg)
16211 +{
16212 +#ifdef DEBUG
16213 +       printk("fscscy: read reg 0x%02x\n",reg);
16214 +#endif
16215 +       return i2c_smbus_read_byte_data(client, reg);
16216 +}
16217 +
16218 +static int fscscy_write_value(struct i2c_client *client, u8 reg, u8 value)
16219 +{
16220 +#ifdef DEBUG
16221 +       printk("fscscy: write reg 0x%02x, val 0x%02x\n",reg, value);
16222 +#endif
16223 +       return i2c_smbus_write_byte_data(client, reg, value);
16224 +}
16225 +
16226 +/* Called when we have found a new FSCSCY. It should set limits, etc. */
16227 +static void fscscy_init_client(struct i2c_client *client)
16228 +{
16229 +       struct fscscy_data *data = client->data;
16230 +
16231 +       /* read revision from chip */
16232 +       data->revision =  fscscy_read_value(client,FSCSCY_REG_REVISION);
16233 +
16234 +        /* Initialize min/max values from chip */
16235 +       data->fan_min[0]  = data->fan_max[0]  = fscscy_read_value(client, FSCSCY_REG_FAN0_ACT);
16236 +       data->fan_min[1]  = data->fan_max[1]  = fscscy_read_value(client, FSCSCY_REG_FAN1_ACT);
16237 +       data->fan_min[2]  = data->fan_max[2]  = fscscy_read_value(client, FSCSCY_REG_FAN2_ACT);
16238 +       data->fan_min[3]  = data->fan_max[3]  = fscscy_read_value(client, FSCSCY_REG_FAN3_ACT);
16239 +       data->fan_min[4]  = data->fan_max[4]  = fscscy_read_value(client, FSCSCY_REG_FAN4_ACT);
16240 +       data->fan_min[4]  = data->fan_max[5]  = fscscy_read_value(client, FSCSCY_REG_FAN5_ACT);
16241 +        data->temp_min[0] = data->temp_max[0] = fscscy_read_value(client, FSCSCY_REG_TEMP0_ACT);
16242 +        data->temp_min[1] = data->temp_max[1] = fscscy_read_value(client, FSCSCY_REG_TEMP1_ACT);
16243 +        data->temp_min[2] = data->temp_max[2] = fscscy_read_value(client, FSCSCY_REG_TEMP2_ACT);
16244 +        data->temp_min[3] = data->temp_max[3] = fscscy_read_value(client, FSCSCY_REG_TEMP3_ACT);
16245 +       data->volt_min[0] = data->volt_max[0] = fscscy_read_value(client, FSCSCY_REG_VOLT_12);
16246 +       data->volt_min[1] = data->volt_max[1] = fscscy_read_value(client, FSCSCY_REG_VOLT_5);
16247 +       data->volt_min[2] = data->volt_max[2] = fscscy_read_value(client, FSCSCY_REG_VOLT_BATT);
16248 +}
16249 +
16250 +static void fscscy_update_client(struct i2c_client *client)
16251 +{
16252 +       struct fscscy_data *data = client->data;
16253 +
16254 +       down(&data->update_lock);
16255 +
16256 +       if ((jiffies - data->last_updated > 2 * HZ) ||
16257 +           (jiffies < data->last_updated) || !data->valid) {
16258 +
16259 +#ifdef DEBUG
16260 +               printk("Starting fscscy update\n");
16261 +#endif
16262 +               data->temp_act[0] = fscscy_read_value(client, FSCSCY_REG_TEMP0_ACT);
16263 +                 if (data->temp_min[0] > data->temp_act[0]) data->temp_min[0] = data->temp_act[0];
16264 +                 if (data->temp_max[0] < data->temp_act[0]) data->temp_max[0] = data->temp_act[0];
16265 +               data->temp_act[1] = fscscy_read_value(client, FSCSCY_REG_TEMP1_ACT);
16266 +                 if (data->temp_min[1] > data->temp_act[1]) data->temp_min[1] = data->temp_act[1];
16267 +                 if (data->temp_max[1] < data->temp_act[1]) data->temp_max[1] = data->temp_act[1];
16268 +               data->temp_act[2] = fscscy_read_value(client, FSCSCY_REG_TEMP2_ACT);
16269 +                 if (data->temp_min[2] > data->temp_act[2]) data->temp_min[2] = data->temp_act[2];
16270 +                 if (data->temp_max[2] < data->temp_act[2]) data->temp_max[2] = data->temp_act[2];
16271 +               data->temp_act[3] = fscscy_read_value(client, FSCSCY_REG_TEMP3_ACT);
16272 +                 if (data->temp_min[3] > data->temp_act[3]) data->temp_min[3] = data->temp_act[3];
16273 +                 if (data->temp_max[3] < data->temp_act[3]) data->temp_max[3] = data->temp_act[3];
16274 +               data->temp_status[0] = fscscy_read_value(client, FSCSCY_REG_TEMP0_STATE);
16275 +               data->temp_status[1] = fscscy_read_value(client, FSCSCY_REG_TEMP1_STATE);
16276 +               data->temp_status[2] = fscscy_read_value(client, FSCSCY_REG_TEMP2_STATE);
16277 +               data->temp_status[3] = fscscy_read_value(client, FSCSCY_REG_TEMP3_STATE);
16278 +               data->temp_lim[0] = fscscy_read_value(client, FSCSCY_REG_TEMP0_LIM);
16279 +               data->temp_lim[1] = fscscy_read_value(client, FSCSCY_REG_TEMP1_LIM);
16280 +               data->temp_lim[2] = fscscy_read_value(client, FSCSCY_REG_TEMP2_LIM);
16281 +               data->temp_lim[3] = fscscy_read_value(client, FSCSCY_REG_TEMP3_LIM);
16282 +
16283 +               data->volt[0] = fscscy_read_value(client, FSCSCY_REG_VOLT_12);
16284 +                 if (data->volt_min[0] > data->volt[0]) data->volt_min[0] = data->volt[0];
16285 +                 if (data->volt_max[0] < data->volt[0]) data->volt_max[0] = data->volt[0];
16286 +               data->volt[1] = fscscy_read_value(client, FSCSCY_REG_VOLT_5);
16287 +                 if (data->volt_min[1] > data->volt[1]) data->volt_min[1] = data->volt[1];
16288 +                 if (data->volt_max[1] < data->volt[1]) data->volt_max[1] = data->volt[1];
16289 +               data->volt[2] = fscscy_read_value(client, FSCSCY_REG_VOLT_BATT);
16290 +                 if (data->volt_min[2] > data->volt[2]) data->volt_min[2] = data->volt[2];
16291 +                 if (data->volt_max[2] < data->volt[2]) data->volt_max[2] = data->volt[2];
16292 +
16293 +               data->fan_act[0] = fscscy_read_value(client, FSCSCY_REG_FAN0_ACT);
16294 +                 if (data->fan_min[0] > data->fan_act[0]) data->fan_min[0] = data->fan_act[0];
16295 +                 if (data->fan_max[0] < data->fan_act[0]) data->fan_max[0] = data->fan_act[0];
16296 +               data->fan_act[1] = fscscy_read_value(client, FSCSCY_REG_FAN1_ACT);
16297 +                 if (data->fan_min[1] > data->fan_act[1]) data->fan_min[1] = data->fan_act[1];
16298 +                 if (data->fan_max[1] < data->fan_act[1]) data->fan_max[1] = data->fan_act[1];
16299 +               data->fan_act[2] = fscscy_read_value(client, FSCSCY_REG_FAN2_ACT);
16300 +                 if (data->fan_min[2] > data->fan_act[2]) data->fan_min[2] = data->fan_act[2];
16301 +                 if (data->fan_max[2] < data->fan_act[2]) data->fan_max[2] = data->fan_act[2];
16302 +               data->fan_act[3] = fscscy_read_value(client, FSCSCY_REG_FAN3_ACT);
16303 +                 if (data->fan_min[3] > data->fan_act[3]) data->fan_min[3] = data->fan_act[3];
16304 +                 if (data->fan_max[3] < data->fan_act[3]) data->fan_max[3] = data->fan_act[3];
16305 +               data->fan_act[4] = fscscy_read_value(client, FSCSCY_REG_FAN4_ACT);
16306 +                 if (data->fan_min[4] > data->fan_act[4]) data->fan_min[4] = data->fan_act[4];
16307 +                 if (data->fan_max[4] < data->fan_act[4]) data->fan_max[4] = data->fan_act[4];
16308 +               data->fan_act[5] = fscscy_read_value(client, FSCSCY_REG_FAN5_ACT);
16309 +                 if (data->fan_min[5] > data->fan_act[5]) data->fan_min[5] = data->fan_act[5];
16310 +                 if (data->fan_max[5] < data->fan_act[5]) data->fan_max[5] = data->fan_act[5];
16311 +               data->fan_status[0] = fscscy_read_value(client, FSCSCY_REG_FAN0_STATE);
16312 +               data->fan_status[1] = fscscy_read_value(client, FSCSCY_REG_FAN1_STATE);
16313 +               data->fan_status[2] = fscscy_read_value(client, FSCSCY_REG_FAN2_STATE);
16314 +               data->fan_status[3] = fscscy_read_value(client, FSCSCY_REG_FAN3_STATE);
16315 +               data->fan_status[4] = fscscy_read_value(client, FSCSCY_REG_FAN4_STATE);
16316 +               data->fan_status[5] = fscscy_read_value(client, FSCSCY_REG_FAN5_STATE);
16317 +               data->fan_rpmmin[0] = fscscy_read_value(client, FSCSCY_REG_FAN0_RPMMIN);
16318 +               data->fan_rpmmin[1] = fscscy_read_value(client, FSCSCY_REG_FAN1_RPMMIN);
16319 +               data->fan_rpmmin[2] = fscscy_read_value(client, FSCSCY_REG_FAN2_RPMMIN);
16320 +               data->fan_rpmmin[3] = fscscy_read_value(client, FSCSCY_REG_FAN3_RPMMIN);
16321 +               data->fan_rpmmin[4] = fscscy_read_value(client, FSCSCY_REG_FAN4_RPMMIN);
16322 +               data->fan_rpmmin[5] = fscscy_read_value(client, FSCSCY_REG_FAN5_RPMMIN);
16323 +               data->fan_ripple[0] = fscscy_read_value(client, FSCSCY_REG_FAN0_RIPPLE);
16324 +               data->fan_ripple[1] = fscscy_read_value(client, FSCSCY_REG_FAN1_RIPPLE);
16325 +               data->fan_ripple[2] = fscscy_read_value(client, FSCSCY_REG_FAN2_RIPPLE);
16326 +               data->fan_ripple[3] = fscscy_read_value(client, FSCSCY_REG_FAN3_RIPPLE);
16327 +               data->fan_ripple[4] = fscscy_read_value(client, FSCSCY_REG_FAN4_RIPPLE);
16328 +               data->fan_ripple[5] = fscscy_read_value(client, FSCSCY_REG_FAN5_RIPPLE);
16329 +
16330 +               data->watchdog[0] = fscscy_read_value(client, FSCSCY_REG_WDOG_PRESET);
16331 +               data->watchdog[1] = fscscy_read_value(client, FSCSCY_REG_WDOG_STATE);
16332 +               data->watchdog[2] = fscscy_read_value(client, FSCSCY_REG_WDOG_CONTROL);
16333 +
16334 +               data->global_event = fscscy_read_value(client, FSCSCY_REG_EVENT_STATE);
16335 +               data->global_control = fscscy_read_value(client, FSCSCY_REG_CONTROL);
16336 +               data->pciload = fscscy_read_value(client, FSCSCY_REG_PCILOAD);
16337 +               data->intr_status = fscscy_read_value(client, FSCSCY_REG_INTR_STATE);
16338 +               data->intr_control = fscscy_read_value(client, FSCSCY_REG_INTR_CTRL);
16339 +
16340 +                data->last_updated = jiffies;
16341 +                data->valid = 1;                 
16342 +       }
16343 +
16344 +       up(&data->update_lock);
16345 +}
16346 +
16347 +
16348 +/* The next few functions are the call-back functions of the /proc/sys and
16349 +   sysctl files. Which function is used is defined in the ctl_table in
16350 +   the extra1 field.
16351 +   Each function must return the magnitude (power of 10 to divide the date
16352 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
16353 +   put a maximum of *nrels elements in results reflecting the data of this
16354 +   file, and set *nrels to the number it actually put in it, if operation==
16355 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
16356 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
16357 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
16358 +   large enough (by checking the incoming value of *nrels). This is not very
16359 +   good practice, but as long as you put less than about 5 values in results,
16360 +   you can assume it is large enough. */
16361 +void fscscy_in(struct i2c_client *client, int operation, int ctl_name,
16362 +            int *nrels_mag, long *results)
16363 +{
16364 +       struct fscscy_data *data = client->data;
16365 +
16366 +       if (operation == SENSORS_PROC_REAL_INFO)
16367 +               *nrels_mag = 0;
16368 +       else if (operation == SENSORS_PROC_REAL_READ) {
16369 +               fscscy_update_client(client);
16370 +               switch(ctl_name) {
16371 +                       case FSCSCY_SYSCTL_REV:
16372 +                               results[0] = data->revision ;
16373 +                               break;
16374 +                       case FSCSCY_SYSCTL_EVENT:
16375 +                               results[0] = data->global_event & 0x9f; /* MKN */
16376 +                               break;
16377 +                       case FSCSCY_SYSCTL_CONTROL:
16378 +                               results[0] = data->global_control & 0x19; /* MKN */
16379 +                               break;
16380 +                       default:
16381 +                               printk("fscscy: ctl_name %d not supported\n",
16382 +                                       ctl_name);
16383 +                               *nrels_mag = 0;
16384 +                               return;
16385 +               }
16386 +               *nrels_mag = 1;
16387 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
16388 +               if((ctl_name == FSCSCY_SYSCTL_CONTROL) && (*nrels_mag >= 1)) {
16389 +                       data->global_control = (data->global_control & 0x18) | (results[0] & 0x01); /* MKN */
16390 +                       printk("fscscy: writing 0x%02x to global_control\n",
16391 +                               data->global_control);
16392 +                       fscscy_write_value(client,FSCSCY_REG_CONTROL,
16393 +                               data->global_control);
16394 +               }
16395 +               else
16396 +                       printk("fscscy: writing to chip not supported\n");
16397 +       }
16398 +}
16399 +
16400 +#define TEMP_FROM_REG(val)    (val-128)
16401 +
16402 +
16403 +void fscscy_temp(struct i2c_client *client, int operation, int ctl_name,
16404 +              int *nrels_mag, long *results)
16405 +{
16406 +       struct fscscy_data *data = client->data;
16407 +
16408 +       if (operation == SENSORS_PROC_REAL_INFO)
16409 +               *nrels_mag = 0;
16410 +       else if (operation == SENSORS_PROC_REAL_READ) {
16411 +               fscscy_update_client(client);
16412 +               switch(ctl_name) {
16413 +                       case FSCSCY_SYSCTL_TEMP0:
16414 +                               results[0] = data->temp_status[0] & 0x03;
16415 +                               results[1] = TEMP_FROM_REG(data->temp_act[0]);
16416 +                               results[2] = TEMP_FROM_REG(data->temp_lim[0]);
16417 +                               results[3] = TEMP_FROM_REG(data->temp_min[0]);
16418 +                               results[4] = TEMP_FROM_REG(data->temp_max[0]);
16419 +                               break;
16420 +                       case FSCSCY_SYSCTL_TEMP1:
16421 +                               results[0] = data->temp_status[1] & 0x03;
16422 +                               results[1] = TEMP_FROM_REG(data->temp_act[1]);
16423 +                               results[2] = TEMP_FROM_REG(data->temp_lim[1]);
16424 +                               results[3] = TEMP_FROM_REG(data->temp_min[1]);
16425 +                               results[4] = TEMP_FROM_REG(data->temp_max[1]);
16426 +                               break;
16427 +                       case FSCSCY_SYSCTL_TEMP2:
16428 +                               results[0] = data->temp_status[2] & 0x03;
16429 +                               results[1] = TEMP_FROM_REG(data->temp_act[2]);
16430 +                               results[2] = TEMP_FROM_REG(data->temp_lim[2]);
16431 +                               results[3] = TEMP_FROM_REG(data->temp_min[2]);
16432 +                               results[4] = TEMP_FROM_REG(data->temp_max[2]);
16433 +                               break;
16434 +                       case FSCSCY_SYSCTL_TEMP3:
16435 +                               results[0] = data->temp_status[3] & 0x03;
16436 +                               results[1] = TEMP_FROM_REG(data->temp_act[3]);
16437 +                               results[2] = TEMP_FROM_REG(data->temp_lim[3]);
16438 +                               results[3] = TEMP_FROM_REG(data->temp_min[3]);
16439 +                               results[4] = TEMP_FROM_REG(data->temp_max[3]);
16440 +                               break;
16441 +                       default:
16442 +                               printk("fscscy: ctl_name %d not supported\n",
16443 +                                       ctl_name);
16444 +                               *nrels_mag = 0;
16445 +                               return;
16446 +               }
16447 +               *nrels_mag = 5;
16448 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
16449 +               if(*nrels_mag >= 1) {
16450 +                       switch(ctl_name) {
16451 +                               case FSCSCY_SYSCTL_TEMP0:
16452 +                                       data->temp_status[0] = 
16453 +                                               (data->temp_status[0] & ~0x02) 
16454 +                                               | (results[0] & 0x02);
16455 +                                       printk("fscscy: writing value 0x%02x "
16456 +                                               "to temp0_status\n",
16457 +                                               data->temp_status[0]);
16458 +                                       fscscy_write_value(client,
16459 +                                               FSCSCY_REG_TEMP0_STATE,
16460 +                                               data->temp_status[0] & 0x02);
16461 +                                       break;
16462 +                               case FSCSCY_SYSCTL_TEMP1:
16463 +                                       data->temp_status[1] = (data->temp_status[1] & ~0x02) | (results[0] & 0x02);
16464 +                                       printk("fscscy: writing value 0x%02x to temp1_status\n", data->temp_status[1]);
16465 +                                       fscscy_write_value(client,FSCSCY_REG_TEMP1_STATE,
16466 +                                               data->temp_status[1] & 0x02);
16467 +                                       break;
16468 +                               case FSCSCY_SYSCTL_TEMP2:
16469 +                                       data->temp_status[2] = (data->temp_status[2] & ~0x02) | (results[0] & 0x02);
16470 +                                       printk("fscscy: writing value 0x%02x to temp2_status\n", data->temp_status[2]);
16471 +                                       fscscy_write_value(client,FSCSCY_REG_TEMP2_STATE,
16472 +                                               data->temp_status[2] & 0x02);
16473 +                                       break;
16474 +                               case FSCSCY_SYSCTL_TEMP3:
16475 +                                       data->temp_status[3] = (data->temp_status[3] & ~0x02) | (results[0] & 0x02);
16476 +                                       printk("fscscy: writing value 0x%02x to temp3_status\n", data->temp_status[3]);
16477 +                                       fscscy_write_value(client,FSCSCY_REG_TEMP3_STATE,
16478 +                                               data->temp_status[3] & 0x02);
16479 +                                       break;
16480 +                               default:
16481 +                                       printk("fscscy: ctl_name %d not supported\n",ctl_name);
16482 +                       }
16483 +               }
16484 +               else
16485 +                       printk("fscscy: writing to chip not supported\n");
16486 +       }
16487 +}
16488 +
16489 +#define VOLT_FROM_REG(val,mult)    (val*mult/255)
16490 +
16491 +void fscscy_volt(struct i2c_client *client, int operation, int ctl_name,
16492 +              int *nrels_mag, long *results)
16493 +{
16494 +       struct fscscy_data *data = client->data;
16495 +       if (operation == SENSORS_PROC_REAL_INFO)
16496 +               *nrels_mag = 2;
16497 +       else if (operation == SENSORS_PROC_REAL_READ) {
16498 +               fscscy_update_client(client);
16499 +               switch(ctl_name) {
16500 +                       case FSCSCY_SYSCTL_VOLT0:
16501 +                               results[0] = VOLT_FROM_REG(data->volt[0],1420);
16502 +                               results[1] = VOLT_FROM_REG(data->volt_min[0],1420);
16503 +                               results[2] = VOLT_FROM_REG(data->volt_max[0],1420);
16504 +                               break;
16505 +                       case FSCSCY_SYSCTL_VOLT1:
16506 +                               results[0] = VOLT_FROM_REG(data->volt[1],660);
16507 +                               results[1] = VOLT_FROM_REG(data->volt_min[1],660);
16508 +                               results[2] = VOLT_FROM_REG(data->volt_max[1],660);
16509 +                               break;
16510 +                       case FSCSCY_SYSCTL_VOLT2:
16511 +                               results[0] = VOLT_FROM_REG(data->volt[2],330);
16512 +                               results[1] = VOLT_FROM_REG(data->volt_min[2],330);
16513 +                               results[2] = VOLT_FROM_REG(data->volt_max[2],330);
16514 +                               break;
16515 +                       default:
16516 +                               printk("fscscy: ctl_name %d not supported\n",
16517 +                                       ctl_name);
16518 +                               *nrels_mag = 0;
16519 +                               return;
16520 +               }
16521 +               *nrels_mag = 3;
16522 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
16523 +                       printk("fscscy: writing to chip not supported\n");
16524 +       }
16525 +}
16526 +
16527 +void fscscy_fan(struct i2c_client *client, int operation, int ctl_name,
16528 +              int *nrels_mag, long *results)
16529 +{
16530 +
16531 +       switch(ctl_name) {
16532 +               case FSCSCY_SYSCTL_FAN0:
16533 +                       fscscy_fan_internal(client,operation,ctl_name,nrels_mag,results,
16534 +                               0,FSCSCY_REG_FAN0_STATE,FSCSCY_REG_FAN0_RPMMIN,
16535 +                               FSCSCY_REG_FAN0_RIPPLE);
16536 +                       break;
16537 +               case FSCSCY_SYSCTL_FAN1:
16538 +                       fscscy_fan_internal(client,operation,ctl_name,nrels_mag,results,
16539 +                               1,FSCSCY_REG_FAN1_STATE,FSCSCY_REG_FAN1_RPMMIN,
16540 +                               FSCSCY_REG_FAN1_RIPPLE);
16541 +                       break;
16542 +               case FSCSCY_SYSCTL_FAN2:
16543 +                       fscscy_fan_internal(client,operation,ctl_name,nrels_mag,results,
16544 +                               2,FSCSCY_REG_FAN2_STATE,FSCSCY_REG_FAN2_RPMMIN,
16545 +                               FSCSCY_REG_FAN2_RIPPLE);
16546 +                       break;
16547 +               case FSCSCY_SYSCTL_FAN3:
16548 +                       fscscy_fan_internal(client,operation,ctl_name,nrels_mag,results,
16549 +                               3,FSCSCY_REG_FAN3_STATE,FSCSCY_REG_FAN3_RPMMIN,
16550 +                               FSCSCY_REG_FAN3_RIPPLE);
16551 +                       break;
16552 +               case FSCSCY_SYSCTL_FAN4:
16553 +                       fscscy_fan_internal(client,operation,ctl_name,nrels_mag,results,
16554 +                               4,FSCSCY_REG_FAN4_STATE,FSCSCY_REG_FAN4_RPMMIN,
16555 +                               FSCSCY_REG_FAN4_RIPPLE);
16556 +                       break;
16557 +               case FSCSCY_SYSCTL_FAN5:
16558 +                       fscscy_fan_internal(client,operation,ctl_name,nrels_mag,results,
16559 +                               5,FSCSCY_REG_FAN5_STATE,FSCSCY_REG_FAN5_RPMMIN,
16560 +                               FSCSCY_REG_FAN5_RIPPLE);
16561 +                       break;
16562 +               default:
16563 +                       printk("fscscy: illegal fan nr %d\n",ctl_name);
16564 +       }
16565 +}
16566 +                       
16567 +#define RPM_FROM_REG(val)   (val*60)
16568 +
16569 +void fscscy_fan_internal(struct i2c_client *client, int operation, int ctl_name,
16570 +              int *nrels_mag, long *results, int nr,
16571 +              int reg_state, int reg_min, int reg_ripple )
16572 +{
16573 +       struct fscscy_data *data = client->data;
16574 +
16575 +       if (operation == SENSORS_PROC_REAL_INFO)
16576 +               *nrels_mag = 0;
16577 +       else if (operation == SENSORS_PROC_REAL_READ) {
16578 +               fscscy_update_client(client);
16579 +               results[0] = data->fan_status[nr] & 0x0f; /* MKN */
16580 +               results[1] = data->fan_rpmmin[nr];
16581 +               results[2] = data->fan_ripple[nr] & 0x03;
16582 +               results[3] = RPM_FROM_REG(data->fan_act[nr]);
16583 +               results[4] = RPM_FROM_REG(data->fan_min[nr]);
16584 +               results[5] = RPM_FROM_REG(data->fan_max[nr]);
16585 +               *nrels_mag = 6;
16586 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
16587 +               if(*nrels_mag >= 1) {
16588 +                       data->fan_status[nr] = (data->fan_status[nr] & 0x0b) | (results[0] & 0x04); /* MKN */
16589 +                       printk("fscscy: writing value 0x%02x to fan%d_status\n",
16590 +                               data->fan_status[nr],nr);
16591 +                       fscscy_write_value(client,reg_state,
16592 +                               data->fan_status[nr]);
16593 +               }
16594 +               if(*nrels_mag >= 2)  {
16595 +                       if((results[1] & 0xff) == 0) {
16596 +                                printk("fscscy: fan%d rpmmin 0 not allowed for safety reasons\n",nr);
16597 +                                return;
16598 +                       }
16599 +                       data->fan_rpmmin[nr] = results[1];
16600 +                       printk("fscscy: writing value 0x%02x to fan%d_min\n",
16601 +                               data->fan_rpmmin[nr],nr);
16602 +                       fscscy_write_value(client,reg_min,
16603 +                               data->fan_rpmmin[nr]);
16604 +               }
16605 +               if(*nrels_mag >= 3) {
16606 +                       if((results[2] & 0x03) == 0) {
16607 +                               printk("fscscy: fan%d ripple 0 is nonsense/not allowed\n",nr);
16608 +                               return;
16609 +                       }
16610 +                       data->fan_ripple[nr] = results[2] & 0x03;
16611 +                       printk("fscscy: writing value 0x%02x to fan%d_ripple\n",
16612 +                               data->fan_ripple[nr],nr);
16613 +                       fscscy_write_value(client,reg_ripple,
16614 +                               data->fan_ripple[nr]);
16615 +               }       
16616 +       }
16617 +}
16618 +
16619 +void fscscy_wdog(struct i2c_client *client, int operation, int ctl_name,
16620 +            int *nrels_mag, long *results)
16621 +{
16622 +       struct fscscy_data *data = client->data;
16623 +
16624 +       if (operation == SENSORS_PROC_REAL_INFO)
16625 +               *nrels_mag = 0;
16626 +       else if (operation == SENSORS_PROC_REAL_READ) {
16627 +               fscscy_update_client(client);
16628 +               results[0] = data->watchdog[0] ;
16629 +               results[1] = data->watchdog[1] & 0x02;
16630 +               results[2] = data->watchdog[2] & 0xb0;
16631 +               *nrels_mag = 3;
16632 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
16633 +               if (*nrels_mag >= 1) {
16634 +                       data->watchdog[0] = results[0] & 0xff;
16635 +                       printk("fscscy: writing value 0x%02x to wdog_preset\n",
16636 +                               data->watchdog[0]); 
16637 +                       fscscy_write_value(client,FSCSCY_REG_WDOG_PRESET,
16638 +                               data->watchdog[0]);
16639 +               } 
16640 +               if (*nrels_mag >= 2) {
16641 +                       data->watchdog[1] = results[1] & 0x02;
16642 +                       printk("fscscy: writing value 0x%02x to wdog_state\n",
16643 +                               data->watchdog[1]); 
16644 +                       fscscy_write_value(client,FSCSCY_REG_WDOG_STATE,
16645 +                               data->watchdog[1]);
16646 +               }
16647 +               if (*nrels_mag >= 3) {
16648 +                       data->watchdog[2] = results[2] & 0xb0;
16649 +                       printk("fscscy: writing value 0x%02x to wdog_control\n",
16650 +                               data->watchdog[2]); 
16651 +                       fscscy_write_value(client,FSCSCY_REG_WDOG_CONTROL,
16652 +                               data->watchdog[2]);
16653 +               }
16654 +       }
16655 +}
16656 +
16657 +void fscscy_pciload(struct i2c_client *client, int operation, int ctl_name,
16658 +              int *nrels_mag, long *results)
16659 +{
16660 +       struct fscscy_data *data = client->data;
16661 +       if (operation == SENSORS_PROC_REAL_INFO)
16662 +               *nrels_mag = 0;
16663 +       else if (operation == SENSORS_PROC_REAL_READ) {
16664 +               fscscy_update_client(client);
16665 +               results[0] = data->pciload;
16666 +               *nrels_mag = 1;
16667 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
16668 +                       printk("fscscy: writing PCILOAD to chip not supported\n");
16669 +       }
16670 +}
16671 +
16672 +void fscscy_intrusion(struct i2c_client *client, int operation, int ctl_name,
16673 +            int *nrels_mag, long *results)
16674 +{
16675 +       struct fscscy_data *data = client->data;
16676 +
16677 +       if (operation == SENSORS_PROC_REAL_INFO)
16678 +               *nrels_mag = 0;
16679 +       else if (operation == SENSORS_PROC_REAL_READ) {
16680 +               fscscy_update_client(client);
16681 +               results[0] = data->intr_control & 0x80;
16682 +               results[1] = data->intr_status & 0xc0;
16683 +               *nrels_mag = 2;
16684 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
16685 +               if (*nrels_mag >= 1) {
16686 +                       data->intr_control = results[0] & 0x80;
16687 +                       printk("fscscy: writing value 0x%02x to intr_control\n",
16688 +                               data->intr_control); 
16689 +                       fscscy_write_value(client,FSCSCY_REG_INTR_CTRL,
16690 +                               data->intr_control);
16691 +               } 
16692 +       }
16693 +}
16694 +
16695 +static int __init sm_fscscy_init(void)
16696 +{
16697 +       printk("fscscy.o version %s (%s)\n", LM_VERSION, LM_DATE);
16698 +       return i2c_add_driver(&fscscy_driver);
16699 +}
16700 +
16701 +static void __exit sm_fscscy_exit(void)
16702 +{
16703 +       i2c_del_driver(&fscscy_driver);
16704 +}
16705 +
16706 +
16707 +
16708 +MODULE_AUTHOR
16709 +    ("Martin Knoblauch <mkn@teraport.de> based on work (fscpos) from  Hermann Jung <hej@odn.de>");
16710 +MODULE_DESCRIPTION("fujitsu siemens scylla chip driver");
16711 +
16712 +module_init(sm_fscscy_init);
16713 +module_exit(sm_fscscy_exit);
16714 --- linux-old/drivers/sensors/gl518sm.c Thu Jan  1 00:00:00 1970
16715 +++ linux/drivers/sensors/gl518sm.c     Mon Dec 13 20:18:46 2004
16716 @@ -0,0 +1,989 @@
16717 +/*
16718 +    gl518sm.c - Part of lm_sensors, Linux kernel modules for hardware
16719 +                monitoring
16720 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
16721 +                              Kyösti Mälkki <kmalkki@cc.hut.fi>
16722 +
16723 +    This program is free software; you can redistribute it and/or modify
16724 +    it under the terms of the GNU General Public License as published by
16725 +    the Free Software Foundation; either version 2 of the License, or
16726 +    (at your option) any later version.
16727 +
16728 +    This program is distributed in the hope that it will be useful,
16729 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
16730 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16731 +    GNU General Public License for more details.
16732 +
16733 +    You should have received a copy of the GNU General Public License
16734 +    along with this program; if not, write to the Free Software
16735 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16736 +
16737 +*/
16738 +
16739 +#include <linux/module.h>
16740 +#include <linux/slab.h>
16741 +#include <linux/i2c.h>
16742 +#include <linux/i2c-proc.h>
16743 +#include <linux/init.h>
16744 +#ifdef __SMP__
16745 +#include <linux/smp_lock.h>
16746 +#endif
16747 +#define LM_DATE "20041007"
16748 +#define LM_VERSION "2.8.8"
16749 +
16750 +MODULE_LICENSE("GPL");
16751 +
16752 +/* Addresses to scan */
16753 +static unsigned short normal_i2c[] = { 0x2c, 0x2d, SENSORS_I2C_END };
16754 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
16755 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
16756 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
16757 +
16758 +/* Insmod parameters */
16759 +SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80);
16760 +
16761 +/* Defining this will enable debug messages for the voltage iteration
16762 +   code used with rev 0 ICs */
16763 +#undef DEBUG_VIN
16764 +
16765 +/* Many GL518 constants specified below */
16766 +
16767 +/* The GL518 registers */
16768 +#define GL518_REG_CHIP_ID 0x00
16769 +#define GL518_REG_REVISION 0x01
16770 +#define GL518_REG_VENDOR_ID 0x02
16771 +#define GL518_REG_CONF 0x03
16772 +#define GL518_REG_TEMP 0x04
16773 +#define GL518_REG_TEMP_OVER 0x05
16774 +#define GL518_REG_TEMP_HYST 0x06
16775 +#define GL518_REG_FAN_COUNT 0x07
16776 +#define GL518_REG_FAN_LIMIT 0x08
16777 +#define GL518_REG_VIN1_LIMIT 0x09
16778 +#define GL518_REG_VIN2_LIMIT 0x0a
16779 +#define GL518_REG_VIN3_LIMIT 0x0b
16780 +#define GL518_REG_VDD_LIMIT 0x0c
16781 +#define GL518_REG_VIN3 0x0d
16782 +#define GL518_REG_MISC 0x0f
16783 +#define GL518_REG_ALARM 0x10
16784 +#define GL518_REG_MASK 0x11
16785 +#define GL518_REG_INT 0x12
16786 +#define GL518_REG_VIN2 0x13
16787 +#define GL518_REG_VIN1 0x14
16788 +#define GL518_REG_VDD 0x15
16789 +
16790 +
16791 +/* Conversions. Rounding and limit checking is only done on the TO_REG
16792 +   variants. Note that you should be a bit careful with which arguments
16793 +   these macros are called: arguments may be evaluated more than once.
16794 +   Fixing this is just not worth it. */
16795 +
16796 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-5:(val)+5) / 10)+119),\
16797 +                                        0,255))
16798 +#define TEMP_FROM_REG(val) (((val) - 119) * 10)
16799 +
16800 +static inline u8 FAN_TO_REG(long rpm, int div)
16801 +{
16802 +       if (rpm == 0)
16803 +               return 255;
16804 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
16805 +       return SENSORS_LIMIT((960000 + rpm * div / 2) / (rpm * div), 1,
16806 +                            254);
16807 +}
16808 +
16809 +#define FAN_FROM_REG(val,div) \
16810 + ( (val)==0 ? 0 : (val)==255 ? 0 : (960000/((val)*(div))) )
16811 +
16812 +#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*10+8)/19),0,255))
16813 +#define IN_FROM_REG(val) (((val)*19)/10)
16814 +
16815 +#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*10+11)/23),0,255))
16816 +#define VDD_FROM_REG(val) (((val)*23)/10)
16817 +
16818 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
16819 +#define DIV_FROM_REG(val) (1 << (val))
16820 +
16821 +#define ALARMS_FROM_REG(val) val
16822 +
16823 +#define BEEP_ENABLE_TO_REG(val) ((val)?0:1)
16824 +#define BEEP_ENABLE_FROM_REG(val) ((val)?0:1)
16825 +
16826 +#define BEEPS_TO_REG(val) ((val) & 0x7f)
16827 +#define BEEPS_FROM_REG(val) ((val) & 0x7f)
16828 +
16829 +/* Each client has this additional data */
16830 +struct gl518_data {
16831 +       struct i2c_client client;
16832 +       int sysctl_id;
16833 +       enum chips type;
16834 +
16835 +       struct semaphore update_lock;
16836 +
16837 +       int iterate_lock;
16838 +       int quit_thread;
16839 +       struct task_struct *thread;
16840 +       wait_queue_head_t wq;
16841 +       char valid;             /* !=0 if following fields are valid */
16842 +       unsigned long last_updated;     /* In jiffies */
16843 +       unsigned long last_updated_v00;
16844 +       /* In jiffies (used only by rev00 chips) */
16845 +
16846 +       u8 voltage[4];          /* Register values; [0] = VDD */
16847 +       u8 voltage_min[4];      /* Register values; [0] = VDD */
16848 +       u8 voltage_max[4];      /* Register values; [0] = VDD */
16849 +       u8 iter_voltage[4];     /* Register values; [0] = VDD */
16850 +       u8 fan[2];
16851 +       u8 fan_min[2];
16852 +       u8 temp;                /* Register values */
16853 +       u8 temp_over;           /* Register values */
16854 +       u8 temp_hyst;           /* Register values */
16855 +       u8 alarms, beeps;       /* Register value */
16856 +       u8 alarm_mask;          /* Register value */
16857 +       u8 fan_div[2];          /* Register encoding, shifted right */
16858 +       u8 beep_enable;         /* Boolean */
16859 +       u8 iterate;             /* Voltage iteration mode */
16860 +};
16861 +
16862 +static int gl518_attach_adapter(struct i2c_adapter *adapter);
16863 +static int gl518_detect(struct i2c_adapter *adapter, int address,
16864 +                       unsigned short flags, int kind);
16865 +static void gl518_init_client(struct i2c_client *client);
16866 +static int gl518_detach_client(struct i2c_client *client);
16867 +
16868 +static int gl518_read_value(struct i2c_client *client, u8 reg);
16869 +static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value);
16870 +static void gl518_update_client(struct i2c_client *client);
16871 +
16872 +static void gl518_update_client_rev00(struct i2c_client *client);
16873 +static void gl518_update_iterate(struct i2c_client *client);
16874 +
16875 +static void gl518_vin(struct i2c_client *client, int operation,
16876 +                     int ctl_name, int *nrels_mag, long *results);
16877 +static void gl518_fan(struct i2c_client *client, int operation,
16878 +                     int ctl_name, int *nrels_mag, long *results);
16879 +static void gl518_temp(struct i2c_client *client, int operation,
16880 +                      int ctl_name, int *nrels_mag, long *results);
16881 +static void gl518_fan_div(struct i2c_client *client, int operation,
16882 +                         int ctl_name, int *nrels_mag, long *results);
16883 +static void gl518_alarms(struct i2c_client *client, int operation,
16884 +                        int ctl_name, int *nrels_mag, long *results);
16885 +static void gl518_beep(struct i2c_client *client, int operation,
16886 +                      int ctl_name, int *nrels_mag, long *results);
16887 +static void gl518_fan1off(struct i2c_client *client, int operation,
16888 +                         int ctl_name, int *nrels_mag, long *results);
16889 +static void gl518_iterate(struct i2c_client *client, int operation,
16890 +                         int ctl_name, int *nrels_mag, long *results);
16891 +
16892 +/* This is the driver that will be inserted */
16893 +static struct i2c_driver gl518_driver = {
16894 +       .owner          = THIS_MODULE,
16895 +       .name           = "GL518SM sensor chip driver",
16896 +       .id             = I2C_DRIVERID_GL518,
16897 +       .flags          = I2C_DF_NOTIFY,
16898 +       .attach_adapter = gl518_attach_adapter,
16899 +       .detach_client  = gl518_detach_client,
16900 +};
16901 +
16902 +/* -- SENSORS SYSCTL START -- */
16903 +
16904 +#define GL518_SYSCTL_VDD  1000 /* Volts * 100 */
16905 +#define GL518_SYSCTL_VIN1 1001
16906 +#define GL518_SYSCTL_VIN2 1002
16907 +#define GL518_SYSCTL_VIN3 1003
16908 +#define GL518_SYSCTL_FAN1 1101 /* RPM */
16909 +#define GL518_SYSCTL_FAN2 1102
16910 +#define GL518_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
16911 +#define GL518_SYSCTL_FAN_DIV 2000      /* 1, 2, 4 or 8 */
16912 +#define GL518_SYSCTL_ALARMS 2001       /* bitvector */
16913 +#define GL518_SYSCTL_BEEP 2002 /* bitvector */
16914 +#define GL518_SYSCTL_FAN1OFF 2003
16915 +#define GL518_SYSCTL_ITERATE 2004
16916 +
16917 +#define GL518_ALARM_VDD 0x01
16918 +#define GL518_ALARM_VIN1 0x02
16919 +#define GL518_ALARM_VIN2 0x04
16920 +#define GL518_ALARM_VIN3 0x08
16921 +#define GL518_ALARM_TEMP 0x10
16922 +#define GL518_ALARM_FAN1 0x20
16923 +#define GL518_ALARM_FAN2 0x40
16924 +
16925 +/* -- SENSORS SYSCTL END -- */
16926 +
16927 +/* These files are created for each detected GL518. This is just a template;
16928 +   though at first sight, you might think we could use a statically
16929 +   allocated list, we need some way to get back to the parent - which
16930 +   is done through one of the 'extra' fields which are initialized
16931 +   when a new copy is allocated. */
16932 +static ctl_table gl518_dir_table_template[] = {
16933 +       {GL518_SYSCTL_VIN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
16934 +        &i2c_sysctl_real, NULL, &gl518_vin},
16935 +       {GL518_SYSCTL_VIN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
16936 +        &i2c_sysctl_real, NULL, &gl518_vin},
16937 +       {GL518_SYSCTL_VIN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
16938 +        &i2c_sysctl_real, NULL, &gl518_vin},
16939 +       {GL518_SYSCTL_VDD, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
16940 +        &i2c_sysctl_real, NULL, &gl518_vin},
16941 +       {GL518_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
16942 +        &i2c_sysctl_real, NULL, &gl518_fan},
16943 +       {GL518_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
16944 +        &i2c_sysctl_real, NULL, &gl518_fan},
16945 +       {GL518_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
16946 +        &i2c_sysctl_real, NULL, &gl518_temp},
16947 +       {GL518_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
16948 +        &i2c_sysctl_real, NULL, &gl518_fan_div},
16949 +       {GL518_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
16950 +        &i2c_sysctl_real, NULL, &gl518_alarms},
16951 +       {GL518_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
16952 +        &i2c_sysctl_real, NULL, &gl518_beep},
16953 +       {GL518_SYSCTL_FAN1OFF, "fan1off", NULL, 0, 0644, NULL, &i2c_proc_real,
16954 +        &i2c_sysctl_real, NULL, &gl518_fan1off},
16955 +       {GL518_SYSCTL_ITERATE, "iterate", NULL, 0, 0644, NULL, &i2c_proc_real,
16956 +        &i2c_sysctl_real, NULL, &gl518_iterate},
16957 +       {0}
16958 +};
16959 +
16960 +/* I choose here for semi-static GL518SM allocation. Complete dynamic
16961 +   allocation could also be used; the code needed for this would probably
16962 +   take more memory than the datastructure takes now. */
16963 +#define MAX_GL518_NR 4
16964 +static struct i2c_client *gl518_list[MAX_GL518_NR];
16965 +
16966 +static int gl518_attach_adapter(struct i2c_adapter *adapter)
16967 +{
16968 +       return i2c_detect(adapter, &addr_data, gl518_detect);
16969 +}
16970 +
16971 +static int gl518_detect(struct i2c_adapter *adapter, int address,
16972 +                       unsigned short flags, int kind)
16973 +{
16974 +       int i;
16975 +       struct i2c_client *new_client;
16976 +       struct gl518_data *data;
16977 +       int err = 0;
16978 +       const char *type_name = "";
16979 +       const char *client_name = "";
16980 +
16981 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
16982 +          at this moment; i2c_detect really won't call us. */
16983 +#ifdef DEBUG
16984 +       if (i2c_is_isa_adapter(adapter)) {
16985 +               printk
16986 +                   ("gl518sm.o: gl518_detect called for an ISA bus adapter?!?\n");
16987 +               return 0;
16988 +       }
16989 +#endif
16990 +
16991 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
16992 +                                    I2C_FUNC_SMBUS_WORD_DATA))
16993 +                   goto ERROR0;
16994 +
16995 +       /* OK. For now, we presume we have a valid client. We now create the
16996 +          client structure, even though we cannot fill it completely yet.
16997 +          But it allows us to access gl518_{read,write}_value. */
16998 +
16999 +       if (!(data = kmalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
17000 +               err = -ENOMEM;
17001 +               goto ERROR0;
17002 +       }
17003 +
17004 +       new_client = &data->client;
17005 +       new_client->addr = address;
17006 +       new_client->data = data;
17007 +       new_client->adapter = adapter;
17008 +       new_client->driver = &gl518_driver;
17009 +       new_client->flags = 0;
17010 +
17011 +       /* Now, we do the remaining detection. */
17012 +
17013 +       if (kind < 0) {
17014 +               if (
17015 +                   (gl518_read_value(new_client, GL518_REG_CHIP_ID) !=
17016 +                    0x80)
17017 +                   || (gl518_read_value(new_client, GL518_REG_CONF) &
17018 +                       0x80)) goto ERROR1;
17019 +       }
17020 +
17021 +       /* Determine the chip type. */
17022 +       if (kind <= 0) {
17023 +               i = gl518_read_value(new_client, GL518_REG_REVISION);
17024 +               if (i == 0x00)
17025 +                       kind = gl518sm_r00;
17026 +               else if (i == 0x80)
17027 +                       kind = gl518sm_r80;
17028 +               else {
17029 +                       if (kind == 0)
17030 +                               printk
17031 +                                   ("gl518sm.o: Ignoring 'force' parameter for unknown chip at "
17032 +                                    "adapter %d, address 0x%02x\n",
17033 +                                    i2c_adapter_id(adapter), address);
17034 +                       goto ERROR1;
17035 +               }
17036 +       }
17037 +
17038 +       type_name = "gl518sm";
17039 +       if (kind == gl518sm_r00) {
17040 +               client_name = "GL518SM Revision 0x00 chip";
17041 +       } else if (kind == gl518sm_r80) {
17042 +               client_name = "GL518SM Revision 0x80 chip";
17043 +       } else {
17044 +#ifdef DEBUG
17045 +               printk("gl518sm.o: Internal error: unknown kind (%d)?!?",
17046 +                      kind);
17047 +#endif
17048 +               goto ERROR1;
17049 +       }
17050 +
17051 +       /* Fill in the remaining client fields and put it into the global list */
17052 +       strcpy(new_client->name, client_name);
17053 +       data->type = kind;
17054 +
17055 +       for (i = 0; i < MAX_GL518_NR; i++)
17056 +               if (!gl518_list[i])
17057 +                       break;
17058 +       if (i == MAX_GL518_NR) {
17059 +               printk
17060 +                   ("gl518sm.o: No empty slots left, recompile and heighten "
17061 +                    "MAX_GL518_NR!\n");
17062 +               err = -ENOMEM;
17063 +               goto ERROR2;
17064 +       }
17065 +       gl518_list[i] = new_client;
17066 +       new_client->id = i;
17067 +       data->valid = 0;
17068 +       init_MUTEX(&data->update_lock);
17069 +
17070 +       /* Tell the I2C layer a new client has arrived */
17071 +       if ((err = i2c_attach_client(new_client)))
17072 +               goto ERROR3;
17073 +
17074 +       /* Register a new directory entry with module sensors */
17075 +       if ((i = i2c_register_entry((struct i2c_client *) new_client,
17076 +                                       type_name,
17077 +                                       gl518_dir_table_template)) < 0) {
17078 +               err = i;
17079 +               goto ERROR4;
17080 +       }
17081 +       data->sysctl_id = i;
17082 +
17083 +       /* Initialize the GL518SM chip */
17084 +       if (kind == gl518sm_r00)
17085 +               data->iterate = 0;
17086 +       else
17087 +               data->iterate = 3;
17088 +       data->iterate_lock = 0;
17089 +       data->quit_thread = 0;
17090 +       data->thread = NULL;
17091 +       data->alarm_mask = 0xff;
17092 +       data->voltage[0]=data->voltage[1]=data->voltage[2]=0;
17093 +       gl518_init_client((struct i2c_client *) new_client);
17094 +       return 0;
17095 +
17096 +/* OK, this is not exactly good programming practice, usually. But it is
17097 +   very code-efficient in this case. */
17098 +
17099 +      ERROR4:
17100 +       i2c_detach_client(new_client);
17101 +      ERROR3:
17102 +       for (i = 0; i < MAX_GL518_NR; i++)
17103 +               if (new_client == gl518_list[i])
17104 +                       gl518_list[i] = NULL;
17105 +      ERROR2:
17106 +      ERROR1:
17107 +       kfree(data);
17108 +      ERROR0:
17109 +       return err;
17110 +}
17111 +
17112 +
17113 +/* Called when we have found a new GL518SM. It should set limits, etc. */
17114 +static void gl518_init_client(struct i2c_client *client)
17115 +{
17116 +       /* Power-on defaults (bit 7=1) */
17117 +       gl518_write_value(client, GL518_REG_CONF, 0x80);
17118 +
17119 +       /* No noisy output (bit 2=1), Comparator mode (bit 3=0), two fans (bit4=0),
17120 +          standby mode (bit6=0) */
17121 +       gl518_write_value(client, GL518_REG_CONF, 0x04);
17122 +
17123 +       /* Never interrupts */
17124 +       gl518_write_value(client, GL518_REG_MASK, 0x00);
17125 +
17126 +       /* Clear status register (bit 5=1), start (bit6=1) */
17127 +       gl518_write_value(client, GL518_REG_CONF, 0x24);
17128 +       gl518_write_value(client, GL518_REG_CONF, 0x44);
17129 +}
17130 +
17131 +static int gl518_detach_client(struct i2c_client *client)
17132 +{
17133 +       int err, i;
17134 +       struct gl518_data *data = client->data;
17135 +
17136 +       i2c_deregister_entry(((struct gl518_data *) (client->data))->
17137 +                                sysctl_id);
17138 +
17139 +       if ((err = i2c_detach_client(client))) {
17140 +               printk
17141 +                   ("gl518sm.o: Client deregistration failed, client not detached.\n");
17142 +               return err;
17143 +       }
17144 +
17145 +       for (i = 0; i < MAX_GL518_NR; i++)
17146 +               if (client == gl518_list[i])
17147 +                       break;
17148 +       if ((i == MAX_GL518_NR)) {
17149 +               printk("gl518sm.o: Client to detach not found.\n");
17150 +               return -ENOENT;
17151 +       }
17152 +       gl518_list[i] = NULL;
17153 +
17154 +       if (data->thread) {
17155 +               data->quit_thread = 1;
17156 +               wake_up_interruptible(&data->wq);
17157 +       }
17158 +
17159 +       kfree(client->data);
17160 +
17161 +       return 0;
17162 +}
17163 +
17164 +
17165 +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
17166 +   GL518 uses a high-byte first convention, which is exactly opposite to
17167 +   the usual practice. */
17168 +static int gl518_read_value(struct i2c_client *client, u8 reg)
17169 +{
17170 +       if ((reg >= 0x07) && (reg <= 0x0c))
17171 +               return swab16(i2c_smbus_read_word_data(client, reg));
17172 +       else
17173 +               return i2c_smbus_read_byte_data(client, reg);
17174 +}
17175 +
17176 +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
17177 +   GL518 uses a high-byte first convention, which is exactly opposite to
17178 +   the usual practice. */
17179 +static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
17180 +{
17181 +       if ((reg >= 0x07) && (reg <= 0x0c))
17182 +               return i2c_smbus_write_word_data(client, reg, swab16(value));
17183 +       else
17184 +               return i2c_smbus_write_byte_data(client, reg, value);
17185 +}
17186 +
17187 +static void gl518_update_client(struct i2c_client *client)
17188 +{
17189 +       struct gl518_data *data = client->data;
17190 +       int val;
17191 +
17192 +       down(&data->update_lock);
17193 +
17194 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
17195 +           (jiffies < data->last_updated) || !data->valid) {
17196 +
17197 +#ifdef DEBUG
17198 +               printk("Starting gl518 update\n");
17199 +#endif
17200 +
17201 +               data->alarms = gl518_read_value(client, GL518_REG_INT);
17202 +               data->beeps = gl518_read_value(client, GL518_REG_ALARM);
17203 +
17204 +               val = gl518_read_value(client, GL518_REG_VDD_LIMIT);
17205 +               data->voltage_min[0] = val & 0xff;
17206 +               data->voltage_max[0] = (val >> 8) & 0xff;
17207 +               val = gl518_read_value(client, GL518_REG_VIN1_LIMIT);
17208 +               data->voltage_min[1] = val & 0xff;
17209 +               data->voltage_max[1] = (val >> 8) & 0xff;
17210 +               val = gl518_read_value(client, GL518_REG_VIN2_LIMIT);
17211 +               data->voltage_min[2] = val & 0xff;
17212 +               data->voltage_max[2] = (val >> 8) & 0xff;
17213 +               val = gl518_read_value(client, GL518_REG_VIN3_LIMIT);
17214 +               data->voltage_min[3] = val & 0xff;
17215 +               data->voltage_max[3] = (val >> 8) & 0xff;
17216 +
17217 +               val = gl518_read_value(client, GL518_REG_FAN_COUNT);
17218 +               data->fan[0] = (val >> 8) & 0xff;
17219 +               data->fan[1] = val & 0xff;
17220 +
17221 +               val = gl518_read_value(client, GL518_REG_FAN_LIMIT);
17222 +               data->fan_min[0] = (val >> 8) & 0xff;
17223 +               data->fan_min[1] = val & 0xff;
17224 +
17225 +               data->temp = gl518_read_value(client, GL518_REG_TEMP);
17226 +               data->temp_over =
17227 +                   gl518_read_value(client, GL518_REG_TEMP_OVER);
17228 +               data->temp_hyst =
17229 +                   gl518_read_value(client, GL518_REG_TEMP_HYST);
17230 +
17231 +               val = gl518_read_value(client, GL518_REG_MISC);
17232 +               data->fan_div[0] = (val >> 6) & 0x03;
17233 +               data->fan_div[1] = (val >> 4) & 0x03;
17234 +
17235 +               data->alarms &= data->alarm_mask;
17236 +
17237 +               val = gl518_read_value(client, GL518_REG_CONF);
17238 +               data->beep_enable = (val >> 2) & 1;
17239 +
17240 +#ifndef DEBUG_VIN
17241 +               if (data->type != gl518sm_r00) {
17242 +                       data->voltage[0] =
17243 +                           gl518_read_value(client, GL518_REG_VDD);
17244 +                       data->voltage[1] =
17245 +                           gl518_read_value(client, GL518_REG_VIN1);
17246 +                       data->voltage[2] =
17247 +                           gl518_read_value(client, GL518_REG_VIN2);
17248 +                       data->voltage[3] =
17249 +                           gl518_read_value(client, GL518_REG_VIN3);
17250 +               } else
17251 +                       gl518_update_client_rev00(client);
17252 +#else
17253 +               gl518_update_client_rev00(client);
17254 +#endif
17255 +
17256 +               data->last_updated = jiffies;
17257 +               data->valid = 1;
17258 +       }
17259 +
17260 +       up(&data->update_lock);
17261 +}
17262 +
17263 +/* Here we decide how to run the iteration code.
17264 +   When called, we trigger the iteration and report the last
17265 +   measured voltage. No delay for user apps */
17266 +static void gl518_update_client_rev00(struct i2c_client *client)
17267 +{
17268 +       struct gl518_data *data = client->data;
17269 +       int i;
17270 +
17271 +       if (data->iterate == 1) {       /* 10 sec delay */
17272 +               /* as that update is slow, we consider the data valid for 30 seconds */
17273 +               if (
17274 +                   ((jiffies - data->last_updated_v00 > 30 * HZ)
17275 +                    || (data->alarms & 7)
17276 +                    || (!data->valid)) && (!data->iterate_lock)) {
17277 +                       data->iterate_lock = 1;
17278 +                       gl518_update_iterate(client);
17279 +                       data->iterate_lock = 0;
17280 +               }
17281 +               for (i = 0; i < 4; i++)
17282 +                       data->voltage[i] = data->iter_voltage[i];
17283 +       } else if (data->iterate == 2) {        /* show results of last iteration */
17284 +               for (i = 0; i < 4; i++)
17285 +                       data->voltage[i] = data->iter_voltage[i];
17286 +               wake_up_interruptible(&data->wq);
17287 +       } else {                /* no iteration */
17288 +               data->voltage[3] =
17289 +                   gl518_read_value(client, GL518_REG_VIN3);
17290 +       }
17291 +}
17292 +
17293 +static int gl518_update_thread(void *c)
17294 +{
17295 +       struct i2c_client *client = c;
17296 +       struct gl518_data *data = client->data;
17297 +
17298 +#ifdef __SMP__
17299 +       lock_kernel();
17300 +#endif
17301 +       exit_mm(current);
17302 +       current->session = 1;
17303 +       current->pgrp = 1;
17304 +       sigfillset(&current->blocked);
17305 +       current->fs->umask = 0;
17306 +       strcpy(current->comm, "gl518sm");
17307 +
17308 +       init_waitqueue_head(&(data->wq));
17309 +       data->thread = current;
17310 +
17311 +#ifdef __SMP__
17312 +       unlock_kernel();
17313 +#endif
17314 +
17315 +       for (;;) {
17316 +               if (!data->iterate_lock) {
17317 +                       data->iterate_lock = 1;
17318 +                       gl518_update_iterate(client);
17319 +                       data->iterate_lock = 0;
17320 +               }
17321 +
17322 +               if ((data->quit_thread) || signal_pending(current))
17323 +                       break;
17324 +               interruptible_sleep_on(&data->wq);
17325 +       }
17326 +
17327 +       data->thread = NULL;
17328 +       data->quit_thread = 0;
17329 +       return 0;
17330 +}
17331 +
17332 +/* This updates vdd, vin1, vin2 values by doing slow and multiple
17333 +   comparisons for the GL518SM rev 00 that lacks support for direct
17334 +   reading of these values.   Values are kept in iter_voltage   */
17335 +
17336 +static void gl518_update_iterate(struct i2c_client *client)
17337 +{
17338 +       struct gl518_data *data = client->data;
17339 +       int i, j, loop_more = 1, min[3], max[3], delta[3];
17340 +       int alarm, beeps, irqs;
17341 +
17342 +#define VIN_REG(c) c==0?GL518_REG_VDD_LIMIT:\
17343 +                   c==1?GL518_REG_VIN1_LIMIT:\
17344 +                   GL518_REG_VIN2_LIMIT
17345 +
17346 +       /* disable beeps & irqs for vin0-2 */
17347 +       beeps = gl518_read_value(client, GL518_REG_ALARM);
17348 +       irqs = gl518_read_value(client, GL518_REG_MASK);
17349 +       gl518_write_value(client, GL518_REG_ALARM, beeps & ~0x7);
17350 +       gl518_write_value(client, GL518_REG_MASK, irqs & ~0x7);
17351 +
17352 +       alarm = data->alarms;
17353 +
17354 +       for (i = 0; i < 3; i++) {
17355 +               if (alarm & (1 << i)) {
17356 +                       min[i] = 0;
17357 +                       max[i] = 127;
17358 +               } else {
17359 +                       min[i] = data->voltage_min[i];
17360 +                       max[i] =
17361 +                           (data->voltage_max[i] +
17362 +                            data->voltage_min[i]) / 2;
17363 +               }
17364 +               delta[i] = (max[i] - min[i]) / 2;
17365 +       }
17366 +
17367 +       for (j = 0; (j < 10 && loop_more); j++) {
17368 +
17369 +               for (i = 0; i < 3; i++)
17370 +                       gl518_write_value(client, VIN_REG(i),
17371 +                                         max[i] << 8 | min[i]);
17372 +
17373 +               if ((data->thread) &&
17374 +                   ((data->quit_thread) || signal_pending(current)))
17375 +                       goto finish;
17376 +
17377 +               /* we wait now 1.5 seconds before comparing */
17378 +               current->state = TASK_INTERRUPTIBLE;
17379 +               schedule_timeout(HZ + HZ / 2);
17380 +
17381 +               alarm = gl518_read_value(client, GL518_REG_INT);
17382 +
17383 +#ifdef DEBUG_VIN
17384 +               printk("gl518sm: iteration %2d: %4d%c %4d%c %4d%c\n", j,
17385 +                      max[0], (alarm & 1) ? '!' : ' ',
17386 +                      max[1], (alarm & 2) ? '!' : ' ',
17387 +                      max[2], (alarm & 4) ? '!' : ' ');
17388 +#endif
17389 +
17390 +               for (loop_more = 0, i = 0; i < 3; i++) {
17391 +                       if (alarm & (1 << i))
17392 +                               max[i] += delta[i];
17393 +                       else
17394 +                               max[i] -= delta[i];
17395 +
17396 +                       if (delta[i])
17397 +                               loop_more++;
17398 +                       delta[i] >>= 1;
17399 +               }
17400 +
17401 +       }
17402 +
17403 +       for (i = 0; i < 3; i++)
17404 +               if (alarm & (1 << i))
17405 +                       max[i]++;
17406 +
17407 +#ifdef DEBUG_VIN
17408 +       printk("gl518sm:    final   :%5d %5d %5d\n", max[0], max[1],
17409 +              max[2]);
17410 +       printk("gl518sm:    meter   :%5d %5d %5d\n", data->voltage[0],
17411 +              data->voltage[1], data->voltage[2]);
17412 +#endif
17413 +
17414 +       /* update values, including vin3 */
17415 +       for (i = 0; i < 3; i++) {
17416 +               data->iter_voltage[i] = max[i];
17417 +       }
17418 +       data->iter_voltage[3] = gl518_read_value(client, GL518_REG_VIN3);
17419 +       data->last_updated_v00 = jiffies;
17420 +
17421 +      finish:
17422 +
17423 +       /* reset values */
17424 +       for (i = 0; i < 3; i++) {
17425 +               gl518_write_value(client, VIN_REG(i),
17426 +                                 data->voltage_max[i] << 8 | data->
17427 +                                 voltage_min[i]);
17428 +       }
17429 +
17430 +       gl518_write_value(client, GL518_REG_ALARM, beeps);
17431 +       gl518_write_value(client, GL518_REG_MASK, irqs);
17432 +
17433 +#undef VIN_REG
17434 +}
17435 +
17436 +void gl518_temp(struct i2c_client *client, int operation, int ctl_name,
17437 +               int *nrels_mag, long *results)
17438 +{
17439 +       struct gl518_data *data = client->data;
17440 +       if (operation == SENSORS_PROC_REAL_INFO)
17441 +               *nrels_mag = 1;
17442 +       else if (operation == SENSORS_PROC_REAL_READ) {
17443 +               gl518_update_client(client);
17444 +               results[0] = TEMP_FROM_REG(data->temp_over);
17445 +               results[1] = TEMP_FROM_REG(data->temp_hyst);
17446 +               results[2] = TEMP_FROM_REG(data->temp);
17447 +               *nrels_mag = 3;
17448 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
17449 +               if (*nrels_mag >= 1) {
17450 +                       data->temp_over = TEMP_TO_REG(results[0]);
17451 +                       gl518_write_value(client, GL518_REG_TEMP_OVER,
17452 +                                         data->temp_over);
17453 +               }
17454 +               if (*nrels_mag >= 2) {
17455 +                       data->temp_hyst = TEMP_TO_REG(results[1]);
17456 +                       gl518_write_value(client, GL518_REG_TEMP_HYST,
17457 +                                         data->temp_hyst);
17458 +               }
17459 +       }
17460 +}
17461 +
17462 +void gl518_vin(struct i2c_client *client, int operation, int ctl_name,
17463 +              int *nrels_mag, long *results)
17464 +{
17465 +       struct gl518_data *data = client->data;
17466 +       int nr = ctl_name - GL518_SYSCTL_VDD;
17467 +       int regnr, old = 0;
17468 +
17469 +       if (operation == SENSORS_PROC_REAL_INFO)
17470 +               *nrels_mag = 2;
17471 +       else if (operation == SENSORS_PROC_REAL_READ) {
17472 +               gl518_update_client(client);
17473 +               results[0] = nr ? IN_FROM_REG(data->voltage_min[nr]) :
17474 +                   VDD_FROM_REG(data->voltage_min[nr]);
17475 +               results[1] = nr ? IN_FROM_REG(data->voltage_max[nr]) :
17476 +                   VDD_FROM_REG(data->voltage_max[nr]);
17477 +               results[2] = nr ? IN_FROM_REG(data->voltage[nr]) :
17478 +                   VDD_FROM_REG(data->voltage[nr]);
17479 +               *nrels_mag = 3;
17480 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
17481 +               regnr =
17482 +                   nr == 0 ? GL518_REG_VDD_LIMIT : nr ==
17483 +                   1 ? GL518_REG_VIN1_LIMIT : nr ==
17484 +                   2 ? GL518_REG_VIN2_LIMIT : GL518_REG_VIN3_LIMIT;
17485 +               if (*nrels_mag == 1)
17486 +                       old = gl518_read_value(client, regnr) & 0xff00;
17487 +               if (*nrels_mag >= 2) {
17488 +                       data->voltage_max[nr] =
17489 +                           nr ? IN_TO_REG(results[1]) :
17490 +                           VDD_TO_REG(results[1]);
17491 +                       old = data->voltage_max[nr] << 8;
17492 +               }
17493 +               if (*nrels_mag >= 1) {
17494 +                       data->voltage_min[nr] =
17495 +                           nr ? IN_TO_REG(results[0]) :
17496 +                           VDD_TO_REG(results[0]);
17497 +                       old |= data->voltage_min[nr];
17498 +                       gl518_write_value(client, regnr, old);
17499 +               }
17500 +       }
17501 +}
17502 +
17503 +
17504 +void gl518_fan(struct i2c_client *client, int operation, int ctl_name,
17505 +              int *nrels_mag, long *results)
17506 +{
17507 +       struct gl518_data *data = client->data;
17508 +       int nr = ctl_name - GL518_SYSCTL_FAN1;
17509 +       int old;
17510 +
17511 +       if (operation == SENSORS_PROC_REAL_INFO)
17512 +               *nrels_mag = 0;
17513 +       else if (operation == SENSORS_PROC_REAL_READ) {
17514 +               gl518_update_client(client);
17515 +               results[0] = FAN_FROM_REG(data->fan_min[nr],
17516 +                                         DIV_FROM_REG(data->fan_div[nr]));
17517 +               results[1] =
17518 +                   FAN_FROM_REG(data->fan[nr],
17519 +                                DIV_FROM_REG(data->fan_div[nr]));
17520 +               *nrels_mag = 2;
17521 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
17522 +               if (*nrels_mag >= 1) {
17523 +                       data->fan_min[nr] = FAN_TO_REG(results[0],
17524 +                                                      DIV_FROM_REG(data->
17525 +                                                                   fan_div
17526 +                                                                   [nr]));
17527 +                       old =
17528 +                           gl518_read_value(client, GL518_REG_FAN_LIMIT);
17529 +
17530 +                       if (nr == 0) {
17531 +                               old =
17532 +                                   (old & 0x00ff) | (data->
17533 +                                                     fan_min[0] << 8);
17534 +                               if (results[0] == 0)
17535 +                                       data->alarm_mask &= ~0x20;
17536 +                               else
17537 +                                       data->alarm_mask |= 0x20;
17538 +                       } else {
17539 +                               old = (old & 0xff00) | data->fan_min[1];
17540 +                               if (results[0] == 0)
17541 +                                       data->alarm_mask &= ~0x40;
17542 +                               else
17543 +                                       data->alarm_mask |= 0x40;
17544 +                       }
17545 +                       gl518_write_value(client, GL518_REG_FAN_LIMIT,
17546 +                                         old);
17547 +               }
17548 +       }
17549 +}
17550 +
17551 +
17552 +void gl518_alarms(struct i2c_client *client, int operation, int ctl_name,
17553 +                 int *nrels_mag, long *results)
17554 +{
17555 +       struct gl518_data *data = client->data;
17556 +       if (operation == SENSORS_PROC_REAL_INFO)
17557 +               *nrels_mag = 0;
17558 +       else if (operation == SENSORS_PROC_REAL_READ) {
17559 +               gl518_update_client(client);
17560 +               results[0] = ALARMS_FROM_REG(data->alarms);
17561 +               *nrels_mag = 1;
17562 +       }
17563 +}
17564 +
17565 +void gl518_beep(struct i2c_client *client, int operation, int ctl_name,
17566 +               int *nrels_mag, long *results)
17567 +{
17568 +       struct gl518_data *data = client->data;
17569 +       if (operation == SENSORS_PROC_REAL_INFO)
17570 +               *nrels_mag = 0;
17571 +       else if (operation == SENSORS_PROC_REAL_READ) {
17572 +               gl518_update_client(client);
17573 +               results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable);
17574 +               results[1] = BEEPS_FROM_REG(data->beeps);
17575 +               *nrels_mag = 2;
17576 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
17577 +               if (*nrels_mag >= 1) {
17578 +                       data->beep_enable = BEEP_ENABLE_TO_REG(results[0]);
17579 +                       gl518_write_value(client, GL518_REG_CONF,
17580 +                                         (gl518_read_value(client,
17581 +                                                           GL518_REG_CONF)
17582 +                                          & 0xfb) | (data->
17583 +                                                     beep_enable << 2));
17584 +               }
17585 +               if (*nrels_mag >= 2) {
17586 +                       data->beeps =
17587 +                           BEEPS_TO_REG(results[1]) & data->alarm_mask;
17588 +                       gl518_write_value(client, GL518_REG_ALARM,
17589 +                                         data->beeps);
17590 +               }
17591 +       }
17592 +}
17593 +
17594 +
17595 +void gl518_fan_div(struct i2c_client *client, int operation, int ctl_name,
17596 +                  int *nrels_mag, long *results)
17597 +{
17598 +       struct gl518_data *data = client->data;
17599 +       int old;
17600 +       if (operation == SENSORS_PROC_REAL_INFO)
17601 +               *nrels_mag = 0;
17602 +       else if (operation == SENSORS_PROC_REAL_READ) {
17603 +               gl518_update_client(client);
17604 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
17605 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
17606 +               *nrels_mag = 2;
17607 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
17608 +               old = gl518_read_value(client, GL518_REG_MISC);
17609 +               if (*nrels_mag >= 2) {
17610 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
17611 +                       old = (old & 0xcf) | (data->fan_div[1] << 4);
17612 +               }
17613 +               if (*nrels_mag >= 1) {
17614 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
17615 +                       old = (old & 0x3f) | (data->fan_div[0] << 6);
17616 +               }
17617 +               gl518_write_value(client, GL518_REG_MISC, old);
17618 +       }
17619 +}
17620 +
17621 +void gl518_fan1off(struct i2c_client *client, int operation, int ctl_name,
17622 +                  int *nrels_mag, long *results)
17623 +{
17624 +       int old;
17625 +       if (operation == SENSORS_PROC_REAL_INFO)
17626 +               *nrels_mag = 0;
17627 +       else if (operation == SENSORS_PROC_REAL_READ) {
17628 +               results[0] =
17629 +                   ((gl518_read_value(client, GL518_REG_MISC) & 0x08) !=
17630 +                    0);
17631 +               results[1] =
17632 +                   ((gl518_read_value(client, GL518_REG_CONF) & 0x10) !=
17633 +                    0);
17634 +               *nrels_mag = 2;
17635 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
17636 +               if (*nrels_mag >= 1) {
17637 +                       old =
17638 +                           gl518_read_value(client,
17639 +                                            GL518_REG_MISC) & 0xf7;
17640 +                       if (results[0])
17641 +                               old |= 0x08;
17642 +                       gl518_write_value(client, GL518_REG_MISC, old);
17643 +               }
17644 +               if (*nrels_mag >= 2) {
17645 +                       old =
17646 +                           gl518_read_value(client,
17647 +                                            GL518_REG_CONF) & 0xef;
17648 +                       if (results[1])
17649 +                               old |= 0x10;
17650 +                       gl518_write_value(client, GL518_REG_CONF, old);
17651 +               }
17652 +       }
17653 +}
17654 +
17655 +void gl518_iterate(struct i2c_client *client, int operation, int ctl_name,
17656 +                  int *nrels_mag, long *results)
17657 +{
17658 +       struct gl518_data *data = client->data;
17659 +       int i;
17660 +       if (operation == SENSORS_PROC_REAL_INFO)
17661 +               *nrels_mag = 0;
17662 +       else if (operation == SENSORS_PROC_REAL_READ) {
17663 +               results[0] = data->iterate;
17664 +               *nrels_mag = 1;
17665 +       } else if (operation == SENSORS_PROC_REAL_WRITE &&
17666 +                  data->type == gl518sm_r00 ) {
17667 +               if ((*nrels_mag >= 1) && (data->iterate != results[0])) {
17668 +                       data->iterate = results[0];
17669 +                       for (i = 0; i < 4; i++) {
17670 +                               data->voltage[i] = 0;
17671 +                               data->iter_voltage[i] = 0;
17672 +                       }
17673 +                       data->valid = 0;
17674 +
17675 +                       if ((data->iterate != 2) && (data->thread)) {
17676 +                               data->quit_thread = 1;
17677 +                               wake_up_interruptible(&data->wq);
17678 +                       } else if ((data->iterate == 2) && (!data->thread)) {
17679 +                               init_waitqueue_head(&(data->wq));
17680 +                               kernel_thread(gl518_update_thread,
17681 +                                             (void *) client, 0);
17682 +                       }
17683 +               }
17684 +       }
17685 +}
17686 +
17687 +static int __init sm_gl518sm_init(void)
17688 +{
17689 +       printk("gl518sm.o version %s (%s)\n", LM_VERSION, LM_DATE);
17690 +       return i2c_add_driver(&gl518_driver);
17691 +}
17692 +
17693 +static void __exit sm_gl518sm_exit(void)
17694 +{
17695 +       i2c_del_driver(&gl518_driver);
17696 +}
17697 +
17698 +
17699 +
17700 +MODULE_AUTHOR
17701 +    ("Frodo Looijaard <frodol@dds.nl> and Kyösti Mälkki <kmalkki@cc.hut.fi>");
17702 +MODULE_DESCRIPTION("GL518SM driver");
17703 +
17704 +module_init(sm_gl518sm_init);
17705 +module_exit(sm_gl518sm_exit);
17706 --- linux-old/drivers/sensors/gl520sm.c Thu Jan  1 00:00:00 1970
17707 +++ linux/drivers/sensors/gl520sm.c     Mon Dec 13 20:18:47 2004
17708 @@ -0,0 +1,809 @@
17709 +/*
17710 +    gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
17711 +                monitoring
17712 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
17713 +                              Kyösti Mälkki <kmalkki@cc.hut.fi>
17714 +
17715 +    This program is free software; you can redistribute it and/or modify
17716 +    it under the terms of the GNU General Public License as published by
17717 +    the Free Software Foundation; either version 2 of the License, or
17718 +    (at your option) any later version.
17719 +
17720 +    This program is distributed in the hope that it will be useful,
17721 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
17722 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17723 +    GNU General Public License for more details.
17724 +
17725 +    You should have received a copy of the GNU General Public License
17726 +    along with this program; if not, write to the Free Software
17727 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17728 +
17729 +*/
17730 +
17731 +#include <linux/module.h>
17732 +#include <linux/slab.h>
17733 +#include <linux/i2c.h>
17734 +#include <linux/i2c-proc.h>
17735 +#include <linux/init.h>
17736 +#define LM_DATE "20041007"
17737 +#define LM_VERSION "2.8.8"
17738 +
17739 +MODULE_LICENSE("GPL");
17740 +
17741 +/* Addresses to scan */
17742 +static unsigned short normal_i2c[] = { 0x2c, 0x2d, SENSORS_I2C_END };
17743 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
17744 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
17745 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
17746 +
17747 +/* Insmod parameters */
17748 +SENSORS_INSMOD_1(gl520sm);
17749 +
17750 +/* Many GL520 constants specified below 
17751 +One of the inputs can be configured as either temp or voltage.
17752 +That's why _TEMP2 and _VIN4 access the same register 
17753 +*/
17754 +
17755 +/* The GL520 registers */
17756 +#define GL520_REG_CHIP_ID 0x00
17757 +#define GL520_REG_REVISION 0x01
17758 +#define GL520_REG_VID 0x02
17759 +#define GL520_REG_CONF 0x03
17760 +#define GL520_REG_TEMP1 0x04
17761 +#define GL520_REG_TEMP1_OVER 0x05
17762 +#define GL520_REG_TEMP1_HYST 0x06
17763 +#define GL520_REG_FAN_COUNT 0x07
17764 +#define GL520_REG_FAN_LIMIT 0x08
17765 +#define GL520_REG_VIN1_LIMIT 0x09
17766 +#define GL520_REG_VIN2_LIMIT 0x0a
17767 +#define GL520_REG_VIN3_LIMIT 0x0b
17768 +#define GL520_REG_VDD_LIMIT 0x0c
17769 +#define GL520_REG_VIN3 0x0d
17770 +#define GL520_REG_VIN4 0x0e
17771 +#define GL520_REG_TEMP2 0x0e
17772 +#define GL520_REG_MISC 0x0f
17773 +#define GL520_REG_ALARM 0x10
17774 +#define GL520_REG_MASK 0x11
17775 +#define GL520_REG_INT 0x12
17776 +#define GL520_REG_VIN2 0x13
17777 +#define GL520_REG_VIN1 0x14
17778 +#define GL520_REG_VDD 0x15
17779 +#define GL520_REG_TEMP2_OVER 0x17
17780 +#define GL520_REG_VIN4_MAX 0x17
17781 +#define GL520_REG_TEMP2_HYST 0x18
17782 +#define GL520_REG_VIN4_MIN 0x18
17783 +
17784 +
17785 +/* Conversions. Rounding and limit checking is only done on the TO_REG
17786 +   variants. Note that you should be a bit careful with which arguments
17787 +   these macros are called: arguments may be evaluated more than once.
17788 +   Fixing this is just not worth it. */
17789 +
17790 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-5:(val)+5) / 10)+130),\
17791 +                                        0,255))
17792 +#define TEMP_FROM_REG(val) (((val) - 130) * 10)
17793 +
17794 +static inline u8 FAN_TO_REG(long rpm, int div)
17795 +{
17796 +       if (rpm == 0)
17797 +               return 255;
17798 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
17799 +       return SENSORS_LIMIT((960000 + rpm * div / 2) / (rpm * div), 1,
17800 +                            254);
17801 +}
17802 +
17803 +#define FAN_FROM_REG(val,div) \
17804 + ( (val)==0 ? 0 : (val)==255 ? 0 : (960000/((val)*(div))) )
17805 +
17806 +#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*10+8)/19),0,255))
17807 +#define IN_FROM_REG(val) (((val)*19)/10)
17808 +
17809 +#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*10+11)/23),0,255))
17810 +#define VDD_FROM_REG(val) (((val)*23)/10)
17811 +
17812 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
17813 +#define DIV_FROM_REG(val) (1 << (val))
17814 +
17815 +#define ALARMS_FROM_REG(val) val
17816 +
17817 +#define BEEP_ENABLE_TO_REG(val) ((val)?0:1)
17818 +#define BEEP_ENABLE_FROM_REG(val) ((val)?0:1)
17819 +
17820 +#define BEEPS_TO_REG(val) (val)
17821 +#define BEEPS_FROM_REG(val) (val)
17822 +
17823 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
17824 +                           205-(val)*5)
17825 +
17826 +/* Each client has this additional data */
17827 +struct gl520_data {
17828 +       struct i2c_client client;
17829 +       int sysctl_id;
17830 +       enum chips type;
17831 +
17832 +       struct semaphore update_lock;
17833 +       char valid;             /* !=0 if following fields are valid */
17834 +       unsigned long last_updated;     /* In jiffies */
17835 +
17836 +       u8 voltage[5];          /* Register values; [0] = VDD */
17837 +       u8 voltage_min[5];      /* Register values; [0] = VDD */
17838 +       u8 voltage_max[5];      /* Register values; [0] = VDD */
17839 +       u8 fan[2];
17840 +       u8 fan_min[2];
17841 +       u8 temp[2];             /* Register values */
17842 +       u8 temp_over[2];        /* Register values */
17843 +       u8 temp_hyst[2];        /* Register values */
17844 +       u8 alarms, beeps, vid;  /* Register value */
17845 +       u8 alarm_mask;          /* Register value */
17846 +       u8 fan_div[2];          /* Register encoding, shifted right */
17847 +       u8 beep_enable;         /* Boolean */
17848 +       u8 two_temps;           /* Boolean */
17849 +};
17850 +
17851 +static int gl520_attach_adapter(struct i2c_adapter *adapter);
17852 +static int gl520_detect(struct i2c_adapter *adapter, int address,
17853 +                       unsigned short flags, int kind);
17854 +static void gl520_init_client(struct i2c_client *client);
17855 +static int gl520_detach_client(struct i2c_client *client);
17856 +
17857 +static int gl520_read_value(struct i2c_client *client, u8 reg);
17858 +static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
17859 +static void gl520_update_client(struct i2c_client *client);
17860 +
17861 +static void gl520_vin(struct i2c_client *client, int operation,
17862 +                     int ctl_name, int *nrels_mag, long *results);
17863 +static void gl520_vid(struct i2c_client *client, int operation,
17864 +                     int ctl_name, int *nrels_mag, long *results);
17865 +static void gl520_fan(struct i2c_client *client, int operation,
17866 +                     int ctl_name, int *nrels_mag, long *results);
17867 +static void gl520_temp(struct i2c_client *client, int operation,
17868 +                      int ctl_name, int *nrels_mag, long *results);
17869 +static void gl520_fan_div(struct i2c_client *client, int operation,
17870 +                         int ctl_name, int *nrels_mag, long *results);
17871 +static void gl520_alarms(struct i2c_client *client, int operation,
17872 +                        int ctl_name, int *nrels_mag, long *results);
17873 +static void gl520_beep(struct i2c_client *client, int operation,
17874 +                      int ctl_name, int *nrels_mag, long *results);
17875 +static void gl520_fan1off(struct i2c_client *client, int operation,
17876 +                         int ctl_name, int *nrels_mag, long *results);
17877 +static void gl520_config(struct i2c_client *client, int operation,
17878 +                        int ctl_name, int *nrels_mag, long *results);
17879 +
17880 +/* This is the driver that will be inserted */
17881 +static struct i2c_driver gl520_driver = {
17882 +       .owner          = THIS_MODULE,
17883 +       .name           = "GL520SM sensor chip driver",
17884 +       .id             = I2C_DRIVERID_GL520,
17885 +       .flags          = I2C_DF_NOTIFY,
17886 +       .attach_adapter = gl520_attach_adapter,
17887 +       .detach_client  = gl520_detach_client,
17888 +};
17889 +/* -- SENSORS SYSCTL START -- */
17890 +
17891 +#define GL520_SYSCTL_VDD  1000 /* Volts * 100 */
17892 +#define GL520_SYSCTL_VIN1 1001
17893 +#define GL520_SYSCTL_VIN2 1002
17894 +#define GL520_SYSCTL_VIN3 1003
17895 +#define GL520_SYSCTL_VIN4 1004
17896 +#define GL520_SYSCTL_FAN1 1101 /* RPM */
17897 +#define GL520_SYSCTL_FAN2 1102
17898 +#define GL520_SYSCTL_TEMP1 1200        /* Degrees Celcius * 10 */
17899 +#define GL520_SYSCTL_TEMP2 1201        /* Degrees Celcius * 10 */
17900 +#define GL520_SYSCTL_VID 1300
17901 +#define GL520_SYSCTL_FAN_DIV 2000      /* 1, 2, 4 or 8 */
17902 +#define GL520_SYSCTL_ALARMS 2001       /* bitvector */
17903 +#define GL520_SYSCTL_BEEP 2002 /* bitvector */
17904 +#define GL520_SYSCTL_FAN1OFF 2003
17905 +#define GL520_SYSCTL_CONFIG 2004
17906 +
17907 +#define GL520_ALARM_VDD 0x01
17908 +#define GL520_ALARM_VIN1 0x02
17909 +#define GL520_ALARM_VIN2 0x04
17910 +#define GL520_ALARM_VIN3 0x08
17911 +#define GL520_ALARM_TEMP1 0x10
17912 +#define GL520_ALARM_FAN1 0x20
17913 +#define GL520_ALARM_FAN2 0x40
17914 +#define GL520_ALARM_TEMP2 0x80
17915 +#define GL520_ALARM_VIN4 0x80
17916 +
17917 +/* -- SENSORS SYSCTL END -- */
17918 +
17919 +/* These files are created for each detected GL520. This is just a template;
17920 +   though at first sight, you might think we could use a statically
17921 +   allocated list, we need some way to get back to the parent - which
17922 +   is done through one of the 'extra' fields which are initialized
17923 +   when a new copy is allocated. */
17924 +static ctl_table gl520_dir_table_template[] = {
17925 +       {GL520_SYSCTL_VIN1, "vin1", NULL, 0, 0644, NULL, &i2c_proc_real,
17926 +        &i2c_sysctl_real, NULL, &gl520_vin},
17927 +       {GL520_SYSCTL_VIN2, "vin2", NULL, 0, 0644, NULL, &i2c_proc_real,
17928 +        &i2c_sysctl_real, NULL, &gl520_vin},
17929 +       {GL520_SYSCTL_VIN3, "vin3", NULL, 0, 0644, NULL, &i2c_proc_real,
17930 +        &i2c_sysctl_real, NULL, &gl520_vin},
17931 +       {GL520_SYSCTL_VIN4, "vin4", NULL, 0, 0644, NULL, &i2c_proc_real,
17932 +        &i2c_sysctl_real, NULL, &gl520_vin},
17933 +       {GL520_SYSCTL_VDD, "vdd", NULL, 0, 0644, NULL, &i2c_proc_real,
17934 +        &i2c_sysctl_real, NULL, &gl520_vin},
17935 +       {GL520_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
17936 +        &i2c_sysctl_real, NULL, &gl520_vid},
17937 +       {GL520_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
17938 +        &i2c_sysctl_real, NULL, &gl520_fan},
17939 +       {GL520_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
17940 +        &i2c_sysctl_real, NULL, &gl520_fan},
17941 +       {GL520_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
17942 +        &i2c_sysctl_real, NULL, &gl520_temp},
17943 +       {GL520_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
17944 +        &i2c_sysctl_real, NULL, &gl520_temp},
17945 +       {GL520_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
17946 +        &i2c_sysctl_real, NULL, &gl520_fan_div},
17947 +       {GL520_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
17948 +        &i2c_sysctl_real, NULL, &gl520_alarms},
17949 +       {GL520_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
17950 +        &i2c_sysctl_real, NULL, &gl520_beep},
17951 +       {GL520_SYSCTL_FAN1OFF, "fan1off", NULL, 0, 0644, NULL, &i2c_proc_real,
17952 +        &i2c_sysctl_real, NULL, &gl520_fan1off},
17953 +       {GL520_SYSCTL_CONFIG, "config", NULL, 0, 0644, NULL, &i2c_proc_real,
17954 +        &i2c_sysctl_real, NULL, &gl520_config},
17955 +       {0}
17956 +};
17957 +
17958 +static int gl520_id = 0;
17959 +
17960 +static int gl520_attach_adapter(struct i2c_adapter *adapter)
17961 +{
17962 +       return i2c_detect(adapter, &addr_data, gl520_detect);
17963 +}
17964 +
17965 +static int gl520_detect(struct i2c_adapter *adapter, int address,
17966 +                       unsigned short flags, int kind)
17967 +{
17968 +       int i;
17969 +       struct i2c_client *new_client;
17970 +       struct gl520_data *data;
17971 +       int err = 0;
17972 +       const char *type_name = "";
17973 +       char client_name[32];
17974 +
17975 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
17976 +          at this moment; i2c_detect really won't call us. */
17977 +#ifdef DEBUG
17978 +       if (i2c_is_isa_adapter(adapter)) {
17979 +               printk
17980 +                   ("gl520sm.o: gl520_detect called for an ISA bus adapter?!?\n");
17981 +               return 0;
17982 +       }
17983 +#endif
17984 +
17985 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
17986 +                                    I2C_FUNC_SMBUS_WORD_DATA))
17987 +                   goto ERROR0;
17988 +
17989 +       /* OK. For now, we presume we have a valid client. We now create the
17990 +          client structure, even though we cannot fill it completely yet.
17991 +          But it allows us to access gl520_{read,write}_value. */
17992 +
17993 +       if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
17994 +               err = -ENOMEM;
17995 +               goto ERROR0;
17996 +       }
17997 +
17998 +       new_client = &data->client;
17999 +       new_client->addr = address;
18000 +       new_client->data = data;
18001 +       new_client->adapter = adapter;
18002 +       new_client->driver = &gl520_driver;
18003 +       new_client->flags = 0;
18004 +
18005 +       /* Determine the chip type. */
18006 +
18007 +       if (gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) {
18008 +               printk
18009 +                   ("gl520sm.o: Ignoring 'force' parameter for unknown chip at "
18010 +                    "adapter %d, address 0x%02x\n",
18011 +                    i2c_adapter_id(adapter), address);
18012 +               goto ERROR1;
18013 +       } else {
18014 +               kind = gl520sm;
18015 +       }
18016 +
18017 +       i = gl520_read_value(new_client, GL520_REG_REVISION);
18018 +       if (kind == gl520sm) {
18019 +               type_name = "gl520sm";
18020 +               sprintf(client_name, "GL520SM Revision %02x chip", i);
18021 +       } else {
18022 +#ifdef DEBUG
18023 +               printk("gl520sm.o: Internal error: unknown kind (%d)?!?",
18024 +                      kind);
18025 +#endif
18026 +               goto ERROR1;
18027 +       }
18028 +
18029 +       /* Fill in the remaining client fields and put it into the global list */
18030 +       strcpy(new_client->name, client_name);
18031 +       data->type = kind;
18032 +
18033 +       new_client->id = gl520_id++;
18034 +       data->valid = 0;
18035 +       init_MUTEX(&data->update_lock);
18036 +
18037 +       /* Tell the I2C layer a new client has arrived */
18038 +       if ((err = i2c_attach_client(new_client)))
18039 +               goto ERROR3;
18040 +
18041 +       /* Register a new directory entry with module sensors */
18042 +       if ((i = i2c_register_entry(new_client,
18043 +                                       type_name,
18044 +                                       gl520_dir_table_template)) < 0) {
18045 +               err = i;
18046 +               goto ERROR4;
18047 +       }
18048 +       data->sysctl_id = i;
18049 +
18050 +       /* Initialize the GL520SM chip */
18051 +       data->alarm_mask = 0xff;
18052 +       gl520_init_client(new_client);
18053 +       if (data->two_temps)
18054 +               data->voltage_max[4] = data->voltage_min[4] =
18055 +                       data->voltage[4] = 0;
18056 +       else
18057 +               data->temp_hyst[1] = data->temp_over[1] =
18058 +                       data->temp[1] = 0;
18059 +
18060 +       return 0;
18061 +
18062 +/* OK, this is not exactly good programming practice, usually. But it is
18063 +   very code-efficient in this case. */
18064 +
18065 +      ERROR4:
18066 +       i2c_detach_client(new_client);
18067 +      ERROR3:
18068 +      ERROR1:
18069 +       kfree(data);
18070 +      ERROR0:
18071 +       return err;
18072 +}
18073 +
18074 +
18075 +/* Called when we have found a new GL520SM. */
18076 +static void gl520_init_client(struct i2c_client *client)
18077 +{
18078 +       struct gl520_data *data = (struct gl520_data *)(client->data);
18079 +       u8 oldconf, conf;
18080 +
18081 +       conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
18082 +       data->two_temps = !(conf & 0x10);
18083 +
18084 +       /* If IRQ# is disabled, we can safely force comparator mode */
18085 +       if (!(conf & 0x20))
18086 +               conf &= 0xf7;
18087 +
18088 +       /* Enable monitoring if needed */
18089 +       conf |= 0x40;
18090 +
18091 +       if (conf != oldconf)
18092 +               gl520_write_value(client, GL520_REG_CONF, conf);
18093 +}
18094 +
18095 +static int gl520_detach_client(struct i2c_client *client)
18096 +{
18097 +       int err;
18098 +
18099 +       i2c_deregister_entry(((struct gl520_data *) (client->data))->
18100 +                                sysctl_id);
18101 +
18102 +       if ((err = i2c_detach_client(client))) {
18103 +               printk
18104 +                   ("gl520sm.o: Client deregistration failed, client not detached.\n");
18105 +               return err;
18106 +       }
18107 +
18108 +       kfree(client->data);
18109 +
18110 +       return 0;
18111 +}
18112 +
18113 +
18114 +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
18115 +   GL520 uses a high-byte first convention, which is exactly opposite to
18116 +   the usual practice. */
18117 +static int gl520_read_value(struct i2c_client *client, u8 reg)
18118 +{
18119 +       if ((reg >= 0x07) && (reg <= 0x0c))
18120 +               return swab16(i2c_smbus_read_word_data(client, reg));
18121 +       else
18122 +               return i2c_smbus_read_byte_data(client, reg);
18123 +}
18124 +
18125 +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
18126 +   GL520 uses a high-byte first convention, which is exactly opposite to
18127 +   the usual practice. */
18128 +static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
18129 +{
18130 +       if ((reg >= 0x07) && (reg <= 0x0c))
18131 +               return i2c_smbus_write_word_data(client, reg, swab16(value));
18132 +       else
18133 +               return i2c_smbus_write_byte_data(client, reg, value);
18134 +}
18135 +
18136 +static void gl520_update_client(struct i2c_client *client)
18137 +{
18138 +       struct gl520_data *data = client->data;
18139 +       int val;
18140 +
18141 +       down(&data->update_lock);
18142 +
18143 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
18144 +           (jiffies < data->last_updated) || !data->valid) {
18145 +
18146 +#ifdef DEBUG
18147 +               printk("Starting gl520 update\n");
18148 +#endif
18149 +
18150 +               data->alarms = gl520_read_value(client, GL520_REG_INT);
18151 +               data->beeps = gl520_read_value(client, GL520_REG_ALARM);
18152 +               data->vid = gl520_read_value(client, GL520_REG_VID) & 0x1f;
18153 +
18154 +               val = gl520_read_value(client, GL520_REG_VDD_LIMIT);
18155 +               data->voltage_min[0] = val & 0xff;
18156 +               data->voltage_max[0] = (val >> 8) & 0xff;
18157 +               val = gl520_read_value(client, GL520_REG_VIN1_LIMIT);
18158 +               data->voltage_min[1] = val & 0xff;
18159 +               data->voltage_max[1] = (val >> 8) & 0xff;
18160 +               val = gl520_read_value(client, GL520_REG_VIN2_LIMIT);
18161 +               data->voltage_min[2] = val & 0xff;
18162 +               data->voltage_max[2] = (val >> 8) & 0xff;
18163 +               val = gl520_read_value(client, GL520_REG_VIN3_LIMIT);
18164 +               data->voltage_min[3] = val & 0xff;
18165 +               data->voltage_max[3] = (val >> 8) & 0xff;
18166 +
18167 +               val = gl520_read_value(client, GL520_REG_FAN_COUNT);
18168 +               data->fan[0] = (val >> 8) & 0xff;
18169 +               data->fan[1] = val & 0xff;
18170 +
18171 +               val = gl520_read_value(client, GL520_REG_FAN_LIMIT);
18172 +               data->fan_min[0] = (val >> 8) & 0xff;
18173 +               data->fan_min[1] = val & 0xff;
18174 +
18175 +               data->temp[0] = gl520_read_value(client, GL520_REG_TEMP1);
18176 +               data->temp_over[0] =
18177 +                   gl520_read_value(client, GL520_REG_TEMP1_OVER);
18178 +               data->temp_hyst[0] =
18179 +                   gl520_read_value(client, GL520_REG_TEMP1_HYST);
18180 +
18181 +               val = gl520_read_value(client, GL520_REG_MISC);
18182 +               data->fan_div[0] = (val >> 6) & 0x03;
18183 +               data->fan_div[1] = (val >> 4) & 0x03;
18184 +
18185 +               data->alarms &= data->alarm_mask;
18186 +
18187 +               val = gl520_read_value(client, GL520_REG_CONF);
18188 +               data->beep_enable = (val >> 2) & 1;
18189 +
18190 +               data->voltage[0] = gl520_read_value(client, GL520_REG_VDD);
18191 +               data->voltage[1] =
18192 +                   gl520_read_value(client, GL520_REG_VIN1);
18193 +               data->voltage[2] =
18194 +                   gl520_read_value(client, GL520_REG_VIN2);
18195 +               data->voltage[3] =
18196 +                   gl520_read_value(client, GL520_REG_VIN3);
18197 +
18198 +               /* Temp1 and Vin4 are the same input */
18199 +               if (data->two_temps) {
18200 +                       data->temp[1] =
18201 +                           gl520_read_value(client, GL520_REG_TEMP2);
18202 +                       data->temp_over[1] =
18203 +                           gl520_read_value(client, GL520_REG_TEMP2_OVER);
18204 +                       data->temp_hyst[1] =
18205 +                           gl520_read_value(client, GL520_REG_TEMP2_HYST);
18206 +               } else {
18207 +                       data->voltage[4] =
18208 +                           gl520_read_value(client, GL520_REG_VIN4);
18209 +                       data->voltage_min[4] =
18210 +                           gl520_read_value(client, GL520_REG_VIN4_MIN);
18211 +                       data->voltage_max[4] =
18212 +                           gl520_read_value(client, GL520_REG_VIN4_MAX);
18213 +               }
18214 +
18215 +               data->last_updated = jiffies;
18216 +               data->valid = 1;
18217 +       }
18218 +
18219 +       up(&data->update_lock);
18220 +}
18221 +
18222 +void gl520_temp(struct i2c_client *client, int operation, int ctl_name,
18223 +               int *nrels_mag, long *results)
18224 +{
18225 +       struct gl520_data *data = client->data;
18226 +       int nr = ctl_name - GL520_SYSCTL_TEMP1;
18227 +       int regnr;
18228 +
18229 +       if (operation == SENSORS_PROC_REAL_INFO)
18230 +               *nrels_mag = 1;
18231 +       else if (operation == SENSORS_PROC_REAL_READ) {
18232 +               gl520_update_client(client);
18233 +               results[0] = TEMP_FROM_REG(data->temp_over[nr]);
18234 +               results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
18235 +               results[2] = TEMP_FROM_REG(data->temp[nr]);
18236 +               *nrels_mag = 3;
18237 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
18238 +               if ((nr == 1) && (!data->two_temps))
18239 +                       return;
18240 +               regnr =
18241 +                   nr == 0 ? GL520_REG_TEMP1_OVER : GL520_REG_TEMP2_OVER;
18242 +               if (*nrels_mag >= 1) {
18243 +                       data->temp_over[nr] = TEMP_TO_REG(results[0]);
18244 +                       gl520_write_value(client, regnr,
18245 +                                         data->temp_over[nr]);
18246 +               }
18247 +               regnr =
18248 +                   nr == 0 ? GL520_REG_TEMP1_HYST : GL520_REG_TEMP2_HYST;
18249 +               if (*nrels_mag >= 2) {
18250 +                       data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
18251 +                       gl520_write_value(client, regnr,
18252 +                                         data->temp_hyst[nr]);
18253 +               }
18254 +       }
18255 +}
18256 +
18257 +void gl520_vin(struct i2c_client *client, int operation, int ctl_name,
18258 +              int *nrels_mag, long *results)
18259 +{
18260 +       struct gl520_data *data = client->data;
18261 +       int nr = ctl_name - GL520_SYSCTL_VDD;
18262 +       int regnr, old = 0;
18263 +
18264 +       if (operation == SENSORS_PROC_REAL_INFO)
18265 +               *nrels_mag = 2;
18266 +       else if (operation == SENSORS_PROC_REAL_READ) {
18267 +               gl520_update_client(client);
18268 +               results[0] = nr ? IN_FROM_REG(data->voltage_min[nr]) :
18269 +                   VDD_FROM_REG(data->voltage_min[nr]);
18270 +               results[1] = nr ? IN_FROM_REG(data->voltage_max[nr]) :
18271 +                   VDD_FROM_REG(data->voltage_max[nr]);
18272 +               results[2] = nr ? IN_FROM_REG(data->voltage[nr]) :
18273 +                   VDD_FROM_REG(data->voltage[nr]);
18274 +               *nrels_mag = 3;
18275 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
18276 +               if (nr != 4) {
18277 +                       regnr =
18278 +                           nr == 0 ? GL520_REG_VDD_LIMIT : nr ==
18279 +                           1 ? GL520_REG_VIN1_LIMIT : nr ==
18280 +                           2 ? GL520_REG_VIN2_LIMIT :
18281 +                           GL520_REG_VIN3_LIMIT;
18282 +                       if (*nrels_mag == 1)
18283 +                               old =
18284 +                                   gl520_read_value(client,
18285 +                                                    regnr) & 0xff00;
18286 +                       if (*nrels_mag >= 2) {
18287 +                               data->voltage_max[nr] =
18288 +                                   nr ? IN_TO_REG(results[1]) :
18289 +                                   VDD_TO_REG(results[1]);
18290 +                               old = data->voltage_max[nr] << 8;
18291 +                       }
18292 +                       if (*nrels_mag >= 1) {
18293 +                               data->voltage_min[nr] =
18294 +                                   nr ? IN_TO_REG(results[0]) :
18295 +                                   VDD_TO_REG(results[0]);
18296 +                               old |= data->voltage_min[nr];
18297 +                               gl520_write_value(client, regnr, old);
18298 +                       }
18299 +               } else if (!data->two_temps) {
18300 +                       if (*nrels_mag == 1)
18301 +                               gl520_write_value(client,
18302 +                                                 GL520_REG_VIN4_MIN,
18303 +                                                 IN_TO_REG(results[0]));
18304 +                       if (*nrels_mag >= 2)
18305 +                               gl520_write_value(client,
18306 +                                                 GL520_REG_VIN4_MAX,
18307 +                                                 IN_TO_REG(results[1]));
18308 +               }
18309 +       }
18310 +}
18311 +
18312 +
18313 +void gl520_fan(struct i2c_client *client, int operation, int ctl_name,
18314 +              int *nrels_mag, long *results)
18315 +{
18316 +       struct gl520_data *data = client->data;
18317 +       int nr = ctl_name - GL520_SYSCTL_FAN1;
18318 +       int old;
18319 +
18320 +       if (operation == SENSORS_PROC_REAL_INFO)
18321 +               *nrels_mag = 0;
18322 +       else if (operation == SENSORS_PROC_REAL_READ) {
18323 +               gl520_update_client(client);
18324 +               results[0] = FAN_FROM_REG(data->fan_min[nr],
18325 +                                         DIV_FROM_REG(data->fan_div[nr]));
18326 +               results[1] =
18327 +                   FAN_FROM_REG(data->fan[nr],
18328 +                                DIV_FROM_REG(data->fan_div[nr]));
18329 +               *nrels_mag = 2;
18330 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
18331 +               if (*nrels_mag >= 1) {
18332 +                       data->fan_min[nr] = FAN_TO_REG(results[0],
18333 +                                                      DIV_FROM_REG(data->
18334 +                                                                   fan_div
18335 +                                                                   [nr]));
18336 +                       old =
18337 +                           gl520_read_value(client, GL520_REG_FAN_LIMIT);
18338 +
18339 +                       if (nr == 0) {
18340 +                               old =
18341 +                                   (old & 0x00ff) | (data->
18342 +                                                     fan_min[nr] << 8);
18343 +                               if (results[0] == 0)
18344 +                                       data->alarm_mask &= ~0x20;
18345 +                               else
18346 +                                       data->alarm_mask |= 0x20;
18347 +                       } else {
18348 +                               old = (old & 0xff00) | data->fan_min[nr];
18349 +                               if (results[0] == 0)
18350 +                                       data->alarm_mask &= ~0x40;
18351 +                               else
18352 +                                       data->alarm_mask |= 0x40;
18353 +                       }
18354 +                       gl520_write_value(client, GL520_REG_FAN_LIMIT,
18355 +                                         old);
18356 +               }
18357 +       }
18358 +}
18359 +
18360 +
18361 +void gl520_alarms(struct i2c_client *client, int operation, int ctl_name,
18362 +                 int *nrels_mag, long *results)
18363 +{
18364 +       struct gl520_data *data = client->data;
18365 +       if (operation == SENSORS_PROC_REAL_INFO)
18366 +               *nrels_mag = 0;
18367 +       else if (operation == SENSORS_PROC_REAL_READ) {
18368 +               gl520_update_client(client);
18369 +               results[0] = ALARMS_FROM_REG(data->alarms);
18370 +               *nrels_mag = 1;
18371 +       }
18372 +}
18373 +
18374 +void gl520_beep(struct i2c_client *client, int operation, int ctl_name,
18375 +               int *nrels_mag, long *results)
18376 +{
18377 +       struct gl520_data *data = client->data;
18378 +       if (operation == SENSORS_PROC_REAL_INFO)
18379 +               *nrels_mag = 0;
18380 +       else if (operation == SENSORS_PROC_REAL_READ) {
18381 +               gl520_update_client(client);
18382 +               results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable);
18383 +               results[1] = BEEPS_FROM_REG(data->beeps);
18384 +               *nrels_mag = 2;
18385 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
18386 +               if (*nrels_mag >= 1) {
18387 +                       data->beep_enable = BEEP_ENABLE_TO_REG(results[0]);
18388 +                       gl520_write_value(client, GL520_REG_CONF,
18389 +                                         (gl520_read_value(client,
18390 +                                                           GL520_REG_CONF)
18391 +                                          & 0xfb) | (data->
18392 +                                                     beep_enable << 2));
18393 +               }
18394 +               if (*nrels_mag >= 2) {
18395 +                       data->beeps =
18396 +                           BEEPS_TO_REG(results[1]) & data->alarm_mask;
18397 +                       gl520_write_value(client, GL520_REG_ALARM,
18398 +                                         data->beeps);
18399 +               }
18400 +       }
18401 +}
18402 +
18403 +
18404 +void gl520_fan_div(struct i2c_client *client, int operation, int ctl_name,
18405 +                  int *nrels_mag, long *results)
18406 +{
18407 +       struct gl520_data *data = client->data;
18408 +       int old;
18409 +       if (operation == SENSORS_PROC_REAL_INFO)
18410 +               *nrels_mag = 0;
18411 +       else if (operation == SENSORS_PROC_REAL_READ) {
18412 +               gl520_update_client(client);
18413 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
18414 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
18415 +               *nrels_mag = 2;
18416 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
18417 +               old = gl520_read_value(client, GL520_REG_MISC);
18418 +               if (*nrels_mag >= 2) {
18419 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
18420 +                       old = (old & 0xcf) | (data->fan_div[1] << 4);
18421 +               }
18422 +               if (*nrels_mag >= 1) {
18423 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
18424 +                       old = (old & 0x3f) | (data->fan_div[0] << 6);
18425 +               }
18426 +               gl520_write_value(client, GL520_REG_MISC, old);
18427 +       }
18428 +}
18429 +
18430 +void gl520_vid(struct i2c_client *client, int operation, int ctl_name,
18431 +              int *nrels_mag, long *results)
18432 +{
18433 +       struct gl520_data *data = client->data;
18434 +       if (operation == SENSORS_PROC_REAL_INFO)
18435 +               *nrels_mag = 2;
18436 +       else if (operation == SENSORS_PROC_REAL_READ) {
18437 +               gl520_update_client(client);
18438 +               results[0] = VID_FROM_REG(data->vid);
18439 +               *nrels_mag = 1;
18440 +       }
18441 +}
18442 +
18443 +void gl520_fan1off(struct i2c_client *client, int operation, int ctl_name,
18444 +                  int *nrels_mag, long *results)
18445 +{
18446 +       int old;
18447 +       if (operation == SENSORS_PROC_REAL_INFO)
18448 +               *nrels_mag = 0;
18449 +       else if (operation == SENSORS_PROC_REAL_READ) {
18450 +               results[0] =
18451 +                   ((gl520_read_value(client, GL520_REG_MISC) & 0x04) !=
18452 +                    0);
18453 +               *nrels_mag = 1;
18454 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
18455 +               if (*nrels_mag >= 1) {
18456 +                       old =
18457 +                           gl520_read_value(client,
18458 +                                            GL520_REG_MISC) & 0xfb;
18459 +                       if (results[0])
18460 +                               old |= 0x04;
18461 +                       gl520_write_value(client, GL520_REG_MISC, old);
18462 +               }
18463 +       }
18464 +}
18465 +
18466 +void gl520_config(struct i2c_client *client, int operation, int ctl_name,
18467 +                 int *nrels_mag, long *results)
18468 +{
18469 +       struct gl520_data *data = client->data;
18470 +       int old;
18471 +       if (operation == SENSORS_PROC_REAL_INFO)
18472 +               *nrels_mag = 0;
18473 +       else if (operation == SENSORS_PROC_REAL_READ) {
18474 +               results[0] =
18475 +                   ((gl520_read_value(client, GL520_REG_CONF) & 0x10) ==
18476 +                    0);
18477 +               data->two_temps = results[0];
18478 +               *nrels_mag = 1;
18479 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
18480 +               if (*nrels_mag >= 1) {
18481 +                       old =
18482 +                           gl520_read_value(client,
18483 +                                            GL520_REG_CONF) & 0xef;
18484 +                       if (!results[1]) {
18485 +                               old |= 0x10;
18486 +                               data->two_temps = 0;
18487 +                               data->temp_hyst[1] = data->temp_over[1] =
18488 +                                       data->temp[1] = 0;
18489 +                       } else {
18490 +                               data->two_temps = 1;
18491 +                               data->voltage_max[4] = data->voltage_min[4] =
18492 +                                       data->voltage[4] = 0;
18493 +                       }
18494 +                       gl520_write_value(client, GL520_REG_CONF, old);
18495 +               }
18496 +       }
18497 +}
18498 +
18499 +static int __init sm_gl520sm_init(void)
18500 +{
18501 +       printk("gl520sm.o version %s (%s)\n", LM_VERSION, LM_DATE);
18502 +       return i2c_add_driver(&gl520_driver);
18503 +}
18504 +
18505 +static void __exit sm_gl520sm_exit(void)
18506 +{
18507 +       i2c_del_driver(&gl520_driver);
18508 +}
18509 +
18510 +
18511 +
18512 +MODULE_AUTHOR
18513 +    ("Frodo Looijaard <frodol@dds.nl> and Kyösti Mälkki <kmalkki@cc.hut.fi>");
18514 +MODULE_DESCRIPTION("GL520SM driver");
18515 +
18516 +module_init(sm_gl520sm_init);
18517 +module_exit(sm_gl520sm_exit);
18518 --- linux-old/drivers/sensors/it87.c    Thu Jan  1 00:00:00 1970
18519 +++ linux/drivers/sensors/it87.c        Mon Dec 13 20:18:47 2004
18520 @@ -0,0 +1,1128 @@
18521 +/*
18522 +    it87.c - Part of lm_sensors, Linux kernel modules for hardware
18523 +             monitoring.
18524 +
18525 +    Supports: IT8705F  Super I/O chip w/LPC interface
18526 +              IT8712F  Super I/O chup w/LPC interface & SMbus
18527 +              Sis950   A clone of the IT8705F
18528 +
18529 +    Copyright (c) 2001 Chris Gauthron <chrisg@0-in.com> 
18530 +    Largely inspired by lm78.c of the same package
18531 +
18532 +    This program is free software; you can redistribute it and/or modify
18533 +    it under the terms of the GNU General Public License as published by
18534 +    the Free Software Foundation; either version 2 of the License, or
18535 +    (at your option) any later version.
18536 +
18537 +    This program is distributed in the hope that it will be useful,
18538 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
18539 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18540 +    GNU General Public License for more details.
18541 +
18542 +    You should have received a copy of the GNU General Public License
18543 +    along with this program; if not, write to the Free Software
18544 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18545 +*/
18546 +
18547 +/*
18548 +    djg@pdp8.net David Gesswein 7/18/01
18549 +    Modified to fix bug with not all alarms enabled.
18550 +    Added ability to read battery voltage and select temperature sensor
18551 +    type at module load time.
18552 +*/
18553 +
18554 +/*
18555 +    michael.hufer@gmx.de Michael Hufer 09/07/03
18556 +    Modified configure (enable/disable) chip reset at module load time.
18557 +    Added ability to read and set fan pwm registers and the smart
18558 +    guardian (sg) features of the chip.
18559 +*/
18560 +
18561 +#include <linux/module.h>
18562 +#include <linux/slab.h>
18563 +#include <linux/ioport.h>
18564 +#include <linux/i2c.h>
18565 +#include <linux/i2c-proc.h>
18566 +#include <linux/init.h>
18567 +#include <asm/io.h>
18568 +#define LM_DATE "20041007"
18569 +#define LM_VERSION "2.8.8"
18570 +
18571 +MODULE_LICENSE("GPL");
18572 +
18573 +/* Addresses to scan */
18574 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
18575 +static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
18576 +static unsigned int normal_isa[] = { 0x0290, SENSORS_ISA_END };
18577 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
18578 +
18579 +/* Insmod parameters */
18580 +SENSORS_INSMOD_4(it87, it8705, it8712, sis950);
18581 +
18582 +
18583 +#define        REG     0x2e    /* The register to read/write */
18584 +#define        DEV     0x07    /* Register: Logical device select */
18585 +#define        VAL     0x2f    /* The value to read/write */
18586 +#define PME    0x04    /* The device with the fan registers in it */
18587 +#define        DEVID   0x20    /* Register: Device ID */
18588 +
18589 +static inline void
18590 +superio_outb(int reg, int val)
18591 +{
18592 +       outb(reg, REG);
18593 +       outb(val, VAL);
18594 +}
18595 +
18596 +static inline int
18597 +superio_inb(int reg)
18598 +{
18599 +       outb(reg, REG);
18600 +       return inb(VAL);
18601 +}
18602 +
18603 +static inline void
18604 +superio_select(void)
18605 +{
18606 +       outb(DEV, REG);
18607 +       outb(PME, VAL);
18608 +}
18609 +
18610 +static inline void
18611 +superio_enter(void)
18612 +{
18613 +       outb(0x87, REG);
18614 +       outb(0x01, REG);
18615 +       outb(0x55, REG);
18616 +       outb(0x55, REG);
18617 +}
18618 +
18619 +static inline void
18620 +superio_exit(void)
18621 +{
18622 +       outb(0x02, REG);
18623 +       outb(0x02, VAL);
18624 +}
18625 +
18626 +/* just IT8712F for now - this should be extended to support the other
18627 +   chips as well */
18628 +#define IT87_DEVID_MATCH(id) ((id) == 0x8712)
18629 +
18630 +#define IT87_ACT_REG  0x30
18631 +#define IT87_BASE_REG 0x60
18632 +
18633 +/* Update battery voltage after every reading if true */
18634 +static int update_vbat = 0;
18635 +
18636 +/* Reset the registers on init */
18637 +static int reset = 0;
18638 +
18639 +/* Many IT87 constants specified below */
18640 +
18641 +/* Length of ISA address segment */
18642 +#define IT87_EXTENT 8
18643 +
18644 +/* Where are the ISA address/data registers relative to the base address */
18645 +#define IT87_ADDR_REG_OFFSET 5
18646 +#define IT87_DATA_REG_OFFSET 6
18647 +
18648 +/*----- The IT87 registers -----*/
18649 +
18650 +#define IT87_REG_CONFIG        0x00
18651 +
18652 +#define IT87_REG_ALARM1        0x01
18653 +#define IT87_REG_ALARM2        0x02
18654 +#define IT87_REG_ALARM3        0x03
18655 +
18656 +#define IT87_REG_VID           0x0a
18657 +#define IT87_REG_FAN_DIV       0x0b
18658 +
18659 +#define IT87_REG_FAN(nr)       (0x0c + (nr))
18660 +#define IT87_REG_FAN_MIN(nr)   (0x0f + (nr))
18661 +#define IT87_REG_FAN_CTRL      0x13
18662 +
18663 +/* pwm and smart guardian registers */
18664 +
18665 +#define IT87_REG_FAN_ONOFF     0x14
18666 +#define IT87_REG_PWM(nr)       (0x14 + (nr))
18667 +#define IT87_REG_SG_TL_OFF(nr) (0x58 + (nr)*8)
18668 +#define IT87_REG_SG_TL_LOW(nr) (0x59 + (nr)*8)
18669 +#define IT87_REG_SG_TL_MED(nr) (0x5a + (nr)*8)
18670 +#define IT87_REG_SG_TL_HI(nr)  (0x5b + (nr)*8)
18671 +#define IT87_REG_SG_TL_OVR(nr) (0x5c + (nr)*8)
18672 +#define IT87_REG_SG_PWM_LOW(nr) (0x5d + (nr)*8)
18673 +#define IT87_REG_SG_PWM_MED(nr) (0x5e + (nr)*8)
18674 +#define IT87_REG_SG_PWM_HI(nr)  (0x5f + (nr)*8)
18675 +
18676 +/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
18677 +
18678 +#define IT87_REG_VIN(nr)       (0x20 + (nr))
18679 +#define IT87_REG_TEMP(nr)      (0x28 + (nr))
18680 +
18681 +#define IT87_REG_VIN_MAX(nr)   (0x30 + (nr) * 2)
18682 +#define IT87_REG_VIN_MIN(nr)   (0x31 + (nr) * 2)
18683 +#define IT87_REG_TEMP_HIGH(nr) (0x3e + (nr) * 2)
18684 +#define IT87_REG_TEMP_LOW(nr)  (0x3f + (nr) * 2)
18685 +
18686 +#define IT87_REG_I2C_ADDR      0x48
18687 +
18688 +#define IT87_REG_VIN_ENABLE    0x50
18689 +#define IT87_REG_TEMP_ENABLE   0x51
18690 +
18691 +#define IT87_REG_CHIPID        0x58
18692 +
18693 +/* sensor pin types */
18694 +#define UNUSED         0
18695 +#define THERMISTOR     2
18696 +#define PIIDIODE       3
18697 +
18698 +/* Conversions. Limit checking is only done on the TO_REG 
18699 +   variants. Note that you should be a bit careful with which arguments
18700 +   these macros are called: arguments may be evaluated more than once.
18701 +   Fixing this is just not worth it. */
18702 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
18703 +#define IN_FROM_REG(val) (((val) *  16 + 5) / 10)
18704 +
18705 +static inline u8 FAN_TO_REG(long rpm, int div)
18706 +{
18707 +       if (rpm == 0)
18708 +               return 255;
18709 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
18710 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
18711 +                            254);
18712 +}
18713 +
18714 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
18715 +
18716 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
18717 +                                                 ((val)+5)/10),-127,127))
18718 +#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
18719 +
18720 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
18721 +                           205-(val)*5)
18722 +#define ALARMS_FROM_REG(val) (val)
18723 +
18724 +extern inline u8 DIV_TO_REG(long val)
18725 +{
18726 +       u8 i;
18727 +       for( i = 0; i <= 7; i++ )
18728 +       {
18729 +               if( val>>i == 1 )
18730 +                       return i;
18731 +       }
18732 +       return 1;
18733 +}
18734 +#define DIV_FROM_REG(val) (1 << (val))
18735 +
18736 +/* For each registered IT87, we need to keep some data in memory. That
18737 +   data is pointed to by it87_list[NR]->data. The structure itself is
18738 +   dynamically allocated, at the same time when a new it87 client is
18739 +   allocated. */
18740 +struct it87_data {
18741 +       struct i2c_client client;
18742 +       struct semaphore lock;
18743 +       int sysctl_id;
18744 +       enum chips type;
18745 +
18746 +       struct semaphore update_lock;
18747 +       char valid;             /* !=0 if following fields are valid */
18748 +       unsigned long last_updated;     /* In jiffies */
18749 +
18750 +       u8 in[9];               /* Register value */
18751 +       u8 in_max[9];           /* Register value */
18752 +       u8 in_min[9];           /* Register value */
18753 +       u8 fan[3];              /* Register value */
18754 +       u8 fan_min[3];          /* Register value */
18755 +       u8 temp[3];             /* Register value */
18756 +       u8 temp_high[3];        /* Register value */
18757 +       u8 temp_low[3];         /* Register value */
18758 +       u8 fan_div[3];          /* Register encoding, shifted right */
18759 +       u8 vid;                 /* Register encoding, combined */
18760 +       u32 alarms;             /* Register encoding, combined */
18761 +       u8 pwm[3];              /* Register value */
18762 +       u8 fan_ctl[2];          /* Register encoding */
18763 +       u8 sg_tl[3][5];         /* Register value */
18764 +       u8 sg_pwm[3][3];        /* Register value */
18765 +       u8 sens[3];             /* 2 = Thermistor,
18766 +                                  3 = PII/Celeron diode */
18767 +};
18768 +
18769 +
18770 +static int it87_attach_adapter(struct i2c_adapter *adapter);
18771 +static int it87_find(int *address);
18772 +static int it87_detect(struct i2c_adapter *adapter, int address,
18773 +                      unsigned short flags, int kind);
18774 +static int it87_detach_client(struct i2c_client *client);
18775 +
18776 +static int it87_read_value(struct i2c_client *client, u8 register);
18777 +static int it87_write_value(struct i2c_client *client, u8 register,
18778 +                           u8 value);
18779 +static void it87_update_client(struct i2c_client *client);
18780 +static void it87_init_client(struct i2c_client *client);
18781 +
18782 +
18783 +static void it87_in(struct i2c_client *client, int operation, int ctl_name,
18784 +                   int *nrels_mag, long *results);
18785 +static void it87_fan(struct i2c_client *client, int operation,
18786 +                    int ctl_name, int *nrels_mag, long *results);
18787 +static void it87_temp(struct i2c_client *client, int operation,
18788 +                     int ctl_name, int *nrels_mag, long *results);
18789 +static void it87_vid(struct i2c_client *client, int operation,
18790 +                    int ctl_name, int *nrels_mag, long *results);
18791 +static void it87_alarms(struct i2c_client *client, int operation,
18792 +                           int ctl_name, int *nrels_mag, long *results);
18793 +static void it87_fan_div(struct i2c_client *client, int operation,
18794 +                        int ctl_name, int *nrels_mag, long *results);
18795 +static void it87_fan_ctl(struct i2c_client *client, int operation,
18796 +                        int ctl_name, int *nrels_mag, long *results);
18797 +static void it87_pwm(struct i2c_client *client, int operation,
18798 +                        int ctl_name, int *nrels_mag, long *results);
18799 +static void it87_sgpwm(struct i2c_client *client, int operation,
18800 +                        int ctl_name, int *nrels_mag, long *results);
18801 +static void it87_sgtl(struct i2c_client *client, int operation,
18802 +                        int ctl_name, int *nrels_mag, long *results);
18803 +static void it87_sens(struct i2c_client *client, int operation,
18804 +                        int ctl_name, int *nrels_mag, long *results);
18805 +
18806 +static struct i2c_driver it87_driver = {
18807 +       .owner          = THIS_MODULE,
18808 +       .name           = "IT87xx sensor driver",
18809 +       .id             = I2C_DRIVERID_IT87,
18810 +       .flags          = I2C_DF_NOTIFY,
18811 +       .attach_adapter = it87_attach_adapter,
18812 +       .detach_client  = it87_detach_client,
18813 +};
18814 +
18815 +static int it87_id = 0;
18816 +
18817 +/* The /proc/sys entries */
18818 +
18819 +/* -- SENSORS SYSCTL START -- */
18820 +#define IT87_SYSCTL_IN0 1000    /* Volts * 100 */
18821 +#define IT87_SYSCTL_IN1 1001
18822 +#define IT87_SYSCTL_IN2 1002
18823 +#define IT87_SYSCTL_IN3 1003
18824 +#define IT87_SYSCTL_IN4 1004
18825 +#define IT87_SYSCTL_IN5 1005
18826 +#define IT87_SYSCTL_IN6 1006
18827 +#define IT87_SYSCTL_IN7 1007
18828 +#define IT87_SYSCTL_IN8 1008
18829 +#define IT87_SYSCTL_FAN1 1101   /* Rotations/min */
18830 +#define IT87_SYSCTL_FAN2 1102
18831 +#define IT87_SYSCTL_FAN3 1103
18832 +#define IT87_SYSCTL_TEMP1 1200  /* Degrees Celcius * 10 */
18833 +#define IT87_SYSCTL_TEMP2 1201  /* Degrees Celcius * 10 */
18834 +#define IT87_SYSCTL_TEMP3 1202  /* Degrees Celcius * 10 */
18835 +#define IT87_SYSCTL_VID 1300    /* Volts * 100 */
18836 +#define IT87_SYSCTL_FAN_DIV 2000        /* 1, 2, 4 or 8 */
18837 +#define IT87_SYSCTL_ALARMS 2004    /* bitvector */
18838 +
18839 +#define IT87_SYSCTL_PWM1 1401
18840 +#define IT87_SYSCTL_PWM2 1402
18841 +#define IT87_SYSCTL_PWM3 1403
18842 +#define IT87_SYSCTL_FAN_CTL  1501
18843 +#define IT87_SYSCTL_FAN_ON_OFF  1502
18844 +#define IT87_SYSCTL_SENS1 1601 /* 1, 2, or Beta (3000-5000) */
18845 +#define IT87_SYSCTL_SENS2 1602
18846 +#define IT87_SYSCTL_SENS3 1603
18847 +
18848 +#define IT87_ALARM_IN0 0x000100
18849 +#define IT87_ALARM_IN1 0x000200
18850 +#define IT87_ALARM_IN2 0x000400
18851 +#define IT87_ALARM_IN3 0x000800
18852 +#define IT87_ALARM_IN4 0x001000
18853 +#define IT87_ALARM_IN5 0x002000
18854 +#define IT87_ALARM_IN6 0x004000
18855 +#define IT87_ALARM_IN7 0x008000
18856 +#define IT87_ALARM_FAN1 0x0001
18857 +#define IT87_ALARM_FAN2 0x0002
18858 +#define IT87_ALARM_FAN3 0x0004
18859 +#define IT87_ALARM_TEMP1 0x00010000
18860 +#define IT87_ALARM_TEMP2 0x00020000
18861 +#define IT87_ALARM_TEMP3 0x00040000
18862 +
18863 +/* -- SENSORS SYSCTL END -- */
18864 +
18865 +/* These files are created for each detected IT87. This is just a template;
18866 +   though at first sight, you might think we could use a statically
18867 +   allocated list, we need some way to get back to the parent - which
18868 +   is done through one of the 'extra' fields which are initialized 
18869 +   when a new copy is allocated. */
18870 +static ctl_table it87_dir_table_template[] = {
18871 +       {IT87_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
18872 +        &i2c_sysctl_real, NULL, &it87_in},
18873 +       {IT87_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
18874 +        &i2c_sysctl_real, NULL, &it87_in},
18875 +       {IT87_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
18876 +        &i2c_sysctl_real, NULL, &it87_in},
18877 +       {IT87_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
18878 +        &i2c_sysctl_real, NULL, &it87_in},
18879 +       {IT87_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
18880 +        &i2c_sysctl_real, NULL, &it87_in},
18881 +       {IT87_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
18882 +        &i2c_sysctl_real, NULL, &it87_in},
18883 +       {IT87_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
18884 +        &i2c_sysctl_real, NULL, &it87_in},
18885 +       {IT87_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
18886 +        &i2c_sysctl_real, NULL, &it87_in},
18887 +       {IT87_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
18888 +        &i2c_sysctl_real, NULL, &it87_in},
18889 +       {IT87_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
18890 +        &i2c_sysctl_real, NULL, &it87_fan},
18891 +       {IT87_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
18892 +        &i2c_sysctl_real, NULL, &it87_fan},
18893 +       {IT87_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
18894 +        &i2c_sysctl_real, NULL, &it87_fan},
18895 +       {IT87_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
18896 +        &i2c_sysctl_real, NULL, &it87_temp},
18897 +       {IT87_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
18898 +        &i2c_sysctl_real, NULL, &it87_temp},
18899 +       {IT87_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
18900 +        &i2c_sysctl_real, NULL, &it87_temp},
18901 +       {IT87_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
18902 +        &i2c_sysctl_real, NULL, &it87_vid},
18903 +       {IT87_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
18904 +        &i2c_sysctl_real, NULL, &it87_fan_div},
18905 +       {IT87_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
18906 +        &i2c_sysctl_real, NULL, &it87_alarms},
18907 +       {IT87_SYSCTL_FAN_CTL, "fan_ctl", NULL, 0, 0644, NULL, &i2c_proc_real,
18908 +        &i2c_sysctl_real, NULL, &it87_fan_ctl},
18909 +       {IT87_SYSCTL_FAN_ON_OFF, "fan_on_off", NULL, 0, 0644, NULL, &i2c_proc_real,
18910 +        &i2c_sysctl_real, NULL, &it87_fan_ctl},
18911 +       {IT87_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
18912 +        &i2c_sysctl_real, NULL, &it87_pwm},
18913 +       {IT87_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
18914 +        &i2c_sysctl_real, NULL, &it87_pwm},
18915 +       {IT87_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
18916 +        &i2c_sysctl_real, NULL, &it87_pwm},
18917 +       {IT87_SYSCTL_PWM1, "sg_pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
18918 +        &i2c_sysctl_real, NULL, &it87_sgpwm},
18919 +       {IT87_SYSCTL_PWM2, "sg_pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
18920 +        &i2c_sysctl_real, NULL, &it87_sgpwm},
18921 +       {IT87_SYSCTL_PWM3, "sg_pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
18922 +        &i2c_sysctl_real, NULL, &it87_sgpwm},
18923 +       {IT87_SYSCTL_PWM1, "sg_tl1", NULL, 0, 0644, NULL, &i2c_proc_real,
18924 +        &i2c_sysctl_real, NULL, &it87_sgtl},
18925 +       {IT87_SYSCTL_PWM2, "sg_tl2", NULL, 0, 0644, NULL, &i2c_proc_real,
18926 +        &i2c_sysctl_real, NULL, &it87_sgtl},
18927 +       {IT87_SYSCTL_PWM3, "sg_tl3", NULL, 0, 0644, NULL, &i2c_proc_real,
18928 +        &i2c_sysctl_real, NULL, &it87_sgtl},
18929 +       {IT87_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
18930 +        &i2c_sysctl_real, NULL, &it87_sens},
18931 +       {IT87_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
18932 +        &i2c_sysctl_real, NULL, &it87_sens},
18933 +       {IT87_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL, &i2c_proc_real,
18934 +        &i2c_sysctl_real, NULL, &it87_sens},
18935 +       {0}
18936 +};
18937 +
18938 +
18939 +/* This function is called when:
18940 +     * it87_driver is inserted (when this module is loaded), for each
18941 +       available adapter
18942 +     * when a new adapter is inserted (and it87_driver is still present) */
18943 +static int it87_attach_adapter(struct i2c_adapter *adapter)
18944 +{
18945 +       return i2c_detect(adapter, &addr_data, it87_detect);
18946 +}
18947 +
18948 +static int it87_find(int *address)
18949 +{
18950 +       u16 val;
18951 +
18952 +       superio_enter();
18953 +       val = (superio_inb(DEVID) << 8) |
18954 +              superio_inb(DEVID + 1);
18955 +       if (!IT87_DEVID_MATCH(val)) {
18956 +               superio_exit();
18957 +               return -ENODEV;
18958 +       }
18959 +
18960 +       superio_select();
18961 +       val = (superio_inb(IT87_BASE_REG) << 8) |
18962 +              superio_inb(IT87_BASE_REG + 1);
18963 +       superio_exit();
18964 +       *address = val & ~(IT87_EXTENT - 1);
18965 +       if (*address == 0) {
18966 +               return -ENODEV;
18967 +       }
18968 +       return 0;
18969 +}
18970 +
18971 +/* This function is called by i2c_detect */
18972 +int it87_detect(struct i2c_adapter *adapter, int address,
18973 +               unsigned short flags, int kind)
18974 +{
18975 +       int i;
18976 +       struct i2c_client *new_client;
18977 +       struct it87_data *data;
18978 +       int err = 0;
18979 +       const char *type_name = "";
18980 +       const char *client_name = "";
18981 +       int is_isa = i2c_is_isa_adapter(adapter);
18982 +
18983 +       if (!is_isa
18984 +        && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
18985 +               return 0;
18986 +
18987 +       if (is_isa
18988 +        && check_region(address, IT87_EXTENT))
18989 +               return 0;
18990 +
18991 +       /* Probe whether there is anything available on this address. Already
18992 +          done for SMBus clients */
18993 +       if (is_isa && kind < 0) {
18994 +#define REALLY_SLOW_IO
18995 +               /* We need the timeouts for at least some IT87-like chips.
18996 +                  But only if we read 'undefined' registers. */
18997 +               i = inb_p(address + 1);
18998 +               if (inb_p(address + 2) != i
18999 +                || inb_p(address + 3) != i
19000 +                || inb_p(address + 7) != i)
19001 +                       return -ENODEV;
19002 +#undef REALLY_SLOW_IO
19003 +
19004 +               /* Let's just hope nothing breaks here */
19005 +               i = inb_p(address + 5) & 0x7f;
19006 +               outb_p(~i & 0x7f, address + 5);
19007 +               if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
19008 +                       outb_p(i, address + 5);
19009 +                       return -ENODEV;
19010 +               }
19011 +       }
19012 +
19013 +       /* OK. For now, we presume we have a valid client. We now create the
19014 +          client structure, even though we cannot fill it completely yet.
19015 +          But it allows us to access it87_{read,write}_value. */
19016 +
19017 +       if (!(data = kmalloc(sizeof(struct it87_data), GFP_KERNEL))) {
19018 +               err = -ENOMEM;
19019 +               goto ERROR0;
19020 +       }
19021 +
19022 +       new_client = &data->client;
19023 +       if (is_isa)
19024 +               init_MUTEX(&data->lock);
19025 +       new_client->addr = address;
19026 +       new_client->data = data;
19027 +       new_client->adapter = adapter;
19028 +       new_client->driver = &it87_driver;
19029 +       new_client->flags = 0;
19030 +
19031 +       /* Now, we do the remaining detection. */
19032 +
19033 +       if (kind < 0) {
19034 +               if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
19035 +                || (!is_isa
19036 +                 && it87_read_value(new_client, IT87_REG_I2C_ADDR) != address)) {
19037 +                       err = -ENODEV;
19038 +                       goto ERROR1;
19039 +               }
19040 +       }
19041 +
19042 +       /* Determine the chip type. */
19043 +       if (kind <= 0) {
19044 +               i = it87_read_value(new_client, IT87_REG_CHIPID);
19045 +               if (i == 0x90) {
19046 +                       kind = it87;
19047 +               }
19048 +               else {
19049 +                       if (kind == 0)
19050 +                               printk
19051 +                                   ("it87.o: Ignoring 'force' parameter for unknown chip at "
19052 +                                    "adapter %d, address 0x%02x\n",
19053 +                                    i2c_adapter_id(adapter), address);
19054 +                       err = -ENODEV;
19055 +                       goto ERROR1;
19056 +               }
19057 +       }
19058 +
19059 +       if (kind == it87) {
19060 +               type_name = "it87";
19061 +               client_name = "IT87 chip";
19062 +       } /* else if (kind == it8712) {
19063 +               type_name = "it8712";
19064 +               client_name = "IT87-J chip";
19065 +       } */ else {
19066 +#ifdef DEBUG
19067 +               printk("it87.o: Internal error: unknown kind (%d)?!?",
19068 +                      kind);
19069 +#endif
19070 +               goto ERROR1;
19071 +       }
19072 +
19073 +       /* Reserve the ISA region */
19074 +       if (is_isa)
19075 +               request_region(address, IT87_EXTENT, type_name);
19076 +
19077 +       /* Fill in the remaining client fields and put it into the global list */
19078 +       strcpy(new_client->name, client_name);
19079 +       data->type = kind;
19080 +
19081 +       new_client->id = it87_id++;
19082 +       data->valid = 0;
19083 +       init_MUTEX(&data->update_lock);
19084 +
19085 +       /* Tell the I2C layer a new client has arrived */
19086 +       if ((err = i2c_attach_client(new_client)))
19087 +               goto ERROR3;
19088 +
19089 +       /* Register a new directory entry with module sensors */
19090 +       if ((i = i2c_register_entry(new_client,
19091 +                                   type_name,
19092 +                                   it87_dir_table_template)) < 0) {
19093 +               err = i;
19094 +               goto ERROR4;
19095 +       }
19096 +       data->sysctl_id = i;
19097 +
19098 +       /* Initialize the IT87 chip */
19099 +       it87_init_client(new_client);
19100 +       return 0;
19101 +
19102 +/* OK, this is not exactly good programming practice, usually. But it is
19103 +   very code-efficient in this case. */
19104 +
19105 +      ERROR4:
19106 +       i2c_detach_client(new_client);
19107 +      ERROR3:
19108 +       if (is_isa)
19109 +               release_region(address, IT87_EXTENT);
19110 +      ERROR1:
19111 +       kfree(data);
19112 +      ERROR0:
19113 +       return err;
19114 +}
19115 +
19116 +static int it87_detach_client(struct i2c_client *client)
19117 +{
19118 +       int err;
19119 +
19120 +       i2c_deregister_entry(((struct it87_data *) (client->data))->
19121 +                               sysctl_id);
19122 +
19123 +       if ((err = i2c_detach_client(client))) {
19124 +               printk
19125 +                   ("it87.o: Client deregistration failed, client not detached.\n");
19126 +               return err;
19127 +       }
19128 +
19129 +       if(i2c_is_isa_client(client))
19130 +               release_region(client->addr, IT87_EXTENT);
19131 +       kfree(client->data);
19132 +
19133 +       return 0;
19134 +}
19135 +
19136 +/* The SMBus locks itself, but ISA access must be locked explicitely! 
19137 +   We don't want to lock the whole ISA bus, so we lock each client
19138 +   separately.
19139 +   We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
19140 +   would slow down the IT87 access and should not be necessary. 
19141 +   There are some ugly typecasts here, but the good new is - they should
19142 +   nowhere else be necessary! */
19143 +static int it87_read_value(struct i2c_client *client, u8 reg)
19144 +{
19145 +       int res;
19146 +       if (i2c_is_isa_client(client)) {
19147 +               down(&(((struct it87_data *) (client->data))->lock));
19148 +               outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
19149 +               res = inb_p(client->addr + IT87_DATA_REG_OFFSET);
19150 +               up(&(((struct it87_data *) (client->data))->lock));
19151 +               return res;
19152 +       } else
19153 +               return i2c_smbus_read_byte_data(client, reg);
19154 +}
19155 +
19156 +/* The SMBus locks itself, but ISA access muse be locked explicitely! 
19157 +   We don't want to lock the whole ISA bus, so we lock each client
19158 +   separately.
19159 +   We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
19160 +   would slow down the IT87 access and should not be necessary. 
19161 +   There are some ugly typecasts here, but the good new is - they should
19162 +   nowhere else be necessary! */
19163 +static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
19164 +{
19165 +       if (i2c_is_isa_client(client)) {
19166 +               down(&(((struct it87_data *) (client->data))->lock));
19167 +               outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
19168 +               outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
19169 +               up(&(((struct it87_data *) (client->data))->lock));
19170 +               return 0;
19171 +       } else
19172 +               return i2c_smbus_write_byte_data(client, reg, value);
19173 +}
19174 +
19175 +/* Called when we have found a new IT87. */
19176 +static void it87_init_client(struct i2c_client *client)
19177 +{
19178 +       int tmp;
19179 +
19180 +       if (reset) {
19181 +               /* Reset all except Watchdog values and last conversion values
19182 +                  This sets fan-divs to 2, among others */
19183 +               it87_write_value(client, IT87_REG_CONFIG, 0x80);
19184 +       }
19185 +
19186 +       /* Check if temperature channnels are reset manually or by some reason */
19187 +       tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
19188 +       if ((tmp & 0x3f) == 0) {
19189 +               /* Temp1,Temp3=thermistor; Temp2=thermal diode */
19190 +               tmp = (tmp & 0xc0) | 0x2a;
19191 +               it87_write_value(client, IT87_REG_TEMP_ENABLE, tmp);
19192 +       }
19193 +
19194 +       /* Check if voltage monitors are reset manually or by some reason */
19195 +       tmp = it87_read_value(client, IT87_REG_VIN_ENABLE);
19196 +       if ((tmp & 0xff) == 0) {
19197 +               /* Enable all voltage monitors */
19198 +               it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff);
19199 +       }
19200 +
19201 +       /* Check if tachometers are reset manually or by some reason */
19202 +       tmp = it87_read_value(client, IT87_REG_FAN_CTRL);
19203 +       if ((tmp & 0x70) == 0) {
19204 +               /* Enable all fan tachometers */
19205 +               tmp = (tmp & 0x8f) | 0x70;
19206 +               it87_write_value(client, IT87_REG_FAN_CTRL, tmp);
19207 +       }
19208 +
19209 +       /* Start monitoring */
19210 +       it87_write_value(client, IT87_REG_CONFIG,
19211 +                        (it87_read_value(client, IT87_REG_CONFIG) & 0x36)
19212 +                        | (update_vbat ? 0x41 : 0x01));
19213 +}
19214 +
19215 +static void it87_update_client(struct i2c_client *client)
19216 +{
19217 +       struct it87_data *data = client->data;
19218 +       int i, tmp, tmp2;
19219 +
19220 +       down(&data->update_lock);
19221 +
19222 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
19223 +           (jiffies < data->last_updated) || !data->valid) {
19224 +
19225 +               if (update_vbat) {
19226 +       /* Cleared after each update, so reenable.  Value
19227 +          returned by this read will be previous value */
19228 +                       it87_write_value(client, IT87_REG_CONFIG,
19229 +                          it87_read_value(client, IT87_REG_CONFIG) | 0x40);
19230 +               }
19231 +               for (i = 0; i <= 7; i++) {
19232 +                       data->in[i] =
19233 +                           it87_read_value(client, IT87_REG_VIN(i));
19234 +                       data->in_min[i] =
19235 +                           it87_read_value(client, IT87_REG_VIN_MIN(i));
19236 +                       data->in_max[i] =
19237 +                           it87_read_value(client, IT87_REG_VIN_MAX(i));
19238 +               }
19239 +               data->in[8] =
19240 +                   it87_read_value(client, IT87_REG_VIN(8));
19241 +               /* VBAT sensor doesn't have limit registers, set
19242 +                  to min and max value */
19243 +               data->in_min[8] = 0;
19244 +               data->in_max[8] = 255;
19245 +                
19246 +               for (i = 1; i <= 3; i++) {
19247 +                       data->fan[i - 1] =
19248 +                           it87_read_value(client, IT87_REG_FAN(i));
19249 +                       data->fan_min[i - 1] =
19250 +                           it87_read_value(client, IT87_REG_FAN_MIN(i));
19251 +               }
19252 +               for (i = 1; i <= 3; i++) {
19253 +                       data->temp[i - 1] =
19254 +                           it87_read_value(client, IT87_REG_TEMP(i));
19255 +                       data->temp_high[i - 1] =
19256 +                           it87_read_value(client, IT87_REG_TEMP_HIGH(i));
19257 +                       data->temp_low[i - 1] =
19258 +                           it87_read_value(client, IT87_REG_TEMP_LOW(i));
19259 +               }
19260 +
19261 +               /* The 8705 does not have VID capability */
19262 +               /*if (data->type == it8712) {
19263 +                       data->vid = it87_read_value(client, IT87_REG_VID);
19264 +                       data->vid &= 0x1f;
19265 +               }
19266 +               else */ {
19267 +                       data->vid = 0x1f;
19268 +               }
19269 +
19270 +               i = it87_read_value(client, IT87_REG_FAN_DIV);
19271 +               data->fan_div[0] = i & 0x07;
19272 +               data->fan_div[1] = (i >> 3) & 0x07;
19273 +               data->fan_div[2] = ( (i&0x40)==0x40 ? 3 : 1 );
19274 +
19275 +               for( i = 1; i <= 3; i++ ) {
19276 +                       data->pwm[i-1] = it87_read_value(client, IT87_REG_PWM(i));
19277 +                       data->sg_tl[i-1][0] = it87_read_value(client, IT87_REG_SG_TL_OFF(i));
19278 +                       data->sg_tl[i-1][1] = it87_read_value(client, IT87_REG_SG_TL_LOW(i));
19279 +                       data->sg_tl[i-1][2] = it87_read_value(client, IT87_REG_SG_TL_MED(i));
19280 +                       data->sg_tl[i-1][3] = it87_read_value(client, IT87_REG_SG_TL_HI(i));
19281 +                       data->sg_tl[i-1][4] = it87_read_value(client, IT87_REG_SG_TL_OVR(i));
19282 +                       data->sg_pwm[i-1][0] = it87_read_value(client, IT87_REG_SG_PWM_LOW(i));
19283 +                       data->sg_pwm[i-1][1] = it87_read_value(client, IT87_REG_SG_PWM_MED(i));
19284 +                       data->sg_pwm[i-1][2] = it87_read_value(client, IT87_REG_SG_PWM_HI(i));
19285 +               }
19286 +               data->alarms =
19287 +                       it87_read_value(client, IT87_REG_ALARM1) |
19288 +                       (it87_read_value(client, IT87_REG_ALARM2) << 8) |
19289 +                       (it87_read_value(client, IT87_REG_ALARM3) << 16);
19290 +               data->fan_ctl[0] = it87_read_value(client, IT87_REG_FAN_CTRL);
19291 +               data->fan_ctl[1] = it87_read_value(client, IT87_REG_FAN_ONOFF);
19292 +
19293 +               tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
19294 +               for(i = 0; i < 3; i++) {
19295 +                       tmp2 = (tmp >> i) & 0x09;
19296 +                       if(tmp2 == 0x01)
19297 +                               data->sens[i] = PIIDIODE;
19298 +                       else if(tmp2 == 0x08)
19299 +                               data->sens[i] = THERMISTOR;
19300 +                       else
19301 +                               data->sens[i] = UNUSED;
19302 +               }
19303 +
19304 +               data->last_updated = jiffies;
19305 +               data->valid = 1;
19306 +       }
19307 +
19308 +       up(&data->update_lock);
19309 +}
19310 +
19311 +
19312 +/* The next few functions are the call-back functions of the /proc/sys and
19313 +   sysctl files. Which function is used is defined in the ctl_table in
19314 +   the extra1 field.
19315 +    - Each function must return the magnitude (power of 10 to divide the
19316 +      data with) if it is called with operation==SENSORS_PROC_REAL_INFO.
19317 +    - It must put a maximum of *nrels elements in results reflecting the
19318 +      data of this file, and set *nrels to the number it actually put 
19319 +      in it, if operation==SENSORS_PROC_REAL_READ.
19320 +    - Finally, it must get upto *nrels elements from results and write them
19321 +      to the chip, if operations==SENSORS_PROC_REAL_WRITE.
19322 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
19323 +   large enough (by checking the incoming value of *nrels). This is not very
19324 +   good practice, but as long as you put less than about 5 values in results,
19325 +   you can assume it is large enough. */
19326 +void it87_in(struct i2c_client *client, int operation, int ctl_name,
19327 +            int *nrels_mag, long *results)
19328 +{
19329 +       struct it87_data *data = client->data;
19330 +       int nr = ctl_name - IT87_SYSCTL_IN0;
19331 +
19332 +       if (operation == SENSORS_PROC_REAL_INFO)
19333 +               *nrels_mag = 2;
19334 +       else if (operation == SENSORS_PROC_REAL_READ) {
19335 +               it87_update_client(client);
19336 +               results[0] = IN_FROM_REG(data->in_min[nr]);
19337 +               results[1] = IN_FROM_REG(data->in_max[nr]);
19338 +               results[2] = IN_FROM_REG(data->in[nr]);
19339 +               *nrels_mag = 3;
19340 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19341 +               if (*nrels_mag >= 1) {
19342 +                       data->in_min[nr] = IN_TO_REG(results[0]);
19343 +                       it87_write_value(client, IT87_REG_VIN_MIN(nr),
19344 +                                        data->in_min[nr]);
19345 +               }
19346 +               if (*nrels_mag >= 2) {
19347 +                       data->in_max[nr] = IN_TO_REG(results[1]);
19348 +                       it87_write_value(client, IT87_REG_VIN_MAX(nr),
19349 +                                        data->in_max[nr]);
19350 +               }
19351 +       }
19352 +}
19353 +
19354 +void it87_fan(struct i2c_client *client, int operation, int ctl_name,
19355 +             int *nrels_mag, long *results)
19356 +{
19357 +       struct it87_data *data = client->data;
19358 +       int nr = ctl_name - IT87_SYSCTL_FAN1 + 1;
19359 +
19360 +       if (operation == SENSORS_PROC_REAL_INFO)
19361 +               *nrels_mag = 0;
19362 +       else if (operation == SENSORS_PROC_REAL_READ) {
19363 +               it87_update_client(client);
19364 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
19365 +                                         DIV_FROM_REG(data->fan_div[nr - 1]));
19366 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
19367 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
19368 +               *nrels_mag = 2;
19369 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19370 +               if (*nrels_mag >= 1) {
19371 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0],
19372 +                                                          DIV_FROM_REG(data->fan_div[nr - 1]));
19373 +                       it87_write_value(client, IT87_REG_FAN_MIN(nr),
19374 +                                        data->fan_min[nr - 1]);
19375 +               }
19376 +       }
19377 +}
19378 +
19379 +
19380 +void it87_temp(struct i2c_client *client, int operation, int ctl_name,
19381 +              int *nrels_mag, long *results)
19382 +{
19383 +       struct it87_data *data = client->data;
19384 +       int nr = ctl_name - IT87_SYSCTL_TEMP1 + 1;
19385 +       if (operation == SENSORS_PROC_REAL_INFO)
19386 +               *nrels_mag = 1;
19387 +       else if (operation == SENSORS_PROC_REAL_READ) {
19388 +               it87_update_client(client);
19389 +               results[0] = TEMP_FROM_REG(data->temp_high[nr - 1]);
19390 +               results[1] = TEMP_FROM_REG(data->temp_low[nr - 1]);
19391 +               results[2] = TEMP_FROM_REG(data->temp[nr - 1]);
19392 +               *nrels_mag = 3;
19393 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19394 +               if (*nrels_mag >= 1) {
19395 +                       data->temp_high[nr - 1] = TEMP_TO_REG(results[0]);
19396 +                       it87_write_value(client, IT87_REG_TEMP_HIGH(nr),
19397 +                                        data->temp_high[nr - 1]);
19398 +               }
19399 +               if (*nrels_mag >= 2) {
19400 +                       data->temp_low[nr - 1] = TEMP_TO_REG(results[1]);
19401 +                       it87_write_value(client, IT87_REG_TEMP_LOW(nr),
19402 +                                        data->temp_low[nr - 1]);
19403 +               }
19404 +       }
19405 +}
19406 +
19407 +void it87_pwm(struct i2c_client *client, int operation, int ctl_name,
19408 +              int *nrels_mag, long *results)
19409 +{
19410 +       struct it87_data *data = client->data;
19411 +       int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
19412 +       if (operation == SENSORS_PROC_REAL_INFO)
19413 +               *nrels_mag = 0;
19414 +       else if (operation == SENSORS_PROC_REAL_READ) {
19415 +               it87_update_client(client);
19416 +               results[0] = data->pwm[nr - 1];
19417 +               *nrels_mag = 1;
19418 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19419 +               if (*nrels_mag >= 1) {
19420 +                       data->pwm[nr - 1] = results[0];
19421 +                       it87_write_value(client, IT87_REG_PWM(nr), data->pwm[nr - 1]);
19422 +               }
19423 +       }
19424 +}
19425 +
19426 +void it87_sgpwm(struct i2c_client *client, int operation, int ctl_name,
19427 +              int *nrels_mag, long *results)
19428 +{
19429 +       struct it87_data *data = client->data;
19430 +       int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
19431 +       if (operation == SENSORS_PROC_REAL_INFO)
19432 +               *nrels_mag = 0;
19433 +       else if (operation == SENSORS_PROC_REAL_READ) {
19434 +               it87_update_client(client);
19435 +               results[0] = data->sg_pwm[nr - 1][0];
19436 +               results[1] = data->sg_pwm[nr - 1][1];
19437 +               results[2] = data->sg_pwm[nr - 1][2];
19438 +               *nrels_mag = 3;
19439 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19440 +               if (*nrels_mag >= 1) {
19441 +                       data->sg_pwm[nr - 1][0] = results[0];
19442 +                       it87_write_value(client, IT87_REG_SG_PWM_LOW(nr), data->sg_pwm[nr - 1][0]);
19443 +               }
19444 +               if (*nrels_mag >= 2) {
19445 +                       data->sg_pwm[nr - 1][1] = results[1];
19446 +                       it87_write_value(client, IT87_REG_SG_PWM_MED(nr), data->sg_pwm[nr - 1][1]);
19447 +               }
19448 +               if (*nrels_mag >= 3) {
19449 +                       data->sg_pwm[nr - 1][2] = results[2];
19450 +                       it87_write_value(client, IT87_REG_SG_PWM_HI(nr), data->sg_pwm[nr - 1][2]);
19451 +               }
19452 +       }
19453 +}
19454 +
19455 +void it87_sgtl(struct i2c_client *client, int operation, int ctl_name,
19456 +              int *nrels_mag, long *results)
19457 +{
19458 +       struct it87_data *data = client->data;
19459 +       int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
19460 +       if (operation == SENSORS_PROC_REAL_INFO)
19461 +               *nrels_mag = 1;
19462 +       else if (operation == SENSORS_PROC_REAL_READ) {
19463 +               it87_update_client(client);
19464 +               results[0] = TEMP_FROM_REG(data->sg_tl[nr - 1][0]);
19465 +               results[1] = TEMP_FROM_REG(data->sg_tl[nr - 1][1]);
19466 +               results[2] = TEMP_FROM_REG(data->sg_tl[nr - 1][2]);
19467 +               results[3] = TEMP_FROM_REG(data->sg_tl[nr - 1][3]);
19468 +               results[4] = TEMP_FROM_REG(data->sg_tl[nr - 1][4]);
19469 +               *nrels_mag = 5;
19470 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19471 +               if (*nrels_mag >= 1) {
19472 +                       data->sg_tl[nr - 1][0] = TEMP_TO_REG(results[0]);
19473 +                       it87_write_value(client, IT87_REG_SG_TL_OFF(nr), data->sg_tl[nr - 1][0]);
19474 +               }
19475 +               if (*nrels_mag >= 2) {
19476 +                       data->sg_tl[nr - 1][1] = TEMP_TO_REG(results[1]);
19477 +                       it87_write_value(client, IT87_REG_SG_TL_LOW(nr), data->sg_tl[nr - 1][1]);
19478 +               }
19479 +               if (*nrels_mag >= 3) {
19480 +                       data->sg_tl[nr - 1][2] = TEMP_TO_REG(results[2]);
19481 +                       it87_write_value(client, IT87_REG_SG_TL_MED(nr), data->sg_tl[nr - 1][2]);
19482 +               }
19483 +               if (*nrels_mag >= 4) {
19484 +                       data->sg_tl[nr - 1][3] = TEMP_TO_REG(results[3]);
19485 +                       it87_write_value(client, IT87_REG_SG_TL_HI(nr), data->sg_tl[nr - 1][3]);
19486 +               }
19487 +               if (*nrels_mag >= 5) {
19488 +                       data->sg_tl[nr - 1][4] = TEMP_TO_REG(results[4]);
19489 +                       it87_write_value(client, IT87_REG_SG_TL_OVR(nr), data->sg_tl[nr - 1][4]);
19490 +               }
19491 +       }
19492 +}
19493 +
19494 +void it87_vid(struct i2c_client *client, int operation, int ctl_name,
19495 +             int *nrels_mag, long *results)
19496 +{
19497 +       struct it87_data *data = client->data;
19498 +       if (operation == SENSORS_PROC_REAL_INFO)
19499 +               *nrels_mag = 2;
19500 +       else if (operation == SENSORS_PROC_REAL_READ) {
19501 +               it87_update_client(client);
19502 +               results[0] = VID_FROM_REG(data->vid);
19503 +               *nrels_mag = 1;
19504 +       }
19505 +}
19506 +
19507 +void it87_alarms(struct i2c_client *client, int operation,
19508 +                     int ctl_name, int *nrels_mag, long *results)
19509 +{
19510 +       struct it87_data *data = client->data;
19511 +       if (operation == SENSORS_PROC_REAL_INFO)
19512 +               *nrels_mag = 0;
19513 +       else if (operation == SENSORS_PROC_REAL_READ) {
19514 +               it87_update_client(client);
19515 +               results[0] = ALARMS_FROM_REG(data->alarms);
19516 +               *nrels_mag = 1;
19517 +       }
19518 +}
19519 +
19520 +void it87_fan_div(struct i2c_client *client, int operation, int ctl_name,
19521 +                 int *nrels_mag, long *results)
19522 +{
19523 +       struct it87_data *data = client->data;
19524 +       int old;
19525 +
19526 +       if (operation == SENSORS_PROC_REAL_INFO)
19527 +               *nrels_mag = 0;
19528 +       else if (operation == SENSORS_PROC_REAL_READ) {
19529 +               it87_update_client(client);
19530 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
19531 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
19532 +               results[2] = DIV_FROM_REG(data->fan_div[2]);;
19533 +               *nrels_mag = 3;
19534 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19535 +               old = it87_read_value(client, IT87_REG_FAN_DIV);
19536 +               if (*nrels_mag >= 3) {
19537 +                       data->fan_div[2] = DIV_TO_REG(results[2]);
19538 +                       if( data->fan[2]!=3 ) {
19539 +                               data->fan_div[2] = 1;
19540 +                               old = (old & 0xbf);
19541 +                       } else {
19542 +                               old = (old | 0x40);
19543 +                       }
19544 +               }
19545 +               if (*nrels_mag >= 2) {
19546 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
19547 +                       old = (old & 0xc3) | (data->fan_div[1] << 3);
19548 +               }
19549 +               if (*nrels_mag >= 1) {
19550 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
19551 +                       old = (old & 0xf8) | data->fan_div[0];
19552 +                       it87_write_value(client, IT87_REG_FAN_DIV, old);
19553 +               }
19554 +       }
19555 +}
19556 +
19557 +void it87_fan_ctl(struct i2c_client *client, int operation, int ctl_name,
19558 +              int *nrels_mag, long *results)
19559 +{
19560 +       struct it87_data *data = client->data;
19561 +       int index = ctl_name - IT87_SYSCTL_FAN_CTL;
19562 +       if (operation == SENSORS_PROC_REAL_INFO)
19563 +               *nrels_mag = 0;
19564 +       else if (operation == SENSORS_PROC_REAL_READ) {
19565 +               it87_update_client(client);
19566 +               results[0] = data->fan_ctl[index];
19567 +               *nrels_mag = 1;
19568 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19569 +               if (*nrels_mag >= 1) {
19570 +                       data->fan_ctl[index] = results[0];
19571 +                       if( index == 0 )
19572 +                               it87_write_value(client, IT87_REG_FAN_CTRL, data->fan_ctl[index] );
19573 +                       else
19574 +                               it87_write_value(client, IT87_REG_FAN_ONOFF, data->fan_ctl[index] );
19575 +               }
19576 +       }
19577 +}
19578 +
19579 +void it87_sens(struct i2c_client *client, int operation, int ctl_name,
19580 +                 int *nrels_mag, long *results)
19581 +{
19582 +       struct it87_data *data = client->data;
19583 +       int nr = 1 + ctl_name - IT87_SYSCTL_SENS1;
19584 +       u8 tmp, val1, val2;
19585 +
19586 +       if (operation == SENSORS_PROC_REAL_INFO)
19587 +               *nrels_mag = 0;
19588 +       else if (operation == SENSORS_PROC_REAL_READ) {
19589 +               results[0] = data->sens[nr - 1];
19590 +               *nrels_mag = 1;
19591 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19592 +               if (*nrels_mag >= 1) {
19593 +                       val1 = 0x01 << (nr - 1);
19594 +                       val2 = 0x08 << (nr - 1);
19595 +                       tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
19596 +                       switch (results[0]) {
19597 +                       case PIIDIODE:
19598 +                               tmp &= ~ val2;
19599 +                               tmp |= val1;
19600 +                               break;
19601 +                       case THERMISTOR:
19602 +                               tmp &= ~ val1;
19603 +                               tmp |= val2;
19604 +                               break;
19605 +                       case UNUSED:
19606 +                               tmp &= ~ val1;
19607 +                               tmp &= ~ val2;
19608 +                               break;
19609 +                       default:
19610 +                               printk(KERN_ERR "it87.o: Invalid sensor type %ld; "
19611 +                                      "must be 0 (unused), 2 (thermistor) "
19612 +                                      "or 3 (diode)\n", results[0]);
19613 +                               return;
19614 +                       }
19615 +                       it87_write_value(client,
19616 +                                        IT87_REG_TEMP_ENABLE, tmp);
19617 +                       data->sens[nr - 1] = results[0];
19618 +               }
19619 +       }
19620 +}
19621 +
19622 +static int __init sm_it87_init(void)
19623 +{
19624 +       int addr;
19625 +
19626 +       printk("it87.o version %s (%s)\n", LM_VERSION, LM_DATE);
19627 +       if (!it87_find(&addr)) {
19628 +               normal_isa[0] = addr;
19629 +       }
19630 +       return i2c_add_driver(&it87_driver);
19631 +}
19632 +
19633 +static void __exit sm_it87_exit(void)
19634 +{
19635 +       i2c_del_driver(&it87_driver);
19636 +}
19637 +
19638 +
19639 +
19640 +MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
19641 +MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
19642 +MODULE_PARM(update_vbat, "i");
19643 +MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
19644 +MODULE_PARM(reset, "i");
19645 +MODULE_PARM_DESC(reset, "Reset the chip's registers, default no");
19646 +
19647 +module_init(sm_it87_init);
19648 +module_exit(sm_it87_exit);
19649 --- linux-old/drivers/sensors/lm75.c    Thu Jan  1 00:00:00 1970
19650 +++ linux/drivers/sensors/lm75.c        Mon Dec 13 20:18:47 2004
19651 @@ -0,0 +1,331 @@
19652 +/*
19653 +    lm75.c - Part of lm_sensors, Linux kernel modules for hardware
19654 +             monitoring
19655 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
19656 +
19657 +    This program is free software; you can redistribute it and/or modify
19658 +    it under the terms of the GNU General Public License as published by
19659 +    the Free Software Foundation; either version 2 of the License, or
19660 +    (at your option) any later version.
19661 +
19662 +    This program is distributed in the hope that it will be useful,
19663 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
19664 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19665 +    GNU General Public License for more details.
19666 +
19667 +    You should have received a copy of the GNU General Public License
19668 +    along with this program; if not, write to the Free Software
19669 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19670 +*/
19671 +
19672 +#include <linux/module.h>
19673 +#include <linux/slab.h>
19674 +#include <linux/i2c.h>
19675 +#include <linux/i2c-proc.h>
19676 +#include <linux/init.h>
19677 +#define LM_DATE "20041007"
19678 +#define LM_VERSION "2.8.8"
19679 +#include "lm75.h"
19680 +
19681 +/* Addresses to scan */
19682 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
19683 +static unsigned short normal_i2c_range[] = { 0x48, 0x4f, SENSORS_I2C_END };
19684 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
19685 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
19686 +
19687 +/* Insmod parameters */
19688 +SENSORS_INSMOD_1(lm75);
19689 +
19690 +/* Many LM75 constants specified below */
19691 +
19692 +/* The LM75 registers */
19693 +#define LM75_REG_TEMP 0x00
19694 +#define LM75_REG_CONF 0x01
19695 +#define LM75_REG_TEMP_HYST 0x02
19696 +#define LM75_REG_TEMP_OS 0x03
19697 +
19698 +/* Each client has this additional data */
19699 +struct lm75_data {
19700 +       struct i2c_client client;
19701 +       int sysctl_id;
19702 +
19703 +       struct semaphore update_lock;
19704 +       char valid;             /* !=0 if following fields are valid */
19705 +       unsigned long last_updated;     /* In jiffies */
19706 +
19707 +       u16 temp, temp_os, temp_hyst;   /* Register values */
19708 +};
19709 +
19710 +static int lm75_attach_adapter(struct i2c_adapter *adapter);
19711 +static int lm75_detect(struct i2c_adapter *adapter, int address,
19712 +                      unsigned short flags, int kind);
19713 +static void lm75_init_client(struct i2c_client *client);
19714 +static int lm75_detach_client(struct i2c_client *client);
19715 +
19716 +static int lm75_read_value(struct i2c_client *client, u8 reg);
19717 +static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
19718 +static void lm75_temp(struct i2c_client *client, int operation,
19719 +                     int ctl_name, int *nrels_mag, long *results);
19720 +static void lm75_update_client(struct i2c_client *client);
19721 +
19722 +
19723 +/* This is the driver that will be inserted */
19724 +static struct i2c_driver lm75_driver = {
19725 +       .owner          = THIS_MODULE,
19726 +       .name           = "LM75 sensor chip driver",
19727 +       .id             = I2C_DRIVERID_LM75,
19728 +       .flags          = I2C_DF_NOTIFY,
19729 +       .attach_adapter = lm75_attach_adapter,
19730 +       .detach_client  = lm75_detach_client,
19731 +};
19732 +
19733 +/* -- SENSORS SYSCTL START -- */
19734 +
19735 +#define LM75_SYSCTL_TEMP 1200  /* Degrees Celcius * 10 */
19736 +
19737 +/* -- SENSORS SYSCTL END -- */
19738 +
19739 +/* These files are created for each detected LM75. This is just a template;
19740 +   though at first sight, you might think we could use a statically
19741 +   allocated list, we need some way to get back to the parent - which
19742 +   is done through one of the 'extra' fields which are initialized
19743 +   when a new copy is allocated. */
19744 +static ctl_table lm75_dir_table_template[] = {
19745 +       {LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
19746 +        &i2c_sysctl_real, NULL, &lm75_temp},
19747 +       {0}
19748 +};
19749 +
19750 +static int lm75_id = 0;
19751 +
19752 +static int lm75_attach_adapter(struct i2c_adapter *adapter)
19753 +{
19754 +       return i2c_detect(adapter, &addr_data, lm75_detect);
19755 +}
19756 +
19757 +/* This function is called by i2c_detect */
19758 +int lm75_detect(struct i2c_adapter *adapter, int address,
19759 +               unsigned short flags, int kind)
19760 +{
19761 +       int i;
19762 +       struct i2c_client *new_client;
19763 +       struct lm75_data *data;
19764 +       int err = 0;
19765 +       const char *type_name, *client_name;
19766 +
19767 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
19768 +          at this moment; i2c_detect really won't call us. */
19769 +#ifdef DEBUG
19770 +       if (i2c_is_isa_adapter(adapter)) {
19771 +               printk
19772 +                   ("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
19773 +               return 0;
19774 +       }
19775 +#endif
19776 +
19777 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
19778 +                                    I2C_FUNC_SMBUS_WORD_DATA))
19779 +                   goto error0;
19780 +
19781 +       /* OK. For now, we presume we have a valid client. We now create the
19782 +          client structure, even though we cannot fill it completely yet.
19783 +          But it allows us to access lm75_{read,write}_value. */
19784 +       if (!(data = kmalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
19785 +               err = -ENOMEM;
19786 +               goto error0;
19787 +       }
19788 +
19789 +       new_client = &data->client;
19790 +       new_client->addr = address;
19791 +       new_client->data = data;
19792 +       new_client->adapter = adapter;
19793 +       new_client->driver = &lm75_driver;
19794 +       new_client->flags = 0;
19795 +
19796 +       /* Now, we do the remaining detection. There is no identification-
19797 +          dedicated register so we have to rely on several tricks:
19798 +          unused bits, registers cycling over 8-address boundaries,
19799 +          addresses 0x04-0x07 returning the last read value.
19800 +          The cycling+unused addresses combination is not tested,
19801 +          since it would significantly slow the detection down and would
19802 +          hardly add any value. */
19803 +       if (kind < 0) {
19804 +               int cur, conf, hyst, os;
19805 +
19806 +               /* Unused addresses */
19807 +               cur = i2c_smbus_read_word_data(new_client, 0);
19808 +               conf = i2c_smbus_read_byte_data(new_client, 1);
19809 +               hyst = i2c_smbus_read_word_data(new_client, 2);
19810 +               if (i2c_smbus_read_word_data(new_client, 4) != hyst
19811 +                || i2c_smbus_read_word_data(new_client, 5) != hyst
19812 +                || i2c_smbus_read_word_data(new_client, 6) != hyst
19813 +                || i2c_smbus_read_word_data(new_client, 7) != hyst)
19814 +                       goto error1;
19815 +               os = i2c_smbus_read_word_data(new_client, 3);
19816 +               if (i2c_smbus_read_word_data(new_client, 4) != os
19817 +                || i2c_smbus_read_word_data(new_client, 5) != os
19818 +                || i2c_smbus_read_word_data(new_client, 6) != os
19819 +                || i2c_smbus_read_word_data(new_client, 7) != os)
19820 +                       goto error1;
19821 +
19822 +               /* Unused bits */
19823 +               if (conf & 0xe0)
19824 +                       goto error1;
19825 +
19826 +               /* Addresses cycling */
19827 +               for (i = 8; i < 0xff; i += 8)
19828 +                       if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
19829 +                        || i2c_smbus_read_word_data(new_client, i + 2) != hyst
19830 +                        || i2c_smbus_read_word_data(new_client, i + 3) != os)
19831 +                               goto error1;
19832 +       }
19833 +
19834 +       /* Determine the chip type - only one kind supported! */
19835 +       if (kind <= 0)
19836 +               kind = lm75;
19837 +
19838 +       if (kind == lm75) {
19839 +               type_name = "lm75";
19840 +               client_name = "LM75 chip";
19841 +       } else {
19842 +               pr_debug("lm75.o: Internal error: unknown kind (%d)?!?", kind);
19843 +               goto error1;
19844 +       }
19845 +
19846 +       /* Fill in the remaining client fields and put it into the global list */
19847 +       strcpy(new_client->name, client_name);
19848 +
19849 +       new_client->id = lm75_id++;
19850 +       data->valid = 0;
19851 +       init_MUTEX(&data->update_lock);
19852 +
19853 +       /* Tell the I2C layer a new client has arrived */
19854 +       if ((err = i2c_attach_client(new_client)))
19855 +               goto error3;
19856 +
19857 +       /* Register a new directory entry with module sensors */
19858 +       if ((i = i2c_register_entry(new_client, type_name,
19859 +                                       lm75_dir_table_template)) < 0) {
19860 +               err = i;
19861 +               goto error4;
19862 +       }
19863 +       data->sysctl_id = i;
19864 +
19865 +       lm75_init_client(new_client);
19866 +       return 0;
19867 +
19868 +/* OK, this is not exactly good programming practice, usually. But it is
19869 +   very code-efficient in this case. */
19870 +
19871 +      error4:
19872 +       i2c_detach_client(new_client);
19873 +      error3:
19874 +      error1:
19875 +       kfree(data);
19876 +      error0:
19877 +       return err;
19878 +}
19879 +
19880 +static int lm75_detach_client(struct i2c_client *client)
19881 +{
19882 +       struct lm75_data *data = client->data;
19883 +
19884 +       i2c_deregister_entry(data->sysctl_id);
19885 +       i2c_detach_client(client);
19886 +       kfree(client->data);
19887 +       return 0;
19888 +}
19889 +
19890 +/* All registers are word-sized, except for the configuration register.
19891 +   LM75 uses a high-byte first convention, which is exactly opposite to
19892 +   the usual practice. */
19893 +static int lm75_read_value(struct i2c_client *client, u8 reg)
19894 +{
19895 +       if (reg == LM75_REG_CONF)
19896 +               return i2c_smbus_read_byte_data(client, reg);
19897 +       else
19898 +               return swab16(i2c_smbus_read_word_data(client, reg));
19899 +}
19900 +
19901 +/* All registers are word-sized, except for the configuration register.
19902 +   LM75 uses a high-byte first convention, which is exactly opposite to
19903 +   the usual practice. */
19904 +static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
19905 +{
19906 +       if (reg == LM75_REG_CONF)
19907 +               return i2c_smbus_write_byte_data(client, reg, value);
19908 +       else
19909 +               return i2c_smbus_write_word_data(client, reg, swab16(value));
19910 +}
19911 +
19912 +static void lm75_init_client(struct i2c_client *client)
19913 +{
19914 +       /* Initialize the LM75 chip */
19915 +       lm75_write_value(client, LM75_REG_CONF, 0);
19916 +}
19917 +
19918 +static void lm75_update_client(struct i2c_client *client)
19919 +{
19920 +       struct lm75_data *data = client->data;
19921 +
19922 +       down(&data->update_lock);
19923 +
19924 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
19925 +           (jiffies < data->last_updated) || !data->valid) {
19926 +               pr_debug("Starting lm75 update\n");
19927 +
19928 +               data->temp = lm75_read_value(client, LM75_REG_TEMP);
19929 +               data->temp_os = lm75_read_value(client, LM75_REG_TEMP_OS);
19930 +               data->temp_hyst =
19931 +                   lm75_read_value(client, LM75_REG_TEMP_HYST);
19932 +               data->last_updated = jiffies;
19933 +               data->valid = 1;
19934 +       }
19935 +
19936 +       up(&data->update_lock);
19937 +}
19938 +
19939 +
19940 +void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
19941 +              int *nrels_mag, long *results)
19942 +{
19943 +       struct lm75_data *data = client->data;
19944 +       if (operation == SENSORS_PROC_REAL_INFO)
19945 +               *nrels_mag = 1;
19946 +       else if (operation == SENSORS_PROC_REAL_READ) {
19947 +               lm75_update_client(client);
19948 +               results[0] = LM75_TEMP_FROM_REG(data->temp_os);
19949 +               results[1] = LM75_TEMP_FROM_REG(data->temp_hyst);
19950 +               results[2] = LM75_TEMP_FROM_REG(data->temp);
19951 +               *nrels_mag = 3;
19952 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
19953 +               if (*nrels_mag >= 1) {
19954 +                       data->temp_os = LM75_TEMP_TO_REG(results[0]);
19955 +                       lm75_write_value(client, LM75_REG_TEMP_OS,
19956 +                                        data->temp_os);
19957 +               }
19958 +               if (*nrels_mag >= 2) {
19959 +                       data->temp_hyst = LM75_TEMP_TO_REG(results[1]);
19960 +                       lm75_write_value(client, LM75_REG_TEMP_HYST,
19961 +                                        data->temp_hyst);
19962 +               }
19963 +       }
19964 +}
19965 +
19966 +static int __init sm_lm75_init(void)
19967 +{
19968 +       printk(KERN_INFO "lm75.o version %s (%s)\n", LM_VERSION, LM_DATE);
19969 +       return i2c_add_driver(&lm75_driver);
19970 +}
19971 +
19972 +static void __exit sm_lm75_exit(void)
19973 +{
19974 +       i2c_del_driver(&lm75_driver);
19975 +}
19976 +
19977 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
19978 +MODULE_DESCRIPTION("LM75 driver");
19979 +MODULE_LICENSE("GPL");
19980 +
19981 +module_init(sm_lm75_init);
19982 +module_exit(sm_lm75_exit);
19983 --- linux-old/drivers/sensors/lm75.h    Thu Jan  1 00:00:00 1970
19984 +++ linux/drivers/sensors/lm75.h        Mon Dec 13 20:18:47 2004
19985 @@ -0,0 +1,49 @@
19986 +/*
19987 +    lm75.h - Part of lm_sensors, Linux kernel modules for hardware
19988 +             monitoring
19989 +    Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
19990 +
19991 +    This program is free software; you can redistribute it and/or modify
19992 +    it under the terms of the GNU General Public License as published by
19993 +    the Free Software Foundation; either version 2 of the License, or
19994 +    (at your option) any later version.
19995 +
19996 +    This program is distributed in the hope that it will be useful,
19997 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
19998 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19999 +    GNU General Public License for more details.
20000 +
20001 +    You should have received a copy of the GNU General Public License
20002 +    along with this program; if not, write to the Free Software
20003 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20004 +*/
20005 +
20006 +/*
20007 +    This file contains common code for encoding/decoding LM75 type
20008 +    temperature readings, which are emulated by many of the chips
20009 +    we support.  As the user is unlikely to load more than one driver
20010 +    which contains this code, we don't worry about the wasted space.
20011 +*/
20012 +
20013 +#include <linux/i2c-proc.h>
20014 +
20015 +/* straight from the datasheet */
20016 +#define LM75_TEMP_MIN (-550)
20017 +#define LM75_TEMP_MAX 1250
20018 +
20019 +/* TEMP: 0.1C/bit (-55C to +125C)
20020 +   REG: (0.5C/bit, two's complement) << 7 */
20021 +static inline u16 LM75_TEMP_TO_REG(int temp)
20022 +{
20023 +       int ntemp = SENSORS_LIMIT(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
20024 +       ntemp += (ntemp<0 ? -2 : 2);
20025 +       return (u16)((ntemp / 5) << 7);
20026 +}
20027 +
20028 +static inline int LM75_TEMP_FROM_REG(u16 reg)
20029 +{
20030 +       /* use integer division instead of equivalent right shift to
20031 +          guarantee arithmetic shift and preserve the sign */
20032 +       return ((s16)reg / 128) * 5;
20033 +}
20034 +
20035 --- linux-old/drivers/sensors/lm78.c    Thu Jan  1 00:00:00 1970
20036 +++ linux/drivers/sensors/lm78.c        Mon Dec 13 20:18:47 2004
20037 @@ -0,0 +1,729 @@
20038 +/*
20039 +    lm78.c - Part of lm_sensors, Linux kernel modules for hardware
20040 +             monitoring
20041 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
20042 +
20043 +    This program is free software; you can redistribute it and/or modify
20044 +    it under the terms of the GNU General Public License as published by
20045 +    the Free Software Foundation; either version 2 of the License, or
20046 +    (at your option) any later version.
20047 +
20048 +    This program is distributed in the hope that it will be useful,
20049 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
20050 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20051 +    GNU General Public License for more details.
20052 +
20053 +    You should have received a copy of the GNU General Public License
20054 +    along with this program; if not, write to the Free Software
20055 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20056 +*/
20057 +
20058 +#include <linux/module.h>
20059 +#include <linux/slab.h>
20060 +#include <linux/ioport.h>
20061 +#include <linux/i2c.h>
20062 +#include <linux/i2c-proc.h>
20063 +#include <linux/init.h>
20064 +#include <asm/io.h>
20065 +#define LM_DATE "20041007"
20066 +#define LM_VERSION "2.8.8"
20067 +
20068 +MODULE_LICENSE("GPL");
20069 +
20070 +/* Addresses to scan */
20071 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
20072 +static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
20073 +static unsigned int normal_isa[] = { 0x0290, SENSORS_ISA_END };
20074 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
20075 +
20076 +/* Insmod parameters */
20077 +SENSORS_INSMOD_3(lm78, lm78j, lm79);
20078 +
20079 +/* Many LM78 constants specified below */
20080 +
20081 +/* Length of ISA address segment */
20082 +#define LM78_EXTENT 8
20083 +
20084 +/* Where are the ISA address/data registers relative to the base address */
20085 +#define LM78_ADDR_REG_OFFSET 5
20086 +#define LM78_DATA_REG_OFFSET 6
20087 +
20088 +/* The LM78 registers */
20089 +#define LM78_REG_IN_MAX(nr) (0x2b + (nr) * 2)
20090 +#define LM78_REG_IN_MIN(nr) (0x2c + (nr) * 2)
20091 +#define LM78_REG_IN(nr) (0x20 + (nr))
20092 +
20093 +#define LM78_REG_FAN_MIN(nr) (0x3a + (nr))
20094 +#define LM78_REG_FAN(nr) (0x27 + (nr))
20095 +
20096 +#define LM78_REG_TEMP 0x27
20097 +#define LM78_REG_TEMP_OVER 0x39
20098 +#define LM78_REG_TEMP_HYST 0x3a
20099 +
20100 +#define LM78_REG_ALARM1 0x41
20101 +#define LM78_REG_ALARM2 0x42
20102 +
20103 +#define LM78_REG_VID_FANDIV 0x47
20104 +
20105 +#define LM78_REG_CONFIG 0x40
20106 +#define LM78_REG_CHIPID 0x49
20107 +#define LM78_REG_I2C_ADDR 0x48
20108 +
20109 +
20110 +/* Conversions. Limit checking is only done on the TO_REG 
20111 +   variants. Note that you should be a bit careful with which arguments
20112 +   these macros are called: arguments may be evaluated more than once.
20113 +   Fixing this is just not worth it. */
20114 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
20115 +#define IN_FROM_REG(val) (((val) *  16 + 5) / 10)
20116 +
20117 +static inline u8 FAN_TO_REG(long rpm, int div)
20118 +{
20119 +       if (rpm == 0)
20120 +               return 255;
20121 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
20122 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
20123 +                            254);
20124 +}
20125 +
20126 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
20127 +
20128 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
20129 +                                                 ((val)+5)/10),0,255))
20130 +#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
20131 +
20132 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
20133 +                           205-(val)*5)
20134 +#define ALARMS_FROM_REG(val) (val)
20135 +
20136 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
20137 +#define DIV_FROM_REG(val) (1 << (val))
20138 +
20139 +/* There are some complications in a module like this. First off, LM78 chips
20140 +   may be both present on the SMBus and the ISA bus, and we have to handle
20141 +   those cases separately at some places. Second, there might be several
20142 +   LM78 chips available (well, actually, that is probably never done; but
20143 +   it is a clean illustration of how to handle a case like that). Finally,
20144 +   a specific chip may be attached to *both* ISA and SMBus, and we would
20145 +   not like to detect it double. Fortunately, in the case of the LM78 at
20146 +   least, a register tells us what SMBus address we are on, so that helps
20147 +   a bit - except if there could be more than one SMBus. Groan. No solution
20148 +   for this yet. */
20149 +
20150 +/* This module may seem overly long and complicated. In fact, it is not so
20151 +   bad. Quite a lot of bookkeeping is done. A real driver can often cut
20152 +   some corners. */
20153 +
20154 +/* For each registered LM78, we need to keep some data in memory. That
20155 +   data is pointed to by lm78_list[NR]->data. The structure itself is
20156 +   dynamically allocated, at the same time when a new lm78 client is
20157 +   allocated. */
20158 +struct lm78_data {
20159 +       struct i2c_client client;
20160 +       struct semaphore lock;
20161 +       int sysctl_id;
20162 +       enum chips type;
20163 +
20164 +       struct semaphore update_lock;
20165 +       char valid;             /* !=0 if following fields are valid */
20166 +       unsigned long last_updated;     /* In jiffies */
20167 +
20168 +       u8 in[7];               /* Register value */
20169 +       u8 in_max[7];           /* Register value */
20170 +       u8 in_min[7];           /* Register value */
20171 +       u8 fan[3];              /* Register value */
20172 +       u8 fan_min[3];          /* Register value */
20173 +       u8 temp;                /* Register value */
20174 +       u8 temp_over;           /* Register value */
20175 +       u8 temp_hyst;           /* Register value */
20176 +       u8 fan_div[3];          /* Register encoding, shifted right */
20177 +       u8 vid;                 /* Register encoding, combined */
20178 +       u16 alarms;             /* Register encoding, combined */
20179 +};
20180 +
20181 +
20182 +static int lm78_attach_adapter(struct i2c_adapter *adapter);
20183 +static int lm78_detect(struct i2c_adapter *adapter, int address,
20184 +                      unsigned short flags, int kind);
20185 +static int lm78_detach_client(struct i2c_client *client);
20186 +
20187 +static int lm78_read_value(struct i2c_client *client, u8 register);
20188 +static int lm78_write_value(struct i2c_client *client, u8 register,
20189 +                           u8 value);
20190 +static void lm78_update_client(struct i2c_client *client);
20191 +static void lm78_init_client(struct i2c_client *client);
20192 +
20193 +
20194 +static void lm78_in(struct i2c_client *client, int operation, int ctl_name,
20195 +                   int *nrels_mag, long *results);
20196 +static void lm78_fan(struct i2c_client *client, int operation,
20197 +                    int ctl_name, int *nrels_mag, long *results);
20198 +static void lm78_temp(struct i2c_client *client, int operation,
20199 +                     int ctl_name, int *nrels_mag, long *results);
20200 +static void lm78_vid(struct i2c_client *client, int operation,
20201 +                    int ctl_name, int *nrels_mag, long *results);
20202 +static void lm78_alarms(struct i2c_client *client, int operation,
20203 +                       int ctl_name, int *nrels_mag, long *results);
20204 +static void lm78_fan_div(struct i2c_client *client, int operation,
20205 +                        int ctl_name, int *nrels_mag, long *results);
20206 +
20207 +static struct i2c_driver lm78_driver = {
20208 +       .owner          = THIS_MODULE,
20209 +       .name           = "LM78(-J) and LM79 sensor driver",
20210 +       .id             = I2C_DRIVERID_LM78,
20211 +       .flags          = I2C_DF_NOTIFY,
20212 +       .attach_adapter = lm78_attach_adapter,
20213 +       .detach_client  = lm78_detach_client,
20214 +};
20215 +
20216 +static int lm78_id = 0;
20217 +
20218 +/* The /proc/sys entries */
20219 +
20220 +/* -- SENSORS SYSCTL START -- */
20221 +#define LM78_SYSCTL_IN0 1000   /* Volts * 100 */
20222 +#define LM78_SYSCTL_IN1 1001
20223 +#define LM78_SYSCTL_IN2 1002
20224 +#define LM78_SYSCTL_IN3 1003
20225 +#define LM78_SYSCTL_IN4 1004
20226 +#define LM78_SYSCTL_IN5 1005
20227 +#define LM78_SYSCTL_IN6 1006
20228 +#define LM78_SYSCTL_FAN1 1101  /* Rotations/min */
20229 +#define LM78_SYSCTL_FAN2 1102
20230 +#define LM78_SYSCTL_FAN3 1103
20231 +#define LM78_SYSCTL_TEMP 1200  /* Degrees Celcius * 10 */
20232 +#define LM78_SYSCTL_VID 1300   /* Volts * 100 */
20233 +#define LM78_SYSCTL_FAN_DIV 2000       /* 1, 2, 4 or 8 */
20234 +#define LM78_SYSCTL_ALARMS 2001        /* bitvector */
20235 +
20236 +#define LM78_ALARM_IN0 0x0001
20237 +#define LM78_ALARM_IN1 0x0002
20238 +#define LM78_ALARM_IN2 0x0004
20239 +#define LM78_ALARM_IN3 0x0008
20240 +#define LM78_ALARM_IN4 0x0100
20241 +#define LM78_ALARM_IN5 0x0200
20242 +#define LM78_ALARM_IN6 0x0400
20243 +#define LM78_ALARM_FAN1 0x0040
20244 +#define LM78_ALARM_FAN2 0x0080
20245 +#define LM78_ALARM_FAN3 0x0800
20246 +#define LM78_ALARM_TEMP 0x0010
20247 +#define LM78_ALARM_BTI 0x0020
20248 +#define LM78_ALARM_CHAS 0x1000
20249 +#define LM78_ALARM_FIFO 0x2000
20250 +#define LM78_ALARM_SMI_IN 0x4000
20251 +
20252 +/* -- SENSORS SYSCTL END -- */
20253 +
20254 +/* These files are created for each detected LM78. This is just a template;
20255 +   though at first sight, you might think we could use a statically
20256 +   allocated list, we need some way to get back to the parent - which
20257 +   is done through one of the 'extra' fields which are initialized 
20258 +   when a new copy is allocated. */
20259 +static ctl_table lm78_dir_table_template[] = {
20260 +       {LM78_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
20261 +        &i2c_sysctl_real, NULL, &lm78_in},
20262 +       {LM78_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
20263 +        &i2c_sysctl_real, NULL, &lm78_in},
20264 +       {LM78_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
20265 +        &i2c_sysctl_real, NULL, &lm78_in},
20266 +       {LM78_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
20267 +        &i2c_sysctl_real, NULL, &lm78_in},
20268 +       {LM78_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
20269 +        &i2c_sysctl_real, NULL, &lm78_in},
20270 +       {LM78_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
20271 +        &i2c_sysctl_real, NULL, &lm78_in},
20272 +       {LM78_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
20273 +        &i2c_sysctl_real, NULL, &lm78_in},
20274 +       {LM78_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
20275 +        &i2c_sysctl_real, NULL, &lm78_fan},
20276 +       {LM78_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
20277 +        &i2c_sysctl_real, NULL, &lm78_fan},
20278 +       {LM78_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
20279 +        &i2c_sysctl_real, NULL, &lm78_fan},
20280 +       {LM78_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
20281 +        &i2c_sysctl_real, NULL, &lm78_temp},
20282 +       {LM78_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
20283 +        &i2c_sysctl_real, NULL, &lm78_vid},
20284 +       {LM78_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
20285 +        &i2c_sysctl_real, NULL, &lm78_fan_div},
20286 +       {LM78_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
20287 +        &i2c_sysctl_real, NULL, &lm78_alarms},
20288 +       {0}
20289 +};
20290 +
20291 +
20292 +/* This function is called when:
20293 +     * lm78_driver is inserted (when this module is loaded), for each
20294 +       available adapter
20295 +     * when a new adapter is inserted (and lm78_driver is still present) */
20296 +static int lm78_attach_adapter(struct i2c_adapter *adapter)
20297 +{
20298 +       return i2c_detect(adapter, &addr_data, lm78_detect);
20299 +}
20300 +
20301 +/* This function is called by i2c_detect */
20302 +int lm78_detect(struct i2c_adapter *adapter, int address,
20303 +               unsigned short flags, int kind)
20304 +{
20305 +       int i;
20306 +       struct i2c_client *new_client;
20307 +       struct lm78_data *data;
20308 +       int err = 0;
20309 +       const char *type_name = "";
20310 +       const char *client_name = "";
20311 +       int is_isa = i2c_is_isa_adapter(adapter);
20312 +
20313 +       if (!is_isa
20314 +           && !i2c_check_functionality(adapter,
20315 +                                       I2C_FUNC_SMBUS_BYTE_DATA)) goto
20316 +                   ERROR0;
20317 +
20318 +       if (is_isa) {
20319 +               if (check_region(address, LM78_EXTENT))
20320 +                       goto ERROR0;
20321 +       }
20322 +
20323 +       /* Probe whether there is anything available on this address. Already
20324 +          done for SMBus clients */
20325 +       if (kind < 0) {
20326 +               if (is_isa) {
20327 +
20328 +#define REALLY_SLOW_IO
20329 +                       /* We need the timeouts for at least some LM78-like chips. But only
20330 +                          if we read 'undefined' registers. */
20331 +                       i = inb_p(address + 1);
20332 +                       if (inb_p(address + 2) != i)
20333 +                               goto ERROR0;
20334 +                       if (inb_p(address + 3) != i)
20335 +                               goto ERROR0;
20336 +                       if (inb_p(address + 7) != i)
20337 +                               goto ERROR0;
20338 +#undef REALLY_SLOW_IO
20339 +
20340 +                       /* Let's just hope nothing breaks here */
20341 +                       i = inb_p(address + 5) & 0x7f;
20342 +                       outb_p(~i & 0x7f, address + 5);
20343 +                       if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
20344 +                               outb_p(i, address + 5);
20345 +                               return 0;
20346 +                       }
20347 +               }
20348 +       }
20349 +
20350 +       /* OK. For now, we presume we have a valid client. We now create the
20351 +          client structure, even though we cannot fill it completely yet.
20352 +          But it allows us to access lm78_{read,write}_value. */
20353 +
20354 +       if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
20355 +               err = -ENOMEM;
20356 +               goto ERROR0;
20357 +       }
20358 +
20359 +       new_client = &data->client;
20360 +       if (is_isa)
20361 +               init_MUTEX(&data->lock);
20362 +       new_client->addr = address;
20363 +       new_client->data = data;
20364 +       new_client->adapter = adapter;
20365 +       new_client->driver = &lm78_driver;
20366 +       new_client->flags = 0;
20367 +
20368 +       /* Now, we do the remaining detection. */
20369 +
20370 +       if (kind < 0) {
20371 +               if (lm78_read_value(new_client, LM78_REG_CONFIG) & 0x80)
20372 +                       goto ERROR1;
20373 +               if (!is_isa
20374 +                   && (lm78_read_value(new_client, LM78_REG_I2C_ADDR) !=
20375 +                       address)) goto ERROR1;
20376 +       }
20377 +
20378 +       /* Determine the chip type. */
20379 +       if (kind <= 0) {
20380 +               i = lm78_read_value(new_client, LM78_REG_CHIPID);
20381 +               if (i == 0x00 || i == 0x20)
20382 +                       kind = lm78;
20383 +               else if (i == 0x40)
20384 +                       kind = lm78j;
20385 +               else if ((i & 0xfe) == 0xc0)
20386 +                       kind = lm79;
20387 +               else {
20388 +                       if (kind == 0)
20389 +                               printk
20390 +                                   ("lm78.o: Ignoring 'force' parameter for unknown chip at "
20391 +                                    "adapter %d, address 0x%02x\n",
20392 +                                    i2c_adapter_id(adapter), address);
20393 +                       goto ERROR1;
20394 +               }
20395 +       }
20396 +
20397 +       if (kind == lm78) {
20398 +               type_name = "lm78";
20399 +               client_name = "LM78 chip";
20400 +       } else if (kind == lm78j) {
20401 +               type_name = "lm78-j";
20402 +               client_name = "LM78-J chip";
20403 +       } else if (kind == lm79) {
20404 +               type_name = "lm79";
20405 +               client_name = "LM79 chip";
20406 +       } else {
20407 +#ifdef DEBUG
20408 +               printk("lm78.o: Internal error: unknown kind (%d)?!?",
20409 +                      kind);
20410 +#endif
20411 +               goto ERROR1;
20412 +       }
20413 +
20414 +       /* Reserve the ISA region */
20415 +       if (is_isa)
20416 +               request_region(address, LM78_EXTENT, type_name);
20417 +
20418 +       /* Fill in the remaining client fields and put it into the global list */
20419 +       strcpy(new_client->name, client_name);
20420 +       data->type = kind;
20421 +
20422 +       new_client->id = lm78_id++;
20423 +       data->valid = 0;
20424 +       init_MUTEX(&data->update_lock);
20425 +
20426 +       /* Tell the I2C layer a new client has arrived */
20427 +       if ((err = i2c_attach_client(new_client)))
20428 +               goto ERROR3;
20429 +
20430 +       /* Register a new directory entry with module sensors */
20431 +       if ((i = i2c_register_entry(new_client,
20432 +                                       type_name,
20433 +                                       lm78_dir_table_template)) < 0) {
20434 +               err = i;
20435 +               goto ERROR4;
20436 +       }
20437 +       data->sysctl_id = i;
20438 +
20439 +       /* Initialize the LM78 chip */
20440 +       lm78_init_client(new_client);
20441 +       return 0;
20442 +
20443 +/* OK, this is not exactly good programming practice, usually. But it is
20444 +   very code-efficient in this case. */
20445 +
20446 +      ERROR4:
20447 +       i2c_detach_client(new_client);
20448 +      ERROR3:
20449 +       if (is_isa)
20450 +               release_region(address, LM78_EXTENT);
20451 +      ERROR1:
20452 +       kfree(data);
20453 +      ERROR0:
20454 +       return err;
20455 +}
20456 +
20457 +static int lm78_detach_client(struct i2c_client *client)
20458 +{
20459 +       int err;
20460 +
20461 +       i2c_deregister_entry(((struct lm78_data *) (client->data))->
20462 +                                sysctl_id);
20463 +
20464 +       if ((err = i2c_detach_client(client))) {
20465 +               printk
20466 +                   ("lm78.o: Client deregistration failed, client not detached.\n");
20467 +               return err;
20468 +       }
20469 +
20470 +       if(i2c_is_isa_client(client))
20471 +               release_region(client->addr, LM78_EXTENT);
20472 +       kfree(client->data);
20473 +
20474 +       return 0;
20475 +}
20476 +
20477 +/* The SMBus locks itself, but ISA access must be locked explicitely! 
20478 +   We don't want to lock the whole ISA bus, so we lock each client
20479 +   separately.
20480 +   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
20481 +   would slow down the LM78 access and should not be necessary. 
20482 +   There are some ugly typecasts here, but the good new is - they should
20483 +   nowhere else be necessary! */
20484 +static int lm78_read_value(struct i2c_client *client, u8 reg)
20485 +{
20486 +       int res;
20487 +       if (i2c_is_isa_client(client)) {
20488 +               down(&(((struct lm78_data *) (client->data))->lock));
20489 +               outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
20490 +               res = inb_p(client->addr + LM78_DATA_REG_OFFSET);
20491 +               up(&(((struct lm78_data *) (client->data))->lock));
20492 +               return res;
20493 +       } else
20494 +               return i2c_smbus_read_byte_data(client, reg);
20495 +}
20496 +
20497 +/* The SMBus locks itself, but ISA access muse be locked explicitely! 
20498 +   We don't want to lock the whole ISA bus, so we lock each client
20499 +   separately.
20500 +   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
20501 +   would slow down the LM78 access and should not be necessary. 
20502 +   There are some ugly typecasts here, but the good new is - they should
20503 +   nowhere else be necessary! */
20504 +static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
20505 +{
20506 +       if (i2c_is_isa_client(client)) {
20507 +               down(&(((struct lm78_data *) (client->data))->lock));
20508 +               outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
20509 +               outb_p(value, client->addr + LM78_DATA_REG_OFFSET);
20510 +               up(&(((struct lm78_data *) (client->data))->lock));
20511 +               return 0;
20512 +       } else
20513 +               return i2c_smbus_write_byte_data(client, reg, value);
20514 +}
20515 +
20516 +/* Called when we have found a new LM78. */
20517 +static void lm78_init_client(struct i2c_client *client)
20518 +{
20519 +       u8 config = lm78_read_value(client, LM78_REG_CONFIG);
20520 +
20521 +       /* Start monitoring */
20522 +       if (!(config & 0x01))
20523 +               lm78_write_value(client, LM78_REG_CONFIG,
20524 +                                (config & 0xf7) | 0x01);
20525 +}
20526 +
20527 +static void lm78_update_client(struct i2c_client *client)
20528 +{
20529 +       struct lm78_data *data = client->data;
20530 +       int i;
20531 +
20532 +       down(&data->update_lock);
20533 +
20534 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
20535 +           (jiffies < data->last_updated) || !data->valid) {
20536 +
20537 +#ifdef DEBUG
20538 +               printk("Starting lm78 update\n");
20539 +#endif
20540 +               for (i = 0; i <= 6; i++) {
20541 +                       data->in[i] =
20542 +                           lm78_read_value(client, LM78_REG_IN(i));
20543 +                       data->in_min[i] =
20544 +                           lm78_read_value(client, LM78_REG_IN_MIN(i));
20545 +                       data->in_max[i] =
20546 +                           lm78_read_value(client, LM78_REG_IN_MAX(i));
20547 +               }
20548 +               for (i = 1; i <= 3; i++) {
20549 +                       data->fan[i - 1] =
20550 +                           lm78_read_value(client, LM78_REG_FAN(i));
20551 +                       data->fan_min[i - 1] =
20552 +                           lm78_read_value(client, LM78_REG_FAN_MIN(i));
20553 +               }
20554 +               data->temp = lm78_read_value(client, LM78_REG_TEMP);
20555 +               data->temp_over =
20556 +                   lm78_read_value(client, LM78_REG_TEMP_OVER);
20557 +               data->temp_hyst =
20558 +                   lm78_read_value(client, LM78_REG_TEMP_HYST);
20559 +               i = lm78_read_value(client, LM78_REG_VID_FANDIV);
20560 +               data->vid = i & 0x0f;
20561 +               if (data->type == lm79)
20562 +                       data->vid |=
20563 +                           (lm78_read_value(client, LM78_REG_CHIPID) &
20564 +                            0x01) << 4;
20565 +               else
20566 +                       data->vid |= 0x10;
20567 +               data->fan_div[0] = (i >> 4) & 0x03;
20568 +               data->fan_div[1] = i >> 6;
20569 +               data->alarms = lm78_read_value(client, LM78_REG_ALARM1) +
20570 +                   (lm78_read_value(client, LM78_REG_ALARM2) << 8);
20571 +               data->last_updated = jiffies;
20572 +               data->valid = 1;
20573 +
20574 +               data->fan_div[2] = 1;
20575 +       }
20576 +
20577 +       up(&data->update_lock);
20578 +}
20579 +
20580 +
20581 +/* The next few functions are the call-back functions of the /proc/sys and
20582 +   sysctl files. Which function is used is defined in the ctl_table in
20583 +   the extra1 field.
20584 +   Each function must return the magnitude (power of 10 to divide the date
20585 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
20586 +   put a maximum of *nrels elements in results reflecting the data of this
20587 +   file, and set *nrels to the number it actually put in it, if operation==
20588 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
20589 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
20590 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
20591 +   large enough (by checking the incoming value of *nrels). This is not very
20592 +   good practice, but as long as you put less than about 5 values in results,
20593 +   you can assume it is large enough. */
20594 +void lm78_in(struct i2c_client *client, int operation, int ctl_name,
20595 +            int *nrels_mag, long *results)
20596 +{
20597 +       struct lm78_data *data = client->data;
20598 +       int nr = ctl_name - LM78_SYSCTL_IN0;
20599 +
20600 +       if (operation == SENSORS_PROC_REAL_INFO)
20601 +               *nrels_mag = 2;
20602 +       else if (operation == SENSORS_PROC_REAL_READ) {
20603 +               lm78_update_client(client);
20604 +               results[0] = IN_FROM_REG(data->in_min[nr]);
20605 +               results[1] = IN_FROM_REG(data->in_max[nr]);
20606 +               results[2] = IN_FROM_REG(data->in[nr]);
20607 +               *nrels_mag = 3;
20608 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
20609 +               if (*nrels_mag >= 1) {
20610 +                       data->in_min[nr] = IN_TO_REG(results[0]);
20611 +                       lm78_write_value(client, LM78_REG_IN_MIN(nr),
20612 +                                        data->in_min[nr]);
20613 +               }
20614 +               if (*nrels_mag >= 2) {
20615 +                       data->in_max[nr] = IN_TO_REG(results[1]);
20616 +                       lm78_write_value(client, LM78_REG_IN_MAX(nr),
20617 +                                        data->in_max[nr]);
20618 +               }
20619 +       }
20620 +}
20621 +
20622 +void lm78_fan(struct i2c_client *client, int operation, int ctl_name,
20623 +             int *nrels_mag, long *results)
20624 +{
20625 +       struct lm78_data *data = client->data;
20626 +       int nr = ctl_name - LM78_SYSCTL_FAN1 + 1;
20627 +
20628 +       if (operation == SENSORS_PROC_REAL_INFO)
20629 +               *nrels_mag = 0;
20630 +       else if (operation == SENSORS_PROC_REAL_READ) {
20631 +               lm78_update_client(client);
20632 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
20633 +                                         DIV_FROM_REG(data->
20634 +                                                      fan_div[nr - 1]));
20635 +               results[1] =
20636 +                   FAN_FROM_REG(data->fan[nr - 1],
20637 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
20638 +               *nrels_mag = 2;
20639 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
20640 +               if (*nrels_mag >= 1) {
20641 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0],
20642 +                                                          DIV_FROM_REG
20643 +                                                          (data->
20644 +                                                           fan_div[nr -
20645 +                                                                   1]));
20646 +                       lm78_write_value(client, LM78_REG_FAN_MIN(nr),
20647 +                                        data->fan_min[nr - 1]);
20648 +               }
20649 +       }
20650 +}
20651 +
20652 +
20653 +void lm78_temp(struct i2c_client *client, int operation, int ctl_name,
20654 +              int *nrels_mag, long *results)
20655 +{
20656 +       struct lm78_data *data = client->data;
20657 +       if (operation == SENSORS_PROC_REAL_INFO)
20658 +               *nrels_mag = 1;
20659 +       else if (operation == SENSORS_PROC_REAL_READ) {
20660 +               lm78_update_client(client);
20661 +               results[0] = TEMP_FROM_REG(data->temp_over);
20662 +               results[1] = TEMP_FROM_REG(data->temp_hyst);
20663 +               results[2] = TEMP_FROM_REG(data->temp);
20664 +               *nrels_mag = 3;
20665 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
20666 +               if (*nrels_mag >= 1) {
20667 +                       data->temp_over = TEMP_TO_REG(results[0]);
20668 +                       lm78_write_value(client, LM78_REG_TEMP_OVER,
20669 +                                        data->temp_over);
20670 +               }
20671 +               if (*nrels_mag >= 2) {
20672 +                       data->temp_hyst = TEMP_TO_REG(results[1]);
20673 +                       lm78_write_value(client, LM78_REG_TEMP_HYST,
20674 +                                        data->temp_hyst);
20675 +               }
20676 +       }
20677 +}
20678 +
20679 +void lm78_vid(struct i2c_client *client, int operation, int ctl_name,
20680 +             int *nrels_mag, long *results)
20681 +{
20682 +       struct lm78_data *data = client->data;
20683 +       if (operation == SENSORS_PROC_REAL_INFO)
20684 +               *nrels_mag = 2;
20685 +       else if (operation == SENSORS_PROC_REAL_READ) {
20686 +               lm78_update_client(client);
20687 +               results[0] = VID_FROM_REG(data->vid);
20688 +               *nrels_mag = 1;
20689 +       }
20690 +}
20691 +
20692 +void lm78_alarms(struct i2c_client *client, int operation, int ctl_name,
20693 +                int *nrels_mag, long *results)
20694 +{
20695 +       struct lm78_data *data = client->data;
20696 +       if (operation == SENSORS_PROC_REAL_INFO)
20697 +               *nrels_mag = 0;
20698 +       else if (operation == SENSORS_PROC_REAL_READ) {
20699 +               lm78_update_client(client);
20700 +               results[0] = ALARMS_FROM_REG(data->alarms);
20701 +               *nrels_mag = 1;
20702 +       }
20703 +}
20704 +
20705 +/* Note: we save and restore the fan minimum here, because its value is
20706 +   determined in part by the fan divisor.  This follows the principle of
20707 +   least surprise: the user doesn't expect the fan minimum to change just
20708 +   because the divisor changed. */
20709 +void lm78_fan_div(struct i2c_client *client, int operation, int ctl_name,
20710 +                 int *nrels_mag, long *results)
20711 +{
20712 +       struct lm78_data *data = client->data;
20713 +       int old, min;
20714 +
20715 +       if (operation == SENSORS_PROC_REAL_INFO)
20716 +               *nrels_mag = 0;
20717 +       else if (operation == SENSORS_PROC_REAL_READ) {
20718 +               lm78_update_client(client);
20719 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
20720 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
20721 +               results[2] = 2;
20722 +               *nrels_mag = 3;
20723 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
20724 +               old = lm78_read_value(client, LM78_REG_VID_FANDIV);
20725 +               if (*nrels_mag >= 2) {
20726 +                       min = FAN_FROM_REG(data->fan_min[1], 
20727 +                                       DIV_FROM_REG(data->fan_div[1]));
20728 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
20729 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
20730 +                       data->fan_min[1] = FAN_TO_REG(min,
20731 +                                       DIV_FROM_REG(data->fan_div[1]));
20732 +                       lm78_write_value(client, LM78_REG_FAN_MIN(2),
20733 +                                       data->fan_min[1]);
20734 +               }
20735 +               if (*nrels_mag >= 1) {
20736 +                       min = FAN_FROM_REG(data->fan_min[0],
20737 +                                       DIV_FROM_REG(data->fan_div[0]));
20738 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
20739 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
20740 +                       data->fan_min[0] = FAN_TO_REG(min,
20741 +                                       DIV_FROM_REG(data->fan_div[0]));
20742 +                       lm78_write_value(client, LM78_REG_FAN_MIN(1),
20743 +                                       data->fan_min[0]);
20744 +                       lm78_write_value(client, LM78_REG_VID_FANDIV, old);
20745 +               }
20746 +       }
20747 +}
20748 +
20749 +static int __init sm_lm78_init(void)
20750 +{
20751 +       printk("lm78.o version %s (%s)\n", LM_VERSION, LM_DATE);
20752 +       return i2c_add_driver(&lm78_driver);
20753 +}
20754 +
20755 +static void __exit sm_lm78_exit(void)
20756 +{
20757 +       i2c_del_driver(&lm78_driver);
20758 +}
20759 +
20760 +
20761 +
20762 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
20763 +MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
20764 +
20765 +module_init(sm_lm78_init);
20766 +module_exit(sm_lm78_exit);
20767 --- linux-old/drivers/sensors/lm80.c    Thu Jan  1 00:00:00 1970
20768 +++ linux/drivers/sensors/lm80.c        Mon Dec 13 20:18:48 2004
20769 @@ -0,0 +1,606 @@
20770 +/*
20771 +    lm80.c - Part of lm_sensors, Linux kernel modules for hardware
20772 +             monitoring
20773 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
20774 +    and Philip Edelbrock <phil@netroedge.com>
20775 +
20776 +    This program is free software; you can redistribute it and/or modify
20777 +    it under the terms of the GNU General Public License as published by
20778 +    the Free Software Foundation; either version 2 of the License, or
20779 +    (at your option) any later version.
20780 +
20781 +    This program is distributed in the hope that it will be useful,
20782 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
20783 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20784 +    GNU General Public License for more details.
20785 +
20786 +    You should have received a copy of the GNU General Public License
20787 +    along with this program; if not, write to the Free Software
20788 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20789 +*/
20790 +
20791 +#include <linux/module.h>
20792 +#include <linux/slab.h>
20793 +#include <linux/i2c.h>
20794 +#include <linux/i2c-proc.h>
20795 +#include <linux/init.h>
20796 +#define LM_DATE "20041007"
20797 +#define LM_VERSION "2.8.8"
20798 +
20799 +MODULE_LICENSE("GPL");
20800 +
20801 +/* Addresses to scan */
20802 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
20803 +static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
20804 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
20805 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
20806 +
20807 +/* Insmod parameters */
20808 +SENSORS_INSMOD_1(lm80);
20809 +
20810 +/* Many LM80 constants specified below */
20811 +
20812 +/* The LM80 registers */
20813 +#define LM80_REG_IN_MAX(nr) (0x2a + (nr) * 2)
20814 +#define LM80_REG_IN_MIN(nr) (0x2b + (nr) * 2)
20815 +#define LM80_REG_IN(nr) (0x20 + (nr))
20816 +
20817 +#define LM80_REG_FAN1_MIN 0x3c
20818 +#define LM80_REG_FAN2_MIN 0x3d
20819 +#define LM80_REG_FAN1 0x28
20820 +#define LM80_REG_FAN2 0x29
20821 +
20822 +#define LM80_REG_TEMP 0x27
20823 +#define LM80_REG_TEMP_HOT_MAX 0x38
20824 +#define LM80_REG_TEMP_HOT_HYST 0x39
20825 +#define LM80_REG_TEMP_OS_MAX 0x3a
20826 +#define LM80_REG_TEMP_OS_HYST 0x3b
20827 +
20828 +#define LM80_REG_CONFIG 0x00
20829 +#define LM80_REG_ALARM1 0x01
20830 +#define LM80_REG_ALARM2 0x02
20831 +#define LM80_REG_MASK1 0x03
20832 +#define LM80_REG_MASK2 0x04
20833 +#define LM80_REG_FANDIV 0x05
20834 +#define LM80_REG_RES 0x06
20835 +
20836 +
20837 +/* Conversions. Rounding and limit checking is only done on the TO_REG
20838 +   variants. Note that you should be a bit careful with which arguments
20839 +   these macros are called: arguments may be evaluated more than once.
20840 +   Fixing this is just not worth it. */
20841 +
20842 +#define IN_TO_REG(val) (SENSORS_LIMIT((val),0,255))
20843 +#define IN_FROM_REG(val) (val)
20844 +
20845 +static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)
20846 +{
20847 +       if (rpm == 0)
20848 +               return 255;
20849 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
20850 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
20851 +                            254);
20852 +}
20853 +
20854 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
20855 +                               (val)==255?0:1350000/((div)*(val)))
20856 +
20857 +static inline long TEMP_FROM_REG(u16 temp)
20858 +{
20859 +       long res;
20860 +
20861 +       temp >>= 4;
20862 +       if (temp < 0x0800)
20863 +               res = 625 * (long) temp;
20864 +       else
20865 +               res = ((long) temp - 0x01000) * 625;
20866 +
20867 +       return res / 100;
20868 +}
20869 +
20870 +#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*100)
20871 +
20872 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-50)/100):\
20873 +                                                      ((val)+50)/100), \
20874 +                                             0,255)
20875 +
20876 +#define ALARMS_FROM_REG(val) (val)
20877 +
20878 +#define DIV_FROM_REG(val) (1 << (val))
20879 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
20880 +
20881 +struct lm80_data {
20882 +       struct i2c_client client;
20883 +       int sysctl_id;
20884 +
20885 +       struct semaphore update_lock;
20886 +       char valid;             /* !=0 if following fields are valid */
20887 +       unsigned long last_updated;     /* In jiffies */
20888 +
20889 +       u8 in[7];               /* Register value */
20890 +       u8 in_max[7];           /* Register value */
20891 +       u8 in_min[7];           /* Register value */
20892 +       u8 fan[2];              /* Register value */
20893 +       u8 fan_min[2];          /* Register value */
20894 +       u8 fan_div[2];          /* Register encoding, shifted right */
20895 +       u16 temp;               /* Register values, shifted right */
20896 +       u8 temp_hot_max;        /* Register value */
20897 +       u8 temp_hot_hyst;       /* Register value */
20898 +       u8 temp_os_max;         /* Register value */
20899 +       u8 temp_os_hyst;        /* Register value */
20900 +       u16 alarms;             /* Register encoding, combined */
20901 +};
20902 +
20903 +
20904 +
20905 +static int lm80_attach_adapter(struct i2c_adapter *adapter);
20906 +static int lm80_detect(struct i2c_adapter *adapter, int address,
20907 +                      unsigned short flags, int kind);
20908 +static int lm80_detach_client(struct i2c_client *client);
20909 +
20910 +static int lm80_read_value(struct i2c_client *client, u8 reg);
20911 +static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
20912 +static void lm80_update_client(struct i2c_client *client);
20913 +static void lm80_init_client(struct i2c_client *client);
20914 +
20915 +
20916 +static void lm80_in(struct i2c_client *client, int operation, int ctl_name,
20917 +                   int *nrels_mag, long *results);
20918 +static void lm80_fan(struct i2c_client *client, int operation,
20919 +                    int ctl_name, int *nrels_mag, long *results);
20920 +static void lm80_temp(struct i2c_client *client, int operation,
20921 +                     int ctl_name, int *nrels_mag, long *results);
20922 +static void lm80_alarms(struct i2c_client *client, int operation,
20923 +                       int ctl_name, int *nrels_mag, long *results);
20924 +static void lm80_fan_div(struct i2c_client *client, int operation,
20925 +                        int ctl_name, int *nrels_mag, long *results);
20926 +
20927 +static int lm80_id = 0;
20928 +
20929 +static struct i2c_driver lm80_driver = {
20930 +       .owner          = THIS_MODULE,
20931 +       .name           = "LM80 sensor driver",
20932 +       .id             = I2C_DRIVERID_LM80,
20933 +       .flags          = I2C_DF_NOTIFY,
20934 +       .attach_adapter = lm80_attach_adapter,
20935 +       .detach_client  = lm80_detach_client,
20936 +};
20937 +
20938 +/* The /proc/sys entries */
20939 +
20940 +/* -- SENSORS SYSCTL START -- */
20941 +
20942 +#define LM80_SYSCTL_IN0 1000   /* Volts * 100 */
20943 +#define LM80_SYSCTL_IN1 1001
20944 +#define LM80_SYSCTL_IN2 1002
20945 +#define LM80_SYSCTL_IN3 1003
20946 +#define LM80_SYSCTL_IN4 1004
20947 +#define LM80_SYSCTL_IN5 1005
20948 +#define LM80_SYSCTL_IN6 1006
20949 +#define LM80_SYSCTL_FAN1 1101  /* Rotations/min */
20950 +#define LM80_SYSCTL_FAN2 1102
20951 +#define LM80_SYSCTL_TEMP 1250  /* Degrees Celcius * 100 */
20952 +#define LM80_SYSCTL_FAN_DIV 2000       /* 1, 2, 4 or 8 */
20953 +#define LM80_SYSCTL_ALARMS 2001        /* bitvector */
20954 +
20955 +#define LM80_ALARM_IN0 0x0001
20956 +#define LM80_ALARM_IN1 0x0002
20957 +#define LM80_ALARM_IN2 0x0004
20958 +#define LM80_ALARM_IN3 0x0008
20959 +#define LM80_ALARM_IN4 0x0010
20960 +#define LM80_ALARM_IN5 0x0020
20961 +#define LM80_ALARM_IN6 0x0040
20962 +#define LM80_ALARM_FAN1 0x0400
20963 +#define LM80_ALARM_FAN2 0x0800
20964 +#define LM80_ALARM_TEMP_HOT 0x0100
20965 +#define LM80_ALARM_TEMP_OS 0x2000
20966 +#define LM80_ALARM_CHAS 0x1000
20967 +#define LM80_ALARM_BTI 0x0200
20968 +#define LM80_ALARM_INT_IN 0x0080
20969 +
20970 +/* -- SENSORS SYSCTL END -- */
20971 +
20972 +/* These files are created for each detected LM80. This is just a template;
20973 +   though at first sight, you might think we could use a statically
20974 +   allocated list, we need some way to get back to the parent - which
20975 +   is done through one of the 'extra' fields which are initialized 
20976 +   when a new copy is allocated. */
20977 +static ctl_table lm80_dir_table_template[] = {
20978 +       {LM80_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
20979 +        &i2c_sysctl_real, NULL, &lm80_in},
20980 +       {LM80_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
20981 +        &i2c_sysctl_real, NULL, &lm80_in},
20982 +       {LM80_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
20983 +        &i2c_sysctl_real, NULL, &lm80_in},
20984 +       {LM80_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
20985 +        &i2c_sysctl_real, NULL, &lm80_in},
20986 +       {LM80_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
20987 +        &i2c_sysctl_real, NULL, &lm80_in},
20988 +       {LM80_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
20989 +        &i2c_sysctl_real, NULL, &lm80_in},
20990 +       {LM80_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
20991 +        &i2c_sysctl_real, NULL, &lm80_in},
20992 +       {LM80_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
20993 +        &i2c_sysctl_real, NULL, &lm80_fan},
20994 +       {LM80_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
20995 +        &i2c_sysctl_real, NULL, &lm80_fan},
20996 +       {LM80_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
20997 +        &i2c_sysctl_real, NULL, &lm80_temp},
20998 +       {LM80_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
20999 +        &i2c_sysctl_real, NULL, &lm80_fan_div},
21000 +       {LM80_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
21001 +        &i2c_sysctl_real, NULL, &lm80_alarms},
21002 +       {0}
21003 +};
21004 +
21005 +static int lm80_attach_adapter(struct i2c_adapter *adapter)
21006 +{
21007 +       return i2c_detect(adapter, &addr_data, lm80_detect);
21008 +}
21009 +
21010 +int lm80_detect(struct i2c_adapter *adapter, int address,
21011 +               unsigned short flags, int kind)
21012 +{
21013 +       int i, cur;
21014 +       struct i2c_client *new_client;
21015 +       struct lm80_data *data;
21016 +       int err = 0;
21017 +       const char *type_name, *client_name;
21018 +
21019 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
21020 +          at this moment; i2c_detect really won't call us. */
21021 +#ifdef DEBUG
21022 +       if (i2c_is_isa_adapter(adapter)) {
21023 +               printk
21024 +                   ("lm80.o: lm80_detect called for an ISA bus adapter?!?\n");
21025 +               return 0;
21026 +       }
21027 +#endif
21028 +
21029 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
21030 +               goto ERROR0;
21031 +
21032 +       /* OK. For now, we presume we have a valid client. We now create the
21033 +          client structure, even though we cannot fill it completely yet.
21034 +          But it allows us to access lm80_{read,write}_value. */
21035 +       if (!(data = kmalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
21036 +               err = -ENOMEM;
21037 +               goto ERROR0;
21038 +       }
21039 +
21040 +       new_client = &data->client;
21041 +       new_client->addr = address;
21042 +       new_client->data = data;
21043 +       new_client->adapter = adapter;
21044 +       new_client->driver = &lm80_driver;
21045 +       new_client->flags = 0;
21046 +
21047 +       /* Now, we do the remaining detection. It is lousy. */
21048 +       if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0)
21049 +               goto ERROR1;
21050 +       for (i = 0x2a; i <= 0x3d; i++) {
21051 +               cur = i2c_smbus_read_byte_data(new_client, i);
21052 +               if ((i2c_smbus_read_byte_data(new_client, i + 0x40) != cur)
21053 +                   || (i2c_smbus_read_byte_data(new_client, i + 0x80) !=
21054 +                       cur)
21055 +                   || (i2c_smbus_read_byte_data(new_client, i + 0xc0) !=
21056 +                       cur)) goto ERROR1;
21057 +       }
21058 +
21059 +       /* Determine the chip type - only one kind supported! */
21060 +       if (kind <= 0)
21061 +               kind = lm80;
21062 +
21063 +       if (kind == lm80) {
21064 +               type_name = "lm80";
21065 +               client_name = "LM80 chip";
21066 +       } else {
21067 +#ifdef DEBUG
21068 +               printk("lm80.o: Internal error: unknown kind (%d)?!?",
21069 +                      kind);
21070 +#endif
21071 +               goto ERROR1;
21072 +       }
21073 +
21074 +       /* Fill in the remaining client fields and put it into the global list */
21075 +       strcpy(new_client->name, client_name);
21076 +
21077 +       new_client->id = lm80_id++;
21078 +       data->valid = 0;
21079 +       init_MUTEX(&data->update_lock);
21080 +
21081 +       /* Tell the I2C layer a new client has arrived */
21082 +       if ((err = i2c_attach_client(new_client)))
21083 +               goto ERROR3;
21084 +
21085 +       /* Register a new directory entry with module sensors */
21086 +       if ((i = i2c_register_entry(new_client, type_name,
21087 +                                       lm80_dir_table_template)) < 0) {
21088 +               err = i;
21089 +               goto ERROR4;
21090 +       }
21091 +       data->sysctl_id = i;
21092 +
21093 +       lm80_init_client(new_client);
21094 +       return 0;
21095 +
21096 +/* OK, this is not exactly good programming practice, usually. But it is
21097 +   very code-efficient in this case. */
21098 +      ERROR4:
21099 +       i2c_detach_client(new_client);
21100 +      ERROR3:
21101 +      ERROR1:
21102 +       kfree(data);
21103 +      ERROR0:
21104 +       return err;
21105 +}
21106 +
21107 +static int lm80_detach_client(struct i2c_client *client)
21108 +{
21109 +       int err;
21110 +
21111 +       i2c_deregister_entry(((struct lm80_data *) (client->data))->
21112 +                                sysctl_id);
21113 +
21114 +       if ((err = i2c_detach_client(client))) {
21115 +               printk
21116 +                   ("lm80.o: Client deregistration failed, client not detached.\n");
21117 +               return err;
21118 +       }
21119 +
21120 +       kfree(client->data);
21121 +
21122 +       return 0;
21123 +}
21124 +
21125 +static int lm80_read_value(struct i2c_client *client, u8 reg)
21126 +{
21127 +       return i2c_smbus_read_byte_data(client, reg);
21128 +}
21129 +
21130 +static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value)
21131 +{
21132 +       return i2c_smbus_write_byte_data(client, reg, value);
21133 +}
21134 +
21135 +/* Called when we have found a new LM80. */
21136 +static void lm80_init_client(struct i2c_client *client)
21137 +{
21138 +       /* Reset all except Watchdog values and last conversion values
21139 +          This sets fan-divs to 2, among others. This makes most other
21140 +          initializations unnecessary */
21141 +       lm80_write_value(client, LM80_REG_CONFIG, 0x80);
21142 +       /* Set 11-bit temperature resolution */
21143 +       lm80_write_value(client, LM80_REG_RES, 0x08);
21144 +
21145 +       /* Start monitoring */
21146 +       lm80_write_value(client, LM80_REG_CONFIG, 0x01);
21147 +}
21148 +
21149 +static void lm80_update_client(struct i2c_client *client)
21150 +{
21151 +       struct lm80_data *data = client->data;
21152 +       int i;
21153 +
21154 +       down(&data->update_lock);
21155 +
21156 +       if ((jiffies - data->last_updated > 2 * HZ) ||
21157 +           (jiffies < data->last_updated) || !data->valid) {
21158 +
21159 +#ifdef DEBUG
21160 +               printk("Starting lm80 update\n");
21161 +#endif
21162 +               for (i = 0; i <= 6; i++) {
21163 +                       data->in[i] =
21164 +                           lm80_read_value(client, LM80_REG_IN(i));
21165 +                       data->in_min[i] =
21166 +                           lm80_read_value(client, LM80_REG_IN_MIN(i));
21167 +                       data->in_max[i] =
21168 +                           lm80_read_value(client, LM80_REG_IN_MAX(i));
21169 +               }
21170 +               data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
21171 +               data->fan_min[0] =
21172 +                   lm80_read_value(client, LM80_REG_FAN1_MIN);
21173 +               data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
21174 +               data->fan_min[1] =
21175 +                   lm80_read_value(client, LM80_REG_FAN2_MIN);
21176 +
21177 +               data->temp =
21178 +                   (lm80_read_value(client, LM80_REG_TEMP) << 8) |
21179 +                   (lm80_read_value(client, LM80_REG_RES) & 0xf0);
21180 +               data->temp_os_max =
21181 +                   lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
21182 +               data->temp_os_hyst =
21183 +                   lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
21184 +               data->temp_hot_max =
21185 +                   lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
21186 +               data->temp_hot_hyst =
21187 +                   lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
21188 +
21189 +               i = lm80_read_value(client, LM80_REG_FANDIV);
21190 +               data->fan_div[0] = (i >> 2) & 0x03;
21191 +               data->fan_div[1] = (i >> 4) & 0x03;
21192 +               data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +
21193 +                   (lm80_read_value(client, LM80_REG_ALARM2) << 8);
21194 +               data->last_updated = jiffies;
21195 +               data->valid = 1;
21196 +       }
21197 +
21198 +       up(&data->update_lock);
21199 +}
21200 +
21201 +
21202 +/* The next few functions are the call-back functions of the /proc/sys and
21203 +   sysctl files. Which function is used is defined in the ctl_table in
21204 +   the extra1 field.
21205 +   Each function must return the magnitude (power of 10 to divide the date
21206 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
21207 +   put a maximum of *nrels elements in results reflecting the data of this
21208 +   file, and set *nrels to the number it actually put in it, if operation==
21209 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
21210 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
21211 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
21212 +   large enough (by checking the incoming value of *nrels). This is not very
21213 +   good practice, but as long as you put less than about 5 values in results,
21214 +   you can assume it is large enough. */
21215 +void lm80_in(struct i2c_client *client, int operation, int ctl_name,
21216 +            int *nrels_mag, long *results)
21217 +{
21218 +       struct lm80_data *data = client->data;
21219 +       int nr = ctl_name - LM80_SYSCTL_IN0;
21220 +
21221 +       if (operation == SENSORS_PROC_REAL_INFO)
21222 +               *nrels_mag = 2;
21223 +       else if (operation == SENSORS_PROC_REAL_READ) {
21224 +               lm80_update_client(client);
21225 +               results[0] = IN_FROM_REG(data->in_min[nr]);
21226 +               results[1] = IN_FROM_REG(data->in_max[nr]);
21227 +               results[2] = IN_FROM_REG(data->in[nr]);
21228 +               *nrels_mag = 3;
21229 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
21230 +               if (*nrels_mag >= 1) {
21231 +                       data->in_min[nr] = IN_TO_REG(results[0]);
21232 +                       lm80_write_value(client, LM80_REG_IN_MIN(nr),
21233 +                                        data->in_min[nr]);
21234 +               }
21235 +               if (*nrels_mag >= 2) {
21236 +                       data->in_max[nr] = IN_TO_REG(results[1]);
21237 +                       lm80_write_value(client, LM80_REG_IN_MAX(nr),
21238 +                                        data->in_max[nr]);
21239 +               }
21240 +       }
21241 +}
21242 +
21243 +void lm80_fan(struct i2c_client *client, int operation, int ctl_name,
21244 +             int *nrels_mag, long *results)
21245 +{
21246 +       struct lm80_data *data = client->data;
21247 +       int nr = ctl_name - LM80_SYSCTL_FAN1 + 1;
21248 +
21249 +       if (operation == SENSORS_PROC_REAL_INFO)
21250 +               *nrels_mag = 0;
21251 +       else if (operation == SENSORS_PROC_REAL_READ) {
21252 +               lm80_update_client(client);
21253 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
21254 +                                         DIV_FROM_REG(data->
21255 +                                                      fan_div[nr - 1]));
21256 +               results[1] =
21257 +                   FAN_FROM_REG(data->fan[nr - 1],
21258 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
21259 +               *nrels_mag = 2;
21260 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
21261 +               if (*nrels_mag >= 1) {
21262 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0],
21263 +                                                          DIV_FROM_REG
21264 +                                                          (data->
21265 +                                                           fan_div[nr -
21266 +                                                                   1]));
21267 +                       lm80_write_value(client,
21268 +                                        nr ==
21269 +                                        1 ? LM80_REG_FAN1_MIN :
21270 +                                        LM80_REG_FAN2_MIN,
21271 +                                        data->fan_min[nr - 1]);
21272 +               }
21273 +       }
21274 +}
21275 +
21276 +
21277 +void lm80_temp(struct i2c_client *client, int operation, int ctl_name,
21278 +              int *nrels_mag, long *results)
21279 +{
21280 +       struct lm80_data *data = client->data;
21281 +       if (operation == SENSORS_PROC_REAL_INFO)
21282 +               *nrels_mag = 2;
21283 +       else if (operation == SENSORS_PROC_REAL_READ) {
21284 +               lm80_update_client(client);
21285 +               results[0] = TEMP_LIMIT_FROM_REG(data->temp_hot_max);
21286 +               results[1] = TEMP_LIMIT_FROM_REG(data->temp_hot_hyst);
21287 +               results[2] = TEMP_LIMIT_FROM_REG(data->temp_os_max);
21288 +               results[3] = TEMP_LIMIT_FROM_REG(data->temp_os_hyst);
21289 +               results[4] = TEMP_FROM_REG(data->temp);
21290 +               *nrels_mag = 5;
21291 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
21292 +               if (*nrels_mag >= 1) {
21293 +                       data->temp_hot_max = TEMP_LIMIT_TO_REG(results[0]);
21294 +                       lm80_write_value(client, LM80_REG_TEMP_HOT_MAX,
21295 +                                        data->temp_hot_max);
21296 +               }
21297 +               if (*nrels_mag >= 2) {
21298 +                       data->temp_hot_hyst =
21299 +                           TEMP_LIMIT_TO_REG(results[1]);
21300 +                       lm80_write_value(client, LM80_REG_TEMP_HOT_HYST,
21301 +                                        data->temp_hot_hyst);
21302 +               }
21303 +               if (*nrels_mag >= 3) {
21304 +                       data->temp_os_max = TEMP_LIMIT_TO_REG(results[2]);
21305 +                       lm80_write_value(client, LM80_REG_TEMP_OS_MAX,
21306 +                                        data->temp_os_max);
21307 +               }
21308 +               if (*nrels_mag >= 4) {
21309 +                       data->temp_os_hyst = TEMP_LIMIT_TO_REG(results[3]);
21310 +                       lm80_write_value(client, LM80_REG_TEMP_OS_HYST,
21311 +                                        data->temp_os_hyst);
21312 +               }
21313 +       }
21314 +}
21315 +
21316 +void lm80_alarms(struct i2c_client *client, int operation, int ctl_name,
21317 +                int *nrels_mag, long *results)
21318 +{
21319 +       struct lm80_data *data = client->data;
21320 +       if (operation == SENSORS_PROC_REAL_INFO)
21321 +               *nrels_mag = 0;
21322 +       else if (operation == SENSORS_PROC_REAL_READ) {
21323 +               lm80_update_client(client);
21324 +               results[0] = ALARMS_FROM_REG(data->alarms);
21325 +               *nrels_mag = 1;
21326 +       }
21327 +}
21328 +
21329 +void lm80_fan_div(struct i2c_client *client, int operation, int ctl_name,
21330 +                 int *nrels_mag, long *results)
21331 +{
21332 +       struct lm80_data *data = client->data;
21333 +       int old;
21334 +
21335 +       if (operation == SENSORS_PROC_REAL_INFO)
21336 +               *nrels_mag = 0;
21337 +       else if (operation == SENSORS_PROC_REAL_READ) {
21338 +               lm80_update_client(client);
21339 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
21340 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
21341 +               results[2] = 2;
21342 +               *nrels_mag = 3;
21343 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
21344 +               old = lm80_read_value(client, LM80_REG_FANDIV);
21345 +               if (*nrels_mag >= 2) {
21346 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
21347 +                       old = (old & 0xcf) | (data->fan_div[1] << 4);
21348 +               }
21349 +               if (*nrels_mag >= 1) {
21350 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
21351 +                       old = (old & 0xf3) | (data->fan_div[0] << 2);
21352 +                       lm80_write_value(client, LM80_REG_FANDIV, old);
21353 +               }
21354 +       }
21355 +}
21356 +
21357 +static int __init sm_lm80_init(void)
21358 +{
21359 +       printk("lm80.o version %s (%s)\n", LM_VERSION, LM_DATE);
21360 +       return i2c_add_driver(&lm80_driver);
21361 +}
21362 +
21363 +static void __exit sm_lm80_exit(void)
21364 +{
21365 +       i2c_del_driver(&lm80_driver);
21366 +}
21367 +
21368 +
21369 +
21370 +MODULE_AUTHOR
21371 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
21372 +MODULE_DESCRIPTION("LM80 driver");
21373 +
21374 +module_init(sm_lm80_init);
21375 +module_exit(sm_lm80_exit);
21376 --- linux-old/drivers/sensors/lm83.c    Thu Jan  1 00:00:00 1970
21377 +++ linux/drivers/sensors/lm83.c        Mon Dec 13 20:18:48 2004
21378 @@ -0,0 +1,513 @@
21379 +/*
21380 + * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
21381 + *          monitoring
21382 + * Copyright (C) 2003  Jean Delvare <khali@linux-fr.org>
21383 + *
21384 + * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
21385 + * a sensor chip made by National Semiconductor. It reports up to four
21386 + * temperatures (its own plus up to three external ones) with a 1 deg
21387 + * resolution and a 3-4 deg accuracy. Complete datasheet can be obtained
21388 + * from National's website at:
21389 + *   http://www.national.com/pf/LM/LM83.html
21390 + * Since the datasheet omits to give the chip stepping code, I give it
21391 + * here: 0x03 (at register 0xff).
21392 + *
21393 + * This program is free software; you can redistribute it and/or modify
21394 + * it under the terms of the GNU General Public License as published by
21395 + * the Free Software Foundation; either version 2 of the License, or
21396 + * (at your option) any later version.
21397 + *
21398 + * This program is distributed in the hope that it will be useful,
21399 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21400 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21401 + * GNU General Public License for more details.
21402 + *
21403 + * You should have received a copy of the GNU General Public License
21404 + * along with this program; if not, write to the Free Software
21405 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21406 + */
21407 +
21408 +#include <linux/module.h>
21409 +#include <linux/slab.h>
21410 +#include <linux/i2c.h>
21411 +#include <linux/i2c-proc.h>
21412 +#include <linux/init.h>
21413 +#define LM_DATE "20041007"
21414 +#define LM_VERSION "2.8.8"
21415 +
21416 +/*
21417 + * Addresses to scan
21418 + * Address is selected using 2 three-level pins, resulting in 9 possible
21419 + * addresses.
21420 + */
21421 +
21422 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
21423 +static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b,
21424 +       0x4c, 0x4e, SENSORS_I2C_END };
21425 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
21426 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
21427 +
21428 +/*
21429 + * Insmod parameters
21430 + */
21431 +
21432 +SENSORS_INSMOD_1(lm83);
21433 +
21434 +/*
21435 + * The LM83 registers
21436 + * Manufacturer ID is 0x01 for National Semiconductor.
21437 + */
21438 +
21439 +#define LM83_REG_R_MAN_ID        0xFE
21440 +#define LM83_REG_R_CHIP_ID       0xFF
21441 +#define LM83_REG_R_CONFIG        0x03
21442 +#define LM83_REG_W_CONFIG        0x09
21443 +#define LM83_REG_R_STATUS1       0x02
21444 +#define LM83_REG_R_STATUS2       0x35
21445 +#define LM83_REG_R_LOCAL_TEMP    0x00
21446 +#define LM83_REG_R_LOCAL_HIGH    0x05
21447 +#define LM83_REG_W_LOCAL_HIGH    0x0B
21448 +#define LM83_REG_R_REMOTE1_TEMP  0x30
21449 +#define LM83_REG_R_REMOTE1_HIGH  0x38
21450 +#define LM83_REG_W_REMOTE1_HIGH  0x50
21451 +#define LM83_REG_R_REMOTE2_TEMP  0x01
21452 +#define LM83_REG_R_REMOTE2_HIGH  0x07
21453 +#define LM83_REG_W_REMOTE2_HIGH  0x0D
21454 +#define LM83_REG_R_REMOTE3_TEMP  0x31
21455 +#define LM83_REG_R_REMOTE3_HIGH  0x3A
21456 +#define LM83_REG_W_REMOTE3_HIGH  0x52
21457 +#define LM83_REG_R_TCRIT         0x42
21458 +#define LM83_REG_W_TCRIT         0x5A
21459 +
21460 +/*
21461 + * Conversions and various macros
21462 + * The LM83 uses signed 8-bit values.
21463 + */
21464 +
21465 +#define TEMP_FROM_REG(val)  ((val) > 127 ? (val) - 0x100 : (val))
21466 +#define TEMP_TO_REG(val)    ((val) <= -50 ? -50 + 0x100 : \
21467 +                             (val) >= 127 ? 127 : \
21468 +                            (val) >= 0 ? (val) : \
21469 +                             (val) + 0x100)
21470 +
21471 +static const u8 LM83_REG_R_TEMP[] = {
21472 +       LM83_REG_R_LOCAL_TEMP,
21473 +       LM83_REG_R_REMOTE1_TEMP,
21474 +       LM83_REG_R_REMOTE2_TEMP,
21475 +       LM83_REG_R_REMOTE3_TEMP
21476 +};
21477 +
21478 +static const u8 LM83_REG_R_HIGH[] = {
21479 +       LM83_REG_R_LOCAL_HIGH,
21480 +       LM83_REG_R_REMOTE1_HIGH,
21481 +       LM83_REG_R_REMOTE2_HIGH,
21482 +       LM83_REG_R_REMOTE3_HIGH
21483 +};
21484 +
21485 +static const u8 LM83_REG_W_HIGH[] = {
21486 +       LM83_REG_W_LOCAL_HIGH,
21487 +       LM83_REG_W_REMOTE1_HIGH,
21488 +       LM83_REG_W_REMOTE2_HIGH,
21489 +       LM83_REG_W_REMOTE3_HIGH
21490 +};
21491 +
21492 +/*
21493 + * Functions declaration
21494 + */
21495 +
21496 +static int lm83_attach_adapter(struct i2c_adapter *adapter);
21497 +static int lm83_detect(struct i2c_adapter *adapter, int address, unsigned
21498 +       short flags, int kind);
21499 +static int lm83_detach_client(struct i2c_client *client);
21500 +static void lm83_update_client(struct i2c_client *client);
21501 +static void lm83_temp(struct i2c_client *client, int operation, int
21502 +       ctl_name, int *nrels_mag, long *results);
21503 +static void lm83_tcrit(struct i2c_client *client, int operation, int
21504 +       ctl_name, int *nrels_mag, long *results);
21505 +static void lm83_alarms(struct i2c_client *client, int operation, int
21506 +       ctl_name, int *nrels_mag, long *results);
21507 +
21508 +/*
21509 + * Driver data (common to all clients)
21510 + */
21511
21512 +static struct i2c_driver lm83_driver = {
21513 +       .owner          = THIS_MODULE,
21514 +       .name           = "LM83 sensor driver",
21515 +       .id             = I2C_DRIVERID_LM83,
21516 +       .flags          = I2C_DF_NOTIFY,
21517 +       .attach_adapter = lm83_attach_adapter,
21518 +       .detach_client  = lm83_detach_client,
21519 +};
21520 +
21521 +/*
21522 + * Client data (each client gets its own)
21523 + */
21524 +
21525 +struct lm83_data
21526 +{
21527 +       struct i2c_client client;
21528 +       int sysctl_id;
21529 +
21530 +       struct semaphore update_lock;
21531 +       char valid; /* zero until following fields are valid */
21532 +       unsigned long last_updated; /* in jiffies */
21533 +
21534 +       /* registers values */
21535 +       u8 temp[4], temp_high[4], tcrit;
21536 +       u16 alarms; /* bitvector, combined */
21537 +};
21538 +
21539 +/*
21540 + * Proc entries
21541 + * These files are created for each detected LM83.
21542 + */
21543 +
21544 +/* -- SENSORS SYSCTL START -- */
21545 +
21546 +#define LM83_SYSCTL_LOCAL_TEMP    1200
21547 +#define LM83_SYSCTL_REMOTE1_TEMP  1201
21548 +#define LM83_SYSCTL_REMOTE2_TEMP  1202
21549 +#define LM83_SYSCTL_REMOTE3_TEMP  1203
21550 +#define LM83_SYSCTL_TCRIT         1208
21551 +#define LM83_SYSCTL_ALARMS        1210
21552 +
21553 +#define LM83_ALARM_LOCAL_HIGH     0x0040
21554 +#define LM83_ALARM_LOCAL_CRIT     0x0001
21555 +#define LM83_ALARM_REMOTE1_HIGH   0x8000
21556 +#define LM83_ALARM_REMOTE1_CRIT   0x0100
21557 +#define LM83_ALARM_REMOTE1_OPEN   0x2000
21558 +#define LM83_ALARM_REMOTE2_HIGH   0x0010
21559 +#define LM83_ALARM_REMOTE2_CRIT   0x0002
21560 +#define LM83_ALARM_REMOTE2_OPEN   0x0004
21561 +#define LM83_ALARM_REMOTE3_HIGH   0x1000
21562 +#define LM83_ALARM_REMOTE3_CRIT   0x0200
21563 +#define LM83_ALARM_REMOTE3_OPEN   0x0400
21564 +
21565 +/* -- SENSORS SYSCTL END -- */
21566 +
21567 +
21568 +static ctl_table lm83_dir_table_template[] =
21569 +{
21570 +       {LM83_SYSCTL_LOCAL_TEMP, "temp1", NULL, 0, 0644, NULL,
21571 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm83_temp},
21572 +       {LM83_SYSCTL_REMOTE1_TEMP, "temp2", NULL, 0, 0644, NULL,
21573 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm83_temp},
21574 +       {LM83_SYSCTL_REMOTE2_TEMP, "temp3", NULL, 0, 0644, NULL,
21575 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm83_temp},
21576 +       {LM83_SYSCTL_REMOTE3_TEMP, "temp4", NULL, 0, 0644, NULL,
21577 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm83_temp},
21578 +       {LM83_SYSCTL_TCRIT, "tcrit", NULL, 0, 0644, NULL,
21579 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm83_tcrit},
21580 +       {LM83_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
21581 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm83_alarms},
21582 +       {0}
21583 +};
21584 +
21585 +/*
21586 + * Internal variables
21587 + */
21588 +
21589 +static int lm83_id = 0;
21590 +
21591 +/*
21592 + * Real code
21593 + */
21594 +
21595 +static int lm83_attach_adapter(struct i2c_adapter *adapter)
21596 +{
21597 +       return i2c_detect(adapter, &addr_data, lm83_detect);
21598 +}
21599 +
21600 +/*
21601 + * The following function does more than just detection. If detection
21602 + * succeeds, it also registers the new chip.
21603 + */
21604 +static int lm83_detect(struct i2c_adapter *adapter, int address, unsigned
21605 +       short flags, int kind)
21606 +{
21607 +       struct i2c_client *new_client;
21608 +       struct lm83_data *data;
21609 +       int err = 0;
21610 +       const char *type_name = "";
21611 +       const char *client_name = "";
21612 +
21613 +#ifdef DEBUG
21614 +       if (i2c_is_isa_adapter(adapter))
21615 +       {
21616 +               printk("lm83.o: Called for an ISA bus adapter, aborting.\n");
21617 +               return 0;
21618 +       }
21619 +#endif
21620 +
21621 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
21622 +       {
21623 +#ifdef DEBUG
21624 +               printk("lm83.o: I2C bus doesn't support byte read mode, "
21625 +                      "skipping.\n");
21626 +#endif
21627 +               return 0;
21628 +       }
21629 +
21630 +       if (!(data = kmalloc(sizeof(struct lm83_data), GFP_KERNEL)))
21631 +       {
21632 +               printk("lm83.o: Out of memory in lm83_detect (new_client).\n");
21633 +               return -ENOMEM;
21634 +       }
21635 +
21636 +       /*
21637 +        * The common I2C client data is placed right before the
21638 +        * LM83-specific data. The LM83-specific data is pointed to by the
21639 +        * data field from the I2C client data.
21640 +        */
21641 +
21642 +       new_client = &data->client;
21643 +       new_client->addr = address;
21644 +       new_client->data = data;
21645 +       new_client->adapter = adapter;
21646 +       new_client->driver = &lm83_driver;
21647 +       new_client->flags = 0;
21648 +
21649 +       /*
21650 +        * Now we do the remaining detection. A negative kind means that
21651 +        * the driver was loaded with no force parameter (default), so we
21652 +        * must both detect and identify the chip (actually there is only
21653 +        * one possible kind of chip for now, LM83). A zero kind means that
21654 +        * the driver was loaded with the force parameter, the detection
21655 +        * step shall be skipped. A positive kind means that the driver
21656 +        * was loaded with the force parameter and a given kind of chip is
21657 +        * requested, so both the detection and the identification steps
21658 +        * are skipped.
21659 +        */
21660 +
21661 +       /* Default to an LM83 if forced */
21662 +       if (kind == 0)
21663 +               kind = lm83;
21664 +
21665 +       if (kind < 0) /* detection */
21666 +       {
21667 +               if (((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1)
21668 +                     & 0xA8) != 0x00)
21669 +               ||  ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2)
21670 +                     & 0x48) != 0x00)
21671 +               ||  ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG)
21672 +                     & 0x41) != 0x00))
21673 +               {
21674 +#ifdef DEBUG
21675 +                       printk(KERN_DEBUG "lm83.o: Detection failed at 0x%02x.\n",
21676 +                               address);
21677 +#endif
21678 +                       goto ERROR1;
21679 +               }
21680 +       }
21681 +
21682 +       if (kind <= 0) /* identification */
21683 +       {
21684 +               u8 man_id, chip_id;
21685 +
21686 +               man_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_MAN_ID);
21687 +               chip_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_CHIP_ID);
21688 +               if (man_id == 0x01) /* National Semiconductor */
21689 +               {
21690 +                       if (chip_id == 0x03)
21691 +                               kind = lm83;
21692 +               }
21693 +       }
21694 +
21695 +       if (kind <= 0) /* identification failed */
21696 +       {
21697 +               printk("lm83.o: Unsupported chip.\n");
21698 +               goto ERROR1;
21699 +       }
21700 +
21701 +       if (kind == lm83)
21702 +       {
21703 +               type_name = "lm83";
21704 +               client_name = "LM83 chip";
21705 +       }
21706 +       else
21707 +       {
21708 +               printk("lm83.o: Unknown kind %d.\n", kind);
21709 +               goto ERROR1;
21710 +       }
21711 +       
21712 +       /*
21713 +        * OK, we got a valid chip so we can fill in the remaining client
21714 +        * fields.
21715 +        */
21716 +
21717 +       strcpy(new_client->name, client_name);
21718 +       new_client->id = lm83_id++;
21719 +       data->valid = 0;
21720 +       init_MUTEX(&data->update_lock);
21721 +
21722 +       /*
21723 +        * Tell the I2C layer a new client has arrived.
21724 +        */
21725 +
21726 +       if ((err = i2c_attach_client(new_client)))
21727 +       {
21728 +#ifdef DEBUG
21729 +               printk("lm83.o: Failed attaching client.\n");
21730 +#endif
21731 +               goto ERROR1;
21732 +       }
21733 +
21734 +       /*
21735 +        * Register a new directory entry.
21736 +        */
21737 +
21738 +       if ((err = i2c_register_entry(new_client, type_name,
21739 +            lm83_dir_table_template)) < 0)
21740 +       {
21741 +#ifdef DEBUG
21742 +               printk("lm83.o: Failed registering directory entry.\n");
21743 +#endif
21744 +               goto ERROR2;
21745 +       }
21746 +       data->sysctl_id = err;
21747 +
21748 +       /*
21749 +        * Initialize the LM83 chip
21750 +        * (Nothing to do for this one.)
21751 +        */
21752 +
21753 +       return 0;
21754 +
21755 +       ERROR2:
21756 +       i2c_detach_client(new_client);
21757 +       ERROR1:
21758 +       kfree(data);
21759 +       return err;
21760 +}
21761 +
21762 +static int lm83_detach_client(struct i2c_client *client)
21763 +{
21764 +       int err;
21765 +
21766 +       i2c_deregister_entry(((struct lm83_data *) (client->data))->sysctl_id);
21767 +       if ((err = i2c_detach_client(client)))
21768 +       {
21769 +               printk("lm83.o: Client deregistration failed, client not "
21770 +                      "detached.\n");
21771 +               return err;
21772 +       }
21773 +
21774 +       kfree(client->data);
21775 +       return 0;
21776 +}
21777 +
21778 +static void lm83_update_client(struct i2c_client *client)
21779 +{
21780 +       struct lm83_data *data = client->data;
21781 +
21782 +       down(&data->update_lock);
21783 +
21784 +       if ((jiffies - data->last_updated > HZ * 2) ||
21785 +           (jiffies < data->last_updated) || !data->valid)
21786 +       {
21787 +               int nr;
21788 +#ifdef DEBUG
21789 +               printk("lm83.o: Updating LM83 data.\n");
21790 +#endif
21791 +               for (nr = 0; nr < 4 ; nr++)
21792 +               {
21793 +                       data->temp[nr] =
21794 +                               i2c_smbus_read_byte_data(client, LM83_REG_R_TEMP[nr]);
21795 +                       data->temp_high[nr] =
21796 +                               i2c_smbus_read_byte_data(client, LM83_REG_R_HIGH[nr]);
21797 +               }
21798 +               data->tcrit = i2c_smbus_read_byte_data(client, LM83_REG_R_TCRIT);
21799 +               data->alarms =
21800 +                       i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1) +
21801 +                       (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2) << 8);
21802 +
21803 +               data->last_updated = jiffies;
21804 +               data->valid = 1;
21805 +       }
21806 +
21807 +       up(&data->update_lock);
21808 +}
21809 +
21810 +static void lm83_temp(struct i2c_client *client, int operation, int
21811 +       ctl_name, int *nrels_mag, long *results)
21812 +{
21813 +       struct lm83_data *data = client->data;
21814 +       int nr = ctl_name - LM83_SYSCTL_LOCAL_TEMP;
21815 +
21816 +       if (operation == SENSORS_PROC_REAL_INFO)
21817 +               *nrels_mag = 0; /* magnitude */
21818 +       else if (operation == SENSORS_PROC_REAL_READ)
21819 +       {
21820 +               lm83_update_client(client);
21821 +               results[0] = TEMP_FROM_REG(data->temp_high[nr]);
21822 +               results[1] = TEMP_FROM_REG(data->temp[nr]);
21823 +               *nrels_mag = 2;
21824 +       }
21825 +       else if (operation == SENSORS_PROC_REAL_WRITE)
21826 +       {
21827 +               if (*nrels_mag >= 1)
21828 +               {
21829 +                       data->temp_high[nr] = TEMP_TO_REG(results[0]);
21830 +                       i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr],
21831 +                                           data->temp_high[nr]);
21832 +               }
21833 +       }
21834 +}
21835 +
21836 +static void lm83_tcrit(struct i2c_client *client, int operation, int
21837 +       ctl_name, int *nrels_mag, long *results)
21838 +{
21839 +       struct lm83_data *data = client->data;
21840 +
21841 +       if (operation == SENSORS_PROC_REAL_INFO)
21842 +               *nrels_mag = 0; /* magnitude */
21843 +       else if (operation == SENSORS_PROC_REAL_READ)
21844 +       {
21845 +               lm83_update_client(client);
21846 +               results[0] = TEMP_FROM_REG(data->tcrit);
21847 +               *nrels_mag = 1;
21848 +       }
21849 +       else if (operation == SENSORS_PROC_REAL_WRITE)
21850 +       {
21851 +               if (*nrels_mag >= 1)
21852 +               {
21853 +                       data->tcrit = TEMP_TO_REG(results[0]);
21854 +                       i2c_smbus_write_byte_data(client, LM83_REG_W_TCRIT,
21855 +                               data->tcrit);
21856 +               }
21857 +       }
21858 +}
21859 +
21860 +static void lm83_alarms(struct i2c_client *client, int operation, int
21861 +       ctl_name, int *nrels_mag, long *results)
21862 +{
21863 +       struct lm83_data *data = client->data;
21864 +
21865 +       if (operation == SENSORS_PROC_REAL_INFO)
21866 +               *nrels_mag = 0; /* magnitude */
21867 +       else if (operation == SENSORS_PROC_REAL_READ)
21868 +       {
21869 +               lm83_update_client(client);
21870 +               results[0] = data->alarms;
21871 +               *nrels_mag = 1;
21872 +       }
21873 +}
21874 +
21875 +static int __init sm_lm83_init(void)
21876 +{
21877 +       printk(KERN_INFO "lm83.o version %s (%s)\n", LM_VERSION, LM_DATE);
21878 +       return i2c_add_driver(&lm83_driver);
21879 +}
21880 +
21881 +static void __exit sm_lm83_exit(void)
21882 +{
21883 +       i2c_del_driver(&lm83_driver);
21884 +}
21885 +
21886 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
21887 +MODULE_DESCRIPTION("LM83 sensor driver");
21888 +MODULE_LICENSE("GPL");
21889 +
21890 +module_init(sm_lm83_init);
21891 +module_exit(sm_lm83_exit);
21892 --- linux-old/drivers/sensors/lm85.c    Thu Jan  1 00:00:00 1970
21893 +++ linux/drivers/sensors/lm85.c        Mon Dec 13 20:18:49 2004
21894 @@ -0,0 +1,2043 @@
21895 +/*
21896 +    lm85.c - Part of lm_sensors, Linux kernel modules for hardware
21897 +             monitoring
21898 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
21899 +    Copyright (c) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
21900 +    Copyright (c) 2003        Margit Schubert-While <margitsw@t-online.de>
21901 +
21902 +    This program is free software; you can redistribute it and/or modify
21903 +    it under the terms of the GNU General Public License as published by
21904 +    the Free Software Foundation; either version 2 of the License, or
21905 +    (at your option) any later version.
21906 +
21907 +    This program is distributed in the hope that it will be useful,
21908 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
21909 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21910 +    GNU General Public License for more details.
21911 +
21912 +    You should have received a copy of the GNU General Public License
21913 +    along with this program; if not, write to the Free Software
21914 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21915 +
21916 +    CHANGELOG
21917 +
21918 +    2002-11-13   First patch for LM85 functionality
21919 +    2002-11-18   LM85 functionality mostly done
21920 +    2002-12-02   Adding ADM1027 functionality
21921 +    2002-12-06   Adding ADT7463 functionality
21922 +    2003-01-09   Code cleanup.
21923 +                 Save reserved bits in case they are implemented
21924 +                    in a future chip.  (Solve problem with lockups
21925 +                    on ADM1027 due to chip initialization)
21926 +                 Added chip initialization bypass option
21927 +    2003-02-12   Add THERM asserted counts for ADT7463
21928 +                 Added #ifdef so we can compile against 2.6.5
21929 +                    without updating i2c-ids.h
21930 +    2003-02-17   Prepare for switch to 2.7.0 development
21931 +                 Implement tmin_control for ADT7463
21932 +                 Expose THERM asserted counts to /proc
21933 +                 Code cleanup
21934 +    2003-02-19   Working with Margit and LM_SENSORS developers
21935 +    2003-02-23   Removed chip initialization entirely
21936 +                 Scale voltages in driver at Margit's request
21937 +                 Change PWM from 0-100% to 0-255 per LM sensors standard
21938 +    2003-02-27   Documentation and code cleanups
21939 +                 Added this CHANGELOG
21940 +                 Print additional precision for temperatures and voltages
21941 +                 Many thanks to Margit Schubert-While and Brandt xxxxxx
21942 +                    for help testing this version
21943 +    2003-02-28   More diagnostic messages regarding BIOS setup
21944 +    2003-03-01   Added Interrupt mask register support.
21945 +    2003-03-08   Fixed problem with pseudo 16-bit registers
21946 +                 Cleaned up some compiler warnings.
21947 +                 Fixed problem with Operating Point and THERM counting
21948 +    2003-03-21   Initial support for EMC6D100 and EMC6D101 chips
21949 +    2003-06-30   Add support for EMC6D100 extra voltage inputs.
21950 +*/
21951 +
21952 +#include <linux/version.h>
21953 +#include <linux/module.h>
21954 +#include <linux/slab.h>
21955 +#include <linux/i2c.h>
21956 +#include <linux/i2c-proc.h>
21957 +#include <linux/init.h>
21958 +#define LM_DATE "20041007"
21959 +#define LM_VERSION "2.8.8"
21960 +#include <linux/sensors_vid.h>
21961 +
21962 +#ifndef I2C_DRIVERID_LM85
21963 +#define I2C_DRIVERID_LM85  1039
21964 +#endif
21965 +
21966 +/* Addresses to scan */
21967 +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, SENSORS_I2C_END };
21968 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
21969 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
21970 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
21971 +
21972 +/* Insmod parameters */
21973 +SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
21974 +
21975 +/* Many LM85 constants specified below */
21976 +
21977 +/* The LM85 registers */
21978 +#define LM85_REG_IN(nr) (0x20 + (nr))
21979 +#define LM85_REG_IN_MIN(nr) (0x44 + (nr) * 2)
21980 +#define LM85_REG_IN_MAX(nr) (0x45 + (nr) * 2)
21981 +
21982 +#define LM85_REG_TEMP(nr) (0x25 + (nr))
21983 +#define LM85_REG_TEMP_MIN(nr) (0x4e + (nr) * 2)
21984 +#define LM85_REG_TEMP_MAX(nr) (0x4f + (nr) * 2)
21985 +
21986 +/* Fan speeds are LSB, MSB (2 bytes) */
21987 +#define LM85_REG_FAN(nr) (0x28 + (nr) *2)
21988 +#define LM85_REG_FAN_MIN(nr) (0x54 + (nr) *2)
21989 +
21990 +#define LM85_REG_PWM(nr) (0x30 + (nr))
21991 +
21992 +#define ADT7463_REG_OPPOINT(nr) (0x33 + (nr))
21993 +
21994 +#define ADT7463_REG_TMIN_CTL1 0x36
21995 +#define ADT7463_REG_TMIN_CTL2 0x37
21996 +#define ADT7463_REG_TMIN_CTL  0x0136
21997 +
21998 +#define LM85_REG_DEVICE 0x3d
21999 +#define LM85_REG_COMPANY 0x3e
22000 +#define LM85_REG_VERSTEP 0x3f
22001 +/* These are the recognized values for the above regs */
22002 +#define LM85_DEVICE_ADX 0x27
22003 +#define LM85_COMPANY_NATIONAL 0x01
22004 +#define LM85_COMPANY_ANALOG_DEV 0x41
22005 +#define LM85_COMPANY_SMSC 0x5c
22006 +#define LM85_VERSTEP_VMASK 0xf0
22007 +#define LM85_VERSTEP_SMASK 0x0f
22008 +#define LM85_VERSTEP_GENERIC 0x60
22009 +#define LM85_VERSTEP_LM85C 0x60
22010 +#define LM85_VERSTEP_LM85B 0x62
22011 +#define LM85_VERSTEP_ADM1027 0x60
22012 +#define LM85_VERSTEP_ADT7463 0x62
22013 +#define LM85_VERSTEP_EMC6D100_A0 0x60
22014 +#define LM85_VERSTEP_EMC6D100_A1 0x61
22015 +
22016 +#define LM85_REG_CONFIG 0x40
22017 +
22018 +#define LM85_REG_ALARM1 0x41
22019 +#define LM85_REG_ALARM2 0x42
22020 +#define LM85_REG_ALARM  0x0141
22021 +
22022 +#define LM85_REG_VID 0x43
22023 +
22024 +/* Automated FAN control */
22025 +#define LM85_REG_AFAN_CONFIG(nr) (0x5c + (nr))
22026 +#define LM85_REG_AFAN_RANGE(nr) (0x5f + (nr))
22027 +#define LM85_REG_AFAN_SPIKE1 0x62
22028 +#define LM85_REG_AFAN_SPIKE2 0x63
22029 +#define LM85_REG_AFAN_MINPWM(nr) (0x64 + (nr))
22030 +#define LM85_REG_AFAN_LIMIT(nr) (0x67 + (nr))
22031 +#define LM85_REG_AFAN_CRITICAL(nr) (0x6a + (nr))
22032 +#define LM85_REG_AFAN_HYST1 0x6d
22033 +#define LM85_REG_AFAN_HYST2 0x6e
22034 +
22035 +#define LM85_REG_TACH_MODE 0x74
22036 +#define LM85_REG_SPINUP_CTL 0x75
22037 +
22038 +#define ADM1027_REG_TEMP_OFFSET(nr) (0x70 + (nr))
22039 +#define ADM1027_REG_CONFIG2 0x73
22040 +#define ADM1027_REG_INTMASK1 0x74
22041 +#define ADM1027_REG_INTMASK2 0x75
22042 +#define ADM1027_REG_INTMASK  0x0174
22043 +#define ADM1027_REG_EXTEND_ADC1 0x76
22044 +#define ADM1027_REG_EXTEND_ADC2 0x77
22045 +#define ADM1027_REG_EXTEND_ADC  0x0176
22046 +#define ADM1027_REG_CONFIG3 0x78
22047 +#define ADM1027_REG_FAN_PPR 0x7b
22048 +
22049 +#define ADT7463_REG_THERM 0x79
22050 +#define ADT7463_REG_THERM_LIMIT 0x7A
22051 +#define ADT7463_REG_CONFIG4 0x7D
22052 +
22053 +#define EMC6D100_REG_SFR  0x7c
22054 +#define EMC6D100_REG_ALARM3  0x7d
22055 +#define EMC6D100_REG_CONF  0x7f
22056 +#define EMC6D100_REG_INT_EN  0x80
22057 +/* IN5, IN6 and IN7 */
22058 +#define EMC6D100_REG_IN(nr)  (0x70 + ((nr)-5))
22059 +#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr)-5) * 2)
22060 +#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr)-5) * 2)
22061 +
22062 +/* Conversions. Rounding and limit checking is only done on the TO_REG 
22063 +   variants. Note that you should be a bit careful with which arguments
22064 +   these macros are called: arguments may be evaluated more than once.
22065 + */
22066 +
22067 +/* IN are scaled 1.000 == 0xc0, mag = 3 */
22068 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255))
22069 +#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0)
22070 +#define IN_FROM_REG(val) (INEXT_FROM_REG(val,0))
22071 +
22072 +/* IN are scaled acording to built-in resistors */
22073 +static int lm85_scaling[] = {  /* .001 Volts */
22074 +               2500, 2250, 3300, 5000, 12000,
22075 +               3300, 1500, 1800,       /* EMC6D100 */
22076 +       };
22077 +#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
22078 +#define INS_TO_REG(n,val)  (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
22079 +#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
22080 +#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
22081 +
22082 +/* FAN speed is measured using 90kHz clock */
22083 +#define FAN_TO_REG(val)  (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
22084 +#define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val))
22085 +
22086 +/* Temperature is reported in .01 degC increments */
22087 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+50)/100,-127,127))
22088 +#define TEMPEXT_FROM_REG(val,ext) ((val)*100 + (ext)*25)
22089 +#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0))
22090 +#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
22091 +#define OPPOINT_TO_REG(val) (SENSORS_LIMIT(val,-127,127))
22092 +#define OPPOINT_FROM_REG(val) (val)
22093 +
22094 +#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
22095 +#define PWM_FROM_REG(val) (val)
22096 +
22097 +#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03)
22098 +
22099 +/* ZONEs have the following parameters:
22100 + *    Limit (low) temp,           1. degC
22101 + *    Hysteresis (below limit),   1. degC (0-15)
22102 + *    Range of speed control,     .1 degC (2-80)
22103 + *    Critical (high) temp,       1. degC
22104 + *
22105 + * FAN PWMs have the following parameters:
22106 + *    Reference Zone,                 1, 2, 3, etc.
22107 + *    Spinup time,                    .05 sec
22108 + *    PWM value at limit/low temp,    1 count
22109 + *    PWM Frequency,                  1. Hz
22110 + *    PWM is Min or OFF below limit,  flag
22111 + *    Invert PWM output,              flag
22112 + *
22113 + * Some chips filter the temp, others the fan.
22114 + *    Filter constant (or disabled)   .1 seconds
22115 + */
22116 +
22117 +/* These are the zone temperature range encodings */
22118 +static int lm85_range_map[] = {   /* .1 degC */
22119 +                20,  25,  33,  40,  50,  66,
22120 +                80, 100, 133, 160, 200, 266,
22121 +               320, 400, 533, 800
22122 +       };
22123 +static int RANGE_TO_REG( int range )
22124 +{
22125 +       int i;
22126 +
22127 +       if( range >= lm85_range_map[15] ) { return 15 ; }
22128 +       for( i = 0 ; i < 15 ; ++i )
22129 +               if( range <= lm85_range_map[i] )
22130 +                       break ;
22131 +       return( i & 0x0f );
22132 +}
22133 +#define RANGE_FROM_REG(val) (lm85_range_map[(val)&0x0f])
22134 +
22135 +/* These are the Acoustic Enhancement, or Temperature smoothing encodings
22136 + * NOTE: The enable/disable bit is INCLUDED in these encodings as the
22137 + *       MSB (bit 3, value 8).  If the enable bit is 0, the encoded value
22138 + *       is ignored, or set to 0.
22139 + */
22140 +static int lm85_smooth_map[] = {  /* .1 sec */
22141 +               350, 176, 118,  70,  44,   30,   16,    8
22142 +/*    35.4 *    1/1, 1/2, 1/3, 1/5, 1/8, 1/12, 1/24, 1/48  */
22143 +       };
22144 +static int SMOOTH_TO_REG( int smooth )
22145 +{
22146 +       int i;
22147 +
22148 +       if( smooth <= 0 ) { return 0 ; }  /* Disabled */
22149 +       for( i = 0 ; i < 7 ; ++i )
22150 +               if( smooth >= lm85_smooth_map[i] )
22151 +                       break ;
22152 +       return( (i & 0x07) | 0x08 );
22153 +}
22154 +#define SMOOTH_FROM_REG(val) ((val)&0x08?lm85_smooth_map[(val)&0x07]:0)
22155 +
22156 +/* These are the fan spinup delay time encodings */
22157 +static int lm85_spinup_map[] = {  /* .1 sec */
22158 +               0, 1, 2, 4, 7, 10, 20, 40
22159 +       };
22160 +static int SPINUP_TO_REG( int spinup )
22161 +{
22162 +       int i;
22163 +
22164 +       if( spinup >= lm85_spinup_map[7] ) { return 7 ; }
22165 +       for( i = 0 ; i < 7 ; ++i )
22166 +               if( spinup <= lm85_spinup_map[i] )
22167 +                       break ;
22168 +       return( i & 0x07 );
22169 +}
22170 +#define SPINUP_FROM_REG(val) (lm85_spinup_map[(val)&0x07])
22171 +
22172 +/* These are the PWM frequency encodings */
22173 +static int lm85_freq_map[] = { /* .1 Hz */
22174 +               100, 150, 230, 300, 380, 470, 620, 980
22175 +       };
22176 +static int FREQ_TO_REG( int freq )
22177 +{
22178 +       int i;
22179 +
22180 +       if( freq >= lm85_freq_map[7] ) { return 7 ; }
22181 +       for( i = 0 ; i < 7 ; ++i )
22182 +               if( freq <= lm85_freq_map[i] )
22183 +                       break ;
22184 +       return( i & 0x07 );
22185 +}
22186 +#define FREQ_FROM_REG(val) (lm85_freq_map[(val)&0x07])
22187 +
22188 +/* Since we can't use strings, I'm abusing these numbers
22189 + *   to stand in for the following meanings:
22190 + *      1 -- PWM responds to Zone 1
22191 + *      2 -- PWM responds to Zone 2
22192 + *      3 -- PWM responds to Zone 3
22193 + *     23 -- PWM responds to the higher temp of Zone 2 or 3
22194 + *    123 -- PWM responds to highest of Zone 1, 2, or 3
22195 + *      0 -- PWM is always at 0% (ie, off)
22196 + *     -1 -- PWM is always at 100%
22197 + *     -2 -- PWM responds to manual control
22198 + */
22199 +static int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 };
22200 +static int ZONE_TO_REG( int zone )
22201 +{
22202 +       int i;
22203 +
22204 +       for( i = 0 ; i <= 7 ; ++i )
22205 +               if( zone == lm85_zone_map[i] )
22206 +                       break ;
22207 +       if( i > 7 )   /* Not found. */
22208 +               i = 3;  /* Always 100% */
22209 +       return( (i & 0x07)<<5 );
22210 +}
22211 +#define ZONE_FROM_REG(val) (lm85_zone_map[((val)>>5)&0x07])
22212 +
22213 +#define HYST_TO_REG(val) (SENSORS_LIMIT((-(val)+5)/10,0,15))
22214 +#define HYST_FROM_REG(val) (-(val)*10)
22215 +
22216 +#define OFFSET_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
22217 +#define OFFSET_FROM_REG(val) ((val)*25)
22218 +
22219 +#define PPR_MASK(fan) (0x03<<(fan *2))
22220 +#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
22221 +#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
22222 +
22223 +/* sensors_vid.h defines vid_from_reg() */
22224 +#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
22225 +
22226 +#define ALARMS_FROM_REG(val) (val)
22227 +
22228 +/* When converting to REG, we need to fixup the carry-over bit */
22229 +#define INTMASK_FROM_REG(val) (val)
22230 +#define INTMASK_TO_REG(val) (SENSORS_LIMIT((val)|((val)&0xff00?0x80:0),0,65535))
22231 +
22232 +/* Unlike some other drivers we DO NOT set initial limits.  Use
22233 + * the config file to set limits.  Some users have reported
22234 + * motherboards shutting down when we set limits in a previous
22235 + * version of this driver.  This may be caused by APM/ACPI
22236 + * detecting an out-of-limit condition when we had the wrong
22237 + * limits set.
22238 + */
22239 +
22240 +/* Typically used with Pentium 4 systems v9.1 VRM spec */
22241 +#define LM85_INIT_VRM  91
22242 +
22243 +/* Chip sampling rates
22244 + *
22245 + * Some sensors are not updated more frequently than once per second
22246 + *    so it doesn't make sense to read them more often than that.
22247 + *    We cache the results and return the saved data if the driver
22248 + *    is called again before a second has elapsed.
22249 + *
22250 + * Also, there is significant configuration data for this chip
22251 + *    given the automatic PWM fan control that is possible.  There
22252 + *    are about 47 bytes of config data to only 22 bytes of actual
22253 + *    readings.  So, we keep the config data up to date in the cache
22254 + *    when it is written and only sample it once every 5 *minutes*
22255 + */
22256 +#define LM85_DATA_INTERVAL  (1 * HZ)
22257 +#define LM85_CONFIG_INTERVAL  (5 * 60 * HZ)
22258 +
22259 +/* For each registered LM85, we need to keep some data in memory. That
22260 +   data is pointed to by client->data. The structure itself is
22261 +   dynamically allocated, when a new lm85 client is allocated. */
22262 +
22263 +/* LM85 can automatically adjust fan speeds based on temperature
22264 + * This structure encapsulates an entire Zone config.  There are
22265 + * three zones (one for each temperature input) on the lm85
22266 + */
22267 +struct lm85_zone {
22268 +       s8 limit;       /* Low temp limit */
22269 +       u8 hyst;        /* Low limit hysteresis. (0-15) */
22270 +       u8 range;       /* Temp range, encoded */
22271 +       s8 critical;    /* "All fans ON" temp limit */
22272 +};
22273 +
22274 +struct lm85_autofan {
22275 +       u8 config;      /* Register value */
22276 +       u8 freq;        /* PWM frequency, encoded */
22277 +       u8 min_pwm;     /* Minimum PWM value, encoded */
22278 +       u8 min_off;     /* Min PWM or OFF below "limit", flag */
22279 +};
22280 +
22281 +struct lm85_data {
22282 +       struct i2c_client client;
22283 +       struct semaphore lock;
22284 +       int sysctl_id;
22285 +       enum chips type;
22286 +
22287 +       struct semaphore update_lock;
22288 +       int valid;              /* !=0 if following fields are valid */
22289 +       unsigned long last_reading;     /* In jiffies */
22290 +       unsigned long last_config;      /* In jiffies */
22291 +
22292 +       u8 in[8];               /* Register value */
22293 +       u8 in_max[8];           /* Register value */
22294 +       u8 in_min[8];           /* Register value */
22295 +       s8 temp[3];             /* Register value */
22296 +       s8 temp_min[3];         /* Register value */
22297 +       s8 temp_max[3];         /* Register value */
22298 +       s8 temp_offset[3];      /* Register value */
22299 +       u16 fan[4];             /* Register value */
22300 +       u16 fan_min[4];         /* Register value */
22301 +       u8 pwm[3];              /* Register value */
22302 +       u8 spinup_ctl;          /* Register encoding, combined */
22303 +       u8 tach_mode;           /* Register encoding, combined */
22304 +       u16 extend_adc;         /* Register value */
22305 +       u8 fan_ppr;             /* Register value */
22306 +       u8 smooth[3];           /* Register encoding */
22307 +       u8 vid;                 /* Register value */
22308 +       u8 vrm;                 /* VRM version */
22309 +       u8 syncpwm3;            /* Saved PWM3 for TACH 2,3,4 config */
22310 +       s8 oppoint[3];          /* Register value */
22311 +       u16 tmin_ctl;           /* Register value */
22312 +       long therm_total;       /* Cummulative therm count */
22313 +       long therm_ovfl;        /* Count of therm overflows */
22314 +       u8 therm_limit;         /* Register value */
22315 +       u32 alarms;             /* Register encoding, combined */
22316 +       u32 alarm_mask;         /* Register encoding, combined */
22317 +       struct lm85_autofan autofan[3];
22318 +       struct lm85_zone zone[3];
22319 +};
22320 +
22321 +static int lm85_attach_adapter(struct i2c_adapter *adapter);
22322 +static int lm85_detect(struct i2c_adapter *adapter, int address,
22323 +                       unsigned short flags, int kind);
22324 +static int lm85_detach_client(struct i2c_client *client);
22325 +static int lm85_read_value(struct i2c_client *client, u16 register);
22326 +static int lm85_write_value(struct i2c_client *client, u16 register, int value);
22327 +static void lm85_update_client(struct i2c_client *client);
22328 +static void lm85_init_client(struct i2c_client *client);
22329 +
22330 +
22331 +static void lm85_in(struct i2c_client *client, int operation, int ctl_name,
22332 +                       int *nrels_mag, long *results);
22333 +static void lm85_fan(struct i2c_client *client, int operation,
22334 +                       int ctl_name, int *nrels_mag, long *results);
22335 +static void lm85_temp(struct i2c_client *client, int operation,
22336 +                       int ctl_name, int *nrels_mag, long *results);
22337 +static void lm85_vid(struct i2c_client *client, int operation,
22338 +                       int ctl_name, int *nrels_mag, long *results);
22339 +static void lm85_vrm(struct i2c_client *client, int operation,
22340 +                       int ctl_name, int *nrels_mag, long *results);
22341 +static void lm85_alarms(struct i2c_client *client, int operation,
22342 +                       int ctl_name, int *nrels_mag, long *results);
22343 +static void lm85_pwm(struct i2c_client *client, int operation,
22344 +                       int ctl_name, int *nrels_mag, long *results);
22345 +static void lm85_zone(struct i2c_client *client, int operation,
22346 +                       int ctl_name, int *nrels_mag, long *results);
22347 +static void lm85_pwm_config(struct i2c_client *client, int operation,
22348 +                       int ctl_name, int *nrels_mag, long *results);
22349 +static void lm85_pwm_zone(struct i2c_client *client, int operation,
22350 +                       int ctl_name, int *nrels_mag, long *results);
22351 +static void lm85_smooth(struct i2c_client *client, int operation,
22352 +                       int ctl_name, int *nrels_mag, long *results);
22353 +
22354 +static void lm85_spinup_ctl(struct i2c_client *client, int operation,
22355 +                       int ctl_name, int *nrels_mag, long *results);
22356 +static void lm85_tach_mode(struct i2c_client *client, int operation,
22357 +                       int ctl_name, int *nrels_mag, long *results);
22358 +
22359 +static void adm1027_tach_mode(struct i2c_client *client, int operation,
22360 +                       int ctl_name, int *nrels_mag, long *results);
22361 +static void adm1027_temp_offset(struct i2c_client *client, int operation,
22362 +                       int ctl_name, int *nrels_mag, long *results);
22363 +static void adm1027_fan_ppr(struct i2c_client *client, int operation,
22364 +                       int ctl_name, int *nrels_mag, long *results);
22365 +static void adm1027_alarm_mask(struct i2c_client *client, int operation,
22366 +                       int ctl_name, int *nrels_mag, long *results);
22367 +
22368 +static void adt7463_tmin_ctl(struct i2c_client *client, int operation,
22369 +                       int ctl_name, int *nrels_mag, long *results);
22370 +static void adt7463_therm_signal(struct i2c_client *client, int operation,
22371 +                       int ctl_name, int *nrels_mag, long *results);
22372 +
22373 +static void emc6d100_in(struct i2c_client *client, int operation,
22374 +                       int ctl_name, int *nrels_mag, long *results);
22375 +
22376 +static struct i2c_driver lm85_driver = {
22377 +       .owner          = THIS_MODULE,
22378 +       .name           =  "LM85 compatible sensor driver",
22379 +       .id             = I2C_DRIVERID_LM85,
22380 +       .flags          = I2C_DF_NOTIFY,
22381 +       .attach_adapter = &lm85_attach_adapter,
22382 +       .detach_client  = &lm85_detach_client,
22383 +};
22384 +
22385 +/* Unique ID assigned to each LM85 detected */
22386 +static int lm85_id = 0;
22387 +
22388 +/* -- SENSORS SYSCTL START -- */
22389 +/* Common parameters */
22390 +#define LM85_SYSCTL_IN0                1000
22391 +#define LM85_SYSCTL_IN1                1001
22392 +#define LM85_SYSCTL_IN2                1002
22393 +#define LM85_SYSCTL_IN3                1003
22394 +#define LM85_SYSCTL_IN4                1004
22395 +#define LM85_SYSCTL_FAN1               1005
22396 +#define LM85_SYSCTL_FAN2               1006
22397 +#define LM85_SYSCTL_FAN3               1007
22398 +#define LM85_SYSCTL_FAN4               1008
22399 +#define LM85_SYSCTL_TEMP1              1009
22400 +#define LM85_SYSCTL_TEMP2              1010
22401 +#define LM85_SYSCTL_TEMP3              1011
22402 +#define LM85_SYSCTL_VID                1012
22403 +#define LM85_SYSCTL_ALARMS             1013
22404 +#define LM85_SYSCTL_PWM1               1014
22405 +#define LM85_SYSCTL_PWM2               1015
22406 +#define LM85_SYSCTL_PWM3               1016
22407 +#define LM85_SYSCTL_VRM                1017
22408 +#define LM85_SYSCTL_PWM_CFG1           1019
22409 +#define LM85_SYSCTL_PWM_CFG2           1020
22410 +#define LM85_SYSCTL_PWM_CFG3           1021
22411 +#define LM85_SYSCTL_PWM_ZONE1          1022
22412 +#define LM85_SYSCTL_PWM_ZONE2          1023
22413 +#define LM85_SYSCTL_PWM_ZONE3          1024
22414 +#define LM85_SYSCTL_ZONE1              1025
22415 +#define LM85_SYSCTL_ZONE2              1026
22416 +#define LM85_SYSCTL_ZONE3              1027
22417 +#define LM85_SYSCTL_SMOOTH1            1028
22418 +#define LM85_SYSCTL_SMOOTH2            1029
22419 +#define LM85_SYSCTL_SMOOTH3            1030
22420 +
22421 +/* Vendor specific values */
22422 +#define LM85_SYSCTL_SPINUP_CTL         1100
22423 +#define LM85_SYSCTL_TACH_MODE          1101
22424 +
22425 +/* Analog Devices variant of the LM85 */
22426 +#define ADM1027_SYSCTL_TACH_MODE       1200
22427 +#define ADM1027_SYSCTL_TEMP_OFFSET1    1201
22428 +#define ADM1027_SYSCTL_TEMP_OFFSET2    1202
22429 +#define ADM1027_SYSCTL_TEMP_OFFSET3    1203
22430 +#define ADM1027_SYSCTL_FAN_PPR         1204
22431 +#define ADM1027_SYSCTL_ALARM_MASK      1205
22432 +
22433 +/* Analog Devices variant of the LM85/ADM1027 */
22434 +#define ADT7463_SYSCTL_TMIN_CTL1       1300
22435 +#define ADT7463_SYSCTL_TMIN_CTL2       1301
22436 +#define ADT7463_SYSCTL_TMIN_CTL3       1302
22437 +#define ADT7463_SYSCTL_THERM_SIGNAL    1303
22438 +
22439 +/* SMSC variant of the LM85 */
22440 +#define EMC6D100_SYSCTL_IN5            1400
22441 +#define EMC6D100_SYSCTL_IN6            1401
22442 +#define EMC6D100_SYSCTL_IN7            1402
22443 +
22444 +#define LM85_ALARM_IN0          0x0001
22445 +#define LM85_ALARM_IN1          0x0002
22446 +#define LM85_ALARM_IN2          0x0004
22447 +#define LM85_ALARM_IN3          0x0008
22448 +#define LM85_ALARM_TEMP1        0x0010
22449 +#define LM85_ALARM_TEMP2        0x0020
22450 +#define LM85_ALARM_TEMP3        0x0040
22451 +#define LM85_ALARM_ALARM2       0x0080
22452 +#define LM85_ALARM_IN4          0x0100
22453 +#define LM85_ALARM_RESERVED     0x0200
22454 +#define LM85_ALARM_FAN1         0x0400
22455 +#define LM85_ALARM_FAN2         0x0800
22456 +#define LM85_ALARM_FAN3         0x1000
22457 +#define LM85_ALARM_FAN4         0x2000
22458 +#define LM85_ALARM_TEMP1_FAULT  0x4000
22459 +#define LM85_ALARM_TEMP3_FAULT 0x08000
22460 +#define LM85_ALARM_IN6         0x10000
22461 +#define LM85_ALARM_IN7         0x20000
22462 +#define LM85_ALARM_IN5         0x40000
22463 +/* -- SENSORS SYSCTL END -- */
22464 +
22465 +/* The /proc/sys entries */
22466 +/* These files are created for each detected LM85. This is just a template;
22467 + *    The actual list is built from this and additional per-chip
22468 + *    custom lists below.  Note the XXX_LEN macros.  These must be
22469 + *    compile time constants because they will be used to allocate
22470 + *    space for the final template passed to i2c_register_entry.
22471 + *    We depend on the ability of GCC to evaluate expressions at
22472 + *    compile time to turn these expressions into compile time
22473 + *    constants, but this can generate a warning.
22474 + */
22475 +static ctl_table lm85_common[] = {
22476 +       {LM85_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
22477 +               &i2c_sysctl_real, NULL, &lm85_in},
22478 +       {LM85_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
22479 +               &i2c_sysctl_real, NULL, &lm85_in},
22480 +       {LM85_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
22481 +               &i2c_sysctl_real, NULL, &lm85_in},
22482 +       {LM85_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
22483 +               &i2c_sysctl_real, NULL, &lm85_in},
22484 +       {LM85_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
22485 +               &i2c_sysctl_real, NULL, &lm85_in},
22486 +       {LM85_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
22487 +               &i2c_sysctl_real, NULL, &lm85_fan},
22488 +       {LM85_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
22489 +               &i2c_sysctl_real, NULL, &lm85_fan},
22490 +       {LM85_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
22491 +               &i2c_sysctl_real, NULL, &lm85_fan},
22492 +       {LM85_SYSCTL_FAN4, "fan4", NULL, 0, 0644, NULL, &i2c_proc_real,
22493 +               &i2c_sysctl_real, NULL, &lm85_fan},
22494 +       {LM85_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
22495 +               &i2c_sysctl_real, NULL, &lm85_temp},
22496 +       {LM85_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
22497 +               &i2c_sysctl_real, NULL, &lm85_temp},
22498 +       {LM85_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
22499 +               &i2c_sysctl_real, NULL, &lm85_temp},
22500 +       {LM85_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
22501 +               &i2c_sysctl_real, NULL, &lm85_vid},
22502 +       {LM85_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
22503 +               &i2c_sysctl_real, NULL, &lm85_vrm},
22504 +       {LM85_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
22505 +               &i2c_sysctl_real, NULL, &lm85_alarms},
22506 +       {LM85_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
22507 +               &i2c_sysctl_real, NULL, &lm85_pwm},
22508 +       {LM85_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
22509 +               &i2c_sysctl_real, NULL, &lm85_pwm},
22510 +       {LM85_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
22511 +               &i2c_sysctl_real, NULL, &lm85_pwm},
22512 +       {LM85_SYSCTL_PWM_CFG1, "pwm1_cfg", NULL, 0, 0644, NULL, &i2c_proc_real,
22513 +               &i2c_sysctl_real, NULL, &lm85_pwm_config},
22514 +       {LM85_SYSCTL_PWM_CFG2, "pwm2_cfg", NULL, 0, 0644, NULL, &i2c_proc_real,
22515 +               &i2c_sysctl_real, NULL, &lm85_pwm_config},
22516 +       {LM85_SYSCTL_PWM_CFG3, "pwm3_cfg", NULL, 0, 0644, NULL, &i2c_proc_real,
22517 +               &i2c_sysctl_real, NULL, &lm85_pwm_config},
22518 +       {LM85_SYSCTL_PWM_ZONE1, "pwm1_zone", NULL, 0, 0644, NULL,
22519 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &lm85_pwm_zone},
22520 +       {LM85_SYSCTL_PWM_ZONE2, "pwm2_zone", NULL, 0, 0644, NULL,
22521 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &lm85_pwm_zone},
22522 +       {LM85_SYSCTL_PWM_ZONE3, "pwm3_zone", NULL, 0, 0644, NULL,
22523 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &lm85_pwm_zone},
22524 +       {LM85_SYSCTL_ZONE1, "zone1", NULL, 0, 0644, NULL, &i2c_proc_real,
22525 +               &i2c_sysctl_real, NULL, &lm85_zone},
22526 +       {LM85_SYSCTL_ZONE2, "zone2", NULL, 0, 0644, NULL, &i2c_proc_real,
22527 +               &i2c_sysctl_real, NULL, &lm85_zone},
22528 +       {LM85_SYSCTL_ZONE3, "zone3", NULL, 0, 0644, NULL, &i2c_proc_real,
22529 +               &i2c_sysctl_real, NULL, &lm85_zone},
22530 +       {LM85_SYSCTL_SMOOTH1, "smooth1", NULL, 0, 0644, NULL, &i2c_proc_real,
22531 +               &i2c_sysctl_real, NULL, &lm85_smooth},
22532 +       {LM85_SYSCTL_SMOOTH2, "smooth2", NULL, 0, 0644, NULL, &i2c_proc_real,
22533 +               &i2c_sysctl_real, NULL, &lm85_smooth},
22534 +       {LM85_SYSCTL_SMOOTH3, "smooth3", NULL, 0, 0644, NULL, &i2c_proc_real,
22535 +               &i2c_sysctl_real, NULL, &lm85_smooth},
22536 +       {0}
22537 +};
22538 +#define CTLTBL_COMMON (sizeof(lm85_common)/sizeof(lm85_common[0]))
22539 +
22540 +/* NOTE: tach_mode is a shared name, but implemented with
22541 + *   different functions
22542 + */
22543 +static ctl_table lm85_specific[] = {
22544 +       {LM85_SYSCTL_SPINUP_CTL, "spinup_ctl", NULL, 0, 0644, NULL,
22545 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &lm85_spinup_ctl},
22546 +       {LM85_SYSCTL_TACH_MODE, "tach_mode", NULL, 0, 0644, NULL,
22547 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &lm85_tach_mode},
22548 +/*     {0} The doc generator needs this. */
22549 +};
22550 +#define CTLTBL_LM85 (sizeof(lm85_specific)/sizeof(lm85_specific[0]))
22551 +
22552 +static ctl_table adm1027_specific[] = {
22553 +       {ADM1027_SYSCTL_TACH_MODE, "tach_mode", NULL, 0, 0644, NULL,
22554 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1027_tach_mode},
22555 +       {ADM1027_SYSCTL_TEMP_OFFSET1, "temp1_offset", NULL, 0, 0644, NULL,
22556 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1027_temp_offset},
22557 +       {ADM1027_SYSCTL_TEMP_OFFSET2, "temp2_offset", NULL, 0, 0644, NULL,
22558 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1027_temp_offset},
22559 +       {ADM1027_SYSCTL_TEMP_OFFSET3, "temp3_offset", NULL, 0, 0644, NULL,
22560 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1027_temp_offset},
22561 +       {ADM1027_SYSCTL_FAN_PPR, "fan_ppr", NULL, 0, 0644, NULL,
22562 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1027_fan_ppr},
22563 +       {ADM1027_SYSCTL_ALARM_MASK, "alarm_mask", NULL, 0, 0644, NULL,
22564 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adm1027_alarm_mask},
22565 +/*     {0} The doc generator needs this. */
22566 +};
22567 +#define CTLTBL_ADM1027 (sizeof(adm1027_specific)/sizeof(adm1027_specific[0]))
22568 +
22569 +static ctl_table adt7463_specific[] = {
22570 +       {ADT7463_SYSCTL_TMIN_CTL1, "tmin_ctl1", NULL, 0, 0644, NULL,
22571 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adt7463_tmin_ctl},
22572 +       {ADT7463_SYSCTL_TMIN_CTL2, "tmin_ctl2", NULL, 0, 0644, NULL,
22573 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adt7463_tmin_ctl},
22574 +       {ADT7463_SYSCTL_TMIN_CTL3, "tmin_ctl3", NULL, 0, 0644, NULL,
22575 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adt7463_tmin_ctl},
22576 +       {ADT7463_SYSCTL_THERM_SIGNAL, "therm_signal", NULL, 0, 0644, NULL,
22577 +               &i2c_proc_real, &i2c_sysctl_real, NULL, &adt7463_therm_signal},
22578 +/*     {0} The doc generator needs this. */
22579 +};
22580 +#define CTLTBL_ADT7463 (sizeof(adt7463_specific)/sizeof(adt7463_specific[0]))
22581 +
22582 +static ctl_table emc6d100_specific[] = {
22583 +       {EMC6D100_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
22584 +               &i2c_sysctl_real, NULL, &emc6d100_in},
22585 +       {EMC6D100_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
22586 +               &i2c_sysctl_real, NULL, &emc6d100_in},
22587 +       {EMC6D100_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
22588 +               &i2c_sysctl_real, NULL, &emc6d100_in},
22589 +/*     {0} The doc generator needs this. */
22590 +};
22591 +#define CTLTBL_EMC6D100 (sizeof(emc6d100_specific)/sizeof(emc6d100_specific[0]))
22592 +
22593 +
22594 +#define MAX2(a,b) ((a)>(b)?(a):(b))
22595 +#define MAX3(a,b,c) ((a)>(b)?MAX2((a),(c)):MAX2((b),(c)))
22596 +#define MAX4(a,b,c,d) ((a)>(b)?MAX3((a),(c),(d)):MAX3((b),(c),(d)))
22597 +
22598 +#define CTLTBL_MAX (CTLTBL_COMMON + MAX3(CTLTBL_LM85, CTLTBL_ADM1027+CTLTBL_ADT7463, CTLTBL_EMC6D100))
22599 +
22600 +/* This function is called when:
22601 +     * lm85_driver is inserted (when this module is loaded), for each
22602 +       available adapter
22603 +     * when a new adapter is inserted (and lm85_driver is still present) */
22604 +int lm85_attach_adapter(struct i2c_adapter *adapter)
22605 +{
22606 +       return i2c_detect(adapter, &addr_data, lm85_detect);
22607 +}
22608 +
22609 +/* This function is called by i2c_detect */
22610 +int lm85_detect(struct i2c_adapter *adapter, int address,
22611 +               unsigned short flags, int kind)
22612 +{
22613 +       int i;
22614 +       int company, verstep ;
22615 +       struct i2c_client *new_client;
22616 +       struct lm85_data *data;
22617 +       int err = 0;
22618 +       const char *type_name = "";
22619 +       struct ctl_table template[CTLTBL_MAX] ;
22620 +       int template_used ;
22621 +
22622 +       if (i2c_is_isa_adapter(adapter)) {
22623 +               /* This chip has no ISA interface */
22624 +               goto ERROR0 ;
22625 +       };
22626 +
22627 +       if (!i2c_check_functionality(adapter,
22628 +                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
22629 +               /* We need to be able to do byte I/O */
22630 +               goto ERROR0 ;
22631 +       };
22632 +
22633 +       /* OK. For now, we presume we have a valid client. We now create the
22634 +          client structure, even though we cannot fill it completely yet.
22635 +          But it allows us to access lm85_{read,write}_value. */
22636 +
22637 +       if (!(data = kmalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
22638 +               err = -ENOMEM;
22639 +               goto ERROR0;
22640 +       }
22641 +
22642 +       new_client = &data->client;
22643 +       new_client->addr = address;
22644 +       new_client->data = data;
22645 +       new_client->adapter = adapter;
22646 +       new_client->driver = &lm85_driver;
22647 +       new_client->flags = 0;
22648 +
22649 +       /* Now, we do the remaining detection. */
22650 +
22651 +       company = lm85_read_value(new_client, LM85_REG_COMPANY);
22652 +       verstep = lm85_read_value(new_client, LM85_REG_VERSTEP);
22653 +
22654 +#ifdef DEBUG
22655 +       printk("lm85: Detecting device at %d,0x%02x with"
22656 +               " COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
22657 +               i2c_adapter_id(new_client->adapter), new_client->addr,
22658 +               company, verstep
22659 +           );
22660 +#endif
22661 +
22662 +       /* If auto-detecting, Determine the chip type. */
22663 +       if (kind <= 0) {
22664 +#ifdef DEBUG
22665 +               printk("lm85: Autodetecting device at %d,0x%02x ...\n",
22666 +                       i2c_adapter_id(adapter), address );
22667 +#endif
22668 +               if( company == LM85_COMPANY_NATIONAL
22669 +                   && verstep == LM85_VERSTEP_LM85C ) {
22670 +                       kind = lm85c ;
22671 +               } else if( company == LM85_COMPANY_NATIONAL
22672 +                   && verstep == LM85_VERSTEP_LM85B ) {
22673 +                       kind = lm85b ;
22674 +               } else if( company == LM85_COMPANY_NATIONAL
22675 +                   && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
22676 +                       printk("lm85: Detected National Semiconductor chip\n");
22677 +                       printk("lm85: Unrecgonized version/stepping 0x%02x"
22678 +                           " Defaulting to Generic LM85.\n", verstep );
22679 +                       kind = any_chip ;
22680 +               } else if( company == LM85_COMPANY_ANALOG_DEV
22681 +                   && verstep == LM85_VERSTEP_ADM1027 ) {
22682 +                       kind = adm1027 ;
22683 +               } else if( company == LM85_COMPANY_ANALOG_DEV
22684 +                   && verstep == LM85_VERSTEP_ADT7463 ) {
22685 +                       kind = adt7463 ;
22686 +               } else if( company == LM85_COMPANY_ANALOG_DEV
22687 +                   && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
22688 +                       printk("lm85: Detected Analog Devices chip\n");
22689 +                       printk("lm85: Unrecgonized version/stepping 0x%02x"
22690 +                           " Defaulting to Generic LM85.\n", verstep );
22691 +                       kind = any_chip ;
22692 +               } else if( company == LM85_COMPANY_SMSC
22693 +                   && (verstep == LM85_VERSTEP_EMC6D100_A0
22694 +                        || verstep == LM85_VERSTEP_EMC6D100_A1) ) {
22695 +                       /* Unfortunately, we can't tell a '100 from a '101
22696 +                        *   from the registers.  Since a '101 is a '100
22697 +                        *   in a package with fewer pins and therefore no
22698 +                        *   3.3V, 1.5V or 1.8V inputs, perhaps if those
22699 +                        *   inputs read 0, then it's a '101.
22700 +                        */
22701 +                       kind = emc6d100 ;
22702 +               } else if( company == LM85_COMPANY_SMSC
22703 +                   && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
22704 +                       printk("lm85: Detected SMSC chip\n");
22705 +                       printk("lm85: Unrecognized version/stepping 0x%02x"
22706 +                           " Defaulting to Generic LM85.\n", verstep );
22707 +                       kind = any_chip ;
22708 +               } else if( kind == any_chip
22709 +                   && (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
22710 +                       printk("lm85: Generic LM85 Version 6 detected\n");
22711 +                       /* Leave kind as "any_chip" */
22712 +               } else {
22713 +#ifdef DEBUG
22714 +                       printk("lm85: Autodetection failed\n");
22715 +#endif
22716 +                       /* Not an LM85 ... */
22717 +                       if( kind == any_chip ) {  /* User used force=x,y */
22718 +                           printk("lm85: Generic LM85 Version 6 not"
22719 +                               " found at %d,0x%02x. Try force_lm85c.\n",
22720 +                               i2c_adapter_id(adapter), address );
22721 +                       }
22722 +                       err = 0 ;
22723 +                       goto ERROR1;
22724 +               }
22725 +       }
22726 +
22727 +       /* Fill in the chip specific driver values */
22728 +       switch (kind) {
22729 +       case any_chip :
22730 +               type_name = "lm85";
22731 +               strcpy(new_client->name, "Generic LM85");
22732 +               template_used = 0 ;
22733 +               break ;
22734 +       case lm85b :
22735 +               type_name = "lm85b";
22736 +               strcpy(new_client->name, "National LM85-B");
22737 +               memcpy( template, lm85_specific, sizeof(lm85_specific) );
22738 +               template_used = CTLTBL_LM85 ;
22739 +               break ;
22740 +       case lm85c :
22741 +               type_name = "lm85c";
22742 +               strcpy(new_client->name, "National LM85-C");
22743 +               memcpy( template, lm85_specific, sizeof(lm85_specific) );
22744 +               template_used = CTLTBL_LM85 ;
22745 +               break ;
22746 +       case adm1027 :
22747 +               type_name = "adm1027";
22748 +               strcpy(new_client->name, "Analog Devices ADM1027");
22749 +               memcpy( template, adm1027_specific, sizeof(adm1027_specific) );
22750 +               template_used = CTLTBL_ADM1027 ;
22751 +               break ;
22752 +       case adt7463 :
22753 +               type_name = "adt7463";
22754 +               strcpy(new_client->name, "Analog Devices ADT7463");
22755 +               memcpy( template, adt7463_specific, sizeof(adt7463_specific) );
22756 +               template_used = CTLTBL_ADT7463 ;
22757 +               memcpy( template+template_used, adm1027_specific, sizeof(adm1027_specific) );
22758 +               template_used += CTLTBL_ADM1027 ;
22759 +               break ;
22760 +       case emc6d100 :
22761 +               type_name = "emc6d100";
22762 +               strcpy(new_client->name, "SMSC EMC6D100");
22763 +               memcpy(template, emc6d100_specific, sizeof(emc6d100_specific));
22764 +               template_used = CTLTBL_EMC6D100 ;
22765 +               break ;
22766 +       default :
22767 +               printk("lm85: Internal error, invalid kind (%d)!", kind);
22768 +               err = -EFAULT ;
22769 +               goto ERROR1;
22770 +       }
22771 +
22772 +       /* Fill in the remaining client fields */
22773 +       new_client->id = lm85_id++;
22774 +       printk("lm85: Assigning ID %d to %s at %d,0x%02x\n",
22775 +               new_client->id, new_client->name,
22776 +               i2c_adapter_id(new_client->adapter),
22777 +               new_client->addr
22778 +           );
22779 +
22780 +       /* Housekeeping values */
22781 +       data->type = kind;
22782 +       data->valid = 0;
22783 +
22784 +       /* Set the VRM version */
22785 +       data->vrm = LM85_INIT_VRM ;
22786 +
22787 +       /* Zero the accumulators */
22788 +       data->therm_total = 0;
22789 +       data->therm_ovfl = 0;
22790 +
22791 +       init_MUTEX(&data->update_lock);
22792 +
22793 +       /* Initialize the LM85 chip */
22794 +       lm85_init_client(new_client);
22795 +
22796 +       /* Tell the I2C layer a new client has arrived */
22797 +       if ((err = i2c_attach_client(new_client)))
22798 +               goto ERROR1;
22799 +
22800 +       /* Finish out the template */
22801 +       memcpy( template + template_used, lm85_common, sizeof(lm85_common) );
22802 +
22803 +       /* Register a new directory entry with module sensors */
22804 +       if ((i = i2c_register_entry(new_client,
22805 +                                       type_name,
22806 +                                       template)) < 0) {
22807 +               err = i;
22808 +               goto ERROR2;
22809 +       }
22810 +       data->sysctl_id = i;
22811 +
22812 +       return 0;
22813 +
22814 +       /* Error out and cleanup code */
22815 +    ERROR2:
22816 +       i2c_detach_client(new_client);
22817 +    ERROR1:
22818 +       kfree(data);
22819 +    ERROR0:
22820 +       return err;
22821 +}
22822 +
22823 +int lm85_detach_client(struct i2c_client *client)
22824 +{
22825 +       int err;
22826 +       int id ;
22827 +
22828 +       id = client->id;
22829 +       i2c_deregister_entry(((struct lm85_data *)(client->data))->sysctl_id);
22830 +
22831 +       if ((err = i2c_detach_client(client))) {
22832 +               printk("lm85(%d): Client deregistration failed,"
22833 +                       " client not detached.\n", id );
22834 +               return err;
22835 +       }
22836 +
22837 +       kfree(client->data);
22838 +
22839 +       return 0;
22840 +}
22841 +
22842 +int lm85_read_value(struct i2c_client *client, u16 reg)
22843 +{
22844 +       int res;
22845 +
22846 +       /* What size location is it? */
22847 +       switch( reg ) {
22848 +       case LM85_REG_FAN(0) :  /* Read WORD data */
22849 +       case LM85_REG_FAN(1) :
22850 +       case LM85_REG_FAN(2) :
22851 +       case LM85_REG_FAN(3) :
22852 +       case LM85_REG_FAN_MIN(0) :
22853 +       case LM85_REG_FAN_MIN(1) :
22854 +       case LM85_REG_FAN_MIN(2) :
22855 +       case LM85_REG_FAN_MIN(3) :
22856 +       case LM85_REG_ALARM :  /* Read ALARM1 and ALARM2 */
22857 +       case ADM1027_REG_INTMASK :  /* Read MASK1 and MASK2 */
22858 +       case ADM1027_REG_EXTEND_ADC :  /* Read ADC1 and ADC2 */
22859 +               reg &= 0xff ;  /* Pseudo words have address + 0x0100 */
22860 +               res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
22861 +               res |= (i2c_smbus_read_byte_data(client, reg+1) & 0xff) << 8 ;
22862 +               break ;
22863 +       case ADT7463_REG_TMIN_CTL :  /* Read WORD MSB, LSB */
22864 +               reg &= 0xff ;  /* Pseudo words have address + 0x0100 */
22865 +               res = (i2c_smbus_read_byte_data(client, reg) & 0xff) << 8 ;
22866 +               res |= i2c_smbus_read_byte_data(client, reg+1) & 0xff ;
22867 +               break ;
22868 +       default:        /* Read BYTE data */
22869 +               res = i2c_smbus_read_byte_data(client, reg & 0xff) & 0xff ;
22870 +               break ;
22871 +       }
22872 +
22873 +       return res ;
22874 +}
22875 +
22876 +int lm85_write_value(struct i2c_client *client, u16 reg, int value)
22877 +{
22878 +       int res ;
22879 +
22880 +       switch( reg ) {
22881 +       case LM85_REG_FAN(0) :  /* Write WORD data */
22882 +       case LM85_REG_FAN(1) :
22883 +       case LM85_REG_FAN(2) :
22884 +       case LM85_REG_FAN(3) :
22885 +       case LM85_REG_FAN_MIN(0) :
22886 +       case LM85_REG_FAN_MIN(1) :
22887 +       case LM85_REG_FAN_MIN(2) :
22888 +       case LM85_REG_FAN_MIN(3) :
22889 +       case ADM1027_REG_INTMASK :
22890 +       /* NOTE: ALARM and ADC are read only, so not included here */
22891 +               reg &= 0xff ;  /* Pseudo words have address + 0x0100 */
22892 +               res = i2c_smbus_write_byte_data(client, reg, value & 0xff) ;
22893 +               res |= i2c_smbus_write_byte_data(client, reg+1, (value>>8) & 0xff) ;
22894 +               break ;
22895 +       case ADT7463_REG_TMIN_CTL :  /* Write WORD MSB, LSB */
22896 +               reg &= 0xff ;  /* Pseudo words have address + 0x0100 */
22897 +               res = i2c_smbus_write_byte_data(client, reg, (value>>8) & 0xff);
22898 +               res |= i2c_smbus_write_byte_data(client, reg+1, value & 0xff) ;
22899 +               break ;
22900 +       default:        /* Write BYTE data */
22901 +               res = i2c_smbus_write_byte_data(client, reg & 0xff, value);
22902 +               break ;
22903 +       }
22904 +
22905 +       return res ;
22906 +}
22907 +
22908 +/* Called when we have found a new LM85. It should set limits, etc. */
22909 +void lm85_init_client(struct i2c_client *client)
22910 +{
22911 +       int value;
22912 +       struct lm85_data *data = client->data;
22913 +
22914 +#ifdef DEBUG
22915 +       printk("lm85(%d): Initializing device\n", client->id);
22916 +#endif
22917 +
22918 +       /* Warn if part was not "READY" */
22919 +       value = lm85_read_value(client, LM85_REG_CONFIG);
22920 +#ifdef DEBUG
22921 +       printk("lm85(%d): LM85_REG_CONFIG is: 0x%02x\n", client->id, value );
22922 +#endif
22923 +       if( value & 0x02 ) {
22924 +               printk("lm85(%d): Client (%d,0x%02x) config is locked.\n",
22925 +                           client->id,
22926 +                           i2c_adapter_id(client->adapter), client->addr );
22927 +       };
22928 +       if( ! (value & 0x04) ) {
22929 +               printk("lm85(%d): Client (%d,0x%02x) is not ready.\n",
22930 +                           client->id,
22931 +                           i2c_adapter_id(client->adapter), client->addr );
22932 +       };
22933 +       if( (data->type == adm1027 || data->type == adt7463)
22934 +           && (value & 0x10)
22935 +       ) {
22936 +               printk("lm85(%d): Client (%d,0x%02x) VxI mode is set.  "
22937 +                       "Please report this to the lm85 maintainer.\n",
22938 +                           client->id,
22939 +                           i2c_adapter_id(client->adapter), client->addr );
22940 +       };
22941 +
22942 +       /* See if SYNC to PWM3 is set */
22943 +       if( data->type == adt7463 
22944 +           && (lm85_read_value(client, LM85_REG_AFAN_SPIKE1) & 0x10)
22945 +       ) {
22946 +               printk("lm85(%d): Sync to PWM3 is set.  Expect PWM3 "
22947 +                       "to control fans 2, 3, and 4\n",
22948 +                       client->id );
22949 +       };
22950 +
22951 +       /* See if PWM2 is #SMBALERT */
22952 +       if( (data->type == adm1027 || data->type == adt7463)
22953 +           && (lm85_read_value(client, ADM1027_REG_CONFIG3) & 0x01)
22954 +       ) {
22955 +               printk("lm85(%d): PWM2 is SMBALERT.  PWM2 not available.\n",
22956 +                       client->id );
22957 +       };
22958 +
22959 +       /* Check if 2.5V and 5V inputs are reconfigured */
22960 +       if( data->type == adt7463 ) {
22961 +               value = lm85_read_value(client, ADT7463_REG_CONFIG4);
22962 +               if( value & 0x01 ) {
22963 +                       printk("lm85(%d): 2.5V input (in0) is SMBALERT.  "
22964 +                               "in0 not available.\n", client->id );
22965 +               };
22966 +               if( value & 0x02 ) {
22967 +                       printk("lm85(%d): 5V input (in3) is THERM.  "
22968 +                               "in3 not available.\n", client->id );
22969 +               }
22970 +       };
22971 +
22972 +       /* FIXME?  Display EMC6D100 config info? */
22973 +
22974 +       /* WE INTENTIONALLY make no changes to the limits,
22975 +        *   offsets, pwms, fans and zones.  If they were
22976 +        *   configured, we don't want to mess with them.
22977 +        *   If they weren't, the default is 100% PWM, no
22978 +        *   control and will suffice until 'sensors -s'
22979 +        *   can be run by the user.
22980 +        */
22981 +
22982 +       /* Start monitoring */
22983 +       value = lm85_read_value(client, LM85_REG_CONFIG);
22984 +       /* Try to clear LOCK, Set START, save everything else */
22985 +       value = ((value & ~ 0x02) | 0x01) & 0xff ;
22986 +#ifdef DEBUG
22987 +       printk("lm85(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
22988 +#endif
22989 +       lm85_write_value(client, LM85_REG_CONFIG, value);
22990 +
22991 +}
22992 +
22993 +void lm85_update_client(struct i2c_client *client)
22994 +{
22995 +       struct lm85_data *data = client->data;
22996 +       int i;
22997 +
22998 +       down(&data->update_lock);
22999 +
23000 +       if (!data->valid
23001 +           || (jiffies - data->last_reading > LM85_DATA_INTERVAL )) {
23002 +               /* Things that change quickly */
23003 +
23004 +#ifdef DEBUG
23005 +               printk("lm85(%d): Reading sensor values\n", client->id);
23006 +#endif
23007 +               /* Have to read extended bits first to "freeze" the
23008 +                * more significant bits that are read later.
23009 +                */
23010 +               switch( data->type ) {
23011 +               case adm1027 :
23012 +               case adt7463 :
23013 +                       data->extend_adc =
23014 +                           lm85_read_value(client, ADM1027_REG_EXTEND_ADC);
23015 +                       break ;
23016 +               default :
23017 +                       data->extend_adc = 0 ;
23018 +                       break ;
23019 +               }
23020 +
23021 +               for (i = 0; i <= 4; ++i) {
23022 +                       data->in[i] =
23023 +                           lm85_read_value(client, LM85_REG_IN(i));
23024 +               }
23025 +
23026 +               for (i = 0; i <= 3; ++i) {
23027 +                       data->fan[i] =
23028 +                           lm85_read_value(client, LM85_REG_FAN(i));
23029 +               }
23030 +
23031 +               for (i = 0; i <= 2; ++i) {
23032 +                       data->temp[i] =
23033 +                           lm85_read_value(client, LM85_REG_TEMP(i));
23034 +               }
23035 +
23036 +               for (i = 0; i <= 2; ++i) {
23037 +                       data->pwm[i] =
23038 +                           lm85_read_value(client, LM85_REG_PWM(i));
23039 +               }
23040 +
23041 +               data->alarms = lm85_read_value(client, LM85_REG_ALARM);
23042 +
23043 +               switch( ((struct lm85_data *)(client->data))->type ) {
23044 +               case adt7463 :
23045 +                       /* REG_THERM code duplicated in therm_signal() */
23046 +                       i = lm85_read_value(client, ADT7463_REG_THERM);
23047 +                       if( data->therm_total < LONG_MAX - 256 ) {
23048 +                           data->therm_total += i ;
23049 +                       }
23050 +                       if( i >= 255 ) {
23051 +                               ++data->therm_ovfl ;
23052 +                       }
23053 +                       break ;
23054 +               case emc6d100 :
23055 +                       /* Three more voltage sensors */
23056 +                       for (i = 5; i <= 7; ++i) {
23057 +                           data->in[i] =
23058 +                               lm85_read_value(client, EMC6D100_REG_IN(i));
23059 +                       }
23060 +                       /* More alarm bits */
23061 +                       data->alarms |=
23062 +                           lm85_read_value(client, EMC6D100_REG_ALARM3) << 16;
23063 +
23064 +                       break ;
23065 +               default : break ; /* no warnings */
23066 +               }
23067 +
23068 +               data->last_reading = jiffies ;
23069 +       };  /* last_reading */
23070 +
23071 +       if (!data->valid
23072 +           || (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
23073 +               /* Things that don't change often */
23074 +
23075 +#ifdef DEBUG
23076 +               printk("lm85(%d): Reading config values\n", client->id);
23077 +#endif
23078 +               for (i = 0; i <= 4; ++i) {
23079 +                       data->in_min[i] =
23080 +                           lm85_read_value(client, LM85_REG_IN_MIN(i));
23081 +                       data->in_max[i] =
23082 +                           lm85_read_value(client, LM85_REG_IN_MAX(i));
23083 +               }
23084 +
23085 +               for (i = 0; i <= 3; ++i) {
23086 +                       data->fan_min[i] =
23087 +                           lm85_read_value(client, LM85_REG_FAN_MIN(i));
23088 +               }
23089 +
23090 +               for (i = 0; i <= 2; ++i) {
23091 +                       data->temp_min[i] =
23092 +                           lm85_read_value(client, LM85_REG_TEMP_MIN(i));
23093 +                       data->temp_max[i] =
23094 +                           lm85_read_value(client, LM85_REG_TEMP_MAX(i));
23095 +               }
23096 +
23097 +               data->vid = lm85_read_value(client, LM85_REG_VID);
23098 +
23099 +               for (i = 0; i <= 2; ++i) {
23100 +                       int val ;
23101 +                       data->autofan[i].config =
23102 +                           lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
23103 +                       val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
23104 +                       data->autofan[i].freq = val & 0x07 ;
23105 +                       data->zone[i].range = (val >> 4) & 0x0f ;
23106 +                       data->autofan[i].min_pwm =
23107 +                           lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
23108 +                       data->zone[i].limit =
23109 +                           lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
23110 +                       data->zone[i].critical =
23111 +                           lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
23112 +               }
23113 +
23114 +               i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
23115 +               data->smooth[0] = i & 0x0f ;
23116 +               data->syncpwm3 = i & 0x10 ;  /* Save PWM3 config */
23117 +               data->autofan[0].min_off = i & 0x20 ;
23118 +               data->autofan[1].min_off = i & 0x40 ;
23119 +               data->autofan[2].min_off = i & 0x80 ;
23120 +               i = lm85_read_value(client, LM85_REG_AFAN_SPIKE2);
23121 +               data->smooth[1] = (i>>4) & 0x0f ;
23122 +               data->smooth[2] = i & 0x0f ;
23123 +
23124 +               i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
23125 +               data->zone[0].hyst = (i>>4) & 0x0f ;
23126 +               data->zone[1].hyst = i & 0x0f ;
23127 +
23128 +               i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
23129 +               data->zone[2].hyst = (i>>4) & 0x0f ;
23130 +
23131 +               switch( ((struct lm85_data *)(client->data))->type ) {
23132 +               case lm85b :
23133 +               case lm85c :
23134 +                       data->tach_mode = lm85_read_value(client,
23135 +                               LM85_REG_TACH_MODE );
23136 +                       data->spinup_ctl = lm85_read_value(client,
23137 +                               LM85_REG_SPINUP_CTL );
23138 +                       break ;
23139 +               case adt7463 :
23140 +                       for (i = 0; i <= 2; ++i) {
23141 +                           data->oppoint[i] = lm85_read_value(client,
23142 +                               ADT7463_REG_OPPOINT(i) );
23143 +                       }
23144 +                       data->tmin_ctl = lm85_read_value(client,
23145 +                               ADT7463_REG_TMIN_CTL );
23146 +                       data->therm_limit = lm85_read_value(client,
23147 +                               ADT7463_REG_THERM_LIMIT );
23148 +               /* FALL THROUGH */
23149 +               case adm1027 :
23150 +                       for (i = 0; i <= 2; ++i) {
23151 +                           data->temp_offset[i] = lm85_read_value(client,
23152 +                               ADM1027_REG_TEMP_OFFSET(i) );
23153 +                       }
23154 +                       data->tach_mode = lm85_read_value(client,
23155 +                               ADM1027_REG_CONFIG3 );
23156 +                       data->fan_ppr = lm85_read_value(client,
23157 +                               ADM1027_REG_FAN_PPR );
23158 +                       data->alarm_mask = lm85_read_value(client,
23159 +                               ADM1027_REG_INTMASK );
23160 +                       break ;
23161 +               case emc6d100 :
23162 +                       for (i = 5; i <= 7; ++i) {
23163 +                           data->in_min[i] =
23164 +                               lm85_read_value(client, EMC6D100_REG_IN_MIN(i));
23165 +                           data->in_max[i] =
23166 +                               lm85_read_value(client, EMC6D100_REG_IN_MAX(i));
23167 +                       }
23168 +                       break ;
23169 +               default : break ; /* no warnings */
23170 +               }
23171 +       
23172 +               data->last_config = jiffies;
23173 +       };  /* last_config */
23174 +
23175 +       data->valid = 1;
23176 +
23177 +       up(&data->update_lock);
23178 +}
23179 +
23180 +
23181 +/* The next functions are the call-back functions of the /proc/sys and
23182 +   sysctl files. Which function is used is defined in the ctl_table in
23183 +   the extra1 field.
23184 +   Each function must return the magnitude (power of 10 to divide the data
23185 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO.  It must
23186 +   put a maximum of *nrels elements in results reflecting the data of this
23187 +   file, and set *nrels to the number it actually put in it, if operation==
23188 +   SENSORS_PROC_REAL_READ.  Finally, it must get upto *nrels elements from
23189 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
23190 + */
23191 +void lm85_in(struct i2c_client *client, int operation, int ctl_name,
23192 +            int *nrels_mag, long *results)
23193 +{
23194 +       struct lm85_data *data = client->data;
23195 +       int nr = ctl_name - LM85_SYSCTL_IN0;
23196 +
23197 +       if (nr < 0 || nr > 4)
23198 +               return ;  /* ERROR */
23199 +
23200 +       if (operation == SENSORS_PROC_REAL_INFO)
23201 +               *nrels_mag = 3;  /* 1.000 */
23202 +       else if (operation == SENSORS_PROC_REAL_READ) {
23203 +               int  ext = 0 ;
23204 +               lm85_update_client(client);
23205 +               ext = EXT_FROM_REG(data->extend_adc, nr);
23206 +               results[0] = INS_FROM_REG(nr,data->in_min[nr]);
23207 +               results[1] = INS_FROM_REG(nr,data->in_max[nr]);
23208 +               results[2] = INSEXT_FROM_REG(nr,data->in[nr],ext);
23209 +               *nrels_mag = 3;
23210 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23211 +               down(&data->update_lock);
23212 +               if (*nrels_mag > 1) {
23213 +                       data->in_max[nr] = INS_TO_REG(nr,results[1]);
23214 +                       lm85_write_value(client, LM85_REG_IN_MAX(nr),
23215 +                                        data->in_max[nr]);
23216 +               }
23217 +               if (*nrels_mag > 0) {
23218 +                       data->in_min[nr] = INS_TO_REG(nr,results[0]);
23219 +                       lm85_write_value(client, LM85_REG_IN_MIN(nr),
23220 +                                        data->in_min[nr]);
23221 +               }
23222 +               up(&data->update_lock);
23223 +       }
23224 +}
23225 +
23226 +void lm85_fan(struct i2c_client *client, int operation, int ctl_name,
23227 +             int *nrels_mag, long *results)
23228 +{
23229 +       struct lm85_data *data = client->data;
23230 +       int nr = ctl_name - LM85_SYSCTL_FAN1 ;
23231 +
23232 +       if (nr < 0 || nr > 3)
23233 +               return ;  /* ERROR */
23234 +
23235 +       if (operation == SENSORS_PROC_REAL_INFO)
23236 +               *nrels_mag = 0;
23237 +       else if (operation == SENSORS_PROC_REAL_READ) {
23238 +               lm85_update_client(client);
23239 +               results[0] = FAN_FROM_REG(data->fan_min[nr]);
23240 +               results[1] = FAN_FROM_REG(data->fan[nr]);
23241 +               *nrels_mag = 2;
23242 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23243 +               down(&data->update_lock);
23244 +               if (*nrels_mag > 0) {
23245 +                       data->fan_min[nr] = FAN_TO_REG(results[0]);
23246 +                       lm85_write_value(client, LM85_REG_FAN_MIN(nr),
23247 +                                        data->fan_min[nr]);
23248 +               }
23249 +               up(&data->update_lock);
23250 +       }
23251 +}
23252 +
23253 +
23254 +void lm85_temp(struct i2c_client *client, int operation, int ctl_name,
23255 +              int *nrels_mag, long *results)
23256 +{
23257 +       struct lm85_data *data = client->data;
23258 +       int nr = ctl_name - LM85_SYSCTL_TEMP1 ;
23259 +
23260 +       if (nr < 0 || nr > 2)
23261 +               return ;  /* ERROR */
23262 +
23263 +       if (operation == SENSORS_PROC_REAL_INFO)
23264 +               *nrels_mag = 2;
23265 +       else if (operation == SENSORS_PROC_REAL_READ) {
23266 +               int  ext = 0 ;
23267 +               lm85_update_client(client);
23268 +
23269 +               /* +5 for offset of temp data in ext reg */
23270 +               ext = EXT_FROM_REG(data->extend_adc, nr+5);
23271 +
23272 +               results[0] = TEMP_FROM_REG(data->temp_min[nr]);
23273 +               results[1] = TEMP_FROM_REG(data->temp_max[nr]);
23274 +               results[2] = TEMPEXT_FROM_REG(data->temp[nr],ext);
23275 +               *nrels_mag = 3;
23276 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23277 +               down(&data->update_lock);
23278 +               if (*nrels_mag > 1) {
23279 +                       data->temp_max[nr] = TEMP_TO_REG(results[1]);
23280 +                       lm85_write_value(client, LM85_REG_TEMP_MAX(nr),
23281 +                                        data->temp_max[nr]);
23282 +               }
23283 +               if (*nrels_mag > 0) {
23284 +                       data->temp_min[nr] = TEMP_TO_REG(results[0]);
23285 +                       lm85_write_value(client, LM85_REG_TEMP_MIN(nr),
23286 +                                        data->temp_min[nr]);
23287 +               }
23288 +               up(&data->update_lock);
23289 +       }
23290 +}
23291 +
23292 +void lm85_pwm(struct i2c_client *client, int operation, int ctl_name,
23293 +             int *nrels_mag, long *results)
23294 +{
23295 +       struct lm85_data *data = client->data;
23296 +       int nr = ctl_name - LM85_SYSCTL_PWM1 ;
23297 +       int pwm_zone ;
23298 +
23299 +       if (nr < 0 || nr > 2)
23300 +               return ;  /* ERROR */
23301 +
23302 +       if (operation == SENSORS_PROC_REAL_INFO)
23303 +               *nrels_mag = 0;
23304 +       else if (operation == SENSORS_PROC_REAL_READ) {
23305 +               lm85_update_client(client);
23306 +               results[0] = PWM_FROM_REG(data->pwm[nr]);
23307 +               pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
23308 +               /* PWM "enabled" if not off (0) nor on (-1) */
23309 +               results[1] = pwm_zone != 0 && pwm_zone != -1 ;
23310 +               *nrels_mag = 2;
23311 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23312 +               down(&data->update_lock);
23313 +               /* PWM enable is read-only */
23314 +               if (*nrels_mag > 0) {
23315 +                       data->pwm[nr] = PWM_TO_REG(results[0]);
23316 +                       lm85_write_value(client, LM85_REG_PWM(nr),
23317 +                                        data->pwm[nr]);
23318 +               }
23319 +               up(&data->update_lock);
23320 +       }
23321 +}
23322 +
23323 +void lm85_vid(struct i2c_client *client, int operation, int ctl_name,
23324 +             int *nrels_mag, long *results)
23325 +{
23326 +       struct lm85_data *data = client->data;
23327 +
23328 +       if( ctl_name != LM85_SYSCTL_VID )
23329 +               return ;  /* ERROR */
23330 +
23331 +       if (operation == SENSORS_PROC_REAL_INFO)
23332 +               *nrels_mag = 3;
23333 +       else if (operation == SENSORS_PROC_REAL_READ) {
23334 +               lm85_update_client(client);
23335 +               results[0] = VID_FROM_REG((data->vid)&0x3f,data->vrm);
23336 +               *nrels_mag = 1;
23337 +       }
23338 +}
23339 +
23340 +void lm85_vrm(struct i2c_client *client, int operation, int ctl_name,
23341 +             int *nrels_mag, long *results)
23342 +{
23343 +       struct lm85_data *data = client->data;
23344 +
23345 +       if( ctl_name != LM85_SYSCTL_VRM )
23346 +               return ;  /* ERROR */
23347 +
23348 +       if (operation == SENSORS_PROC_REAL_INFO)
23349 +               *nrels_mag = 1;
23350 +       else if (operation == SENSORS_PROC_REAL_READ) {
23351 +               results[0] = data->vrm ;
23352 +               *nrels_mag = 1;
23353 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23354 +               down(&data->update_lock);
23355 +               if (*nrels_mag > 0) {
23356 +                       data->vrm = results[0] ;
23357 +               }
23358 +               up(&data->update_lock);
23359 +       }
23360 +}
23361 +
23362 +void lm85_alarms(struct i2c_client *client, int operation, int ctl_name,
23363 +               int *nrels_mag, long *results)
23364 +{
23365 +       struct lm85_data *data = client->data;
23366 +
23367 +       if( ctl_name != LM85_SYSCTL_ALARMS )
23368 +               return ;  /* ERROR */
23369 +
23370 +       if (operation == SENSORS_PROC_REAL_INFO)
23371 +               *nrels_mag = 0;
23372 +       else if (operation == SENSORS_PROC_REAL_READ) {
23373 +               lm85_update_client(client);
23374 +               results[0] = ALARMS_FROM_REG(data->alarms);
23375 +               *nrels_mag = 1;
23376 +       }
23377 +}
23378 +
23379 +void lm85_spinup_ctl(struct i2c_client *client, int operation, int ctl_name,
23380 +                 int *nrels_mag, long *results)
23381 +{
23382 +       struct lm85_data *data = client->data;
23383 +       int old;
23384 +
23385 +       if( ctl_name != LM85_SYSCTL_SPINUP_CTL )
23386 +               return ;  /* ERROR */
23387 +
23388 +       if (operation == SENSORS_PROC_REAL_INFO)
23389 +               *nrels_mag = 0;
23390 +       else if (operation == SENSORS_PROC_REAL_READ) {
23391 +               lm85_update_client(client);
23392 +               results[0] = (data->spinup_ctl & 1) != 0 ;
23393 +               results[1] = (data->spinup_ctl & 2) != 0 ;
23394 +               results[2] = (data->spinup_ctl & 4) != 0 ;
23395 +               *nrels_mag = 3;
23396 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23397 +               down(&data->update_lock);
23398 +               old = data->spinup_ctl ;
23399 +               if (*nrels_mag > 2) {
23400 +                       old = (old & (~4)) | (results[2]?4:0) ;
23401 +               }
23402 +               if (*nrels_mag > 1) {
23403 +                       old = (old & (~2)) | (results[1]?2:0) ;
23404 +               }
23405 +               if (*nrels_mag > 0) {
23406 +                       old = (old & (~1)) | (results[0]?1:0) ;
23407 +                       lm85_write_value(client, LM85_REG_SPINUP_CTL, old);
23408 +                       data->spinup_ctl = old ;
23409 +               }
23410 +               up(&data->update_lock);
23411 +       }
23412 +}
23413 +
23414 +void lm85_tach_mode(struct i2c_client *client, int operation, int ctl_name,
23415 +                 int *nrels_mag, long *results)
23416 +{
23417 +       struct lm85_data *data = client->data;
23418 +       int old;
23419 +
23420 +       /* Tach Mode 1, Tach Mode 2, Tach Mode 3 & 4 */
23421 +
23422 +       if( ctl_name != LM85_SYSCTL_TACH_MODE )
23423 +               return ;  /* ERROR */
23424 +
23425 +       if (operation == SENSORS_PROC_REAL_INFO)
23426 +               *nrels_mag = 0;
23427 +       else if (operation == SENSORS_PROC_REAL_READ) {
23428 +               lm85_update_client(client);
23429 +               results[0] = (data->tach_mode & 0x03) ;
23430 +               results[1] = (data->tach_mode & 0x0c) >> 2 ;
23431 +               results[2] = (data->tach_mode & 0x30) >> 4 ;
23432 +               *nrels_mag = 3;
23433 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23434 +               down(&data->update_lock);
23435 +               old = data->tach_mode ;
23436 +               if (*nrels_mag > 2) {
23437 +                       old = (old & (~0x30)) | ((results[2]&3) << 4) ;
23438 +               }
23439 +               if (*nrels_mag > 1) {
23440 +                       old = (old & (~0x0c)) | ((results[1]&3) << 2) ;
23441 +               }
23442 +               if (*nrels_mag > 0) {
23443 +                       old = (old & (~0x03)) |  (results[0]&3) ;
23444 +                       lm85_write_value(client, LM85_REG_TACH_MODE, old);
23445 +                       data->tach_mode = old ;
23446 +               }
23447 +               up(&data->update_lock);
23448 +       }
23449 +}
23450 +
23451 +void adm1027_tach_mode(struct i2c_client *client, int operation, int ctl_name,
23452 +                 int *nrels_mag, long *results)
23453 +{
23454 +       struct lm85_data *data = client->data;
23455 +       int old;
23456 +
23457 +       /* Tach/DC 1, Tach/DC 2, Tach/DC 3, Tach/DC 4 */
23458 +
23459 +       if( ctl_name != ADM1027_SYSCTL_TACH_MODE )
23460 +               return ;  /* ERROR */
23461 +
23462 +       if (operation == SENSORS_PROC_REAL_INFO)
23463 +               *nrels_mag = 0;
23464 +       else if (operation == SENSORS_PROC_REAL_READ) {
23465 +               lm85_update_client(client);
23466 +               results[0] = (data->tach_mode & 0x10) != 0 ;
23467 +               results[1] = (data->tach_mode & 0x20) != 0 ;
23468 +               results[2] = (data->tach_mode & 0x40) != 0 ;
23469 +               results[3] = (data->tach_mode & 0x80) != 0 ;
23470 +               *nrels_mag = 4;
23471 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23472 +               down(&data->update_lock);
23473 +               old = data->tach_mode ;
23474 +               if (*nrels_mag > 3) {
23475 +                       old = (old & (~0x80)) | (results[3] ? 0x80 : 0) ;
23476 +               }
23477 +               if (*nrels_mag > 2) {
23478 +                       old = (old & (~0x40)) | (results[2] ? 0x40 : 0) ;
23479 +               }
23480 +               if (*nrels_mag > 1) {
23481 +                       old = (old & (~0x20)) | (results[1] ? 0x20 : 0) ;
23482 +               }
23483 +               if (*nrels_mag > 0) {
23484 +                       old = (old & (~0x10)) | (results[0] ? 0x10 : 0) ;
23485 +
23486 +                       /* Enable fast measurements if any TACH's are DC */
23487 +                       old = (old & (~0x08)) | ((old&0xf0) ? 0x08 : 0) ;
23488 +
23489 +                       lm85_write_value(client, ADM1027_REG_CONFIG3, old);
23490 +                       data->tach_mode = old ;
23491 +               }
23492 +               up(&data->update_lock);
23493 +       }
23494 +}
23495 +
23496 +void lm85_pwm_config(struct i2c_client *client, int operation, int ctl_name,
23497 +                 int *nrels_mag, long *results)
23498 +{
23499 +       struct lm85_data *data = client->data;
23500 +       int nr = ctl_name - LM85_SYSCTL_PWM_CFG1 ;
23501 +
23502 +       /* Spinup, min PWM, PWM Frequency, min below limit, Invert */
23503 +
23504 +       if (nr < 0 || nr > 2)
23505 +               return ;  /* ERROR */
23506 +
23507 +       if (operation == SENSORS_PROC_REAL_INFO)
23508 +               *nrels_mag = 1;
23509 +       else if (operation == SENSORS_PROC_REAL_READ) {
23510 +               lm85_update_client(client);
23511 +
23512 +               results[0] = SPINUP_FROM_REG(data->autofan[nr].config);
23513 +               results[1] = PWM_FROM_REG(data->autofan[nr].min_pwm)*10;
23514 +               results[2] = FREQ_FROM_REG(data->autofan[nr].freq);
23515 +               results[3] = data->autofan[nr].min_off ? 10 : 0 ;
23516 +               results[4] = (data->autofan[nr].config & 0x10) ? 10 : 0 ;
23517 +               *nrels_mag = 5;
23518 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23519 +               int  old_config ;
23520 +
23521 +               down(&data->update_lock);
23522 +               old_config = data->autofan[nr].config ;
23523 +               if (*nrels_mag > 4) {
23524 +                       old_config = (old_config & (~0x10)) | (results[4]?0x10:0) ;
23525 +               }
23526 +               if (*nrels_mag > 3) {
23527 +                       data->autofan[nr].min_off = results[3] != 0 ;
23528 +                       lm85_write_value(client, LM85_REG_AFAN_SPIKE1,
23529 +                               data->smooth[0]
23530 +                               | data->syncpwm3
23531 +                               | (data->autofan[0].min_off ? 0x20 : 0)
23532 +                               | (data->autofan[1].min_off ? 0x40 : 0)
23533 +                               | (data->autofan[2].min_off ? 0x80 : 0)
23534 +                       );
23535 +               }
23536 +               if (*nrels_mag > 2) {
23537 +                       data->autofan[nr].freq = FREQ_TO_REG(results[2]) ;
23538 +                       lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
23539 +                           (data->zone[nr].range << 4)
23540 +                           | data->autofan[nr].freq
23541 +                       );
23542 +               }
23543 +               if (*nrels_mag > 1) {
23544 +                       data->autofan[nr].min_pwm = PWM_TO_REG((results[1]+5)/10);
23545 +                       lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr),
23546 +                                       data->autofan[nr].min_pwm
23547 +                       );
23548 +               }
23549 +               if (*nrels_mag > 0) {
23550 +                       old_config = (old_config & (~0x07)) | SPINUP_TO_REG(results[0]) ;
23551 +                       lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), old_config);
23552 +                       data->autofan[nr].config = old_config ;
23553 +               }
23554 +               up(&data->update_lock);
23555 +       }
23556 +}
23557 +
23558 +void lm85_smooth(struct i2c_client *client, int operation, int ctl_name,
23559 +                 int *nrels_mag, long *results)
23560 +{
23561 +       struct lm85_data *data = client->data;
23562 +       int nr = ctl_name - LM85_SYSCTL_SMOOTH1 ;
23563 +
23564 +       if (nr < 0 || nr > 2)
23565 +               return ;  /* ERROR */
23566 +
23567 +       if (operation == SENSORS_PROC_REAL_INFO)
23568 +               *nrels_mag = 1;
23569 +       else if (operation == SENSORS_PROC_REAL_READ) {
23570 +               lm85_update_client(client);
23571 +               results[0] = SMOOTH_FROM_REG(data->smooth[nr]);
23572 +               *nrels_mag = 1;
23573 +
23574 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23575 +               down(&data->update_lock);
23576 +               if( *nrels_mag > 0 ) {
23577 +                       data->smooth[nr] = SMOOTH_TO_REG(results[0]);
23578 +               }
23579 +               if( nr == 0 ) {
23580 +                   lm85_write_value(client, LM85_REG_AFAN_SPIKE1,
23581 +                       data->smooth[0]
23582 +                       | data->syncpwm3
23583 +                       | (data->autofan[0].min_off ? 0x20 : 0)
23584 +                       | (data->autofan[1].min_off ? 0x40 : 0)
23585 +                       | (data->autofan[2].min_off ? 0x80 : 0)
23586 +                   );
23587 +               } else {
23588 +                   lm85_write_value(client, LM85_REG_AFAN_SPIKE2,
23589 +                       (data->smooth[1] << 4) | data->smooth[2]);
23590 +               }
23591 +               up(&data->update_lock);
23592 +       }
23593 +}
23594 +
23595 +void lm85_zone(struct i2c_client *client, int operation, int ctl_name,
23596 +                 int *nrels_mag, long *results)
23597 +{
23598 +       struct lm85_data *data = client->data;
23599 +       int nr = ctl_name - LM85_SYSCTL_ZONE1 ;
23600 +
23601 +       /* Limit, Hysteresis (neg), Range, Critical */
23602 +
23603 +       if (nr < 0 || nr > 2)
23604 +               return ;  /* ERROR */
23605 +
23606 +       if (operation == SENSORS_PROC_REAL_INFO)
23607 +               *nrels_mag = 1;
23608 +       else if (operation == SENSORS_PROC_REAL_READ) {
23609 +               lm85_update_client(client);
23610 +
23611 +               results[0] = TEMP_FROM_REG(data->zone[nr].limit) / 10;
23612 +               results[1] = HYST_FROM_REG(data->zone[nr].hyst);
23613 +               results[2] = RANGE_FROM_REG(data->zone[nr].range);
23614 +               results[3] = TEMP_FROM_REG(data->zone[nr].critical) / 10;
23615 +               *nrels_mag = 4;
23616 +
23617 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23618 +               down(&data->update_lock);
23619 +               if (*nrels_mag > 3) {
23620 +                       data->zone[nr].critical = TEMP_TO_REG(results[3]*10);
23621 +                       lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr),
23622 +                               data->zone[nr].critical );
23623 +               }
23624 +               if (*nrels_mag > 2) {
23625 +                       data->zone[nr].range = RANGE_TO_REG(results[2]);
23626 +                       lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
23627 +                           (data->zone[nr].range << 4)
23628 +                           | data->autofan[nr].freq
23629 +                       );
23630 +               }
23631 +               if (*nrels_mag > 1) {
23632 +                       data->zone[nr].hyst = HYST_TO_REG(results[1]);
23633 +                       if( nr == 0 || nr == 1 ) {
23634 +                           lm85_write_value(client, LM85_REG_AFAN_HYST1,
23635 +                               (data->zone[0].hyst << 4)
23636 +                               | data->zone[1].hyst
23637 +                           );
23638 +                       } else {
23639 +                           lm85_write_value(client, LM85_REG_AFAN_HYST2,
23640 +                               (data->zone[2].hyst << 4)
23641 +                           );
23642 +                       }
23643 +               }
23644 +               if (*nrels_mag > 0) {
23645 +                       data->zone[nr].limit = TEMP_TO_REG(results[0]*10);
23646 +                       lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr),
23647 +                           data->zone[nr].limit
23648 +                       );
23649 +               }
23650 +               up(&data->update_lock);
23651 +       }
23652 +}
23653 +
23654 +void lm85_pwm_zone(struct i2c_client *client, int operation, int ctl_name,
23655 +               int *nrels_mag, long *results)
23656 +{
23657 +       struct lm85_data *data = client->data;
23658 +       int nr = ctl_name - LM85_SYSCTL_PWM_ZONE1 ;
23659 +
23660 +       if (nr < 0 || nr > 2)
23661 +               return ;  /* ERROR */
23662 +
23663 +       if (operation == SENSORS_PROC_REAL_INFO)
23664 +               *nrels_mag = 0;
23665 +       else if (operation == SENSORS_PROC_REAL_READ) {
23666 +               lm85_update_client(client);
23667 +               results[0] = ZONE_FROM_REG(data->autofan[nr].config);
23668 +               *nrels_mag = 1;
23669 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23670 +               down(&data->update_lock);
23671 +               if (*nrels_mag > 0) {
23672 +                       data->autofan[nr].config =
23673 +                           (data->autofan[nr].config & (~0xe0))
23674 +                           | ZONE_TO_REG(results[0]) ;
23675 +                       lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr),
23676 +                           data->autofan[nr].config);
23677 +               }
23678 +               up(&data->update_lock);
23679 +       }
23680 +}
23681 +
23682 +void adm1027_temp_offset(struct i2c_client *client, int operation, int ctl_name,
23683 +               int *nrels_mag, long *results)
23684 +{
23685 +       struct lm85_data *data = client->data;
23686 +       int nr = ctl_name - ADM1027_SYSCTL_TEMP_OFFSET1 ;
23687 +
23688 +       if (nr < 0 || nr > 2)
23689 +               return ;  /* ERROR */
23690 +
23691 +       if (operation == SENSORS_PROC_REAL_INFO)
23692 +               *nrels_mag = 2;
23693 +       else if (operation == SENSORS_PROC_REAL_READ) {
23694 +               lm85_update_client(client);
23695 +               switch( data->type ) {
23696 +               case adm1027 :
23697 +               default :
23698 +                       results[0] = TEMP_FROM_REG(data->temp_offset[nr]);
23699 +                       break ;
23700 +               case adt7463 :
23701 +                       results[0] = TEMPEXT_FROM_REG(0,data->temp_offset[nr]);
23702 +                       break ;
23703 +               }
23704 +               *nrels_mag = 1;
23705 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23706 +               down(&data->update_lock);
23707 +               if (*nrels_mag > 0) {
23708 +                       switch( data->type ) {
23709 +                       case adm1027 :
23710 +                       default :
23711 +                           data->temp_offset[nr] = TEMP_TO_REG(results[0]);
23712 +                           break ;
23713 +                       case adt7463 :
23714 +                           data->temp_offset[nr] = EXTTEMP_TO_REG(results[0]);
23715 +                           break ;
23716 +                       };
23717 +                       lm85_write_value(client, ADM1027_REG_TEMP_OFFSET(nr),
23718 +                           data->temp_offset[nr]);
23719 +               }
23720 +               up(&data->update_lock);
23721 +       }
23722 +}
23723 +
23724 +void adm1027_fan_ppr(struct i2c_client *client, int operation, int ctl_name,
23725 +               int *nrels_mag, long *results)
23726 +{
23727 +       struct lm85_data *data = client->data;
23728 +       int old ;
23729 +
23730 +       if (ctl_name != ADM1027_SYSCTL_FAN_PPR)
23731 +               return ;  /* ERROR */
23732 +
23733 +       if (operation == SENSORS_PROC_REAL_INFO)
23734 +               *nrels_mag = 0;
23735 +       else if (operation == SENSORS_PROC_REAL_READ) {
23736 +               lm85_update_client(client);
23737 +               results[0] = PPR_FROM_REG(data->fan_ppr,0);
23738 +               results[1] = PPR_FROM_REG(data->fan_ppr,1);
23739 +               results[2] = PPR_FROM_REG(data->fan_ppr,2);
23740 +               results[3] = PPR_FROM_REG(data->fan_ppr,3);
23741 +               *nrels_mag = 4;
23742 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23743 +               down(&data->update_lock);
23744 +               old = data->fan_ppr ;
23745 +               if (*nrels_mag > 3) {
23746 +                       old = (old & ~PPR_MASK(3)) | PPR_TO_REG(results[3],3);
23747 +               };
23748 +               if (*nrels_mag > 2) {
23749 +                       old = (old & ~PPR_MASK(2)) | PPR_TO_REG(results[2],2);
23750 +               };
23751 +               if (*nrels_mag > 1) {
23752 +                       old = (old & ~PPR_MASK(1)) | PPR_TO_REG(results[1],1);
23753 +               };
23754 +               if (*nrels_mag > 0) {
23755 +                       old = (old & ~PPR_MASK(0)) | PPR_TO_REG(results[0],0);
23756 +                       lm85_write_value(client, ADM1027_REG_FAN_PPR, old);
23757 +                       data->fan_ppr = old ;
23758 +               }
23759 +               up(&data->update_lock);
23760 +       }
23761 +}
23762 +
23763 +void adm1027_alarm_mask(struct i2c_client *client, int operation,
23764 +               int ctl_name, int *nrels_mag, long *results)
23765 +{
23766 +       struct lm85_data *data = client->data;
23767 +
23768 +       if( ctl_name != ADM1027_SYSCTL_ALARM_MASK )
23769 +               return ;  /* ERROR */
23770 +
23771 +       if (operation == SENSORS_PROC_REAL_INFO)
23772 +               *nrels_mag = 0;
23773 +       else if (operation == SENSORS_PROC_REAL_READ) {
23774 +               lm85_update_client(client);
23775 +               results[0] = INTMASK_FROM_REG(data->alarm_mask);
23776 +               *nrels_mag = 1;
23777 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23778 +               down(&data->update_lock);
23779 +               if (*nrels_mag > 0) {
23780 +                       data->alarm_mask = INTMASK_TO_REG(results[0]);
23781 +                       lm85_write_value(client, ADM1027_REG_INTMASK,
23782 +                           data->alarm_mask);
23783 +               }
23784 +               up(&data->update_lock);
23785 +       }
23786 +}
23787 +
23788 +void adt7463_tmin_ctl(struct i2c_client *client, int operation, int ctl_name,
23789 +               int *nrels_mag, long *results)
23790 +{
23791 +       struct lm85_data *data = client->data;
23792 +       int nr = ctl_name - ADT7463_SYSCTL_TMIN_CTL1 ;
23793 +       u16 old ;
23794 +
23795 +       if (nr < 0 || nr > 2)
23796 +               return ;  /* ERROR */
23797 +
23798 +       if (operation == SENSORS_PROC_REAL_INFO)
23799 +               *nrels_mag = 0;
23800 +       else if (operation == SENSORS_PROC_REAL_READ) {
23801 +               old = data->tmin_ctl ;
23802 +               results[0] = (old & ( 0x2000 << nr )) != 0 ;
23803 +               results[1] = (old >> (nr*3)) & 0x07  ;
23804 +               results[2] = (old & ( 0x0400 << nr )) != 0 ;
23805 +               results[3] = OPPOINT_FROM_REG(data->oppoint[nr]);
23806 +               *nrels_mag = 4;
23807 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23808 +               down(&data->update_lock);
23809 +               old = data->tmin_ctl ;
23810 +               if (*nrels_mag > 3) {
23811 +                       data->oppoint[nr] = OPPOINT_TO_REG(results[3]);
23812 +                       lm85_write_value(client, ADT7463_REG_OPPOINT(nr),
23813 +                           data->oppoint[nr]);
23814 +               };
23815 +               if (*nrels_mag > 2) {
23816 +                       if( results[2] ) {
23817 +                               old |= (0x0400 << nr) ;
23818 +                       } else {
23819 +                               old &= ~(0x0400 << nr) ;
23820 +                       }
23821 +               };
23822 +               if (*nrels_mag > 1) {
23823 +                       old &= ~(0x07 << (nr*3)) ;
23824 +                       old |= (results[1] & 0x07) << (nr*3) ;
23825 +               };
23826 +               if (*nrels_mag > 0) {
23827 +                       if( results[0] ) {
23828 +                               old |= 0x2000 << nr ;
23829 +                       } else {
23830 +                               old &= ~(0x2000 << nr) ;
23831 +                       }
23832 +                       lm85_write_value(client, ADT7463_REG_TMIN_CTL, old);
23833 +                       data->tmin_ctl = old ;
23834 +               }
23835 +               up(&data->update_lock);
23836 +       }
23837 +}
23838 +
23839 +void adt7463_therm_signal(struct i2c_client *client, int operation,
23840 +               int ctl_name, int *nrels_mag, long *results)
23841 +{
23842 +       struct lm85_data *data = client->data;
23843 +       int counts ;
23844 +
23845 +       if (ctl_name != ADT7463_SYSCTL_THERM_SIGNAL)
23846 +               return ;  /* ERROR */
23847 +
23848 +       if (operation == SENSORS_PROC_REAL_INFO)
23849 +               *nrels_mag = 0;
23850 +       else if (operation == SENSORS_PROC_REAL_READ) {
23851 +               /* Don't call update_client here because
23852 +                *   ADT7463_REG_THERM has to be read every
23853 +                *   5 seconds to prevent lost counts
23854 +                */
23855 +               down(&data->update_lock);
23856 +               counts = lm85_read_value(client, ADT7463_REG_THERM) & 0xff;
23857 +               if( data->therm_total < LONG_MAX - 256 ) {
23858 +                   data->therm_total += counts ;
23859 +               }
23860 +               if( counts >= 255 ) {
23861 +                   ++data->therm_ovfl ;
23862 +               }
23863 +               up(&data->update_lock);
23864 +
23865 +               results[0] = data->therm_limit ;
23866 +               results[1] = data->therm_total ;
23867 +               results[2] = data->therm_ovfl ;
23868 +               *nrels_mag = 3;
23869 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23870 +               down(&data->update_lock);
23871 +               /* therm_total and therm_ovfl are read only */
23872 +               if (*nrels_mag > 0) {
23873 +                       data->therm_limit = SENSORS_LIMIT(results[0],0,255);
23874 +                       lm85_write_value(client, ADT7463_REG_THERM_LIMIT,
23875 +                           data->therm_limit);
23876 +               };
23877 +               up(&data->update_lock);
23878 +       }
23879 +}
23880 +
23881 +
23882 +void emc6d100_in(struct i2c_client *client, int operation, int ctl_name,
23883 +            int *nrels_mag, long *results)
23884 +{
23885 +       struct lm85_data *data = client->data;
23886 +       int nr = ctl_name - EMC6D100_SYSCTL_IN5 +5;
23887 +
23888 +       if (nr < 5 || nr > 7)
23889 +               return ;  /* ERROR */
23890 +
23891 +       if (operation == SENSORS_PROC_REAL_INFO)
23892 +               *nrels_mag = 3;  /* 1.000 */
23893 +       else if (operation == SENSORS_PROC_REAL_READ) {
23894 +               lm85_update_client(client);
23895 +               results[0] = INS_FROM_REG(nr,data->in_min[nr]);
23896 +               results[1] = INS_FROM_REG(nr,data->in_max[nr]);
23897 +               results[2] = INS_FROM_REG(nr,data->in[nr]);
23898 +               *nrels_mag = 3;
23899 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
23900 +               down(&data->update_lock);
23901 +               if (*nrels_mag > 1) {
23902 +                       data->in_max[nr] = INS_TO_REG(nr,results[1]);
23903 +                       lm85_write_value(client, EMC6D100_REG_IN_MAX(nr),
23904 +                                        data->in_max[nr]);
23905 +               }
23906 +               if (*nrels_mag > 0) {
23907 +                       data->in_min[nr] = INS_TO_REG(nr,results[0]);
23908 +                       lm85_write_value(client, EMC6D100_REG_IN_MIN(nr),
23909 +                                        data->in_min[nr]);
23910 +               }
23911 +               up(&data->update_lock);
23912 +       }
23913 +}
23914 +
23915 +
23916 +static int __init sm_lm85_init(void)
23917 +{
23918 +       printk("lm85: Version %s (%s)\n", LM_VERSION, LM_DATE);
23919 +       printk("lm85: See http://www.penguincomputing.com/lm_sensors for more info.\n" );
23920 +       return i2c_add_driver(&lm85_driver);
23921 +}
23922 +
23923 +static void __exit sm_lm85_exit(void)
23924 +{
23925 +       i2c_del_driver(&lm85_driver);
23926 +}
23927 +
23928 +/* Thanks to Richard Barrington for adding the LM85 to sensors-detect.
23929 + * Thanks to Margit Schubert-While <margitsw@t-online.de> for help with
23930 + *     post 2.7.0 CVS changes
23931 + */
23932 +MODULE_LICENSE("GPL");
23933 +MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com");
23934 +MODULE_DESCRIPTION("LM85-B, LM85-C driver");
23935 +
23936 +module_init(sm_lm85_init);
23937 +module_exit(sm_lm85_exit);
23938 --- linux-old/drivers/sensors/lm87.c    Thu Jan  1 00:00:00 1970
23939 +++ linux/drivers/sensors/lm87.c        Mon Dec 13 20:18:49 2004
23940 @@ -0,0 +1,988 @@
23941 +/*
23942 +    LM87.c - Part of lm_sensors, Linux kernel modules for hardware
23943 +             monitoring
23944 +    Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>
23945 +                        Philip Edelbrock <phil@netroedge.com>
23946 +                       Stephen Rousset <stephen.rousset@rocketlogix.com>
23947 +                       Dan Eaton <dan.eaton@rocketlogix.com>
23948 +
23949 +    This program is free software; you can redistribute it and/or modify
23950 +    it under the terms of the GNU General Public License as published by
23951 +    the Free Software Foundation; either version 2 of the License, or 
23952 +    (at your option) any later version.
23953 +
23954 +    This program is distributed in the hope that it will be useful,
23955 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
23956 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23957 +    GNU General Public License for more details.
23958 +
23959 +    You should have received a copy of the GNU General Public License
23960 +    along with this program; if not, write to the Free Software
23961 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23962 +*/
23963 +
23964 +
23965 +#include <linux/module.h>
23966 +#include <linux/slab.h>
23967 +#include <linux/i2c.h>
23968 +#include <linux/i2c-proc.h>
23969 +#include <linux/init.h>
23970 +#define LM_DATE "20041007"
23971 +#define LM_VERSION "2.8.8"
23972 +#include <linux/sensors_vid.h>
23973 +
23974 +/* Chip configuration settings.  These should be set to reflect the
23975 +HARDWARE configuration of your chip.  By default (read: when all of
23976 +these are left commented out), this driver assumes that the
23977 +configuration is the same as National's defaults for the Channel Mode
23978 +register.
23979 +
23980 +Set to '1' the appropriate defines, as nessesary:
23981 +
23982 + - External temp sensors 2 (possible second CPU temp)
23983 +   This will disable the 2.5V and Vccp2 readings.
23984 +   Ironically, National decided that you can read the
23985 +   temperature of a second CPU or it's core voltage,
23986 +   but not both!  Comment out if FAULT is reported.  */
23987 +
23988 +/* #define LM87_EXT2 1 */
23989 +
23990 +/* Aux analog input. When enabled, the Fan 1 reading 
23991 +   will be disabled */
23992 +
23993 +/* #define LM87_AIN1 1 */
23994 +
23995 +/* Aux analog input 2. When enabled, the Fan 2 reading 
23996 +   will be disabled */
23997 +
23998 +/* #define LM87_AIN2 1 */
23999 +
24000 +/* Internal Vcc is 5V instead of 3.3V */
24001 +
24002 +/* #define LM87_5V_VCC 1 */
24003 +
24004 +/* That's the end of the hardware config defines.  I would have made
24005 +   them insmod params, but it would be too much work. ;') */
24006 +
24007 +
24008 +
24009 +/* Addresses to scan */
24010 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
24011 +static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, SENSORS_I2C_END };
24012 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
24013 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
24014 +
24015 +/* Insmod parameters */
24016 +SENSORS_INSMOD_1(lm87);
24017 +
24018 +/* The following is the calculation for the register offset
24019 + * for the monitored items minimum and maximum locations.
24020 + */
24021 +#define LM87_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
24022 +#define LM87_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
24023 +#define LM87_REG_IN(nr) (0x20 + (nr))
24024 +
24025 +/* Initial limits */
24026 +
24027 +/*
24028 + * LM87 register definition
24029 + * 
24030 + */
24031 +
24032 +      /* The LM87 registers */
24033 +#define LM87_INT_TEMP_HI_LIMIT_LOCKABLE  0x13
24034 +#define LM87_EXT_TEMP_HI_LIMIT_LOCKABLE  0x14
24035 +#define LM87_REG_TEST                    0x15
24036 +#define LM87_REG_CHANNEL_MODE            0x16
24037 +#define LM87_REG_INT_TEMP_HI_LIMIT       0x17
24038 +#define LM87_REG_EXT_TEMP_HI_LIMIT       0x18
24039 +#define LM87_REG_ANALOG_OUT              0x19
24040 +
24041 +      /* These are all read-only */
24042 +#define LM87_REG_2_5V_EXT_TEMP_2         0x20
24043 +#define LM87_REG_VCCP1                   0x21
24044 +#define LM87_REG_3_3V                    0x22  
24045 +#define LM87_REG_5V                      0x23
24046 +#define LM87_REG_12V                     0x24
24047 +#define LM87_REG_VCCP2                   0x25
24048 +#define LM87_REG_EXT_TEMP_1              0x26
24049 +#define LM87_REG_INT_TEMP                0x27  /* LM87 temp. */
24050 +#define LM87_REG_FAN1_AIN1               0x28
24051 +#define LM87_REG_FAN2_AIN2               0x29
24052 +
24053 +/* These are read/write */
24054 +#define LM87_REG_AIN1_LOW                0x1A
24055 +#define LM87_REG_AIN2_LOW                0x1B
24056 +#define LM87_REG_2_5V_EXT_TEMP_2_HIGH    0x2B  
24057 +#define LM87_REG_2_5V_EXT_TEMP_2_LOW     0x2C  
24058 +#define LM87_REG_VCCP1_HIGH              0x2D  
24059 +#define LM87_REG_VCCP1_LOW               0x2E  
24060 +#define LM87_REG_3_3V_HIGH               0x2F
24061 +#define LM87_REG_3_3V_LOW                0x30
24062 +#define LM87_REG_5V_HIGH                 0x31
24063 +#define LM87_REG_5V_LOW                  0x32
24064 +#define LM87_REG_12V_HIGH                0x33
24065 +#define LM87_REG_12V_LOW                 0x34
24066 +#define LM87_REG_VCCP2_HIGH              0x35
24067 +#define LM87_REG_VCCP2_LOW               0x36
24068 +#define LM87_REG_EXT_TEMP_1_HIGH         0x37    
24069 +#define LM87_REG_EXT_TEMP_1_LOW          0x38  
24070 +#define LM87_REG_INT_TEMP_HIGH           0x39  
24071 +#define LM87_REG_INT_TEMP_LOW            0x3A  
24072 +#define LM87_REG_FAN1_AIN1_LIMIT         0x3B
24073 +#define LM87_REG_FAN2_AIN2_LIMIT         0x3C
24074 +#define LM87_REG_COMPANY_ID              0x3E 
24075 +#define LM87_REG_DIE_REV                 0x3F
24076 +
24077 +#define LM87_REG_CONFIG                  0x40
24078 +#define LM87_REG_INT1_STAT               0x41
24079 +#define LM87_REG_INT2_STAT               0x42
24080 +#define LM87_REG_INT1_MASK               0x43
24081 +#define LM87_REG_INT2_MASK               0x44
24082 +#define LM87_REG_CHASSIS_CLEAR           0x46
24083 +#define LM87_REG_VID_FAN_DIV             0x47
24084 +#define LM87_REG_VID4                    0x49
24085 +#define LM87_REG_CONFIG_2                0x4A
24086 +#define LM87_REG_INTRPT_STATUS_1_MIRROR  0x4C
24087 +#define LM87_REG_INTRPT_STATUS_2_MIRROR  0x4D
24088 +#define LM87_REG_SMBALERT_NUM_ENABLE     0x80
24089 +
24090 +
24091 +
24092 +/* Conversions. Rounding and limit checking is only done on the TO_REG
24093 +   variants. Note that you should be a bit careful with which arguments
24094 +   these macros are called: arguments may be evaluated more than once.
24095 +   Fixing this is just not worth it. */
24096 +
24097 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT(((val) & 0xff),0,255))
24098 +#define IN_FROM_REG(val,nr) (val)
24099 +
24100 +static inline u8 FAN_TO_REG(long rpm, int div)
24101 +{
24102 +       if (rpm == 0)
24103 +               return 255;
24104 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
24105 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
24106 +                            254);
24107 +}
24108 +
24109 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
24110 +                               (val)==255?0:1350000/((div)*(val)))
24111 +
24112 +#define TEMP_FROM_REG(temp)  (temp * 10)
24113 +
24114 +#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
24115 +
24116 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
24117 +                                                      ((val)+5)/10),0,255)
24118 +#if 0
24119 +#define TEMP_FROM_REG(temp) \
24120 +   ((temp)<256?((((temp)&0x1fe) >> 1) * 10)      + ((temp) & 1) * 5:  \
24121 +               ((((temp)&0x1fe) >> 1) -255) * 10 - ((temp) & 1) * 5)  \
24122 +
24123 +#define TEMP_LIMIT_FROM_REG(val) (val)
24124 +
24125 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val),0,255)
24126 +#endif
24127 +
24128 +
24129 +#define ALARMS_FROM_REG(val) (val)
24130 +
24131 +#define DIV_FROM_REG(val) (1 << (val))
24132 +#define DIV_TO_REG(val) ((val)==1?0:((val)==8?3:((val)==4?2:1)))
24133 +
24134 +/* For each registered LM87, we need to keep some data in memory. That
24135 +   data is pointed to by LM87_list[NR]->data. The structure itself is
24136 +   dynamically allocated, at the same time when a new LM87 client is
24137 +   allocated. */
24138 +struct lm87_data {
24139 +       struct i2c_client client;
24140 +       int sysctl_id;
24141 +       enum chips type;
24142 +
24143 +       struct semaphore update_lock;
24144 +       char valid;             /* !=0 if following fields are valid */
24145 +       unsigned long last_updated;     /* In jiffies */
24146 +
24147 +       u8  in[6];              /* Scaled Register value */
24148 +       u8  in_max[6];          /* Scaled Register value */
24149 +       u8  in_min[6];          /* Scaled Register value */
24150 +       u8  ain1;               /* Register value */
24151 +       u8  ain1_min;           /* Register value */
24152 +       u8  ain1_max;           /* Register value */
24153 +       u8  ain2;               /* Register value */
24154 +       u8  ain2_min;           /* Register value */
24155 +       u8  ain2_max;           /* Register value */
24156 +       u8  fan;                /* Register value */
24157 +       u8  fan_min;            /* Register value */
24158 +       u8  fan_div;            /* Register encoding, shifted right */
24159 +       u8  fan2;               /* Register value */
24160 +       u8  fan2_min;           /* Register value */
24161 +       u8  fan2_div;           /* Register encoding, shifted right */
24162 +       int ext2_temp;          /* Temp, shifted right */
24163 +       int ext_temp;           /* Temp, shifted right */
24164 +       int int_temp;           /* Temp, shifted right */
24165 +       u8  ext_temp_max;       /* Register value */
24166 +       u8  ext_temp_min;       /* Register value */
24167 +       u8  ext2_temp_max;      /* Register value */
24168 +       u8  ext2_temp_min;      /* Register value */
24169 +       u8  int_temp_max;       /* Register value */
24170 +       u8  int_temp_min;       /* Register value */
24171 +       u16 alarms;             /* Register encoding, combined */
24172 +       u8  analog_out;         /* Register value */
24173 +       u8  vid;                /* Register value combined */
24174 +       u8  vrm;                /* VRM version * 10 */
24175 +};
24176 +
24177 +static int lm87_attach_adapter(struct i2c_adapter *adapter);
24178 +static int lm87_detect(struct i2c_adapter *adapter, int address,
24179 +                         unsigned short flags, int kind);
24180 +static int lm87_detach_client(struct i2c_client *client);
24181 +
24182 +static int lm87_read_value(struct i2c_client *client, u8 register);
24183 +static int lm87_write_value(struct i2c_client *client, u8 register,
24184 +                              u8 value);
24185 +static void lm87_update_client(struct i2c_client *client);
24186 +static void lm87_init_client(struct i2c_client *client);
24187 +
24188 +
24189 +static void lm87_in(struct i2c_client *client, int operation,
24190 +                      int ctl_name, int *nrels_mag, long *results);
24191 +#if defined (LM87_AIN1) || defined (LM87_AIN2)
24192 +static void lm87_ain(struct i2c_client *client, int operation,
24193 +                      int ctl_name, int *nrels_mag, long *results);
24194 +#endif
24195 +static void lm87_fan(struct i2c_client *client, int operation,
24196 +                       int ctl_name, int *nrels_mag, long *results);
24197 +static void lm87_temp(struct i2c_client *client, int operation,
24198 +                        int ctl_name, int *nrels_mag, long *results);
24199 +static void lm87_alarms(struct i2c_client *client, int operation,
24200 +                          int ctl_name, int *nrels_mag, long *results);
24201 +static void lm87_fan_div(struct i2c_client *client, int operation,
24202 +                           int ctl_name, int *nrels_mag, long *results);
24203 +static void lm87_analog_out(struct i2c_client *client, int operation,
24204 +                              int ctl_name, int *nrels_mag,
24205 +                              long *results);
24206 +static void lm87_vid(struct i2c_client *client, int operation,
24207 +                       int ctl_name, int *nrels_mag, long *results);
24208 +static void lm87_vrm(struct i2c_client *client, int operation,
24209 +                       int ctl_name, int *nrels_mag, long *results);
24210 +
24211 +static int lm87_id = 0;
24212 +
24213 +static struct i2c_driver LM87_driver = {
24214 +       .owner          = THIS_MODULE,
24215 +       .name           = "LM87 sensor driver",
24216 +       .id             = I2C_DRIVERID_LM87,
24217 +       .flags          = I2C_DF_NOTIFY,
24218 +       .attach_adapter = lm87_attach_adapter,
24219 +       .detach_client  = lm87_detach_client,
24220 +};
24221 +
24222 +/* -- SENSORS SYSCTL START -- */
24223 +#define LM87_SYSCTL_IN0        1000 /* Volts * 100 */
24224 +#define LM87_SYSCTL_IN1        1001
24225 +#define LM87_SYSCTL_IN2        1002
24226 +#define LM87_SYSCTL_IN3        1003
24227 +#define LM87_SYSCTL_IN4        1004
24228 +#define LM87_SYSCTL_IN5        1005
24229 +#define LM87_SYSCTL_AIN1       1006
24230 +#define LM87_SYSCTL_AIN2       1007
24231 +#define LM87_SYSCTL_FAN1       1102
24232 +#define LM87_SYSCTL_FAN2       1103
24233 +#define LM87_SYSCTL_TEMP1  1250 /* Degrees Celcius * 100 */
24234 +#define LM87_SYSCTL_TEMP2   1251 /* Degrees Celcius * 100 */
24235 +#define LM87_SYSCTL_TEMP3   1252 /* Degrees Celcius * 100 */
24236 +#define LM87_SYSCTL_FAN_DIV    2000 /* 1, 2, 4 or 8 */
24237 +#define LM87_SYSCTL_ALARMS     2001 /* bitvector */
24238 +#define LM87_SYSCTL_ANALOG_OUT 2002
24239 +#define LM87_SYSCTL_VID        2003
24240 +#define LM87_SYSCTL_VRM        2004
24241 +
24242 +#define LM87_ALARM_IN0          0x0001
24243 +#define LM87_ALARM_IN1          0x0002
24244 +#define LM87_ALARM_IN2          0x0004
24245 +#define LM87_ALARM_IN3          0x0008
24246 +#define LM87_ALARM_TEMP1        0x0010
24247 +#define LM87_ALARM_TEMP2        0x0020
24248 +#define LM87_ALARM_TEMP3        0x0020 /* same?? */
24249 +#define LM87_ALARM_FAN1         0x0040
24250 +#define LM87_ALARM_FAN2         0x0080
24251 +#define LM87_ALARM_IN4          0x0100
24252 +#define LM87_ALARM_IN5          0x0200
24253 +#define LM87_ALARM_RESERVED1    0x0400
24254 +#define LM87_ALARM_RESERVED2    0x0800
24255 +#define LM87_ALARM_CHAS         0x1000
24256 +#define LM87_ALARM_THERM_SIG    0x2000
24257 +#define LM87_ALARM_TEMP2_FAULT  0x4000
24258 +#define LM87_ALARM_TEMP3_FAULT 0x08000
24259 +
24260 +/* -- SENSORS SYSCTL END -- */
24261 +
24262 +/* The /proc/sys entries */
24263 +/* These files are created for each detected LM87. This is just a template;
24264 +   though at first sight, you might think we could use a statically
24265 +   allocated list, we need some way to get back to the parent - which
24266 +   is done through one of the 'extra' fields which are initialized 
24267 +   when a new copy is allocated. */
24268 +
24269 +static ctl_table LM87_dir_table_template[] = {
24270 +#ifdef LM87_AIN1
24271 +       {LM87_SYSCTL_AIN1, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
24272 +         &i2c_sysctl_real, NULL, &lm87_ain},
24273 +#endif
24274 +#ifdef LM87_AIN2
24275 +       {LM87_SYSCTL_AIN2, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
24276 +         &i2c_sysctl_real, NULL, &lm87_ain},
24277 +#endif
24278 +#ifndef LM87_EXT2
24279 +       {LM87_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
24280 +         &i2c_sysctl_real, NULL, &lm87_in},
24281 +       {LM87_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
24282 +         &i2c_sysctl_real, NULL, &lm87_in},
24283 +#endif
24284 +       {LM87_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
24285 +         &i2c_sysctl_real, NULL, &lm87_in},
24286 +       {LM87_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
24287 +         &i2c_sysctl_real, NULL, &lm87_in},
24288 +       {LM87_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
24289 +         &i2c_sysctl_real, NULL, &lm87_in},
24290 +       {LM87_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
24291 +         &i2c_sysctl_real, NULL, &lm87_in},
24292 +#ifndef LM87_AIN1
24293 +       {LM87_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
24294 +         &i2c_sysctl_real, NULL, &lm87_fan},
24295 +       {LM87_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
24296 +         &i2c_sysctl_real, NULL, &lm87_fan_div},
24297 +#define LM87_FANDIV_FLAG
24298 +#endif
24299 +#ifndef LM87_AIN2
24300 +       {LM87_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
24301 +         &i2c_sysctl_real, NULL, &lm87_fan},
24302 +#ifndef LM87_FANDIV_FLAG
24303 +       {LM87_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
24304 +         &i2c_sysctl_real, NULL, &lm87_fan_div},
24305 +#endif /* LM87_FANDIV_FLAG */
24306 +#endif /* LM87_AIN2 */
24307 +#ifdef LM87_EXT2
24308 +        {LM87_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
24309 +         &i2c_sysctl_real, NULL, &lm87_temp},
24310 +#endif
24311 +       {LM87_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
24312 +         &i2c_sysctl_real, NULL, &lm87_temp},
24313 +       {LM87_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
24314 +         &i2c_sysctl_real, NULL, &lm87_temp},
24315 +       {LM87_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
24316 +         &i2c_sysctl_real, NULL, &lm87_alarms},
24317 +       {LM87_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL, &i2c_proc_real,
24318 +         &i2c_sysctl_real, NULL, &lm87_analog_out},
24319 +       {LM87_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
24320 +         &i2c_sysctl_real, NULL, &lm87_vid},
24321 +       {LM87_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
24322 +        &i2c_sysctl_real, NULL, &lm87_vrm},
24323 +       {0}
24324 +};
24325 +
24326 +static int lm87_attach_adapter(struct i2c_adapter *adapter)
24327 +{
24328 +       int error;
24329 +       struct i2c_client_address_data  lm87_client_data;
24330 +
24331 +       lm87_client_data.normal_i2c       = addr_data.normal_i2c;
24332 +       lm87_client_data.normal_i2c_range = addr_data.normal_i2c_range;
24333 +       lm87_client_data.probe            = addr_data.probe;
24334 +       lm87_client_data.probe_range      = addr_data.probe_range;
24335 +       lm87_client_data.ignore           = addr_data.ignore;
24336 +       lm87_client_data.ignore_range     = addr_data.ignore_range;
24337 +       lm87_client_data.force            = addr_data.forces->force;
24338 +
24339 +       error = i2c_probe(adapter, &lm87_client_data, lm87_detect);
24340 +       i2c_detect(adapter, &addr_data, lm87_detect);
24341 +
24342 +        return error;
24343 +}
24344 +
24345 +static int lm87_detect(struct i2c_adapter *adapter, int address,
24346 +                         unsigned short flags, int kind)
24347 +{
24348 +       int i;
24349 +       struct i2c_client *new_client;
24350 +       struct lm87_data *data;
24351 +       int err = 0;
24352 +       const char *type_name = "";
24353 +       const char *client_name = "";
24354 +
24355 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
24356 +               goto ERROR0;
24357 +
24358 +       /* OK. For now, we presume we have a valid client. We now create the
24359 +          client structure, even though we cannot fill it completely yet.
24360 +          But it allows us to access LM87_{read,write}_value. */
24361 +
24362 +       if (!(data = kmalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
24363 +               err = -ENOMEM;
24364 +               goto ERROR0;
24365 +       }
24366 +
24367 +       new_client = &data->client;
24368 +       new_client->addr = address;
24369 +       new_client->data = data;
24370 +       new_client->adapter = adapter;
24371 +       new_client->driver = &LM87_driver;
24372 +       new_client->flags = 0;
24373 +
24374 +       /* Now, we do the remaining detection. */
24375 +
24376 +       if (kind < 0) {
24377 +               if (((lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)
24378 +                    != 0x00) ||
24379 +                   (lm87_read_value(new_client, LM87_REG_COMPANY_ID) != 0x02))
24380 +              goto ERROR1;
24381 +       }
24382 +
24383 +       /* Fill in the remaining client fields and put into the global list */
24384 +        type_name = "lm87";
24385 +        client_name = "LM87 chip";
24386 +       strcpy(new_client->name, client_name);
24387 +       data->type = kind;
24388 +
24389 +       new_client->id = lm87_id++;
24390 +       data->valid = 0;
24391 +       init_MUTEX(&data->update_lock);
24392 +
24393 +       /* Tell the I2C layer a new client has arrived */
24394 +       if ((err = i2c_attach_client(new_client)))
24395 +               goto ERROR3;
24396 +
24397 +       /* Register a new directory entry with module sensors */
24398 +       if ((i = i2c_register_entry(new_client,
24399 +                                       type_name,
24400 +                                       LM87_dir_table_template)) < 0) {
24401 +               err = i;
24402 +               goto ERROR4;
24403 +       }
24404 +       data->sysctl_id = i;
24405 +
24406 +       /* Initialize the LM87 chip */
24407 +       lm87_init_client(new_client);
24408 +       return 0;
24409 +
24410 +/* OK, this is not exactly good programming practice, usually. But it is
24411 +   very code-efficient in this case. */
24412 +
24413 +      ERROR4:
24414 +       i2c_detach_client(new_client);
24415 +      ERROR3:
24416 +      ERROR1:
24417 +       kfree(data);
24418 +      ERROR0:
24419 +       return err;
24420 +}
24421 +
24422 +static int lm87_detach_client(struct i2c_client *client)
24423 +{
24424 +       int err;
24425 +
24426 +       i2c_deregister_entry(((struct lm87_data *) (client->data))->
24427 +                                sysctl_id);
24428 +
24429 +       if ((err = i2c_detach_client(client))) {
24430 +               printk
24431 +                   ("lm87.o: Client deregistration failed, client not detached.\n");
24432 +               return err;
24433 +       }
24434 +
24435 +       kfree(client->data);
24436 +
24437 +       return 0;
24438 +}
24439 +
24440 +static int lm87_read_value(struct i2c_client *client, u8 reg)
24441 +{
24442 +       return 0xFF & i2c_smbus_read_byte_data(client, reg);
24443 +}
24444 +
24445 +static int lm87_write_value(struct i2c_client *client, u8 reg, u8 value)
24446 +{
24447 +       return i2c_smbus_write_byte_data(client, reg, value);
24448 +}
24449 +
24450 +/* Called when we have found a new LM87. It should set limits, etc. */
24451 +static void lm87_init_client(struct i2c_client *client)
24452 +{
24453 +       struct lm87_data *data = client->data;
24454 +
24455 +       /* Reset all except Watchdog values and last conversion values
24456 +          This sets fan-divs to 2, among others. This makes most other
24457 +          initializations unnecessary */
24458 +       lm87_write_value(client, LM87_REG_CONFIG, 0x80);
24459 +
24460 +        /* Setup Channel Mode register for configuration of monitoring 
24461 +        * Default is 00000000b
24462 +        *      bit 0 - Configures Fan 1/AIN 1 input (1 = AIN)
24463 +        *      bit 1 - Configures Fan 2/AIN 2 input (1 = AIN)
24464 +        *      bit 2 - Configures 2.5V&Vccp2/D2 input (1 = 2nd Therm.) 
24465 +        *      bit 3 - Configures Vcc for 5V/3.3V reading (0 = 3.3V)
24466 +        *      bit 4 - Configures IRQ0 Enable if = 1
24467 +        *      bit 5 - Configures IRQ1 Enable if = 1
24468 +        *      bit 6 - Configures IRQ2 Enable if = 1
24469 +        *      bit 7 - Configures VID/IRQ input as interrupts if = 1
24470 +        */
24471 +
24472 +/* I know, not clean, but it works. :'p */
24473 +       lm87_write_value(client, LM87_REG_CHANNEL_MODE,
24474 +#ifdef LM87_AIN1
24475 + 0x01
24476 +#else
24477 +0
24478 +#endif
24479 + | 
24480 +#ifdef LM87_AIN2
24481 + 0x02
24482 +#else
24483 +0
24484 +#endif
24485 + |
24486 +#ifdef LM87_EXT2
24487 + 0x04
24488 +#else
24489 +0
24490 +#endif
24491 + | 
24492 +#ifdef LM87_5V_VCC
24493 +0x08
24494 +#else   
24495 +0
24496 +#endif
24497 +       );
24498 +
24499 +       data->vrm = DEFAULT_VRM;
24500 +
24501 +       /* Start monitoring */
24502 +       lm87_write_value(client, LM87_REG_CONFIG, 0x01);
24503 +}
24504 +
24505 +static void lm87_update_client(struct i2c_client *client)
24506 +{
24507 +       struct lm87_data *data = client->data;
24508 +       int i;
24509 +
24510 +       down(&data->update_lock);
24511 +
24512 +       if ((jiffies - data->last_updated > HZ) ||  /* 1 sec cache */
24513 +            (jiffies < data->last_updated)      || 
24514 +             !data->valid) {
24515 +               for (i = 0; i <= 5; i++) {  
24516 +                data->in[i] = 
24517 +                   lm87_read_value(client,LM87_REG_IN(i));
24518 +                data->in_min[i] = 
24519 +                   lm87_read_value(client,LM87_REG_IN_MIN(i));
24520 +                data->in_max[i] = 
24521 +                   lm87_read_value(client,LM87_REG_IN_MAX(i));
24522 +               }
24523 +                data->ain1 = 
24524 +                   lm87_read_value(client,LM87_REG_FAN1_AIN1);
24525 +                data->ain1_min =
24526 +                   lm87_read_value(client,LM87_REG_AIN1_LOW);
24527 +                data->ain1_max =
24528 +                   lm87_read_value(client,LM87_REG_FAN1_AIN1_LIMIT);
24529 +                data->ain2 = 
24530 +                   lm87_read_value(client,LM87_REG_FAN2_AIN2);
24531 +                data->ain2_min =
24532 +                   lm87_read_value(client,LM87_REG_AIN2_LOW);
24533 +                data->ain2_max =
24534 +                   lm87_read_value(client,LM87_REG_FAN2_AIN2_LIMIT);
24535 +
24536 +               data->fan =
24537 +                   lm87_read_value(client, LM87_REG_FAN1_AIN1);
24538 +               data->fan_min =
24539 +                   lm87_read_value(client, LM87_REG_FAN1_AIN1_LIMIT);
24540 +               data->fan2 =
24541 +                   lm87_read_value(client, LM87_REG_FAN2_AIN2);
24542 +               data->fan2_min =
24543 +                   lm87_read_value(client, LM87_REG_FAN2_AIN2_LIMIT);
24544 +
24545 +               data->ext2_temp =
24546 +                   lm87_read_value(client, LM87_REG_2_5V_EXT_TEMP_2);
24547 +               data->ext_temp =
24548 +                   lm87_read_value(client, LM87_REG_EXT_TEMP_1);
24549 +               data->int_temp =
24550 +                   lm87_read_value(client, LM87_REG_INT_TEMP);
24551 +
24552 +               data->ext2_temp_max =
24553 +                   lm87_read_value(client, LM87_REG_2_5V_EXT_TEMP_2_HIGH);
24554 +               data->ext2_temp_min =
24555 +                   lm87_read_value(client, LM87_REG_2_5V_EXT_TEMP_2_LOW);
24556 +
24557 +               data->ext_temp_max =
24558 +                   lm87_read_value(client, LM87_REG_EXT_TEMP_1_HIGH);
24559 +               data->ext_temp_min =
24560 +                   lm87_read_value(client, LM87_REG_EXT_TEMP_1_LOW);
24561 +
24562 +               data->int_temp_max =
24563 +                   lm87_read_value(client, LM87_REG_INT_TEMP_HIGH);
24564 +               data->int_temp_min =
24565 +                   lm87_read_value(client, LM87_REG_INT_TEMP_LOW);
24566 +
24567 +               i = lm87_read_value(client, LM87_REG_VID_FAN_DIV);
24568 +               data->fan_div = (i >> 4) & 0x03;
24569 +               data->fan2_div = (i >> 6) & 0x03;
24570 +               data->vid = i & 0x0f;
24571 +               data->vid |=
24572 +                   (lm87_read_value(client, LM87_REG_VID4) & 0x01)
24573 +                   << 4;
24574 +               data->alarms =
24575 +                   lm87_read_value(client, LM87_REG_INT1_STAT) +
24576 +                   (lm87_read_value(client, LM87_REG_INT2_STAT) << 8);
24577 +               data->analog_out =
24578 +                   lm87_read_value(client, LM87_REG_ANALOG_OUT);
24579 +               data->last_updated = jiffies;
24580 +               data->valid = 1;
24581 +       }
24582 +       up(&data->update_lock);
24583 +}
24584 +
24585 +
24586 +/* The next few functions are the call-back functions of the /proc/sys and
24587 +   sysctl files. Which function is used is defined in the ctl_table in
24588 +   the extra1 field.
24589 +   Each function must return the magnitude (power of 10 to divide the date
24590 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
24591 +   put a maximum of *nrels elements in results reflecting the data of this
24592 +   file, and set *nrels to the number it actually put in it, if operation==
24593 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
24594 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
24595 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
24596 +   large enough (by checking the incoming value of *nrels). This is not very
24597 +   good practice, but as long as you put less than about 5 values in results,
24598 +   you can assume it is large enough. */
24599 +void lm87_in(struct i2c_client *client, int operation, int ctl_name,
24600 +               int *nrels_mag, long *results)
24601 +{
24602 +       long scales[6] = { 250, 270, 
24603 +#ifdef LM87_5V_VCC
24604 +500,
24605 +#else
24606 +330,
24607 +#endif
24608 +               500, 1200, 270 };
24609 +
24610 +       struct lm87_data *data = client->data;
24611 +       int nr = ctl_name - LM87_SYSCTL_IN0;
24612 +
24613 +       if (operation == SENSORS_PROC_REAL_INFO)
24614 +               *nrels_mag = 2;
24615 +       else if (operation == SENSORS_PROC_REAL_READ) {
24616 +               lm87_update_client(client);
24617 +               results[0] =
24618 +                   ((long)data->in_min[nr] * scales[nr]) / 192;
24619 +               results[1] =
24620 +                   ((long)data->in_max[nr] * scales[nr]) / 192;
24621 +               results[2] =
24622 +                   ((long)data->in[nr] * scales[nr]) / 192;
24623 +               *nrels_mag = 3;
24624 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
24625 +               if (*nrels_mag >= 1) {
24626 +                       data->in_min[nr] =
24627 +                           (results[0] * 192) / scales[nr];
24628 +                       lm87_write_value(client, LM87_REG_IN_MIN(nr),
24629 +                                           data->in_min[nr]);
24630 +               }
24631 +               if (*nrels_mag >= 2) {
24632 +                       data->in_max[nr] =
24633 +                           (results[1] * 192) / scales[nr];
24634 +                       lm87_write_value(client, LM87_REG_IN_MAX(nr),
24635 +                                           data->in_max[nr]);
24636 +               }
24637 +       }
24638 +}
24639 +
24640 +#if defined (LM87_AIN1) || defined (LM87_AIN2)
24641 +void lm87_ain(struct i2c_client *client, int operation, int ctl_name,
24642 +               int *nrels_mag, long *results)
24643 +{
24644 +       struct lm87_data *data = client->data;
24645 +
24646 +       if (operation == SENSORS_PROC_REAL_INFO)
24647 +               *nrels_mag = 0;
24648 +       else if (operation == SENSORS_PROC_REAL_READ) {
24649 +               lm87_update_client(client);
24650 +               if (ctl_name == LM87_SYSCTL_AIN1) {
24651 +                results[0] = data->ain1_min;
24652 +                results[1] = data->ain1_max;
24653 +                results[2] = data->ain1;
24654 +               } else {
24655 +                results[0] = data->ain2_min;
24656 +                results[1] = data->ain2_max;
24657 +                results[2] = data->ain2;
24658 +               }
24659 +               *nrels_mag = 3;
24660 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
24661 +               if (*nrels_mag >= 1) {
24662 +                if (ctl_name == LM87_SYSCTL_AIN1) {
24663 +                       data->ain1_min = results[0];
24664 +                       lm87_write_value(client, LM87_REG_AIN1_LOW,
24665 +                                           data->ain1_min);
24666 +                } else {
24667 +                       data->ain2_min = results[0];
24668 +                       lm87_write_value(client, LM87_REG_AIN2_LOW,
24669 +                                           data->ain2_min);
24670 +                }
24671 +               }
24672 +               if (*nrels_mag >= 2) {
24673 +                if (ctl_name == LM87_SYSCTL_AIN1) {
24674 +                       data->ain1_max = results[1];
24675 +                       lm87_write_value(client, LM87_REG_FAN1_AIN1_LIMIT,
24676 +                                           data->ain1_max);
24677 +                } else {
24678 +                       data->ain2_max = results[1];
24679 +                       lm87_write_value(client, LM87_REG_FAN2_AIN2_LIMIT,
24680 +                                           data->ain2_max);
24681 +                }
24682 +               }
24683 +       }
24684 +}
24685 +#endif
24686 +
24687 +void lm87_fan(struct i2c_client *client, int operation, int ctl_name,
24688 +                int *nrels_mag, long *results)
24689 +{
24690 +       struct lm87_data *data = client->data;
24691 +
24692 +       if (operation == SENSORS_PROC_REAL_INFO)
24693 +               *nrels_mag = 0;
24694 +       else if (operation == SENSORS_PROC_REAL_READ) {
24695 +               lm87_update_client(client);
24696 +               if (ctl_name == LM87_SYSCTL_FAN1) {
24697 +                results[0] = FAN_FROM_REG(data->fan_min,
24698 +                                         DIV_FROM_REG(data->fan_div));
24699 +                results[1] = FAN_FROM_REG(data->fan, 
24700 +                                        DIV_FROM_REG(data->fan_div));
24701 +               } else {
24702 +                results[0] = FAN_FROM_REG(data->fan2_min,
24703 +                                         DIV_FROM_REG(data->fan2_div));
24704 +                results[1] = FAN_FROM_REG(data->fan2, 
24705 +                                        DIV_FROM_REG(data->fan2_div));
24706 +               }
24707 +               *nrels_mag = 2;
24708 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
24709 +               if (*nrels_mag >= 0) {
24710 +                       if (ctl_name == LM87_SYSCTL_FAN1) {
24711 +                        data->fan_min = FAN_TO_REG(results[0],
24712 +                                                  DIV_FROM_REG
24713 +                                                  (data->fan_div));
24714 +                        lm87_write_value(client, LM87_REG_FAN1_AIN1_LIMIT,
24715 +                                           data->fan_min);
24716 +                       } else {
24717 +                        data->fan2_min = FAN_TO_REG(results[0],
24718 +                                                  DIV_FROM_REG
24719 +                                                  (data->fan2_div));
24720 +                        lm87_write_value(client, LM87_REG_FAN2_AIN2_LIMIT,
24721 +                                           data->fan2_min);
24722 +                       }
24723 +               }
24724 +       }
24725 +}
24726 +
24727 +
24728 +void lm87_temp(struct i2c_client *client, int operation, int ctl_name,
24729 +                 int *nrels_mag, long *results)
24730 +{
24731 +       struct lm87_data *data = client->data;
24732 +
24733 +       if (operation == SENSORS_PROC_REAL_INFO)
24734 +               *nrels_mag = 1;
24735 +       else if (operation == SENSORS_PROC_REAL_READ) 
24736 +       {
24737 +          lm87_update_client(client);
24738 +
24739 +          /* find out which temp. is being requested */
24740 +          if (ctl_name == LM87_SYSCTL_TEMP3) 
24741 +          {
24742 +               results[0] = TEMP_LIMIT_FROM_REG(data->ext2_temp_max);
24743 +               results[1] = TEMP_LIMIT_FROM_REG(data->ext2_temp_min);
24744 +               results[2] = TEMP_FROM_REG(data->ext2_temp);
24745 +          }
24746 +          else if(ctl_name == LM87_SYSCTL_TEMP2)
24747 +          {
24748 +               results[0] = TEMP_LIMIT_FROM_REG(data->ext_temp_max);
24749 +               results[1] = TEMP_LIMIT_FROM_REG(data->ext_temp_min);
24750 +               results[2] = TEMP_FROM_REG(data->ext_temp);
24751 +          }
24752 +          else if(ctl_name == LM87_SYSCTL_TEMP1)
24753 +          {
24754 +               results[0] = TEMP_LIMIT_FROM_REG(data->int_temp_max);
24755 +               results[1] = TEMP_LIMIT_FROM_REG(data->int_temp_min);
24756 +               results[2] = TEMP_FROM_REG(data->int_temp);
24757 +          }
24758 +          *nrels_mag = 3;
24759 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
24760 +               if (*nrels_mag >= 1) {
24761 +                  if (ctl_name == LM87_SYSCTL_TEMP3) {
24762 +                       data->ext2_temp_max = TEMP_LIMIT_TO_REG(results[0]);
24763 +                       lm87_write_value(client, LM87_REG_2_5V_EXT_TEMP_2_HIGH,
24764 +                                           data->ext2_temp_max);
24765 +                  }
24766 +                  if (ctl_name == LM87_SYSCTL_TEMP2) {
24767 +                       data->ext_temp_max = TEMP_LIMIT_TO_REG(results[0]);
24768 +                       lm87_write_value(client, LM87_REG_EXT_TEMP_1_HIGH,
24769 +                                           data->ext_temp_max);
24770 +                  }
24771 +                  if (ctl_name == LM87_SYSCTL_TEMP1) {
24772 +                       data->int_temp_max = TEMP_LIMIT_TO_REG(results[0]);
24773 +                       lm87_write_value(client, LM87_REG_INT_TEMP_HIGH,
24774 +                                           data->int_temp_max);
24775 +                  }
24776 +               }
24777 +               if (*nrels_mag >= 2) {
24778 +                  if (ctl_name == LM87_SYSCTL_TEMP3) {
24779 +                       data->ext2_temp_min = TEMP_LIMIT_TO_REG(results[1]);
24780 +                       lm87_write_value(client, LM87_REG_2_5V_EXT_TEMP_2_LOW,
24781 +                                           data->ext2_temp_min);
24782 +                  }
24783 +                  if (ctl_name == LM87_SYSCTL_TEMP2) {
24784 +                       data->ext_temp_min = TEMP_LIMIT_TO_REG(results[1]);
24785 +                       lm87_write_value(client, LM87_REG_EXT_TEMP_1_LOW,
24786 +                                           data->ext_temp_min);
24787 +                  }
24788 +                  if (ctl_name == LM87_SYSCTL_TEMP1) {
24789 +                       data->int_temp_min = TEMP_LIMIT_TO_REG(results[1]);
24790 +                       lm87_write_value(client, LM87_REG_INT_TEMP_LOW,
24791 +                                           data->int_temp_min);
24792 +                  }
24793 +               }
24794 +       }
24795 +}
24796 +
24797 +void lm87_alarms(struct i2c_client *client, int operation, int ctl_name,
24798 +                   int *nrels_mag, long *results)
24799 +{
24800 +       struct lm87_data *data = client->data;
24801 +       if (operation == SENSORS_PROC_REAL_INFO)
24802 +               *nrels_mag = 0;
24803 +       else if (operation == SENSORS_PROC_REAL_READ) {
24804 +               lm87_update_client(client);
24805 +               results[0] = ALARMS_FROM_REG(data->alarms);
24806 +               *nrels_mag = 1;
24807 +       }
24808 +}
24809 +
24810 +void lm87_fan_div(struct i2c_client *client, int operation,
24811 +                    int ctl_name, int *nrels_mag, long *results)
24812 +{
24813 +/* This gets a little hairy depending on the hardware config */
24814 +
24815 +       struct lm87_data *data = client->data;
24816 +       int old;
24817 +
24818 +       if (operation == SENSORS_PROC_REAL_INFO)
24819 +               *nrels_mag = 0;
24820 +       else if (operation == SENSORS_PROC_REAL_READ) {
24821 +               lm87_update_client(client);
24822 +#ifndef LM87_AIN1
24823 +               results[0] = DIV_FROM_REG(data->fan_div);
24824 +# ifndef LM87_AIN2
24825 +               results[1] = DIV_FROM_REG(data->fan2_div);
24826 +               *nrels_mag = 2;
24827 +# else
24828 +               *nrels_mag = 1;
24829 +# endif
24830 +#else /* Must be referring to fan 2 */
24831 +               results[0] = DIV_FROM_REG(data->fan2_div);
24832 +               *nrels_mag = 1;
24833 +#endif
24834 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
24835 +               old = lm87_read_value(client, LM87_REG_VID_FAN_DIV);
24836 +/* Note: it's OK to change fan2 div even if fan2 isn't enabled */
24837 +#ifndef LM87_AIN1
24838 +               if (*nrels_mag >= 2) {
24839 +                       data->fan2_div = DIV_TO_REG(results[1]);
24840 +                       old = (old & 0x3f) | (data->fan2_div << 6);
24841 +               }
24842 +               if (*nrels_mag >= 1) {
24843 +                       data->fan_div = DIV_TO_REG(results[0]);
24844 +                       old = (old & 0xcf) | (data->fan_div << 4);
24845 +                       lm87_write_value(client, LM87_REG_VID_FAN_DIV, old);
24846 +               }
24847 +#else /* Must be referring to fan 2 */
24848 +               if (*nrels_mag >= 1) {
24849 +                       data->fan2_div = DIV_TO_REG(results[0]);
24850 +                       old = (old & 0xcf) | (data->fan2_div << 6);
24851 +                       lm87_write_value(client, LM87_REG_VID_FAN_DIV, old);
24852 +               }
24853 +#endif
24854 +       }
24855 +}
24856 +
24857 +void lm87_analog_out(struct i2c_client *client, int operation,
24858 +                       int ctl_name, int *nrels_mag, long *results)
24859 +{
24860 +       struct lm87_data *data = client->data;
24861 +
24862 +       if (operation == SENSORS_PROC_REAL_INFO)
24863 +               *nrels_mag = 0;
24864 +       else if (operation == SENSORS_PROC_REAL_READ) {
24865 +               lm87_update_client(client);
24866 +               results[0] = data->analog_out;
24867 +               *nrels_mag = 1;
24868 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
24869 +               if (*nrels_mag >= 1) {
24870 +                       data->analog_out = results[0];
24871 +                       lm87_write_value(client, LM87_REG_ANALOG_OUT,
24872 +                                           data->analog_out);
24873 +               }
24874 +       }
24875 +}
24876 +
24877 +void lm87_vid(struct i2c_client *client, int operation, int ctl_name,
24878 +                int *nrels_mag, long *results)
24879 +{
24880 +       struct lm87_data *data = client->data;
24881 +
24882 +       if (operation == SENSORS_PROC_REAL_INFO)
24883 +               *nrels_mag = 3;
24884 +       else if (operation == SENSORS_PROC_REAL_READ) {
24885 +               lm87_update_client(client);
24886 +               results[0] = vid_from_reg(data->vid, data->vrm);
24887 +               *nrels_mag = 1;
24888 +       }
24889 +}
24890 +
24891 +void lm87_vrm(struct i2c_client *client, int operation, int ctl_name,
24892 +                int *nrels_mag, long *results)
24893 +{
24894 +       struct lm87_data *data = client->data;
24895 +       if (operation == SENSORS_PROC_REAL_INFO)
24896 +               *nrels_mag = 1;
24897 +       else if (operation == SENSORS_PROC_REAL_READ) {
24898 +               results[0] = data->vrm;
24899 +               *nrels_mag = 1;
24900 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
24901 +               if (*nrels_mag >= 1)
24902 +                       data->vrm = results[0];
24903 +       }
24904 +}
24905 +
24906 +static int __init sm_lm87_init(void)
24907 +{
24908 +       printk("lm87.o version %s (%s)\n", LM_VERSION, LM_DATE);
24909 +       return i2c_add_driver(&LM87_driver);
24910 +}
24911 +
24912 +static void __exit sm_lm87_exit(void)
24913 +{
24914 +       i2c_del_driver(&LM87_driver);
24915 +}
24916 +
24917 +
24918 +
24919 +MODULE_LICENSE("GPL");
24920 +
24921 +MODULE_AUTHOR
24922 +    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, "
24923 +     "Mark Studebaker <mdsxyz123@yahoo.com>, and Stephen Rousset <stephen.rousset@rocketlogix.com>");
24924 +
24925 +MODULE_DESCRIPTION("LM87 driver");
24926 +
24927 +module_init(sm_lm87_init);
24928 +module_exit(sm_lm87_exit);
24929 --- linux-old/drivers/sensors/lm90.c    Thu Jan  1 00:00:00 1970
24930 +++ linux/drivers/sensors/lm90.c        Mon Dec 13 20:18:49 2004
24931 @@ -0,0 +1,782 @@
24932 +/*
24933 + * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
24934 + *          monitoring
24935 + * Copyright (C) 2003-2004  Jean Delvare <khali@linux-fr.org>
24936 + *
24937 + * Based on the lm83 driver. The LM90 is a sensor chip made by National
24938 + * Semiconductor. It reports up to two temperatures (its own plus up to
24939 + * one external one) with a 0.125 deg resolution (1 deg for local
24940 + * temperature) and a 3-4 deg accuracy. Complete datasheet can be
24941 + * obtained from National's website at:
24942 + *   http://www.national.com/pf/LM/LM90.html
24943 + *
24944 + * This driver also supports the LM89 and LM99, two other sensor chips
24945 + * made by National Semiconductor. Both have an increased remote
24946 + * temperature measurement accuracy (1 degree), and the LM99
24947 + * additionally shifts remote temperatures (measured and limits) by 16
24948 + * degrees, which allows for higher temperatures measurement. The
24949 + * driver doesn't handle it since it can be done easily in user-space.
24950 + * Complete datasheets can be obtained from National's website at:
24951 + *   http://www.national.com/pf/LM/LM89.html
24952 + *   http://www.national.com/pf/LM/LM99.html
24953 + * Note that there is no way to differenciate between both chips.
24954 + *
24955 + * This driver also supports the LM86, another sensor chip made by
24956 + * National Semiconductor. It is exactly similar to the LM90 except it
24957 + * has a higher accuracy.
24958 + * Complete datasheet can be obtained from National's website at:
24959 + *   http://www.national.com/pf/LM/LM86.html
24960 + *
24961 + * This driver also supports the ADM1032, a sensor chip made by Analog
24962 + * Devices. That chip is similar to the LM90, with a few differences
24963 + * that are not handled by this driver. Complete datasheet can be
24964 + * obtained from Analog's website at:
24965 + *   http://products.analog.com/products/info.asp?product=ADM1032
24966 + * Among others, it has a higher accuracy than the LM90, much like the
24967 + * LM86 does.
24968 + *
24969 + * This driver also supports the MAX6657 and MAX6658, sensor chips made
24970 + * by Maxim. These chips are similar to the LM86. Complete datasheet
24971 + * can be obtained at Maxim's website at:
24972 + *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
24973 + * Note that there is no way to differenciate between both chips (but
24974 + * no need either).
24975 + *
24976 + * Since the LM90 was the first chipset supported by this driver, most
24977 + * comments will refer to this chipset, but are actually general and
24978 + * concern all supported chipsets, unless mentioned otherwise.
24979 + *
24980 + * This program is free software; you can redistribute it and/or modify
24981 + * it under the terms of the GNU General Public License as published by
24982 + * the Free Software Foundation; either version 2 of the License, or
24983 + * (at your option) any later version.
24984 + *
24985 + * This program is distributed in the hope that it will be useful,
24986 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24987 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24988 + * GNU General Public License for more details.
24989 + *
24990 + * You should have received a copy of the GNU General Public License
24991 + * along with this program; if not, write to the Free Software
24992 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24993 + */
24994 +
24995 +#include <linux/module.h>
24996 +#include <linux/slab.h>
24997 +#include <linux/i2c.h>
24998 +#include <linux/i2c-proc.h>
24999 +#include <linux/init.h>
25000 +#define LM_DATE "20041007"
25001 +#define LM_VERSION "2.8.8"
25002 +
25003 +#ifndef I2C_DRIVERID_LM90
25004 +#define I2C_DRIVERID_LM90      1042
25005 +#endif
25006 +
25007 +/*
25008 + * Addresses to scan
25009 + * Address is fully defined internally and cannot be changed.
25010 + * LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
25011 + * LM89-1, and LM99-1 have address 0x4d.
25012 + */
25013 +
25014 +static unsigned short normal_i2c[] = { 0x4c, 0x4d, SENSORS_I2C_END };
25015 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
25016 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
25017 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
25018 +
25019 +/*
25020 + * Insmod parameters
25021 + */
25022 +
25023 +SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657);
25024 +
25025 +/*
25026 + * The LM90 registers
25027 + */
25028 +
25029 +#define LM90_REG_R_MAN_ID        0xFE
25030 +#define LM90_REG_R_CHIP_ID       0xFF
25031 +#define LM90_REG_R_CONFIG1       0x03
25032 +#define LM90_REG_W_CONFIG1       0x09
25033 +#define LM90_REG_R_CONFIG2       0xBF
25034 +#define LM90_REG_W_CONFIG2       0xBF
25035 +#define LM90_REG_R_CONVRATE      0x04
25036 +#define LM90_REG_W_CONVRATE      0x0A
25037 +#define LM90_REG_R_STATUS        0x02
25038 +#define LM90_REG_R_LOCAL_TEMP    0x00
25039 +#define LM90_REG_R_LOCAL_HIGH    0x05
25040 +#define LM90_REG_W_LOCAL_HIGH    0x0B
25041 +#define LM90_REG_R_LOCAL_LOW     0x06
25042 +#define LM90_REG_W_LOCAL_LOW     0x0C
25043 +#define LM90_REG_R_LOCAL_CRIT    0x20
25044 +#define LM90_REG_W_LOCAL_CRIT    0x20
25045 +#define LM90_REG_R_REMOTE_TEMPH  0x01
25046 +#define LM90_REG_R_REMOTE_TEMPL  0x10
25047 +#define LM90_REG_R_REMOTE_OFFSH  0x11
25048 +#define LM90_REG_W_REMOTE_OFFSH  0x11
25049 +#define LM90_REG_R_REMOTE_OFFSL  0x12
25050 +#define LM90_REG_W_REMOTE_OFFSL  0x12
25051 +#define LM90_REG_R_REMOTE_HIGHH  0x07
25052 +#define LM90_REG_W_REMOTE_HIGHH  0x0D
25053 +#define LM90_REG_R_REMOTE_HIGHL  0x13
25054 +#define LM90_REG_W_REMOTE_HIGHL  0x13
25055 +#define LM90_REG_R_REMOTE_LOWH   0x08
25056 +#define LM90_REG_W_REMOTE_LOWH   0x0E
25057 +#define LM90_REG_R_REMOTE_LOWL   0x14
25058 +#define LM90_REG_W_REMOTE_LOWL   0x14
25059 +#define LM90_REG_R_REMOTE_CRIT   0x19
25060 +#define LM90_REG_W_REMOTE_CRIT   0x19
25061 +#define LM90_REG_R_TCRIT_HYST    0x21
25062 +#define LM90_REG_W_TCRIT_HYST    0x21
25063 +
25064 +/*
25065 + * Conversions and various macros
25066 + * The LM90 uses signed 8-bit values for the local temperatures,
25067 + * and signed 11-bit values for the remote temperatures (except
25068 + * T_CRIT). The 11-bit conversion formulas may not round negative
25069 + * numbers perfectly, but who cares?
25070 + */
25071 +
25072 +#define TEMP1_FROM_REG(val)  (val & 0x80 ? val-0x100 : val)
25073 +#define TEMP1_TO_REG(val)    (val < 0 ? val+0x100 : val)
25074 +#define TEMP2_FROM_REG(val)  (((val & 0x8000 ? val-0x10000 : val) \
25075 +                             * 10 + 128) >> 8)
25076 +#define TEMP2_TO_REG(val)    (((val << 8) / 10 + (val < 0 ? \
25077 +                             0x10000 : 0)) & 0xFFE0)
25078 +#define HYST_TO_REG(val)     (val < 0 ? 0 : val > 31 ? 31 : val)
25079 +
25080 +/*
25081 + * Functions declaration
25082 + */
25083 +
25084 +static int lm90_attach_adapter(struct i2c_adapter *adapter);
25085 +static int lm90_detect(struct i2c_adapter *adapter, int address,
25086 +       unsigned short flags, int kind);
25087 +static void lm90_init_client(struct i2c_client *client);
25088 +static int lm90_detach_client(struct i2c_client *client);
25089 +static void lm90_local_temp(struct i2c_client *client, int operation,
25090 +       int ctl_name, int *nrels_mag, long *results);
25091 +static void lm90_remote_temp(struct i2c_client *client, int operation,
25092 +       int ctl_name, int *nrels_mag, long *results);
25093 +static void lm90_local_tcrit(struct i2c_client *client, int operation,
25094 +       int ctl_name, int *nrels_mag, long *results);
25095 +static void lm90_remote_tcrit(struct i2c_client *client, int operation,
25096 +       int ctl_name, int *nrels_mag, long *results);
25097 +static void lm90_local_hyst(struct i2c_client *client, int operation,
25098 +       int ctl_name, int *nrels_mag, long *results);
25099 +static void lm90_remote_hyst(struct i2c_client *client, int operation,
25100 +       int ctl_name, int *nrels_mag, long *results);
25101 +static void lm90_alarms(struct i2c_client *client, int operation,
25102 +       int ctl_name, int *nrels_mag, long *results);
25103 +
25104 +/*
25105 + * Driver data (common to all clients)
25106 + */
25107 +
25108 +static struct i2c_driver lm90_driver = {
25109 +       .owner          = THIS_MODULE,
25110 +       .name           = "LM90/ADM1032 sensor driver",
25111 +       .id             = I2C_DRIVERID_LM90,
25112 +       .flags          = I2C_DF_NOTIFY,
25113 +       .attach_adapter = lm90_attach_adapter,
25114 +       .detach_client  = lm90_detach_client
25115 +};
25116 +
25117 +/*
25118 + * Client data (each client gets its own)
25119 + */
25120 +
25121 +struct lm90_data
25122 +{
25123 +       struct i2c_client client;
25124 +       int sysctl_id;
25125 +
25126 +       struct semaphore update_lock;
25127 +       char valid; /* zero until following fields are valid */
25128 +       unsigned long last_updated; /* in jiffies */
25129 +
25130 +       /* registers values */
25131 +       u8 local_temp, local_high, local_low;
25132 +       u16 remote_temp, remote_high, remote_low; /* combined */
25133 +       u8 local_crit, remote_crit;
25134 +       u8 hyst; /* linked to two sysctl files (hyst1 RW, hyst2 RO) */
25135 +       u16 alarms; /* bitvector, combined */
25136 +};
25137 +
25138 +/*
25139 + * Proc entries
25140 + * These files are created for each detected LM90.
25141 + */
25142 +
25143 +/* -- SENSORS SYSCTL START -- */
25144 +
25145 +#define LM90_SYSCTL_LOCAL_TEMP    1200
25146 +#define LM90_SYSCTL_REMOTE_TEMP   1201
25147 +#define LM90_SYSCTL_LOCAL_TCRIT   1204
25148 +#define LM90_SYSCTL_REMOTE_TCRIT  1205
25149 +#define LM90_SYSCTL_LOCAL_HYST    1207
25150 +#define LM90_SYSCTL_REMOTE_HYST   1208
25151 +#define LM90_SYSCTL_ALARMS        1210
25152 +
25153 +#define LM90_ALARM_LOCAL_HIGH     0x40
25154 +#define LM90_ALARM_LOCAL_LOW      0x20
25155 +#define LM90_ALARM_LOCAL_CRIT     0x01
25156 +#define LM90_ALARM_REMOTE_HIGH    0x10
25157 +#define LM90_ALARM_REMOTE_LOW     0x08
25158 +#define LM90_ALARM_REMOTE_CRIT    0x02
25159 +#define LM90_ALARM_REMOTE_OPEN    0x04
25160 +
25161 +/* -- SENSORS SYSCTL END -- */
25162 +
25163 +
25164 +static ctl_table lm90_dir_table_template[] =
25165 +{
25166 +       {LM90_SYSCTL_LOCAL_TEMP, "temp1", NULL, 0, 0644, NULL,
25167 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm90_local_temp},
25168 +       {LM90_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL,
25169 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm90_remote_temp},
25170 +       {LM90_SYSCTL_LOCAL_TCRIT, "tcrit1", NULL, 0, 0644, NULL,
25171 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm90_local_tcrit},
25172 +       {LM90_SYSCTL_REMOTE_TCRIT, "tcrit2", NULL, 0, 0644, NULL,
25173 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm90_remote_tcrit},
25174 +       {LM90_SYSCTL_LOCAL_HYST, "hyst1", NULL, 0, 0644, NULL,
25175 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm90_local_hyst},
25176 +       {LM90_SYSCTL_REMOTE_HYST, "hyst2", NULL, 0, 0444, NULL,
25177 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm90_remote_hyst},
25178 +       {LM90_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
25179 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &lm90_alarms},
25180 +       {0}
25181 +};
25182 +
25183 +/*
25184 + * Internal variables
25185 + */
25186 +
25187 +static int lm90_id = 0;
25188 +
25189 +/*
25190 + * Real code
25191 + */
25192 +
25193 +static int lm90_attach_adapter(struct i2c_adapter *adapter)
25194 +{
25195 +       return i2c_detect(adapter, &addr_data, lm90_detect);
25196 +}
25197 +
25198 +/*
25199 + * The following function does more than just detection. If detection
25200 + * succeeds, it also registers the new chip.
25201 + */
25202 +static int lm90_detect(struct i2c_adapter *adapter, int address,
25203 +       unsigned short flags, int kind)
25204 +{
25205 +       struct i2c_client *new_client;
25206 +       struct lm90_data *data;
25207 +       int err = 0;
25208 +       const char *type_name = "";
25209 +       const char *client_name = "";
25210 +
25211 +#ifdef DEBUG
25212 +       if (i2c_is_isa_adapter(adapter))
25213 +       {
25214 +               printk("lm90.o: Called for an ISA bus adapter, aborting.\n");
25215 +               return 0;
25216 +       }
25217 +#endif
25218 +
25219 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
25220 +       {
25221 +#ifdef DEBUG
25222 +               printk("lm90.o: I2C bus doesn't support byte read mode, "
25223 +                      "skipping.\n");
25224 +#endif
25225 +               return 0;
25226 +       }
25227 +
25228 +       if (!(data = kmalloc(sizeof(struct lm90_data), GFP_KERNEL)))
25229 +       {
25230 +               printk("lm90.o: Out of memory in lm90_detect (new_client).\n");
25231 +               return -ENOMEM;
25232 +       }
25233 +
25234 +       /*
25235 +        * The common I2C client data is placed right before the
25236 +        * LM90-specific data. The LM90-specific data is pointed to by the
25237 +        * data field from the I2C client data.
25238 +        */
25239 +
25240 +       new_client = &data->client;
25241 +       new_client->addr = address;
25242 +       new_client->data = data;
25243 +       new_client->adapter = adapter;
25244 +       new_client->driver = &lm90_driver;
25245 +       new_client->flags = 0;
25246 +
25247 +       /*
25248 +        * Now we do the remaining detection. A negative kind means that
25249 +        * the driver was loaded with no force parameter (default), so we
25250 +        * must both detect and identify the chip. A zero kind means that
25251 +        * the driver was loaded with the force parameter, the detection
25252 +        * step shall be skipped. A positive kind means that the driver
25253 +        * was loaded with the force parameter and a given kind of chip is
25254 +        * requested, so both the detection and the identification steps
25255 +        * are skipped.
25256 +        */
25257 +
25258 +       /* Default to an LM90 if forced */
25259 +       if (kind == 0)
25260 +               kind = lm90;
25261 +
25262 +       if (kind < 0) /* detection and identification */
25263 +       {
25264 +               u8 man_id, chip_id, reg_config1, reg_convrate;
25265 +
25266 +               man_id = i2c_smbus_read_byte_data(new_client,
25267 +                       LM90_REG_R_MAN_ID);
25268 +               chip_id = i2c_smbus_read_byte_data(new_client,
25269 +                       LM90_REG_R_CHIP_ID);
25270 +               reg_config1 = i2c_smbus_read_byte_data(new_client,
25271 +                       LM90_REG_R_CONFIG1);
25272 +               reg_convrate = i2c_smbus_read_byte_data(new_client,
25273 +                       LM90_REG_R_CONVRATE);
25274 +               
25275 +               if (man_id == 0x01) /* National Semiconductor */
25276 +               {
25277 +                       u8 reg_config2;
25278 +
25279 +                       reg_config2 = i2c_smbus_read_byte_data(new_client,
25280 +                               LM90_REG_R_CONFIG2);
25281 +
25282 +                       if ((reg_config1 & 0x2A) == 0x00
25283 +                        && (reg_config2 & 0xF8) == 0x00
25284 +                        && reg_convrate <= 0x09)
25285 +                       {
25286 +                               if (address == 0x4C
25287 +                                && (chip_id & 0xF0) == 0x20) /* LM90 */
25288 +                                       kind = lm90;
25289 +                               else if ((chip_id & 0xF0) == 0x30) /* LM89/LM99 */
25290 +                                       kind = lm99;
25291 +                               else if (address == 0x4C
25292 +                                && (chip_id & 0xF0) == 0x10) /* LM86 */
25293 +                                       kind = lm99;
25294 +                       }
25295 +               }
25296 +               else if (man_id == 0x41) /* Analog Devices */
25297 +               {
25298 +                       if (address == 0x4C
25299 +                        && (chip_id & 0xF0) == 0x40 /* ADM1032 */
25300 +                        && (reg_config1 & 0x3F) == 0x00
25301 +                        && reg_convrate <= 0x0A)
25302 +                               kind = adm1032;
25303 +               }
25304 +               else if (man_id == 0x4D) /* Maxim */
25305 +               {
25306 +                       if (address == 0x4C
25307 +                        && (reg_config1 & 0x1F) == 0
25308 +                        && reg_convrate <= 0x09)
25309 +                               kind = max6657;
25310 +               }
25311 +       }
25312 +
25313 +       if (kind <= 0) /* identification failed */
25314 +       {
25315 +               printk("lm90.o: Unsupported chip.\n");
25316 +               goto ERROR1;
25317 +       }
25318 +
25319 +       if (kind == lm90)
25320 +       {
25321 +               type_name = "lm90";
25322 +               client_name = "LM90 chip";
25323 +       }
25324 +       else if (kind == adm1032)
25325 +       {
25326 +               type_name = "adm1032";
25327 +               client_name = "ADM1032 chip";
25328 +       }
25329 +       else if (kind == lm99)
25330 +       {
25331 +               type_name = "lm99";
25332 +               client_name = "LM99 chip";
25333 +       }
25334 +       else if (kind == lm86)
25335 +       {
25336 +               type_name = "lm86";
25337 +               client_name = "LM86 chip";
25338 +       }
25339 +       else if (kind == max6657)
25340 +       {
25341 +               type_name = "max6657";
25342 +               client_name = "MAX6657 chip";
25343 +       }
25344 +       else
25345 +       {
25346 +               printk("lm90.o: Unknown kind %d.\n", kind);
25347 +               goto ERROR1;
25348 +       }
25349 +
25350 +       /*
25351 +        * OK, we got a valid chip so we can fill in the remaining client
25352 +        * fields.
25353 +        */
25354 +
25355 +       strcpy(new_client->name, client_name);
25356 +       new_client->id = lm90_id++;
25357 +       data->valid = 0;
25358 +       init_MUTEX(&data->update_lock);
25359 +
25360 +       /*
25361 +        * Tell the I2C layer a new client has arrived.
25362 +        */
25363 +
25364 +       if ((err = i2c_attach_client(new_client)))
25365 +       {
25366 +#ifdef DEBUG
25367 +               printk("lm90.o: Failed attaching client.\n");
25368 +#endif
25369 +               goto ERROR1;
25370 +       }
25371 +
25372 +       /*
25373 +        * Register a new directory entry.
25374 +        */
25375 +
25376 +       if ((err = i2c_register_entry(new_client, type_name,
25377 +            lm90_dir_table_template)) < 0)
25378 +       {
25379 +#ifdef DEBUG
25380 +               printk("lm90.o: Failed registering directory entry.\n");
25381 +#endif
25382 +               goto ERROR2;
25383 +       }
25384 +       data->sysctl_id = err;
25385 +
25386 +       /*
25387 +        * Initialize the LM90 chip.
25388 +        */
25389 +
25390 +       lm90_init_client(new_client);
25391 +       return 0;
25392 +
25393 +       ERROR2:
25394 +       i2c_detach_client(new_client);
25395 +       ERROR1:
25396 +       kfree(data);
25397 +       return err;
25398 +}
25399 +
25400 +static void lm90_init_client(struct i2c_client *client)
25401 +{
25402 +       u8 config;
25403 +
25404 +       /*
25405 +        * Start the conversions.
25406 +        */
25407 +
25408 +       i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
25409 +               5); /* 2 Hz */
25410 +       config = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
25411 +       if (config & 0x40)
25412 +               i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
25413 +                       config & 0xBF); /* run */
25414 +}
25415 +
25416 +
25417 +static int lm90_detach_client(struct i2c_client *client)
25418 +{
25419 +       int err;
25420 +
25421 +       i2c_deregister_entry(((struct lm90_data *) (client->data))->sysctl_id);
25422 +       if ((err = i2c_detach_client(client)))
25423 +       {
25424 +               printk("lm90.o: Client deregistration failed, client not "
25425 +                      "detached.\n");
25426 +               return err;
25427 +       }
25428 +
25429 +       kfree(client->data);
25430 +       return 0;
25431 +}
25432 +
25433 +static void lm90_update_client(struct i2c_client *client)
25434 +{
25435 +       struct lm90_data *data = client->data;
25436 +
25437 +       down(&data->update_lock);
25438 +
25439 +       if ((jiffies - data->last_updated > HZ * 2) ||
25440 +           (jiffies < data->last_updated) || !data->valid)
25441 +       {
25442 +               u8 oldh, newh;
25443 +#ifdef DEBUG
25444 +               printk("lm90.o: Updating data.\n");
25445 +#endif
25446 +
25447 +               data->local_temp =
25448 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_LOCAL_TEMP);
25449 +               data->local_high =
25450 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_LOCAL_HIGH);
25451 +               data->local_low =
25452 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_LOCAL_LOW);
25453 +               data->local_crit =
25454 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_LOCAL_CRIT);
25455 +
25456 +               /*
25457 +                * There is a trick here. We have to read two registers to
25458 +                * have the remote sensor temperature, but we have to beware
25459 +                * a conversion could occur inbetween the readings. The
25460 +                * datasheet says we should either use the one-shot
25461 +                * conversion register, which we don't want to do (disables
25462 +                * hardware monitoring) or monitor the busy bit, which is
25463 +                * impossible (we can't read the values and monitor that bit
25464 +                * at the exact same time). So the solution used here is to
25465 +                * read the high byte once, then the low byte, then the high
25466 +                * byte again. If the new high byte matches the old one,
25467 +                * then we have a valid reading. Else we have to read the low
25468 +                * byte again, and now we believe we have a correct reading.
25469 +                */
25470 +
25471 +               oldh =
25472 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_TEMPH);
25473 +               data->remote_temp =
25474 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_TEMPL);
25475 +               newh =
25476 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_TEMPH);
25477 +               if (newh != oldh)
25478 +               {
25479 +                       data->remote_temp =
25480 +                               i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_TEMPL);
25481 +#ifdef DEBUG
25482 +                       oldh = /* actually newer */
25483 +                               i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_TEMPH);
25484 +                       if (newh != oldh)
25485 +                               printk("lm90.o: Remote temperature may be wrong.\n");
25486 +#endif
25487 +               }
25488 +               data->remote_temp |= (newh << 8);
25489 +               data->remote_high =
25490 +                       (i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_HIGHH) << 8)
25491 +                       + i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_HIGHL);
25492 +               data->remote_low =
25493 +                       (i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_LOWH) << 8)
25494 +                       + i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_LOWL);
25495 +               data->remote_crit =
25496 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_CRIT);
25497 +
25498 +               data->hyst =
25499 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_TCRIT_HYST);
25500 +               data->alarms =
25501 +                       i2c_smbus_read_byte_data(client, LM90_REG_R_STATUS);
25502 +
25503 +               data->last_updated = jiffies;
25504 +               data->valid = 1;
25505 +       }
25506 +
25507 +       up(&data->update_lock);
25508 +}
25509 +
25510 +static void lm90_local_temp(struct i2c_client *client, int operation,
25511 +       int ctl_name, int *nrels_mag, long *results)
25512 +{
25513 +       struct lm90_data *data = client->data;
25514 +
25515 +       if (operation == SENSORS_PROC_REAL_INFO)
25516 +               *nrels_mag = 0; /* magnitude */
25517 +       else if (operation == SENSORS_PROC_REAL_READ)
25518 +       {
25519 +               lm90_update_client(client);
25520 +               results[0] = TEMP1_FROM_REG(data->local_high);
25521 +               results[1] = TEMP1_FROM_REG(data->local_low);
25522 +               results[2] = TEMP1_FROM_REG(data->local_temp);
25523 +               *nrels_mag = 3;
25524 +       }
25525 +       else if (operation == SENSORS_PROC_REAL_WRITE)
25526 +       {
25527 +               if (*nrels_mag >= 1)
25528 +               {
25529 +                       data->local_high = TEMP1_TO_REG(results[0]);
25530 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_LOCAL_HIGH,
25531 +                               data->local_high);
25532 +               }
25533 +               if (*nrels_mag >= 2)
25534 +               {
25535 +                       data->local_low = TEMP1_TO_REG(results[1]);
25536 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_LOCAL_LOW,
25537 +                               data->local_low);
25538 +               }
25539 +       }
25540 +}
25541 +
25542 +static void lm90_remote_temp(struct i2c_client *client, int operation,
25543 +       int ctl_name, int *nrels_mag, long *results)
25544 +{
25545 +       struct lm90_data *data = client->data;
25546 +
25547 +       if (operation == SENSORS_PROC_REAL_INFO)
25548 +               *nrels_mag = 1; /* magnitude */
25549 +       else if (operation == SENSORS_PROC_REAL_READ)
25550 +       {
25551 +               lm90_update_client(client);
25552 +               results[0] = TEMP2_FROM_REG(data->remote_high);
25553 +               results[1] = TEMP2_FROM_REG(data->remote_low);
25554 +               results[2] = TEMP2_FROM_REG(data->remote_temp);
25555 +               *nrels_mag = 3;
25556 +       }
25557 +       else if (operation == SENSORS_PROC_REAL_WRITE)
25558 +       {
25559 +               if (*nrels_mag >= 1)
25560 +               {
25561 +                       data->remote_high = TEMP2_TO_REG(results[0]);
25562 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_REMOTE_HIGHH,
25563 +                               data->remote_high >> 8);
25564 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_REMOTE_HIGHL,
25565 +                               data->remote_high & 0xFF);
25566 +               }
25567 +               if (*nrels_mag >= 2)
25568 +               {
25569 +                       data->remote_low = TEMP2_TO_REG(results[1]);
25570 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_REMOTE_LOWH,
25571 +                               data->remote_low >> 8);
25572 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_REMOTE_LOWL,
25573 +                               data->remote_low & 0xFF);
25574 +               }
25575 +       }
25576 +}
25577 +
25578 +static void lm90_local_tcrit(struct i2c_client *client, int operation,
25579 +       int ctl_name, int *nrels_mag, long *results)
25580 +{
25581 +       struct lm90_data *data = client->data;
25582 +
25583 +       if (operation == SENSORS_PROC_REAL_INFO)
25584 +               *nrels_mag = 0; /* magnitude */
25585 +       else if (operation == SENSORS_PROC_REAL_READ)
25586 +       {
25587 +               lm90_update_client(client);
25588 +               results[0] = TEMP1_FROM_REG(data->local_crit);
25589 +               *nrels_mag = 1;
25590 +       }
25591 +       else if (operation == SENSORS_PROC_REAL_WRITE)
25592 +       {
25593 +               if (*nrels_mag >= 1)
25594 +               {
25595 +                       data->local_crit = TEMP1_TO_REG(results[0]);
25596 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_LOCAL_CRIT,
25597 +                               data->local_crit);
25598 +               }
25599 +       }
25600 +}
25601 +
25602 +static void lm90_remote_tcrit(struct i2c_client *client, int operation,
25603 +       int ctl_name, int *nrels_mag, long *results)
25604 +{
25605 +       struct lm90_data *data = client->data;
25606 +
25607 +       if (operation == SENSORS_PROC_REAL_INFO)
25608 +               *nrels_mag = 0; /* magnitude */
25609 +       else if (operation == SENSORS_PROC_REAL_READ)
25610 +       {
25611 +               lm90_update_client(client);
25612 +               results[0] = TEMP1_FROM_REG(data->remote_crit);
25613 +               *nrels_mag = 1;
25614 +       }
25615 +       else if (operation == SENSORS_PROC_REAL_WRITE)
25616 +       {
25617 +               if (*nrels_mag >= 1)
25618 +               {
25619 +                       data->remote_crit = TEMP1_TO_REG(results[0]);
25620 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_REMOTE_CRIT,
25621 +                               data->remote_crit);
25622 +               }
25623 +       }
25624 +}
25625 +
25626 +/*
25627 + * One quick note about hysteresis. Internally, the hysteresis value
25628 + * is held in a single register by the LM90, as a relative value.
25629 + * This relative value applies to both the local critical temperature
25630 + * and the remote critical temperature. Since all temperatures exported
25631 + * through procfs have to be absolute, we have to do some conversions.
25632 + * The solution retained here is to export two absolute values, one for
25633 + * each critical temperature. In order not to confuse the users too
25634 + * much, only one file is writable. Would we fail to do so, users
25635 + * would probably attempt to write to both files, as if they were
25636 + * independant, and since they aren't, they wouldn't understand why
25637 + * setting one affects the other one (and would probably claim there's
25638 + * a bug in the driver).
25639 + */
25640 +
25641 +static void lm90_local_hyst(struct i2c_client *client, int operation,
25642 +       int ctl_name, int *nrels_mag, long *results)
25643 +{
25644 +       struct lm90_data *data = client->data;
25645 +
25646 +       if (operation == SENSORS_PROC_REAL_INFO)
25647 +               *nrels_mag = 0; /* magnitude */
25648 +       else if (operation == SENSORS_PROC_REAL_READ)
25649 +       {
25650 +               lm90_update_client(client);
25651 +               results[0] = TEMP1_FROM_REG(data->local_crit) -
25652 +                       TEMP1_FROM_REG(data->hyst);
25653 +               *nrels_mag = 1;
25654 +       }
25655 +       else if (operation == SENSORS_PROC_REAL_WRITE)
25656 +       {
25657 +               if (*nrels_mag >= 1)
25658 +               {
25659 +                       data->hyst = HYST_TO_REG(data->local_crit - results[0]);
25660 +                       i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
25661 +                               data->hyst);
25662 +               }
25663 +       }
25664 +}
25665 +
25666 +static void lm90_remote_hyst(struct i2c_client *client, int operation,
25667 +       int ctl_name, int *nrels_mag, long *results)
25668 +{
25669 +       struct lm90_data *data = client->data;
25670 +
25671 +       if (operation == SENSORS_PROC_REAL_INFO)
25672 +               *nrels_mag = 0; /* magnitude */
25673 +       else if (operation == SENSORS_PROC_REAL_READ)
25674 +       {
25675 +               lm90_update_client(client);
25676 +               results[0] = TEMP1_FROM_REG(data->remote_crit) -
25677 +                       TEMP1_FROM_REG(data->hyst);
25678 +               *nrels_mag = 1;
25679 +       }
25680 +}
25681 +
25682 +static void lm90_alarms(struct i2c_client *client, int operation,
25683 +       int ctl_name, int *nrels_mag, long *results)
25684 +{
25685 +       struct lm90_data *data = client->data;
25686 +
25687 +       if (operation == SENSORS_PROC_REAL_INFO)
25688 +               *nrels_mag = 0; /* magnitude */
25689 +       else if (operation == SENSORS_PROC_REAL_READ)
25690 +       {
25691 +               lm90_update_client(client);
25692 +               results[0] = data->alarms;
25693 +               *nrels_mag = 1;
25694 +       }
25695 +}
25696 +
25697 +static int __init sm_lm90_init(void)
25698 +{
25699 +       printk(KERN_INFO "lm90.o version %s (%s)\n", LM_VERSION, LM_DATE);
25700 +       return i2c_add_driver(&lm90_driver);
25701 +}
25702 +
25703 +static void __exit sm_lm90_exit(void)
25704 +{
25705 +       i2c_del_driver(&lm90_driver);
25706 +}
25707 +
25708 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
25709 +MODULE_DESCRIPTION("LM90/ADM1032 sensor driver");
25710 +MODULE_LICENSE("GPL");
25711 +
25712 +module_init(sm_lm90_init);
25713 +module_exit(sm_lm90_exit);
25714 --- linux-old/drivers/sensors/lm92.c    Thu Jan  1 00:00:00 1970
25715 +++ linux/drivers/sensors/lm92.c        Mon Dec 13 20:18:49 2004
25716 @@ -0,0 +1,421 @@
25717 +
25718 +/*
25719 + * LM92 - Part of lm_sensors, Linux kernel modules for hardware
25720 + *        monitoring
25721 + *
25722 + * Author: Abraham van der Merwe <abraham@2d3d.co.za>
25723 + *
25724 + * Linux support for the National Semiconductor LM92 Temperature
25725 + * Sensor.
25726 + *
25727 + * Based on code from the lm-sensors project which is available
25728 + * at http://www.lm-sensors.nu/. lm87.c have been particularly
25729 + * helpful (:
25730 + *
25731 + * This source code is free software; you can redistribute it and/or
25732 + * modify it under the terms of the GNU General Public License
25733 + * version 2 as published by the Free Software Foundation.
25734 + */
25735 +
25736 +#include <linux/config.h>
25737 +#include <linux/module.h>
25738 +#include <linux/kernel.h>
25739 +#include <linux/string.h>
25740 +#include <linux/slab.h>
25741 +#include <linux/init.h>
25742 +#include <linux/i2c.h>
25743 +#include <linux/i2c-proc.h>
25744 +#include <linux/proc_fs.h>
25745 +#include <linux/sysctl.h>
25746 +#include <asm/semaphore.h>
25747 +#define LM_DATE "20041007"
25748 +#define LM_VERSION "2.8.8"
25749 +
25750 +/* if defined, 4 faults must occur consecutively to set alarm flags */
25751 +/* #define ENABLE_FAULT_QUEUE */
25752 +
25753 +#define LM92_REG_TEMPERATURE           0x00    /* ro, 16-bit   */
25754 +#define LM92_REG_CONFIGURATION         0x01    /* rw, 8-bit    */
25755 +#define LM92_REG_TRIP_HYSTERESIS       0x02    /* rw, 16-bit   */
25756 +#define LM92_REG_TRIP_CRITICAL         0x03    /* rw, 16-bit   */
25757 +#define LM92_REG_TRIP_LOW                      0x04    /* rw, 16-bit   */
25758 +#define LM92_REG_TRIP_HIGH                     0x05    /* rw, 16-bit   */
25759 +#define LM92_REG_MANUFACTURER          0x07    /* ro, 16-bit   */
25760 +
25761 +#define LM92_MANUFACTURER_ID           0x8001
25762 +
25763 +#define TEMP_MIN       (-4096)
25764 +#define TEMP_MAX       4095
25765 +
25766 +#define LIMIT(x) do {                                                  \
25767 +               if ((x) < TEMP_MIN) (x) = TEMP_MIN;             \
25768 +               if ((x) > TEMP_MAX) (x) = TEMP_MAX;             \
25769 +       } while (0)
25770 +
25771 +#define PROC_TO_NATIVE(x) ((x) / 625)
25772 +#define NATIVE_TO_PROC(x) ((x) * 625)
25773 +#define CELSIUS(x) ((x) * 16)
25774 +
25775 +static void lm92_temp (struct i2c_client *client,int operation,int ctl_name,int *nrels_mag,long *results);
25776 +static void lm92_alarms (struct i2c_client *client,int operation,int ctl_name,int *nrels_mag,long *results);
25777 +
25778 +/* -- SENSORS SYSCTL START -- */
25779 +#define LM92_SYSCTL_ALARMS             2001    /* high, low, critical */
25780 +#define LM92_SYSCTL_TEMP               1200    /* high, low, critical, hysteresis, input */
25781 +
25782 +#define LM92_ALARM_TEMP_HIGH   0x01
25783 +#define LM92_ALARM_TEMP_LOW            0x02
25784 +#define LM92_ALARM_TEMP_CRIT   0x04
25785 +#define LM92_TEMP_HIGH                 0x08
25786 +#define LM92_TEMP_LOW                  0x10
25787 +#define LM92_TEMP_CRIT                 0x20
25788 +#define LM92_TEMP_HYST                 0x40
25789 +#define LM92_TEMP_INPUT                        0x80
25790 +
25791 +/* -- SENSORS SYSCTL END -- */
25792 +
25793 +static ctl_table lm92_dir_table[] = {
25794 +       {LM92_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
25795 +        &i2c_sysctl_real, NULL, &lm92_temp, NULL},
25796 +       {LM92_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
25797 +        &i2c_sysctl_real, NULL, &lm92_alarms, NULL},
25798 +       {0}
25799 +};
25800 +
25801 +/* NOTE: all temperatures are degrees centigrade * 16 */
25802 +typedef struct {
25803 +       struct i2c_client client;
25804 +       int sysctl_id;
25805 +       unsigned long timestamp;
25806 +       struct {
25807 +               long high;
25808 +               long low;
25809 +               long crit;
25810 +               long hyst;
25811 +               long input;
25812 +       } temp;
25813 +       struct {
25814 +               long low;
25815 +               long high;
25816 +               long crit;
25817 +       } alarms;
25818 +} lm92_t;
25819 +
25820 +/* this is needed for each client driver method */
25821 +static struct i2c_driver lm92_driver;
25822 +
25823 +/* ensure exclusive access to chip and static variables */
25824 +static DECLARE_MUTEX (mutex);
25825 +
25826 +/* addresses to scan */
25827 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
25828 +static unsigned short normal_i2c_range[] = { 0x48, 0x4f, SENSORS_I2C_END };
25829 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
25830 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
25831 +
25832 +/* insmod parameters */
25833 +SENSORS_INSMOD_1 (lm92);
25834 +
25835 +static inline int lm92_write8 (struct i2c_client *client,u8 reg,u8 value)
25836 +{
25837 +       return (i2c_smbus_write_byte_data (client,reg,value) < 0 ? -EIO : 0);
25838 +}
25839 +
25840 +static inline int lm92_read16 (struct i2c_client *client,u8 reg,u16 *value)
25841 +{
25842 +       s32 tmp = i2c_smbus_read_word_data (client,reg);
25843 +
25844 +       if (tmp < 0) return (-EIO);
25845 +
25846 +       /* convert the data to little endian format */
25847 +       *value = swab16((u16) tmp);
25848 +
25849 +       return (0);
25850 +}
25851 +
25852 +static inline int lm92_write16 (struct i2c_client *client,u8 reg,u16 value)
25853 +{
25854 +       /* convert the data to big endian format */
25855 +       if (i2c_smbus_write_word_data(client, reg, swab16(value)) < 0)
25856 +               return -EIO;
25857 +
25858 +       return 0;
25859 +}
25860 +
25861 +static int lm92_read (struct i2c_client *client)
25862 +{
25863 +       lm92_t *data = (lm92_t *) client->data;
25864 +       u16 value[5];
25865 +
25866 +       if ((jiffies - data->timestamp) > HZ) {
25867 +               if (lm92_read16 (client,LM92_REG_TEMPERATURE,value) < 0 ||
25868 +                       lm92_read16 (client,LM92_REG_TRIP_HYSTERESIS,value + 1) < 0 ||
25869 +                       lm92_read16 (client,LM92_REG_TRIP_CRITICAL,value + 2) < 0 ||
25870 +                       lm92_read16 (client,LM92_REG_TRIP_LOW,value + 3) < 0 ||
25871 +                       lm92_read16 (client,LM92_REG_TRIP_HIGH,value + 4) < 0)
25872 +                       return (-EIO);
25873 +
25874 +               data->temp.input = (s16) value[0] >> 3;
25875 +               data->temp.hyst = (s16) value[1] >> 3;
25876 +               data->temp.crit = (s16) value[2] >> 3;
25877 +               data->temp.low = (s16) value[3] >> 3;
25878 +               data->temp.high = (s16) value[4] >> 3;
25879 +
25880 +               data->alarms.low = value[0] & 1;
25881 +               data->alarms.high = (value[0] & 2) >> 1;
25882 +               data->alarms.crit = (value[0] & 4) >> 2;
25883 +
25884 +               data->timestamp = jiffies;
25885 +       }
25886 +
25887 +       return (0);
25888 +}
25889 +
25890 +static int lm92_write (struct i2c_client *client)
25891 +{
25892 +       lm92_t *data = (lm92_t *) client->data;
25893 +
25894 +       LIMIT (data->temp.hyst);
25895 +       LIMIT (data->temp.crit);
25896 +       LIMIT (data->temp.low);
25897 +       LIMIT (data->temp.high);
25898 +
25899 +       if (lm92_write16 (client,LM92_REG_TRIP_HYSTERESIS,((s16) data->temp.hyst << 3)) < 0 ||
25900 +               lm92_write16 (client,LM92_REG_TRIP_CRITICAL,((s16) data->temp.crit << 3)) < 0 ||
25901 +               lm92_write16 (client,LM92_REG_TRIP_LOW,((s16) data->temp.low << 3)) < 0 ||
25902 +               lm92_write16 (client,LM92_REG_TRIP_HIGH,((s16) data->temp.high << 3)) < 0)
25903 +               return (-EIO);
25904 +
25905 +       return (0);
25906 +}
25907 +
25908 +static void lm92_temp (struct i2c_client *client,int operation,int ctl_name,int *nrels_mag,long *results)
25909 +{
25910 +       if (!down_interruptible (&mutex)) {
25911 +               lm92_t *data = (lm92_t *) client->data;
25912 +
25913 +               if (operation == SENSORS_PROC_REAL_READ) {
25914 +                       lm92_read (client);
25915 +                       results[0] = NATIVE_TO_PROC (data->temp.input);
25916 +                       results[1] = NATIVE_TO_PROC (data->temp.high);
25917 +                       results[2] = NATIVE_TO_PROC (data->temp.low);
25918 +                       results[3] = NATIVE_TO_PROC (data->temp.crit);
25919 +                       results[4] = NATIVE_TO_PROC (data->temp.hyst);
25920 +                       *nrels_mag = 5;
25921 +               } else if (operation == SENSORS_PROC_REAL_WRITE && *nrels_mag == 4) {
25922 +                       data->temp.high = PROC_TO_NATIVE (results[0]);
25923 +                       data->temp.low = PROC_TO_NATIVE (results[1]);
25924 +                       data->temp.crit = PROC_TO_NATIVE (results[2]);
25925 +                       data->temp.hyst = PROC_TO_NATIVE (results[3]);
25926 +                       lm92_write (client);
25927 +               } else if (operation == SENSORS_PROC_REAL_INFO) {
25928 +                       *nrels_mag = 4;
25929 +               }
25930 +
25931 +               up (&mutex);
25932 +       }
25933 +}
25934 +
25935 +static void lm92_alarms (struct i2c_client *client,int operation,int ctl_name,int *nrels_mag,long *results)
25936 +{
25937 +       if (!down_interruptible (&mutex)) {
25938 +               lm92_t *data = (lm92_t *) client->data;
25939 +
25940 +               if (operation == SENSORS_PROC_REAL_READ) {
25941 +                       lm92_read (client);
25942 +                       results[0] = data->alarms.high || (data->alarms.low << 1) || (data->alarms.crit << 2);
25943 +                       *nrels_mag = 1;
25944 +               } else if (operation == SENSORS_PROC_REAL_INFO) {
25945 +                       *nrels_mag = 0;
25946 +               }
25947 +
25948 +               up (&mutex);
25949 +       }
25950 +}
25951 +
25952 +static int max6635_check(struct i2c_client *client)
25953 +{
25954 +       int i;
25955 +       u16 temp_low, temp_high, temp_hyst, temp_crit;
25956 +       u8 conf;
25957 +
25958 +       temp_low = i2c_smbus_read_word_data(client, LM92_REG_TRIP_LOW);
25959 +       temp_high = i2c_smbus_read_word_data(client, LM92_REG_TRIP_HIGH);
25960 +       temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TRIP_HYSTERESIS);
25961 +       temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TRIP_CRITICAL);
25962 +       
25963 +       if ((temp_low & 0x7f00) || (temp_high & 0x7f00)
25964 +        || (temp_hyst & 0x7f00) || (temp_crit & 0x7f00))
25965 +               return 0;
25966 +
25967 +       conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIGURATION);
25968 +
25969 +       for (i=0; i<128; i+=16) {
25970 +               if (temp_low != i2c_smbus_read_word_data(client, LM92_REG_TRIP_LOW + i)
25971 +                || temp_high != i2c_smbus_read_word_data(client, LM92_REG_TRIP_HIGH + i)
25972 +                || temp_hyst != i2c_smbus_read_word_data(client, LM92_REG_TRIP_HYSTERESIS + i)
25973 +                || temp_crit != i2c_smbus_read_word_data(client, LM92_REG_TRIP_CRITICAL + i)
25974 +                || conf != i2c_smbus_read_byte_data(client, LM92_REG_CONFIGURATION + i))
25975 +                       return 0;
25976 +       }
25977 +       
25978 +       return 1;
25979 +}
25980 +
25981 +static int lm92_init_client (struct i2c_client *client)
25982 +{
25983 +       lm92_t *data = (lm92_t *) client->data;
25984 +       u8 value = 0;
25985 +       int result;
25986 +
25987 +       /* force reads to query the chip */
25988 +       data->timestamp = 0;
25989 +
25990 +       /* setup the configuration register */
25991 +
25992 +#ifdef ENABLE_FAULT_QUEUE
25993 +       value |= 0x10;
25994 +#endif /* #ifdef ENABLE_FAULT_QUEUE */
25995 +
25996 +       if (lm92_write8 (client,LM92_REG_CONFIGURATION,value) < 0)
25997 +               return (-ENODEV);
25998 +
25999 +       /* set default alarm trigger values */
26000 +
26001 +       data->temp.high = CELSIUS (64);
26002 +       data->temp.low = CELSIUS (10);
26003 +       data->temp.crit = CELSIUS (80);
26004 +       data->temp.hyst = CELSIUS (2);
26005 +
26006 +       if ((result = lm92_write (client)) < 0)
26007 +               return (result);
26008 +
26009 +       /* read everything once so that our cached data is updated */
26010 +
26011 +       if ((result = lm92_read (client)) < 0)
26012 +               return (result);
26013 +
26014 +       return (0);
26015 +}
26016 +
26017 +static int lm92_detect (struct i2c_adapter *adapter,int address,unsigned short flags,int kind)
26018 +{
26019 +       static int id = 0;
26020 +       struct i2c_client *client;
26021 +       lm92_t *data;
26022 +       int result;
26023 +       u16 manufacturer;
26024 +
26025 +       if (!i2c_check_functionality (adapter,I2C_FUNC_SMBUS_BYTE_DATA))
26026 +               return (-ENODEV);
26027 +
26028 +       if (!(data = kmalloc(sizeof(lm92_t), GFP_KERNEL)))
26029 +               return (-ENOMEM);
26030 +
26031 +       client = &data->client;
26032 +       client->addr = address;
26033 +       client->data = data;
26034 +       client->adapter = adapter;
26035 +       client->driver = &lm92_driver;
26036 +       client->flags = 0;
26037 +       strcpy (client->name,lm92_driver.name);
26038 +
26039 +       if (down_interruptible (&mutex)) {
26040 +               result = -ERESTARTSYS;
26041 +               goto ERROR1;
26042 +       }
26043 +
26044 +       if (kind < 0) {
26045 +               /* Is it an lm92? */
26046 +               if (address < 0x4c
26047 +                && (lm92_read16(client,LM92_REG_MANUFACTURER,&manufacturer) < 0
26048 +                 || manufacturer != LM92_MANUFACTURER_ID)) {
26049 +                       /* Is it a MAX6635/MAX6635/MAX6635? */
26050 +                       if (!max6635_check(client)) {
26051 +                               result = -ENODEV;
26052 +                               goto ERROR2;
26053 +                       }
26054 +               }
26055 +       }
26056 +
26057 +       if ((result = i2c_attach_client (client))) {
26058 +               goto ERROR2;
26059 +       }
26060 +
26061 +       if ((result = i2c_register_entry (client,client->name,lm92_dir_table)) < 0) {
26062 +               goto ERROR3;
26063 +       }
26064 +       data->sysctl_id = result;
26065 +
26066 +       if ((result = lm92_init_client (client)) < 0) {
26067 +               goto ERROR4;
26068 +       }
26069 +
26070 +       client->id = id++;
26071 +
26072 +       up (&mutex);
26073 +
26074 +       return (0);
26075 +
26076 +ERROR4:
26077 +       i2c_deregister_entry(data->sysctl_id);
26078 +ERROR3:
26079 +       i2c_detach_client(client);
26080 +ERROR2:
26081 +       up(&mutex);
26082 +ERROR1:
26083 +       kfree(data);
26084 +       return result;
26085 +}
26086 +
26087 +static int lm92_attach_adapter (struct i2c_adapter *adapter)
26088 +{
26089 +       return i2c_detect (adapter,&addr_data,lm92_detect);
26090 +}
26091 +
26092 +static int lm92_detach_client (struct i2c_client *client)
26093 +{
26094 +       int result;
26095 +
26096 +       i2c_deregister_entry (((lm92_t *) (client->data))->sysctl_id);
26097 +
26098 +       if ((result = i2c_detach_client (client)))
26099 +               return (result);
26100 +
26101 +       kfree(client->data);
26102 +
26103 +       return (0);
26104 +}
26105 +
26106 +
26107 +static struct i2c_driver lm92_driver = {
26108 +       .owner          = THIS_MODULE,
26109 +       .name           = "lm92",
26110 +       .id             = I2C_DRIVERID_LM92,
26111 +       .flags          = I2C_DF_NOTIFY,
26112 +       .attach_adapter = lm92_attach_adapter,
26113 +       .detach_client  = lm92_detach_client,
26114 +};
26115 +
26116 +static int __init sm_lm92_init(void)
26117 +{
26118 +       printk ("lm92.o version %s (%s)\n",LM_VERSION,LM_DATE);
26119 +       return i2c_add_driver(&lm92_driver);
26120 +}
26121 +
26122 +
26123 +static void __exit sm_lm92_exit(void)
26124 +{
26125 +       i2c_del_driver(&lm92_driver);
26126 +}
26127 +
26128 +
26129 +
26130 +MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
26131 +MODULE_DESCRIPTION ("Linux support for LM92 Temperature Sensor");
26132 +
26133 +MODULE_LICENSE ("GPL");
26134 +
26135 +module_init(sm_lm92_init);
26136 +module_exit(sm_lm92_exit);
26137 +
26138 --- linux-old/drivers/sensors/matorb.c  Thu Jan  1 00:00:00 1970
26139 +++ linux/drivers/sensors/matorb.c      Mon Dec 13 20:18:49 2004
26140 @@ -0,0 +1,286 @@
26141 +/*
26142 +    matorb.c - Part of lm_sensors, Linux kernel modules for hardware
26143 +             monitoring
26144 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
26145 +    and Philip Edelbrock <phil@netroedge.com>
26146 +
26147 +    This program is free software; you can redistribute it and/or modify
26148 +    it under the terms of the GNU General Public License as published by
26149 +    the Free Software Foundation; either version 2 of the License, or
26150 +    (at your option) any later version.
26151 +
26152 +    This program is distributed in the hope that it will be useful,
26153 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
26154 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26155 +    GNU General Public License for more details.
26156 +
26157 +    You should have received a copy of the GNU General Public License
26158 +    along with this program; if not, write to the Free Software
26159 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26160 +*/
26161 +
26162 +
26163 +#define DEBUG 1
26164 +
26165 +#include <linux/module.h>
26166 +#include <linux/slab.h>
26167 +#include <linux/i2c.h>
26168 +#include <linux/i2c-proc.h>
26169 +#include <linux/init.h>
26170 +#define LM_DATE "20041007"
26171 +#define LM_VERSION "2.8.8"
26172 +
26173 +MODULE_LICENSE("GPL");
26174 +
26175 +/* Addresses to scan */
26176 +static unsigned short normal_i2c[] = { 0x2E, SENSORS_I2C_END };
26177 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
26178 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
26179 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
26180 +
26181 +/* Insmod parameters */
26182 +SENSORS_INSMOD_1(matorb);
26183 +
26184 +/* Many MATORB constants specified below */
26185 +
26186 +
26187 +/* Each client has this additional data */
26188 +struct matorb_data {
26189 +       struct i2c_client client;
26190 +       int sysctl_id;
26191 +
26192 +       struct semaphore update_lock;
26193 +       char valid;             /* !=0 if following fields are valid */
26194 +       unsigned long last_updated;     /* In jiffies */
26195 +
26196 +};
26197 +
26198 +static int matorb_attach_adapter(struct i2c_adapter *adapter);
26199 +static int matorb_detect(struct i2c_adapter *adapter, int address,
26200 +                        unsigned short flags, int kind);
26201 +static void matorb_init_client(struct i2c_client *client);
26202 +static int matorb_detach_client(struct i2c_client *client);
26203 +
26204 +static int matorb_write_value(struct i2c_client *client, u8 reg,
26205 +                             u16 value);
26206 +static void matorb_disp(struct i2c_client *client, int operation,
26207 +                       int ctl_name, int *nrels_mag, long *results);
26208 +static void matorb_update_client(struct i2c_client *client);
26209 +
26210 +
26211 +/* This is the driver that will be inserted */
26212 +static struct i2c_driver matorb_driver = {
26213 +       .owner          = THIS_MODULE,
26214 +       .name           = "Matrix Orbital LCD driver",
26215 +       .id             = I2C_DRIVERID_MATORB,
26216 +       .flags          = I2C_DF_NOTIFY,
26217 +       .attach_adapter = matorb_attach_adapter,
26218 +       .detach_client  = matorb_detach_client,
26219 +};
26220 +
26221 +/* -- SENSORS SYSCTL START -- */
26222 +#define MATORB_SYSCTL_DISP 1000
26223 +/* -- SENSORS SYSCTL END -- */
26224 +
26225 +/* These files are created for each detected MATORB. This is just a template;
26226 +   though at first sight, you might think we could use a statically
26227 +   allocated list, we need some way to get back to the parent - which
26228 +   is done through one of the 'extra' fields which are initialized
26229 +   when a new copy is allocated. */
26230 +static ctl_table matorb_dir_table_template[] = {
26231 +       {MATORB_SYSCTL_DISP, "disp", NULL, 0, 0644, NULL, &i2c_proc_real,
26232 +        &i2c_sysctl_real, NULL, &matorb_disp},
26233 +       {0}
26234 +};
26235 +
26236 +static int matorb_id = 0;
26237 +
26238 +static int matorb_attach_adapter(struct i2c_adapter *adapter)
26239 +{
26240 +       return i2c_detect(adapter, &addr_data, matorb_detect);
26241 +}
26242 +
26243 +/* This function is called by i2c_detect */
26244 +int matorb_detect(struct i2c_adapter *adapter, int address,
26245 +                 unsigned short flags, int kind)
26246 +{
26247 +       int i, cur;
26248 +       struct i2c_client *new_client;
26249 +       struct matorb_data *data;
26250 +       int err = 0;
26251 +       const char *type_name = "matorb";
26252 +       const char *client_name = "matorb";
26253 +
26254 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
26255 +          at this moment; i2c_detect really won't call us. */
26256 +#ifdef DEBUG
26257 +       if (i2c_is_isa_adapter(adapter)) {
26258 +               printk
26259 +                   ("matorb.o: matorb_detect called for an ISA bus adapter?!?\n");
26260 +               return 0;
26261 +       }
26262 +#endif
26263 +
26264 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE |
26265 +                                    I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
26266 +                   goto ERROR0;
26267 +
26268 +
26269 +       /* OK. For now, we presume we have a valid client. We now create the
26270 +          client structure, even though we cannot fill it completely yet.
26271 +          But it allows us to access matorb_{read,write}_value. */
26272 +       if (!(data = kmalloc(sizeof(struct matorb_data), GFP_KERNEL))) {
26273 +               err = -ENOMEM;
26274 +               goto ERROR0;
26275 +       }
26276 +
26277 +       new_client = &data->client;
26278 +       new_client->addr = address;
26279 +       new_client->data = data;
26280 +       new_client->adapter = adapter;
26281 +       new_client->driver = &matorb_driver;
26282 +       new_client->flags = 0;
26283 +
26284 +       /* Now, we do the remaining detection. It is lousy. */
26285 +       cur = i2c_smbus_write_byte_data(new_client, 0x0FE, 0x58);       /* clear screen */
26286 +
26287 +       printk("matorb.o: debug detect 0x%X\n", cur);
26288 +
26289 +       /* Fill in the remaining client fields and put it into the global list */
26290 +       strcpy(new_client->name, client_name);
26291 +
26292 +       new_client->id = matorb_id++;
26293 +       data->valid = 0;
26294 +       init_MUTEX(&data->update_lock);
26295 +
26296 +       /* Tell the I2C layer a new client has arrived */
26297 +       if ((err = i2c_attach_client(new_client)))
26298 +               goto ERROR3;
26299 +
26300 +       /* Register a new directory entry with module sensors */
26301 +       if ((i = i2c_register_entry(new_client, type_name,
26302 +                                       matorb_dir_table_template)) < 0) {
26303 +               err = i;
26304 +               goto ERROR4;
26305 +       }
26306 +       data->sysctl_id = i;
26307 +
26308 +       matorb_init_client(new_client);
26309 +       return 0;
26310 +
26311 +/* OK, this is not exactly good programming practice, usually. But it is
26312 +   very code-efficient in this case. */
26313 +
26314 +      ERROR4:
26315 +       i2c_detach_client(new_client);
26316 +      ERROR3:
26317 +       kfree(data);
26318 +      ERROR0:
26319 +       return err;
26320 +}
26321 +
26322 +static int matorb_detach_client(struct i2c_client *client)
26323 +{
26324 +       int err;
26325 +
26326 +       i2c_deregister_entry(((struct matorb_data *) (client->data))->
26327 +                                sysctl_id);
26328 +
26329 +       if ((err = i2c_detach_client(client))) {
26330 +               printk
26331 +                   ("matorb.o: Client deregistration failed, client not detached.\n");
26332 +               return err;
26333 +       }
26334 +
26335 +       kfree(client->data);
26336 +
26337 +       return 0;
26338 +}
26339 +
26340 +
26341 +#if 0
26342 +/* All registers are word-sized, except for the configuration register.
26343 +   MATORB uses a high-byte first convention, which is exactly opposite to
26344 +   the usual practice. */
26345 +static int matorb_read_value(struct i2c_client *client, u8 reg)
26346 +{
26347 +       return -1;              /* Doesn't support reads */
26348 +}
26349 +#endif
26350 +
26351 +/* All registers are word-sized, except for the configuration register.
26352 +   MATORB uses a high-byte first convention, which is exactly opposite to
26353 +   the usual practice. */
26354 +static int matorb_write_value(struct i2c_client *client, u8 reg, u16 value)
26355 +{
26356 +       if (reg == 0) {
26357 +               return i2c_smbus_write_byte(client, value);
26358 +       } else {
26359 +               return i2c_smbus_write_byte_data(client, reg, value);
26360 +       }
26361 +}
26362 +
26363 +static void matorb_init_client(struct i2c_client *client)
26364 +{
26365 +       /* Initialize the MATORB chip */
26366 +}
26367 +
26368 +static void matorb_update_client(struct i2c_client *client)
26369 +{
26370 +       struct matorb_data *data = client->data;
26371 +
26372 +       down(&data->update_lock);
26373 +
26374 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
26375 +           (jiffies < data->last_updated) || !data->valid) {
26376 +
26377 +#ifdef DEBUG
26378 +               printk("Starting matorb update\n");
26379 +#endif
26380 +
26381 +/* nothing yet */
26382 +               data->last_updated = jiffies;
26383 +               data->valid = 1;
26384 +       }
26385 +
26386 +       up(&data->update_lock);
26387 +}
26388 +
26389 +
26390 +void matorb_disp(struct i2c_client *client, int operation, int ctl_name,
26391 +                int *nrels_mag, long *results)
26392 +{
26393 +       int i;
26394 +
26395 +       if (operation == SENSORS_PROC_REAL_INFO)
26396 +               *nrels_mag = 0;
26397 +       else if (operation == SENSORS_PROC_REAL_READ) {
26398 +               matorb_update_client(client);
26399 +               results[0] = 0;
26400 +               *nrels_mag = 3;
26401 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
26402 +               for (i = 1; i <= *nrels_mag; i++) {
26403 +                       matorb_write_value(client, 0, results[i - 1]);
26404 +               }
26405 +       }
26406 +}
26407 +
26408 +static int __init sm_matorb_init(void)
26409 +{
26410 +       printk("matorb.o version %s (%s)\n", LM_VERSION, LM_DATE);
26411 +       return i2c_add_driver(&matorb_driver);
26412 +}
26413 +
26414 +static void __exit sm_matorb_exit(void)
26415 +{
26416 +       i2c_del_driver(&matorb_driver);
26417 +}
26418 +
26419 +
26420 +
26421 +MODULE_AUTHOR
26422 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
26423 +MODULE_DESCRIPTION("MATORB driver");
26424 +
26425 +module_init(sm_matorb_init);
26426 +module_exit(sm_matorb_exit);
26427 --- linux-old/drivers/sensors/max6650.c Thu Jan  1 00:00:00 1970
26428 +++ linux/drivers/sensors/max6650.c     Mon Dec 13 20:18:50 2004
26429 @@ -0,0 +1,545 @@
26430 +/*
26431 + * max6650.c - Part of lm_sensors, Linux kernel modules for hardware
26432 + *             monitoring. 
26433 + * 
26434 + * Author: John Morris <john.morris@spirentcom.com>
26435 + *
26436 + * Copyright (c) 2003 Spirent Communications
26437 + *
26438 + * This module has only been tested with the MAX6651 chip. It should
26439 + * work with the MAX6650 also, though with reduced functionality. It
26440 + * does not yet distinguish max6650 and max6651 chips.
26441 + * 
26442 + * Tha datasheet was last seen at: 
26443 + *
26444 + *        http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
26445 + *
26446 + * This program is free software; you can redistribute it and/or modify
26447 + * it under the terms of the GNU General Public License as published by
26448 + * the Free Software Foundation; either version 2 of the License, or
26449 + * (at your option) any later version.
26450 + *
26451 + * This program is distributed in the hope that it will be useful,
26452 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
26453 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26454 + * GNU General Public License for more details.
26455 + *
26456 + * You should have received a copy of the GNU General Public License
26457 + * along with this program; if not, write to the Free Software
26458 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26459 + */
26460 +
26461 +#include <linux/module.h>
26462 +#include <linux/slab.h>
26463 +#include <linux/i2c.h>
26464 +#include <linux/i2c-proc.h>
26465 +#include <linux/i2c-id.h>
26466 +#include <linux/init.h>
26467 +#define LM_DATE "20041007"
26468 +#define LM_VERSION "2.8.8"
26469 +
26470 +#ifndef I2C_DRIVERID_MAX6650
26471 +#define I2C_DRIVERID_MAX6650   1044
26472 +#endif
26473 +
26474 +/*
26475 + * Addresses to scan. There are four disjoint possibilities, by pin config.
26476 + */
26477 +
26478 +static unsigned short normal_i2c[] = {0x1b, 0x1f, 0x48, 0x4b, SENSORS_I2C_END};
26479 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
26480 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
26481 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
26482 +
26483 +/*
26484 + * Insmod parameters
26485 + */
26486 +
26487 +SENSORS_INSMOD_1(max6650);
26488 +
26489 +/* 
26490 + * MAX 6650/6651 registers
26491 + */
26492 +
26493 +#define MAX6650_REG_SPEED       0x00
26494 +#define MAX6650_REG_CONFIG      0x02
26495 +#define MAX6650_REG_GPIO_DEF    0x04
26496 +#define MAX6650_REG_DAC         0x06
26497 +#define MAX6650_REG_ALARM_EN    0x08
26498 +#define MAX6650_REG_ALARM       0x0A
26499 +#define MAX6650_REG_TACH0       0x0C
26500 +#define MAX6650_REG_TACH1       0x0E
26501 +#define MAX6650_REG_TACH2       0x10
26502 +#define MAX6650_REG_TACH3       0x12
26503 +#define MAX6650_REG_GPIO_STAT   0x14
26504 +#define MAX6650_REG_COUNT       0x16
26505 +
26506 +/*
26507 + * Config register bits
26508 + */
26509
26510 +#define MAX6650_CFG_MODE_MASK           0x30
26511 +#define MAX6650_CFG_MODE_ON             0x00
26512 +#define MAX6650_CFG_MODE_OFF            0x10
26513 +#define MAX6650_CFG_MODE_CLOSED_LOOP    0x20
26514 +#define MAX6650_CFG_MODE_OPEN_LOOP      0x30
26515 +
26516 +static const u8 tach_reg[] = 
26517 +{
26518 +    MAX6650_REG_TACH0, MAX6650_REG_TACH1, 
26519 +    MAX6650_REG_TACH2, MAX6650_REG_TACH3 
26520 +};
26521 +
26522 +#define MAX6650_INT_CLK 254000  /* Default clock speed - 254 kHz */
26523 +
26524 +/*
26525 + * Functions declaration
26526 + */
26527 +
26528 +static void max6650_fan (struct i2c_client *client, int operation, int
26529 +       ctl_name, int *nrels_mag, long *results);
26530 +static void max6650_speed (struct i2c_client *client, int operation, int
26531 +       ctl_name, int *nrels_mag, long *results);
26532 +static void max6650_xdump (struct i2c_client *client, int operation, int
26533 +       ctl_name, int *nrels_mag, long *results);
26534 +static int max6650_detect(struct i2c_adapter *adapter, int address, unsigned
26535 +       short flags, int kind);
26536 +static int max6650_attach_adapter(struct i2c_adapter *adapter);
26537 +static int max6650_detach_client(struct i2c_client *client);
26538 +static void max6650_init_client(struct i2c_client *client);
26539 +static int max6650_read(struct i2c_client *client, u8 reg);
26540 +
26541 +/*
26542 + * Driver data (common to all clients)
26543 + */
26544 +
26545 +
26546 +static struct i2c_driver max6650_driver = {
26547 +    .owner          = THIS_MODULE,
26548 +    .name           = "MAX6650/1 sensor driver",
26549 +    .id             = I2C_DRIVERID_MAX6650,
26550 +    .flags          = I2C_DF_NOTIFY,
26551 +    .attach_adapter = max6650_attach_adapter,
26552 +    .detach_client  = max6650_detach_client
26553 +};
26554 +
26555 +/*
26556 + * Client data (each client gets its own)
26557 + */
26558 +
26559 +struct max6650_data
26560 +{
26561 +       struct i2c_client client;
26562 +    int sysctl_id;
26563 +    struct semaphore update_lock;
26564 +    char valid;                 /* zero until following fields are valid */
26565 +    unsigned long last_updated; /* in jiffies */
26566 +
26567 +    /* register values */
26568 +       
26569 +    u8 speed;
26570 +    u8 config;
26571 +    u8 tach[4];
26572 +    u8 count;
26573 +};
26574 +
26575 +/*
26576 + * Proc entries
26577 + * These files are created for each detected max6650.
26578 + */
26579 +
26580 +/* -- SENSORS SYSCTL START -- */
26581 +
26582 +#define MAX6650_SYSCTL_FAN1     1101
26583 +#define MAX6650_SYSCTL_FAN2     1102
26584 +#define MAX6650_SYSCTL_FAN3     1103
26585 +#define MAX6650_SYSCTL_FAN4     1104
26586 +#define MAX6650_SYSCTL_SPEED    1105
26587 +#define MAX6650_SYSCTL_XDUMP    1106
26588 +
26589 +
26590 +/* -- SENSORS SYSCTL END -- */
26591 +
26592 +
26593 +static ctl_table max6650_dir_table_template[] =
26594 +{
26595 +    {MAX6650_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
26596 +                &i2c_proc_real, &i2c_sysctl_real, NULL, &max6650_fan},
26597 +    {MAX6650_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL,
26598 +                &i2c_proc_real, &i2c_sysctl_real, NULL, &max6650_fan},
26599 +    {MAX6650_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL,
26600 +                &i2c_proc_real, &i2c_sysctl_real, NULL, &max6650_fan},
26601 +    {MAX6650_SYSCTL_FAN4, "fan4", NULL, 0, 0644, NULL,
26602 +                &i2c_proc_real, &i2c_sysctl_real, NULL, &max6650_fan},
26603 +    {MAX6650_SYSCTL_SPEED, "speed", NULL, 0, 0644, NULL,
26604 +                &i2c_proc_real, &i2c_sysctl_real, NULL, &max6650_speed},
26605 +    {MAX6650_SYSCTL_XDUMP, "xdump", NULL, 0, 0644, NULL,
26606 +                &i2c_proc_real, &i2c_sysctl_real, NULL, &max6650_xdump},
26607 +    {0}
26608 +};
26609 +
26610 +/*
26611 + * Internal variables
26612 + */
26613 +
26614 +static int max6650_id = 0;
26615 +
26616 +/*
26617 + * Real code
26618 + */
26619 +
26620 +static int max6650_attach_adapter(struct i2c_adapter *adapter)
26621 +{
26622 +    return i2c_detect(adapter, &addr_data, max6650_detect);
26623 +}
26624 +
26625 +/*
26626 + * The following function does more than just detection. If detection
26627 + * succeeds, it also registers the new chip.
26628 + */
26629 +
26630 +static int max6650_detect(struct i2c_adapter *adapter, int address, unsigned
26631 +       short flags, int kind)
26632 +{
26633 +    struct i2c_client *new_client;
26634 +    struct max6650_data *data;
26635 +    int err = 0;
26636 +    const char *type_name = "";
26637 +    const char *client_name = "";
26638 +
26639 +#ifdef DEBUG
26640 +    if (i2c_is_isa_adapter(adapter)) {
26641 +        printk("max6650.o: Called for an ISA bus adapter, aborting.\n");
26642 +        return 0;
26643 +    }
26644 +#endif
26645 +
26646 +    if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
26647 +#ifdef DEBUG
26648 +        printk("max6650.o: I2C bus doesn't support byte read mode, skipping.\n");
26649 +#endif
26650 +        return 0;
26651 +    }
26652 +
26653 +    if (!(data = kmalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
26654 +        printk("max6650.o: Out of memory in max6650_detect (new_client).\n");
26655 +        return -ENOMEM;
26656 +    }
26657 +
26658 +    /*
26659 +     * The common I2C client data is placed right before the
26660 +     * max6650-specific data. The max6650-specific data is pointed to by the
26661 +        * data field from the I2C client data.
26662 +     */
26663 +
26664 +       new_client = &data->client;
26665 +    new_client->addr = address;
26666 +    new_client->data = data;
26667 +    new_client->adapter = adapter;
26668 +    new_client->driver = &max6650_driver;
26669 +    new_client->flags = 0;
26670 +
26671 +    /*
26672 +     * Now we do the remaining detection. A negative kind means that
26673 +     * the driver was loaded with no force parameter (default), so we
26674 +     * must both detect and identify the chip (actually there is only
26675 +     * one possible kind of chip for now, max6650). A zero kind means that
26676 +     * the driver was loaded with the force parameter, the detection
26677 +     * step shall be skipped. A positive kind means that the driver
26678 +     * was loaded with the force parameter and a given kind of chip is
26679 +     * requested, so both the detection and the identification steps
26680 +     * are skipped.
26681 +     *
26682 +     * Currently I can find no way to distinguish between a MAX6650 and 
26683 +     * a MAX6651. This driver has only been tried on the latter.
26684 +     */
26685 +
26686 +    if (kind < 0) {     /* detection */
26687 +        if (
26688 +            (max6650_read(new_client, MAX6650_REG_CONFIG) & 0xC0) ||
26689 +            (max6650_read(new_client, MAX6650_REG_GPIO_STAT) & 0xE0) ||
26690 +            (max6650_read(new_client, MAX6650_REG_ALARM_EN) & 0xE0) ||
26691 +            (max6650_read(new_client, MAX6650_REG_ALARM) & 0xE0) ||
26692 +            (max6650_read(new_client, MAX6650_REG_COUNT) & 0xFC) 
26693 +        )
26694 +        {
26695 +#ifdef DEBUG
26696 +            printk("max6650.o: max6650 detection failed at 0x%02x.\n",
26697 +                                                                    address);
26698 +#endif
26699 +            goto ERROR1;
26700 +        }
26701 +    }
26702 +
26703 +    if (kind <= 0) { /* identification */
26704 +        kind = max6650;
26705 +    }
26706 +
26707 +    if (kind <= 0) {    /* identification failed */
26708 +        printk("max6650.o: Unsupported chip.\n");
26709 +        goto ERROR1;
26710 +    }
26711 +
26712 +    if (kind == max6650) {
26713 +        type_name = "max6650";
26714 +        client_name = "max6650 chip";
26715 +    } else {
26716 +        printk("max6650.o: Unknown kind %d.\n", kind);
26717 +        goto ERROR1;
26718 +    }
26719 +       
26720 +    /*
26721 +     * OK, we got a valid chip so we can fill in the remaining client
26722 +     * fields.
26723 +     */
26724 +
26725 +    strcpy(new_client->name, client_name);
26726 +    new_client->id = max6650_id++;
26727 +    data->valid = 0;
26728 +    init_MUTEX(&data->update_lock);
26729 +
26730 +    /*
26731 +     * Tell the I2C layer a new client has arrived.
26732 +     */
26733 +
26734 +    if ((err = i2c_attach_client(new_client))) {
26735 +#ifdef DEBUG
26736 +        printk("max6650.o: Failed attaching client.\n");
26737 +#endif
26738 +        goto ERROR1;
26739 +    }
26740 +
26741 +    /*
26742 +     * Register a new directory entry.
26743 +     */
26744 +    if ((err = i2c_register_entry(new_client, type_name,
26745 +                                    max6650_dir_table_template)) < 0) {
26746 +#ifdef DEBUG
26747 +        printk("max6650.o: Failed registering directory entry.\n");
26748 +#endif
26749 +        goto ERROR2;
26750 +    }
26751 +    data->sysctl_id = err;
26752 +
26753 +    /*
26754 +     * Initialize the max6650 chip
26755 +     */
26756 +    max6650_init_client(new_client);
26757 +    return 0;
26758 +
26759 +ERROR2:
26760 +    i2c_detach_client(new_client);
26761 +ERROR1:
26762 +    kfree(data);
26763 +    return err;
26764 +}
26765 +
26766 +static void max6650_init_client(struct i2c_client *client)
26767 +{
26768 +    /* Nothing to do here - assume the BIOS has initialized the chip */
26769 +}
26770 +
26771 +static int max6650_detach_client(struct i2c_client *client)
26772 +{
26773 +    int err;
26774 +
26775 +    i2c_deregister_entry(((struct max6650_data *) (client->data))->sysctl_id);
26776 +    if ((err = i2c_detach_client(client))) {
26777 +        printk("max6650.o: Client deregistration failed, "
26778 +                                        "client not detached.\n");
26779 +        return err;
26780 +    }
26781 +
26782 +    kfree(client->data);
26783 +    return 0;
26784 +}
26785 +
26786 +static int max6650_read(struct i2c_client *client, u8 reg)
26787 +{
26788 +    return i2c_smbus_read_byte_data(client, reg);
26789 +}
26790 +
26791 +static int max6650_write(struct i2c_client *client, u8 reg, u8 value)
26792 +{
26793 +    return i2c_smbus_write_byte_data(client, reg, value);
26794 +}
26795 +
26796 +static void max6650_update_client(struct i2c_client *client)
26797 +{
26798 +    int i;
26799 +    struct max6650_data *data = client->data;
26800 +
26801 +    down(&data->update_lock);
26802 +    
26803 +    if ((jiffies - data->last_updated > HZ) ||
26804 +        (jiffies < data->last_updated) || !data->valid) {
26805 +#ifdef DEBUG
26806 +        printk("max6650.o: Updating max6650 data.\n");
26807 +#endif
26808 +        data->speed  = max6650_read (client, MAX6650_REG_SPEED);
26809 +        data->config = max6650_read (client, MAX6650_REG_CONFIG);
26810 +        for (i = 0; i < 4; i++) {
26811 +            data->tach[i] = max6650_read(client, tach_reg[i]);
26812 +        }
26813 +        data->count = max6650_read (client, MAX6650_REG_COUNT);
26814 +        data->last_updated = jiffies;
26815 +        data->valid = 1;
26816 +    }
26817 +    up(&data->update_lock);
26818 +}
26819 +
26820 +static void max6650_fan (struct i2c_client *client, int operation, int
26821 +       ctl_name, int *nrels_mag, long *results)
26822 +{
26823 +    int index = ctl_name - MAX6650_SYSCTL_FAN1;
26824 +    struct max6650_data *data = client->data;
26825 +    int tcount;         /* Tachometer count time, 0.25 second units */
26826 +
26827 +    if (operation == SENSORS_PROC_REAL_INFO) {
26828 +       *nrels_mag = 0;
26829 +    } else if (operation == SENSORS_PROC_REAL_READ) {
26830 +        max6650_update_client(client);
26831 +
26832 +        /*
26833 +         * Calculation details:
26834 +         *
26835 +         * Each tachometer counts over an interval given by the "count"
26836 +         * register (0.25, 0.5, 1 or 2 seconds). This module assumes
26837 +         * that the fans produce two pulses per revolution (this seems
26838 +         * to be the most common).
26839 +         */
26840 +         
26841 +        tcount = 1 << data->count;         /* 0.25 second units */
26842 +        results[0] = (data->tach[index] * 240) / tcount;    /* counts per min */
26843 +        results[0] /= 2;                   /* Assume two counts per rev */
26844 +        *nrels_mag = 1;
26845 +    }
26846 +}
26847 +
26848 +/*
26849 + * Set the fan speed to the specified RPM (or read back the RPM setting).
26850 + *
26851 + * The MAX6650/1 will automatically control fan speed when in closed loop
26852 + * mode.
26853 + *
26854 + * Assumptions:
26855 + *
26856 + * 1) The MAX6650/1 is running from its internal 254kHz clock (perhaps
26857 + *    this should be made a module parameter).
26858 + *
26859 + * 2) The prescaler (low three bits of the config register) has already
26860 + *    been set to an appropriate value.
26861 + *
26862 + * The relevant equations are given on pages 21 and 22 of the datasheet.
26863 + *
26864 + * From the datasheet, the relevant equation when in regulation is:
26865 + *
26866 + *    [fCLK / (128 x (KTACH + 1))] = 2 x FanSpeed / KSCALE
26867 + *
26868 + * where:
26869 + *
26870 + *    fCLK is the oscillator frequency (either the 254kHz internal 
26871 + *         oscillator or the externally applied clock)
26872 + *
26873 + *    KTACH is the value in the speed register
26874 + *
26875 + *    FanSpeed is the speed of the fan in rps
26876 + *
26877 + *    KSCALE is the prescaler value (1, 2, 4, 8, or 16)
26878 + *
26879 + * When reading, we need to solve for FanSpeed. When writing, we need to
26880 + * solve for KTACH.
26881 + *
26882 + * Note: this tachometer is completely separate from the tachometers
26883 + * used to measure the fan speeds. Only one fan's speed (fan1) is
26884 + * controlled.
26885 + */
26886 +
26887 +static void max6650_speed (struct i2c_client *client, int operation, int
26888 +                               ctl_name, int *nrels_mag, long *results)
26889 +{
26890 +    struct max6650_data *data = client->data;
26891 +    int kscale, ktach, fclk, rpm;
26892 +    
26893 +    if (operation == SENSORS_PROC_REAL_INFO) {
26894 +        *nrels_mag = 0;
26895 +    } else if (operation == SENSORS_PROC_REAL_READ) {
26896 +        /*
26897 +         * Use the datasheet equation:
26898 +         *
26899 +         *    FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)]
26900 +         *
26901 +         * then multiply by 60 to give rpm.
26902 +         */
26903 +
26904 +        max6650_update_client(client);
26905 +
26906 +        kscale = 1 << (data->config & 7);
26907 +        ktach  = data->speed;
26908 +        fclk   = MAX6650_INT_CLK;
26909 +        rpm    = 60 * kscale * fclk / (256 * (ktach + 1));
26910 +
26911 +        results[0] = rpm;
26912 +        *nrels_mag = 1;
26913 +    } else if (operation == SENSORS_PROC_REAL_WRITE && *nrels_mag >= 1) {
26914 +        /*
26915 +         * Divide the required speed by 60 to get from rpm to rps, then
26916 +         * use the datasheet equation:
26917 +         *
26918 +         *     KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1
26919 +         */
26920 +
26921 +        max6650_update_client(client);
26922 +
26923 +        rpm    = results[0];
26924 +        kscale = 1 << (data->config & 7);
26925 +        fclk   = MAX6650_INT_CLK;
26926 +        ktach  = ((fclk * kscale) / (256 * rpm / 60)) - 1;
26927 +
26928 +        data->speed  = ktach;
26929 +        data->config = (data->config & ~MAX6650_CFG_MODE_MASK) | 
26930 +                                            MAX6650_CFG_MODE_CLOSED_LOOP;
26931 +        max6650_write (client, MAX6650_REG_CONFIG, data->config);
26932 +        max6650_write (client, MAX6650_REG_SPEED,  data->speed);
26933 +    }
26934 +}
26935 +
26936 +/*
26937 + * Debug - dump all registers except the tach counts.
26938 + */
26939 +                                 
26940 +static void max6650_xdump (struct i2c_client *client, int operation, int
26941 +       ctl_name, int *nrels_mag, long *results)
26942 +{
26943 +    if (operation == SENSORS_PROC_REAL_INFO) {
26944 +        *nrels_mag = 0;
26945 +    } else if (operation == SENSORS_PROC_REAL_READ) {
26946 +        results[0] = max6650_read (client, MAX6650_REG_SPEED);
26947 +        results[1] = max6650_read (client, MAX6650_REG_CONFIG);
26948 +        results[2] = max6650_read (client, MAX6650_REG_GPIO_DEF);
26949 +        results[3] = max6650_read (client, MAX6650_REG_DAC);
26950 +        results[4] = max6650_read (client, MAX6650_REG_ALARM_EN);
26951 +        results[5] = max6650_read (client, MAX6650_REG_ALARM);
26952 +        results[6] = max6650_read (client, MAX6650_REG_GPIO_STAT);
26953 +        results[7] = max6650_read (client, MAX6650_REG_COUNT);
26954 +        *nrels_mag = 8;
26955 +    }
26956 +}
26957 +
26958 +static int __init sm_max6650_init(void)
26959 +{
26960 +    printk(KERN_INFO "max6650.o version %s (%s)\n", LM_VERSION, LM_DATE);
26961 +    return i2c_add_driver(&max6650_driver);
26962 +}
26963 +
26964 +static void __exit sm_max6650_exit(void)
26965 +{
26966 +    i2c_del_driver(&max6650_driver);
26967 +}
26968 +
26969 +MODULE_AUTHOR("john.morris@spirentcom.com");
26970 +MODULE_DESCRIPTION("max6650 sensor driver");
26971 +MODULE_LICENSE("GPL");
26972 +
26973 +module_init(sm_max6650_init);
26974 +module_exit(sm_max6650_exit);
26975 --- linux-old/drivers/sensors/maxilife.c        Thu Jan  1 00:00:00 1970
26976 +++ linux/drivers/sensors/maxilife.c    Mon Dec 13 20:18:50 2004
26977 @@ -0,0 +1,1387 @@
26978 +/*
26979 +    maxilife.c - Part of lm_sensors, Linux kernel modules for hardware
26980 +                 monitoring
26981 +    Copyright (c) 1999-2000 Fons Rademakers <Fons.Rademakers@cern.ch> 
26982 +
26983 +    This program is free software; you can redistribute it and/or modify
26984 +    it under the terms of the GNU General Public License as published by
26985 +    the Free Software Foundation; either version 2 of the License, or
26986 +    (at your option) any later version.
26987 +
26988 +    This program is distributed in the hope that it will be useful,
26989 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
26990 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26991 +    GNU General Public License for more details.
26992 +
26993 +    You should have received a copy of the GNU General Public License
26994 +    along with this program; if not, write to the Free Software
26995 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26996 +*/
26997 +
26998 +/* The is the driver for the HP MaxiLife Health monitoring system
26999 +   as used in the line of HP Kayak Workstation PC's.
27000 +   
27001 +   The driver supports the following MaxiLife firmware versions:
27002 +   
27003 +   0) HP KAYAK XU/XAs (Dual Pentium II Slot 1, Deschutes/Klamath)
27004 +   1) HP KAYAK XU (Dual Xeon [Slot 2] 400/450 Mhz)
27005 +   2) HP KAYAK XA (Pentium II Slot 1, monoprocessor)
27006 +   
27007 +   Currently firmware auto detection is not implemented. To use the
27008 +   driver load it with the correct option for you Kayak. For example:
27009 +   
27010 +   insmod maxilife.o maxi_version=0 | 1 | 2
27011 +   
27012 +   maxi_version=0 is the default
27013 +   
27014 +   This version of MaxiLife is called MaxiLife'98 and has been
27015 +   succeeded by MaxiLife'99, see below.
27016 +   
27017 +   The new version of the driver also supports MaxiLife NBA (New BIOS
27018 +   Architecture). This new MaxiLife controller provides a much cleaner
27019 +   machine independent abstraction layer to the MaxiLife controller.
27020 +   Instead of accessing directly registers (different for each revision)
27021 +   one now accesses the sensors via unique mailbox tokens that do not
27022 +   change between revisions. Also the quantities are already in physical
27023 +   units (degrees, rpms, voltages, etc.) and don't need special conversion
27024 +   formulas. This new MaxiLife is available on the new 2000 machines,
27025 +   like the Kayak XU800 and XM600. This hardware is also autodetected.
27026 +*/
27027 +
27028 +static const char *version_str = "2.00 29/2/2000 Fons Rademakers";
27029 +
27030 +
27031 +#include <linux/module.h>
27032 +#include <linux/slab.h>
27033 +#include <linux/i2c.h>
27034 +#include <linux/i2c-proc.h>
27035 +#include <linux/init.h>
27036 +#define LM_DATE "20041007"
27037 +#define LM_VERSION "2.8.8"
27038 +
27039 +MODULE_LICENSE("GPL");
27040 +
27041 +#undef AUTODETECT              /* try to autodetect MaxiLife version */
27042 +/*#define AUTODETECT*/
27043 +#define NOWRITE                        /* don't allow writing to MaxiLife registers */
27044 +
27045 +#ifdef AUTODETECT
27046 +#include <linux/vmalloc.h>
27047 +#include <linux/ctype.h>
27048 +#endif
27049 +
27050 +/* Addresses to scan */
27051 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
27052 +static unsigned short normal_i2c_range[] = { 0x10, 0x14, SENSORS_I2C_END };
27053 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
27054 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
27055 +
27056 +/* Insmod parameters */
27057 +SENSORS_INSMOD_1(maxilife);
27058 +
27059 +/* Macro definitions */
27060 +#define LOW(MyWord) ((u8) (MyWord))
27061 +#define HIGH(MyWord) ((u8) (((u16)(MyWord) >> 8) & 0xFF))
27062 +
27063 +/*----------------- MaxiLife'98 registers and conversion formulas ------------*/
27064 +#define MAXI_REG_TEMP(nr)      (0x60 + (nr))
27065 +
27066 +#define MAXI_REG_FAN(nr)       (0x65 + (nr))
27067 +#define MAXI_REG_FAN_MIN(nr)   ((nr)==0 ? 0xb3 : (nr)==1 ? 0xb3 : 0xab)
27068 +#define MAXI_REG_FAN_MINAS(nr) ((nr)==0 ? 0xb3 : (nr)==1 ? 0xab : 0xb3)
27069 +#define MAXI_REG_FAN_SPEED(nr) ((nr)==0 ? 0xe4 : (nr)==1 ? 0xe5 : 0xe9)
27070 +
27071 +#define MAXI_REG_PLL           0xb9
27072 +#define MAXI_REG_PLL_MIN       0xba
27073 +#define MAXI_REG_PLL_MAX       0xbb
27074 +
27075 +#define MAXI_REG_VID(nr)       ((nr)==0 ? 0xd1 : (nr)==1 ? 0xd9 : \
27076 +                                (nr)==2 ? 0xd4 : 0xc5)
27077 +#define MAXI_REG_VID_MIN(nr)   MAXI_REG_VID(nr)+1
27078 +#define MAXI_REG_VID_MAX(nr)   MAXI_REG_VID(nr)+2
27079 +
27080 +#define MAXI_REG_DIAG_RT1      0x2c
27081 +#define MAXI_REG_DIAG_RT2      0x2d
27082 +
27083 +#define MAXI_REG_BIOS_CTRL     0x2a
27084 +
27085 +/* Conversions. Rounding and limit checking is only done on the TO_REG
27086 +   variants. Note that you should be a bit careful with which arguments
27087 +   these macros are called: arguments may be evaluated more than once.
27088 +   Fixing this is just not worth it. */
27089 +
27090 +                              /* 0xfe: fan off, 0xff: stopped (alarm) */
27091 +                              /* 19531 / val * 60 == 1171860 / val */
27092 +#define FAN_FROM_REG(val)      ((val)==0xfe ? 0 : (val)==0xff ? -1 : \
27093 +                                (val)==0x00 ? -1 : (1171860 / (val)))
27094 +
27095 +static inline u8 FAN_TO_REG(long rpm)
27096 +{
27097 +       if (rpm == 0)
27098 +               return 255;
27099 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
27100 +       return SENSORS_LIMIT((1171860 + rpm / 2) / (rpm), 1, 254);
27101 +}
27102 +
27103 +#define TEMP_FROM_REG(val)     ((val) * 5)
27104 +#define TEMP_TO_REG(val)       (SENSORS_LIMIT((val+2) / 5),0,0xff)
27105 +#define PLL_FROM_REG(val)      (((val) * 1000) / 32)
27106 +#define PLL_TO_REG(val)        (SENSORS_LIMIT((((val) * 32 + 500) / 1000),\
27107 +                                              0,0xff))
27108 +#define VID_FROM_REG(val)      ((val) ? (((val) * 27390) / 256) + 3208 : 0)
27109 +#define VID_TO_REG(val)        (SENSORS_LIMIT((((val) - 3208) * 256) / 27390, \
27110 +                                              0,255))
27111 +#define ALARMS_FROM_REG(val)   (val)
27112 +
27113 +/*----------------- MaxiLife'99 mailbox and token definitions ----------------*/
27114 +/* MaxiLife mailbox data register map */
27115 +#define MAXI_REG_MBX_STATUS    0x5a
27116 +#define MAXI_REG_MBX_CMD       0x5b
27117 +#define MAXI_REG_MBX_TOKEN_H   0x5c
27118 +#define MAXI_REG_MBX_TOKEN_L   0x5d
27119 +#define MAXI_REG_MBX_DATA      0x60
27120 +
27121 +/* Mailbox status register definition */
27122 +#define MAXI_STAT_IDLE         0xff
27123 +#define MAXI_STAT_OK           0x00
27124 +#define MAXI_STAT_BUSY         0x0b
27125 +/* other values not used */
27126 +
27127 +/* Mailbox command register opcodes */
27128 +#define MAXI_CMD_READ          0x02
27129 +#define MAXI_CMD_WRITE         0x03
27130 +/* other values not used */
27131 +
27132 +/* MaxiLife NBA Hardware monitoring tokens */
27133 +
27134 +/* Alarm tokens (0x1xxx) */
27135 +#define MAXI_TOK_ALARM(nr)    (0x1000 + (nr))
27136 +#define MAXI_TOK_ALARM_EVENT   0x1000
27137 +#define MAXI_TOK_ALARM_FAN     0x1001
27138 +#define MAXI_TOK_ALARM_TEMP    0x1002
27139 +#define MAXI_TOK_ALARM_VID     0x1003  /* voltages */
27140 +#define MAXI_TOK_ALARM_AVID    0x1004  /* additional voltages */
27141 +#define MAXI_TOK_ALARM_PWR     0x1101  /* power supply glitch */
27142 +
27143 +/* Fan status tokens (0x20xx) */
27144 +#define MAXI_TOK_FAN(nr)      (0x2000 + (nr))
27145 +#define MAXI_TOK_FAN_CPU       0x2000
27146 +#define MAXI_TOK_FAN_PCI       0x2001
27147 +#define MAXI_TOK_FAN_HDD       0x2002  /* hard disk bay fan */
27148 +#define MAXI_TOK_FAN_SINK      0x2003  /* heatsink */
27149 +
27150 +/* Temperature status tokens (0x21xx) */
27151 +#define MAXI_TOK_TEMP(nr)     (0x2100 + (nr))
27152 +#define MAXI_TOK_TEMP_CPU1     0x2100
27153 +#define MAXI_TOK_TEMP_CPU2     0x2101
27154 +#define MAXI_TOK_TEMP_PCI      0x2102  /* PCI/ambient temp */
27155 +#define MAXI_TOK_TEMP_HDD      0x2103  /* hard disk bay temp */
27156 +#define MAXI_TOK_TEMP_MEM      0x2104  /* mother board temp */
27157 +#define MAXI_TOK_TEMP_CPU      0x2105  /* CPU reference temp */
27158 +
27159 +/* Voltage status tokens (0x22xx) */
27160 +#define MAXI_TOK_VID(nr)      (0x2200 + (nr))
27161 +#define MAXI_TOK_VID_12        0x2200  /* +12 volt */
27162 +#define MAXI_TOK_VID_CPU1      0x2201  /* cpu 1 voltage */
27163 +#define MAXI_TOK_VID_CPU2      0x2202  /* cpu 2 voltage */
27164 +#define MAXI_TOK_VID_L2        0x2203  /* level 2 cache voltage */
27165 +#define MAXI_TOK_VID_M12       0x2204  /* -12 volt */
27166 +
27167 +/* Additive voltage status tokens (0x23xx) */
27168 +#define MAXI_TOK_AVID(nr)     (0x2300 + (nr))
27169 +#define MAXI_TOK_AVID_15       0x2300  /* 1.5 volt */
27170 +#define MAXI_TOK_AVID_18       0x2301  /* 1.8 volt */
27171 +#define MAXI_TOK_AVID_25       0x2302  /* 2.5 volt */
27172 +#define MAXI_TOK_AVID_33       0x2303  /* 3.3 volt */
27173 +#define MAXI_TOK_AVID_5        0x2304  /* 5 volt */
27174 +#define MAXI_TOK_AVID_M5       0x2305  /* -5 volt */
27175 +#define MAXI_TOK_AVID_BAT      0x2306  /* battery voltage */
27176 +
27177 +/* Threshold tokens (0x3xxx) */
27178 +#define MAXI_TOK_MIN(token)    ((token) + 0x1000)
27179 +#define MAXI_TOK_MAX(token)    ((token) + 0x1800)
27180 +
27181 +/* LCD Panel (0x4xxx) */
27182 +#define MAXI_TOK_LCD(nr)      (0x4000 + (nr))
27183 +#define MAXI_TOK_LCD_LINE1     0x4000
27184 +#define MAXI_TOK_LCD_LINE2     0x4001
27185 +#define MAXI_TOK_LCD_LINE3     0x4002
27186 +#define MAXI_TOK_LCD_LINE4     0x4003
27187 +
27188 +                              /* 0xfe: fan off, 0xff: stopped (alarm) */
27189 +                              /* or not available */
27190 +#define FAN99_FROM_REG(val)    ((val)==0xfe ? 0 : (val)==0xff ? -1 : ((val)*39))
27191 +
27192 +                              /* when no CPU2 temp is 127 (0x7f) */
27193 +#define TEMP99_FROM_REG(val)   ((val)==0x7f ? -1 : (val)==0xff ? -1 : (val))
27194 +
27195 +#define VID99_FROM_REG(nr,val) ((val)==0xff ? 0 : \
27196 +                                (nr)==1 ? ((val) * 608) : \
27197 +                                (nr)==2 ? ((val) * 160) : \
27198 +                                (nr)==3 ? ((val) * 160) : \
27199 +                                (nr)==4 ? (val) /* no formula spcified */ : \
27200 +                                (nr)==5 ? ((val) * 823 - 149140) : 0)
27201 +
27202 +
27203 +/* The following product codenames apply:
27204 +     Cristal/Geronimo: HP KAYAK XU/XAs
27205 +                       (Dual Pentium II Slot 1, Deschutes/Klamath)
27206 +     Cognac: HP KAYAK XU (Dual Xeon [Slot 2] 400/450 Mhz)
27207 +     Ashaki: HP KAYAK XA (Pentium II Slot 1, monoprocessor)
27208 +     NBA:    New BIOS Architecture, Kayak XU800, XM600, ... */
27209 +
27210 +enum maxi_type { cristal, cognac, ashaki, nba };
27211 +enum sensor_type { fan, temp, vid, pll, lcd, alarm };
27212 +
27213 +/* For each registered MaxiLife controller, we need to keep some data in
27214 +   memory. That data is pointed to by maxi_list[NR]->data. The structure
27215 +   itself is dynamically allocated, at the same time when a new MaxiLife
27216 +   client is allocated. We assume MaxiLife will only be present on the
27217 +   SMBus and not on the ISA bus. */
27218 +struct maxi_data {
27219 +       struct i2c_client client;
27220 +       struct semaphore lock;
27221 +       int sysctl_id;
27222 +       enum maxi_type type;
27223 +
27224 +       struct semaphore update_lock;
27225 +       char valid;             /* !=0 if following fields are valid */
27226 +       unsigned long last_updated;     /* In jiffies */
27227 +
27228 +       u8 fan[4];              /* Register value */
27229 +       u8 fan_min[4];          /* Register value */
27230 +       u8 fan_speed[4];        /* Register value */
27231 +       u8 fan_div[4];          /* Static value */
27232 +       u8 temp[6];             /* Register value */
27233 +       u8 temp_max[6];         /* Static value */
27234 +       u8 temp_hyst[6];        /* Static value */
27235 +       u8 pll;                 /* Register value */
27236 +       u8 pll_min;             /* Register value */
27237 +       u8 pll_max;             /* register value */
27238 +       u8 vid[5];              /* Register value */
27239 +       u8 vid_min[5];          /* Register value */
27240 +       u8 vid_max[5];          /* Register value */
27241 +       u8 lcd[4][17];          /* Four LCD lines */
27242 +       u16 alarms;             /* Register encoding, combined */
27243 +};
27244 +
27245 +
27246 +static int maxi_attach_adapter(struct i2c_adapter *adapter);
27247 +static int maxi_detect(struct i2c_adapter *adapter, int address,
27248 +                      unsigned short flags, int kind);
27249 +static int maxi_detach_client(struct i2c_client *client);
27250 +
27251 +static int maxi_read_value(struct i2c_client *client, u8 register);
27252 +static int maxi_read_token(struct i2c_client *client, u16 token);
27253 +#ifndef NOWRITE
27254 +static int maxi_write_value(struct i2c_client *client, u8 register,
27255 +                           u8 value);
27256 +#endif
27257 +static int maxi_write_token_loop(struct i2c_client *client, u16 token,
27258 +                                u8 len, u8 * values);
27259 +
27260 +static void maxi_update_client(struct i2c_client *client);
27261 +static void maxi99_update_client(struct i2c_client *client,
27262 +                                enum sensor_type sensor, int which);
27263 +static void maxi_init_client(struct i2c_client *client);
27264 +
27265 +static void maxi_fan(struct i2c_client *client, int operation,
27266 +                    int ctl_name, int *nrels_mag, long *results);
27267 +static void maxi99_fan(struct i2c_client *client, int operation,
27268 +                      int ctl_name, int *nrels_mag, long *results);
27269 +static void maxi_temp(struct i2c_client *client, int operation,
27270 +                     int ctl_name, int *nrels_mag, long *results);
27271 +static void maxi99_temp(struct i2c_client *client, int operation,
27272 +                       int ctl_name, int *nrels_mag, long *results);
27273 +static void maxi_pll(struct i2c_client *client, int operation,
27274 +                    int ctl_name, int *nrels_mag, long *results);
27275 +static void maxi_vid(struct i2c_client *client, int operation,
27276 +                    int ctl_name, int *nrels_mag, long *results);
27277 +static void maxi99_vid(struct i2c_client *client, int operation,
27278 +                      int ctl_name, int *nrels_mag, long *results);
27279 +static void maxi_lcd(struct i2c_client *client, int operation,
27280 +                    int ctl_name, int *nrels_mag, long *results);
27281 +static void maxi_alarms(struct i2c_client *client, int operation,
27282 +                       int ctl_name, int *nrels_mag, long *results);
27283 +
27284 +/* The driver. I choose to use type i2c_driver, as at is identical to
27285 +   the smbus_driver. */
27286 +static struct i2c_driver maxi_driver = {
27287 +       .owner          = THIS_MODULE,
27288 +       .name           = "HP MaxiLife driver",
27289 +       .id             = I2C_DRIVERID_MAXILIFE,
27290 +       .flags          = I2C_DF_NOTIFY,
27291 +       .attach_adapter = maxi_attach_adapter,
27292 +       .detach_client  = maxi_detach_client,
27293 +};
27294 +
27295 +static int maxi_id = 0;
27296 +
27297 +/* Default firmware version. Use module option "maxi_version"
27298 +   to set desired version. Auto detect is not yet working */
27299 +static int maxi_version = cristal;
27300 +
27301 +/* The /proc/sys entries */
27302 +
27303 +/* -- SENSORS SYSCTL START -- */
27304 +#define MAXI_SYSCTL_FAN1   1101        /* Rotations/min */
27305 +#define MAXI_SYSCTL_FAN2   1102        /* Rotations/min */
27306 +#define MAXI_SYSCTL_FAN3   1103        /* Rotations/min */
27307 +#define MAXI_SYSCTL_FAN4   1104        /* Rotations/min */
27308 +#define MAXI_SYSCTL_TEMP1  1201        /* Degrees Celcius */
27309 +#define MAXI_SYSCTL_TEMP2  1202        /* Degrees Celcius */
27310 +#define MAXI_SYSCTL_TEMP3  1203        /* Degrees Celcius */
27311 +#define MAXI_SYSCTL_TEMP4  1204        /* Degrees Celcius */
27312 +#define MAXI_SYSCTL_TEMP5  1205        /* Degrees Celcius */
27313 +#define MAXI_SYSCTL_TEMP6  1206        /* Degrees Celcius */
27314 +#define MAXI_SYSCTL_PLL    1301        /* MHz */
27315 +#define MAXI_SYSCTL_VID1   1401        /* Volts / 6.337, for nba just Volts */
27316 +#define MAXI_SYSCTL_VID2   1402        /* Volts */
27317 +#define MAXI_SYSCTL_VID3   1403        /* Volts */
27318 +#define MAXI_SYSCTL_VID4   1404        /* Volts */
27319 +#define MAXI_SYSCTL_VID5   1405        /* Volts */
27320 +#define MAXI_SYSCTL_LCD1   1501        /* Line 1 of LCD */
27321 +#define MAXI_SYSCTL_LCD2   1502        /* Line 2 of LCD */
27322 +#define MAXI_SYSCTL_LCD3   1503        /* Line 3 of LCD */
27323 +#define MAXI_SYSCTL_LCD4   1504        /* Line 4 of LCD */
27324 +#define MAXI_SYSCTL_ALARMS 2001        /* Bitvector (see below) */
27325 +
27326 +#define MAXI_ALARM_VID4      0x0001
27327 +#define MAXI_ALARM_TEMP2     0x0002
27328 +#define MAXI_ALARM_VID1      0x0004
27329 +#define MAXI_ALARM_VID2      0x0008
27330 +#define MAXI_ALARM_VID3      0x0010
27331 +#define MAXI_ALARM_PLL       0x0080
27332 +#define MAXI_ALARM_TEMP4     0x0100
27333 +#define MAXI_ALARM_TEMP5     0x0200
27334 +#define MAXI_ALARM_FAN1      0x1000
27335 +#define MAXI_ALARM_FAN2      0x2000
27336 +#define MAXI_ALARM_FAN3      0x4000
27337 +
27338 +#define MAXI_ALARM_FAN       0x0100    /* To be used with  MaxiLife'99 */
27339 +#define MAXI_ALARM_VID       0x0200    /* The MSB specifies which sensor */
27340 +#define MAXI_ALARM_TEMP      0x0400    /* in the alarm group failed, i.e.: */
27341 +#define MAXI_ALARM_VADD      0x0800    /* 0x0402 = TEMP2 failed = CPU2 temp */
27342 +
27343 +/* -- SENSORS SYSCTL END -- */
27344 +
27345 +/* These files are created for each detected MaxiLife processor.
27346 +   This is just a template; though at first sight, you might think we
27347 +   could use a statically allocated list, we need some way to get back
27348 +   to the parent - which is done through one of the 'extra' fields 
27349 +   which are initialized when a new copy is allocated. */
27350 +static ctl_table maxi_dir_table_template[] = {
27351 +       {MAXI_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
27352 +        &i2c_sysctl_real, NULL, &maxi_fan},
27353 +       {MAXI_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
27354 +        &i2c_sysctl_real, NULL, &maxi_fan},
27355 +       {MAXI_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
27356 +        &i2c_sysctl_real, NULL, &maxi_fan},
27357 +       {MAXI_SYSCTL_FAN4, "fan4", NULL, 0, 0644, NULL, &i2c_proc_real,
27358 +        &i2c_sysctl_real, NULL, &maxi_fan},
27359 +       {MAXI_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
27360 +        &i2c_sysctl_real, NULL, &maxi_temp},
27361 +       {MAXI_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
27362 +        &i2c_sysctl_real, NULL, &maxi_temp},
27363 +       {MAXI_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
27364 +        &i2c_sysctl_real, NULL, &maxi_temp},
27365 +       {MAXI_SYSCTL_TEMP4, "temp4", NULL, 0, 0644, NULL, &i2c_proc_real,
27366 +        &i2c_sysctl_real, NULL, &maxi_temp},
27367 +       {MAXI_SYSCTL_TEMP5, "temp5", NULL, 0, 0644, NULL, &i2c_proc_real,
27368 +        &i2c_sysctl_real, NULL, &maxi_temp},
27369 +       {MAXI_SYSCTL_TEMP6, "temp6", NULL, 0, 0644, NULL, &i2c_proc_real,
27370 +        &i2c_sysctl_real, NULL, &maxi_temp},
27371 +       {MAXI_SYSCTL_PLL, "pll", NULL, 0, 0644, NULL, &i2c_proc_real,
27372 +        &i2c_sysctl_real, NULL, &maxi_pll},
27373 +       {MAXI_SYSCTL_VID1, "vid1", NULL, 0, 0644, NULL, &i2c_proc_real,
27374 +        &i2c_sysctl_real, NULL, &maxi_vid},
27375 +       {MAXI_SYSCTL_VID2, "vid2", NULL, 0, 0644, NULL, &i2c_proc_real,
27376 +        &i2c_sysctl_real, NULL, &maxi_vid},
27377 +       {MAXI_SYSCTL_VID3, "vid3", NULL, 0, 0644, NULL, &i2c_proc_real,
27378 +        &i2c_sysctl_real, NULL, &maxi_vid},
27379 +       {MAXI_SYSCTL_VID4, "vid4", NULL, 0, 0644, NULL, &i2c_proc_real,
27380 +        &i2c_sysctl_real, NULL, &maxi_vid},
27381 +       {MAXI_SYSCTL_VID5, "vid5", NULL, 0, 0644, NULL, &i2c_proc_real,
27382 +        &i2c_sysctl_real, NULL, &maxi_vid},
27383 +       {MAXI_SYSCTL_LCD1, "lcd1", NULL, 0, 0644, NULL, &i2c_proc_real,
27384 +        &i2c_sysctl_real, NULL, &maxi_lcd},
27385 +       {MAXI_SYSCTL_LCD2, "lcd2", NULL, 0, 0644, NULL, &i2c_proc_real,
27386 +        &i2c_sysctl_real, NULL, &maxi_lcd},
27387 +       {MAXI_SYSCTL_LCD3, "lcd3", NULL, 0, 0644, NULL, &i2c_proc_real,
27388 +        &i2c_sysctl_real, NULL, &maxi_lcd},
27389 +       {MAXI_SYSCTL_LCD4, "lcd4", NULL, 0, 0644, NULL, &i2c_proc_real,
27390 +        &i2c_sysctl_real, NULL, &maxi_lcd},
27391 +       {MAXI_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
27392 +        &i2c_sysctl_real, NULL, &maxi_alarms},
27393 +       {0}
27394 +};
27395 +
27396 +/* This function is called when:
27397 +    - maxi_driver is inserted (when this module is loaded), for each
27398 +      available adapter
27399 +    - when a new adapter is inserted (and maxi_driver is still present) */
27400 +static int maxi_attach_adapter(struct i2c_adapter *adapter)
27401 +{
27402 +       return i2c_detect(adapter, &addr_data, maxi_detect);
27403 +}
27404 +
27405 +/* This function is called by i2c_detect */
27406 +int maxi_detect(struct i2c_adapter *adapter, int address,
27407 +               unsigned short flags, int kind)
27408 +{
27409 +       struct i2c_client *new_client;
27410 +       struct maxi_data *data;
27411 +       enum maxi_type type = 0;
27412 +       int i, j, err = 0;
27413 +       const char *type_name = NULL, *client_name = NULL;
27414 +
27415 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
27416 +               goto ERROR0;
27417 +
27418 +       /* OK. For now, we presume we have a valid client. We now create the
27419 +          client structure, even though we cannot fill it completely yet.
27420 +          But it allows us to access maxi_{read,write}_value. */
27421 +       if (!(data = kmalloc(sizeof(struct maxi_data), GFP_KERNEL))) {
27422 +               err = -ENOMEM;
27423 +               goto ERROR0;
27424 +       }
27425 +
27426 +       /* Fill the new client structure with data */
27427 +       new_client = &data->client;
27428 +       new_client->addr = address;
27429 +       new_client->data = data;
27430 +       new_client->adapter = adapter;
27431 +       new_client->driver = &maxi_driver;
27432 +       new_client->flags = 0;
27433 +
27434 +       /* Now we do the remaining detection. */
27435 +       if (kind < 0) {
27436 +               if (i2c_smbus_read_byte_data
27437 +                   (new_client, MAXI_REG_MBX_STATUS) < 0)
27438 +                       goto ERROR2;
27439 +       }
27440 +
27441 +       /* Determine the chip type - only one kind supported */
27442 +       if (kind <= 0)
27443 +               kind = maxilife;
27444 +
27445 +       if (kind == maxilife) {
27446 +               /* Detect if the machine has a MaxiLife NBA controller.
27447 +                  The right way to perform this check is to do a read/modify/write
27448 +                  on register MbxStatus (5A):
27449 +                  - Read 5A (value 0 for non-NBA firmware, FF (MbxIdle on NBA-firmware)
27450 +                  - Write 55 on 5A, then read back 5A
27451 +                  Non-NBA firmware: value is 55 (reg 5A is a standard writable reg)
27452 +                  NBA firmaware: value is FF (write-protect on MbxStatus active) */
27453 +               int stat;
27454 +               i2c_smbus_write_byte_data(new_client, MAXI_REG_MBX_STATUS,
27455 +                                         0x55);
27456 +               stat =
27457 +                   i2c_smbus_read_byte_data(new_client,
27458 +                                            MAXI_REG_MBX_STATUS);
27459 +
27460 +               /*if (stat == MAXI_STAT_IDLE || stat == MAXI_STAT_OK) */
27461 +               if (stat != 0x55)
27462 +                       maxi_version = nba;
27463 +#ifdef AUTODETECT
27464 +               else {
27465 +                       /* The right way to get the platform info is to read the firmware
27466 +                          revision from serial EEPROM (addr=0x54), at offset 0x0045.
27467 +                          This is a string as:
27468 +                          "CG 00.04" -> Cristal [XU] / Geronimo [XAs]
27469 +                          "CO 00.03" -> Cognac [XU]
27470 +                          "AS 00.01" -> Ashaki [XA] */
27471 +#if 0
27472 +                       int biosctl;
27473 +                       biosctl =
27474 +                           i2c_smbus_read_byte_data(new_client,
27475 +                                                    MAXI_REG_BIOS_CTRL);
27476 +                       i2c_smbus_write_byte_data(new_client,
27477 +                                                 MAXI_REG_BIOS_CTRL,
27478 +                                                 biosctl | 4);
27479 +                       err = eeprom_read_byte_data(adapter, 0x54, 0x45);
27480 +                       i2c_smbus_write_byte_data(new_client,
27481 +                                                 MAXI_REG_BIOS_CTRL,
27482 +                                                 biosctl);
27483 +#endif
27484 +                       int i;
27485 +                       char *biosmem, *bm;
27486 +                       bm = biosmem = ioremap(0xe0000, 0x20000);
27487 +                       if (biosmem) {
27488 +                               printk("begin of bios search\n");
27489 +                               for (i = 0; i < 0x20000; i++) {
27490 +                                       if (*bm == 'C') {
27491 +                                               char *s = bm;
27492 +                                               while (s && isprint(*s)) {
27493 +                                                       printk("%c", *s);
27494 +                                                       s++;
27495 +                                               }
27496 +                                               printk("\n");
27497 +                                               if (!strncmp
27498 +                                                   (bm, "CG 00.04", 8)) {
27499 +                                                       maxi_version =
27500 +                                                           cristal;
27501 +                                                       printk
27502 +                                                           ("maxilife: found MaxiLife Rev CG 00.04\n");
27503 +                                                       break;
27504 +                                               }
27505 +                                               if (!strncmp
27506 +                                                   (bm, "CO 00.03", 8)) {
27507 +                                                       maxi_version =
27508 +                                                           cognac;
27509 +                                                       printk
27510 +                                                           ("maxilife: found MaxiLife Rev CO 00.03\n");
27511 +                                                       break;
27512 +                                               }
27513 +                                       }
27514 +                                       if (*bm == 'A' && *(bm + 1) == 'S') {
27515 +                                               char *s = bm;
27516 +                                               while (s && isprint(*s)) {
27517 +                                                       printk("%c", *s);
27518 +                                                       s++;
27519 +                                               }
27520 +                                               printk("\n");
27521 +                                               if (!strncmp
27522 +                                                   (bm, "AS 00.01", 8)) {
27523 +                                                       maxi_version =
27524 +                                                           ashaki;
27525 +                                                       printk
27526 +                                                           ("maxilife: found MaxiLife Rev AS 00.01\n");
27527 +                                                       break;
27528 +                                               }
27529 +                                       }
27530 +                                       bm++;
27531 +                               }
27532 +                               printk("end of bios search\n");
27533 +                       } else
27534 +                               printk("could not map bios memory\n");
27535 +               }
27536 +#endif
27537 +
27538 +               if (maxi_version == cristal) {
27539 +                       type = cristal;
27540 +                       type_name = "maxilife-cg";
27541 +                       client_name = "HP MaxiLife Rev CG 00.04";
27542 +                       printk
27543 +                           ("maxilife: HP KAYAK XU/XAs (Dual Pentium II Slot 1)\n");
27544 +               } else if (maxi_version == cognac) {
27545 +                       type = cognac;
27546 +                       type_name = "maxilife-co";
27547 +                       client_name = "HP MaxiLife Rev CO 00.03";
27548 +                       printk
27549 +                           ("maxilife: HP KAYAK XU (Dual Xeon Slot 2 400/450 Mhz)\n");
27550 +               } else if (maxi_version == ashaki) {
27551 +                       type = ashaki;
27552 +                       type_name = "maxilife-as";
27553 +                       client_name = "HP MaxiLife Rev AS 00.01";
27554 +                       printk
27555 +                           ("maxilife: HP KAYAK XA (Pentium II Slot 1, monoprocessor)\n");
27556 +               } else if (maxi_version == nba) {
27557 +                       type = nba;
27558 +                       type_name = "maxilife-nba";
27559 +                       client_name = "HP MaxiLife NBA";
27560 +                       printk("maxilife: HP KAYAK XU800/XM600\n");
27561 +               } else {
27562 +#ifdef AUTODETECT
27563 +                       printk
27564 +                           ("maxilife: Warning: probed non-maxilife chip?!? (%x)\n",
27565 +                            err);
27566 +#else
27567 +                       printk
27568 +                           ("maxilife: Error: specified wrong maxi_version (%d)\n",
27569 +                            maxi_version);
27570 +#endif
27571 +                       goto ERROR2;
27572 +               }
27573 +       }
27574 +
27575 +       /* Fill in the remaining client fields and put it into the global list */
27576 +       strcpy(new_client->name, client_name);
27577 +       ((struct maxi_data *) (new_client->data))->type = type;
27578 +
27579 +       for (i = 0; i < 4; i++)
27580 +               for (j = 0; j < 17; j++)
27581 +                           ((struct maxi_data *) (new_client->data))->
27582 +                           lcd[i][j] = (u8) 0;
27583 +
27584 +       new_client->id = maxi_id++;
27585 +
27586 +       data->valid = 0;
27587 +       init_MUTEX(&data->lock);
27588 +       init_MUTEX(&data->update_lock);
27589 +
27590 +       /* Tell i2c-core that a new client has arrived */
27591 +       if ((err = i2c_attach_client(new_client)))
27592 +               goto ERROR2;
27593 +
27594 +       /* Register a new directory entry with module sensors */
27595 +       if ((err = i2c_register_entry(new_client, type_name,
27596 +                                         maxi_dir_table_template)) < 0)
27597 +               goto ERROR4;
27598 +       data->sysctl_id = err;
27599 +
27600 +       /* Initialize the MaxiLife chip */
27601 +       maxi_init_client(new_client);
27602 +       return 0;
27603 +
27604 +       /* OK, this is not exactly good programming practice, usually.
27605 +          But it is very code-efficient in this case. */
27606 +      ERROR4:
27607 +       i2c_detach_client(new_client);
27608 +      ERROR2:
27609 +       kfree(data);
27610 +      ERROR0:
27611 +       return err;
27612 +}
27613 +
27614 +/* This function is called whenever a client should be removed:
27615 +    - maxi_driver is removed (when this module is unloaded)
27616 +    - when an adapter is removed which has a maxi client (and maxi_driver
27617 +      is still present). */
27618 +static int maxi_detach_client(struct i2c_client *client)
27619 +{
27620 +       int err;
27621 +
27622 +       i2c_deregister_entry(((struct maxi_data *) (client->data))->
27623 +                                sysctl_id);
27624 +
27625 +       if ((err = i2c_detach_client(client))) {
27626 +               printk
27627 +                   ("maxilife: Client deregistration failed, client not detached.\n");
27628 +               return err;
27629 +       }
27630 +       kfree(client->data);
27631 +       return 0;
27632 +}
27633 +
27634 +/* Read byte from specified register (-1 in case of error, value otherwise). */
27635 +static int maxi_read_value(struct i2c_client *client, u8 reg)
27636 +{
27637 +       return i2c_smbus_read_byte_data(client, reg);
27638 +}
27639 +
27640 +/* Read the byte value for a MaxiLife token (-1 in case of error, value otherwise */
27641 +static int maxi_read_token(struct i2c_client *client, u16 token)
27642 +{
27643 +       u8 lowToken, highToken;
27644 +       int error, value;
27645 +
27646 +       lowToken = LOW(token);
27647 +       highToken = HIGH(token);
27648 +
27649 +       /* Set mailbox status register to idle state. */
27650 +       error =
27651 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
27652 +                                     MAXI_STAT_IDLE);
27653 +       if (error < 0)
27654 +               return error;
27655 +
27656 +       /* Check for mailbox idle state. */
27657 +       error = i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27658 +       if (error != MAXI_STAT_IDLE)
27659 +               return -1;
27660 +
27661 +       /* Write the most significant byte of the token we want to read. */
27662 +       error =
27663 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_H,
27664 +                                     highToken);
27665 +       if (error < 0)
27666 +               return error;
27667 +
27668 +       /* Write the least significant byte of the token we want to read. */
27669 +       error =
27670 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_L,
27671 +                                     lowToken);
27672 +       if (error < 0)
27673 +               return error;
27674 +
27675 +       /* Write the read token opcode to the mailbox. */
27676 +       error =
27677 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_CMD,
27678 +                                     MAXI_CMD_READ);
27679 +       if (error < 0)
27680 +               return error;
27681 +
27682 +       /* Check for transaction completion */
27683 +       do {
27684 +               error =
27685 +                   i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27686 +       } while (error == MAXI_STAT_BUSY);
27687 +       if (error != MAXI_STAT_OK)
27688 +               return -1;
27689 +
27690 +       /* Read the value of the token. */
27691 +       value = i2c_smbus_read_byte_data(client, MAXI_REG_MBX_DATA);
27692 +       if (value == -1)
27693 +               return -1;
27694 +
27695 +       /* set mailbox status to idle to complete transaction. */
27696 +       error =
27697 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
27698 +                                     MAXI_STAT_IDLE);
27699 +       if (error < 0)
27700 +               return error;
27701 +
27702 +       return value;
27703 +}
27704 +
27705 +#ifndef NOWRITE
27706 +/* Write byte to specified register (-1 in case of error, 0 otherwise). */
27707 +static int maxi_write_value(struct i2c_client *client, u8 reg, u8 value)
27708 +{
27709 +       return i2c_smbus_write_byte_data(client, reg, value);
27710 +}
27711 +#endif
27712 +
27713 +/* Write a set of len byte values to MaxiLife token (-1 in case of error, 0 otherwise). */
27714 +int maxi_write_token_loop(struct i2c_client *client, u16 token, u8 len,
27715 +                         u8 * values)
27716 +{
27717 +       u8 lowToken, highToken, bCounter;
27718 +       int error;
27719 +
27720 +       lowToken = LOW(token);
27721 +       highToken = HIGH(token);
27722 +
27723 +       /* Set mailbox status register to idle state. */
27724 +       error =
27725 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
27726 +                                     MAXI_STAT_IDLE);
27727 +       if (error < 0)
27728 +               return error;
27729 +
27730 +       /* Check for mailbox idle state. */
27731 +       error = i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27732 +       if (error != MAXI_STAT_IDLE)
27733 +               return -1;
27734 +
27735 +       for (bCounter = 0; (bCounter < len && bCounter < 32); bCounter++) {
27736 +               error =
27737 +                   i2c_smbus_write_byte_data(client,
27738 +                                             (u8) (MAXI_REG_MBX_DATA +
27739 +                                                   bCounter),
27740 +                                             values[bCounter]);
27741 +               if (error < 0)
27742 +                       return error;
27743 +       }
27744 +
27745 +       /* Write the most significant byte of the token we want to read. */
27746 +       error =
27747 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_H,
27748 +                                     highToken);
27749 +       if (error < 0)
27750 +               return error;
27751 +
27752 +       /* Write the least significant byte of the token we want to read. */
27753 +       error =
27754 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_L,
27755 +                                     lowToken);
27756 +       if (error < 0)
27757 +               return error;
27758 +
27759 +       /* Write the write token opcode to the mailbox. */
27760 +       error =
27761 +           i2c_smbus_write_byte_data(client, MAXI_REG_MBX_CMD,
27762 +                                     MAXI_CMD_WRITE);
27763 +       if (error < 0)
27764 +               return error;
27765 +
27766 +       /* Check for transaction completion */
27767 +       do {
27768 +               error =
27769 +                   i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27770 +       } while (error == MAXI_STAT_BUSY);
27771 +       if (error != MAXI_STAT_OK)
27772 +               return -1;
27773 +
27774 +       /* set mailbox status to idle to complete transaction. */
27775 +       return i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
27776 +                                        MAXI_STAT_IDLE);
27777 +}
27778 +
27779 +/* Called when we have found a new MaxiLife. It should set limits, etc. */
27780 +static void maxi_init_client(struct i2c_client *client)
27781 +{
27782 +       struct maxi_data *data = client->data;
27783 +
27784 +       if (data->type == nba) {
27785 +               strcpy(data->lcd[2], " Linux MaxiLife");
27786 +               maxi_write_token_loop(client, MAXI_TOK_LCD(2),
27787 +                                     strlen(data->lcd[2]) + 1,
27788 +                                     data->lcd[2]);
27789 +       }
27790 +}
27791 +
27792 +static void maxi_update_client(struct i2c_client *client)
27793 +{
27794 +       struct maxi_data *data = client->data;
27795 +       int i;
27796 +
27797 +       if (data->type == nba) {
27798 +               printk
27799 +                   ("maxi_update_client should never be called by nba\n");
27800 +               return;
27801 +       }
27802 +
27803 +       down(&data->update_lock);
27804 +
27805 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
27806 +           (jiffies < data->last_updated) || !data->valid) {
27807 +
27808 +#ifdef DEBUG
27809 +               printk("maxilife: Starting MaxiLife update\n");
27810 +#endif
27811 +               for (i = 0; i < 5; i++)
27812 +                       data->temp[i] =
27813 +                           maxi_read_value(client, MAXI_REG_TEMP(i));
27814 +               switch (data->type) {
27815 +               case cristal:
27816 +                       data->temp[0] = 0;      /* not valid */
27817 +                       data->temp_max[0] = 0;
27818 +                       data->temp_hyst[0] = 0;
27819 +                       data->temp_max[1] = 110;        /* max PCI slot temp */
27820 +                       data->temp_hyst[1] = 100;
27821 +                       data->temp_max[2] = 120;        /* max BX chipset temp */
27822 +                       data->temp_hyst[2] = 110;
27823 +                       data->temp_max[3] = 100;        /* max HDD temp */
27824 +                       data->temp_hyst[3] = 90;
27825 +                       data->temp_max[4] = 120;        /* max CPU temp */
27826 +                       data->temp_hyst[4] = 110;
27827 +                       break;
27828 +
27829 +               case cognac:
27830 +                       data->temp_max[0] = 120;        /* max CPU1 temp */
27831 +                       data->temp_hyst[0] = 110;
27832 +                       data->temp_max[1] = 110;        /* max PCI slot temp */
27833 +                       data->temp_hyst[1] = 100;
27834 +                       data->temp_max[2] = 120;        /* max CPU2 temp */
27835 +                       data->temp_hyst[2] = 110;
27836 +                       data->temp_max[3] = 100;        /* max HDD temp */
27837 +                       data->temp_hyst[3] = 90;
27838 +                       data->temp_max[4] = 120;        /* max reference CPU temp */
27839 +                       data->temp_hyst[4] = 110;
27840 +                       break;
27841 +
27842 +               case ashaki:
27843 +                       data->temp[0] = 0;      /* not valid */
27844 +                       data->temp_max[0] = 0;
27845 +                       data->temp_hyst[0] = 0;
27846 +                       data->temp_max[1] = 110;        /* max PCI slot temp */
27847 +                       data->temp_hyst[1] = 100;
27848 +                       data->temp[2] = 0;      /* not valid */
27849 +                       data->temp_max[2] = 0;
27850 +                       data->temp_hyst[2] = 0;
27851 +                       data->temp_max[3] = 100;        /* max HDD temp */
27852 +                       data->temp_hyst[3] = 90;
27853 +                       data->temp_max[4] = 120;        /* max CPU temp */
27854 +                       data->temp_hyst[4] = 110;
27855 +                       break;
27856 +
27857 +               default:
27858 +                       printk("maxilife: Unknown MaxiLife chip\n");
27859 +               }
27860 +               data->temp[5] = 0;      /* only used by MaxiLife'99 */
27861 +               data->temp_max[5] = 0;
27862 +               data->temp_hyst[5] = 0;
27863 +
27864 +               for (i = 0; i < 3; i++) {
27865 +                       data->fan[i] =
27866 +                           maxi_read_value(client, MAXI_REG_FAN(i));
27867 +                       data->fan_speed[i] =
27868 +                           maxi_read_value(client, MAXI_REG_FAN_SPEED(i));
27869 +                       data->fan_div[i] = 4;
27870 +                       if (data->type == ashaki)
27871 +                               data->fan_min[i] =
27872 +                                   maxi_read_value(client,
27873 +                                                   MAXI_REG_FAN_MINAS(i));
27874 +                       else
27875 +                               data->fan_min[i] =
27876 +                                   maxi_read_value(client,
27877 +                                                   MAXI_REG_FAN_MIN(i));
27878 +               }
27879 +               data->fan[3] = 0xff;    /* only used by MaxiLife'99 */
27880 +               data->fan_speed[3] = 0;
27881 +               data->fan_div[3] = 4;   /* avoid possible /0 */
27882 +               data->fan_min[3] = 0;
27883 +
27884 +               data->pll = maxi_read_value(client, MAXI_REG_PLL);
27885 +               data->pll_min = maxi_read_value(client, MAXI_REG_PLL_MIN);
27886 +               data->pll_max = maxi_read_value(client, MAXI_REG_PLL_MAX);
27887 +
27888 +               for (i = 0; i < 4; i++) {
27889 +                       data->vid[i] =
27890 +                           maxi_read_value(client, MAXI_REG_VID(i));
27891 +                       data->vid_min[i] =
27892 +                           maxi_read_value(client, MAXI_REG_VID_MIN(i));
27893 +                       data->vid_max[i] =
27894 +                           maxi_read_value(client, MAXI_REG_VID_MAX(i));
27895 +               }
27896 +               switch (data->type) {
27897 +               case cristal:
27898 +                       data->vid[3] = 0;       /* no voltage cache L2 */
27899 +                       data->vid_min[3] = 0;
27900 +                       data->vid_max[3] = 0;
27901 +                       break;
27902 +
27903 +               case cognac:
27904 +                       break;
27905 +
27906 +               case ashaki:
27907 +                       data->vid[1] = 0;       /* no voltage CPU 2 */
27908 +                       data->vid_min[1] = 0;
27909 +                       data->vid_max[1] = 0;
27910 +                       data->vid[3] = 0;       /* no voltage cache L2 */
27911 +                       data->vid_min[3] = 0;
27912 +                       data->vid_max[3] = 0;
27913 +                       break;
27914 +
27915 +               default:
27916 +                       printk("maxilife: Unknown MaxiLife chip\n");
27917 +               }
27918 +               data->vid[4] = 0;       /* only used by MaxliLife'99 */
27919 +               data->vid_min[4] = 0;
27920 +               data->vid_max[4] = 0;
27921 +
27922 +               data->alarms = maxi_read_value(client, MAXI_REG_DIAG_RT1) +
27923 +                   (maxi_read_value(client, MAXI_REG_DIAG_RT2) << 8);
27924 +
27925 +               data->last_updated = jiffies;
27926 +               data->valid = 1;
27927 +       }
27928 +
27929 +       up(&data->update_lock);
27930 +}
27931 +
27932 +void maxi99_update_client(struct i2c_client *client,
27933 +                         enum sensor_type sensor, int which)
27934 +{
27935 +       static unsigned long last_updated[6][6];        /* sensor, which */
27936 +       struct maxi_data *data = client->data;
27937 +
27938 +       down(&data->update_lock);
27939 +
27940 +       /*maxi_write_token_loop(client, MAXI_TOK_LCD_LINE3, 13, "Linux 2.2.13"); */
27941 +
27942 +       if ((jiffies - last_updated[sensor][which] > 2 * HZ) ||
27943 +           (jiffies < last_updated[sensor][which]
27944 +            || !last_updated[sensor][which])) {
27945 +
27946 +               int tmp, i;
27947 +
27948 +               switch (sensor) {
27949 +               case fan:
27950 +                       for (i = 0; i < 4; i++) {
27951 +                               if (i == which) {
27952 +                                       tmp =
27953 +                                           maxi_read_token(client,
27954 +                                                           MAXI_TOK_FAN
27955 +                                                           (i));
27956 +                                       data->fan[i] =
27957 +                                           maxi_read_token(client,
27958 +                                                           MAXI_TOK_FAN
27959 +                                                           (i));
27960 +                                       data->fan_speed[i] =
27961 +                                           maxi_read_token(client,
27962 +                                                           MAXI_TOK_MAX
27963 +                                                           (MAXI_TOK_FAN
27964 +                                                            (i)));
27965 +                                       data->fan_div[i] = 1;
27966 +                                       data->fan_min[i] = 0;
27967 +                               }
27968 +                       }
27969 +                       break;
27970 +
27971 +               case temp:
27972 +                       for (i = 0; i < 6; i++) {
27973 +                               if (i == which) {
27974 +                                       data->temp[i] =
27975 +                                           maxi_read_token(client,
27976 +                                                           MAXI_TOK_TEMP
27977 +                                                           (i));
27978 +                                       data->temp_max[i] =
27979 +                                           maxi_read_token(client,
27980 +                                                           MAXI_TOK_MAX
27981 +                                                           (MAXI_TOK_TEMP
27982 +                                                            (i)));
27983 +                                       data->temp_hyst[i] =
27984 +                                           data->temp_max[i] - 5;
27985 +                               }
27986 +                       }
27987 +                       break;
27988 +
27989 +               case vid:
27990 +                       for (i = 0; i < 5; i++) {
27991 +                               if (i == which) {
27992 +                                       data->vid[i] =
27993 +                                           maxi_read_token(client,
27994 +                                                           MAXI_TOK_VID
27995 +                                                           (i));
27996 +                                       data->vid_min[i] =
27997 +                                           maxi_read_token(client,
27998 +                                                           MAXI_TOK_MIN
27999 +                                                           (MAXI_TOK_VID
28000 +                                                            (i)));
28001 +                                       data->vid_max[i] =
28002 +                                           maxi_read_token(client,
28003 +                                                           MAXI_TOK_MAX
28004 +                                                           (MAXI_TOK_VID
28005 +                                                            (i)));
28006 +                               }
28007 +                       }
28008 +                       break;
28009 +
28010 +               case pll:
28011 +                       data->pll = 0;
28012 +                       data->pll_min = 0;
28013 +                       data->pll_max = 0;
28014 +                       break;
28015 +
28016 +               case alarm:
28017 +                       data->alarms =
28018 +                           (maxi_read_token(client, MAXI_TOK_ALARM_EVENT)
28019 +                            << 8);
28020 +                       if (data->alarms)
28021 +                               data->alarms +=
28022 +                                   data->alarms ==
28023 +                                   (1 << 8) ? maxi_read_token(client,
28024 +                                                              MAXI_TOK_ALARM_FAN)
28025 +                                   : data->alarms ==
28026 +                                   (2 << 8) ? maxi_read_token(client,
28027 +                                                              MAXI_TOK_ALARM_VID)
28028 +                                   : data->alarms ==
28029 +                                   (4 << 8) ? maxi_read_token(client,
28030 +                                                              MAXI_TOK_ALARM_TEMP)
28031 +                                   : data->alarms ==
28032 +                                   (8 << 8) ? maxi_read_token(client,
28033 +                                                              MAXI_TOK_ALARM_FAN)
28034 +                                   : 0;
28035 +                       break;
28036 +
28037 +               default:
28038 +                       printk("maxilife: Unknown sensor type\n");
28039 +               }
28040 +
28041 +               last_updated[sensor][which] = jiffies;
28042 +               data->valid = 1;
28043 +       }
28044 +
28045 +       up(&data->update_lock);
28046 +}
28047 +
28048 +/* The next few functions are the call-back functions of the /proc/sys and
28049 +   sysctl files. Which function is used is defined in the ctl_table in
28050 +   the extra1 field.
28051 +   Each function must return the magnitude (power of 10 to divide the data
28052 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
28053 +   put a maximum of *nrels elements in results reflecting the data of this
28054 +   file, and set *nrels to the number it actually put in it, if operation==
28055 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
28056 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
28057 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
28058 +   large enough (by checking the incoming value of *nrels). This is not very
28059 +   good practice, but as long as you put less than about 5 values in results,
28060 +   you can assume it is large enough. */
28061 +void maxi_fan(struct i2c_client *client, int operation, int ctl_name,
28062 +             int *nrels_mag, long *results)
28063 +{
28064 +       struct maxi_data *data = client->data;
28065 +       int nr;
28066 +
28067 +       if (data->type == nba) {
28068 +               maxi99_fan(client, operation, ctl_name, nrels_mag,
28069 +                          results);
28070 +               return;
28071 +       }
28072 +
28073 +       nr = ctl_name - MAXI_SYSCTL_FAN1 + 1;
28074 +
28075 +       if (operation == SENSORS_PROC_REAL_INFO)
28076 +               *nrels_mag = 0;
28077 +       else if (operation == SENSORS_PROC_REAL_READ) {
28078 +               maxi_update_client(client);
28079 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1]);
28080 +               results[1] = data->fan_div[nr - 1];
28081 +               results[2] = FAN_FROM_REG(data->fan[nr - 1]);
28082 +               *nrels_mag = 3;
28083 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28084 +#ifndef NOWRITE
28085 +               if (*nrels_mag >= 1) {
28086 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0]);
28087 +                       maxi_write_value(client, MAXI_REG_FAN_MIN(nr),
28088 +                                        data->fan_min[nr - 1]);
28089 +               }
28090 +#endif
28091 +       }
28092 +}
28093 +
28094 +void maxi99_fan(struct i2c_client *client, int operation, int ctl_name,
28095 +               int *nrels_mag, long *results)
28096 +{
28097 +       struct maxi_data *data = client->data;
28098 +       int nr;
28099 +
28100 +       nr = ctl_name - MAXI_SYSCTL_FAN1 + 1;
28101 +
28102 +       if (operation == SENSORS_PROC_REAL_INFO)
28103 +               *nrels_mag = 0;
28104 +       else if (operation == SENSORS_PROC_REAL_READ) {
28105 +               maxi99_update_client(client, fan, nr - 1);
28106 +               results[0] = FAN99_FROM_REG(data->fan_min[nr - 1]);     /* min rpm */
28107 +               results[1] = data->fan_div[nr - 1];     /* divisor */
28108 +               results[2] = FAN99_FROM_REG(data->fan[nr - 1]); /* rpm */
28109 +               *nrels_mag = 3;
28110 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28111 +#ifndef NOWRITE
28112 +               /* still to do */
28113 +               if (*nrels_mag >= 1) {
28114 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0]);
28115 +                       maxi_write_value(client, MAXI_REG_FAN_MIN(nr),
28116 +                                        data->fan_min[nr - 1]);
28117 +               }
28118 +#endif
28119 +       }
28120 +}
28121 +
28122 +void maxi_temp(struct i2c_client *client, int operation, int ctl_name,
28123 +              int *nrels_mag, long *results)
28124 +{
28125 +       struct maxi_data *data = client->data;
28126 +       int nr;
28127 +
28128 +       if (data->type == nba) {
28129 +               maxi99_temp(client, operation, ctl_name, nrels_mag,
28130 +                           results);
28131 +               return;
28132 +       }
28133 +
28134 +       nr = ctl_name - MAXI_SYSCTL_TEMP1 + 1;
28135 +
28136 +       if (operation == SENSORS_PROC_REAL_INFO)
28137 +               *nrels_mag = 1;
28138 +       else if (operation == SENSORS_PROC_REAL_READ) {
28139 +               maxi_update_client(client);
28140 +               results[0] = TEMP_FROM_REG(data->temp_max[nr - 1]);
28141 +               results[1] = TEMP_FROM_REG(data->temp_hyst[nr - 1]);
28142 +               results[2] = TEMP_FROM_REG(data->temp[nr - 1]);
28143 +               *nrels_mag = 3;
28144 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28145 +               /* temperature range can not be changed */
28146 +       }
28147 +}
28148 +
28149 +void maxi99_temp(struct i2c_client *client, int operation, int ctl_name,
28150 +                int *nrels_mag, long *results)
28151 +{
28152 +       struct maxi_data *data = client->data;
28153 +       int nr;
28154 +
28155 +       nr = ctl_name - MAXI_SYSCTL_TEMP1 + 1;
28156 +
28157 +       if (operation == SENSORS_PROC_REAL_INFO)
28158 +               *nrels_mag = 0;
28159 +       else if (operation == SENSORS_PROC_REAL_READ) {
28160 +               maxi99_update_client(client, temp, nr - 1);
28161 +               results[0] = TEMP99_FROM_REG(data->temp_max[nr - 1]);
28162 +               results[1] = TEMP99_FROM_REG(data->temp_hyst[nr - 1]);
28163 +               results[2] = TEMP99_FROM_REG(data->temp[nr - 1]);
28164 +               *nrels_mag = 3;
28165 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28166 +               /* temperature range can not be changed */
28167 +       }
28168 +}
28169 +
28170 +void maxi_pll(struct i2c_client *client, int operation, int ctl_name,
28171 +             int *nrels_mag, long *results)
28172 +{
28173 +       struct maxi_data *data = client->data;
28174 +
28175 +       if (operation == SENSORS_PROC_REAL_INFO)
28176 +               *nrels_mag = 2;
28177 +       else if (operation == SENSORS_PROC_REAL_READ) {
28178 +               if (data->type == nba)
28179 +                       maxi99_update_client(client, pll, 0);
28180 +               else
28181 +                       maxi_update_client(client);
28182 +               results[0] = PLL_FROM_REG(data->pll_min);
28183 +               results[1] = PLL_FROM_REG(data->pll_max);
28184 +               results[2] = PLL_FROM_REG(data->pll);
28185 +               *nrels_mag = 3;
28186 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28187 +#ifndef NOWRITE
28188 +               if (*nrels_mag >= 1) {
28189 +                       data->pll_min = PLL_TO_REG(results[0]);
28190 +                       maxi_write_value(client, MAXI_REG_PLL_MIN,
28191 +                                        data->pll_min);
28192 +               }
28193 +               if (*nrels_mag >= 2) {
28194 +                       data->pll_max = PLL_TO_REG(results[1]);
28195 +                       maxi_write_value(client, MAXI_REG_PLL_MAX,
28196 +                                        data->pll_max);
28197 +               }
28198 +#endif
28199 +       }
28200 +}
28201 +
28202 +void maxi_vid(struct i2c_client *client, int operation, int ctl_name,
28203 +             int *nrels_mag, long *results)
28204 +{
28205 +       struct maxi_data *data = client->data;
28206 +       int nr;
28207 +
28208 +       if (data->type == nba) {
28209 +               maxi99_vid(client, operation, ctl_name, nrels_mag,
28210 +                          results);
28211 +               return;
28212 +       }
28213 +
28214 +       nr = ctl_name - MAXI_SYSCTL_VID1 + 1;
28215 +
28216 +       if (operation == SENSORS_PROC_REAL_INFO)
28217 +               *nrels_mag = 4;
28218 +       else if (operation == SENSORS_PROC_REAL_READ) {
28219 +               maxi_update_client(client);
28220 +               results[0] = VID_FROM_REG(data->vid_min[nr - 1]);
28221 +               results[1] = VID_FROM_REG(data->vid_max[nr - 1]);
28222 +               results[2] = VID_FROM_REG(data->vid[nr - 1]);
28223 +               *nrels_mag = 3;
28224 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28225 +#ifndef NOWRITE
28226 +               if (*nrels_mag >= 1) {
28227 +                       data->vid_min[nr - 1] = VID_TO_REG(results[0]);
28228 +                       maxi_write_value(client, MAXI_REG_VID_MIN(nr),
28229 +                                        data->vid_min[nr - 1]);
28230 +               }
28231 +               if (*nrels_mag >= 2) {
28232 +                       data->vid_max[nr - 1] = VID_TO_REG(results[1]);
28233 +                       maxi_write_value(client, MAXI_REG_VID_MAX(nr),
28234 +                                        data->vid_max[nr - 1]);
28235 +               }
28236 +#endif
28237 +       }
28238 +}
28239 +
28240 +void maxi99_vid(struct i2c_client *client, int operation, int ctl_name,
28241 +               int *nrels_mag, long *results)
28242 +{
28243 +       struct maxi_data *data = client->data;
28244 +       int nr = ctl_name - MAXI_SYSCTL_VID1 + 1;
28245 +
28246 +       if (operation == SENSORS_PROC_REAL_INFO)
28247 +               *nrels_mag = 4;
28248 +       else if (operation == SENSORS_PROC_REAL_READ) {
28249 +               maxi99_update_client(client, vid, nr - 1);
28250 +               results[0] = VID99_FROM_REG(nr, data->vid_min[nr - 1]);
28251 +               results[1] = VID99_FROM_REG(nr, data->vid_max[nr - 1]);
28252 +               results[2] = VID99_FROM_REG(nr, data->vid[nr - 1]);
28253 +               *nrels_mag = 3;
28254 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28255 +#ifndef NOWRITE
28256 +               /* still to do */
28257 +               if (*nrels_mag >= 1) {
28258 +                       data->vid_min[nr - 1] = VID_TO_REG(results[0]);
28259 +                       maxi_write_value(client, MAXI_REG_VID_MIN(nr),
28260 +                                        data->vid_min[nr - 1]);
28261 +               }
28262 +               if (*nrels_mag >= 2) {
28263 +                       data->vid_max[nr - 1] = VID_TO_REG(results[1]);
28264 +                       maxi_write_value(client, MAXI_REG_VID_MAX(nr),
28265 +                                        data->vid_max[nr - 1]);
28266 +               }
28267 +#endif
28268 +       }
28269 +}
28270 +
28271 +void maxi_lcd(struct i2c_client *client, int operation, int ctl_name,
28272 +             int *nrels_mag, long *results)
28273 +{
28274 +       /* Allows writing and reading from LCD display */
28275 +
28276 +       struct maxi_data *data = client->data;
28277 +       int nr;
28278 +
28279 +       if (data->type != nba)
28280 +               return;
28281 +
28282 +       nr = ctl_name - MAXI_SYSCTL_LCD1 + 1;
28283 +
28284 +       if (operation == SENSORS_PROC_REAL_INFO)
28285 +               *nrels_mag = 0;
28286 +       else if (operation == SENSORS_PROC_REAL_READ) {
28287 +               results[0] = *((long *) &data->lcd[nr - 1][0]);
28288 +               results[1] = *((long *) &data->lcd[nr - 1][4]);
28289 +               results[2] = *((long *) &data->lcd[nr - 1][8]);
28290 +               results[3] = *((long *) &data->lcd[nr - 1][12]);
28291 +               *nrels_mag = 4;
28292 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
28293 +               /* 
28294 +                  Writing a string to line 3 of the LCD can be done like:
28295 +                  echo -n "Linux MaxiLife" | od -A n -l > \
28296 +                  /proc/sys/dev/sensors/maxilife-nba-i2c-0-14/lcd3
28297 +                */
28298 +               if (*nrels_mag >= 1)
28299 +                       *((long *) &data->lcd[nr - 1][0]) = results[0];
28300 +               if (*nrels_mag >= 2)
28301 +                       *((long *) &data->lcd[nr - 1][4]) = results[1];
28302 +               if (*nrels_mag >= 3)
28303 +                       *((long *) &data->lcd[nr - 1][8]) = results[2];
28304 +               if (*nrels_mag >= 4)
28305 +                       *((long *) &data->lcd[nr - 1][12]) = results[3];
28306 +               maxi_write_token_loop(client, MAXI_TOK_LCD(nr - 1),
28307 +                                     strlen(data->lcd[nr - 1]) + 1,
28308 +                                     data->lcd[nr - 1]);
28309 +#if 0
28310 +               if (*nrels_mag >= 1)
28311 +                       printk("nr=%d, result[0] = %.4s\n", nr,
28312 +                              (char *) &results[0]);
28313 +               if (*nrels_mag >= 2)
28314 +                       printk("nr=%d, result[1] = %.4s\n", nr,
28315 +                              (char *) &results[1]);
28316 +               if (*nrels_mag >= 3)
28317 +                       printk("nr=%d, result[2] = %.4s\n", nr,
28318 +                              (char *) &results[2]);
28319 +               if (*nrels_mag >= 4)
28320 +                       printk("nr=%d, result[3] = %.4s\n", nr,
28321 +                              (char *) &results[3]);
28322 +#endif
28323 +       }
28324 +
28325 +}
28326 +
28327 +void maxi_alarms(struct i2c_client *client, int operation, int ctl_name,
28328 +                int *nrels_mag, long *results)
28329 +{
28330 +       struct maxi_data *data = client->data;
28331 +
28332 +       if (operation == SENSORS_PROC_REAL_INFO)
28333 +               *nrels_mag = 0;
28334 +       else if (operation == SENSORS_PROC_REAL_READ) {
28335 +               if (data->type == nba)
28336 +                       maxi99_update_client(client, alarm, 0);
28337 +               else
28338 +                       maxi_update_client(client);
28339 +               results[0] = ALARMS_FROM_REG(data->alarms);
28340 +               *nrels_mag = 1;
28341 +       }
28342 +}
28343 +
28344 +static int __init sm_maxilife_init(void)
28345 +{
28346 +       printk("maxilife: Version %s (lm_sensors %s (%s))\n", version_str,
28347 +              LM_VERSION, LM_DATE);
28348 +       return i2c_add_driver(&maxi_driver);
28349 +}
28350 +
28351 +static void __exit sm_maxilife_exit(void)
28352 +{
28353 +       i2c_del_driver(&maxi_driver);
28354 +}
28355 +
28356 +
28357 +
28358 +MODULE_AUTHOR("Fons Rademakers <Fons.Rademakers@cern.ch>");
28359 +MODULE_DESCRIPTION("HP MaxiLife driver");
28360 +MODULE_PARM(maxi_version, "i");
28361 +MODULE_PARM_DESC(maxi_version, "MaxiLife firmware version");
28362 +
28363 +module_init(sm_maxilife_init);
28364 +module_exit(sm_maxilife_exit);
28365 --- linux-old/drivers/sensors/mtp008.c  Thu Jan  1 00:00:00 1970
28366 +++ linux/drivers/sensors/mtp008.c      Mon Dec 13 20:18:51 2004
28367 @@ -0,0 +1,1103 @@
28368 +/*
28369 +   mtp008.c - Part of lm_sensors, Linux kernel modules for hardware
28370 +   monitoring
28371 +   Copyright (C) 2001, 2004  Kris Van Hees <aedil@alchar.org>
28372 +
28373 +   This program is free software; you can redistribute it and/or modify
28374 +   it under the terms of the GNU General Public License as published by
28375 +   the Free Software Foundation; either version 2 of the License, or
28376 +   (at your option) any later version.
28377 +
28378 +   This program is distributed in the hope that it will be useful,
28379 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
28380 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28381 +   GNU General Public License for more details.
28382 +
28383 +   You should have received a copy of the GNU General Public License
28384 +   along with this program; if not, write to the Free Software
28385 +   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28386 + */
28387 +
28388 +#include <linux/module.h>
28389 +#include <linux/slab.h>
28390 +#include <linux/i2c.h>
28391 +#include <linux/i2c-proc.h>
28392 +#include <linux/init.h>
28393 +#define LM_DATE "20041007"
28394 +#define LM_VERSION "2.8.8"
28395 +
28396 +MODULE_LICENSE("GPL");
28397 +
28398 +/* Addresses to scan */
28399 +static unsigned short normal_i2c[] = {SENSORS_I2C_END};
28400 +static unsigned short normal_i2c_range[] = {0x2c, 0x2e, SENSORS_I2C_END};
28401 +static unsigned int normal_isa[] = {SENSORS_ISA_END};
28402 +static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
28403 +
28404 +/* Insmod parameters */
28405 +SENSORS_INSMOD_1(mtp008);
28406 +
28407 +/* The MTP008 registers */
28408 +/*      in0 .. in6 */
28409 +#define MTP008_REG_IN(nr)              (0x20 + (nr))
28410 +#define MTP008_REG_IN_MAX(nr)          (0x2b + (nr) * 2)
28411 +#define MTP008_REG_IN_MIN(nr)          (0x2c + (nr) * 2)
28412 +
28413 +/*      temp1 */
28414 +#define MTP008_REG_TEMP                        0x27
28415 +#define MTP008_REG_TEMP_MAX            0x39
28416 +#define MTP008_REG_TEMP_MIN            0x3a
28417 +
28418 +/*      fan1 .. fan3 */
28419 +#define MTP008_REG_FAN(nr)             (0x27 + (nr))
28420 +#define MTP008_REG_FAN_MIN(nr)         (0x3a + (nr))
28421 +
28422 +#define MTP008_REG_CONFIG              0x40
28423 +#define MTP008_REG_INT_STAT1           0x41
28424 +#define MTP008_REG_INT_STAT2           0x42
28425 +
28426 +#define MTP008_REG_SMI_MASK1           0x43
28427 +#define MTP008_REG_SMI_MASK2           0x44
28428 +
28429 +#define MTP008_REG_NMI_MASK1           0x45
28430 +#define MTP008_REG_NMI_MASK2           0x46
28431 +
28432 +#define MTP008_REG_VID_FANDIV          0x47
28433 +
28434 +#define MTP008_REG_I2C_ADDR            0x48
28435 +
28436 +#define MTP008_REG_RESET_VID4          0x49
28437 +
28438 +#define MTP008_REG_OVT_PROP            0x50
28439 +
28440 +#define MTP008_REG_BEEP_CTRL1          0x51
28441 +#define MTP008_REG_BEEP_CTRL2          0x52
28442 +
28443 +/*      pwm1 .. pwm3  nr range 1-3 */
28444 +#define MTP008_REG_PWM_CTRL(nr)                (0x52 + (nr))
28445 +
28446 +#define MTP008_REG_PIN_CTRL1           0x56
28447 +#define MTP008_REG_PIN_CTRL2           0x57
28448 +
28449 +#define MTP008_REG_CHIPID              0x58
28450 +
28451 +/*
28452 + * Pin control register configuration constants.
28453 + */
28454 +#define MTP008_CFG_VT1_PII             0x08
28455 +#define MTP008_CFG_VT2_AIN             0x00
28456 +#define MTP008_CFG_VT2_VT              0x03
28457 +#define MTP008_CFG_VT2_PII             0x04
28458 +#define MTP008_CFG_VT2_MASK            0x06
28459 +#define MTP008_CFG_VT3_VT              0x01
28460 +
28461 +/* sensor pin types */
28462 +#define VOLTAGE                1
28463 +#define THERMISTOR     2
28464 +#define PIIDIODE       3
28465 +
28466 +/*
28467 + * Conversion routines and macros.  Limit checking is only done on
28468 + * the TO_REG variants.
28469 + *
28470 + * Note that IN values are expressed as 100 times the actual voltage to avoid
28471 + * having to use floating point values.  As such, IN values are between 0 and
28472 + * 409 (0V to 4.096V).
28473 + */
28474 +#define IN_TO_REG(val)         (SENSORS_LIMIT((((val) * 10 + 8) / 16), 0, 255))
28475 +#define IN_FROM_REG(val)       (((val) * 16 + 5) / 10)
28476 +
28477 +/*
28478 + * The fan cotation count (as stored in the register) is calculated using the
28479 + * following formula:
28480 + *      count = (22.5K * 60) / (rpm * div) = 1350000 / (rpm * div)
28481 + * and the rpm is therefore:
28482 + *      rpm = 1350000 / (count * div)
28483 + */
28484 +static inline u8 FAN_TO_REG(long rpm, int div)
28485 +{
28486 +       if (rpm == 0)
28487 +               return 255;
28488 +
28489 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
28490 +
28491 +       return SENSORS_LIMIT(
28492 +                (1350000 + rpm * div / 2) / (rpm * div),
28493 +                1, 254
28494 +              );
28495 +}
28496 +
28497 +#define FAN_FROM_REG(val, div) ((val) == 0 ? -1                              \
28498 +                                           : (val) == 255 ? 0                \
28499 +                                                          : 1350000 /        \
28500 +                                                            ((val) * (div))  \
28501 +                               )
28502 +
28503 +/*
28504 + * Temperatures are stored as two's complement values of the Celsius value.  It
28505 + * actually uses 10 times the Celsius value to avoid using floating point
28506 + * values.
28507 + */
28508 +#define TEMP_TO_REG(val)       (                                             \
28509 +                                (val) < 0                                    \
28510 +                                   ? SENSORS_LIMIT(((val) - 5) / 10, 0, 255) \
28511 +                                   : SENSORS_LIMIT(((val) + 5) / 10, 0, 255) \
28512 +                               )
28513 +#define TEMP_FROM_REG(val)     (                                             \
28514 +                                (                                            \
28515 +                                 (val) > 0x80 ? (val) - 0x100                \
28516 +                                              : (val)                        \
28517 +                                ) * 10                                       \
28518 +                               )
28519 +
28520 +/*
28521 + * VCORE voltage:
28522 + *      0x00 to 0x0f    = 2.05 to 1.30 (0.05 per unit)
28523 + *      0x10 to 0x1e    = 3.50 to 2.10 (0.10 per unit)
28524 + *      0x1f            = No CPU
28525 + */
28526 +#define VID_FROM_REG(val)      ((val) == 0x1f                                \
28527 +                                        ? 0                                  \
28528 +                                        : (val) < 0x10 ? 205 - (val) * 5     \
28529 +                                                       : 510 - (val) * 10)
28530 +
28531 +/*
28532 + * Fan divider.
28533 + */
28534 +#define DIV_FROM_REG(val)      (1 << (val))
28535 +#define DIV_TO_REG(val)                ((val) == 8 ? 3                               \
28536 +                                           : (val) == 4 ? 2                  \
28537 +                                                        : (val) == 2 ? 1     \
28538 +                                                                     : 0)
28539 +
28540 +/*
28541 + * Alarms (interrupt status).
28542 + */
28543 +#define ALARMS_FROM_REG(val)   (val)
28544 +
28545 +/*
28546 + * Beep controls.
28547 + */
28548 +#define BEEPS_FROM_REG(val)    (val)
28549 +#define BEEPS_TO_REG(val)      (val)
28550 +
28551 +/*
28552 + * PWM control. nr range 1 to 3
28553 + */
28554 +#define PWM_FROM_REG(val)      (val)
28555 +#define PWM_TO_REG(val)                (val)
28556 +#define PWMENABLE_FROM_REG(nr, val)    (((val) >> ((nr) + 3)) & 1)
28557 +
28558 +/*
28559 + * For each registered MTP008, we need to keep some data in memory.  The
28560 + * structure itself is dynamically allocated, at the same time when a new
28561 + * mtp008 client is allocated.
28562 + */
28563 +struct mtp008_data {
28564 +       struct i2c_client client;
28565 +       int sysctl_id;
28566 +       enum chips type;
28567 +
28568 +       struct semaphore update_lock;
28569 +       char valid;                             /* !=0 if fields are valid */
28570 +       unsigned long last_updated;             /* In jiffies */
28571 +
28572 +       u8 in[7];                               /* Register value */
28573 +       u8 in_max[7];                           /* Register value */
28574 +       u8 in_min[7];                           /* Register value */
28575 +       u8 temp;                                /* Register value */
28576 +       u8 temp_max;                            /* Register value */
28577 +       u8 temp_min;                            /* Register value */
28578 +       u8 fan[3];                              /* Register value */
28579 +       u8 fan_min[3];                          /* Register value */
28580 +       u8 vid;                                 /* Register encoding */
28581 +       u8 fan_div[3];                          /* Register encoding */
28582 +       u16 alarms;                             /* Register encoding */
28583 +       u16 beeps;                              /* Register encoding */
28584 +       u8 pwm[4];                              /* Register value */
28585 +       u8 sens[3];                             /* 1 = Analog input,
28586 +                                                  2 = Thermistor,
28587 +                                                  3 = PII/Celeron diode */
28588 +       u8 pwmenable;                           /* Register 0x57 value */
28589 +};
28590 +
28591 +static int mtp008_attach_adapter(struct i2c_adapter *adapter);
28592 +static int mtp008_detect(struct i2c_adapter *adapter, int address,
28593 +                        unsigned short flags, int kind);
28594 +static int mtp008_detach_client(struct i2c_client *client);
28595 +
28596 +static int mtp008_read_value(struct i2c_client *client, u8 register);
28597 +static int mtp008_write_value(struct i2c_client *client, u8 register, u8 value);
28598 +static void mtp008_update_client(struct i2c_client *client);
28599 +static void mtp008_init_client(struct i2c_client *client);
28600 +
28601 +static void mtp008_in(struct i2c_client *client, int operation,
28602 +                     int ctl_name, int *nrels_mag, long *results);
28603 +static void mtp008_fan(struct i2c_client *client, int operation,
28604 +                      int ctl_name, int *nrels_mag, long *results);
28605 +static void mtp008_temp(struct i2c_client *client, int operation,
28606 +                       int ctl_name, int *nrels_mag, long *results);
28607 +static void mtp008_temp_add(struct i2c_client *client, int operation,
28608 +                           int ctl_name, int *nrels_mag, long *results);
28609 +static void mtp008_vid(struct i2c_client *client, int operation,
28610 +                      int ctl_name, int *nrels_mag, long *results);
28611 +static void mtp008_fan_div(struct i2c_client *client, int operation,
28612 +                          int ctl_name, int *nrels_mag, long *results);
28613 +static void mtp008_alarms(struct i2c_client *client, int operation,
28614 +                         int ctl_name, int *nrels_mag, long *results);
28615 +static void mtp008_beep(struct i2c_client *client, int operation,
28616 +                       int ctl_name, int *nrels_mag, long *results);
28617 +static void mtp008_pwm(struct i2c_client *client, int operation,
28618 +                      int ctl_name, int *nrels_mag, long *results);
28619 +static void mtp008_sens(struct i2c_client *client, int operation,
28620 +                       int ctl_name, int *nrels_mag, long *results);
28621 +static void mtp008_getsensortype(struct mtp008_data *data, u8 inp);
28622 +
28623 +static int mtp008_id = 0;
28624 +
28625 +static struct i2c_driver mtp008_driver =
28626 +{
28627 +       .owner          = THIS_MODULE,
28628 +       .name           = "MTP008 sensor driver",
28629 +       .id             = I2C_DRIVERID_MTP008,
28630 +       .flags          = I2C_DF_NOTIFY,
28631 +       .attach_adapter = mtp008_attach_adapter,
28632 +       .detach_client  = mtp008_detach_client,
28633 +};
28634 +
28635 +/* -- SENSORS SYSCTL START -- */
28636 +#define MTP008_SYSCTL_IN0      1000    /* Volts * 100 */
28637 +#define MTP008_SYSCTL_IN1      1001
28638 +#define MTP008_SYSCTL_IN2      1002
28639 +#define MTP008_SYSCTL_IN3      1003
28640 +#define MTP008_SYSCTL_IN4      1004
28641 +#define MTP008_SYSCTL_IN5      1005
28642 +#define MTP008_SYSCTL_IN6      1006
28643 +#define MTP008_SYSCTL_FAN1     1101    /* Rotations/min */
28644 +#define MTP008_SYSCTL_FAN2     1102
28645 +#define MTP008_SYSCTL_FAN3     1103
28646 +#define MTP008_SYSCTL_TEMP1    1200    /* Degrees Celcius * 10 */
28647 +#define MTP008_SYSCTL_TEMP2    1201    /* Degrees Celcius * 10 */
28648 +#define MTP008_SYSCTL_TEMP3    1202    /* Degrees Celcius * 10 */
28649 +#define MTP008_SYSCTL_VID      1300    /* Volts * 100 */
28650 +#define MTP008_SYSCTL_PWM1     1401
28651 +#define MTP008_SYSCTL_PWM2     1402
28652 +#define MTP008_SYSCTL_PWM3     1403
28653 +#define MTP008_SYSCTL_SENS1    1501    /* 1, 2, or Beta (3000-5000) */
28654 +#define MTP008_SYSCTL_SENS2    1502
28655 +#define MTP008_SYSCTL_SENS3    1503
28656 +#define MTP008_SYSCTL_FAN_DIV  2000    /* 1, 2, 4 or 8 */
28657 +#define MTP008_SYSCTL_ALARMS   2001    /* bitvector */
28658 +#define MTP008_SYSCTL_BEEP     2002    /* bitvector */
28659 +
28660 +#define MTP008_ALARM_IN0       0x0001
28661 +#define MTP008_ALARM_IN1       0x0002
28662 +#define MTP008_ALARM_IN2       0x0004
28663 +#define MTP008_ALARM_IN3       0x0008
28664 +#define MTP008_ALARM_IN4       0x0100
28665 +#define MTP008_ALARM_IN5       0x0200
28666 +#define MTP008_ALARM_IN6       0x0400
28667 +#define MTP008_ALARM_FAN1      0x0040
28668 +#define MTP008_ALARM_FAN2      0x0080
28669 +#define MTP008_ALARM_FAN3      0x0800
28670 +#define MTP008_ALARM_TEMP1     0x0010
28671 +#define MTP008_ALARM_TEMP2     0x0100
28672 +#define MTP008_ALARM_TEMP3     0x0200
28673 +
28674 +/* -- SENSORS SYSCTL END -- */
28675 +
28676 +/* The /proc/sys entries */
28677 +/* These files are created for each detected chip. This is just a template;
28678 +   though at first sight, you might think we could use a statically
28679 +   allocated list, we need some way to get back to the parent - which
28680 +   is done through one of the 'extra' fields which are initialized 
28681 +   when a new copy is allocated. */
28682 +
28683 +static ctl_table mtp008_dir_table_template[] =
28684 +{
28685 +       {MTP008_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL,
28686 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_in},
28687 +       {MTP008_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL,
28688 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_in},
28689 +       {MTP008_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL,
28690 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_in},
28691 +       {MTP008_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL,
28692 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_in},
28693 +       {MTP008_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL,
28694 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_in},
28695 +       {MTP008_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL,
28696 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_in},
28697 +       {MTP008_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL,
28698 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_in},
28699 +       {MTP008_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
28700 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_fan},
28701 +       {MTP008_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL,
28702 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_fan},
28703 +       {MTP008_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL,
28704 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_fan},
28705 +       {MTP008_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL,
28706 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_temp},
28707 +       {MTP008_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
28708 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_temp_add},
28709 +       {MTP008_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
28710 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_temp_add},
28711 +       {MTP008_SYSCTL_VID, "vid", NULL, 0, 0444, NULL,
28712 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_vid},
28713 +       {MTP008_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
28714 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_fan_div},
28715 +       {MTP008_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
28716 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_alarms},
28717 +       {MTP008_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL,
28718 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_beep},
28719 +       {MTP008_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL,
28720 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_pwm},
28721 +       {MTP008_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL,
28722 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_pwm},
28723 +       {MTP008_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL,
28724 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_pwm},
28725 +       {MTP008_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL,
28726 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_sens},
28727 +       {MTP008_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL,
28728 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_sens},
28729 +       {MTP008_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL,
28730 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &mtp008_sens},
28731 +       {0}
28732 +};
28733 +
28734 +/* This function is called when:
28735 + * mtp008_driver is inserted (when this module is loaded), for each available
28736 + * adapter when a new adapter is inserted (and mtp008_driver is still present)
28737 + */
28738 +static int mtp008_attach_adapter(struct i2c_adapter *adapter)
28739 +{
28740 +       struct i2c_client_address_data mtp008_addr_data;
28741 +
28742 +       mtp008_addr_data.normal_i2c = addr_data.normal_i2c;
28743 +       mtp008_addr_data.normal_i2c_range = addr_data.normal_i2c_range;
28744 +       mtp008_addr_data.probe = addr_data.probe;
28745 +       mtp008_addr_data.probe_range = addr_data.probe_range;
28746 +       mtp008_addr_data.ignore = addr_data.ignore;
28747 +       mtp008_addr_data.ignore_range = addr_data.ignore_range;
28748 +       mtp008_addr_data.force = addr_data.forces->force;
28749 +
28750 +       return i2c_probe(adapter, &mtp008_addr_data, mtp008_detect);
28751 +}
28752 +
28753 +int mtp008_detect(struct i2c_adapter *adapter, int address,
28754 +                 unsigned short flags, int kind)
28755 +{
28756 +       const char *type_name = "";
28757 +       const char *client_name = "";
28758 +       int is_isa, err, sysid;
28759 +       struct i2c_client *new_client;
28760 +       struct mtp008_data *data;
28761 +
28762 +       err = 0;
28763 +
28764 +       is_isa = i2c_is_isa_adapter(adapter);
28765 +       if (is_isa ||
28766 +           !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
28767 +               goto ERROR0;
28768 +
28769 +       /*
28770 +        * We presume we have a valid client.  We now create the client
28771 +        * structure, even though we cannot fill it completely yet.  But it
28772 +        * allows us to use mtp008_(read|write)_value().
28773 +        */
28774 +       if (!(data = kmalloc(sizeof(struct mtp008_data), GFP_KERNEL))) {
28775 +               err = -ENOMEM;
28776 +               goto ERROR0;
28777 +       }
28778 +
28779 +       new_client = &data->client;
28780 +       new_client->addr = address;
28781 +       new_client->data = data;
28782 +       new_client->adapter = adapter;
28783 +       new_client->driver = &mtp008_driver;
28784 +       new_client->flags = 0;
28785 +
28786 +       /*
28787 +        * Remaining detection.
28788 +        */
28789 +       if (kind < 0) {
28790 +               if (mtp008_read_value(new_client, MTP008_REG_CHIPID) != 0xac)
28791 +                       goto ERROR1;
28792 +       }
28793 +       /*
28794 +        * Fill in the remaining client fields and put it into the global list.
28795 +        */
28796 +       type_name = "mtp008";
28797 +       client_name = "MTP008 chip";
28798 +       strcpy(new_client->name, client_name);
28799 +       data->type = kind;
28800 +
28801 +       new_client->id = mtp008_id++;
28802 +       data->valid = 0;
28803 +       init_MUTEX(&data->update_lock);
28804 +
28805 +       /*
28806 +        * Tell the I2C layer that a new client has arrived.
28807 +        */
28808 +       if ((err = i2c_attach_client(new_client)))
28809 +               goto ERROR1;
28810 +
28811 +       /*
28812 +        * Register a new directory entry with the sensors module.
28813 +        */
28814 +       if ((sysid = i2c_register_entry(new_client, type_name,
28815 +                                           mtp008_dir_table_template)) < 0) {
28816 +               err = sysid;
28817 +               goto ERROR2;
28818 +       }
28819 +       data->sysctl_id = sysid;
28820 +
28821 +       /*
28822 +        * Initialize the MTP008 chip.
28823 +        */
28824 +       mtp008_init_client(new_client);
28825 +
28826 +       return 0;
28827 +
28828 +       /*
28829 +        * Error handling.  Bad programming practise but very code efficient.
28830 +        */
28831 +      ERROR2:
28832 +       i2c_detach_client(new_client);
28833 +      ERROR1:
28834 +       kfree(data);
28835 +
28836 +      ERROR0:
28837 +       return err;
28838 +}
28839 +
28840 +static int mtp008_detach_client(struct i2c_client *client)
28841 +{
28842 +       int err;
28843 +
28844 +       i2c_deregister_entry(
28845 +               ((struct mtp008_data *) (client->data))->sysctl_id);
28846 +
28847 +       if ((err = i2c_detach_client(client))) {
28848 +               printk("mtp008.o: Deregistration failed, "
28849 +                      "client not detached.\n");
28850 +               return err;
28851 +       }
28852 +       kfree(client->data);
28853 +
28854 +       return 0;
28855 +}
28856 +
28857 +
28858 +static int mtp008_read_value(struct i2c_client *client, u8 reg)
28859 +{
28860 +       return i2c_smbus_read_byte_data(client, reg) & 0xff;
28861 +}
28862 +
28863 +static int mtp008_write_value(struct i2c_client *client, u8 reg, u8 value)
28864 +{
28865 +       return i2c_smbus_write_byte_data(client, reg, value);
28866 +}
28867 +
28868 +/* Called when we have found a new MTP008. It should set limits, etc. */
28869 +static void mtp008_init_client(struct i2c_client *client)
28870 +{
28871 +       u8 save1, save2;
28872 +       struct mtp008_data *data;
28873 +
28874 +       data = client->data;
28875 +
28876 +       /*
28877 +        * Initialize the Myson MTP008 hardware monitoring chip.
28878 +        * Save the pin settings that the BIOS hopefully set.
28879 +        */
28880 +       save1 = mtp008_read_value(client, MTP008_REG_PIN_CTRL1);
28881 +       save2 = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
28882 +       mtp008_write_value(client, MTP008_REG_CONFIG,
28883 +            (mtp008_read_value(client, MTP008_REG_CONFIG) & 0x7f) | 0x80);
28884 +       mtp008_write_value(client, MTP008_REG_PIN_CTRL1, save1);
28885 +       mtp008_write_value(client, MTP008_REG_PIN_CTRL2, save2);
28886 +
28887 +       mtp008_getsensortype(data, save2);
28888 +
28889 +
28890 +       /*
28891 +        * Start monitoring.
28892 +        */
28893 +       mtp008_write_value(
28894 +               client, MTP008_REG_CONFIG,
28895 +               (mtp008_read_value(client, MTP008_REG_CONFIG) & 0xf7) | 0x01
28896 +       );
28897 +}
28898 +
28899 +static void mtp008_update_client(struct i2c_client *client)
28900 +{
28901 +       int i;
28902 +       u8 inp;
28903 +       struct mtp008_data *data;
28904 +
28905 +       data = client->data;
28906 +
28907 +       down(&data->update_lock);
28908 +
28909 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
28910 +           (jiffies < data->last_updated) || !data->valid) {
28911 +#ifdef DEBUG
28912 +               printk("Starting MTP008 update\n");
28913 +#endif
28914 +
28915 +               /*
28916 +                * Read in the analog inputs.  We're reading AIN4 and AIN5 as
28917 +                * regular analog inputs, even though they may have been
28918 +                * configured as temperature readings instead.  Interpretation
28919 +                * of these values is done elsewhere.
28920 +                */
28921 +               for (i = 0; i < 7; i++) {
28922 +                       data->in[i] =
28923 +                               mtp008_read_value(client, MTP008_REG_IN(i));
28924 +                       data->in_max[i] =
28925 +                               mtp008_read_value(client, MTP008_REG_IN_MAX(i));
28926 +                       data->in_min[i] =
28927 +                               mtp008_read_value(client, MTP008_REG_IN_MIN(i));
28928 +               }
28929 +
28930 +               /*
28931 +                * Read the temperature sensor.
28932 +                */
28933 +               data->temp = mtp008_read_value(client, MTP008_REG_TEMP);
28934 +               data->temp_max = mtp008_read_value(client, MTP008_REG_TEMP_MAX);
28935 +               data->temp_min = mtp008_read_value(client, MTP008_REG_TEMP_MIN);
28936 +
28937 +               /*
28938 +                * Read the first 2 fan dividers and the VID setting.  Read the
28939 +                * third fan divider from a different register.
28940 +                */
28941 +               inp = mtp008_read_value(client, MTP008_REG_VID_FANDIV);
28942 +               data->vid = inp & 0x0f;
28943 +               data->vid |= (mtp008_read_value(client,
28944 +                                    MTP008_REG_RESET_VID4) & 0x01) << 4;
28945 +
28946 +               data->fan_div[0] = (inp >> 4) & 0x03;
28947 +               data->fan_div[1] = inp >> 6;
28948 +               data->fan_div[2] =
28949 +                       mtp008_read_value(client, MTP008_REG_PIN_CTRL1) >> 6;
28950 +
28951 +               /*
28952 +                * Read the interrupt status registers.
28953 +                */
28954 +               data->alarms =
28955 +                       (mtp008_read_value(client,
28956 +                                          MTP008_REG_INT_STAT1) & 0xdf) |
28957 +                       (mtp008_read_value(client,
28958 +                                          MTP008_REG_INT_STAT2) & 0x0f) << 8;
28959 +
28960 +               /*
28961 +                * Read the beep control registers.
28962 +                */
28963 +               data->beeps =
28964 +                       (mtp008_read_value(client,
28965 +                                          MTP008_REG_BEEP_CTRL1) & 0xdf) |
28966 +                       (mtp008_read_value(client,
28967 +                                          MTP008_REG_BEEP_CTRL2) & 0x8f) << 8;
28968 +
28969 +               /*
28970 +                * Read the sensor configuration.
28971 +                */
28972 +               inp = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
28973 +               mtp008_getsensortype(data, inp);
28974 +               data->pwmenable = inp;
28975 +
28976 +               /*
28977 +                * Read the PWM registers if enabled.
28978 +                */
28979 +               for (i = 1; i <= 3; i++)
28980 +               {
28981 +                       if(PWMENABLE_FROM_REG(i, inp))
28982 +                               data->pwm[i-1] = mtp008_read_value(client,
28983 +                                                 MTP008_REG_PWM_CTRL(i));
28984 +                       else
28985 +                               data->pwm[i-1] = 255;
28986 +               }
28987 +
28988 +               /*
28989 +                * Read the fan sensors. Skip 3 if PWM1 enabled.
28990 +                */
28991 +               for (i = 1; i <= 3; i++) {
28992 +                       if(i == 3 && PWMENABLE_FROM_REG(1, inp)) {
28993 +                               data->fan[2] = 0;
28994 +                               data->fan_min[2] = 0;
28995 +                       } else {
28996 +                               data->fan[i-1] = mtp008_read_value(client,
28997 +                                         MTP008_REG_FAN(i));
28998 +                               data->fan_min[i-1] = mtp008_read_value(client,
28999 +                                         MTP008_REG_FAN_MIN(i));
29000 +                       }
29001 +               }
29002 +
29003 +               data->last_updated = jiffies;
29004 +               data->valid = 1;
29005 +       }
29006 +       up(&data->update_lock);
29007 +}
29008 +
29009 +static void mtp008_getsensortype(struct mtp008_data *data, u8 inp)
29010 +{
29011 +       inp &= 0x0f;
29012 +       data->sens[0] = (inp >> 3) + 2;                 /* 2 or 3 */
29013 +       data->sens[1] = ((inp >> 1) & 0x03) + 1;        /* 1, 2 or 3 */
29014 +       data->sens[2] = (inp & 0x01) + 1;               /* 1 or 2 */
29015 +}
29016 +
29017 +/* The next few functions are the call-back functions of the /proc/sys and
29018 +   sysctl files. Which function is used is defined in the ctl_table in
29019 +   the extra1 field.
29020 +   Each function must return the magnitude (power of 10 to divide the date
29021 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
29022 +   put a maximum of *nrels elements in results reflecting the data of this
29023 +   file, and set *nrels to the number it actually put in it, if operation==
29024 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
29025 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
29026 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
29027 +   large enough (by checking the incoming value of *nrels). This is not very
29028 +   good practice, but as long as you put less than about 5 values in results,
29029 +   you can assume it is large enough. */
29030 +void mtp008_in(struct i2c_client *client, int operation, int ctl_name,
29031 +              int *nrels_mag, long *results)
29032 +{
29033 +       int nr;
29034 +       struct mtp008_data *data;
29035 +
29036 +       nr = ctl_name - MTP008_SYSCTL_IN0;
29037 +       data = client->data;
29038 +
29039 +       switch (operation) {
29040 +       case SENSORS_PROC_REAL_INFO:
29041 +               *nrels_mag = 2;
29042 +
29043 +               break;
29044 +       case SENSORS_PROC_REAL_READ:
29045 +               mtp008_update_client(client);
29046 +
29047 +               if((nr != 4 && nr != 5) || data->sens[nr - 3] == VOLTAGE) {
29048 +                       results[0] = IN_FROM_REG(data->in_min[nr]);
29049 +                       results[1] = IN_FROM_REG(data->in_max[nr]);
29050 +                       results[2] = IN_FROM_REG(data->in[nr]);
29051 +               } else {
29052 +                       results[0] = 0;
29053 +                       results[1] = 0;
29054 +                       results[2] = 0;
29055 +               }
29056 +
29057 +               *nrels_mag = 3;
29058 +
29059 +               break;
29060 +       case SENSORS_PROC_REAL_WRITE:
29061 +               if((nr != 4 && nr != 5) || data->sens[nr - 3] == VOLTAGE) {
29062 +                       if (*nrels_mag >= 1) {
29063 +                               data->in_min[nr] = IN_TO_REG(results[0]);
29064 +                               mtp008_write_value(client, MTP008_REG_IN_MIN(nr),
29065 +                                                  data->in_min[nr]);
29066 +                       }
29067 +                       if (*nrels_mag >= 2) {
29068 +                               data->in_max[nr] = IN_TO_REG(results[1]);
29069 +                               mtp008_write_value(client, MTP008_REG_IN_MAX(nr),
29070 +                                                  data->in_max[nr]);
29071 +                       }
29072 +               }
29073 +       }
29074 +}
29075 +
29076 +void mtp008_fan(struct i2c_client *client, int operation, int ctl_name,
29077 +               int *nrels_mag, long *results)
29078 +{
29079 +       int nr;
29080 +       struct mtp008_data *data;
29081 +
29082 +       nr = ctl_name - MTP008_SYSCTL_FAN1;
29083 +       data = client->data;
29084 +
29085 +       switch (operation) {
29086 +       case SENSORS_PROC_REAL_INFO:
29087 +               *nrels_mag = 0;
29088 +
29089 +               break;
29090 +       case SENSORS_PROC_REAL_READ:
29091 +               mtp008_update_client(client);
29092 +
29093 +               results[0] = FAN_FROM_REG(data->fan_min[nr],
29094 +                                       DIV_FROM_REG(data->fan_div[nr]));
29095 +               results[1] = FAN_FROM_REG(data->fan[nr],
29096 +                                       DIV_FROM_REG(data->fan_div[nr]));
29097 +
29098 +               *nrels_mag = 2;
29099 +
29100 +               break;
29101 +       case SENSORS_PROC_REAL_WRITE:
29102 +               if (*nrels_mag >= 1) {
29103 +                       data->fan_min[nr] =
29104 +                           FAN_TO_REG(results[0],
29105 +                                      DIV_FROM_REG(data->fan_div[nr]));
29106 +                       mtp008_write_value(client, MTP008_REG_FAN_MIN(nr + 1),
29107 +                                          data->fan_min[nr]);
29108 +               }
29109 +       }
29110 +}
29111 +
29112 +void mtp008_temp(struct i2c_client *client, int operation, int ctl_name,
29113 +                int *nrels_mag, long *results)
29114 +{
29115 +       struct mtp008_data *data;
29116 +
29117 +       data = client->data;
29118 +
29119 +       switch (operation) {
29120 +       case SENSORS_PROC_REAL_INFO:
29121 +               *nrels_mag = 1;
29122 +
29123 +               break;
29124 +       case SENSORS_PROC_REAL_READ:
29125 +               mtp008_update_client(client);
29126 +
29127 +               results[0] = TEMP_FROM_REG(data->temp_max);
29128 +               results[1] = TEMP_FROM_REG(data->temp_min);
29129 +               results[2] = TEMP_FROM_REG(data->temp);
29130 +               *nrels_mag = 3;
29131 +
29132 +               break;
29133 +       case SENSORS_PROC_REAL_WRITE:
29134 +               if (*nrels_mag >= 1) {
29135 +                       data->temp_max = TEMP_TO_REG(results[0]);
29136 +                       mtp008_write_value(client, MTP008_REG_TEMP_MAX,
29137 +                                          data->temp_max);
29138 +               }
29139 +               if (*nrels_mag >= 2) {
29140 +                       data->temp_min = TEMP_TO_REG(results[1]);
29141 +                       mtp008_write_value(client, MTP008_REG_TEMP_MIN,
29142 +                                          data->temp_min);
29143 +               }
29144 +       }
29145 +}
29146 +
29147 +void mtp008_temp_add(struct i2c_client *client, int operation, int ctl_name,
29148 +                    int *nrels_mag, long *results)
29149 +{
29150 +       int nr;
29151 +       struct mtp008_data *data;
29152 +
29153 +       nr = 3 + ctl_name - MTP008_SYSCTL_TEMP1;        /* AIN4 or AIN5 */
29154 +       data = client->data;
29155 +
29156 +       switch (operation) {
29157 +       case SENSORS_PROC_REAL_INFO:
29158 +               *nrels_mag = 1;
29159 +
29160 +               break;
29161 +       case SENSORS_PROC_REAL_READ:
29162 +               mtp008_update_client(client);
29163 +
29164 +               if(data->sens[nr - 3] != VOLTAGE) {
29165 +                       results[0] = TEMP_FROM_REG(data->in_max[nr]);
29166 +                       results[1] = TEMP_FROM_REG(data->in_min[nr]);
29167 +                       results[2] = TEMP_FROM_REG(data->in[nr]);
29168 +               } else {
29169 +                       results[0] = 0;
29170 +                       results[1] = 0;
29171 +                       results[2] = 0;
29172 +               }
29173 +               *nrels_mag = 3;
29174 +
29175 +               break;
29176 +       case SENSORS_PROC_REAL_WRITE:
29177 +               if(data->sens[nr - 3] != VOLTAGE) {
29178 +                       if (*nrels_mag >= 1) {
29179 +                               data->in_max[nr] = TEMP_TO_REG(results[0]);
29180 +                               mtp008_write_value(client,
29181 +                                                  MTP008_REG_IN_MAX(nr),
29182 +                                                  data->in_max[nr]);
29183 +                       }
29184 +                       if (*nrels_mag >= 2) {
29185 +                               data->in_min[nr] = TEMP_TO_REG(results[1]);
29186 +                               mtp008_write_value(client,
29187 +                                                  MTP008_REG_IN_MIN(nr),
29188 +                                                  data->in_min[nr]);
29189 +                       }
29190 +               }
29191 +       }
29192 +}
29193 +
29194 +void mtp008_vid(struct i2c_client *client, int operation, int ctl_name,
29195 +               int *nrels_mag, long *results)
29196 +{
29197 +       struct mtp008_data *data;
29198 +
29199 +       data = client->data;
29200 +
29201 +       switch (operation) {
29202 +       case SENSORS_PROC_REAL_INFO:
29203 +               *nrels_mag = 2;
29204 +
29205 +               break;
29206 +       case SENSORS_PROC_REAL_READ:
29207 +               mtp008_update_client(client);
29208 +
29209 +               results[0] = VID_FROM_REG(data->vid);
29210 +
29211 +               *nrels_mag = 1;
29212 +       }
29213 +}
29214 +
29215 +void mtp008_fan_div(struct i2c_client *client, int operation,
29216 +                   int ctl_name, int *nrels_mag, long *results)
29217 +{
29218 +       struct mtp008_data *data;
29219 +       u8 val;
29220 +
29221 +       data = client->data;
29222 +
29223 +       switch (operation) {
29224 +       case SENSORS_PROC_REAL_INFO:
29225 +               *nrels_mag = 0;
29226 +
29227 +               break;
29228 +       case SENSORS_PROC_REAL_READ:
29229 +               mtp008_update_client(client);
29230 +
29231 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
29232 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
29233 +               results[2] = DIV_FROM_REG(data->fan_div[2]);
29234 +
29235 +               *nrels_mag = 3;
29236 +
29237 +               break;
29238 +       case SENSORS_PROC_REAL_WRITE:
29239 +               if (*nrels_mag >= 3) {
29240 +                       data->fan_div[2] = DIV_TO_REG(results[2]);
29241 +                       val = mtp008_read_value(client, MTP008_REG_PIN_CTRL1);
29242 +                       val = (val & 0x3f) | (data->fan_div[2] & 0x03) << 6;
29243 +                       mtp008_write_value(client, MTP008_REG_PIN_CTRL1, val);
29244 +               }
29245 +               if (*nrels_mag >= 1) {
29246 +                       val = mtp008_read_value(client, MTP008_REG_VID_FANDIV);
29247 +                       if (*nrels_mag >= 2) {
29248 +                               data->fan_div[1] = DIV_TO_REG(results[1]);
29249 +                               val = (val & 0x3f) |
29250 +                                     (data->fan_div[1] & 0x03) << 6;
29251 +                       }
29252 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
29253 +                       val = (val & 0xcf) | (data->fan_div[0] & 0x03) << 4;
29254 +                       mtp008_write_value(client, MTP008_REG_VID_FANDIV, val);
29255 +               }
29256 +       }
29257 +}
29258 +
29259 +void mtp008_alarms(struct i2c_client *client, int operation, int ctl_name,
29260 +                  int *nrels_mag, long *results)
29261 +{
29262 +       struct mtp008_data *data;
29263 +
29264 +       data = client->data;
29265 +
29266 +       switch (operation) {
29267 +       case SENSORS_PROC_REAL_INFO:
29268 +               *nrels_mag = 0;
29269 +
29270 +               break;
29271 +       case SENSORS_PROC_REAL_READ:
29272 +               mtp008_update_client(client);
29273 +
29274 +               results[0] = ALARMS_FROM_REG(data->alarms);
29275 +
29276 +               *nrels_mag = 1;
29277 +       }
29278 +}
29279 +
29280 +void mtp008_beep(struct i2c_client *client, int operation, int ctl_name,
29281 +                int *nrels_mag, long *results)
29282 +{
29283 +       struct mtp008_data *data;
29284 +
29285 +       data = client->data;
29286 +
29287 +       switch (operation) {
29288 +       case SENSORS_PROC_REAL_INFO:
29289 +               *nrels_mag = 0;
29290 +
29291 +               break;
29292 +       case SENSORS_PROC_REAL_READ:
29293 +               mtp008_update_client(client);
29294 +
29295 +               results[0] = BEEPS_FROM_REG(data->beeps);
29296 +
29297 +               *nrels_mag = 1;
29298 +
29299 +               break;
29300 +       case SENSORS_PROC_REAL_WRITE:
29301 +               if (*nrels_mag >= 1) {
29302 +                       data->beeps = BEEPS_TO_REG(results[0]) & 0xdf8f;
29303 +
29304 +                       mtp008_write_value(client, MTP008_REG_BEEP_CTRL1,
29305 +                                          data->beeps & 0xff);
29306 +                       mtp008_write_value(client, MTP008_REG_BEEP_CTRL2,
29307 +                                          data->beeps >> 8);
29308 +               }
29309 +       }
29310 +}
29311 +
29312 +void mtp008_pwm(struct i2c_client *client, int operation, int ctl_name,
29313 +               int *nrels_mag, long *results)
29314 +{
29315 +       int nr;
29316 +       struct mtp008_data *data;
29317 +
29318 +       nr = ctl_name - MTP008_SYSCTL_PWM1;
29319 +       data = client->data;
29320 +
29321 +       switch (operation) {
29322 +       case SENSORS_PROC_REAL_INFO:
29323 +               *nrels_mag = 0;
29324 +
29325 +               break;
29326 +       case SENSORS_PROC_REAL_READ:
29327 +               mtp008_update_client(client);
29328 +
29329 +               results[0] = PWM_FROM_REG(data->pwm[nr]);
29330 +               results[1] = PWMENABLE_FROM_REG(nr + 1, data->pwmenable);
29331 +               *nrels_mag = 2;
29332 +
29333 +               break;
29334 +       case SENSORS_PROC_REAL_WRITE:
29335 +               if (*nrels_mag >= 1) {
29336 +                       if (*nrels_mag >= 2) {
29337 +                               if(results[1])
29338 +                                       data->pwmenable |= 0x10 << nr;
29339 +                               else
29340 +                                       data->pwmenable &= ~(0x10 << nr);
29341 +                               mtp008_write_value(client, MTP008_REG_PIN_CTRL2,
29342 +                                                  data->pwmenable);
29343 +                       }
29344 +                       data->pwm[nr] = PWM_TO_REG(results[0]);
29345 +                       mtp008_write_value(client, MTP008_REG_PWM_CTRL(nr),
29346 +                                          data->pwm[nr]);
29347 +               }
29348 +       }
29349 +}
29350 +
29351 +void mtp008_sens(struct i2c_client *client, int operation, int ctl_name,
29352 +                int *nrels_mag, long *results)
29353 +{
29354 +       const char *opts = "";
29355 +       int nr;
29356 +       u8 tmp;
29357 +       struct mtp008_data *data;
29358 +
29359 +       nr = 1 + ctl_name - MTP008_SYSCTL_SENS1;
29360 +       data = client->data;
29361 +
29362 +       switch (operation) {
29363 +       case SENSORS_PROC_REAL_INFO:
29364 +               *nrels_mag = 0;
29365 +
29366 +               break;
29367 +       case SENSORS_PROC_REAL_READ:
29368 +               results[0] = data->sens[nr - 1];
29369 +
29370 +               *nrels_mag = 1;
29371 +
29372 +               break;
29373 +       case SENSORS_PROC_REAL_WRITE:
29374 +               if (*nrels_mag >= 1) {
29375 +                       tmp = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
29376 +
29377 +                       switch (nr) {
29378 +                       case 1: /* VT or PII */
29379 +                               opts = "2 or 3";
29380 +
29381 +                               switch (results[0]) {
29382 +                               case THERMISTOR:
29383 +                                       mtp008_write_value(
29384 +                                               client, MTP008_REG_PIN_CTRL2,
29385 +                                               tmp & ~MTP008_CFG_VT1_PII);
29386 +                                       data->sens[0] = 2;
29387 +                                       return;
29388 +                               case PIIDIODE:
29389 +                                       mtp008_write_value(
29390 +                                               client, MTP008_REG_PIN_CTRL2,
29391 +                                               tmp | MTP008_CFG_VT1_PII);
29392 +                                       data->sens[0] = 3;
29393 +                                       return;
29394 +                               }
29395 +
29396 +                               break;
29397 +                       case 2: /* AIN, VT or PII */
29398 +                               tmp &= ~MTP008_CFG_VT2_MASK;
29399 +                               opts = "1, 2 or 3";
29400 +
29401 +                               switch (results[0]) {
29402 +                               case VOLTAGE:
29403 +                                       mtp008_write_value(
29404 +                                               client, MTP008_REG_PIN_CTRL2,
29405 +                                               tmp | MTP008_CFG_VT2_AIN);
29406 +                                       data->sens[1] = 1;
29407 +                                       return;
29408 +                               case THERMISTOR:
29409 +                                       mtp008_write_value(
29410 +                                               client, MTP008_REG_PIN_CTRL2,
29411 +                                               tmp | MTP008_CFG_VT2_VT);
29412 +                                       data->sens[1] = 2;
29413 +                                       return;
29414 +                               case PIIDIODE:
29415 +                                       mtp008_write_value(
29416 +                                               client, MTP008_REG_PIN_CTRL2,
29417 +                                               tmp | MTP008_CFG_VT2_PII);
29418 +                                       data->sens[1] = 3;
29419 +                                       return;
29420 +                               }
29421 +
29422 +                               break;
29423 +                       case 3: /* AIN or VT */
29424 +                               opts = "1 or 2";
29425 +
29426 +                               switch (results[0]) {
29427 +                               case VOLTAGE:
29428 +                                       mtp008_write_value(
29429 +                                               client, MTP008_REG_PIN_CTRL2,
29430 +                                               tmp & ~MTP008_CFG_VT3_VT);
29431 +                                       data->sens[2] = 1;
29432 +                                       return;
29433 +                               case THERMISTOR:
29434 +                                       mtp008_write_value(
29435 +                                               client, MTP008_REG_PIN_CTRL2,
29436 +                                               tmp | MTP008_CFG_VT3_VT);
29437 +                                       data->sens[2] = 2;
29438 +                                       return;
29439 +                               }
29440 +
29441 +                               break;
29442 +                       }
29443 +
29444 +                       printk("mtp008.o: Invalid sensor type %ld "
29445 +                              "for sensor %d; must be %s.\n",
29446 +                              results[0], nr, opts);
29447 +               }
29448 +       }
29449 +}
29450 +
29451 +static int __init sm_mtp008_init(void)
29452 +{
29453 +       printk("mtp008.o version %s (%s)\n", LM_VERSION, LM_DATE);
29454 +       return i2c_add_driver(&mtp008_driver);
29455 +}
29456 +
29457 +static void __exit sm_mtp008_exit(void)
29458 +{
29459 +       i2c_del_driver(&mtp008_driver);
29460 +}
29461 +
29462 +
29463 +
29464 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
29465 +             "Philip Edelbrock <phil@netroedge.com>, "
29466 +             "and Kris Van Hees <aedil@alchar.org>");
29467 +MODULE_DESCRIPTION("MTP008 driver");
29468 +
29469 +module_init(sm_mtp008_init);
29470 +module_exit(sm_mtp008_exit);
29471 --- linux-old/drivers/sensors/pc87360.c Thu Jan  1 00:00:00 1970
29472 +++ linux/drivers/sensors/pc87360.c     Mon Dec 13 20:18:51 2004
29473 @@ -0,0 +1,1357 @@
29474 +/*
29475 + *  pc87360.c - Part of lm_sensors, Linux kernel modules
29476 + *              for hardware monitoring
29477 + *  Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> 
29478 + *
29479 + *  Copied from smsc47m1.c:
29480 + *  Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
29481 + *
29482 + *  This program is free software; you can redistribute it and/or modify
29483 + *  it under the terms of the GNU General Public License as published by
29484 + *  the Free Software Foundation; either version 2 of the License, or
29485 + *  (at your option) any later version.
29486 + *
29487 + *  This program is distributed in the hope that it will be useful,
29488 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
29489 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29490 + *  GNU General Public License for more details.
29491 + *
29492 + *  You should have received a copy of the GNU General Public License
29493 + *  along with this program; if not, write to the Free Software
29494 + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29495 + *
29496 + *  Supports the following chips:
29497 + *
29498 + *  Chip        #vin    #fan    #pwm    #temp   devid
29499 + *  PC87360     -       2       2       -       0xE1
29500 + *  PC87363     -       2       2       -       0xE8
29501 + *  PC87364     -       3       3       -       0xE4
29502 + *  PC87365     11      3       3       2       0xE5
29503 + *  PC87366     11      3       3       3-4     0xE9
29504 + *
29505 + *  This driver assumes that no more than one chip is present, and the
29506 + *  standard Super-I/O address is used (0x2E/0x2F).
29507 + */
29508 +
29509 +#include <linux/module.h>
29510 +#include <linux/slab.h>
29511 +#include <linux/ioport.h>
29512 +#include <linux/i2c.h>
29513 +#include <linux/i2c-proc.h>
29514 +#include <linux/init.h>
29515 +#include <asm/io.h>
29516 +#define LM_DATE "20041007"
29517 +#define LM_VERSION "2.8.8"
29518 +#include <linux/sensors_vid.h>
29519 +
29520 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
29521 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
29522 +static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
29523 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
29524 +static struct i2c_force_data forces[] = {{NULL}};
29525 +static u8 devid;
29526 +static unsigned int extra_isa[] = { 0x0000, 0x0000, 0x0000 };
29527 +static u8 confreg[4];
29528 +
29529 +enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 };
29530 +static struct i2c_address_data addr_data = {
29531 +       .normal_i2c             = normal_i2c,
29532 +       .normal_i2c_range       = normal_i2c_range,
29533 +       .normal_isa             = normal_isa,
29534 +       .normal_isa_range       = normal_isa_range,
29535 +       .probe                  = normal_i2c,           /* cheat */
29536 +       .probe_range            = normal_i2c_range,     /* cheat */
29537 +       .ignore                 = normal_i2c,           /* cheat */
29538 +       .ignore_range           = normal_i2c_range,     /* cheat */
29539 +       .forces                 = forces,
29540 +};
29541 +
29542 +static int init = 1;
29543 +MODULE_PARM(init, "i");
29544 +MODULE_PARM_DESC(init,
29545 +       "Chip initialization level:\n"
29546 +       " 0: None\n"
29547 +       "*1: Forcibly enable internal voltage and temperature channels, except in9\n"
29548 +       " 2: Forcibly enable all voltage and temperature channels, except in9\n"
29549 +       " 3: Forcibly enable all voltage and temperature channels, including in9");
29550 +
29551 +/*
29552 + * Super-I/O registers and operations
29553 + */
29554 +
29555 +#define REG    0x2e    /* The register to read/write */
29556 +#define VAL    0x2f    /* The value to read/write */
29557 +
29558 +#define DEV    0x07    /* Register: Logical device select */
29559 +#define DEVID  0x20    /* Register: Device ID */
29560 +#define ACT    0x30    /* Register: Device activation */
29561 +#define BASE   0x60    /* Register: Base address */
29562 +
29563 +#define FSCM   0x09    /* Logical device: fans */
29564 +#define VLM    0x0d    /* Logical device: voltages */
29565 +#define TMS    0x0e    /* Logical device: temperatures */
29566 +static const u8 logdev[3] = { FSCM, VLM, TMS };
29567 +
29568 +#define LD_FAN         0
29569 +#define LD_IN          1
29570 +#define LD_TEMP                2
29571 +
29572 +static inline void superio_outb(int reg, int val)
29573 +{
29574 +       outb(reg, REG);
29575 +       outb(val, VAL);
29576 +}
29577 +
29578 +static inline int superio_inb(int reg)
29579 +{
29580 +       outb(reg, REG);
29581 +       return inb(VAL);
29582 +}
29583 +
29584 +static inline void superio_exit(void)
29585 +{
29586 +       outb(0x02, REG);
29587 +       outb(0x02, VAL);
29588 +}
29589 +
29590 +/*
29591 + * Logical devices
29592 + */
29593 +
29594 +#define PC87360_EXTENT         0x10
29595 +#define PC87365_REG_BANK       0x09
29596 +#define NO_BANK                        0xff
29597 +
29598 +/*
29599 + * Fan registers and conversions
29600 + */
29601 +
29602 +/* nr has to be 0 or 1 (PC87360/87363) or 2 (PC87364/87365/87366) */
29603 +#define PC87360_REG_PRESCALE(nr)       (0x00 + 2 * (nr))
29604 +#define PC87360_REG_PWM(nr)            (0x01 + 2 * (nr))
29605 +#define PC87360_REG_FAN_MIN(nr)                (0x06 + 3 * (nr))
29606 +#define PC87360_REG_FAN(nr)            (0x07 + 3 * (nr))
29607 +#define PC87360_REG_FAN_STATUS(nr)     (0x08 + 3 * (nr))
29608 +
29609 +#define FAN_FROM_REG(val,div)          ((val)==0?0: \
29610 +                                        480000/((val)*(div)))
29611 +#define FAN_TO_REG(val,div)            ((val)<=100?0: \
29612 +                                        480000/((val)*(div)))
29613 +#define FAN_DIV_FROM_REG(val)          (1 << ((val >> 5) & 0x03))
29614 +#define FAN_DIV_TO_REG(val)            ((val)==8?0x60:(val)==4?0x40: \
29615 +                                        (val)==1?0x00:0x20)
29616 +#define FAN_STATUS_FROM_REG(val)       ((val) & 0x07)
29617 +
29618 +#define FAN_CONFIG_MONITOR(val,nr)     (((val) >> (2 + nr * 3)) & 1)
29619 +#define FAN_CONFIG_CONTROL(val,nr)     (((val) >> (3 + nr * 3)) & 1)
29620 +#define FAN_CONFIG_INVERT(val,nr)      (((val) >> (4 + nr * 3)) & 1)
29621 +
29622 +#define PWM_FROM_REG(val,inv)          ((inv) ? 255 - (val) : (val))
29623 +static inline u8 PWM_TO_REG(int val, int inv)
29624 +{
29625 +       if (inv)
29626 +               val = 255 - val;
29627 +       if (val < 0)
29628 +               return 0;
29629 +       if (val > 255)
29630 +               return 255;
29631 +       return val;
29632 +}
29633 +
29634 +/*
29635 + * Voltage registers and conversions
29636 + */
29637 +
29638 +#define PC87365_REG_IN_CONVRATE                0x07
29639 +#define PC87365_REG_IN_CONFIG          0x08
29640 +#define PC87365_REG_IN                 0x0B
29641 +#define PC87365_REG_IN_MIN             0x0D
29642 +#define PC87365_REG_IN_MAX             0x0C
29643 +#define PC87365_REG_IN_STATUS          0x0A
29644 +#define PC87365_REG_IN_ALARMS1         0x00
29645 +#define PC87365_REG_IN_ALARMS2         0x01
29646 +#define PC87365_REG_VID                        0x06
29647 +
29648 +#define IN_FROM_REG(val,ref)           (((val) * (ref) + 128) / 256)
29649 +#define IN_TO_REG(val,ref)             ((val)<0 ? 0 : \
29650 +                                        (val)*256>=(ref)*255 ? 255: \
29651 +                                        ((val) * 256 + (ref) / 2) / (ref))
29652 +
29653 +/*
29654 + * Temperature registers and conversions
29655 + */
29656 +
29657 +#define PC87365_REG_TEMP_CONFIG                0x08
29658 +#define PC87365_REG_TEMP               0x0B
29659 +#define PC87365_REG_TEMP_MIN           0x0D
29660 +#define PC87365_REG_TEMP_MAX           0x0C
29661 +#define PC87365_REG_TEMP_CRIT          0x0E
29662 +#define PC87365_REG_TEMP_STATUS                0x0A
29663 +#define PC87365_REG_TEMP_ALARMS                0x00
29664 +
29665 +#define TEMP_FROM_REG(val)             ((val)&0x80 ? (val) - 0x100 : (val))
29666 +#define TEMP_TO_REG(val)               ((val)<-55 ? 201 : (val)>127 ? 0x7F : \
29667 +                                        (val)<0 ? (val) + 0x100 : (val))
29668 +
29669 +struct pc87360_data {
29670 +       struct i2c_client client;
29671 +       struct semaphore lock;
29672 +       int sysctl_id;
29673 +       int address[3];
29674 +
29675 +       struct semaphore update_lock;
29676 +       char valid;             /* !=0 if following fields are valid */
29677 +       unsigned long last_updated;     /* In jiffies */
29678 +
29679 +       u8 fannr, innr, tempnr;
29680 +
29681 +       u8 fan[3];              /* Register value */
29682 +       u8 fan_min[3];          /* Register value */
29683 +       u8 fan_status[3];       /* Register value */
29684 +       u8 pwm[3];              /* Register value */
29685 +       u16 fan_conf;           /* Configuration register values, combined */
29686 +
29687 +       u16 in_vref;            /* 10mV/bit */
29688 +       u8 in[14];              /* Register value */
29689 +       u8 in_min[14];          /* Register value */
29690 +       u8 in_max[14];          /* Register value */
29691 +       u8 in_crit[3];          /* Register value */
29692 +       u8 in_status[14];       /* Register value */
29693 +       u16 in_alarms;          /* Register values, combined, masked */
29694 +       u8 vid_conf;            /* Configuration register value */
29695 +       u8 vrm;
29696 +       u8 vid;                 /* Register value */
29697 +
29698 +       u8 temp[3];             /* Register value */
29699 +       u8 temp_min[3];         /* Register value */
29700 +       u8 temp_max[3];         /* Register value */
29701 +       u8 temp_crit[3];        /* Register value */
29702 +       u8 temp_status[3];      /* Register value */
29703 +       u8 temp_alarms;         /* Register value, masked */
29704 +};
29705 +
29706 +
29707 +static int pc87360_attach_adapter(struct i2c_adapter *adapter);
29708 +static int pc87360_detect(struct i2c_adapter *adapter, int address,
29709 +                         unsigned short flags, int kind);
29710 +static int pc87360_detach_client(struct i2c_client *client);
29711 +
29712 +static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
29713 +                             u8 reg);
29714 +static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
29715 +                               u8 reg, u8 value);
29716 +static void pc87360_init_client(struct i2c_client *client, int use_thermistors);
29717 +static void pc87360_update_client(struct i2c_client *client);
29718 +static int pc87360_find(u8 *devid, int *address);
29719 +
29720 +
29721 +void pc87365_alarms(struct i2c_client *client, int operation, int ctl_name,
29722 +                   int *nrels_mag, long *results);
29723 +
29724 +static void pc87360_fan(struct i2c_client *client, int operation,
29725 +                       int ctl_name, int *nrels_mag, long *results);
29726 +static void pc87360_fan_status(struct i2c_client *client, int operation,
29727 +                              int ctl_name, int *nrels_mag, long *results);
29728 +static void pc87360_fan_div(struct i2c_client *client, int operation,
29729 +                           int ctl_name, int *nrels_mag, long *results);
29730 +static void pc87360_pwm(struct i2c_client *client, int operation,
29731 +                       int ctl_name, int *nrels_mag, long *results);
29732 +
29733 +void pc87365_in(struct i2c_client *client, int operation, int ctl_name,
29734 +               int *nrels_mag, long *results);
29735 +void pc87365_in_status(struct i2c_client *client, int operation, int ctl_name,
29736 +                      int *nrels_mag, long *results);
29737 +void pc87365_vid(struct i2c_client *client, int operation, int ctl_name,
29738 +                int *nrels_mag, long *results);
29739 +void pc87365_vrm(struct i2c_client *client, int operation, int ctl_name,
29740 +                int *nrels_mag, long *results);
29741 +
29742 +void pc87365_temp(struct i2c_client *client, int operation, int ctl_name,
29743 +                 int *nrels_mag, long *results);
29744 +void pc87365_temp_status(struct i2c_client *client, int operation, int ctl_name,
29745 +                        int *nrels_mag, long *results);
29746 +
29747 +static int pc87360_id = 0;
29748 +
29749 +static struct i2c_driver pc87360_driver = {
29750 +       .owner          = THIS_MODULE,
29751 +       .name           = "PC8736x hardware monitor",
29752 +       .flags          = I2C_DF_NOTIFY,
29753 +       .attach_adapter = pc87360_attach_adapter,
29754 +       .detach_client  = pc87360_detach_client,
29755 +};
29756 +
29757 +/* -- SENSORS SYSCTL START -- */
29758 +
29759 +#define PC87365_SYSCTL_ALARMS          100 /* bit field */
29760 +
29761 +#define PC87360_SYSCTL_FAN1            1101 /* Rotations/min */
29762 +#define PC87360_SYSCTL_FAN2            1102
29763 +#define PC87360_SYSCTL_FAN3            1103 /* not for PC87360/PC87363 */
29764 +#define PC87360_SYSCTL_FAN_DIV         1201 /* 1, 2, 4 or 8 */
29765 +#define PC87360_SYSCTL_FAN1_STATUS     1301 /* bit field */
29766 +#define PC87360_SYSCTL_FAN2_STATUS     1302
29767 +#define PC87360_SYSCTL_FAN3_STATUS     1303 /* not for PC87360/PC87363 */
29768 +#define PC87360_SYSCTL_PWM1            1401 /* 0-255 */
29769 +#define PC87360_SYSCTL_PWM2            1402
29770 +#define PC87360_SYSCTL_PWM3            1403 /* not for PC87360/PC87363 */
29771 +
29772 +#define PC87360_STATUS_FAN_READY       0x01
29773 +#define PC87360_STATUS_FAN_LOW         0x02
29774 +#define PC87360_STATUS_FAN_OVERFLOW    0x04
29775 +
29776 +#define PC87365_SYSCTL_IN0             2100 /* mV */
29777 +#define PC87365_SYSCTL_IN1             2101
29778 +#define PC87365_SYSCTL_IN2             2102
29779 +#define PC87365_SYSCTL_IN3             2103
29780 +#define PC87365_SYSCTL_IN4             2104
29781 +#define PC87365_SYSCTL_IN5             2105
29782 +#define PC87365_SYSCTL_IN6             2106
29783 +#define PC87365_SYSCTL_IN7             2107
29784 +#define PC87365_SYSCTL_IN8             2108
29785 +#define PC87365_SYSCTL_IN9             2109
29786 +#define PC87365_SYSCTL_IN10            2110
29787 +#define PC87365_SYSCTL_TEMP4           2111 /* not for PC87365 */
29788 +#define PC87365_SYSCTL_TEMP5           2112 /* not for PC87365 */
29789 +#define PC87365_SYSCTL_TEMP6           2113 /* not for PC87365 */
29790 +#define PC87365_SYSCTL_IN0_STATUS      2300 /* bit field */
29791 +#define PC87365_SYSCTL_IN1_STATUS      2301
29792 +#define PC87365_SYSCTL_IN2_STATUS      2302
29793 +#define PC87365_SYSCTL_IN3_STATUS      2303
29794 +#define PC87365_SYSCTL_IN4_STATUS      2304
29795 +#define PC87365_SYSCTL_IN5_STATUS      2305
29796 +#define PC87365_SYSCTL_IN6_STATUS      2306
29797 +#define PC87365_SYSCTL_IN7_STATUS      2307
29798 +#define PC87365_SYSCTL_IN8_STATUS      2308
29799 +#define PC87365_SYSCTL_IN9_STATUS      2309
29800 +#define PC87365_SYSCTL_IN10_STATUS     2310
29801 +#define PC87365_SYSCTL_TEMP4_STATUS    2311 /* not for PC87365 */
29802 +#define PC87365_SYSCTL_TEMP5_STATUS    2312 /* not for PC87365 */
29803 +#define PC87365_SYSCTL_TEMP6_STATUS    2313 /* not for PC87365 */
29804 +
29805 +#define PC87365_SYSCTL_VID             2400
29806 +#define PC87365_SYSCTL_VRM             2401
29807 +
29808 +#define PC87365_STATUS_IN_MIN          0x02
29809 +#define PC87365_STATUS_IN_MAX          0x04
29810 +
29811 +#define PC87365_SYSCTL_TEMP1           3101 /* degrees Celcius */
29812 +#define PC87365_SYSCTL_TEMP2           3102
29813 +#define PC87365_SYSCTL_TEMP3           3103 /* not for PC87365 */
29814 +#define PC87365_SYSCTL_TEMP1_STATUS    3301 /* bit field */
29815 +#define PC87365_SYSCTL_TEMP2_STATUS    3302
29816 +#define PC87365_SYSCTL_TEMP3_STATUS    3303 /* not for PC87365 */
29817 +
29818 +#define PC87365_STATUS_TEMP_MIN                0x02
29819 +#define PC87365_STATUS_TEMP_MAX                0x04
29820 +#define PC87365_STATUS_TEMP_CRIT       0x08
29821 +#define PC87365_STATUS_TEMP_OPEN       0x40
29822 +
29823 +/* -- SENSORS SYSCTL END -- */
29824 +
29825 +static ctl_table pc87360_dir_table_template[] = { /* PC87363 and PC87364 too */
29826 +       {PC87360_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
29827 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan},
29828 +       {PC87360_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL,
29829 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan},
29830 +       {PC87360_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL,
29831 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan},
29832 +       {PC87360_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
29833 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_div},
29834 +       {PC87360_SYSCTL_FAN1_STATUS, "fan1_status", NULL, 0, 0444, NULL,
29835 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status},
29836 +       {PC87360_SYSCTL_FAN2_STATUS, "fan2_status", NULL, 0, 0444, NULL,
29837 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status},
29838 +       {PC87360_SYSCTL_FAN3_STATUS, "fan3_status", NULL, 0, 0444, NULL,
29839 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status},
29840 +       {PC87360_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL,
29841 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm},
29842 +       {PC87360_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL,
29843 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm},
29844 +       {PC87360_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL,
29845 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm},
29846 +       {0}
29847 +};
29848 +
29849 +static ctl_table pc87365_dir_table_template[] = { /* PC87366 too */
29850 +       {PC87365_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
29851 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_alarms},
29852 +       {PC87360_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
29853 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan},
29854 +       {PC87360_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL,
29855 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan},
29856 +       {PC87360_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL,
29857 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan},
29858 +       {PC87360_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
29859 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_div},
29860 +       {PC87360_SYSCTL_FAN1_STATUS, "fan1_status", NULL, 0, 0444, NULL,
29861 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status},
29862 +       {PC87360_SYSCTL_FAN2_STATUS, "fan2_status", NULL, 0, 0444, NULL,
29863 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status},
29864 +       {PC87360_SYSCTL_FAN3_STATUS, "fan3_status", NULL, 0, 0444, NULL,
29865 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status},
29866 +       {PC87360_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL,
29867 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm},
29868 +       {PC87360_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL,
29869 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm},
29870 +       {PC87360_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL,
29871 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm},
29872 +       {PC87365_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL,
29873 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29874 +       {PC87365_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL,
29875 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29876 +       {PC87365_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL,
29877 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29878 +       {PC87365_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL,
29879 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29880 +       {PC87365_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL,
29881 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29882 +       {PC87365_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL,
29883 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29884 +       {PC87365_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL,
29885 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29886 +       {PC87365_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL,
29887 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29888 +       {PC87365_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL,
29889 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29890 +       {PC87365_SYSCTL_IN9, "in9", NULL, 0, 0644, NULL,
29891 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29892 +       {PC87365_SYSCTL_IN10, "in10", NULL, 0, 0644, NULL,
29893 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29894 +       {PC87365_SYSCTL_IN0_STATUS, "in0_status", NULL, 0, 0444, NULL,
29895 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29896 +       {PC87365_SYSCTL_IN1_STATUS, "in1_status", NULL, 0, 0444, NULL,
29897 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29898 +       {PC87365_SYSCTL_IN2_STATUS, "in2_status", NULL, 0, 0444, NULL,
29899 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29900 +       {PC87365_SYSCTL_IN3_STATUS, "in3_status", NULL, 0, 0444, NULL,
29901 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29902 +       {PC87365_SYSCTL_IN4_STATUS, "in4_status", NULL, 0, 0444, NULL,
29903 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29904 +       {PC87365_SYSCTL_IN5_STATUS, "in5_status", NULL, 0, 0444, NULL,
29905 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29906 +       {PC87365_SYSCTL_IN6_STATUS, "in6_status", NULL, 0, 0444, NULL,
29907 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29908 +       {PC87365_SYSCTL_IN7_STATUS, "in7_status", NULL, 0, 0444, NULL,
29909 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29910 +       {PC87365_SYSCTL_IN8_STATUS, "in8_status", NULL, 0, 0444, NULL,
29911 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29912 +       {PC87365_SYSCTL_IN9_STATUS, "in9_status", NULL, 0, 0444, NULL,
29913 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29914 +       {PC87365_SYSCTL_IN10_STATUS, "in10_status", NULL, 0, 0444, NULL,
29915 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29916 +       {PC87365_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL,
29917 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp},
29918 +       {PC87365_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
29919 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp},
29920 +       {PC87365_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
29921 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp},
29922 +       {PC87365_SYSCTL_TEMP4, "temp4", NULL, 0, 0644, NULL,
29923 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29924 +       {PC87365_SYSCTL_TEMP5, "temp5", NULL, 0, 0644, NULL,
29925 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29926 +       {PC87365_SYSCTL_TEMP6, "temp6", NULL, 0, 0644, NULL,
29927 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in},
29928 +       {PC87365_SYSCTL_TEMP1_STATUS, "temp1_status", NULL, 0, 0444, NULL,
29929 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp_status},
29930 +       {PC87365_SYSCTL_TEMP2_STATUS, "temp2_status", NULL, 0, 0444, NULL,
29931 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp_status},
29932 +       {PC87365_SYSCTL_TEMP3_STATUS, "temp3_status", NULL, 0, 0444, NULL,
29933 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp_status},
29934 +       {PC87365_SYSCTL_TEMP4_STATUS, "temp4_status", NULL, 0, 0444, NULL,
29935 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29936 +       {PC87365_SYSCTL_TEMP5_STATUS, "temp5_status", NULL, 0, 0444, NULL,
29937 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29938 +       {PC87365_SYSCTL_TEMP6_STATUS, "temp6_status", NULL, 0, 0444, NULL,
29939 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status},
29940 +       {PC87365_SYSCTL_VID, "vid", NULL, 0, 0444, NULL,
29941 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_vid},
29942 +       {PC87365_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL,
29943 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_vrm},
29944 +       {0}
29945 +};
29946 +
29947 +static int pc87360_attach_adapter(struct i2c_adapter *adapter)
29948 +{
29949 +       return i2c_detect(adapter, &addr_data, pc87360_detect);
29950 +}
29951 +
29952 +static int pc87360_find(u8 *devid, int *address)
29953 +{
29954 +       u16 val;
29955 +       int i;
29956 +       int nrdev; /* logical device count */
29957 +
29958 +       /* No superio_enter */
29959 +
29960 +       /* Identify device */
29961 +       val = superio_inb(DEVID);
29962 +       switch (val) {
29963 +       case 0xE1: /* PC87360 */
29964 +       case 0xE8: /* PC87363 */
29965 +       case 0xE4: /* PC87364 */
29966 +               nrdev = 1;
29967 +               break;
29968 +       case 0xE5: /* PC87365 */
29969 +       case 0xE9: /* PC87366 */
29970 +               nrdev = 3;
29971 +               break;
29972 +       default:
29973 +               superio_exit();
29974 +               return -ENODEV;
29975 +       }
29976 +       /* Remember the device id */
29977 +       *devid = val;
29978 +
29979 +       for (i = 0; i < nrdev; i++) {
29980 +               /* select logical device */
29981 +               superio_outb(DEV, logdev[i]);
29982 +
29983 +               val = superio_inb(ACT);
29984 +               if (!(val & 0x01)) {
29985 +                       printk(KERN_INFO "pc87360.o: Device 0x%02x not "
29986 +                              "activated\n", logdev[i]);
29987 +                       continue;
29988 +               }
29989 +
29990 +               val = (superio_inb(BASE) << 8)
29991 +                   | superio_inb(BASE + 1);
29992 +               if (!val) {
29993 +                       printk(KERN_INFO "pc87360.o: Base address not set for "
29994 +                              "device 0x%02x\n", logdev[i]);
29995 +                       continue;
29996 +               }
29997 +
29998 +               address[i] = val;
29999 +
30000 +               if (i==0) { /* Fans */
30001 +                       confreg[0] = superio_inb(0xF0);
30002 +                       confreg[1] = superio_inb(0xF1);
30003 +                       
30004 +#ifdef DEBUG
30005 +                       printk(KERN_DEBUG "pc87360.o: Fan 1: mon=%d "
30006 +                              "ctrl=%d inv=%d\n", (confreg[0]>>2)&1,
30007 +                              (confreg[0]>>3)&1, (confreg[0]>>4)&1);
30008 +                       printk(KERN_DEBUG "pc87360.o: Fan 2: mon=%d "
30009 +                              "ctrl=%d inv=%d\n", (confreg[0]>>5)&1,
30010 +                              (confreg[0]>>6)&1, (confreg[0]>>7)&1);
30011 +                       printk(KERN_DEBUG "pc87360.o: Fan 3: mon=%d "
30012 +                              "ctrl=%d inv=%d\n", confreg[1]&1,
30013 +                              (confreg[1]>>1)&1, (confreg[1]>>2)&1);
30014 +#endif
30015 +               } else if (i==1) { /* Voltages */
30016 +                       /* Are we using thermistors? */
30017 +                       if (*devid == 0xE9) { /* PC87366 */
30018 +                               /* These registers are not logical-device
30019 +                                  specific, just that we won't need them if
30020 +                                  we don't use the VLM device */
30021 +                               confreg[2] = superio_inb(0x2B);
30022 +                               confreg[3] = superio_inb(0x25);
30023 +
30024 +                               if (confreg[2] & 0x40) {
30025 +                                       printk(KERN_INFO "pc87360.o: Using "
30026 +                                              "thermistors for temperature "
30027 +                                              "monitoring\n");
30028 +                               }
30029 +                               if (confreg[3] & 0xE0) {
30030 +                                       printk(KERN_INFO "pc87360.o: VID "
30031 +                                              "inputs routed (mode %u)\n",
30032 +                                               confreg[3] >> 5);
30033 +                               }
30034 +                       }
30035 +               }
30036 +       }
30037 +
30038 +       superio_exit();
30039 +       return 0;
30040 +}
30041 +
30042 +/* We don't really care about the address.
30043 +   Read from extra_isa instead. */
30044 +int pc87360_detect(struct i2c_adapter *adapter, int address,
30045 +                  unsigned short flags, int kind)
30046 +{
30047 +       int i;
30048 +       struct i2c_client *new_client;
30049 +       struct pc87360_data *data;
30050 +       int err = 0;
30051 +       const char *type_name = "pc87360";
30052 +       const char *client_name = "PC8736x chip";
30053 +       ctl_table *template = pc87360_dir_table_template;
30054 +       int use_thermistors = 0;
30055 +
30056 +       if (!i2c_is_isa_adapter(adapter)) {
30057 +               return 0;
30058 +       }
30059 +
30060 +       for (i = 0; i < 3; i++) {
30061 +               if (extra_isa[i]
30062 +                && check_region(extra_isa[i], PC87360_EXTENT)) {
30063 +                       printk(KERN_ERR "pc87360.o: Region 0x%x-0x%x already "
30064 +                              "in use!\n", extra_isa[i],
30065 +                              extra_isa[i]+PC87360_EXTENT-1);
30066 +                       return -ENODEV;
30067 +               }
30068 +       }
30069 +
30070 +       if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL))) {
30071 +               return -ENOMEM;
30072 +       }
30073 +       memset(data, 0x00, sizeof(struct pc87360_data));
30074 +
30075 +       new_client = &data->client;
30076 +       new_client->addr = address;
30077 +       init_MUTEX(&data->lock);
30078 +       new_client->data = data;
30079 +       new_client->adapter = adapter;
30080 +       new_client->driver = &pc87360_driver;
30081 +       new_client->flags = 0;
30082 +
30083 +       data->fannr = 2;
30084 +       data->innr = 0;
30085 +       data->tempnr = 0;
30086 +       
30087 +       switch (devid) {
30088 +       case 0xe8:
30089 +               type_name = "pc87363";
30090 +               break;
30091 +       case 0xe4:
30092 +               type_name = "pc87364";
30093 +               data->fannr = 3;
30094 +               break;
30095 +       case 0xe5:
30096 +               type_name = "pc87365";
30097 +               template = pc87365_dir_table_template;
30098 +               data->fannr = extra_isa[0] ? 3 : 0;
30099 +               data->innr = extra_isa[1] ? 11 : 0;
30100 +               data->tempnr = extra_isa[2] ? 2 : 0;
30101 +               break;
30102 +       case 0xe9:
30103 +               type_name = "pc87366";
30104 +               template = pc87365_dir_table_template;
30105 +               data->fannr = extra_isa[0] ? 3 : 0;
30106 +               data->innr = extra_isa[1] ? 14 : 0;
30107 +               data->tempnr = extra_isa[2] ? 3 : 0;
30108 +               break;
30109 +       }
30110 +
30111 +       /* Retrieve the fans configuration from Super-I/O space */
30112 +       if (data->fannr)
30113 +               data->fan_conf = confreg[0] | (confreg[1] << 8);
30114 +
30115 +       for (i = 0; i < 3; i++) {
30116 +               if ((data->address[i] = extra_isa[i])) {
30117 +                       request_region(extra_isa[i], PC87360_EXTENT, "pc87360");
30118 +               }
30119 +       }
30120 +       strcpy(new_client->name, client_name);
30121 +
30122 +       new_client->id = pc87360_id++;
30123 +       data->valid = 0;
30124 +       init_MUTEX(&data->update_lock);
30125 +
30126 +       if ((err = i2c_attach_client(new_client)))
30127 +               goto ERROR1;
30128 +
30129 +       /* Use the correct reference voltage
30130 +          Unless both the VLM and the TMS logical devices agree to
30131 +          use an external Vref, the internal one is used. */
30132 +       if (data->innr) {
30133 +               i = pc87360_read_value(data, LD_IN, NO_BANK,
30134 +                                      PC87365_REG_IN_CONFIG);
30135 +               if (data->tempnr) {
30136 +                       i &= pc87360_read_value(data, LD_TEMP, NO_BANK,
30137 +                                               PC87365_REG_TEMP_CONFIG);
30138 +               }
30139 +               data->in_vref = (i&0x02) ? 3025 : 2966;
30140 +#ifdef DEBUG
30141 +               printk(KERN_DEBUG "pc87360.o: Using %s reference voltage\n",
30142 +                      (i&0x02) ? "external" : "internal");
30143 +#endif
30144 +
30145 +               data->vid_conf = confreg[3];
30146 +               data->vrm = 90;
30147 +       }
30148 +
30149 +       /* Fan clock dividers may be needed before any data is read */
30150 +       for (i = 0; i < data->fannr; i++) {
30151 +               data->fan_status[i] = pc87360_read_value(data, LD_FAN,
30152 +                                     NO_BANK, PC87360_REG_FAN_STATUS(i));
30153 +       }
30154 +
30155 +       if (init > 0) {
30156 +               if (devid == 0xe9 && data->address[1]) /* PC87366 */
30157 +                       use_thermistors = confreg[2] & 0x40;
30158 +
30159 +               pc87360_init_client(new_client, use_thermistors);
30160 +       }
30161 +
30162 +       if ((i = i2c_register_entry((struct i2c_client *) new_client,
30163 +                                   type_name, template)) < 0) {
30164 +               err = i;
30165 +               goto ERROR2;
30166 +       }
30167 +       data->sysctl_id = i;
30168 +
30169 +       return 0;
30170 +
30171 +ERROR2:
30172 +       i2c_detach_client(new_client);
30173 +ERROR1:
30174 +       for (i = 0; i < 3; i++) {
30175 +               if (data->address[i]) {
30176 +                       release_region(data->address[i], PC87360_EXTENT);
30177 +               }
30178 +       }
30179 +       kfree(data);
30180 +       return err;
30181 +}
30182 +
30183 +static int pc87360_detach_client(struct i2c_client *client)
30184 +{
30185 +       struct pc87360_data *data = client->data;
30186 +       int i, err;
30187 +
30188 +       i2c_deregister_entry(data->sysctl_id);
30189 +
30190 +       if ((err = i2c_detach_client(client))) {
30191 +               printk(KERN_ERR "pc87360.o: Client deregistration failed, "
30192 +                      "client not detached.\n");
30193 +               return err;
30194 +       }
30195 +
30196 +       for (i = 0; i < 3; i++) {
30197 +               if (data->address[i]) {
30198 +                       release_region(data->address[i], PC87360_EXTENT);
30199 +               }
30200 +       }
30201 +       kfree(client->data);
30202 +
30203 +       return 0;
30204 +}
30205 +
30206 +/* ldi is the logical device index
30207 +   bank is for voltages and temperatures only */
30208 +static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
30209 +                             u8 reg)
30210 +{
30211 +       int res;
30212 +
30213 +       down(&(data->lock));
30214 +       if (bank != NO_BANK) {
30215 +               outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
30216 +       }
30217 +       res = inb_p(data->address[ldi] + reg);
30218 +       up(&(data->lock));
30219 +       return res;
30220 +}
30221 +
30222 +static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
30223 +                               u8 reg, u8 value)
30224 +{
30225 +       down(&(data->lock));
30226 +       if (bank != NO_BANK) {
30227 +               outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
30228 +       }
30229 +       outb_p(value, data->address[ldi] + reg);
30230 +       up(&(data->lock));
30231 +}
30232 +
30233 +static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
30234 +{
30235 +       struct pc87360_data *data = client->data;
30236 +       int i, nr;
30237 +       const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 };
30238 +       const u8 init_temp[3] = { 2, 2, 1 };
30239 +       u8 reg;
30240 +
30241 +       if (init >= 2 && data->innr) {
30242 +               reg = pc87360_read_value(data, LD_IN, NO_BANK,
30243 +                                        PC87365_REG_IN_CONVRATE);
30244 +               printk(KERN_INFO "pc87360.o: VLM conversion set to"
30245 +                      "1s period, 160us delay\n");
30246 +               pc87360_write_value(data, LD_IN, NO_BANK,
30247 +                                   PC87365_REG_IN_CONVRATE,
30248 +                                   (reg & 0xC0) | 0x11);
30249 +       }
30250 +
30251 +       nr = data->innr < 11 ? data->innr : 11;
30252 +       for (i=0; i<nr; i++) {
30253 +               if (init >= init_in[i]) {
30254 +                       /* Forcibly enable voltage channel */
30255 +                       reg = pc87360_read_value(data, LD_IN, i,
30256 +                                                PC87365_REG_IN_STATUS);
30257 +                       if (!(reg & 0x01)) {
30258 +#ifdef DEBUG
30259 +                               printk(KERN_DEBUG "pc87360.o: Forcibly "
30260 +                                      "enabling in%d\n", i);
30261 +#endif
30262 +                               pc87360_write_value(data, LD_IN, i,
30263 +                                                   PC87365_REG_IN_STATUS,
30264 +                                                   (reg & 0x68) | 0x87);
30265 +                       }
30266 +               }
30267 +       }
30268 +
30269 +       /* We can't blindly trust the Super-I/O space configuration bit,
30270 +          most BIOS won't set it properly */
30271 +       for (i=11; i<data->innr; i++) {
30272 +               reg = pc87360_read_value(data, LD_IN, i,
30273 +                                        PC87365_REG_TEMP_STATUS);
30274 +               use_thermistors = use_thermistors || (reg & 0x01);
30275 +       }
30276 +
30277 +       i = use_thermistors ? 2 : 0;
30278 +       for (; i<data->tempnr; i++) {
30279 +               if (init >= init_temp[i]) {
30280 +                       /* Forcibly enable temperature channel */
30281 +                       reg = pc87360_read_value(data, LD_TEMP, i,
30282 +                                                PC87365_REG_TEMP_STATUS);
30283 +                       if (!(reg & 0x01)) {
30284 +#ifdef DEBUG
30285 +                               printk(KERN_DEBUG "pc87360.o: Forcibly "
30286 +                                      "enabling temp%d\n", i+1);
30287 +#endif
30288 +                               pc87360_write_value(data, LD_TEMP, i,
30289 +                                                   PC87365_REG_TEMP_STATUS,
30290 +                                                   0xCF);
30291 +                       }
30292 +               }
30293 +       }
30294 +
30295 +       if (use_thermistors) {
30296 +               for (i=11; i<data->innr; i++) {
30297 +                       if (init >= init_in[i]) {
30298 +                               /* The pin may already be used by thermal
30299 +                                  diodes */
30300 +                               reg = pc87360_read_value(data, LD_TEMP, (i-11)/2,
30301 +                                                        PC87365_REG_TEMP_STATUS);
30302 +                               if (reg & 0x01) {
30303 +#ifdef DEBUG
30304 +                                       printk(KERN_DEBUG "pc87360.o: Skipping "
30305 +                                              "temp%d, pin already in use by ",
30306 +                                              "temp%d\n", i-7, (i-11)/2);
30307 +#endif
30308 +                                       continue;
30309 +                               }
30310 +                       
30311 +                               /* Forcibly enable thermistor channel */
30312 +                               reg = pc87360_read_value(data, LD_IN, i,
30313 +                                                        PC87365_REG_IN_STATUS);
30314 +                               if (!(reg & 0x01)) {
30315 +#ifdef DEBUG
30316 +                                       printk(KERN_DEBUG "pc87360.o: Forcibly "
30317 +                                              "enabling temp%d\n", i-7);
30318 +#endif
30319 +                                       pc87360_write_value(data, LD_IN, i,
30320 +                                                           PC87365_REG_TEMP_STATUS,
30321 +                                                           (reg & 0x60) | 0x8F);
30322 +                               }
30323 +                       }
30324 +               }
30325 +       }
30326 +
30327 +       if (data->innr) {
30328 +               reg = pc87360_read_value(data, LD_IN, NO_BANK,
30329 +                                        PC87365_REG_IN_CONFIG);
30330 +               if (reg & 0x01) {
30331 +#ifdef DEBUG
30332 +                       printk(KERN_DEBUG "pc87360.o: Forcibly "
30333 +                              "enabling monitoring (VLM)\n");
30334 +#endif
30335 +                       pc87360_write_value(data, LD_IN, NO_BANK,
30336 +                                           PC87365_REG_IN_CONFIG,
30337 +                                           reg & 0xFE);
30338 +               }
30339 +       }
30340 +
30341 +       if (data->tempnr) {
30342 +               reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
30343 +                                        PC87365_REG_TEMP_CONFIG);
30344 +               if (reg & 0x01) {
30345 +#ifdef DEBUG
30346 +                       printk(KERN_DEBUG "pc87360.o: Forcibly "
30347 +                              "enabling monitoring (TMS)\n");
30348 +#endif
30349 +                       pc87360_write_value(data, LD_TEMP, NO_BANK,
30350 +                                           PC87365_REG_TEMP_CONFIG,
30351 +                                           reg & 0xFE);
30352 +               }
30353 +
30354 +               if (init >= 2) {
30355 +                       /* Chip config as documented by National Semi. */
30356 +                       pc87360_write_value(data, LD_TEMP, 0xF, 0xA, 0x08);
30357 +                       /* We voluntarily omit the bank here, in case the
30358 +                          sequence itself matters. It shouldn't be a problem,
30359 +                          since nobody else is supposed to access the
30360 +                          device at that point. */
30361 +                       pc87360_write_value(data, LD_TEMP, NO_BANK, 0xB, 0x04);
30362 +                       pc87360_write_value(data, LD_TEMP, NO_BANK, 0xC, 0x35);
30363 +                       pc87360_write_value(data, LD_TEMP, NO_BANK, 0xD, 0x05);
30364 +                       pc87360_write_value(data, LD_TEMP, NO_BANK, 0xE, 0x05);
30365 +               }
30366 +       }
30367 +}
30368 +
30369 +static void pc87360_autodiv(struct pc87360_data *data, int nr)
30370 +{
30371 +       u8 old_min = data->fan_min[nr];
30372 +
30373 +       /* Increase clock divider if needed and possible */
30374 +       if ((data->fan_status[nr] & 0x04) /* overflow flag */
30375 +        || (data->fan[nr] >= 224)) { /* next to overflow */
30376 +               if ((data->fan_status[nr] & 0x60) != 0x60) {
30377 +                       data->fan_status[nr] += 0x20;
30378 +                       data->fan_min[nr] >>= 1;
30379 +                       data->fan[nr] >>= 1;
30380 +#ifdef DEBUG
30381 +                       printk(KERN_DEBUG "pc87360.o: Increasing "
30382 +                              "clock divider to %d for fan %d\n",
30383 +                              FAN_DIV_FROM_REG(data->fan_status[nr]),
30384 +                              nr+1);
30385 +#endif
30386 +               }
30387 +       } else {
30388 +               /* Decrease clock divider if possible */
30389 +               while (!(data->fan_min[nr] & 0x80) /* fan min "nails" divider */
30390 +                && data->fan[nr] < 85 /* bad accuracy */
30391 +                && (data->fan_status[nr] & 0x60) != 0x00) {
30392 +                       data->fan_status[nr] -= 0x20;
30393 +                       data->fan_min[nr] <<= 1;
30394 +                       data->fan[nr] <<= 1;
30395 +#ifdef DEBUG
30396 +                       printk(KERN_DEBUG "pc87360.o: Decreasing "
30397 +                              "clock divider to %d for fan %d\n",
30398 +                              FAN_DIV_FROM_REG(data->fan_status[nr]),
30399 +                              nr+1);
30400 +#endif
30401 +               }
30402 +       }
30403 +
30404 +       /* Write new fan min if it changed */
30405 +       if (old_min != data->fan_min[nr]) {
30406 +               pc87360_write_value(data, LD_FAN, NO_BANK,
30407 +                                   PC87360_REG_FAN_MIN(nr),
30408 +                                   data->fan_min[nr]);
30409 +       }
30410 +}
30411 +
30412 +static void pc87360_update_client(struct i2c_client *client)
30413 +{
30414 +       struct pc87360_data *data = client->data;
30415 +       u8 i;
30416 +
30417 +       down(&data->update_lock);
30418 +
30419 +       if ((jiffies - data->last_updated > HZ * 2) ||
30420 +           (jiffies < data->last_updated) || !data->valid) {
30421 +#ifdef DEBUG
30422 +               printk(KERN_DEBUG "pc87360.o: Data update\n");
30423 +#endif
30424 +
30425 +               /* Fans */
30426 +               for (i = 0; i < data->fannr; i++) {
30427 +                       if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
30428 +                               data->fan_status[i] = pc87360_read_value(data,
30429 +                                                     LD_FAN, NO_BANK,
30430 +                                                     PC87360_REG_FAN_STATUS(i));
30431 +                               data->fan[i] = pc87360_read_value(data, LD_FAN,
30432 +                                              NO_BANK, PC87360_REG_FAN(i));
30433 +                               data->fan_min[i] = pc87360_read_value(data,
30434 +                                                  LD_FAN, NO_BANK,
30435 +                                                  PC87360_REG_FAN_MIN(i));
30436 +                               /* Change clock divider if needed */
30437 +                               pc87360_autodiv(data, i);
30438 +                               /* Clear bits and write new divider */
30439 +                               pc87360_write_value(data, LD_FAN, NO_BANK,
30440 +                                                   PC87360_REG_FAN_STATUS(i),
30441 +                                                   data->fan_status[i]);
30442 +                       }
30443 +                       data->pwm[i] = pc87360_read_value(data, LD_FAN,
30444 +                                      NO_BANK, PC87360_REG_PWM(i));
30445 +               }
30446 +
30447 +               /* Voltages */
30448 +               for (i = 0; i < data->innr; i++) {
30449 +                       data->in_status[i] = pc87360_read_value(data, LD_IN, i,
30450 +                                            PC87365_REG_IN_STATUS);
30451 +                       /* Clear bits */
30452 +                       pc87360_write_value(data, LD_IN, i,
30453 +                                           PC87365_REG_IN_STATUS,
30454 +                                           data->in_status[i]);
30455 +                       if ((data->in_status[i] & 0x81) == 0x81) {
30456 +                               data->in[i] = pc87360_read_value(data, LD_IN,
30457 +                                             i, PC87365_REG_IN);
30458 +                       }
30459 +                       if (data->in_status[i] & 0x01) {
30460 +                               data->in_min[i] = pc87360_read_value(data,
30461 +                                                 LD_IN, i,
30462 +                                                 PC87365_REG_IN_MIN);
30463 +                               data->in_max[i] = pc87360_read_value(data,
30464 +                                                 LD_IN, i,
30465 +                                                 PC87365_REG_IN_MAX);
30466 +                               if (i >= 11)
30467 +                                       data->in_crit[i-11] =
30468 +                                               pc87360_read_value(data, LD_IN,
30469 +                                               i, PC87365_REG_TEMP_CRIT);
30470 +                       }
30471 +               }
30472 +               if (data->innr) {
30473 +                       data->in_alarms = pc87360_read_value(data, LD_IN,
30474 +                                         NO_BANK, PC87365_REG_IN_ALARMS1)
30475 +                                       | ((pc87360_read_value(data, LD_IN,
30476 +                                           NO_BANK, PC87365_REG_IN_ALARMS2)
30477 +                                           & 0x07) << 8);
30478 +                       data->vid = (data->vid_conf & 0xE0) ?
30479 +                                   pc87360_read_value(data, LD_IN,
30480 +                                   NO_BANK, PC87365_REG_VID) : 0x1F;
30481 +               }
30482 +
30483 +               /* Temperatures */
30484 +               for (i = 0; i < data->tempnr; i++) {
30485 +                       data->temp_status[i] = pc87360_read_value(data,
30486 +                                              LD_TEMP, i,
30487 +                                              PC87365_REG_TEMP_STATUS);
30488 +                       /* Clear bits */
30489 +                       pc87360_write_value(data, LD_TEMP, i,
30490 +                                           PC87365_REG_TEMP_STATUS,
30491 +                                           data->temp_status[i]);
30492 +                       if ((data->temp_status[i] & 0x81) == 0x81) {
30493 +                               data->temp[i] = pc87360_read_value(data,
30494 +                                               LD_TEMP, i,
30495 +                                               PC87365_REG_TEMP);
30496 +                       }
30497 +                       if (data->temp_status[i] & 0x01) {
30498 +                               data->temp_min[i] = pc87360_read_value(data,
30499 +                                                   LD_TEMP, i,
30500 +                                                   PC87365_REG_TEMP_MIN);
30501 +                               data->temp_max[i] = pc87360_read_value(data,
30502 +                                                   LD_TEMP, i,
30503 +                                                   PC87365_REG_TEMP_MAX);
30504 +                               data->temp_crit[i] = pc87360_read_value(data,
30505 +                                                    LD_TEMP, i,
30506 +                                                    PC87365_REG_TEMP_CRIT);
30507 +                       }
30508 +               }
30509 +               if (data->tempnr) {
30510 +                       data->temp_alarms = pc87360_read_value(data, LD_TEMP,
30511 +                                           NO_BANK, PC87365_REG_TEMP_ALARMS)
30512 +                                         & 0x3F;
30513 +               }
30514 +
30515 +               data->last_updated = jiffies;
30516 +               data->valid = 1;
30517 +       }
30518 +
30519 +       up(&data->update_lock);
30520 +}
30521 +
30522 +
30523 +void pc87365_alarms(struct i2c_client *client, int operation, int ctl_name,
30524 +                   int *nrels_mag, long *results)
30525 +{
30526 +       struct pc87360_data *data = client->data;
30527 +
30528 +       if (operation == SENSORS_PROC_REAL_INFO)
30529 +               *nrels_mag = 0;
30530 +       else if (operation == SENSORS_PROC_REAL_READ) {
30531 +               pc87360_update_client(client);
30532 +               results[0] = data->in_alarms;
30533 +               results[1] = data->temp_alarms;
30534 +               *nrels_mag = 2;
30535 +       }
30536 +}
30537 +
30538 +void pc87360_fan(struct i2c_client *client, int operation, int ctl_name,
30539 +                int *nrels_mag, long *results)
30540 +{
30541 +       struct pc87360_data *data = client->data;
30542 +       int nr = ctl_name - PC87360_SYSCTL_FAN1;
30543 +
30544 +       if (operation == SENSORS_PROC_REAL_INFO)
30545 +               *nrels_mag = 0;
30546 +       else if (operation == SENSORS_PROC_REAL_READ) {
30547 +               pc87360_update_client(client);
30548 +               results[0] = FAN_FROM_REG(data->fan_min[nr],
30549 +                            FAN_DIV_FROM_REG(data->fan_status[nr]));
30550 +               results[1] = FAN_FROM_REG(data->fan[nr],
30551 +                            FAN_DIV_FROM_REG(data->fan_status[nr]));
30552 +               *nrels_mag = 2;
30553 +       }
30554 +       /* We ignore National's recommendation */
30555 +       else if (operation == SENSORS_PROC_REAL_WRITE) {
30556 +               if (nr >= data->fannr)
30557 +                       return;
30558 +               if (*nrels_mag >= 1) {
30559 +                       int fan_min = FAN_TO_REG(results[0],
30560 +                                     FAN_DIV_FROM_REG(data->fan_status[nr]));
30561 +                       /* If it wouldn't fit, change clock divisor */
30562 +                       while (fan_min > 255
30563 +                           && (data->fan_status[nr] & 0x60) != 0x60) {
30564 +                               fan_min >>= 1;
30565 +                               data->fan[nr] >>= 1;
30566 +                               data->fan_status[nr] += 0x20;
30567 +                       }
30568 +                       data->fan_min[nr] = fan_min > 255 ? 255 : fan_min;
30569 +                       pc87360_write_value(data, LD_FAN, NO_BANK,
30570 +                                           PC87360_REG_FAN_MIN(nr),
30571 +                                           data->fan_min[nr]);
30572 +                       /* Write new divider, preserve alarm bits */
30573 +                       pc87360_write_value(data, LD_FAN, NO_BANK,
30574 +                                           PC87360_REG_FAN_STATUS(nr),
30575 +                                           data->fan_status[nr] & 0xF9);
30576 +               }
30577 +       }
30578 +}
30579 +
30580 +void pc87360_fan_div(struct i2c_client *client, int operation,
30581 +                    int ctl_name, int *nrels_mag, long *results)
30582 +{
30583 +       struct pc87360_data *data = client->data;
30584 +       int i;
30585 +
30586 +       if (operation == SENSORS_PROC_REAL_INFO)
30587 +               *nrels_mag = 0;
30588 +       else if (operation == SENSORS_PROC_REAL_READ) {
30589 +               pc87360_update_client(client);
30590 +               for (i = 0; i < data->fannr; i++) {
30591 +                       results[i] = FAN_DIV_FROM_REG(data->fan_status[i]);
30592 +               }
30593 +               for (; i < 3; i++) {
30594 +                       results[i] = 0;
30595 +               }
30596 +               *nrels_mag = 3;
30597 +       }
30598 +}
30599 +
30600 +void pc87360_pwm(struct i2c_client *client, int operation, int ctl_name,
30601 +                int *nrels_mag, long *results)
30602 +{
30603 +       struct pc87360_data *data = client->data;
30604 +       int nr = ctl_name - PC87360_SYSCTL_PWM1;
30605 +
30606 +       if (operation == SENSORS_PROC_REAL_INFO)
30607 +               *nrels_mag = 0;
30608 +       else if (operation == SENSORS_PROC_REAL_READ) {
30609 +               pc87360_update_client(client);
30610 +               results[0] = PWM_FROM_REG(data->pwm[nr],
30611 +                            FAN_CONFIG_INVERT(data->fan_conf, nr));
30612 +               results[1] = FAN_CONFIG_CONTROL(data->fan_conf, nr);
30613 +               *nrels_mag = 2;
30614 +       }
30615 +       else if (operation == SENSORS_PROC_REAL_WRITE) {
30616 +               if (nr >= data->fannr)
30617 +                       return;
30618 +               if (*nrels_mag >= 1) {
30619 +                       data->pwm[nr] = PWM_TO_REG(results[0],
30620 +                                       FAN_CONFIG_INVERT(data->fan_conf, nr));
30621 +                       pc87360_write_value(data, LD_FAN, NO_BANK,
30622 +                                           PC87360_REG_PWM(nr),
30623 +                                           data->pwm[nr]);
30624 +               }
30625 +       }
30626 +}
30627 +
30628 +void pc87360_fan_status(struct i2c_client *client, int operation, int ctl_name,
30629 +                       int *nrels_mag, long *results)
30630 +{
30631 +       struct pc87360_data *data = client->data;
30632 +       int nr = ctl_name - PC87360_SYSCTL_FAN1_STATUS;
30633 +
30634 +       if (operation == SENSORS_PROC_REAL_INFO)
30635 +               *nrels_mag = 0;
30636 +       else if (operation == SENSORS_PROC_REAL_READ) {
30637 +               pc87360_update_client(client);
30638 +               results[0] = FAN_STATUS_FROM_REG(data->fan_status[nr]);
30639 +               *nrels_mag = 1;
30640 +       }
30641 +}
30642 +
30643 +void pc87365_in(struct i2c_client *client, int operation, int ctl_name,
30644 +               int *nrels_mag, long *results)
30645 +{
30646 +       struct pc87360_data *data = client->data;
30647 +       int nr = ctl_name - PC87365_SYSCTL_IN0;
30648 +
30649 +       if (operation == SENSORS_PROC_REAL_INFO)
30650 +               *nrels_mag = 3;
30651 +       else if (operation == SENSORS_PROC_REAL_READ) {
30652 +               pc87360_update_client(client);
30653 +               results[0] = IN_FROM_REG(data->in_min[nr], data->in_vref);
30654 +               results[1] = IN_FROM_REG(data->in_max[nr], data->in_vref);
30655 +               if (nr < 11) {
30656 +                       *nrels_mag = 3;
30657 +               } else {
30658 +                       results[2] = IN_FROM_REG(data->in_crit[nr-11],
30659 +                                                data->in_vref);
30660 +                       *nrels_mag = 4;
30661 +               }
30662 +               results[(*nrels_mag)-1] = IN_FROM_REG(data->in[nr],
30663 +                                                     data->in_vref);
30664 +       }
30665 +       else if (operation == SENSORS_PROC_REAL_WRITE) {
30666 +               if (*nrels_mag >= 1) {
30667 +                       data->in_min[nr] = IN_TO_REG(results[0],
30668 +                                                    data->in_vref);
30669 +                       pc87360_write_value(data, LD_IN, nr,
30670 +                                           PC87365_REG_IN_MIN,
30671 +                                           data->in_min[nr]);
30672 +               }
30673 +               if (*nrels_mag >= 2) {
30674 +                       data->in_max[nr] = IN_TO_REG(results[1],
30675 +                                                    data->in_vref);
30676 +                       pc87360_write_value(data, LD_IN, nr,
30677 +                                           PC87365_REG_IN_MAX,
30678 +                                           data->in_max[nr]);
30679 +               }
30680 +               if (*nrels_mag >= 3 && nr >= 11) {
30681 +                       data->in_crit[nr-11] = IN_TO_REG(results[2],
30682 +                                                        data->in_vref);
30683 +                       pc87360_write_value(data, LD_IN, nr,
30684 +                                           PC87365_REG_TEMP_CRIT,
30685 +                                           data->in_crit[nr-11]);
30686 +               }
30687 +       }
30688 +}
30689 +
30690 +void pc87365_in_status(struct i2c_client *client, int operation, int ctl_name,
30691 +                      int *nrels_mag, long *results)
30692 +{
30693 +       struct pc87360_data *data = client->data;
30694 +       int nr = ctl_name - PC87365_SYSCTL_IN0_STATUS;
30695 +
30696 +       if (operation == SENSORS_PROC_REAL_INFO)
30697 +               *nrels_mag = 0;
30698 +       else if (operation == SENSORS_PROC_REAL_READ) {
30699 +               pc87360_update_client(client);
30700 +               results[0] = data->in_status[nr];
30701 +               *nrels_mag = 1;
30702 +       }
30703 +}
30704 +
30705 +void pc87365_vid(struct i2c_client *client, int operation, int ctl_name,
30706 +                int *nrels_mag, long *results)
30707 +{
30708 +       struct pc87360_data *data = client->data;
30709 +       if (operation == SENSORS_PROC_REAL_INFO)
30710 +               *nrels_mag = 3;
30711 +       else if (operation == SENSORS_PROC_REAL_READ) {
30712 +               pc87360_update_client(client);
30713 +               results[0] = vid_from_reg(data->vid & 0x1f, data->vrm);
30714 +               *nrels_mag = 1;
30715 +       }
30716 +}
30717 +
30718 +void pc87365_vrm(struct i2c_client *client, int operation, int ctl_name,
30719 +                int *nrels_mag, long *results)
30720 +{
30721 +       struct pc87360_data *data = client->data;
30722 +       if (operation == SENSORS_PROC_REAL_INFO)
30723 +               *nrels_mag = 1;
30724 +       else if (operation == SENSORS_PROC_REAL_READ) {
30725 +               results[0] = data->vrm;
30726 +               *nrels_mag = 1;
30727 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
30728 +               if (*nrels_mag >= 1)
30729 +                       data->vrm = results[0];
30730 +       }
30731 +}
30732 +
30733 +void pc87365_temp(struct i2c_client *client, int operation, int ctl_name,
30734 +                 int *nrels_mag, long *results)
30735 +{
30736 +       struct pc87360_data *data = client->data;
30737 +       int nr = ctl_name - PC87365_SYSCTL_TEMP1;
30738 +
30739 +       if (operation == SENSORS_PROC_REAL_INFO)
30740 +               *nrels_mag = 0;
30741 +       else if (operation == SENSORS_PROC_REAL_READ) {
30742 +               pc87360_update_client(client);
30743 +               results[0] = TEMP_FROM_REG(data->temp_max[nr]);
30744 +               results[1] = TEMP_FROM_REG(data->temp_min[nr]);
30745 +               results[2] = TEMP_FROM_REG(data->temp_crit[nr]);
30746 +               results[3] = TEMP_FROM_REG(data->temp[nr]);
30747 +               *nrels_mag = 4;
30748 +       }
30749 +       else if (operation == SENSORS_PROC_REAL_WRITE) {
30750 +               if (nr >= data->tempnr)
30751 +                       return;
30752 +               if (*nrels_mag >= 1) {
30753 +                       data->temp_max[nr] = TEMP_TO_REG(results[0]);
30754 +                       pc87360_write_value(data, LD_TEMP, nr,
30755 +                                           PC87365_REG_TEMP_MAX,
30756 +                                           data->temp_max[nr]);
30757 +               }
30758 +               if (*nrels_mag >= 2) {
30759 +                       data->temp_min[nr] = TEMP_TO_REG(results[1]);
30760 +                       pc87360_write_value(data, LD_TEMP, nr,
30761 +                                           PC87365_REG_TEMP_MIN,
30762 +                                           data->temp_min[nr]);
30763 +               }
30764 +               if (*nrels_mag >= 3) {
30765 +                       data->temp_crit[nr] = TEMP_TO_REG(results[2]);
30766 +                       pc87360_write_value(data, LD_TEMP, nr,
30767 +                                           PC87365_REG_TEMP_CRIT,
30768 +                                           data->temp_crit[nr]);
30769 +               }
30770 +       }
30771 +}
30772 +
30773 +void pc87365_temp_status(struct i2c_client *client, int operation, int ctl_name,
30774 +                        int *nrels_mag, long *results)
30775 +{
30776 +       struct pc87360_data *data = client->data;
30777 +       int nr = ctl_name - PC87365_SYSCTL_TEMP1_STATUS;
30778 +
30779 +       if (operation == SENSORS_PROC_REAL_INFO)
30780 +               *nrels_mag = 0;
30781 +       else if (operation == SENSORS_PROC_REAL_READ) {
30782 +               pc87360_update_client(client);
30783 +               results[0] = data->temp_status[nr];
30784 +               *nrels_mag = 1;
30785 +       }
30786 +}
30787 +
30788 +
30789 +static int __init pc87360_init(void)
30790 +{
30791 +       int i;
30792 +
30793 +       printk(KERN_INFO "pc87360.o version %s (%s)\n", LM_VERSION, LM_DATE);
30794 +
30795 +       if (pc87360_find(&devid, extra_isa)) {
30796 +               printk(KERN_WARNING "pc87360.o: PC8736x not detected, "
30797 +                      "module not inserted.\n");
30798 +               return -ENODEV;
30799 +       }
30800 +
30801 +       /* Arbitrarily pick one of the addresses */
30802 +       for (i = 0; i < 3; i++) {
30803 +               if (extra_isa[i] != 0x0000) {
30804 +                       normal_isa[0] = extra_isa[i];
30805 +                       break;
30806 +               }
30807 +       }
30808 +
30809 +       if (normal_isa[0] == 0x0000) {
30810 +               printk(KERN_WARNING "pc87360.o: No active logical device, "
30811 +                      "module not inserted.\n");
30812 +               return -ENODEV;
30813 +       
30814 +       }
30815 +
30816 +       return i2c_add_driver(&pc87360_driver);
30817 +}
30818 +
30819 +static void __exit pc87360_exit(void)
30820 +{
30821 +       i2c_del_driver(&pc87360_driver);
30822 +}
30823 +
30824 +
30825 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
30826 +MODULE_DESCRIPTION("PC8736x hardware monitor");
30827 +MODULE_LICENSE("GPL");
30828 +
30829 +module_init(pc87360_init);
30830 +module_exit(pc87360_exit);
30831 --- linux-old/drivers/sensors/pcf8574.c Thu Jan  1 00:00:00 1970
30832 +++ linux/drivers/sensors/pcf8574.c     Mon Dec 13 20:18:51 2004
30833 @@ -0,0 +1,309 @@
30834 +/*
30835 +    pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware
30836 +             monitoring
30837 +    Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>, 
30838 +                        Philip Edelbrock <phil@netroedge.com>,
30839 +                        Dan Eaton <dan.eaton@rocketlogix.com>
30840 +
30841 +    This program is free software; you can redistribute it and/or modify
30842 +    it under the terms of the GNU General Public License as published by
30843 +    the Free Software Foundation; either version 2 of the License, or
30844 +    (at your option) any later version.
30845 +    
30846 +    This program is distributed in the hope that it will be useful,
30847 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
30848 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30849 +    GNU General Public License for more details.
30850 +
30851 +    You should have received a copy of the GNU General Public License
30852 +    along with this program; if not, write to the Free Software
30853 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30854 +*/
30855 +
30856 +/* A few notes about the PCF8574:
30857 +
30858 +* The PCF8574 is an 8-bit I/O expander for the I2C bus produced by
30859 +  Philips Semiconductors.  It is designed to provide a byte I2C
30860 +  interface to up to 8 separate devices.
30861 +  
30862 +* The PCF8574 appears as a very simple SMBus device which can be
30863 +  read from or written to with SMBUS byte read/write accesses.
30864 +
30865 +* Because of the general purpose nature of this device, it will most
30866 +  likely be necessary to customize the /proc interface to suit the
30867 +  specific application.
30868 +
30869 +  --Dan
30870 +
30871 +*/
30872 +
30873 +
30874 +#include <linux/module.h>
30875 +#include <linux/slab.h>
30876 +#include <linux/i2c.h>
30877 +#include <linux/i2c-proc.h>
30878 +#include <linux/init.h>
30879 +#define LM_DATE "20041007"
30880 +#define LM_VERSION "2.8.8"
30881 +
30882 +MODULE_LICENSE("GPL");
30883 +
30884 +/* Addresses to scan */
30885 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
30886 +static unsigned short normal_i2c_range[] = { 0x20, 0x27, 0x38, 0x3f, SENSORS_I2C_END };
30887 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
30888 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
30889 +
30890 +/* Insmod parameters */
30891 +SENSORS_INSMOD_2(pcf8574, pcf8574a);
30892 +
30893 +/* The PCF8574 registers */
30894 +
30895 +/* (No registers.  [Wow! This thing is SIMPLE!] ) */
30896 +
30897 +/* Initial values */
30898 +#define PCF8574_INIT 255       /* All outputs on (input mode) */
30899 +
30900 +/* Each client has this additional data */
30901 +struct pcf8574_data {
30902 +       struct i2c_client client;
30903 +       int sysctl_id;
30904 +
30905 +       struct semaphore update_lock;
30906 +
30907 +       u8 read, write;         /* Register values */
30908 +};
30909 +
30910 +static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
30911 +static int pcf8574_detect(struct i2c_adapter *adapter, int address,
30912 +                         unsigned short flags, int kind);
30913 +static int pcf8574_detach_client(struct i2c_client *client);
30914 +
30915 +static void pcf8574_read(struct i2c_client *client, int operation,
30916 +                                      int ctl_name, int *nrels_mag, long *results);
30917 +static void pcf8574_write(struct i2c_client *client, int operation,
30918 +                                      int ctl_name, int *nrels_mag, long *results);
30919 +static void pcf8574_update_client(struct i2c_client *client);
30920 +static void pcf8574_init_client(struct i2c_client *client);
30921 +
30922 +/* This is the driver that will be inserted */
30923 +static struct i2c_driver pcf8574_driver = {
30924 +       .owner          = THIS_MODULE,
30925 +       .name           = "PCF8574 sensor chip driver",
30926 +       .id             = I2C_DRIVERID_PCF8574,
30927 +       .flags          = I2C_DF_NOTIFY,
30928 +       .attach_adapter = pcf8574_attach_adapter,
30929 +       .detach_client  = pcf8574_detach_client,
30930 +};
30931 +
30932 +
30933 +/* -- SENSORS SYSCTL START -- */
30934 +#define PCF8574_SYSCTL_READ     1000
30935 +#define PCF8574_SYSCTL_WRITE    1001
30936 +
30937 +/* -- SENSORS SYSCTL END -- */
30938 +
30939 +/* These files are created for each detected PCF8574. This is just a template;
30940 +   though at first sight, you might think we could use a statically
30941 +   allocated list, we need some way to get back to the parent - which
30942 +   is done through one of the 'extra' fields which are initialized
30943 +   when a new copy is allocated. */
30944 +static ctl_table pcf8574_dir_table_template[] = {
30945 +       {PCF8574_SYSCTL_READ, "read", NULL, 0, 0444, NULL, &i2c_proc_real,
30946 +        &i2c_sysctl_real, NULL, &pcf8574_read},
30947 +       {PCF8574_SYSCTL_WRITE, "write", NULL, 0, 0644, NULL, &i2c_proc_real,
30948 +        &i2c_sysctl_real, NULL, &pcf8574_write},
30949 +       {0}
30950 +};
30951 +
30952 +static int pcf8574_id = 0;
30953 +
30954 +static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
30955 +{
30956 +       return i2c_detect(adapter, &addr_data, pcf8574_detect);
30957 +}
30958 +
30959 +/* This function is called by i2c_detect */
30960 +int pcf8574_detect(struct i2c_adapter *adapter, int address,
30961 +                  unsigned short flags, int kind)
30962 +{
30963 +       int i;
30964 +       struct i2c_client *new_client;
30965 +       struct pcf8574_data *data;
30966 +       int err = 0;
30967 +       const char *type_name, *client_name;
30968 +
30969 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
30970 +          at this moment; i2c_detect really won't call us. */
30971 +#ifdef DEBUG
30972 +       if (i2c_is_isa_adapter(adapter)) {
30973 +               printk
30974 +                   ("pcf8574.o: pcf8574_detect called for an ISA bus adapter?!?\n");
30975 +               return 0;
30976 +       }
30977 +#endif
30978 +
30979 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
30980 +               goto ERROR0;
30981 +
30982 +       /* OK. For now, we presume we have a valid client. We now create the
30983 +          client structure, even though we cannot fill it completely yet. */
30984 +       if (!(data = kmalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
30985 +               err = -ENOMEM;
30986 +               goto ERROR0;
30987 +       }
30988 +
30989 +       new_client = &data->client;
30990 +       new_client->addr = address;
30991 +       new_client->data = data;
30992 +       new_client->adapter = adapter;
30993 +       new_client->driver = &pcf8574_driver;
30994 +       new_client->flags = 0;
30995 +
30996 +       /* Now, we would do the remaining detection. But the PCF8574 is plainly
30997 +          impossible to detect! Stupid chip. */
30998 +
30999 +       /* Determine the chip type */
31000 +       if (kind <= 0) {
31001 +               if (address >= 0x38 && address <= 0x3f)
31002 +                       kind = pcf8574a;
31003 +               else
31004 +                       kind = pcf8574;
31005 +       }
31006 +
31007 +       if (kind == pcf8574a) {
31008 +               type_name = "pcf8574a";
31009 +               client_name = "PCF8574A chip";
31010 +       } else {
31011 +               type_name = "pcf8574a";
31012 +               client_name = "PCF8574A chip";
31013 +       }
31014 +
31015 +       /* Fill in the remaining client fields and put it into the global list */
31016 +       strcpy(new_client->name, client_name);
31017 +
31018 +       new_client->id = pcf8574_id++;
31019 +       init_MUTEX(&data->update_lock);
31020 +
31021 +       /* Tell the I2C layer a new client has arrived */
31022 +       if ((err = i2c_attach_client(new_client)))
31023 +               goto ERROR1;
31024 +
31025 +       /* Register a new directory entry with module sensors */
31026 +       if ((i = i2c_register_entry(new_client, type_name,
31027 +                                   pcf8574_dir_table_template)) < 0) {
31028 +               err = i;
31029 +               goto ERROR2;
31030 +       }
31031 +       data->sysctl_id = i;
31032 +
31033 +       /* Initialize the PCF8574 chip */
31034 +       pcf8574_init_client(new_client);
31035 +       return 0;
31036 +
31037 +/* OK, this is not exactly good programming practice, usually. But it is
31038 +   very code-efficient in this case. */
31039 +
31040 +      ERROR2:
31041 +       i2c_detach_client(new_client);
31042 +      ERROR1:
31043 +       kfree(data);
31044 +      ERROR0:
31045 +       return err;
31046 +}
31047 +
31048 +static int pcf8574_detach_client(struct i2c_client *client)
31049 +{
31050 +       int err;
31051 +
31052 +       i2c_deregister_entry(((struct pcf8574_data *) (client->data))->
31053 +                                sysctl_id);
31054 +
31055 +       if ((err = i2c_detach_client(client))) {
31056 +               printk("pcf8574.o: Client deregistration failed, "
31057 +                      "client not detached.\n");
31058 +               return err;
31059 +       }
31060 +
31061 +       kfree(client->data);
31062 +
31063 +       return 0;
31064 +}
31065 +
31066 +/* Called when we have found a new PCF8574. */
31067 +static void pcf8574_init_client(struct i2c_client *client)
31068 +{
31069 +       struct pcf8574_data *data = client->data;
31070 +       data->write = PCF8574_INIT;
31071 +       i2c_smbus_write_byte(client, data->write);
31072 +}
31073 +
31074 +
31075 +static void pcf8574_update_client(struct i2c_client *client)
31076 +{
31077 +       struct pcf8574_data *data = client->data;
31078 +
31079 +       down(&data->update_lock);
31080 +
31081 +#ifdef DEBUG
31082 +       printk("Starting pcf8574 update\n");
31083 +#endif
31084 +
31085 +       data->read = i2c_smbus_read_byte(client); 
31086 +
31087 +       up(&data->update_lock);
31088 +}
31089 +
31090 +
31091 +void pcf8574_read(struct i2c_client *client, int operation,
31092 +                 int ctl_name, int *nrels_mag, long *results)
31093 +{
31094 +       struct pcf8574_data *data = client->data;
31095 +
31096 +       if (operation == SENSORS_PROC_REAL_INFO)
31097 +               *nrels_mag = 0;
31098 +       else if (operation == SENSORS_PROC_REAL_READ) {
31099 +               pcf8574_update_client(client);
31100 +               results[0] = data->read;
31101 +               *nrels_mag = 1;
31102 +       }  
31103 +}
31104 +void pcf8574_write(struct i2c_client *client, int operation,
31105 +                  int ctl_name, int *nrels_mag, long *results)
31106 +{
31107 +       struct pcf8574_data *data = client->data;
31108 +
31109 +       if (operation == SENSORS_PROC_REAL_INFO)
31110 +               *nrels_mag = 0;
31111 +       else if (operation == SENSORS_PROC_REAL_READ) {
31112 +               results[0] = data->write; 
31113 +               *nrels_mag = 1;
31114 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
31115 +               if (*nrels_mag >= 1) {
31116 +                       data->write = results[0];
31117 +                       i2c_smbus_write_byte(client, data->write);
31118 +               }
31119 +       }
31120 +}
31121 +
31122 +
31123 +static int __init sm_pcf8574_init(void)
31124 +{
31125 +       printk("pcf8574.o version %s (%s)\n", LM_VERSION, LM_DATE);
31126 +       return i2c_add_driver(&pcf8574_driver);
31127 +}
31128 +
31129 +static void __exit sm_pcf8574_exit(void)
31130 +{
31131 +       i2c_del_driver(&pcf8574_driver);
31132 +}
31133 +
31134 +
31135 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
31136 +             "Philip Edelbrock <phil@netroedge.com>, "
31137 +             "Dan Eaton <dan.eaton@rocketlogix.com> and "
31138 +             "Aurelien Jarno <aurelien@aurel32.net>");
31139 +MODULE_DESCRIPTION("PCF8574 driver");
31140 +
31141 +module_init(sm_pcf8574_init);
31142 +module_exit(sm_pcf8574_exit);
31143 --- linux-old/drivers/sensors/pcf8591.c Thu Jan  1 00:00:00 1970
31144 +++ linux/drivers/sensors/pcf8591.c     Mon Dec 13 20:18:51 2004
31145 @@ -0,0 +1,448 @@
31146 +/*
31147 +    pcf8591.c - Part of lm_sensors, Linux kernel modules for hardware
31148 +             monitoring
31149 +    Copyright (c) 2001  Aurelien Jarno <aurelien@aurel32.net>
31150 +
31151 +    This program is free software; you can redistribute it and/or modify
31152 +    it under the terms of the GNU General Public License as published by
31153 +    the Free Software Foundation; either version 2 of the License, or
31154 +    (at your option) any later version.
31155 +
31156 +    This program is distributed in the hope that it will be useful,
31157 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
31158 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31159 +    GNU General Public License for more details.
31160 +
31161 +    You should have received a copy of the GNU General Public License
31162 +    along with this program; if not, write to the Free Software
31163 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31164 +*/
31165 +
31166 +#include <linux/module.h>
31167 +#include <linux/slab.h>
31168 +#include <linux/i2c.h>
31169 +#include <linux/i2c-proc.h>
31170 +#include <linux/init.h>
31171 +#define LM_DATE "20041007"
31172 +#define LM_VERSION "2.8.8"
31173 +
31174 +/* Addresses to scan */
31175 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
31176 +static unsigned short normal_i2c_range[] = { 0x48, 0x4f, SENSORS_I2C_END };
31177 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
31178 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
31179 +
31180 +/* Insmod parameters */
31181 +SENSORS_INSMOD_1(pcf8591);
31182 +
31183 +/* The PCF8591 control byte */
31184 +/*    7    6    5    4    3    2    1    0   */
31185 +/* |  0 |AOEF|   AIP   |  0 |AINC|  AICH   | */
31186 +
31187 +#define PCF8591_CONTROL_BYTE_AOEF 0x40  /* Analog Output Enable Flag */
31188 +                                        /* (analog output active if 1) */
31189 +
31190 +#define PCF8591_CONTROL_BYTE_AIP 0x30   /* Analog Input Programming */
31191 +                                        /* 0x00 = four single ended inputs */
31192 +                                        /* 0x10 = three differential inputs */
31193 +                                        /* 0x20 = single ended and differential mixed */
31194 +                                        /* 0x30 = two differential inputs */
31195 +
31196 +#define PCF8591_CONTROL_BYTE_AINC 0x04  /* Autoincrement Flag */
31197 +                                        /* (switch on if 1) */
31198 +
31199 +#define PCF8591_CONTROL_BYTE_AICH 0x03  /* Analog Output Enable Flag */
31200 +                                        /* 0x00 = channel 0 */
31201 +                                        /* 0x01 = channel 1 */
31202 +                                        /* 0x02 = channel 2 */
31203 +                                        /* 0x03 = channel 3 */
31204 +
31205 +
31206 +/* Initial values */
31207 +#define PCF8591_INIT_CONTROL_BYTE (PCF8591_CONTROL_BYTE_AOEF | PCF8591_CONTROL_BYTE_AINC)
31208 +                /* DAC out enabled, four single ended inputs, autoincrement */
31209 +
31210 +#define PCF8591_INIT_AOUT 0             /* DAC out = 0 */
31211 +
31212 +
31213 +/* Conversions. */
31214 +#define REG_TO_SIGNED(reg) (reg & 0x80)?(reg - 256):(reg)
31215 +                          /* Convert signed 8 bit value to signed value */
31216 +
31217 +
31218 +struct pcf8591_data {
31219 +       struct i2c_client client;
31220 +        int sysctl_id;
31221 +
31222 +        struct semaphore update_lock;
31223 +        char valid;             /* !=0 if following fields are valid */
31224 +        unsigned long last_updated;     /* In jiffies */
31225 +
31226 +        u8 control_byte;
31227 +        u8 ch[4];
31228 +        u8 aout;
31229 +};
31230 +
31231 +static int pcf8591_attach_adapter(struct i2c_adapter *adapter);
31232 +static int pcf8591_detect(struct i2c_adapter *adapter, int address,
31233 +                          unsigned short flags, int kind);
31234 +static int pcf8591_detach_client(struct i2c_client *client);
31235 +
31236 +static void pcf8591_update_client(struct i2c_client *client);
31237 +static void pcf8591_init_client(struct i2c_client *client);
31238 +
31239 +static void pcf8591_ain_conf(struct i2c_client *client, int operation,
31240 +                             int ctl_name, int *nrels_mag, long *results);
31241 +static void pcf8591_ain(struct i2c_client *client, int operation,
31242 +                        int ctl_name, int *nrels_mag, long *results);
31243 +static void pcf8591_aout_enable(struct i2c_client *client, int operation,
31244 +                                int ctl_name, int *nrels_mag, long *results);
31245 +static void pcf8591_aout(struct i2c_client *client, int operation,
31246 +                         int ctl_name, int *nrels_mag, long *results);
31247 +
31248 +
31249 +/* This is the driver that will be inserted */
31250 +static struct i2c_driver pcf8591_driver = {
31251 +       .owner          = THIS_MODULE,
31252 +       .name           = "PCF8591 sensor chip driver",
31253 +       .id             = I2C_DRIVERID_PCF8591,
31254 +       .flags          = I2C_DF_NOTIFY,
31255 +       .attach_adapter = pcf8591_attach_adapter,
31256 +       .detach_client  = pcf8591_detach_client,
31257 +};
31258 +
31259 +static int pcf8591_id = 0;
31260 +
31261 +/* The /proc/sys entries */
31262 +
31263 +/* -- SENSORS SYSCTL START -- */
31264 +#define PCF8591_SYSCTL_AIN_CONF 1000      /* Analog input configuration */
31265 +#define PCF8591_SYSCTL_CH0 1001           /* Input channel 1 */
31266 +#define PCF8591_SYSCTL_CH1 1002           /* Input channel 2 */
31267 +#define PCF8591_SYSCTL_CH2 1003           /* Input channel 3 */
31268 +#define PCF8591_SYSCTL_CH3 1004           /* Input channel 4 */
31269 +#define PCF8591_SYSCTL_AOUT_ENABLE 1005   /* Analog output enable flag */
31270 +#define PCF8591_SYSCTL_AOUT 1006          /* Analog output */
31271 +/* -- SENSORS SYSCTL END -- */
31272 +
31273 +/* These files are created for each detected PCF8591. This is just a template;
31274 +   though at first sight, you might think we could use a statically
31275 +   allocated list, we need some way to get back to the parent - which
31276 +   is done through one of the 'extra' fields which are initialized
31277 +   when a new copy is allocated. */
31278 +static ctl_table pcf8591_dir_table_template[] = {
31279 +        {PCF8591_SYSCTL_AIN_CONF, "ain_conf", NULL, 0, 0644, NULL, &i2c_proc_real,
31280 +         &i2c_sysctl_real, NULL, &pcf8591_ain_conf},
31281 +        {PCF8591_SYSCTL_CH0, "ch0", NULL, 0, 0444, NULL, &i2c_proc_real,
31282 +         &i2c_sysctl_real, NULL, &pcf8591_ain},
31283 +        {PCF8591_SYSCTL_CH1, "ch1", NULL, 0, 0444, NULL, &i2c_proc_real,
31284 +         &i2c_sysctl_real, NULL, &pcf8591_ain},
31285 +        {PCF8591_SYSCTL_CH2, "ch2", NULL, 0, 0444, NULL, &i2c_proc_real,
31286 +         &i2c_sysctl_real, NULL, &pcf8591_ain},
31287 +        {PCF8591_SYSCTL_CH3, "ch3", NULL, 0, 0444, NULL, &i2c_proc_real,
31288 +         &i2c_sysctl_real, NULL, &pcf8591_ain},
31289 +        {PCF8591_SYSCTL_AOUT_ENABLE, "aout_enable", NULL, 0, 0644, NULL, &i2c_proc_real,
31290 +         &i2c_sysctl_real, NULL, &pcf8591_aout_enable},
31291 +        {PCF8591_SYSCTL_AOUT, "aout", NULL, 0, 0644, NULL, &i2c_proc_real,
31292 +         &i2c_sysctl_real, NULL, &pcf8591_aout},
31293 +        {0}
31294 +};
31295 +
31296 +
31297 +/* This function is called when:
31298 +     * pcf8591_driver is inserted (when this module is loaded), for each
31299 +       available adapter
31300 +     * when a new adapter is inserted (and pcf8591_driver is still present) */
31301 +static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
31302 +{
31303 +        return i2c_detect(adapter, &addr_data, pcf8591_detect);
31304 +}
31305 +
31306 +/* This function is called by i2c_detect */
31307 +int pcf8591_detect(struct i2c_adapter *adapter, int address,
31308 +                unsigned short flags, int kind)
31309 +{
31310 +        int i;
31311 +        struct i2c_client *new_client;
31312 +        struct pcf8591_data *data;
31313 +        int err = 0;
31314 +
31315 +        const char *type_name = "";
31316 +        const char *client_name = "";
31317 +
31318 +        /* Make sure we aren't probing the ISA bus!! This is just a safety check at this moment; i2c_detect really won't call us. */
31319 +#ifdef DEBUG
31320 +        if (i2c_is_isa_adapter(adapter)) {
31321 +                printk
31322 +                    (KERN_ERR "pcf8591.o: pcf8591_detect called for an ISA bus adapter?!?\n");
31323 +                return 0;
31324 +        }
31325 +#endif
31326 +
31327 +        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE
31328 +                                     | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
31329 +                goto ERROR0;
31330 +
31331 +        /* OK. For now, we presume we have a valid client. We now create the
31332 +           client structure, even though we cannot fill it completely yet. */
31333 +       if (!(data = kmalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
31334 +                err = -ENOMEM;
31335 +                goto ERROR0;
31336 +        }
31337 +
31338 +       new_client = &data->client;
31339 +        new_client->addr = address;
31340 +        new_client->data = data;
31341 +        new_client->adapter = adapter;
31342 +        new_client->driver = &pcf8591_driver;
31343 +        new_client->flags = 0;
31344 +
31345 +        /* Now, we would do the remaining detection. But the PCF8591 is plainly
31346 +           impossible to detect! Stupid chip. */
31347 +
31348 +        /* Determine the chip type - only one kind supported! */
31349 +        if (kind <= 0)
31350 +                kind = pcf8591;
31351 +
31352 +       type_name = "pcf8591";
31353 +       client_name = "PCF8591 chip";
31354 +
31355 +        /* Fill in the remaining client fields and put it into the global list */
31356 +        strcpy(new_client->name, client_name);
31357 +
31358 +        new_client->id = pcf8591_id++;
31359 +        data->valid = 0;
31360 +        init_MUTEX(&data->update_lock);
31361 +
31362 +        /* Tell the I2C layer a new client has arrived */
31363 +        if ((err = i2c_attach_client(new_client)))
31364 +                goto ERROR3;
31365 +
31366 +        /* Register a new directory entry with module sensors */
31367 +        if ((i = i2c_register_entry(new_client,
31368 +                                        type_name,
31369 +                                        pcf8591_dir_table_template)) < 0) {
31370 +                err = i;
31371 +                goto ERROR4;
31372 +        }
31373 +        data->sysctl_id = i;
31374 +
31375 +        /* Initialize the PCF8591 chip */
31376 +        pcf8591_init_client(new_client);
31377 +        return 0;
31378 +
31379 +/* OK, this is not exactly good programming practice, usually. But it is
31380 +   very code-efficient in this case. */
31381 +
31382 +      ERROR4:
31383 +        i2c_detach_client(new_client);
31384 +      ERROR3:
31385 +       kfree(data);
31386 +      ERROR0:
31387 +        return err;
31388 +}
31389 +
31390 +static int pcf8591_detach_client(struct i2c_client *client)
31391 +{
31392 +        int err;
31393 +
31394 +        i2c_deregister_entry(((struct pcf8591_data *) (client->data))->
31395 +                                 sysctl_id);
31396 +
31397 +        if ((err = i2c_detach_client(client))) {
31398 +                printk
31399 +                    (KERN_ERR "pcf8591.o: Client deregistration failed, client not detached.\n");
31400 +                return err;
31401 +        }
31402 +
31403 +       kfree(client->data);
31404 +
31405 +        return 0;
31406 +}
31407 +
31408 +/* Called when we have found a new PCF8591. */
31409 +static void pcf8591_init_client(struct i2c_client *client)
31410 +{
31411 +        struct pcf8591_data *data = client->data;
31412 +        data->control_byte = PCF8591_INIT_CONTROL_BYTE;
31413 +        data->aout = PCF8591_INIT_AOUT;
31414 +
31415 +        i2c_smbus_write_byte_data(client, data->control_byte, data->aout);
31416 +}
31417 +
31418 +static void pcf8591_update_client(struct i2c_client *client)
31419 +{
31420 +        struct pcf8591_data *data = client->data;
31421 +
31422 +        down(&data->update_lock);
31423 +
31424 +        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
31425 +            (jiffies < data->last_updated) || !data->valid) {
31426 +
31427 +#ifdef DEBUG
31428 +                printk(KERN_DEBUG "Starting pcf8591 update\n");
31429 +#endif
31430 +
31431 +                i2c_smbus_write_byte(client, data->control_byte);
31432 +                i2c_smbus_read_byte(client);    /* The first byte transmitted contains the */
31433 +                                                /* conversion code of the previous read cycled */
31434 +                                                /* FLUSH IT ! */
31435 +
31436 +
31437 +                /* Number of byte to read to signed depend on the analog input mode */
31438 +                data->ch[0] = i2c_smbus_read_byte(client);
31439 +                data->ch[1] = i2c_smbus_read_byte(client);
31440 +                        /* In all case, read at least two values */
31441 +
31442 +                if ((data->control_byte & PCF8591_CONTROL_BYTE_AIP) != 0x30)
31443 +                        data->ch[2] = i2c_smbus_read_byte(client);
31444 +                        /* Read the third value if not in "two differential inputs" mode */
31445 +
31446 +                if ((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 0x00)
31447 +                        data->ch[3] = i2c_smbus_read_byte(client);
31448 +                        /* Read the fourth value only in "four single ended inputs" mode */
31449 +
31450 +                data->last_updated = jiffies;
31451 +                data->valid = 1;
31452 +        }
31453 +
31454 +        up(&data->update_lock);
31455 +}
31456 +
31457 +/* The next few functions are the call-back functions of the /proc/sys and
31458 +   sysctl files. Which function is used is defined in the ctl_table in
31459 +   the extra1 field. */
31460 +void pcf8591_ain_conf(struct i2c_client *client, int operation, int ctl_name,
31461 +             int *nrels_mag, long *results)
31462 +{
31463 +        struct pcf8591_data *data = client->data;
31464 +
31465 +        if (operation == SENSORS_PROC_REAL_INFO)
31466 +                *nrels_mag = 0;
31467 +        else if (operation == SENSORS_PROC_REAL_READ) {
31468 +                results[0] = (data->control_byte & PCF8591_CONTROL_BYTE_AIP) >> 4;
31469 +                *nrels_mag = 1;
31470 +        } else if (operation == SENSORS_PROC_REAL_WRITE) {
31471 +                if (*nrels_mag >= 1) {
31472 +                        if (results[0] >= 0 && results[0] <= 3)
31473 +                        {
31474 +                                data->control_byte &= ~PCF8591_CONTROL_BYTE_AIP;
31475 +                                data->control_byte |= (results[0] << 4);
31476 +                                i2c_smbus_write_byte(client, data->control_byte);
31477 +                                data->valid = 0;
31478 +                        }
31479 +                }
31480 +        }
31481 +}
31482 +
31483 +void pcf8591_ain(struct i2c_client *client, int operation, int ctl_name,
31484 +             int *nrels_mag, long *results)
31485 +{
31486 +        struct pcf8591_data *data = client->data;
31487 +        int nr = ctl_name - PCF8591_SYSCTL_CH0;
31488 +
31489 +        if (operation == SENSORS_PROC_REAL_INFO)
31490 +                *nrels_mag = 0;
31491 +        else if (operation == SENSORS_PROC_REAL_READ) {
31492 +                pcf8591_update_client(client);
31493 +
31494 +                /* Number of data to show and conversion to signed depend on */
31495 +                /* the analog input mode */
31496 +
31497 +                switch(nr) {
31498 +                        case 0:
31499 +                                if (((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 0)
31500 +                                   | ((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 2))
31501 +                                        results[0] = data->ch[0];               /* single ended */
31502 +                                else
31503 +                                        results[0] = REG_TO_SIGNED(data->ch[0]);/* differential */
31504 +                                break;
31505 +                        case 1:
31506 +                                if (((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 0)
31507 +                                   | ((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 2))
31508 +                                        results[0] = data->ch[1]; /* single ended */
31509 +                                else
31510 +                                        results[0] = REG_TO_SIGNED(data->ch[1]);/* differential */
31511 +                                break;
31512 +                        case 2:
31513 +                                if ((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 3)
31514 +                                        results[0] = 0;  /* channel not used */
31515 +                                else if ((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 0)
31516 +                                        results[0] = data->ch[2]; /* single ended */
31517 +                                else
31518 +                                        results[0] = REG_TO_SIGNED(data->ch[2]);/* differential */
31519 +                                break;
31520 +                        case 3:
31521 +                                if (((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 0)
31522 +                                   | ((data->control_byte & PCF8591_CONTROL_BYTE_AIP) == 2))
31523 +                                        results[0] = data->ch[3]; /* single ended */
31524 +                                else
31525 +                                        results[0] = 0;  /* channel not used */
31526 +                                break;
31527 +                }
31528 +        *nrels_mag = 1;
31529 +        }
31530 +}
31531 +
31532 +void pcf8591_aout_enable(struct i2c_client *client, int operation, int ctl_name,
31533 +             int *nrels_mag, long *results)
31534 +{
31535 +        struct pcf8591_data *data = client->data;
31536 +
31537 +        if (operation == SENSORS_PROC_REAL_INFO)
31538 +                *nrels_mag = 0;
31539 +        else if (operation == SENSORS_PROC_REAL_READ) {
31540 +                results[0] = !(!(data->control_byte & PCF8591_CONTROL_BYTE_AOEF));
31541 +                *nrels_mag = 1;
31542 +        } else if (operation == SENSORS_PROC_REAL_WRITE) {
31543 +                if (*nrels_mag >= 1) {
31544 +                        if (results[0])
31545 +                                data->control_byte |= PCF8591_CONTROL_BYTE_AOEF;
31546 +                        else
31547 +                                data->control_byte &= ~PCF8591_CONTROL_BYTE_AOEF;
31548 +
31549 +                        i2c_smbus_write_byte(client, data->control_byte);
31550 +                }
31551 +        }
31552 +}
31553 +
31554 +void pcf8591_aout(struct i2c_client *client, int operation, int ctl_name,
31555 +             int *nrels_mag, long *results)
31556 +{
31557 +        struct pcf8591_data *data = client->data;
31558 +
31559 +        if (operation == SENSORS_PROC_REAL_INFO)
31560 +                *nrels_mag = 0;
31561 +        else if (operation == SENSORS_PROC_REAL_READ) {
31562 +                results[0] = data->aout;
31563 +                *nrels_mag = 1;
31564 +        } else if (operation == SENSORS_PROC_REAL_WRITE) {
31565 +                if (*nrels_mag >= 1) {
31566 +                        if (results[0] >= 0 && results[0] <= 255) /* ignore values outside DAC range */
31567 +                        {
31568 +                                data->aout = results[0];
31569 +                                i2c_smbus_write_byte_data(client, data->control_byte, data->aout);
31570 +                        }
31571 +                }
31572 +        }
31573 +}
31574 +
31575 +static int __init sm_pcf8591_init(void)
31576 +{
31577 +        printk(KERN_INFO "pcf8591.o version %s (%s)\n", LM_VERSION, LM_DATE);
31578 +       return i2c_add_driver(&pcf8591_driver);
31579 +}
31580 +
31581 +static void __exit sm_pcf8591_exit(void)
31582 +{
31583 +        i2c_del_driver(&pcf8591_driver);
31584 +}
31585 +
31586 +
31587 +
31588 +MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
31589 +MODULE_DESCRIPTION("PCF8591 driver");
31590 +MODULE_LICENSE("GPL");
31591 +
31592 +module_init(sm_pcf8591_init);
31593 +module_exit(sm_pcf8591_exit);
31594 --- linux-old/drivers/sensors/sis5595.c Thu Jan  1 00:00:00 1970
31595 +++ linux/drivers/sensors/sis5595.c     Mon Dec 13 20:18:52 2004
31596 @@ -0,0 +1,735 @@
31597 +/*
31598 +    sis5595.c - Part of lm_sensors, Linux kernel modules
31599 +                for hardware monitoring
31600 +                
31601 +    Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
31602 +                        Kyösti Mälkki <kmalkki@cc.hut.fi>, and
31603 +                       Mark D. Studebaker <mdsxyz123@yahoo.com>
31604 +
31605 +    This program is free software; you can redistribute it and/or modify
31606 +    it under the terms of the GNU General Public License as published by
31607 +    the Free Software Foundation; either version 2 of the License, or
31608 +    (at your option) any later version.
31609 +
31610 +    This program is distributed in the hope that it will be useful,
31611 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
31612 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31613 +    GNU General Public License for more details.
31614 +
31615 +    You should have received a copy of the GNU General Public License
31616 +    along with this program; if not, write to the Free Software
31617 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31618 +*/
31619 +
31620 +/* 
31621 +    Supports following revisions:
31622 +       Version         PCI ID          PCI Revision
31623 +       1               1039/0008       AF or less
31624 +       2               1039/0008       B0 or greater
31625 +
31626 +   Note: these chips contain a 0008 device which is incompatible with the
31627 +         5595. We recognize these by the presence of the listed
31628 +         "blacklist" PCI ID and refuse to load.
31629 +
31630 +   NOT SUPPORTED       PCI ID          BLACKLIST PCI ID        
31631 +        540            0008            0540
31632 +        550            0008            0550
31633 +       5513            0008            5511
31634 +       5581            0008            5597
31635 +       5582            0008            5597
31636 +       5597            0008            5597
31637 +       5598            0008            5597/5598
31638 +        630            0008            0630
31639 +        645            0008            0645
31640 +        730            0008            0730
31641 +        735            0008            0735
31642 +*/
31643 +
31644 +#include <linux/module.h>
31645 +#include <linux/slab.h>
31646 +#include <linux/ioport.h>
31647 +#include <linux/pci.h>
31648 +#include <linux/i2c.h>
31649 +#include <linux/i2c-proc.h>
31650 +#include <linux/init.h>
31651 +#include <asm/io.h>
31652 +#define LM_DATE "20041007"
31653 +#define LM_VERSION "2.8.8"
31654 +
31655 +MODULE_LICENSE("GPL");
31656 +
31657 +/* If force_addr is set to anything different from 0, we forcibly enable
31658 +   the device at the given address. */
31659 +static int force_addr = 0;
31660 +MODULE_PARM(force_addr, "i");
31661 +MODULE_PARM_DESC(force_addr,
31662 +                "Initialize the base address of the sensors");
31663 +
31664 +/* Addresses to scan.
31665 +   Note that we can't determine the ISA address until we have initialized
31666 +   our module */
31667 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
31668 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
31669 +static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
31670 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
31671 +
31672 +/* Insmod parameters */
31673 +SENSORS_INSMOD_1(sis5595);
31674 +
31675 +static int blacklist[] = {
31676 +                       PCI_DEVICE_ID_SI_540,
31677 +                       PCI_DEVICE_ID_SI_550,
31678 +                       PCI_DEVICE_ID_SI_630,
31679 +                       PCI_DEVICE_ID_SI_730,
31680 +                       PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but
31681 +                                                 that ID shows up in other chips so we
31682 +                                                 use the 5511 ID for recognition */
31683 +                       PCI_DEVICE_ID_SI_5597,
31684 +                       PCI_DEVICE_ID_SI_5598,
31685 +                       0x645,
31686 +                       0x735,
31687 +                          0 };
31688 +/*
31689 +   SiS southbridge has a LM78-like chip integrated on the same IC.
31690 +   This driver is a customized copy of lm78.c
31691 +*/
31692 +
31693 +/* Many SIS5595 constants specified below */
31694 +
31695 +/* Length of ISA address segment */
31696 +#define SIS5595_EXTENT 8
31697 +/* PCI Config Registers */
31698 +#define SIS5595_REVISION_REG 0x08
31699 +#define SIS5595_BASE_REG 0x68
31700 +#define SIS5595_PIN_REG 0x7A
31701 +#define SIS5595_ENABLE_REG 0x7B
31702 +
31703 +/* Where are the ISA address/data registers relative to the base address */
31704 +#define SIS5595_ADDR_REG_OFFSET 5
31705 +#define SIS5595_DATA_REG_OFFSET 6
31706 +
31707 +/* The SIS5595 registers */
31708 +#define SIS5595_REG_IN_MAX(nr) (0x2b + (nr) * 2)
31709 +#define SIS5595_REG_IN_MIN(nr) (0x2c + (nr) * 2)
31710 +#define SIS5595_REG_IN(nr) (0x20 + (nr))
31711 +
31712 +#define SIS5595_REG_FAN_MIN(nr) (0x3a + (nr))
31713 +#define SIS5595_REG_FAN(nr) (0x27 + (nr))
31714 +
31715 +/* On the first version of the chip, the temp registers are separate.
31716 +   On the second version,
31717 +   TEMP pin is shared with IN4, configured in PCI register 0x7A.
31718 +   The registers are the same as well.
31719 +   OVER and HYST are really MAX and MIN. */
31720 +
31721 +#define REV2MIN        0xb0
31722 +#define SIS5595_REG_TEMP       (( data->revision) >= REV2MIN) ? \
31723 +                                       SIS5595_REG_IN(4) : 0x27
31724 +#define SIS5595_REG_TEMP_OVER  (( data->revision) >= REV2MIN) ? \
31725 +                                       SIS5595_REG_IN_MAX(4) : 0x39
31726 +#define SIS5595_REG_TEMP_HYST  (( data->revision) >= REV2MIN) ? \
31727 +                                       SIS5595_REG_IN_MIN(4) : 0x3a
31728 +
31729 +#define SIS5595_REG_CONFIG 0x40
31730 +#define SIS5595_REG_ALARM1 0x41
31731 +#define SIS5595_REG_ALARM2 0x42
31732 +#define SIS5595_REG_FANDIV 0x47
31733 +
31734 +/* Conversions. Limit checking is only done on the TO_REG
31735 +   variants. Note that you should be a bit careful with which arguments
31736 +   these macros are called: arguments may be evaluated more than once.
31737 +   Fixing this is just not worth it. */
31738 +
31739 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
31740 +#define IN_FROM_REG(val) (((val) *  16 + 5) / 10)
31741 +
31742 +static inline u8 FAN_TO_REG(long rpm, int div)
31743 +{
31744 +       if (rpm == 0)
31745 +               return 255;
31746 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
31747 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
31748 +                            254);
31749 +}
31750 +
31751 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
31752 +
31753 +/* Version 1 datasheet temp=.83*reg + 52.12 */
31754 +#define TEMP_FROM_REG(val) (((((val)>=0x80?(val)-0x100:(val))*83)+5212)/10)
31755 +/* inverse 1.20*val - 62.77 */
31756 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?\
31757 +                               ((((val)*12)-6327)/100):\
31758 +                                ((((val)*12)-6227)/100)),0,255))
31759 +
31760 +#define ALARMS_FROM_REG(val) (val)
31761 +
31762 +#define DIV_FROM_REG(val) (1 << (val))
31763 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
31764 +
31765 +/* For the SIS5595, we need to keep some data in memory. That
31766 +   data is pointed to by sis5595_list[NR]->data. The structure itself is
31767 +   dynamically allocated, at the time when the new sis5595 client is
31768 +   allocated. */
31769 +struct sis5595_data {
31770 +       struct i2c_client client;
31771 +       struct semaphore lock;
31772 +       int sysctl_id;
31773 +
31774 +       struct semaphore update_lock;
31775 +       char valid;             /* !=0 if following fields are valid */
31776 +       unsigned long last_updated;     /* In jiffies */
31777 +       char maxins;            /* == 3 if temp enabled, otherwise == 4 */
31778 +       u8 revision;            /* Reg. value */
31779 +
31780 +       u8 in[5];               /* Register value */
31781 +       u8 in_max[5];           /* Register value */
31782 +       u8 in_min[5];           /* Register value */
31783 +       u8 fan[2];              /* Register value */
31784 +       u8 fan_min[2];          /* Register value */
31785 +       u8 temp;                /* Register value */
31786 +       u8 temp_over;           /* Register value  - really max */
31787 +       u8 temp_hyst;           /* Register value  - really min */
31788 +       u8 fan_div[2];          /* Register encoding, shifted right */
31789 +       u16 alarms;             /* Register encoding, combined */
31790 +};
31791 +
31792 +static struct pci_dev *s_bridge;       /* pointer to the (only) sis5595 */
31793 +
31794 +static int sis5595_attach_adapter(struct i2c_adapter *adapter);
31795 +static int sis5595_detect(struct i2c_adapter *adapter, int address,
31796 +                         unsigned short flags, int kind);
31797 +static int sis5595_detach_client(struct i2c_client *client);
31798 +
31799 +static int sis5595_read_value(struct i2c_client *client, u8 register);
31800 +static int sis5595_write_value(struct i2c_client *client, u8 register,
31801 +                              u8 value);
31802 +static void sis5595_update_client(struct i2c_client *client);
31803 +static void sis5595_init_client(struct i2c_client *client);
31804 +static int sis5595_find_sis(int *address);
31805 +
31806 +
31807 +static void sis5595_in(struct i2c_client *client, int operation,
31808 +                      int ctl_name, int *nrels_mag, long *results);
31809 +static void sis5595_fan(struct i2c_client *client, int operation,
31810 +                       int ctl_name, int *nrels_mag, long *results);
31811 +static void sis5595_temp(struct i2c_client *client, int operation,
31812 +                        int ctl_name, int *nrels_mag, long *results);
31813 +static void sis5595_alarms(struct i2c_client *client, int operation,
31814 +                          int ctl_name, int *nrels_mag, long *results);
31815 +static void sis5595_fan_div(struct i2c_client *client, int operation,
31816 +                           int ctl_name, int *nrels_mag, long *results);
31817 +
31818 +static int sis5595_id = 0;
31819 +
31820 +/* The driver. I choose to use type i2c_driver, as at is identical to both
31821 +   smbus_driver and isa_driver, and clients could be of either kind */
31822 +static struct i2c_driver sis5595_driver = {
31823 +       .owner          = THIS_MODULE,
31824 +       .name           = "SiS 5595",
31825 +       .id             = I2C_DRIVERID_SIS5595,
31826 +       .flags          = I2C_DF_NOTIFY,
31827 +       .attach_adapter = sis5595_attach_adapter,
31828 +       .detach_client  = sis5595_detach_client,
31829 +};
31830 +
31831 +/* The /proc/sys entries */
31832 +
31833 +/* -- SENSORS SYSCTL START -- */
31834 +#define SIS5595_SYSCTL_IN0 1000        /* Volts * 100 */
31835 +#define SIS5595_SYSCTL_IN1 1001
31836 +#define SIS5595_SYSCTL_IN2 1002
31837 +#define SIS5595_SYSCTL_IN3 1003
31838 +#define SIS5595_SYSCTL_IN4 1004
31839 +#define SIS5595_SYSCTL_FAN1 1101       /* Rotations/min */
31840 +#define SIS5595_SYSCTL_FAN2 1102
31841 +#define SIS5595_SYSCTL_TEMP 1200       /* Degrees Celcius * 10 */
31842 +#define SIS5595_SYSCTL_FAN_DIV 2000    /* 1, 2, 4 or 8 */
31843 +#define SIS5595_SYSCTL_ALARMS 2001     /* bitvector */
31844 +
31845 +#define SIS5595_ALARM_IN0 0x01
31846 +#define SIS5595_ALARM_IN1 0x02
31847 +#define SIS5595_ALARM_IN2 0x04
31848 +#define SIS5595_ALARM_IN3 0x08
31849 +#define SIS5595_ALARM_BTI 0x20
31850 +#define SIS5595_ALARM_FAN1 0x40
31851 +#define SIS5595_ALARM_FAN2 0x80
31852 +#define SIS5595_ALARM_IN4  0x8000
31853 +#define SIS5595_ALARM_TEMP 0x8000
31854 +
31855 +/* -- SENSORS SYSCTL END -- */
31856 +
31857 +/* These files are created for each detected SIS5595. This is just a template;
31858 +   though at first sight, you might think we could use a statically
31859 +   allocated list, we need some way to get back to the parent - which
31860 +   is done through one of the 'extra' fields which are initialized 
31861 +   when a new copy is allocated. */
31862 +static ctl_table sis5595_dir_table_template[] = {
31863 +       {SIS5595_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
31864 +        &i2c_sysctl_real, NULL, &sis5595_in},
31865 +       {SIS5595_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
31866 +        &i2c_sysctl_real, NULL, &sis5595_in},
31867 +       {SIS5595_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
31868 +        &i2c_sysctl_real, NULL, &sis5595_in},
31869 +       {SIS5595_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
31870 +        &i2c_sysctl_real, NULL, &sis5595_in},
31871 +       {SIS5595_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
31872 +        &i2c_sysctl_real, NULL, &sis5595_in},
31873 +       {SIS5595_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
31874 +        &i2c_sysctl_real, NULL, &sis5595_fan},
31875 +       {SIS5595_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
31876 +        &i2c_sysctl_real, NULL, &sis5595_fan},
31877 +       {SIS5595_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
31878 +        &i2c_sysctl_real, NULL, &sis5595_temp},
31879 +       {SIS5595_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
31880 +        &i2c_sysctl_real, NULL, &sis5595_fan_div},
31881 +       {SIS5595_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
31882 +        &i2c_sysctl_real, NULL, &sis5595_alarms},
31883 +       {0}
31884 +};
31885 +
31886 +/* This is called when the module is loaded */
31887 +static int sis5595_attach_adapter(struct i2c_adapter *adapter)
31888 +{
31889 +       return i2c_detect(adapter, &addr_data, sis5595_detect);
31890 +}
31891 +
31892 +/* Locate SiS bridge and correct base address for SIS5595 */
31893 +static int sis5595_find_sis(int *address)
31894 +{
31895 +       u16 val;
31896 +       int *i;
31897 +
31898 +       if (!pci_present())
31899 +               return -ENODEV;
31900 +
31901 +       if (!(s_bridge =
31902 +             pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503,
31903 +                            NULL)))
31904 +               return -ENODEV;
31905 +
31906 +       /* Look for imposters */
31907 +       for(i = blacklist; *i != 0; i++) {
31908 +               if (pci_find_device(PCI_VENDOR_ID_SI, *i, NULL)) {
31909 +                       printk("sis5595.o: Error: Looked for SIS5595 but found unsupported device %.4X\n", *i);
31910 +                       return -ENODEV;
31911 +               }
31912 +       }
31913 +
31914 +       if (PCIBIOS_SUCCESSFUL !=
31915 +           pci_read_config_word(s_bridge, SIS5595_BASE_REG, &val))
31916 +               return -ENODEV;
31917 +
31918 +       *address = val & ~(SIS5595_EXTENT - 1);
31919 +       if (*address == 0 && force_addr == 0) {
31920 +               printk("sis5595.o: base address not set - upgrade BIOS or use force_addr=0xaddr\n");
31921 +               return -ENODEV;
31922 +       }
31923 +       if (force_addr)
31924 +               *address = force_addr;  /* so detect will get called */
31925 +
31926 +       return 0;
31927 +}
31928 +
31929 +int sis5595_detect(struct i2c_adapter *adapter, int address,
31930 +                  unsigned short flags, int kind)
31931 +{
31932 +       int i;
31933 +       struct i2c_client *new_client;
31934 +       struct sis5595_data *data;
31935 +       int err = 0;
31936 +       const char *type_name = "sis5595";
31937 +       const char *client_name = "SIS5595 chip";
31938 +       char val;
31939 +       u16 a;
31940 +
31941 +       /* Make sure we are probing the ISA bus!!  */
31942 +       if (!i2c_is_isa_adapter(adapter)) {
31943 +               printk
31944 +                   ("sis5595.o: sis5595_detect called for an I2C bus adapter?!?\n");
31945 +               return 0;
31946 +       }
31947 +
31948 +       if(force_addr)
31949 +               address = force_addr & ~(SIS5595_EXTENT - 1);
31950 +       if (check_region(address, SIS5595_EXTENT)) {
31951 +               printk("sis5595.o: region 0x%x already in use!\n", address);
31952 +               return -ENODEV;
31953 +       }
31954 +       if(force_addr) {
31955 +               printk("sis5595.o: forcing ISA address 0x%04X\n", address);
31956 +               if (PCIBIOS_SUCCESSFUL !=
31957 +                   pci_write_config_word(s_bridge, SIS5595_BASE_REG, address))
31958 +                       return -ENODEV;
31959 +               if (PCIBIOS_SUCCESSFUL !=
31960 +                   pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
31961 +                       return -ENODEV;
31962 +               if ((a & ~(SIS5595_EXTENT - 1)) != address) {
31963 +                       /* doesn't work for some chips? */
31964 +                       printk("sis5595.o: force address failed\n");
31965 +                       return -ENODEV;
31966 +               }
31967 +       }
31968 +
31969 +       if (PCIBIOS_SUCCESSFUL !=
31970 +           pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
31971 +               return -ENODEV;
31972 +       if((val & 0x80) == 0) {
31973 +               printk("sis5595.o: enabling sensors\n");
31974 +               if (PCIBIOS_SUCCESSFUL !=
31975 +                   pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG,
31976 +                                     val | 0x80))
31977 +                       return -ENODEV;
31978 +               if (PCIBIOS_SUCCESSFUL !=
31979 +                   pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
31980 +                       return -ENODEV;
31981 +               if((val & 0x80) == 0) { /* doesn't work for some chips! */
31982 +                       printk("sis5595.o: sensors enable failed - not supported?\n");
31983 +                       return -ENODEV;
31984 +               }
31985 +       }
31986 +
31987 +       if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
31988 +               return -ENOMEM;
31989 +       }
31990 +
31991 +       new_client = &data->client;
31992 +       new_client->addr = address;
31993 +       init_MUTEX(&data->lock);
31994 +       new_client->data = data;
31995 +       new_client->adapter = adapter;
31996 +       new_client->driver = &sis5595_driver;
31997 +       new_client->flags = 0;
31998 +
31999 +       /* Reserve the ISA region */
32000 +       request_region(address, SIS5595_EXTENT, type_name);
32001 +
32002 +       /* Check revision and pin registers to determine whether 3 or 4 voltages */
32003 +       pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision));
32004 +       if(data->revision < REV2MIN) {
32005 +               data->maxins = 3;
32006 +       } else {
32007 +               pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val);
32008 +               if(val & 0x80)
32009 +                       /* 3 voltages, 1 temp */
32010 +                       data->maxins = 3;
32011 +               else
32012 +                       /* 4 voltages, no temps */
32013 +                       data->maxins = 4;
32014 +       }
32015 +
32016 +       /* Fill in the remaining client fields and put it into the global list */
32017 +       strcpy(new_client->name, client_name);
32018 +
32019 +       new_client->id = sis5595_id++;
32020 +       data->valid = 0;
32021 +       init_MUTEX(&data->update_lock);
32022 +
32023 +       /* Tell the I2C layer a new client has arrived */
32024 +       if ((err = i2c_attach_client(new_client)))
32025 +               goto ERROR3;
32026 +
32027 +       /* Register a new directory entry with module sensors */
32028 +       if ((i = i2c_register_entry((struct i2c_client *) new_client,
32029 +                                       type_name,
32030 +                                       sis5595_dir_table_template)) < 0) {
32031 +               err = i;
32032 +               goto ERROR4;
32033 +       }
32034 +       data->sysctl_id = i;
32035 +
32036 +       /* Initialize the SIS5595 chip */
32037 +       sis5595_init_client(new_client);
32038 +       return 0;
32039 +
32040 +      ERROR4:
32041 +       i2c_detach_client(new_client);
32042 +      ERROR3:
32043 +       release_region(address, SIS5595_EXTENT);
32044 +       kfree(data);
32045 +       return err;
32046 +}
32047 +
32048 +static int sis5595_detach_client(struct i2c_client *client)
32049 +{
32050 +       int err;
32051 +
32052 +       i2c_deregister_entry(((struct sis5595_data *) (client->data))->
32053 +                                sysctl_id);
32054 +
32055 +       if ((err = i2c_detach_client(client))) {
32056 +               printk
32057 +                   ("sis5595.o: Client deregistration failed, client not detached.\n");
32058 +               return err;
32059 +       }
32060 +
32061 +       release_region(client->addr, SIS5595_EXTENT);
32062 +       kfree(client->data);
32063 +
32064 +       return 0;
32065 +}
32066 +
32067 +
32068 +/* ISA access must be locked explicitly.
32069 +   There are some ugly typecasts here, but the good news is - they should
32070 +   nowhere else be necessary! */
32071 +static int sis5595_read_value(struct i2c_client *client, u8 reg)
32072 +{
32073 +       int res;
32074 +
32075 +       down(&(((struct sis5595_data *) (client->data))->lock));
32076 +       outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
32077 +       res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET);
32078 +       up(&(((struct sis5595_data *) (client->data))->lock));
32079 +       return res;
32080 +}
32081 +
32082 +static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
32083 +{
32084 +       down(&(((struct sis5595_data *) (client->data))->lock));
32085 +       outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
32086 +       outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET);
32087 +       up(&(((struct sis5595_data *) (client->data))->lock));
32088 +       return 0;
32089 +}
32090 +
32091 +/* Called when we have found a new SIS5595. */
32092 +static void sis5595_init_client(struct i2c_client *client)
32093 +{
32094 +       u8 reg;
32095 +
32096 +       /* Start monitoring */
32097 +       reg = i2c_smbus_read_byte_data(client, SIS5595_REG_CONFIG);
32098 +       sis5595_write_value(client, SIS5595_REG_CONFIG, (reg|0x01)&0x7F);
32099 +}
32100 +
32101 +static void sis5595_update_client(struct i2c_client *client)
32102 +{
32103 +       struct sis5595_data *data = client->data;
32104 +       int i;
32105 +
32106 +       down(&data->update_lock);
32107 +
32108 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
32109 +           (jiffies < data->last_updated) || !data->valid) {
32110 +
32111 +               for (i = 0; i <= data->maxins; i++) {
32112 +                       data->in[i] =
32113 +                           sis5595_read_value(client, SIS5595_REG_IN(i));
32114 +                       data->in_min[i] =
32115 +                           sis5595_read_value(client,
32116 +                                              SIS5595_REG_IN_MIN(i));
32117 +                       data->in_max[i] =
32118 +                           sis5595_read_value(client,
32119 +                                              SIS5595_REG_IN_MAX(i));
32120 +               }
32121 +               for (i = 1; i <= 2; i++) {
32122 +                       data->fan[i - 1] =
32123 +                           sis5595_read_value(client, SIS5595_REG_FAN(i));
32124 +                       data->fan_min[i - 1] =
32125 +                           sis5595_read_value(client,
32126 +                                              SIS5595_REG_FAN_MIN(i));
32127 +               }
32128 +               if(data->maxins == 3) {
32129 +                       data->temp =
32130 +                           sis5595_read_value(client, SIS5595_REG_TEMP);
32131 +                       data->temp_over =
32132 +                           sis5595_read_value(client, SIS5595_REG_TEMP_OVER);
32133 +                       data->temp_hyst =
32134 +                           sis5595_read_value(client, SIS5595_REG_TEMP_HYST);
32135 +               }
32136 +               i = sis5595_read_value(client, SIS5595_REG_FANDIV);
32137 +               data->fan_div[0] = (i >> 4) & 0x03;
32138 +               data->fan_div[1] = i >> 6;
32139 +               data->alarms =
32140 +                   sis5595_read_value(client, SIS5595_REG_ALARM1) |
32141 +                   (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8);
32142 +               data->last_updated = jiffies;
32143 +               data->valid = 1;
32144 +       }
32145 +
32146 +       up(&data->update_lock);
32147 +}
32148 +
32149 +
32150 +/* The next few functions are the call-back functions of the /proc/sys and
32151 +   sysctl files. Which function is used is defined in the ctl_table in
32152 +   the extra1 field.
32153 +   Each function must return the magnitude (power of 10 to divide the date
32154 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
32155 +   put a maximum of *nrels elements in results reflecting the data of this
32156 +   file, and set *nrels to the number it actually put in it, if operation==
32157 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
32158 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
32159 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
32160 +   large enough (by checking the incoming value of *nrels). This is not very
32161 +   good practice, but as long as you put less than about 5 values in results,
32162 +   you can assume it is large enough. */
32163 +
32164 +/* Return 0 for in4 and disallow writes if pin used for temp */
32165 +void sis5595_in(struct i2c_client *client, int operation, int ctl_name,
32166 +               int *nrels_mag, long *results)
32167 +{
32168 +       struct sis5595_data *data = client->data;
32169 +       int nr = ctl_name - SIS5595_SYSCTL_IN0;
32170 +
32171 +       if (operation == SENSORS_PROC_REAL_INFO)
32172 +               *nrels_mag = 2;
32173 +       else if (operation == SENSORS_PROC_REAL_READ) {
32174 +               if(nr <= 3 || data->maxins == 4) {
32175 +                       sis5595_update_client(client);
32176 +                       results[0] = IN_FROM_REG(data->in_min[nr]);
32177 +                       results[1] = IN_FROM_REG(data->in_max[nr]);
32178 +                       results[2] = IN_FROM_REG(data->in[nr]);
32179 +               } else {
32180 +                       results[0] = 0;
32181 +                       results[1] = 0;
32182 +                       results[2] = 0;
32183 +               }
32184 +               *nrels_mag = 3;
32185 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
32186 +               if(nr <= 3 || data->maxins == 4) {
32187 +                       if (*nrels_mag >= 1) {
32188 +                               data->in_min[nr] = IN_TO_REG(results[0]);
32189 +                               sis5595_write_value(client,
32190 +                                   SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
32191 +                       }
32192 +                       if (*nrels_mag >= 2) {
32193 +                               data->in_max[nr] = IN_TO_REG(results[1]);
32194 +                               sis5595_write_value(client,
32195 +                                   SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
32196 +                       }
32197 +               }
32198 +       }
32199 +}
32200 +
32201 +void sis5595_fan(struct i2c_client *client, int operation, int ctl_name,
32202 +                int *nrels_mag, long *results)
32203 +{
32204 +       struct sis5595_data *data = client->data;
32205 +       int nr = ctl_name - SIS5595_SYSCTL_FAN1 + 1;
32206 +
32207 +       if (operation == SENSORS_PROC_REAL_INFO)
32208 +               *nrels_mag = 0;
32209 +       else if (operation == SENSORS_PROC_REAL_READ) {
32210 +               sis5595_update_client(client);
32211 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
32212 +                                         DIV_FROM_REG(data->fan_div[nr - 1]));
32213 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
32214 +                                         DIV_FROM_REG(data->fan_div[nr - 1]));
32215 +               *nrels_mag = 2;
32216 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
32217 +               if (*nrels_mag >= 1) {
32218 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0],
32219 +                                                          DIV_FROM_REG
32220 +                                                          (data->
32221 +                                                           fan_div[nr-1]));
32222 +                       sis5595_write_value(client,
32223 +                                           SIS5595_REG_FAN_MIN(nr),
32224 +                                           data->fan_min[nr - 1]);
32225 +               }
32226 +       }
32227 +}
32228 +
32229 +
32230 +/* Return 0 for temp and disallow writes if pin used for in4 */
32231 +void sis5595_temp(struct i2c_client *client, int operation, int ctl_name,
32232 +                 int *nrels_mag, long *results)
32233 +{
32234 +       struct sis5595_data *data = client->data;
32235 +       if (operation == SENSORS_PROC_REAL_INFO)
32236 +               *nrels_mag = 1;
32237 +       else if (operation == SENSORS_PROC_REAL_READ) {
32238 +               if(data->maxins == 3) {
32239 +                       sis5595_update_client(client);
32240 +                       results[0] = TEMP_FROM_REG(data->temp_over);
32241 +                       results[1] = TEMP_FROM_REG(data->temp_hyst);
32242 +                       results[2] = TEMP_FROM_REG(data->temp);
32243 +               } else {
32244 +                       results[0] = 0;
32245 +                       results[1] = 0;
32246 +                       results[2] = 0;
32247 +               }
32248 +               *nrels_mag = 3;
32249 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
32250 +               if(data->maxins == 3) {
32251 +                       if (*nrels_mag >= 1) {
32252 +                               data->temp_over = TEMP_TO_REG(results[0]);
32253 +                               sis5595_write_value(client,
32254 +                                   SIS5595_REG_TEMP_OVER, data->temp_over);
32255 +                       }
32256 +                       if (*nrels_mag >= 2) {
32257 +                               data->temp_hyst = TEMP_TO_REG(results[1]);
32258 +                               sis5595_write_value(client,
32259 +                                   SIS5595_REG_TEMP_HYST, data->temp_hyst);
32260 +                       }
32261 +               }
32262 +       }
32263 +}
32264 +
32265 +void sis5595_alarms(struct i2c_client *client, int operation, int ctl_name,
32266 +                   int *nrels_mag, long *results)
32267 +{
32268 +       struct sis5595_data *data = client->data;
32269 +       if (operation == SENSORS_PROC_REAL_INFO)
32270 +               *nrels_mag = 0;
32271 +       else if (operation == SENSORS_PROC_REAL_READ) {
32272 +               sis5595_update_client(client);
32273 +               results[0] = ALARMS_FROM_REG(data->alarms);
32274 +               *nrels_mag = 1;
32275 +       }
32276 +}
32277 +
32278 +void sis5595_fan_div(struct i2c_client *client, int operation,
32279 +                    int ctl_name, int *nrels_mag, long *results)
32280 +{
32281 +       struct sis5595_data *data = client->data;
32282 +       int old;
32283 +
32284 +       if (operation == SENSORS_PROC_REAL_INFO)
32285 +               *nrels_mag = 0;
32286 +       else if (operation == SENSORS_PROC_REAL_READ) {
32287 +               sis5595_update_client(client);
32288 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
32289 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
32290 +               *nrels_mag = 2;
32291 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
32292 +               old = sis5595_read_value(client, SIS5595_REG_FANDIV);
32293 +               if (*nrels_mag >= 2) {
32294 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
32295 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
32296 +               }
32297 +               if (*nrels_mag >= 1) {
32298 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
32299 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
32300 +                       sis5595_write_value(client, SIS5595_REG_FANDIV, old);
32301 +               }
32302 +       }
32303 +}
32304 +
32305 +static int __init sm_sis5595_init(void)
32306 +{
32307 +       int addr;
32308 +
32309 +       printk("sis5595.o version %s (%s)\n", LM_VERSION, LM_DATE);
32310 +
32311 +       if (sis5595_find_sis(&addr)) {
32312 +               printk("sis5595.o: SIS5595 not detected, module not inserted.\n");
32313 +               return -ENODEV;
32314 +       }
32315 +       normal_isa[0] = addr;
32316 +
32317 +       return i2c_add_driver(&sis5595_driver);
32318 +}
32319 +
32320 +static void __exit sm_sis5595_exit(void)
32321 +{
32322 +       i2c_del_driver(&sis5595_driver);
32323 +}
32324 +
32325 +
32326 +
32327 +MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
32328 +MODULE_DESCRIPTION("SiS 5595 Sensor device");
32329 +
32330 +module_init(sm_sis5595_init);
32331 +module_exit(sm_sis5595_exit);
32332 --- linux-old/drivers/sensors/smsc47m1.c        Thu Jan  1 00:00:00 1970
32333 +++ linux/drivers/sensors/smsc47m1.c    Mon Dec 13 20:18:52 2004
32334 @@ -0,0 +1,515 @@
32335 +/*
32336 +    smsc47m1.c - Part of lm_sensors, Linux kernel modules
32337 +                for hardware monitoring
32338 +                
32339 +    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
32340 +
32341 +    This program is free software; you can redistribute it and/or modify
32342 +    it under the terms of the GNU General Public License as published by
32343 +    the Free Software Foundation; either version 2 of the License, or
32344 +    (at your option) any later version.
32345 +
32346 +    This program is distributed in the hope that it will be useful,
32347 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
32348 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32349 +    GNU General Public License for more details.
32350 +
32351 +    You should have received a copy of the GNU General Public License
32352 +    along with this program; if not, write to the Free Software
32353 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32354 +*/
32355 +
32356 +#include <linux/module.h>
32357 +#include <linux/slab.h>
32358 +#include <linux/ioport.h>
32359 +#include <linux/i2c.h>
32360 +#include <linux/i2c-proc.h>
32361 +#include <linux/init.h>
32362 +#include <asm/io.h>
32363 +#define LM_DATE "20041007"
32364 +#define LM_VERSION "2.8.8"
32365 +
32366 +static int force_addr = 0;
32367 +MODULE_PARM(force_addr, "i");
32368 +MODULE_PARM_DESC(force_addr,
32369 +                "Initialize the base address of the sensors");
32370 +
32371 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
32372 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
32373 +static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
32374 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
32375 +
32376 +SENSORS_INSMOD_1(smsc47m1);
32377 +
32378 +/* modified from kernel/include/traps.c */
32379 +#define        REG     0x2e    /* The register to read/write */
32380 +#define        DEV     0x07    /* Register: Logical device select */
32381 +#define        VAL     0x2f    /* The value to read/write */
32382 +#define PME    0x0a    /* The device with the fan registers in it */
32383 +#define        DEVID   0x20    /* Register: Device ID */
32384 +
32385 +static inline void
32386 +superio_outb(int reg, int val)
32387 +{
32388 +       outb(reg, REG);
32389 +       outb(val, VAL);
32390 +}
32391 +
32392 +static inline int
32393 +superio_inb(int reg)
32394 +{
32395 +       outb(reg, REG);
32396 +       return inb(VAL);
32397 +}
32398 +
32399 +static inline void
32400 +superio_select(void)
32401 +{
32402 +       outb(DEV, REG);
32403 +       outb(PME, VAL);
32404 +}
32405 +
32406 +static inline void
32407 +superio_enter(void)
32408 +{
32409 +       outb(0x55, REG);
32410 +}
32411 +
32412 +static inline void
32413 +superio_exit(void)
32414 +{
32415 +       outb(0xAA, REG);
32416 +}
32417 +
32418 +/*
32419 + * SMSC LPC47M10x (device id 0x59), LPC47M14x (device id 0x5F) and
32420 + * LPC47B27x (device id 0x51) have fan control.
32421 + * The 47M15x and 47M192 chips "with hardware monitoring block"
32422 + * can do much more besides (device id 0x60).
32423 + */
32424 +#define SMSC_DEVID_MATCH(id) ((id) == 0x51 || (id) == 0x59 || (id) == 0x5F)
32425 +
32426 +#define SMSC_ACT_REG 0x30
32427 +#define SMSC_BASE_REG 0x60
32428 +
32429 +#define SMSC_EXTENT 0x80
32430 +
32431 +#define SMSC47M1_REG_ALARM1 0x04
32432 +#define SMSC47M1_REG_TPIN2 0x33
32433 +#define SMSC47M1_REG_TPIN1 0x34
32434 +#define SMSC47M1_REG_PPIN(nr) (0x37 - (nr))
32435 +#define SMSC47M1_REG_PWM(nr) (0x55 + (nr))
32436 +#define SMSC47M1_REG_FANDIV 0x58
32437 +#define SMSC47M1_REG_FAN(nr) (0x58 + (nr))
32438 +#define SMSC47M1_REG_FAN_MIN(nr) (0x5a + (nr))
32439 +
32440 +static inline u8 MIN_TO_REG(long rpm, int div)
32441 +{
32442 +       if (rpm == 0)
32443 +               return 0;
32444 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
32445 +       return SENSORS_LIMIT(192 - ((983040 + rpm * div / 2) / (rpm * div)),
32446 +                            0, 191);
32447 +}
32448 +
32449 +#define MIN_FROM_REG(val,div) ((val)>=192?0: \
32450 +                                983040/((192-(val))*(div)))
32451 +#define FAN_FROM_REG(val,div,preload) ((val)==0?-1:(val)==255?0: \
32452 +                                983040/(((val)-preload)*(div)))
32453 +#define DIV_FROM_REG(val) (1 << (val))
32454 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
32455 +/* reg is 6 middle bits; /proc is 8 bits */
32456 +#define PWM_FROM_REG(val) (((val) << 1) & 0xfc)
32457 +#define PWM_TO_REG(val)   (((SENSORS_LIMIT((val), 0, 255)) >> 1) & 0x7e)
32458 +
32459 +struct smsc47m1_data {
32460 +       struct i2c_client client;
32461 +       struct semaphore lock;
32462 +       int sysctl_id;
32463 +
32464 +       struct semaphore update_lock;
32465 +       char valid;             /* !=0 if following fields are valid */
32466 +       unsigned long last_updated;     /* In jiffies */
32467 +
32468 +       u8 fan[2];              /* Register value */
32469 +       u8 fan_min[2];          /* Register value */
32470 +       u8 fan_div[2];          /* Register encoding, shifted right */
32471 +       u8 alarms;              /* Register encoding */
32472 +       u8 pwm[2];              /* Register value (bit 7 is enable) */
32473 +};
32474 +
32475 +
32476 +static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
32477 +static int smsc47m1_detect(struct i2c_adapter *adapter, int address,
32478 +                         unsigned short flags, int kind);
32479 +static int smsc47m1_detach_client(struct i2c_client *client);
32480 +
32481 +static int smsc47m1_read_value(struct i2c_client *client, u8 register);
32482 +static int smsc47m1_write_value(struct i2c_client *client, u8 register,
32483 +                              u8 value);
32484 +static void smsc47m1_update_client(struct i2c_client *client);
32485 +static void smsc47m1_init_client(struct i2c_client *client);
32486 +static int smsc47m1_find(int *address);
32487 +
32488 +
32489 +static void smsc47m1_fan(struct i2c_client *client, int operation,
32490 +                       int ctl_name, int *nrels_mag, long *results);
32491 +static void smsc47m1_alarms(struct i2c_client *client, int operation,
32492 +                          int ctl_name, int *nrels_mag, long *results);
32493 +static void smsc47m1_fan_div(struct i2c_client *client, int operation,
32494 +                           int ctl_name, int *nrels_mag, long *results);
32495 +static void smsc47m1_pwm(struct i2c_client *client, int operation,
32496 +                       int ctl_name, int *nrels_mag, long *results);
32497 +
32498 +static int smsc47m1_id = 0;
32499 +
32500 +static struct i2c_driver smsc47m1_driver = {
32501 +       .owner          = THIS_MODULE,
32502 +       .name           = "SMSC 47M1xx fan monitor",
32503 +       .id             = I2C_DRIVERID_SMSC47M1,
32504 +       .flags          = I2C_DF_NOTIFY,
32505 +       .attach_adapter = smsc47m1_attach_adapter,
32506 +       .detach_client  = smsc47m1_detach_client,
32507 +};
32508 +
32509 +/* -- SENSORS SYSCTL START -- */
32510 +#define SMSC47M1_SYSCTL_FAN1 1101   /* Rotations/min */
32511 +#define SMSC47M1_SYSCTL_FAN2 1102
32512 +#define SMSC47M1_SYSCTL_PWM1 1401
32513 +#define SMSC47M1_SYSCTL_PWM2 1402
32514 +#define SMSC47M1_SYSCTL_FAN_DIV 2000        /* 1, 2, 4 or 8 */
32515 +#define SMSC47M1_SYSCTL_ALARMS 2004    /* bitvector */
32516 +
32517 +#define SMSC47M1_ALARM_FAN1 0x0001
32518 +#define SMSC47M1_ALARM_FAN2 0x0002
32519 +
32520 +/* -- SENSORS SYSCTL END -- */
32521 +
32522 +static ctl_table smsc47m1_dir_table_template[] = {
32523 +       {SMSC47M1_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
32524 +        &i2c_sysctl_real, NULL, &smsc47m1_fan},
32525 +       {SMSC47M1_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
32526 +        &i2c_sysctl_real, NULL, &smsc47m1_fan},
32527 +       {SMSC47M1_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
32528 +        &i2c_sysctl_real, NULL, &smsc47m1_fan_div},
32529 +       {SMSC47M1_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
32530 +        &i2c_sysctl_real, NULL, &smsc47m1_alarms},
32531 +       {SMSC47M1_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
32532 +        &i2c_sysctl_real, NULL, &smsc47m1_pwm},
32533 +       {SMSC47M1_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
32534 +        &i2c_sysctl_real, NULL, &smsc47m1_pwm},
32535 +       {0}
32536 +};
32537 +
32538 +static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
32539 +{
32540 +       return i2c_detect(adapter, &addr_data, smsc47m1_detect);
32541 +}
32542 +
32543 +static int smsc47m1_find(int *address)
32544 +{
32545 +       u16 val;
32546 +
32547 +       superio_enter();
32548 +       val= superio_inb(DEVID);
32549 +       if (!SMSC_DEVID_MATCH(val)) {
32550 +               superio_exit();
32551 +               return -ENODEV;
32552 +       }
32553 +
32554 +       superio_select();
32555 +       val = (superio_inb(SMSC_BASE_REG) << 8) |
32556 +              superio_inb(SMSC_BASE_REG + 1);
32557 +       *address = val & ~(SMSC_EXTENT - 1);
32558 +       if (*address == 0 && force_addr == 0) {
32559 +               printk("smsc47m1.o: base address not set - use force_addr=0xaddr\n");
32560 +               superio_exit();
32561 +               return -ENODEV;
32562 +       }
32563 +       if (force_addr)
32564 +               *address = force_addr;  /* so detect will get called */
32565 +
32566 +       superio_exit();
32567 +       return 0;
32568 +}
32569 +
32570 +int smsc47m1_detect(struct i2c_adapter *adapter, int address,
32571 +                  unsigned short flags, int kind)
32572 +{
32573 +       int i;
32574 +       struct i2c_client *new_client;
32575 +       struct smsc47m1_data *data;
32576 +       int err = 0;
32577 +       const char *type_name = "smsc47m1";
32578 +       const char *client_name = "47M1xx chip";
32579 +
32580 +       if (!i2c_is_isa_adapter(adapter)) {
32581 +               return 0;
32582 +       }
32583 +
32584 +       if(force_addr)
32585 +               address = force_addr & ~(SMSC_EXTENT - 1);
32586 +       if (check_region(address, SMSC_EXTENT)) {
32587 +               printk("smsc47m1.o: region 0x%x already in use!\n", address);
32588 +               return -ENODEV;
32589 +       }
32590 +       if(force_addr) {
32591 +               printk("smsc47m1.o: forcing ISA address 0x%04X\n", address);
32592 +               superio_enter();
32593 +               superio_select();
32594 +               superio_outb(SMSC_BASE_REG, address >> 8);
32595 +               superio_outb(SMSC_BASE_REG+1, address & 0xff);
32596 +               superio_exit();
32597 +       }
32598 +
32599 +       if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
32600 +               return -ENOMEM;
32601 +       }
32602 +
32603 +       new_client = &data->client;
32604 +       new_client->addr = address;
32605 +       init_MUTEX(&data->lock);
32606 +       new_client->data = data;
32607 +       new_client->adapter = adapter;
32608 +       new_client->driver = &smsc47m1_driver;
32609 +       new_client->flags = 0;
32610 +
32611 +       request_region(address, SMSC_EXTENT, "smsc47m1-fans");
32612 +       strcpy(new_client->name, client_name);
32613 +
32614 +       new_client->id = smsc47m1_id++;
32615 +       data->valid = 0;
32616 +       init_MUTEX(&data->update_lock);
32617 +
32618 +       if ((err = i2c_attach_client(new_client)))
32619 +               goto ERROR3;
32620 +
32621 +       if ((i = i2c_register_entry((struct i2c_client *) new_client,
32622 +                                       type_name,
32623 +                                       smsc47m1_dir_table_template)) < 0) {
32624 +               err = i;
32625 +               goto ERROR4;
32626 +       }
32627 +       data->sysctl_id = i;
32628 +
32629 +       smsc47m1_init_client(new_client);
32630 +       return 0;
32631 +
32632 +      ERROR4:
32633 +       i2c_detach_client(new_client);
32634 +      ERROR3:
32635 +       release_region(address, SMSC_EXTENT);
32636 +       kfree(data);
32637 +       return err;
32638 +}
32639 +
32640 +static int smsc47m1_detach_client(struct i2c_client *client)
32641 +{
32642 +       int err;
32643 +
32644 +       i2c_deregister_entry(((struct smsc47m1_data *) (client->data))->
32645 +                                sysctl_id);
32646 +
32647 +       if ((err = i2c_detach_client(client))) {
32648 +               printk
32649 +                   ("smsc47m1.o: Client deregistration failed, client not detached.\n");
32650 +               return err;
32651 +       }
32652 +
32653 +       release_region(client->addr, SMSC_EXTENT);
32654 +       kfree(client->data);
32655 +
32656 +       return 0;
32657 +}
32658 +
32659 +static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
32660 +{
32661 +       int res;
32662 +
32663 +       down(&(((struct smsc47m1_data *) (client->data))->lock));
32664 +       res = inb_p(client->addr + reg);
32665 +       up(&(((struct smsc47m1_data *) (client->data))->lock));
32666 +       return res;
32667 +}
32668 +
32669 +static int smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
32670 +{
32671 +       down(&(((struct smsc47m1_data *) (client->data))->lock));
32672 +       outb_p(value, client->addr + reg);
32673 +       up(&(((struct smsc47m1_data *) (client->data))->lock));
32674 +       return 0;
32675 +}
32676 +
32677 +static void smsc47m1_init_client(struct i2c_client *client)
32678 +{
32679 +       /* configure pins for tach function */
32680 +       smsc47m1_write_value(client, SMSC47M1_REG_TPIN1, 0x05);
32681 +       smsc47m1_write_value(client, SMSC47M1_REG_TPIN2, 0x05);
32682 +}
32683 +
32684 +static void smsc47m1_update_client(struct i2c_client *client)
32685 +{
32686 +       struct smsc47m1_data *data = client->data;
32687 +       int i;
32688 +
32689 +       down(&data->update_lock);
32690 +
32691 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
32692 +           (jiffies < data->last_updated) || !data->valid) {
32693 +               for (i = 1; i <= 2; i++) {
32694 +                       data->fan[i - 1] =
32695 +                           smsc47m1_read_value(client, SMSC47M1_REG_FAN(i));
32696 +                       data->fan_min[i - 1] =
32697 +                           smsc47m1_read_value(client, SMSC47M1_REG_FAN_MIN(i));
32698 +                       data->pwm[i - 1] =
32699 +                           smsc47m1_read_value(client, SMSC47M1_REG_PWM(i));
32700 +               }
32701 +
32702 +               i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
32703 +               data->fan_div[0] = (i >> 4) & 0x03;
32704 +               data->fan_div[1] = i >> 6;
32705 +               data->alarms =
32706 +                       smsc47m1_read_value(client, SMSC47M1_REG_ALARM1) >> 6;
32707 +               if(data->alarms)
32708 +                       smsc47m1_write_value(client, SMSC47M1_REG_ALARM1, 0xc0);
32709 +               data->last_updated = jiffies;
32710 +               data->valid = 1;
32711 +       }
32712 +
32713 +       up(&data->update_lock);
32714 +}
32715 +
32716 +
32717 +void smsc47m1_fan(struct i2c_client *client, int operation, int ctl_name,
32718 +                int *nrels_mag, long *results)
32719 +{
32720 +       struct smsc47m1_data *data = client->data;
32721 +       int nr = ctl_name - SMSC47M1_SYSCTL_FAN1 + 1;
32722 +
32723 +       if (operation == SENSORS_PROC_REAL_INFO)
32724 +               *nrels_mag = 0;
32725 +       else if (operation == SENSORS_PROC_REAL_READ) {
32726 +               smsc47m1_update_client(client);
32727 +               results[0] = MIN_FROM_REG(data->fan_min[nr - 1],
32728 +                                         DIV_FROM_REG(data->fan_div[nr - 1]));
32729 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
32730 +                                         DIV_FROM_REG(data->fan_div[nr - 1]),
32731 +                                         data->fan_min[nr - 1]);
32732 +               *nrels_mag = 2;
32733 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
32734 +               if (*nrels_mag >= 1) {
32735 +                       data->fan_min[nr - 1] = MIN_TO_REG(results[0],
32736 +                                                          DIV_FROM_REG
32737 +                                                          (data->
32738 +                                                           fan_div[nr-1]));
32739 +                       smsc47m1_write_value(client, SMSC47M1_REG_FAN_MIN(nr),
32740 +                                           data->fan_min[nr - 1]);
32741 +               }
32742 +       }
32743 +}
32744 +
32745 +
32746 +void smsc47m1_alarms(struct i2c_client *client, int operation, int ctl_name,
32747 +                   int *nrels_mag, long *results)
32748 +{
32749 +       struct smsc47m1_data *data = client->data;
32750 +       if (operation == SENSORS_PROC_REAL_INFO)
32751 +               *nrels_mag = 0;
32752 +       else if (operation == SENSORS_PROC_REAL_READ) {
32753 +               smsc47m1_update_client(client);
32754 +               results[0] = data->alarms;
32755 +               *nrels_mag = 1;
32756 +       }
32757 +}
32758 +
32759 +void smsc47m1_fan_div(struct i2c_client *client, int operation,
32760 +                    int ctl_name, int *nrels_mag, long *results)
32761 +{
32762 +       struct smsc47m1_data *data = client->data;
32763 +       int old;
32764 +
32765 +       if (operation == SENSORS_PROC_REAL_INFO)
32766 +               *nrels_mag = 0;
32767 +       else if (operation == SENSORS_PROC_REAL_READ) {
32768 +               smsc47m1_update_client(client);
32769 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
32770 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
32771 +               *nrels_mag = 2;
32772 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
32773 +               old = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
32774 +               if (*nrels_mag >= 2) {
32775 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
32776 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
32777 +               }
32778 +               if (*nrels_mag >= 1) {
32779 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
32780 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
32781 +                       smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, old);
32782 +               }
32783 +       }
32784 +}
32785 +
32786 +void smsc47m1_pwm(struct i2c_client *client, int operation, int ctl_name,
32787 +                int *nrels_mag, long *results)
32788 +{
32789 +       struct smsc47m1_data *data = client->data;
32790 +       int nr = 1 + ctl_name - SMSC47M1_SYSCTL_PWM1;
32791 +
32792 +       if (operation == SENSORS_PROC_REAL_INFO)
32793 +               *nrels_mag = 0;
32794 +       else if (operation == SENSORS_PROC_REAL_READ) {
32795 +               smsc47m1_update_client(client);
32796 +               results[0] = PWM_FROM_REG(data->pwm[nr - 1]);
32797 +               results[1] = data->pwm[nr - 1] & 0x01;
32798 +               *nrels_mag = 2;
32799 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
32800 +               if (*nrels_mag >= 1) {
32801 +                       data->pwm[nr - 1] &= 0x81;
32802 +                       data->pwm[nr - 1] |= PWM_TO_REG(results[0]);
32803 +                       if (*nrels_mag >= 2) {
32804 +                               if(results[1] && (data->pwm[nr-1] & 0x01)) {
32805 +                                       /* enable PWM */
32806 +/* hope BIOS did it already
32807 +                                       smsc47m1_write_value(client,
32808 +                                                 SMSC47M1_REG_PPIN(nr), 0x04);
32809 +*/
32810 +                                       data->pwm[nr - 1] &= 0xfe;
32811 +                               } else if((!results[1]) && (!(data->pwm[nr-1] & 0x01))) {
32812 +                                       /* disable PWM */
32813 +                                       data->pwm[nr - 1] |= 0x01;
32814 +                               }
32815 +                       }
32816 +                       smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
32817 +                                            data->pwm[nr - 1]);
32818 +               }
32819 +       }
32820 +}
32821 +
32822 +static int __init sm_smsc47m1_init(void)
32823 +{
32824 +       int addr;
32825 +
32826 +       printk("smsc47m1.o version %s (%s)\n", LM_VERSION, LM_DATE);
32827 +
32828 +       if (smsc47m1_find(&addr)) {
32829 +               printk("smsc47m1.o: SMSC 47M1xx not detected, module not inserted.\n");
32830 +               return -ENODEV;
32831 +       }
32832 +       normal_isa[0] = addr;
32833 +
32834 +       return i2c_add_driver(&smsc47m1_driver);
32835 +}
32836 +
32837 +static void __exit sm_smsc47m1_exit(void)
32838 +{
32839 +       i2c_del_driver(&smsc47m1_driver);
32840 +}
32841 +
32842 +
32843 +
32844 +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
32845 +MODULE_DESCRIPTION("SMSC 47M1xx Fan sensors");
32846 +MODULE_LICENSE("GPL");
32847 +
32848 +module_init(sm_smsc47m1_init);
32849 +module_exit(sm_smsc47m1_exit);
32850 --- linux-old/drivers/sensors/thmc50.c  Thu Jan  1 00:00:00 1970
32851 +++ linux/drivers/sensors/thmc50.c      Mon Dec 13 20:18:52 2004
32852 @@ -0,0 +1,496 @@
32853 +/*
32854 +    thmc50.c - Part of lm_sensors, Linux kernel modules for hardware
32855 +             monitoring
32856 +    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
32857 +    Philip Edelbrock <phil@netroedge.com>
32858 +
32859 +    This program is free software; you can redistribute it and/or modify
32860 +    it under the terms of the GNU General Public License as published by
32861 +    the Free Software Foundation; either version 2 of the License, or
32862 +    (at your option) any later version.
32863 +
32864 +    This program is distributed in the hope that it will be useful,
32865 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
32866 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32867 +    GNU General Public License for more details.
32868 +
32869 +    You should have received a copy of the GNU General Public License
32870 +    along with this program; if not, write to the Free Software
32871 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32872 +*/
32873 +
32874 +#define DEBUG 1
32875 +
32876 +#include <linux/module.h>
32877 +#include <linux/slab.h>
32878 +#include <linux/i2c.h>
32879 +#include <linux/i2c-proc.h>
32880 +#include <linux/init.h>
32881 +#define LM_DATE "20041007"
32882 +#define LM_VERSION "2.8.8"
32883 +
32884 +MODULE_LICENSE("GPL");
32885 +
32886 +/* Addresses to scan */
32887 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
32888 +static unsigned short normal_i2c_range[] = { 0x2D, 0x2E, SENSORS_I2C_END };
32889 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
32890 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
32891 +
32892 +/* Insmod parameters */
32893 +SENSORS_INSMOD_1(thmc50);
32894 +
32895 +/* Many THMC50 constants specified below */
32896 +
32897 +/* The THMC50 registers */
32898 +#define THMC50_REG_TEMP 0x27
32899 +#define THMC50_REG_CONF 0x40
32900 +#define THMC50_REG_TEMP_HYST 0x3A
32901 +#define THMC50_REG_TEMP_OS 0x39
32902 +
32903 +#define THMC50_REG_TEMP_TRIP 0x13
32904 +#define THMC50_REG_TEMP_REMOTE_TRIP 0x14
32905 +#define THMC50_REG_TEMP_DEFAULT_TRIP 0x17
32906 +#define THMC50_REG_TEMP_REMOTE_DEFAULT_TRIP 0x18
32907 +#define THMC50_REG_ANALOG_OUT 0x19
32908 +#define THMC50_REG_REMOTE_TEMP 0x26
32909 +#define THMC50_REG_REMOTE_TEMP_HYST 0x38
32910 +#define THMC50_REG_REMOTE_TEMP_OS 0x37
32911 +
32912 +#define THMC50_REG_INTER 0x41
32913 +#define THMC50_REG_INTER_MIRROR 0x4C
32914 +#define THMC50_REG_INTER_MASK 0x43
32915 +
32916 +#define THMC50_REG_COMPANY_ID 0x3E
32917 +#define THMC50_REG_DIE_CODE 0x3F
32918 +
32919 +
32920 +/* Conversions. Rounding and limit checking is only done on the TO_REG
32921 +   variants. Note that you should be a bit careful with which arguments
32922 +   these macros are called: arguments may be evaluated more than once.
32923 +   Fixing this is just not worth it. */
32924 +#define TEMP_FROM_REG(val) ((val>127)?val - 0x0100:val)
32925 +#define TEMP_TO_REG(val)   ((val<0)?0x0100+val:val)
32926 +
32927 +/* Each client has this additional data */
32928 +struct thmc50_data {
32929 +       struct i2c_client client;
32930 +       int sysctl_id;
32931 +
32932 +       struct semaphore update_lock;
32933 +       char valid;             /* !=0 if following fields are valid */
32934 +       unsigned long last_updated;     /* In jiffies */
32935 +
32936 +       u16 temp, temp_os, temp_hyst,
32937 +           remote_temp, remote_temp_os, remote_temp_hyst,
32938 +           inter, inter_mask, die_code, analog_out;    /* Register values */
32939 +};
32940 +
32941 +static int thmc50_attach_adapter(struct i2c_adapter *adapter);
32942 +static int thmc50_detect(struct i2c_adapter *adapter, int address,
32943 +                        unsigned short flags, int kind);
32944 +static void thmc50_init_client(struct i2c_client *client);
32945 +static int thmc50_detach_client(struct i2c_client *client);
32946 +
32947 +static int thmc50_read_value(struct i2c_client *client, u8 reg);
32948 +static int thmc50_write_value(struct i2c_client *client, u8 reg,
32949 +                             u16 value);
32950 +static void thmc50_temp(struct i2c_client *client, int operation,
32951 +                       int ctl_name, int *nrels_mag, long *results);
32952 +static void thmc50_remote_temp(struct i2c_client *client, int operation,
32953 +                              int ctl_name, int *nrels_mag,
32954 +                              long *results);
32955 +static void thmc50_inter(struct i2c_client *client, int operation,
32956 +                        int ctl_name, int *nrels_mag, long *results);
32957 +static void thmc50_inter_mask(struct i2c_client *client, int operation,
32958 +                             int ctl_name, int *nrels_mag, long *results);
32959 +static void thmc50_die_code(struct i2c_client *client, int operation,
32960 +                           int ctl_name, int *nrels_mag, long *results);
32961 +static void thmc50_analog_out(struct i2c_client *client, int operation,
32962 +                             int ctl_name, int *nrels_mag, long *results);
32963 +static void thmc50_update_client(struct i2c_client *client);
32964 +
32965 +
32966 +/* This is the driver that will be inserted */
32967 +static struct i2c_driver thmc50_driver = {
32968 +       .owner          = THIS_MODULE,
32969 +       .name           = "THMC50 sensor chip driver",
32970 +       .id             = I2C_DRIVERID_THMC50,
32971 +       .flags          = I2C_DF_NOTIFY,
32972 +       .attach_adapter = thmc50_attach_adapter,
32973 +       .detach_client  = thmc50_detach_client,
32974 +};
32975 +
32976 +/* -- SENSORS SYSCTL START -- */
32977 +
32978 +#define THMC50_SYSCTL_TEMP 1200        /* Degrees Celcius */
32979 +#define THMC50_SYSCTL_REMOTE_TEMP 1201 /* Degrees Celcius */
32980 +#define THMC50_SYSCTL_INTER 1202
32981 +#define THMC50_SYSCTL_INTER_MASK 1203
32982 +#define THMC50_SYSCTL_DIE_CODE 1204
32983 +#define THMC50_SYSCTL_ANALOG_OUT 1205
32984 +
32985 +/* -- SENSORS SYSCTL END -- */
32986 +
32987 +/* These files are created for each detected THMC50. This is just a template;
32988 +   though at first sight, you might think we could use a statically
32989 +   allocated list, we need some way to get back to the parent - which
32990 +   is done through one of the 'extra' fields which are initialized
32991 +   when a new copy is allocated. */
32992 +static ctl_table thmc50_dir_table_template[] = {
32993 +       {THMC50_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
32994 +        &i2c_sysctl_real, NULL, &thmc50_temp},
32995 +       {THMC50_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
32996 +        &i2c_sysctl_real, NULL, &thmc50_remote_temp},
32997 +       {THMC50_SYSCTL_INTER, "inter", NULL, 0, 0444, NULL, &i2c_proc_real,
32998 +        &i2c_sysctl_real, NULL, &thmc50_inter},
32999 +       {THMC50_SYSCTL_INTER_MASK, "inter_mask", NULL, 0, 0644, NULL, &i2c_proc_real,
33000 +        &i2c_sysctl_real, NULL, &thmc50_inter_mask},
33001 +       {THMC50_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
33002 +        &i2c_sysctl_real, NULL, &thmc50_die_code},
33003 +       {THMC50_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL, &i2c_proc_real,
33004 +        &i2c_sysctl_real, NULL, &thmc50_analog_out},
33005 +       {0}
33006 +};
33007 +
33008 +
33009 +static int thmc50_id = 0;
33010 +
33011 +static int thmc50_attach_adapter(struct i2c_adapter *adapter)
33012 +{
33013 +       return i2c_detect(adapter, &addr_data, thmc50_detect);
33014 +}
33015 +
33016 +/* This function is called by i2c_detect */
33017 +int thmc50_detect(struct i2c_adapter *adapter, int address,
33018 +                 unsigned short flags, int kind)
33019 +{
33020 +       int company, i;
33021 +       struct i2c_client *new_client;
33022 +       struct thmc50_data *data;
33023 +       int err = 0;
33024 +       const char *type_name, *client_name;
33025 +
33026 +#ifdef DEBUG
33027 +       printk("thmc50.o: Probing for THMC50 at 0x%2X on bus %d\n",
33028 +              address, adapter->id);
33029 +#endif
33030 +
33031 +       /* Make sure we aren't probing the ISA bus!! This is just a safety check
33032 +          at this moment; i2c_detect really won't call us. */
33033 +#ifdef DEBUG
33034 +       if (i2c_is_isa_adapter(adapter)) {
33035 +               printk
33036 +                   ("thmc50.o: thmc50_detect called for an ISA bus adapter?!?\n");
33037 +               return 0;
33038 +       }
33039 +#endif
33040 +
33041 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
33042 +               goto ERROR0;
33043 +
33044 +       /* OK. For now, we presume we have a valid client. We now create the
33045 +          client structure, even though we cannot fill it completely yet.
33046 +          But it allows us to access thmc50_{read,write}_value. */
33047 +       if (!(data = kmalloc(sizeof(struct thmc50_data), GFP_KERNEL))) {
33048 +               err = -ENOMEM;
33049 +               goto ERROR0;
33050 +       }
33051 +
33052 +       new_client = &data->client;
33053 +       new_client->addr = address;
33054 +       new_client->data = data;
33055 +       new_client->adapter = adapter;
33056 +       new_client->driver = &thmc50_driver;
33057 +       new_client->flags = 0;
33058 +
33059 +       /* Now, we do the remaining detection. */
33060 +       company =
33061 +           i2c_smbus_read_byte_data(new_client, THMC50_REG_COMPANY_ID);
33062 +
33063 +       if (company != 0x49) {
33064 +#ifdef DEBUG
33065 +               printk
33066 +                   ("thmc50.o: Detect of THMC50 failed (reg 3E: 0x%X)\n",
33067 +                    company);
33068 +#endif
33069 +               goto ERROR1;
33070 +       }
33071 +
33072 +       /* Determine the chip type - only one kind supported! */
33073 +       kind = thmc50;
33074 +
33075 +       if (kind == thmc50) {
33076 +               type_name = "thmc50";
33077 +               client_name = "THMC50 chip";
33078 +       } else {
33079 +#ifdef DEBUG
33080 +               printk("thmc50.o: Internal error: unknown kind (%d)?!?",
33081 +                      kind);
33082 +#endif
33083 +               goto ERROR1;
33084 +       }
33085 +
33086 +       /* Fill in the remaining client fields and put it into the global list */
33087 +       strcpy(new_client->name, client_name);
33088 +
33089 +       new_client->id = thmc50_id++;
33090 +       data->valid = 0;
33091 +       init_MUTEX(&data->update_lock);
33092 +
33093 +       /* Tell the I2C layer a new client has arrived */
33094 +       if ((err = i2c_attach_client(new_client)))
33095 +               goto ERROR3;
33096 +
33097 +       /* Register a new directory entry with module sensors */
33098 +       if ((i = i2c_register_entry(new_client, type_name,
33099 +                                       thmc50_dir_table_template)) < 0) {
33100 +               err = i;
33101 +               goto ERROR4;
33102 +       }
33103 +       data->sysctl_id = i;
33104 +
33105 +       thmc50_init_client(new_client);
33106 +       return 0;
33107 +
33108 +/* OK, this is not exactly good programming practice, usually. But it is
33109 +   very code-efficient in this case. */
33110 +
33111 +      ERROR4:
33112 +       i2c_detach_client(new_client);
33113 +      ERROR3:
33114 +      ERROR1:
33115 +       kfree(data);
33116 +      ERROR0:
33117 +       return err;
33118 +}
33119 +
33120 +static int thmc50_detach_client(struct i2c_client *client)
33121 +{
33122 +       int err;
33123 +
33124 +       i2c_deregister_entry(((struct thmc50_data *) (client->data))->
33125 +                                sysctl_id);
33126 +
33127 +       if ((err = i2c_detach_client(client))) {
33128 +               printk
33129 +                   ("thmc50.o: Client deregistration failed, client not detached.\n");
33130 +               return err;
33131 +       }
33132 +
33133 +       kfree(client->data);
33134 +
33135 +       return 0;
33136 +}
33137 +
33138 +
33139 +/* All registers are word-sized, except for the configuration register.
33140 +   THMC50 uses a high-byte first convention, which is exactly opposite to
33141 +   the usual practice. */
33142 +static int thmc50_read_value(struct i2c_client *client, u8 reg)
33143 +{
33144 +       return i2c_smbus_read_byte_data(client, reg);
33145 +}
33146 +
33147 +/* All registers are word-sized, except for the configuration register.
33148 +   THMC50 uses a high-byte first convention, which is exactly opposite to
33149 +   the usual practice. */
33150 +static int thmc50_write_value(struct i2c_client *client, u8 reg, u16 value)
33151 +{
33152 +       return i2c_smbus_write_byte_data(client, reg, value);
33153 +}
33154 +
33155 +static void thmc50_init_client(struct i2c_client *client)
33156 +{
33157 +       thmc50_write_value(client, THMC50_REG_CONF, 1);
33158 +}
33159 +
33160 +static void thmc50_update_client(struct i2c_client *client)
33161 +{
33162 +       struct thmc50_data *data = client->data;
33163 +
33164 +       down(&data->update_lock);
33165 +
33166 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
33167 +           (jiffies < data->last_updated) || !data->valid) {
33168 +
33169 +#ifdef DEBUG
33170 +               printk("Starting thmc50 update\n");
33171 +#endif
33172 +
33173 +               data->temp = thmc50_read_value(client, THMC50_REG_TEMP);
33174 +               data->temp_os =
33175 +                   thmc50_read_value(client, THMC50_REG_TEMP_OS);
33176 +               data->temp_hyst =
33177 +                   thmc50_read_value(client, THMC50_REG_TEMP_HYST);
33178 +               data->remote_temp =
33179 +                   thmc50_read_value(client, THMC50_REG_REMOTE_TEMP);
33180 +               data->remote_temp_os =
33181 +                   thmc50_read_value(client, THMC50_REG_REMOTE_TEMP_OS);
33182 +               data->remote_temp_hyst =
33183 +                   thmc50_read_value(client, THMC50_REG_REMOTE_TEMP_HYST);
33184 +               data->inter = thmc50_read_value(client, THMC50_REG_INTER);
33185 +               data->inter_mask =
33186 +                   thmc50_read_value(client, THMC50_REG_INTER_MASK);
33187 +               data->die_code =
33188 +                   thmc50_read_value(client, THMC50_REG_DIE_CODE);
33189 +               data->analog_out =
33190 +                   thmc50_read_value(client, THMC50_REG_ANALOG_OUT);
33191 +               data->last_updated = jiffies;
33192 +               data->valid = 1;
33193 +       }
33194 +
33195 +       up(&data->update_lock);
33196 +}
33197 +
33198 +
33199 +void thmc50_temp(struct i2c_client *client, int operation, int ctl_name,
33200 +                int *nrels_mag, long *results)
33201 +{
33202 +       struct thmc50_data *data = client->data;
33203 +       if (operation == SENSORS_PROC_REAL_INFO)
33204 +               *nrels_mag = 0;
33205 +       else if (operation == SENSORS_PROC_REAL_READ) {
33206 +               thmc50_update_client(client);
33207 +               results[0] = TEMP_FROM_REG(data->temp_os);
33208 +               results[1] = TEMP_FROM_REG(data->temp_hyst);
33209 +               results[2] = TEMP_FROM_REG(data->temp);
33210 +               *nrels_mag = 3;
33211 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
33212 +               if (*nrels_mag >= 1) {
33213 +                       data->temp_os = TEMP_TO_REG(results[0]);
33214 +                       thmc50_write_value(client, THMC50_REG_TEMP_OS,
33215 +                                          data->temp_os);
33216 +               }
33217 +               if (*nrels_mag >= 2) {
33218 +                       data->temp_hyst = TEMP_TO_REG(results[1]);
33219 +                       thmc50_write_value(client, THMC50_REG_TEMP_HYST,
33220 +                                          data->temp_hyst);
33221 +               }
33222 +       }
33223 +}
33224 +
33225 +
33226 +void thmc50_remote_temp(struct i2c_client *client, int operation,
33227 +                       int ctl_name, int *nrels_mag, long *results)
33228 +{
33229 +       struct thmc50_data *data = client->data;
33230 +       if (operation == SENSORS_PROC_REAL_INFO)
33231 +               *nrels_mag = 0;
33232 +       else if (operation == SENSORS_PROC_REAL_READ) {
33233 +               thmc50_update_client(client);
33234 +               results[0] = TEMP_FROM_REG(data->remote_temp_os);
33235 +               results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
33236 +               results[2] = TEMP_FROM_REG(data->remote_temp);
33237 +               *nrels_mag = 3;
33238 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
33239 +               if (*nrels_mag >= 1) {
33240 +                       data->remote_temp_os = TEMP_TO_REG(results[0]);
33241 +                       thmc50_write_value(client,
33242 +                                          THMC50_REG_REMOTE_TEMP_OS,
33243 +                                          data->remote_temp_os);
33244 +               }
33245 +               if (*nrels_mag >= 2) {
33246 +                       data->remote_temp_hyst = TEMP_TO_REG(results[1]);
33247 +                       thmc50_write_value(client,
33248 +                                          THMC50_REG_REMOTE_TEMP_HYST,
33249 +                                          data->remote_temp_hyst);
33250 +               }
33251 +       }
33252 +}
33253 +
33254 +
33255 +void thmc50_inter(struct i2c_client *client, int operation, int ctl_name,
33256 +                 int *nrels_mag, long *results)
33257 +{
33258 +       struct thmc50_data *data = client->data;
33259 +       if (operation == SENSORS_PROC_REAL_INFO)
33260 +               *nrels_mag = 0;
33261 +       else if (operation == SENSORS_PROC_REAL_READ) {
33262 +               thmc50_update_client(client);
33263 +               results[0] = data->inter;
33264 +               *nrels_mag = 1;
33265 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
33266 +               printk("thmc50.o: No writes to Interrupt register!\n");
33267 +       }
33268 +}
33269 +
33270 +
33271 +void thmc50_inter_mask(struct i2c_client *client, int operation,
33272 +                      int ctl_name, int *nrels_mag, long *results)
33273 +{
33274 +       struct thmc50_data *data = client->data;
33275 +       if (operation == SENSORS_PROC_REAL_INFO)
33276 +               *nrels_mag = 0;
33277 +       else if (operation == SENSORS_PROC_REAL_READ) {
33278 +               thmc50_update_client(client);
33279 +               results[0] = data->inter_mask;
33280 +               *nrels_mag = 1;
33281 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
33282 +               if (*nrels_mag >= 1) {
33283 +                       data->inter_mask = results[0];
33284 +                       thmc50_write_value(client, THMC50_REG_INTER_MASK,
33285 +                                          data->inter_mask);
33286 +               }
33287 +       }
33288 +}
33289 +
33290 +
33291 +void thmc50_die_code(struct i2c_client *client, int operation,
33292 +                    int ctl_name, int *nrels_mag, long *results)
33293 +{
33294 +       struct thmc50_data *data = client->data;
33295 +       if (operation == SENSORS_PROC_REAL_INFO)
33296 +               *nrels_mag = 0;
33297 +       else if (operation == SENSORS_PROC_REAL_READ) {
33298 +               thmc50_update_client(client);
33299 +               results[0] = data->die_code;
33300 +               *nrels_mag = 1;
33301 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
33302 +               printk("thmc50.o: No writes to Die-Code register!\n");
33303 +       }
33304 +}
33305 +
33306 +
33307 +void thmc50_analog_out(struct i2c_client *client, int operation,
33308 +                      int ctl_name, int *nrels_mag, long *results)
33309 +{
33310 +       struct thmc50_data *data = client->data;
33311 +       if (operation == SENSORS_PROC_REAL_INFO)
33312 +               *nrels_mag = 0;
33313 +       else if (operation == SENSORS_PROC_REAL_READ) {
33314 +               thmc50_update_client(client);
33315 +               results[0] = data->analog_out;
33316 +               *nrels_mag = 1;
33317 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
33318 +               if (*nrels_mag >= 1) {
33319 +                       data->analog_out = results[0];
33320 +                       thmc50_write_value(client, THMC50_REG_ANALOG_OUT,
33321 +                                          data->analog_out);
33322 +               }
33323 +       }
33324 +}
33325 +
33326 +
33327 +
33328 +
33329 +static int __init sm_thmc50_init(void)
33330 +{
33331 +       printk("thmc50.o version %s (%s)\n", LM_VERSION, LM_DATE);
33332 +
33333 +       return i2c_add_driver(&thmc50_driver);
33334 +}
33335 +
33336 +static void __exit sm_thmc50_exit(void)
33337 +{
33338 +       i2c_del_driver(&thmc50_driver);
33339 +}
33340 +
33341 +
33342 +
33343 +MODULE_AUTHOR
33344 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
33345 +MODULE_DESCRIPTION("THMC50 driver");
33346 +
33347 +module_init(sm_thmc50_init);
33348 +module_exit(sm_thmc50_exit);
33349 --- linux-old/drivers/sensors/via686a.c Thu Jan  1 00:00:00 1970
33350 +++ linux/drivers/sensors/via686a.c     Mon Dec 13 20:18:52 2004
33351 @@ -0,0 +1,849 @@
33352 +/*
33353 +    via686a.c - Part of lm_sensors, Linux kernel modules
33354 +                for hardware monitoring
33355 +                
33356 +    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
33357 +                        Kyösti Mälkki <kmalkki@cc.hut.fi>,
33358 +                       Mark Studebaker <mdsxyz123@yahoo.com>,
33359 +                       and Bob Dougherty <bobd@stanford.edu>
33360 +    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew 
33361 +    <j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
33362 +
33363 +    This program is free software; you can redistribute it and/or modify
33364 +    it under the terms of the GNU General Public License as published by
33365 +    the Free Software Foundation; either version 2 of the License, or
33366 +    (at your option) any later version.
33367 +
33368 +    This program is distributed in the hope that it will be useful,
33369 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
33370 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33371 +    GNU General Public License for more details.
33372 +
33373 +    You should have received a copy of the GNU General Public License
33374 +    along with this program; if not, write to the Free Software
33375 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33376 +*/
33377 +
33378 +/*
33379 +    Supports the Via VT82C686A, VT82C686B south bridges.
33380 +    Reports all as a 686A.
33381 +    See doc/chips/via686a for details.
33382 +    Warning - only supports a single device.
33383 +*/
33384 +
33385 +#include <linux/module.h>
33386 +#include <linux/slab.h>
33387 +#include <linux/pci.h>
33388 +#include <linux/delay.h>
33389 +#include <linux/i2c.h>
33390 +#include <linux/i2c-proc.h>
33391 +#include <linux/init.h>
33392 +#include <asm/io.h>
33393 +#define LM_DATE "20041007"
33394 +#define LM_VERSION "2.8.8"
33395 +
33396 +
33397 +/* If force_addr is set to anything different from 0, we forcibly enable
33398 +   the device at the given address. */
33399 +static int force_addr = 0;
33400 +MODULE_PARM(force_addr, "i");
33401 +MODULE_PARM_DESC(force_addr,
33402 +                "Initialize the base address of the sensors");
33403 +
33404 +/* Addresses to scan.
33405 +   Note that we can't determine the ISA address until we have initialized
33406 +   our module */
33407 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
33408 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
33409 +static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
33410 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
33411 +
33412 +/* Insmod parameters */
33413 +SENSORS_INSMOD_1(via686a);
33414 +
33415 +/*
33416 +   The Via 686a southbridge has a LM78-like chip integrated on the same IC.
33417 +   This driver is a customized copy of lm78.c
33418 +*/
33419 +
33420 +/* Many VIA686A constants specified below */
33421 +
33422 +/* Length of ISA address segment */
33423 +#define VIA686A_EXTENT 0x80
33424 +#define VIA686A_BASE_REG 0x70
33425 +#define VIA686A_ENABLE_REG 0x74
33426 +
33427 +/* The VIA686A registers */
33428 +/* ins numbered 0-4 */
33429 +#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
33430 +#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
33431 +#define VIA686A_REG_IN(nr)     (0x22 + (nr))
33432 +
33433 +/* fans numbered 1-2 */
33434 +#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
33435 +#define VIA686A_REG_FAN(nr)     (0x28 + (nr))
33436 +
33437 +// the following values are as speced by VIA:
33438 +static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
33439 +static const u8 regover[] = { 0x39, 0x3d, 0x1d };
33440 +static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
33441 +
33442 +/* temps numbered 1-3 */
33443 +#define VIA686A_REG_TEMP(nr)           (regtemp[(nr) - 1])
33444 +#define VIA686A_REG_TEMP_OVER(nr)      (regover[(nr) - 1])
33445 +#define VIA686A_REG_TEMP_HYST(nr)      (reghyst[(nr) - 1])
33446 +#define VIA686A_REG_TEMP_LOW1  0x4b    // bits 7-6
33447 +#define VIA686A_REG_TEMP_LOW23 0x49    // 2 = bits 5-4, 3 = bits 7-6
33448 +
33449 +#define VIA686A_REG_ALARM1 0x41
33450 +#define VIA686A_REG_ALARM2 0x42
33451 +#define VIA686A_REG_FANDIV 0x47
33452 +#define VIA686A_REG_CONFIG 0x40
33453 +// The following register sets temp interrupt mode (bits 1-0 for temp1, 
33454 +// 3-2 for temp2, 5-4 for temp3).  Modes are:
33455 +//    00 interrupt stays as long as value is out-of-range
33456 +//    01 interrupt is cleared once register is read (default)
33457 +//    10 comparator mode- like 00, but ignores hysteresis
33458 +//    11 same as 00
33459 +#define VIA686A_REG_TEMP_MODE 0x4b
33460 +// We'll just assume that you want to set all 3 simultaneously:
33461 +#define VIA686A_TEMP_MODE_MASK 0x3F
33462 +#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
33463 +
33464 +/* Conversions. Limit checking is only done on the TO_REG
33465 +   variants. */
33466 +
33467 +/********* VOLTAGE CONVERSIONS (Bob Dougherty) ********/
33468 +// From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
33469 +// voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp
33470 +// voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V
33471 +// voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V
33472 +// voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V
33473 +// voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V
33474 +// in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
33475 +// That is:
33476 +// volts = (25*regVal+133)*factor
33477 +// regVal = (volts/factor-133)/25
33478 +// (These conversions were contributed by Jonathan Teh Soon Yew 
33479 +// <j.teh@iname.com>)
33480 +static inline u8 IN_TO_REG(long val, int inNum)
33481 +{
33482 +       /* To avoid floating point, we multiply constants by 10 (100 for +12V).
33483 +          Rounding is done (120500 is actually 133000 - 12500).
33484 +          Remember that val is expressed in 0.01V/bit, which is why we divide
33485 +          by an additional 1000 (10000 for +12V): 100 for val and 10 (100)
33486 +          for the constants. */
33487 +       if (inNum <= 1)
33488 +               return (u8)
33489 +                   SENSORS_LIMIT((val * 21024 - 120500) / 25000, 0, 255);
33490 +       else if (inNum == 2)
33491 +               return (u8)
33492 +                   SENSORS_LIMIT((val * 15737 - 120500) / 25000, 0, 255);
33493 +       else if (inNum == 3)
33494 +               return (u8)
33495 +                   SENSORS_LIMIT((val * 10108 - 120500) / 25000, 0, 255);
33496 +       else
33497 +               return (u8)
33498 +                   SENSORS_LIMIT((val * 41714 - 1205000) / 250000, 0, 255);
33499 +}
33500 +
33501 +static inline long IN_FROM_REG(u8 val, int inNum)
33502 +{
33503 +       /* To avoid floating point, we multiply constants by 10 (100 for +12V).
33504 +          We also multiply them by 100 because we want 0.01V/bit for the
33505 +          output value. Rounding is done. */
33506 +       if (inNum <= 1)
33507 +               return (long) ((25000 * val + 133000 + 21024 / 2) / 21024);
33508 +       else if (inNum == 2)
33509 +               return (long) ((25000 * val + 133000 + 15737 / 2) / 15737);
33510 +       else if (inNum == 3)
33511 +               return (long) ((25000 * val + 133000 + 10108 / 2) / 10108);
33512 +       else
33513 +               return (long) ((250000 * val + 1330000 + 41714 / 2) / 41714);
33514 +}
33515 +
33516 +/********* FAN RPM CONVERSIONS ********/
33517 +// Higher register values = slower fans (the fan's strobe gates a counter).
33518 +// But this chip saturates back at 0, not at 255 like all the other chips.
33519 +// So, 0 means 0 RPM
33520 +static inline u8 FAN_TO_REG(long rpm, int div)
33521 +{
33522 +       if (rpm == 0)
33523 +               return 0;
33524 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
33525 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
33526 +}
33527 +
33528 +#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
33529 +
33530 +/******** TEMP CONVERSIONS (Bob Dougherty) *********/
33531 +// linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
33532 +//      if(temp<169)
33533 +//              return double(temp)*0.427-32.08;
33534 +//      else if(temp>=169 && temp<=202)
33535 +//              return double(temp)*0.582-58.16;
33536 +//      else
33537 +//              return double(temp)*0.924-127.33;
33538 +//
33539 +// A fifth-order polynomial fits the unofficial data (provided by Alex van 
33540 +// Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable 
33541 +// numbers on my machine (ie. they agree with what my BIOS tells me).  
33542 +// Here's the fifth-order fit to the 8-bit data:
33543 +// temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 - 
33544 +//        2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
33545 +//
33546 +// (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for 
33547 +// finding my typos in this formula!)
33548 +//
33549 +// Alas, none of the elegant function-fit solutions will work because we 
33550 +// aren't allowed to use floating point in the kernel and doing it with 
33551 +// integers doesn't rpovide enough precision.  So we'll do boring old 
33552 +// look-up table stuff.  The unofficial data (see below) have effectively 
33553 +// 7-bit resolution (they are rounded to the nearest degree).  I'm assuming 
33554 +// that the transfer function of the device is monotonic and smooth, so a 
33555 +// smooth function fit to the data will allow us to get better precision.  
33556 +// I used the 5th-order poly fit described above and solved for
33557 +// VIA register values 0-255.  I *10 before rounding, so we get tenth-degree 
33558 +// precision.  (I could have done all 1024 values for our 10-bit readings, 
33559 +// but the function is very linear in the useful range (0-80 deg C), so 
33560 +// we'll just use linear interpolation for 10-bit readings.)  So, tempLUT 
33561 +// is the temp at via register values 0-255:
33562 +static const long tempLUT[] =
33563 +    { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
33564 +           -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
33565 +           -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
33566 +           -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
33567 +           -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
33568 +           -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
33569 +           -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
33570 +           20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
33571 +           88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
33572 +           142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
33573 +           193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
33574 +           245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
33575 +           299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
33576 +           353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
33577 +           409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
33578 +           469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
33579 +           538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
33580 +           621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
33581 +           728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
33582 +           870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
33583 +           1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
33584 +           1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
33585 +};
33586 +
33587 +/* the original LUT values from Alex van Kaam <darkside@chello.nl> 
33588 +   (for via register values 12-240):
33589 +{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
33590 +-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
33591 +-15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
33592 +-3,-2,-2,-1,-1,0,0,1,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12,
33593 +12,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
33594 +22,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
33595 +33,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
33596 +45,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
33597 +61,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
33598 +85,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
33599 +*/
33600 +
33601 +// Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
33602 +// an extra term for a good fit to these inverse data!) and then 
33603 +// solving for each temp value from -50 to 110 (the useable range for 
33604 +// this chip).  Here's the fit: 
33605 +// viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4 
33606 +// - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
33607 +// Note that n=161:
33608 +static const u8 viaLUT[] =
33609 +    { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
33610 +           23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
33611 +           41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
33612 +           69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
33613 +           103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
33614 +           131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
33615 +           158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
33616 +           182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
33617 +           200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
33618 +           214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
33619 +           225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
33620 +           233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
33621 +           239, 240
33622 +};
33623 +
33624 +/* Converting temps to (8-bit) hyst and over registers
33625 +   No interpolation here.
33626 +   The +50 is because the temps start at -50 */
33627 +static inline u8 TEMP_TO_REG(long val)
33628 +{
33629 +       return viaLUT[val <= -500 ? 0 : val >= 1100 ? 160 : 
33630 +                     (val < 0 ? val - 5 : val + 5) / 10 + 50];
33631 +}
33632 +
33633 +/* for 8-bit temperature hyst and over registers */
33634 +#define TEMP_FROM_REG(val) (tempLUT[(val)])
33635 +
33636 +/* for 10-bit temperature readings */
33637 +// You might _think_ this is too long to inline, but's it's really only
33638 +// called once...
33639 +static inline long TEMP_FROM_REG10(u16 val)
33640 +{
33641 +       // the temp values are already *10, so we don't need to do that.
33642 +       long temp;
33643 +       u16 eightBits = val >> 2;
33644 +       u16 twoBits = val & 3;
33645 +
33646 +       /* no interpolation for these */
33647 +       if (twoBits == 0 || eightBits == 255)
33648 +               return (long) tempLUT[eightBits];
33649 +
33650 +       /* do some linear interpolation */
33651 +       temp = (4 - twoBits) * tempLUT[eightBits]
33652 +            + twoBits * tempLUT[eightBits + 1];
33653 +       /* achieve rounding */
33654 +       return (temp < 0 ? temp - 2 : temp + 2) / 4;
33655 +}
33656 +
33657 +#define ALARMS_FROM_REG(val) (val)
33658 +
33659 +#define DIV_FROM_REG(val) (1 << (val))
33660 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
33661 +
33662 +/* For the VIA686A, we need to keep some data in memory.
33663 +   The structure is dynamically allocated, at the same time when a new
33664 +   via686a client is allocated. */
33665 +struct via686a_data {
33666 +       struct i2c_client client;
33667 +       struct semaphore lock;
33668 +       int sysctl_id;
33669 +
33670 +       struct semaphore update_lock;
33671 +       char valid;             /* !=0 if following fields are valid */
33672 +       unsigned long last_updated;     /* In jiffies */
33673 +
33674 +       u8 in[5];               /* Register value */
33675 +       u8 in_max[5];           /* Register value */
33676 +       u8 in_min[5];           /* Register value */
33677 +       u8 fan[2];              /* Register value */
33678 +       u8 fan_min[2];          /* Register value */
33679 +       u16 temp[3];            /* Register value 10 bit */
33680 +       u8 temp_over[3];        /* Register value */
33681 +       u8 temp_hyst[3];        /* Register value */
33682 +       u8 fan_div[2];          /* Register encoding, shifted right */
33683 +       u16 alarms;             /* Register encoding, combined */
33684 +};
33685 +
33686 +static struct pci_dev *s_bridge;       /* pointer to the (only) via686a */
33687 +
33688 +static int via686a_attach_adapter(struct i2c_adapter *adapter);
33689 +static int via686a_detect(struct i2c_adapter *adapter, int address,
33690 +                         unsigned short flags, int kind);
33691 +static int via686a_detach_client(struct i2c_client *client);
33692 +
33693 +static int via686a_read_value(struct i2c_client *client, u8 register);
33694 +static void via686a_write_value(struct i2c_client *client, u8 register,
33695 +                               u8 value);
33696 +static void via686a_update_client(struct i2c_client *client);
33697 +static void via686a_init_client(struct i2c_client *client);
33698 +
33699 +
33700 +static void via686a_in(struct i2c_client *client, int operation,
33701 +                      int ctl_name, int *nrels_mag, long *results);
33702 +static void via686a_fan(struct i2c_client *client, int operation,
33703 +                       int ctl_name, int *nrels_mag, long *results);
33704 +static void via686a_temp(struct i2c_client *client, int operation,
33705 +                        int ctl_name, int *nrels_mag, long *results);
33706 +static void via686a_alarms(struct i2c_client *client, int operation,
33707 +                          int ctl_name, int *nrels_mag, long *results);
33708 +static void via686a_fan_div(struct i2c_client *client, int operation,
33709 +                           int ctl_name, int *nrels_mag, long *results);
33710 +
33711 +static int via686a_id = 0;
33712 +
33713 +/* The driver. I choose to use type i2c_driver, as at is identical to both
33714 +   smbus_driver and isa_driver, and clients could be of either kind */
33715 +static struct i2c_driver via686a_driver = {
33716 +       .owner          = THIS_MODULE,
33717 +       .name           = "VIA 686A",
33718 +       .id             = I2C_DRIVERID_VIA686A,
33719 +       .flags          = I2C_DF_NOTIFY,
33720 +       .attach_adapter = via686a_attach_adapter,
33721 +       .detach_client  = via686a_detach_client,
33722 +};
33723 +
33724 +
33725 +
33726 +/* The /proc/sys entries */
33727 +
33728 +/* -- SENSORS SYSCTL START -- */
33729 +#define VIA686A_SYSCTL_IN0 1000
33730 +#define VIA686A_SYSCTL_IN1 1001
33731 +#define VIA686A_SYSCTL_IN2 1002
33732 +#define VIA686A_SYSCTL_IN3 1003
33733 +#define VIA686A_SYSCTL_IN4 1004
33734 +#define VIA686A_SYSCTL_FAN1 1101
33735 +#define VIA686A_SYSCTL_FAN2 1102
33736 +#define VIA686A_SYSCTL_TEMP 1200
33737 +#define VIA686A_SYSCTL_TEMP2 1201
33738 +#define VIA686A_SYSCTL_TEMP3 1202
33739 +#define VIA686A_SYSCTL_FAN_DIV 2000
33740 +#define VIA686A_SYSCTL_ALARMS 2001
33741 +
33742 +#define VIA686A_ALARM_IN0 0x01
33743 +#define VIA686A_ALARM_IN1 0x02
33744 +#define VIA686A_ALARM_IN2 0x04
33745 +#define VIA686A_ALARM_IN3 0x08
33746 +#define VIA686A_ALARM_TEMP 0x10
33747 +#define VIA686A_ALARM_FAN1 0x40
33748 +#define VIA686A_ALARM_FAN2 0x80
33749 +#define VIA686A_ALARM_IN4 0x100
33750 +#define VIA686A_ALARM_TEMP2 0x800
33751 +#define VIA686A_ALARM_CHAS 0x1000
33752 +#define VIA686A_ALARM_TEMP3 0x8000
33753 +
33754 +/* -- SENSORS SYSCTL END -- */
33755 +
33756 +/* These files are created for each detected VIA686A. This is just a template;
33757 +   though at first sight, you might think we could use a statically
33758 +   allocated list, we need some way to get back to the parent - which
33759 +   is done through one of the 'extra' fields which are initialized 
33760 +   when a new copy is allocated. */
33761 +static ctl_table via686a_dir_table_template[] = {
33762 +       {VIA686A_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
33763 +        &i2c_sysctl_real, NULL, &via686a_in},
33764 +       {VIA686A_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
33765 +        &i2c_sysctl_real, NULL, &via686a_in},
33766 +       {VIA686A_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
33767 +        &i2c_sysctl_real, NULL, &via686a_in},
33768 +       {VIA686A_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
33769 +        &i2c_sysctl_real, NULL, &via686a_in},
33770 +       {VIA686A_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
33771 +        &i2c_sysctl_real, NULL, &via686a_in},
33772 +       {VIA686A_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
33773 +        &i2c_sysctl_real, NULL, &via686a_fan},
33774 +       {VIA686A_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
33775 +        &i2c_sysctl_real, NULL, &via686a_fan},
33776 +       {VIA686A_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
33777 +        &i2c_sysctl_real, NULL, &via686a_temp},
33778 +       {VIA686A_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
33779 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
33780 +       {VIA686A_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
33781 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
33782 +       {VIA686A_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
33783 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_fan_div},
33784 +       {VIA686A_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
33785 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_alarms},
33786 +       {0}
33787 +};
33788 +
33789 +static inline int via686a_read_value(struct i2c_client *client, u8 reg)
33790 +{
33791 +       return (inb_p(client->addr + reg));
33792 +}
33793 +
33794 +static inline void via686a_write_value(struct i2c_client *client, u8 reg,
33795 +                                      u8 value)
33796 +{
33797 +       outb_p(value, client->addr + reg);
33798 +}
33799 +
33800 +/* This is called when the module is loaded */
33801 +static int via686a_attach_adapter(struct i2c_adapter *adapter)
33802 +{
33803 +       return i2c_detect(adapter, &addr_data, via686a_detect);
33804 +}
33805 +
33806 +int via686a_detect(struct i2c_adapter *adapter, int address,
33807 +                  unsigned short flags, int kind)
33808 +{
33809 +       int i;
33810 +       struct i2c_client *new_client;
33811 +       struct via686a_data *data;
33812 +       int err = 0;
33813 +       const char *type_name = "via686a";
33814 +       u16 val;
33815 +
33816 +       /* Make sure we are probing the ISA bus!!  */
33817 +       if (!i2c_is_isa_adapter(adapter)) {
33818 +               printk
33819 +               ("via686a.o: via686a_detect called for an I2C bus adapter?!?\n");
33820 +               return 0;
33821 +       }
33822 +
33823 +       /* 8231 requires multiple of 256, we enforce that on 686 as well */
33824 +       if(force_addr)
33825 +               address = force_addr & 0xFF00;
33826 +       if (check_region(address, VIA686A_EXTENT)) {
33827 +               printk("via686a.o: region 0x%x already in use!\n",
33828 +                      address);
33829 +               return -ENODEV;
33830 +       }
33831 +
33832 +       if(force_addr) {
33833 +               printk("via686a.o: forcing ISA address 0x%04X\n", address);
33834 +               if (PCIBIOS_SUCCESSFUL !=
33835 +                   pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
33836 +                       return -ENODEV;
33837 +       }
33838 +       if (PCIBIOS_SUCCESSFUL !=
33839 +           pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
33840 +               return -ENODEV;
33841 +       if (!(val & 0x0001)) {
33842 +               printk("via686a.o: enabling sensors\n");
33843 +               if (PCIBIOS_SUCCESSFUL !=
33844 +                   pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
33845 +                                     val | 0x0001))
33846 +                       return -ENODEV;
33847 +       }
33848 +
33849 +       if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
33850 +               err = -ENOMEM;
33851 +               goto ERROR0;
33852 +       }
33853 +
33854 +       new_client = &data->client;
33855 +       new_client->addr = address;
33856 +       init_MUTEX(&data->lock);
33857 +       new_client->data = data;
33858 +       new_client->adapter = adapter;
33859 +       new_client->driver = &via686a_driver;
33860 +       new_client->flags = 0;
33861 +
33862 +       /* Reserve the ISA region */
33863 +       request_region(address, VIA686A_EXTENT, "via686a-sensors");
33864 +
33865 +       /* Fill in the remaining client fields and put into the global list */
33866 +       strcpy(new_client->name, "Via 686A Integrated Sensors");
33867 +
33868 +       new_client->id = via686a_id++;
33869 +       data->valid = 0;
33870 +       init_MUTEX(&data->update_lock);
33871 +
33872 +       /* Tell the I2C layer a new client has arrived */
33873 +       if ((err = i2c_attach_client(new_client)))
33874 +               goto ERROR3;
33875 +
33876 +       /* Register a new directory entry with module sensors */
33877 +       if ((i = i2c_register_entry((struct i2c_client *) new_client,
33878 +                                       type_name,
33879 +                                       via686a_dir_table_template)) < 0) {
33880 +               err = i;
33881 +               goto ERROR4;
33882 +       }
33883 +       data->sysctl_id = i;
33884 +
33885 +       /* Initialize the VIA686A chip */
33886 +       via686a_init_client(new_client);
33887 +       return 0;
33888 +
33889 +      ERROR4:
33890 +       i2c_detach_client(new_client);
33891 +      ERROR3:
33892 +       release_region(address, VIA686A_EXTENT);
33893 +       kfree(data);
33894 +      ERROR0:
33895 +       return err;
33896 +}
33897 +
33898 +static int via686a_detach_client(struct i2c_client *client)
33899 +{
33900 +       int err;
33901 +
33902 +       i2c_deregister_entry(((struct via686a_data *) 
33903 +                                 (client->data))->sysctl_id);
33904 +
33905 +       if ((err = i2c_detach_client(client))) {
33906 +               printk
33907 +               ("via686a.o: Client deregistration failed, client not detached.\n");
33908 +               return err;
33909 +       }
33910 +
33911 +       release_region(client->addr, VIA686A_EXTENT);
33912 +       kfree(client->data);
33913 +
33914 +       return 0;
33915 +}
33916 +
33917 +/* Called when we have found a new VIA686A. */
33918 +static void via686a_init_client(struct i2c_client *client)
33919 +{
33920 +       u8 reg;
33921 +
33922 +       /* Start monitoring */
33923 +       reg = via686a_read_value(client, VIA686A_REG_CONFIG);
33924 +       via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
33925 +
33926 +       /* Configure temp interrupt mode for continuous-interrupt operation */
33927 +       via686a_write_value(client, VIA686A_REG_TEMP_MODE, 
33928 +                           via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
33929 +                           !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
33930 +}
33931 +
33932 +static void via686a_update_client(struct i2c_client *client)
33933 +{
33934 +       struct via686a_data *data = client->data;
33935 +       int i;
33936 +
33937 +       down(&data->update_lock);
33938 +
33939 +       if (time_after(jiffies - data->last_updated, HZ + HZ / 2) ||
33940 +           time_before(jiffies, data->last_updated) || !data->valid) {
33941 +
33942 +               for (i = 0; i <= 4; i++) {
33943 +                       data->in[i] =
33944 +                           via686a_read_value(client, VIA686A_REG_IN(i));
33945 +                       data->in_min[i] = via686a_read_value(client,
33946 +                                                            VIA686A_REG_IN_MIN
33947 +                                                            (i));
33948 +                       data->in_max[i] =
33949 +                           via686a_read_value(client, VIA686A_REG_IN_MAX(i));
33950 +               }
33951 +               for (i = 1; i <= 2; i++) {
33952 +                       data->fan[i - 1] =
33953 +                           via686a_read_value(client, VIA686A_REG_FAN(i));
33954 +                       data->fan_min[i - 1] = via686a_read_value(client,
33955 +                                                    VIA686A_REG_FAN_MIN(i));
33956 +               }
33957 +               for (i = 1; i <= 3; i++) {
33958 +                       data->temp[i - 1] = via686a_read_value(client,
33959 +                                                VIA686A_REG_TEMP(i)) << 2;
33960 +                       data->temp_over[i - 1] =
33961 +                           via686a_read_value(client,
33962 +                                              VIA686A_REG_TEMP_OVER(i));
33963 +                       data->temp_hyst[i - 1] =
33964 +                           via686a_read_value(client,
33965 +                                              VIA686A_REG_TEMP_HYST(i));
33966 +               }
33967 +               /* add in lower 2 bits 
33968 +                  temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
33969 +                  temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
33970 +                  temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
33971 +                */
33972 +               data->temp[0] |= (via686a_read_value(client,
33973 +                                                    VIA686A_REG_TEMP_LOW1)
33974 +                                 & 0xc0) >> 6;
33975 +               data->temp[1] |=
33976 +                   (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
33977 +                    0x30) >> 4;
33978 +               data->temp[2] |=
33979 +                   (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
33980 +                    0xc0) >> 6;
33981 +
33982 +               i = via686a_read_value(client, VIA686A_REG_FANDIV);
33983 +               data->fan_div[0] = (i >> 4) & 0x03;
33984 +               data->fan_div[1] = i >> 6;
33985 +               data->alarms =
33986 +                   via686a_read_value(client,
33987 +                                      VIA686A_REG_ALARM1) |
33988 +                   (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);
33989 +               data->last_updated = jiffies;
33990 +               data->valid = 1;
33991 +       }
33992 +
33993 +       up(&data->update_lock);
33994 +}
33995 +
33996 +
33997 +/* The next few functions are the call-back functions of the /proc/sys and
33998 +   sysctl files. Which function is used is defined in the ctl_table in
33999 +   the extra1 field.
34000 +   Each function must return the magnitude (power of 10 to divide the date
34001 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
34002 +   put a maximum of *nrels elements in results reflecting the data of this
34003 +   file, and set *nrels to the number it actually put in it, if operation==
34004 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
34005 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
34006 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
34007 +   large enough (by checking the incoming value of *nrels). This is not very
34008 +   good practice, but as long as you put less than about 5 values in results,
34009 +   you can assume it is large enough. */
34010 +static void via686a_in(struct i2c_client *client, int operation, int ctl_name,
34011 +               int *nrels_mag, long *results)
34012 +{
34013 +       struct via686a_data *data = client->data;
34014 +       int nr = ctl_name - VIA686A_SYSCTL_IN0;
34015 +
34016 +       if (operation == SENSORS_PROC_REAL_INFO)
34017 +               *nrels_mag = 2;
34018 +       else if (operation == SENSORS_PROC_REAL_READ) {
34019 +               via686a_update_client(client);
34020 +               results[0] = IN_FROM_REG(data->in_min[nr], nr);
34021 +               results[1] = IN_FROM_REG(data->in_max[nr], nr);
34022 +               results[2] = IN_FROM_REG(data->in[nr], nr);
34023 +               *nrels_mag = 3;
34024 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34025 +               if (*nrels_mag >= 1) {
34026 +                       data->in_min[nr] = IN_TO_REG(results[0], nr);
34027 +                       via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
34028 +                                           data->in_min[nr]);
34029 +               }
34030 +               if (*nrels_mag >= 2) {
34031 +                       data->in_max[nr] = IN_TO_REG(results[1], nr);
34032 +                       via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
34033 +                                           data->in_max[nr]);
34034 +               }
34035 +       }
34036 +}
34037 +
34038 +void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
34039 +                int *nrels_mag, long *results)
34040 +{
34041 +       struct via686a_data *data = client->data;
34042 +       int nr = ctl_name - VIA686A_SYSCTL_FAN1 + 1;
34043 +
34044 +       if (operation == SENSORS_PROC_REAL_INFO)
34045 +               *nrels_mag = 0;
34046 +       else if (operation == SENSORS_PROC_REAL_READ) {
34047 +               via686a_update_client(client);
34048 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
34049 +                                         DIV_FROM_REG(data->fan_div
34050 +                                                      [nr - 1]));
34051 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
34052 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
34053 +               *nrels_mag = 2;
34054 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34055 +               if (*nrels_mag >= 1) {
34056 +                       data->fan_min[nr - 1] = FAN_TO_REG(results[0], 
34057 +                                                          DIV_FROM_REG(data->
34058 +                                                             fan_div[nr -1]));
34059 +                       via686a_write_value(client,
34060 +                                           VIA686A_REG_FAN_MIN(nr),
34061 +                                           data->fan_min[nr - 1]);
34062 +               }
34063 +       }
34064 +}
34065 +
34066 +void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
34067 +                 int *nrels_mag, long *results)
34068 +{
34069 +       struct via686a_data *data = client->data;
34070 +       int nr = ctl_name - VIA686A_SYSCTL_TEMP;
34071 +
34072 +       if (operation == SENSORS_PROC_REAL_INFO)
34073 +               *nrels_mag = 1;
34074 +       else if (operation == SENSORS_PROC_REAL_READ) {
34075 +               via686a_update_client(client);
34076 +               results[0] = TEMP_FROM_REG(data->temp_over[nr]);
34077 +               results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
34078 +               results[2] = TEMP_FROM_REG10(data->temp[nr]);
34079 +               *nrels_mag = 3;
34080 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34081 +               if (*nrels_mag >= 1) {
34082 +                       data->temp_over[nr] = TEMP_TO_REG(results[0]);
34083 +                       via686a_write_value(client,
34084 +                                           VIA686A_REG_TEMP_OVER(nr + 1),
34085 +                                           data->temp_over[nr]);
34086 +               }
34087 +               if (*nrels_mag >= 2) {
34088 +                       data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
34089 +                       via686a_write_value(client,
34090 +                                           VIA686A_REG_TEMP_HYST(nr + 1),
34091 +                                           data->temp_hyst[nr]);
34092 +               }
34093 +       }
34094 +}
34095 +
34096 +void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
34097 +                   int *nrels_mag, long *results)
34098 +{
34099 +       struct via686a_data *data = client->data;
34100 +       if (operation == SENSORS_PROC_REAL_INFO)
34101 +               *nrels_mag = 0;
34102 +       else if (operation == SENSORS_PROC_REAL_READ) {
34103 +               via686a_update_client(client);
34104 +               results[0] = ALARMS_FROM_REG(data->alarms);
34105 +               *nrels_mag = 1;
34106 +       }
34107 +}
34108 +
34109 +void via686a_fan_div(struct i2c_client *client, int operation,
34110 +                    int ctl_name, int *nrels_mag, long *results)
34111 +{
34112 +       struct via686a_data *data = client->data;
34113 +       int old;
34114 +
34115 +       if (operation == SENSORS_PROC_REAL_INFO)
34116 +               *nrels_mag = 0;
34117 +       else if (operation == SENSORS_PROC_REAL_READ) {
34118 +               via686a_update_client(client);
34119 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
34120 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
34121 +               *nrels_mag = 2;
34122 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34123 +               old = via686a_read_value(client, VIA686A_REG_FANDIV);
34124 +               if (*nrels_mag >= 2) {
34125 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
34126 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
34127 +               }
34128 +               if (*nrels_mag >= 1) {
34129 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
34130 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
34131 +                       via686a_write_value(client, VIA686A_REG_FANDIV,
34132 +                                           old);
34133 +               }
34134 +       }
34135 +}
34136 +
34137 +
34138 +static struct pci_device_id via686a_pci_ids[] __devinitdata = {
34139 +       {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
34140 +       { 0, }
34141 +};
34142 +
34143 +static int __devinit via686a_pci_probe(struct pci_dev *dev,
34144 +                                      const struct pci_device_id *id)
34145 +{
34146 +       u16 val;
34147 +       int addr = 0;
34148 +
34149 +       if (PCIBIOS_SUCCESSFUL !=
34150 +           pci_read_config_word(dev, VIA686A_BASE_REG, &val))
34151 +               return -ENODEV;
34152 +
34153 +       addr = val & ~(VIA686A_EXTENT - 1);
34154 +       if (addr == 0 && force_addr == 0) {
34155 +               printk("via686a.o: base address not set - upgrade BIOS or use force_addr=0xaddr\n");
34156 +               return -ENODEV;
34157 +       }
34158 +       if (force_addr)
34159 +               addr = force_addr;      /* so detect will get called */
34160 +
34161 +       if (!addr) {
34162 +               printk("via686a.o: No Via 686A sensors found.\n");
34163 +               return -ENODEV;
34164 +       }
34165 +       normal_isa[0] = addr;
34166 +       s_bridge = dev;
34167 +       return i2c_add_driver(&via686a_driver);
34168 +}
34169 +
34170 +static void __devexit via686a_pci_remove(struct pci_dev *dev)
34171 +{
34172 +       i2c_del_driver(&via686a_driver);
34173 +}
34174 +
34175 +static struct pci_driver via686a_pci_driver = {
34176 +       .name           = "via686a",
34177 +       .id_table       = via686a_pci_ids,
34178 +       .probe          = via686a_pci_probe,
34179 +       .remove         = __devexit_p(via686a_pci_remove),
34180 +};
34181 +
34182 +static int __init sm_via686a_init(void)
34183 +{
34184 +       printk("via686a.o version %s (%s)\n", LM_VERSION, LM_DATE);
34185 +       return pci_module_init(&via686a_pci_driver);
34186 +}
34187 +
34188 +static void __exit sm_via686a_exit(void)
34189 +{
34190 +       pci_unregister_driver(&via686a_pci_driver);
34191 +}
34192 +
34193 +MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
34194 +              "Mark Studebaker <mdsxyz123@yahoo.com> "
34195 +             "and Bob Dougherty <bobd@stanford.edu>");
34196 +MODULE_DESCRIPTION("VIA 686A Sensor device");
34197 +MODULE_LICENSE("GPL");
34198 +
34199 +module_init(sm_via686a_init);
34200 +module_exit(sm_via686a_exit);
34201 --- linux-old/drivers/sensors/vt1211.c  Thu Jan  1 00:00:00 1970
34202 +++ linux/drivers/sensors/vt1211.c      Mon Dec 13 20:18:53 2004
34203 @@ -0,0 +1,823 @@
34204 +/*
34205 +    vt1211.c - Part of lm_sensors, Linux kernel modules
34206 +                for hardware monitoring
34207 +                
34208 +    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
34209 +
34210 +    This program is free software; you can redistribute it and/or modify
34211 +    it under the terms of the GNU General Public License as published by
34212 +    the Free Software Foundation; either version 2 of the License, or
34213 +    (at your option) any later version.
34214 +
34215 +    This program is distributed in the hope that it will be useful,
34216 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
34217 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34218 +    GNU General Public License for more details.
34219 +
34220 +    You should have received a copy of the GNU General Public License
34221 +    along with this program; if not, write to the Free Software
34222 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34223 +*/
34224 +
34225 +/* Supports VIA VT1211 Super I/O sensors via ISA (LPC) accesses only. */
34226 +
34227 +#include <linux/module.h>
34228 +#include <linux/slab.h>
34229 +#include <linux/ioport.h>
34230 +#include <linux/i2c.h>
34231 +#include <linux/i2c-proc.h>
34232 +#include <linux/init.h>
34233 +#include <asm/io.h>
34234 +#define LM_DATE "20041007"
34235 +#define LM_VERSION "2.8.8"
34236 +#include <linux/sensors_vid.h>
34237 +
34238 +static int force_addr = 0;
34239 +MODULE_PARM(force_addr, "i");
34240 +MODULE_PARM_DESC(force_addr,
34241 +                "Initialize the base address of the sensors");
34242 +
34243 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
34244 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
34245 +static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
34246 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
34247 +
34248 +SENSORS_INSMOD_1(vt1211);
34249 +
34250 +/* modified from kernel/include/traps.c */
34251 +#define        REG     0x2e    /* The register to read/write */
34252 +#define        DEV     0x07    /* Register: Logical device select */
34253 +#define        VAL     0x2f    /* The value to read/write */
34254 +#define PME    0x0b    /* The device with the hardware monitor */
34255 +#define        DEVID   0x20    /* Register: Device ID */
34256 +
34257 +static inline void
34258 +superio_outb(int reg, int val)
34259 +{
34260 +       outb(reg, REG);
34261 +       outb(val, VAL);
34262 +}
34263 +
34264 +static inline int
34265 +superio_inb(int reg)
34266 +{
34267 +       outb(reg, REG);
34268 +       return inb(VAL);
34269 +}
34270 +
34271 +static inline void
34272 +superio_select(void)
34273 +{
34274 +       outb(DEV, REG);
34275 +       outb(PME, VAL);
34276 +}
34277 +
34278 +static inline void
34279 +superio_enter(void)
34280 +{
34281 +       outb(0x87, REG);
34282 +       outb(0x87, REG);
34283 +}
34284 +
34285 +static inline void
34286 +superio_exit(void)
34287 +{
34288 +       outb(0xAA, REG);
34289 +}
34290 +
34291 +#define VT1211_DEVID 0x3c
34292 +#define VT1211_ACT_REG 0x30
34293 +#define VT1211_BASE_REG 0x60
34294 +
34295 +#define VT1211_EXTENT 0x80
34296 +
34297 +/* pwm numbered 1-2 */
34298 +#define VT1211_REG_PWM(nr) (0x5f + (nr))
34299 +#define VT1211_REG_PWM_CTL 0x51
34300 +
34301 +/* The VT1211 registers */
34302 +/* We define the sensors as follows. Somewhat convoluted to minimize
34303 +   changes from via686a.
34304 +       Sensor          Voltage Mode    Temp Mode
34305 +       --------        ------------    ---------
34306 +       Reading 1                       temp3
34307 +       Reading 3                       temp1   not in vt1211
34308 +       UCH1/Reading2   in0             temp2
34309 +       UCH2            in1             temp4
34310 +       UCH3            in2             temp5
34311 +       UCH4            in3             temp6
34312 +       UCH5            in4             temp7
34313 +       3.3V            in5
34314 +       -12V            in6                     not in vt1211
34315 +*/
34316 +
34317 +/* ins numbered 0-6 */
34318 +#define VT1211_REG_IN_MAX(nr) ((nr)==0 ? 0x3d : 0x29 + ((nr) * 2))
34319 +#define VT1211_REG_IN_MIN(nr) ((nr)==0 ? 0x3e : 0x2a + ((nr) * 2))
34320 +#define VT1211_REG_IN(nr)     (0x21 + (nr))
34321 +
34322 +/* fans numbered 1-2 */
34323 +#define VT1211_REG_FAN_MIN(nr) (0x3a + (nr))
34324 +#define VT1211_REG_FAN(nr)     (0x28 + (nr))
34325 +
34326 +static const u8 regtemp[] = { 0x20, 0x21, 0x1f, 0x22, 0x23, 0x24, 0x25 };
34327 +static const u8 regover[] = { 0x39, 0x3d, 0x1d, 0x2b, 0x2d, 0x2f, 0x31 };
34328 +static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e, 0x2c, 0x2e, 0x30, 0x32 };
34329 +
34330 +/* temps numbered 1-7 */
34331 +#define VT1211_REG_TEMP(nr)            (regtemp[(nr) - 1])
34332 +#define VT1211_REG_TEMP_OVER(nr)       (regover[(nr) - 1])
34333 +#define VT1211_REG_TEMP_HYST(nr)       (reghyst[(nr) - 1])
34334 +#define VT1211_REG_TEMP_LOW3   0x4b    /* bits 7-6 */
34335 +#define VT1211_REG_TEMP_LOW2   0x49    /* bits 5-4 */
34336 +#define VT1211_REG_TEMP_LOW47  0x4d
34337 +
34338 +#define VT1211_REG_CONFIG 0x40
34339 +#define VT1211_REG_ALARM1 0x41
34340 +#define VT1211_REG_ALARM2 0x42
34341 +#define VT1211_REG_VID    0x45
34342 +#define VT1211_REG_FANDIV 0x47
34343 +#define VT1211_REG_UCH_CONFIG 0x4a
34344 +#define VT1211_REG_TEMP1_CONFIG 0x4b
34345 +#define VT1211_REG_TEMP2_CONFIG 0x4c
34346 +
34347 +/* temps 1-7; voltages 0-6 */
34348 +#define ISTEMP(i, ch_config) ((i) == 1 ? 1 : \
34349 +                             (i) == 3 ? 1 : \
34350 +                             (i) == 2 ? ((ch_config) >> 1) & 0x01 : \
34351 +                                        ((ch_config) >> ((i)-1)) & 0x01)
34352 +#define ISVOLT(i, ch_config) ((i) > 4 ? 1 : !(((ch_config) >> ((i)+2)) & 0x01))
34353 +
34354 +#define DIV_FROM_REG(val) (1 << (val))
34355 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
34356 +#define PWM_FROM_REG(val) (val)
34357 +#define PWM_TO_REG(val) SENSORS_LIMIT((val), 0, 255)
34358 +
34359 +#define TEMP_FROM_REG(val) ((val)*10)
34360 +#define TEMP_FROM_REG10(val) (((val)*10)/4)
34361 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
34362 +                                                 ((val)+5)/10),0,255))
34363 +#define IN_FROM_REG(val) /*(((val)*10+5)/10)*/ (val)
34364 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 5)/10),0,255))
34365 +
34366 +
34367 +/********* FAN RPM CONVERSIONS ********/
34368 +/* But this chip saturates back at 0, not at 255 like all the other chips.
34369 +   So, 0 means 0 RPM */
34370 +static inline u8 FAN_TO_REG(long rpm, int div)
34371 +{
34372 +       if (rpm == 0)
34373 +               return 0;
34374 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
34375 +       return SENSORS_LIMIT((1310720 + rpm * div / 2) / (rpm * div), 1, 255);
34376 +}
34377 +
34378 +#define MIN_TO_REG(a,b) FAN_TO_REG(a,b)
34379 +#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1310720/((val)*(div)))
34380 +
34381 +struct vt1211_data {
34382 +       struct i2c_client client;
34383 +       struct semaphore lock;
34384 +       int sysctl_id;
34385 +
34386 +       struct semaphore update_lock;
34387 +       char valid;             /* !=0 if following fields are valid */
34388 +       unsigned long last_updated;     /* In jiffies */
34389 +
34390 +       u8 in[7];               /* Register value */
34391 +       u8 in_max[7];           /* Register value */
34392 +       u8 in_min[7];           /* Register value */
34393 +       u16 temp[7];            /* Register value 10 bit */
34394 +       u8 temp_over[7];        /* Register value */
34395 +       u8 temp_hyst[7];        /* Register value */
34396 +       u8 fan[2];              /* Register value */
34397 +       u8 fan_min[2];          /* Register value */
34398 +       u8 fan_div[2];          /* Register encoding, shifted right */
34399 +       u16 alarms;             /* Register encoding */
34400 +       u8 pwm[2];              /* Register value */
34401 +       u8 pwm_ctl;             /* Register value */
34402 +       u8 vid;                 /* Register encoding */
34403 +       u8 vrm;
34404 +       u8 uch_config;
34405 +};
34406 +
34407 +static int vt1211_attach_adapter(struct i2c_adapter *adapter);
34408 +static int vt1211_detect(struct i2c_adapter *adapter, int address,
34409 +                         unsigned short flags, int kind);
34410 +static int vt1211_detach_client(struct i2c_client *client);
34411 +
34412 +static inline int vt_rdval(struct i2c_client *client, u8 register);
34413 +static inline void vt1211_write_value(struct i2c_client *client, u8 register,
34414 +                              u8 value);
34415 +static void vt1211_update_client(struct i2c_client *client);
34416 +static void vt1211_init_client(struct i2c_client *client);
34417 +static int vt1211_find(int *address);
34418 +
34419 +
34420 +static void vt1211_fan(struct i2c_client *client, int operation,
34421 +                       int ctl_name, int *nrels_mag, long *results);
34422 +static void vt1211_alarms(struct i2c_client *client, int operation,
34423 +                          int ctl_name, int *nrels_mag, long *results);
34424 +static void vt1211_fan_div(struct i2c_client *client, int operation,
34425 +                           int ctl_name, int *nrels_mag, long *results);
34426 +static void vt1211_in(struct i2c_client *client, int operation,
34427 +                       int ctl_name, int *nrels_mag, long *results);
34428 +static void vt1211_pwm(struct i2c_client *client, int operation,
34429 +                       int ctl_name, int *nrels_mag, long *results);
34430 +static void vt1211_vid(struct i2c_client *client, int operation,
34431 +                       int ctl_name, int *nrels_mag, long *results);
34432 +static void vt1211_vrm(struct i2c_client *client, int operation,
34433 +                       int ctl_name, int *nrels_mag, long *results);
34434 +static void vt1211_uch(struct i2c_client *client, int operation,
34435 +                       int ctl_name, int *nrels_mag, long *results);
34436 +static void vt1211_temp(struct i2c_client *client, int operation,
34437 +                       int ctl_name, int *nrels_mag, long *results);
34438 +
34439 +static int vt1211_id = 0;
34440 +
34441 +static struct i2c_driver vt1211_driver = {
34442 +       .owner          = THIS_MODULE,
34443 +       .name           = "VT1211 sensors driver",
34444 +       .id             = I2C_DRIVERID_VT1211,
34445 +       .flags          = I2C_DF_NOTIFY,
34446 +       .attach_adapter = vt1211_attach_adapter,
34447 +       .detach_client  = vt1211_detach_client,
34448 +};
34449 +
34450 +/* -- SENSORS SYSCTL START -- */
34451 +#define VT1211_SYSCTL_IN0 1000
34452 +#define VT1211_SYSCTL_IN1 1001
34453 +#define VT1211_SYSCTL_IN2 1002
34454 +#define VT1211_SYSCTL_IN3 1003
34455 +#define VT1211_SYSCTL_IN4 1004
34456 +#define VT1211_SYSCTL_IN5 1005
34457 +#define VT1211_SYSCTL_IN6 1006
34458 +#define VT1211_SYSCTL_FAN1 1101
34459 +#define VT1211_SYSCTL_FAN2 1102
34460 +#define VT1211_SYSCTL_TEMP 1200
34461 +#define VT1211_SYSCTL_TEMP2 1201
34462 +#define VT1211_SYSCTL_TEMP3 1202
34463 +#define VT1211_SYSCTL_TEMP4 1203
34464 +#define VT1211_SYSCTL_TEMP5 1204
34465 +#define VT1211_SYSCTL_TEMP6 1205
34466 +#define VT1211_SYSCTL_TEMP7 1206
34467 +#define VT1211_SYSCTL_VID      1300
34468 +#define VT1211_SYSCTL_PWM1     1401
34469 +#define VT1211_SYSCTL_PWM2     1402
34470 +#define VT1211_SYSCTL_VRM      1600
34471 +#define VT1211_SYSCTL_UCH      1700
34472 +#define VT1211_SYSCTL_FAN_DIV 2000
34473 +#define VT1211_SYSCTL_ALARMS 2001
34474 +
34475 +#define VT1211_ALARM_IN1 0x01
34476 +#define VT1211_ALARM_IN2 0x02
34477 +#define VT1211_ALARM_IN5 0x04
34478 +#define VT1211_ALARM_IN3 0x08
34479 +#define VT1211_ALARM_TEMP 0x10
34480 +#define VT1211_ALARM_FAN1 0x40
34481 +#define VT1211_ALARM_FAN2 0x80
34482 +#define VT1211_ALARM_IN4 0x100
34483 +#define VT1211_ALARM_IN6 0x200
34484 +#define VT1211_ALARM_TEMP2 0x800
34485 +#define VT1211_ALARM_CHAS 0x1000
34486 +#define VT1211_ALARM_TEMP3 0x8000
34487 +/* duplicates */
34488 +#define VT1211_ALARM_IN0 VT1211_ALARM_TEMP
34489 +#define VT1211_ALARM_TEMP4 VT1211_ALARM_IN1
34490 +#define VT1211_ALARM_TEMP5 VT1211_ALARM_IN2
34491 +#define VT1211_ALARM_TEMP6 VT1211_ALARM_IN3
34492 +#define VT1211_ALARM_TEMP7 VT1211_ALARM_IN4
34493 +
34494 +/* -- SENSORS SYSCTL END -- */
34495 +
34496 +static ctl_table vt1211_dir_table_template[] = {
34497 +       {VT1211_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
34498 +        &i2c_sysctl_real, NULL, &vt1211_in},
34499 +       {VT1211_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
34500 +        &i2c_sysctl_real, NULL, &vt1211_in},
34501 +       {VT1211_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
34502 +        &i2c_sysctl_real, NULL, &vt1211_in},
34503 +       {VT1211_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
34504 +        &i2c_sysctl_real, NULL, &vt1211_in},
34505 +       {VT1211_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
34506 +        &i2c_sysctl_real, NULL, &vt1211_in},
34507 +       {VT1211_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
34508 +        &i2c_sysctl_real, NULL, &vt1211_in},
34509 +/*
34510 +    datasheet says these are reserved
34511 +       {VT1211_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
34512 +        &i2c_sysctl_real, NULL, &vt1211_in},
34513 +       {VT1211_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
34514 +        &i2c_sysctl_real, NULL, &vt1211_temp},
34515 +*/
34516 +       {VT1211_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
34517 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
34518 +       {VT1211_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
34519 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
34520 +       {VT1211_SYSCTL_TEMP4, "temp4", NULL, 0, 0644, NULL,
34521 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
34522 +       {VT1211_SYSCTL_TEMP5, "temp5", NULL, 0, 0644, NULL,
34523 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
34524 +       {VT1211_SYSCTL_TEMP6, "temp6", NULL, 0, 0644, NULL,
34525 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
34526 +       {VT1211_SYSCTL_TEMP7, "temp7", NULL, 0, 0644, NULL,
34527 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt1211_temp},
34528 +       {VT1211_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
34529 +        &i2c_sysctl_real, NULL, &vt1211_fan},
34530 +       {VT1211_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
34531 +        &i2c_sysctl_real, NULL, &vt1211_fan},
34532 +       {VT1211_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
34533 +        &i2c_sysctl_real, NULL, &vt1211_fan_div},
34534 +       {VT1211_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
34535 +        &i2c_sysctl_real, NULL, &vt1211_alarms},
34536 +       {VT1211_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
34537 +        &i2c_sysctl_real, NULL, &vt1211_pwm},
34538 +       {VT1211_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
34539 +        &i2c_sysctl_real, NULL, &vt1211_pwm},
34540 +       {VT1211_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
34541 +        &i2c_sysctl_real, NULL, &vt1211_vid},
34542 +       {VT1211_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
34543 +        &i2c_sysctl_real, NULL, &vt1211_vrm},
34544 +       {VT1211_SYSCTL_UCH, "uch_config", NULL, 0, 0644, NULL, &i2c_proc_real,
34545 +        &i2c_sysctl_real, NULL, &vt1211_uch},
34546 +       {0}
34547 +};
34548 +
34549 +static int vt1211_attach_adapter(struct i2c_adapter *adapter)
34550 +{
34551 +       return i2c_detect(adapter, &addr_data, vt1211_detect);
34552 +}
34553 +
34554 +static int vt1211_find(int *address)
34555 +{
34556 +       u16 val;
34557 +
34558 +       superio_enter();
34559 +       val= superio_inb(DEVID);
34560 +       if(VT1211_DEVID != val) {
34561 +               superio_exit();
34562 +               return -ENODEV;
34563 +       }
34564 +
34565 +       superio_select();
34566 +       val = (superio_inb(VT1211_BASE_REG) << 8) |
34567 +              superio_inb(VT1211_BASE_REG + 1);
34568 +       *address = val & ~(VT1211_EXTENT - 1);
34569 +       if (*address == 0 && force_addr == 0) {
34570 +               printk("vt1211.o: base address not set - use force_addr=0xaddr\n");
34571 +               superio_exit();
34572 +               return -ENODEV;
34573 +       }
34574 +       if (force_addr)
34575 +               *address = force_addr;  /* so detect will get called */
34576 +
34577 +       superio_exit();
34578 +       return 0;
34579 +}
34580 +
34581 +int vt1211_detect(struct i2c_adapter *adapter, int address,
34582 +                  unsigned short flags, int kind)
34583 +{
34584 +       int i;
34585 +       struct i2c_client *new_client;
34586 +       struct vt1211_data *data;
34587 +       int err = 0;
34588 +       u8 val;
34589 +       const char *type_name = "vt1211";
34590 +       const char *client_name = "VT1211 chip";
34591 +
34592 +       if (!i2c_is_isa_adapter(adapter)) {
34593 +               return 0;
34594 +       }
34595 +
34596 +       if(force_addr)
34597 +               address = force_addr & ~(VT1211_EXTENT - 1);
34598 +       if (check_region(address, VT1211_EXTENT)) {
34599 +               printk("vt1211.o: region 0x%x already in use!\n", address);
34600 +               return -ENODEV;
34601 +       }
34602 +       if(force_addr) {
34603 +               printk("vt1211.o: forcing ISA address 0x%04X\n", address);
34604 +               superio_enter();
34605 +               superio_select();
34606 +               superio_outb(VT1211_BASE_REG, address >> 8);
34607 +               superio_outb(VT1211_BASE_REG+1, address & 0xff);
34608 +               superio_exit();
34609 +       }
34610 +
34611 +       superio_enter();
34612 +       superio_select();
34613 +       if((val = 0x01 & superio_inb(VT1211_ACT_REG)) == 0)
34614 +               superio_outb(VT1211_ACT_REG, 1);
34615 +       superio_exit();
34616 +
34617 +       if (!(data = kmalloc(sizeof(struct vt1211_data), GFP_KERNEL))) {
34618 +               return -ENOMEM;
34619 +       }
34620 +
34621 +       new_client = &data->client;
34622 +       new_client->addr = address;
34623 +       init_MUTEX(&data->lock);
34624 +       new_client->data = data;
34625 +       new_client->adapter = adapter;
34626 +       new_client->driver = &vt1211_driver;
34627 +       new_client->flags = 0;
34628 +
34629 +       request_region(address, VT1211_EXTENT, "vt1211-sensors");
34630 +       strcpy(new_client->name, client_name);
34631 +
34632 +       new_client->id = vt1211_id++;
34633 +       data->valid = 0;
34634 +       init_MUTEX(&data->update_lock);
34635 +
34636 +       if ((err = i2c_attach_client(new_client)))
34637 +               goto ERROR3;
34638 +
34639 +       if ((i = i2c_register_entry((struct i2c_client *) new_client,
34640 +                                       type_name,
34641 +                                       vt1211_dir_table_template)) < 0) {
34642 +               err = i;
34643 +               goto ERROR4;
34644 +       }
34645 +       data->sysctl_id = i;
34646 +
34647 +       vt1211_init_client(new_client);
34648 +       return 0;
34649 +
34650 +      ERROR4:
34651 +       i2c_detach_client(new_client);
34652 +      ERROR3:
34653 +       release_region(address, VT1211_EXTENT);
34654 +       kfree(data);
34655 +       return err;
34656 +}
34657 +
34658 +static int vt1211_detach_client(struct i2c_client *client)
34659 +{
34660 +       int err;
34661 +
34662 +       i2c_deregister_entry(((struct vt1211_data *) (client->data))->
34663 +                                sysctl_id);
34664 +
34665 +       if ((err = i2c_detach_client(client))) {
34666 +               printk
34667 +                   ("vt1211.o: Client deregistration failed, client not detached.\n");
34668 +               return err;
34669 +       }
34670 +
34671 +       release_region(client->addr, VT1211_EXTENT);
34672 +       kfree(client->data);
34673 +
34674 +       return 0;
34675 +}
34676 +
34677 +static inline int vt_rdval(struct i2c_client *client, u8 reg)
34678 +{
34679 +       return (inb_p(client->addr + reg));
34680 +}
34681 +
34682 +static inline void vt1211_write_value(struct i2c_client *client, u8 reg, u8 value)
34683 +{
34684 +       outb_p(value, client->addr + reg);
34685 +}
34686 +
34687 +static void vt1211_init_client(struct i2c_client *client)
34688 +{
34689 +       struct vt1211_data *data = client->data;
34690 +
34691 +       data->vrm = DEFAULT_VRM;
34692 +       /* set "default" interrupt mode for alarms, which isn't the default */
34693 +       vt1211_write_value(client, VT1211_REG_TEMP1_CONFIG, 0);
34694 +       vt1211_write_value(client, VT1211_REG_TEMP2_CONFIG, 0);
34695 +}
34696 +
34697 +static void vt1211_update_client(struct i2c_client *client)
34698 +{
34699 +       struct vt1211_data *data = client->data;
34700 +       int i, j;
34701 +
34702 +       down(&data->update_lock);
34703 +
34704 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
34705 +           (jiffies < data->last_updated) || !data->valid) {
34706 +               data->uch_config = vt_rdval(client, VT1211_REG_UCH_CONFIG);
34707 +               for (i = 0; i <= 5; i++) {
34708 +                       if(ISVOLT(i, data->uch_config)) {
34709 +                               data->in[i] = vt_rdval(client, VT1211_REG_IN(i));
34710 +                               data->in_min[i] = vt_rdval(client,
34711 +                                                       VT1211_REG_IN_MIN(i));
34712 +                               data->in_max[i] = vt_rdval(client,
34713 +                                                       VT1211_REG_IN_MAX(i));
34714 +                       } else {
34715 +                               data->in[i] = 0;
34716 +                               data->in_min[i] = 0;
34717 +                               data->in_max[i] = 0;
34718 +                       }
34719 +               }
34720 +               for (i = 1; i <= 2; i++) {
34721 +                       data->fan[i - 1] = vt_rdval(client, VT1211_REG_FAN(i));
34722 +                       data->fan_min[i - 1] = vt_rdval(client,
34723 +                                                    VT1211_REG_FAN_MIN(i));
34724 +               }
34725 +               for (i = 2; i <= 7; i++) {
34726 +                       if(ISTEMP(i, data->uch_config)) {
34727 +                               data->temp[i - 1] = vt_rdval(client,
34728 +                                                    VT1211_REG_TEMP(i)) << 2;
34729 +                               switch(i) {
34730 +                                       case 1:
34731 +                                               /* ? */
34732 +                                               j = 0;
34733 +                                               break;
34734 +                                       case 2:
34735 +                                               j = (vt_rdval(client,
34736 +                                                 VT1211_REG_TEMP_LOW2) &
34737 +                                                                   0x30) >> 4;
34738 +                                               break;
34739 +                                       case 3:
34740 +                                               j = (vt_rdval(client,
34741 +                                                 VT1211_REG_TEMP_LOW3) &
34742 +                                                                   0xc0) >> 6;
34743 +                                               break;
34744 +                                       case 4:
34745 +                                       case 5:
34746 +                                       case 6:
34747 +                                       case 7:
34748 +                                       default:
34749 +                                               j = (vt_rdval(client,
34750 +                                                 VT1211_REG_TEMP_LOW47) >>
34751 +                                                           ((i-4)*2)) & 0x03;  
34752 +                                               break;
34753 +       
34754 +                               }
34755 +                               data->temp[i - 1] |= j;
34756 +                               data->temp_over[i - 1] = vt_rdval(client,
34757 +                                                     VT1211_REG_TEMP_OVER(i));
34758 +                               data->temp_hyst[i - 1] = vt_rdval(client,
34759 +                                                     VT1211_REG_TEMP_HYST(i));
34760 +                       } else {
34761 +                               data->temp[i - 1] = 0;
34762 +                               data->temp_over[i - 1] = 0;
34763 +                               data->temp_hyst[i - 1] = 0;
34764 +                       }
34765 +               }
34766 +
34767 +               for (i = 1; i <= 2; i++) {
34768 +                       data->fan[i - 1] = vt_rdval(client, VT1211_REG_FAN(i));
34769 +                       data->fan_min[i - 1] = vt_rdval(client,
34770 +                                                       VT1211_REG_FAN_MIN(i));
34771 +                       data->pwm[i - 1] = vt_rdval(client, VT1211_REG_PWM(i));
34772 +               }
34773 +
34774 +               data->pwm_ctl = vt_rdval(client, VT1211_REG_PWM_CTL);
34775 +               i = vt_rdval(client, VT1211_REG_FANDIV);
34776 +               data->fan_div[0] = (i >> 4) & 0x03;
34777 +               data->fan_div[1] = i >> 6;
34778 +               data->alarms = vt_rdval(client, VT1211_REG_ALARM1) |
34779 +                                   (vt_rdval(client, VT1211_REG_ALARM2) << 8);
34780 +               data->vid= vt_rdval(client, VT1211_REG_VID) & 0x1f;
34781 +               data->last_updated = jiffies;
34782 +               data->valid = 1;
34783 +       }
34784 +
34785 +       up(&data->update_lock);
34786 +}
34787 +
34788 +
34789 +void vt1211_in(struct i2c_client *client, int operation, int ctl_name,
34790 +               int *nrels_mag, long *results)
34791 +{
34792 +       struct vt1211_data *data = client->data;
34793 +       int nr = ctl_name - VT1211_SYSCTL_IN0;
34794 +
34795 +       if (operation == SENSORS_PROC_REAL_INFO)
34796 +               *nrels_mag = 2;
34797 +       else if (operation == SENSORS_PROC_REAL_READ) {
34798 +               vt1211_update_client(client);
34799 +               results[0] = IN_FROM_REG(data->in_min[nr]);
34800 +               results[1] = IN_FROM_REG(data->in_max[nr]);
34801 +               results[2] = IN_FROM_REG(data->in[nr]);
34802 +               *nrels_mag = 3;
34803 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34804 +               if (*nrels_mag >= 1) {
34805 +                       data->in_min[nr] = IN_TO_REG(results[0]);
34806 +                       vt1211_write_value(client, VT1211_REG_IN_MIN(nr),
34807 +                                           data->in_min[nr]);
34808 +               }
34809 +               if (*nrels_mag >= 2) {
34810 +                       data->in_max[nr] = IN_TO_REG(results[1]);
34811 +                       vt1211_write_value(client, VT1211_REG_IN_MAX(nr),
34812 +                                           data->in_max[nr]);
34813 +               }
34814 +       }
34815 +}
34816 +
34817 +void vt1211_fan(struct i2c_client *client, int operation, int ctl_name,
34818 +                int *nrels_mag, long *results)
34819 +{
34820 +       struct vt1211_data *data = client->data;
34821 +       int nr = ctl_name - VT1211_SYSCTL_FAN1 + 1;
34822 +
34823 +       if (operation == SENSORS_PROC_REAL_INFO)
34824 +               *nrels_mag = 0;
34825 +       else if (operation == SENSORS_PROC_REAL_READ) {
34826 +               vt1211_update_client(client);
34827 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
34828 +                                         DIV_FROM_REG(data->fan_div
34829 +                                                      [nr - 1]));
34830 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
34831 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
34832 +               *nrels_mag = 2;
34833 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34834 +               if (*nrels_mag >= 1) {
34835 +                       data->fan_min[nr - 1] = MIN_TO_REG(results[0],
34836 +                                                          DIV_FROM_REG
34837 +                                                          (data->
34838 +                                                           fan_div[nr-1]));
34839 +                       vt1211_write_value(client, VT1211_REG_FAN_MIN(nr),
34840 +                                           data->fan_min[nr - 1]);
34841 +               }
34842 +       }
34843 +}
34844 +
34845 +
34846 +void vt1211_temp(struct i2c_client *client, int operation, int ctl_name,
34847 +                 int *nrels_mag, long *results)
34848 +{
34849 +       struct vt1211_data *data = client->data;
34850 +       int nr = ctl_name - VT1211_SYSCTL_TEMP;
34851 +
34852 +       if (operation == SENSORS_PROC_REAL_INFO)
34853 +               *nrels_mag = 1;
34854 +       else if (operation == SENSORS_PROC_REAL_READ) {
34855 +               vt1211_update_client(client);
34856 +               results[0] = TEMP_FROM_REG(data->temp_over[nr]);
34857 +               results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
34858 +               results[2] = TEMP_FROM_REG10(data->temp[nr]);
34859 +               *nrels_mag = 3;
34860 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34861 +               if (*nrels_mag >= 1) {
34862 +                       data->temp_over[nr] = TEMP_TO_REG(results[0]);
34863 +                       vt1211_write_value(client,
34864 +                                           VT1211_REG_TEMP_OVER(nr + 1),
34865 +                                           data->temp_over[nr]);
34866 +               }
34867 +               if (*nrels_mag >= 2) {
34868 +                       data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
34869 +                       vt1211_write_value(client,
34870 +                                           VT1211_REG_TEMP_HYST(nr + 1),
34871 +                                           data->temp_hyst[nr]);
34872 +               }
34873 +       }
34874 +}
34875 +
34876 +void vt1211_alarms(struct i2c_client *client, int operation, int ctl_name,
34877 +                   int *nrels_mag, long *results)
34878 +{
34879 +       struct vt1211_data *data = client->data;
34880 +       if (operation == SENSORS_PROC_REAL_INFO)
34881 +               *nrels_mag = 0;
34882 +       else if (operation == SENSORS_PROC_REAL_READ) {
34883 +               vt1211_update_client(client);
34884 +               results[0] = data->alarms;
34885 +               *nrels_mag = 1;
34886 +       }
34887 +}
34888 +
34889 +void vt1211_fan_div(struct i2c_client *client, int operation,
34890 +                    int ctl_name, int *nrels_mag, long *results)
34891 +{
34892 +       struct vt1211_data *data = client->data;
34893 +       int old;
34894 +
34895 +       if (operation == SENSORS_PROC_REAL_INFO)
34896 +               *nrels_mag = 0;
34897 +       else if (operation == SENSORS_PROC_REAL_READ) {
34898 +               vt1211_update_client(client);
34899 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
34900 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
34901 +               *nrels_mag = 2;
34902 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34903 +               old = vt_rdval(client, VT1211_REG_FANDIV);
34904 +               if (*nrels_mag >= 2) {
34905 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
34906 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
34907 +               }
34908 +               if (*nrels_mag >= 1) {
34909 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
34910 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
34911 +                       vt1211_write_value(client, VT1211_REG_FANDIV, old);
34912 +               }
34913 +       }
34914 +}
34915 +
34916 +void vt1211_pwm(struct i2c_client *client, int operation, int ctl_name,
34917 +                int *nrels_mag, long *results)
34918 +{
34919 +       struct vt1211_data *data = client->data;
34920 +       int nr = 1 + ctl_name - VT1211_SYSCTL_PWM1;
34921 +
34922 +       if (operation == SENSORS_PROC_REAL_INFO)
34923 +               *nrels_mag = 0;
34924 +       else if (operation == SENSORS_PROC_REAL_READ) {
34925 +               vt1211_update_client(client);
34926 +               results[0] = PWM_FROM_REG(data->pwm[nr - 1]);
34927 +               results[1] = (data->pwm_ctl >> (3 + (4 * (nr - 1)))) & 1;
34928 +               *nrels_mag = 2;
34929 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34930 +               if (*nrels_mag >= 1) {
34931 +                       data->pwm[nr - 1] = PWM_TO_REG(results[0]);
34932 +                       if (*nrels_mag >= 2) {
34933 +                               if(results[1]) {
34934 +                                       data->pwm_ctl |=
34935 +                                                 (0x08 << (4 * (nr - 1)));
34936 +                                       vt1211_write_value(client,
34937 +                                                          VT1211_REG_PWM_CTL, 
34938 +                                                          data->pwm_ctl);
34939 +                               } else {
34940 +                                       data->pwm_ctl &=
34941 +                                               ~ (0x08 << (4 * (nr - 1)));
34942 +                                       vt1211_write_value(client,
34943 +                                                          VT1211_REG_PWM_CTL, 
34944 +                                                          data->pwm_ctl);
34945 +                               }
34946 +                       }
34947 +                       vt1211_write_value(client, VT1211_REG_PWM(nr),
34948 +                                           data->pwm[nr - 1]);
34949 +               }
34950 +       }
34951 +}
34952 +
34953 +void vt1211_vid(struct i2c_client *client, int operation, int ctl_name,
34954 +                int *nrels_mag, long *results)
34955 +{
34956 +       struct vt1211_data *data = client->data;
34957 +       if (operation == SENSORS_PROC_REAL_INFO)
34958 +               *nrels_mag = 3;
34959 +       else if (operation == SENSORS_PROC_REAL_READ) {
34960 +               vt1211_update_client(client);
34961 +               results[0] = vid_from_reg(data->vid, data->vrm);
34962 +               *nrels_mag = 1;
34963 +       }
34964 +}
34965 +
34966 +void vt1211_vrm(struct i2c_client *client, int operation, int ctl_name,
34967 +                int *nrels_mag, long *results)
34968 +{
34969 +       struct vt1211_data *data = client->data;
34970 +       if (operation == SENSORS_PROC_REAL_INFO)
34971 +               *nrels_mag = 1;
34972 +       else if (operation == SENSORS_PROC_REAL_READ) {
34973 +               results[0] = data->vrm;
34974 +               *nrels_mag = 1;
34975 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34976 +               if (*nrels_mag >= 1)
34977 +                       data->vrm = results[0];
34978 +       }
34979 +}
34980 +
34981 +void vt1211_uch(struct i2c_client *client, int operation, int ctl_name,
34982 +                int *nrels_mag, long *results)
34983 +{
34984 +       struct vt1211_data *data = client->data;
34985 +       if (operation == SENSORS_PROC_REAL_INFO)
34986 +               *nrels_mag = 0;
34987 +       else if (operation == SENSORS_PROC_REAL_READ) {
34988 +               results[0] = data->uch_config & 0x7c;
34989 +               *nrels_mag = 1;
34990 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
34991 +               if (*nrels_mag >= 1) {
34992 +                       data->uch_config = (data->uch_config & 0x83)|(results[0] & 0x7c);
34993 +                       vt1211_write_value(client, VT1211_REG_UCH_CONFIG,
34994 +                                          data->uch_config);
34995 +               }
34996 +       }
34997 +}
34998 +
34999 +static int __init sm_vt1211_init(void)
35000 +{
35001 +       int addr;
35002 +
35003 +       printk("vt1211.o version %s (%s)\n", LM_VERSION, LM_DATE);
35004 +
35005 +       if (vt1211_find(&addr)) {
35006 +               printk("vt1211.o: VT1211 not detected, module not inserted.\n");
35007 +               return -ENODEV;
35008 +       }
35009 +       normal_isa[0] = addr;
35010 +
35011 +       return i2c_add_driver(&vt1211_driver);
35012 +}
35013 +
35014 +static void __exit sm_vt1211_exit(void)
35015 +{
35016 +       i2c_del_driver(&vt1211_driver);
35017 +}
35018 +
35019 +
35020 +
35021 +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
35022 +MODULE_DESCRIPTION("VT1211 sensors");
35023 +MODULE_LICENSE("GPL");
35024 +
35025 +module_init(sm_vt1211_init);
35026 +module_exit(sm_vt1211_exit);
35027 --- linux-old/drivers/sensors/vt8231.c  Thu Jan  1 00:00:00 1970
35028 +++ linux/drivers/sensors/vt8231.c      Mon Dec 13 20:18:53 2004
35029 @@ -0,0 +1,794 @@
35030 +/*
35031 +    vt8231.c - Part of lm_sensors, Linux kernel modules
35032 +                for hardware monitoring
35033 +                
35034 +    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
35035 +
35036 +    This program is free software; you can redistribute it and/or modify
35037 +    it under the terms of the GNU General Public License as published by
35038 +    the Free Software Foundation; either version 2 of the License, or
35039 +    (at your option) any later version.
35040 +
35041 +    This program is distributed in the hope that it will be useful,
35042 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
35043 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35044 +    GNU General Public License for more details.
35045 +
35046 +    You should have received a copy of the GNU General Public License
35047 +    along with this program; if not, write to the Free Software
35048 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35049 +*/
35050 +
35051 +/* Supports VIA VT8231 South Bridge embedded sensors */
35052 +
35053 +#include <linux/module.h>
35054 +#include <linux/slab.h>
35055 +#include <linux/ioport.h>
35056 +#include <linux/pci.h>
35057 +#include <linux/i2c.h>
35058 +#include <linux/i2c-proc.h>
35059 +#include <linux/init.h>
35060 +#include <asm/io.h>
35061 +#define LM_DATE "20041007"
35062 +#define LM_VERSION "2.8.8"
35063 +#include <linux/sensors_vid.h>
35064 +
35065 +
35066 +static int force_addr = 0;
35067 +MODULE_PARM(force_addr, "i");
35068 +MODULE_PARM_DESC(force_addr,
35069 +                "Initialize the base address of the sensors");
35070 +
35071 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
35072 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
35073 +static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
35074 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
35075 +
35076 +SENSORS_INSMOD_1(vt8231);
35077 +
35078 +#define VIA686A_EXTENT 0x80
35079 +#define VIA686A_BASE_REG 0x70
35080 +#define VIA686A_ENABLE_REG 0x74
35081 +
35082 +/* pwm numbered 1-2 */
35083 +#define VT8231_REG_PWM(nr) (0x5f + (nr))
35084 +#define VT8231_REG_PWM_CTL 0x51
35085 +
35086 +/* The VT8231 registers */
35087 +/* We define the sensors as follows. Somewhat convoluted to minimize
35088 +   changes from via686a.
35089 +       Sensor          Voltage Mode    Temp Mode
35090 +       --------        ------------    ---------
35091 +       Reading 1                       temp3
35092 +       Reading 3                       temp1   not in vt8231
35093 +       UCH1/Reading2   in0             temp2
35094 +       UCH2            in1             temp4
35095 +       UCH3            in2             temp5
35096 +       UCH4            in3             temp6
35097 +       UCH5            in4             temp7
35098 +       3.3V            in5
35099 +       -12V            in6                     not in vt8231
35100 +*/
35101 +
35102 +/* ins numbered 0-6 */
35103 +#define VT8231_REG_IN_MAX(nr) ((nr)==0 ? 0x3d : 0x29 + ((nr) * 2))
35104 +#define VT8231_REG_IN_MIN(nr) ((nr)==0 ? 0x3e : 0x2a + ((nr) * 2))
35105 +#define VT8231_REG_IN(nr)     (0x21 + (nr))
35106 +
35107 +/* fans numbered 1-2 */
35108 +#define VT8231_REG_FAN_MIN(nr) (0x3a + (nr))
35109 +#define VT8231_REG_FAN(nr)     (0x28 + (nr))
35110 +
35111 +static const u8 regtemp[] = { 0x20, 0x21, 0x1f, 0x22, 0x23, 0x24, 0x25 };
35112 +static const u8 regover[] = { 0x39, 0x3d, 0x1d, 0x2b, 0x2d, 0x2f, 0x31 };
35113 +static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e, 0x2c, 0x2e, 0x30, 0x32 };
35114 +
35115 +/* temps numbered 1-7 */
35116 +#define VT8231_REG_TEMP(nr)            (regtemp[(nr) - 1])
35117 +#define VT8231_REG_TEMP_OVER(nr)       (regover[(nr) - 1])
35118 +#define VT8231_REG_TEMP_HYST(nr)       (reghyst[(nr) - 1])
35119 +#define VT8231_REG_TEMP_LOW3   0x4b    /* bits 7-6 */
35120 +#define VT8231_REG_TEMP_LOW2   0x49    /* bits 5-4 */
35121 +#define VT8231_REG_TEMP_LOW47  0x4d
35122 +
35123 +#define VT8231_REG_CONFIG 0x40
35124 +#define VT8231_REG_ALARM1 0x41
35125 +#define VT8231_REG_ALARM2 0x42
35126 +#define VT8231_REG_VID    0x45
35127 +#define VT8231_REG_FANDIV 0x47
35128 +#define VT8231_REG_UCH_CONFIG 0x4a
35129 +#define VT8231_REG_TEMP1_CONFIG 0x4b
35130 +#define VT8231_REG_TEMP2_CONFIG 0x4c
35131 +
35132 +/* temps 1-7; voltages 0-6 */
35133 +#define ISTEMP(i, ch_config) ((i) == 1 ? 1 : \
35134 +                             (i) == 3 ? 1 : \
35135 +                             (i) == 2 ? ((ch_config) >> 1) & 0x01 : \
35136 +                                        ((ch_config) >> ((i)-1)) & 0x01)
35137 +#define ISVOLT(i, ch_config) ((i) > 4 ? 1 : !(((ch_config) >> ((i)+2)) & 0x01))
35138 +
35139 +#define DIV_FROM_REG(val) (1 << (val))
35140 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
35141 +#define PWM_FROM_REG(val) (val)
35142 +#define PWM_TO_REG(val) SENSORS_LIMIT((val), 0, 255)
35143 +
35144 +#define TEMP_FROM_REG(val) ((val)*10)
35145 +#define TEMP_FROM_REG10(val) (((val)*10)/4)
35146 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
35147 +                                                 ((val)+5)/10),0,255))
35148 +#define IN_FROM_REG(val) /*(((val)*10+5)/10)*/ (val)
35149 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 5)/10),0,255))
35150 +
35151 +
35152 +/********* FAN RPM CONVERSIONS ********/
35153 +/* But this chip saturates back at 0, not at 255 like all the other chips.
35154 +   So, 0 means 0 RPM */
35155 +static inline u8 FAN_TO_REG(long rpm, int div)
35156 +{
35157 +       if (rpm == 0)
35158 +               return 0;
35159 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
35160 +       return SENSORS_LIMIT((1310720 + rpm * div / 2) / (rpm * div), 1, 255);
35161 +}
35162 +
35163 +#define MIN_TO_REG(a,b) FAN_TO_REG(a,b)
35164 +#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1310720/((val)*(div)))
35165 +
35166 +struct vt8231_data {
35167 +       struct i2c_client client;
35168 +       struct semaphore lock;
35169 +       int sysctl_id;
35170 +
35171 +       struct semaphore update_lock;
35172 +       char valid;             /* !=0 if following fields are valid */
35173 +       unsigned long last_updated;     /* In jiffies */
35174 +
35175 +       u8 in[7];               /* Register value */
35176 +       u8 in_max[7];           /* Register value */
35177 +       u8 in_min[7];           /* Register value */
35178 +       u16 temp[7];            /* Register value 10 bit */
35179 +       u8 temp_over[7];        /* Register value */
35180 +       u8 temp_hyst[7];        /* Register value */
35181 +       u8 fan[2];              /* Register value */
35182 +       u8 fan_min[2];          /* Register value */
35183 +       u8 fan_div[2];          /* Register encoding, shifted right */
35184 +       u16 alarms;             /* Register encoding */
35185 +       u8 pwm[2];              /* Register value */
35186 +       u8 pwm_ctl;             /* Register value */
35187 +       u8 vid;                 /* Register encoding */
35188 +       u8 vrm;
35189 +       u8 uch_config;
35190 +};
35191 +
35192 +static int vt8231_attach_adapter(struct i2c_adapter *adapter);
35193 +static int vt8231_detect(struct i2c_adapter *adapter, int address,
35194 +                         unsigned short flags, int kind);
35195 +static int vt8231_detach_client(struct i2c_client *client);
35196 +
35197 +static inline int vt_rdval(struct i2c_client *client, u8 register);
35198 +static inline void vt8231_write_value(struct i2c_client *client, u8 register,
35199 +                              u8 value);
35200 +static void vt8231_update_client(struct i2c_client *client);
35201 +static void vt8231_init_client(struct i2c_client *client);
35202 +static int vt8231_find(int *address);
35203 +
35204 +
35205 +static void vt8231_fan(struct i2c_client *client, int operation,
35206 +                       int ctl_name, int *nrels_mag, long *results);
35207 +static void vt8231_alarms(struct i2c_client *client, int operation,
35208 +                          int ctl_name, int *nrels_mag, long *results);
35209 +static void vt8231_fan_div(struct i2c_client *client, int operation,
35210 +                           int ctl_name, int *nrels_mag, long *results);
35211 +static void vt8231_in(struct i2c_client *client, int operation,
35212 +                       int ctl_name, int *nrels_mag, long *results);
35213 +static void vt8231_pwm(struct i2c_client *client, int operation,
35214 +                       int ctl_name, int *nrels_mag, long *results);
35215 +static void vt8231_vid(struct i2c_client *client, int operation,
35216 +                       int ctl_name, int *nrels_mag, long *results);
35217 +static void vt8231_vrm(struct i2c_client *client, int operation,
35218 +                       int ctl_name, int *nrels_mag, long *results);
35219 +static void vt8231_uch(struct i2c_client *client, int operation,
35220 +                       int ctl_name, int *nrels_mag, long *results);
35221 +static void vt8231_temp(struct i2c_client *client, int operation,
35222 +                       int ctl_name, int *nrels_mag, long *results);
35223 +
35224 +static int vt8231_id = 0;
35225 +
35226 +static struct i2c_driver vt8231_driver = {
35227 +       .owner          = THIS_MODULE,
35228 +       .name           = "VT8231 sensors driver",
35229 +       .id             = I2C_DRIVERID_VT8231,
35230 +       .flags          = I2C_DF_NOTIFY,
35231 +       .attach_adapter = vt8231_attach_adapter,
35232 +       .detach_client  = vt8231_detach_client,
35233 +};
35234 +
35235 +/* -- SENSORS SYSCTL START -- */
35236 +#define VT8231_SYSCTL_IN0 1000
35237 +#define VT8231_SYSCTL_IN1 1001
35238 +#define VT8231_SYSCTL_IN2 1002
35239 +#define VT8231_SYSCTL_IN3 1003
35240 +#define VT8231_SYSCTL_IN4 1004
35241 +#define VT8231_SYSCTL_IN5 1005
35242 +#define VT8231_SYSCTL_IN6 1006
35243 +#define VT8231_SYSCTL_FAN1 1101
35244 +#define VT8231_SYSCTL_FAN2 1102
35245 +#define VT8231_SYSCTL_TEMP 1200
35246 +#define VT8231_SYSCTL_TEMP2 1201
35247 +#define VT8231_SYSCTL_TEMP3 1202
35248 +#define VT8231_SYSCTL_TEMP4 1203
35249 +#define VT8231_SYSCTL_TEMP5 1204
35250 +#define VT8231_SYSCTL_TEMP6 1205
35251 +#define VT8231_SYSCTL_TEMP7 1206
35252 +#define VT8231_SYSCTL_VID      1300
35253 +#define VT8231_SYSCTL_PWM1     1401
35254 +#define VT8231_SYSCTL_PWM2     1402
35255 +#define VT8231_SYSCTL_VRM      1600
35256 +#define VT8231_SYSCTL_UCH      1700
35257 +#define VT8231_SYSCTL_FAN_DIV 2000
35258 +#define VT8231_SYSCTL_ALARMS 2001
35259 +
35260 +#define VT8231_ALARM_IN1 0x01
35261 +#define VT8231_ALARM_IN2 0x02
35262 +#define VT8231_ALARM_IN5 0x04
35263 +#define VT8231_ALARM_IN3 0x08
35264 +#define VT8231_ALARM_TEMP 0x10
35265 +#define VT8231_ALARM_FAN1 0x40
35266 +#define VT8231_ALARM_FAN2 0x80
35267 +#define VT8231_ALARM_IN4 0x100
35268 +#define VT8231_ALARM_IN6 0x200
35269 +#define VT8231_ALARM_TEMP2 0x800
35270 +#define VT8231_ALARM_CHAS 0x1000
35271 +#define VT8231_ALARM_TEMP3 0x8000
35272 +/* duplicates */
35273 +#define VT8231_ALARM_IN0 VT8231_ALARM_TEMP
35274 +#define VT8231_ALARM_TEMP4 VT8231_ALARM_IN1
35275 +#define VT8231_ALARM_TEMP5 VT8231_ALARM_IN2
35276 +#define VT8231_ALARM_TEMP6 VT8231_ALARM_IN3
35277 +#define VT8231_ALARM_TEMP7 VT8231_ALARM_IN4
35278 +
35279 +/* -- SENSORS SYSCTL END -- */
35280 +
35281 +static ctl_table vt8231_dir_table_template[] = {
35282 +       {VT8231_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
35283 +        &i2c_sysctl_real, NULL, &vt8231_in},
35284 +       {VT8231_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
35285 +        &i2c_sysctl_real, NULL, &vt8231_in},
35286 +       {VT8231_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
35287 +        &i2c_sysctl_real, NULL, &vt8231_in},
35288 +       {VT8231_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
35289 +        &i2c_sysctl_real, NULL, &vt8231_in},
35290 +       {VT8231_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
35291 +        &i2c_sysctl_real, NULL, &vt8231_in},
35292 +       {VT8231_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
35293 +        &i2c_sysctl_real, NULL, &vt8231_in},
35294 +/*
35295 +    not in 8231
35296 +       {VT8231_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
35297 +        &i2c_sysctl_real, NULL, &vt8231_in},
35298 +       {VT8231_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
35299 +        &i2c_sysctl_real, NULL, &vt8231_temp},
35300 +*/
35301 +       {VT8231_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
35302 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt8231_temp},
35303 +       {VT8231_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
35304 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt8231_temp},
35305 +       {VT8231_SYSCTL_TEMP4, "temp4", NULL, 0, 0644, NULL,
35306 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt8231_temp},
35307 +       {VT8231_SYSCTL_TEMP5, "temp5", NULL, 0, 0644, NULL,
35308 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt8231_temp},
35309 +       {VT8231_SYSCTL_TEMP6, "temp6", NULL, 0, 0644, NULL,
35310 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt8231_temp},
35311 +       {VT8231_SYSCTL_TEMP7, "temp7", NULL, 0, 0644, NULL,
35312 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &vt8231_temp},
35313 +       {VT8231_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
35314 +        &i2c_sysctl_real, NULL, &vt8231_fan},
35315 +       {VT8231_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
35316 +        &i2c_sysctl_real, NULL, &vt8231_fan},
35317 +       {VT8231_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
35318 +        &i2c_sysctl_real, NULL, &vt8231_fan_div},
35319 +       {VT8231_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
35320 +        &i2c_sysctl_real, NULL, &vt8231_alarms},
35321 +       {VT8231_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
35322 +        &i2c_sysctl_real, NULL, &vt8231_pwm},
35323 +       {VT8231_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
35324 +        &i2c_sysctl_real, NULL, &vt8231_pwm},
35325 +       {VT8231_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
35326 +        &i2c_sysctl_real, NULL, &vt8231_vid},
35327 +       {VT8231_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
35328 +        &i2c_sysctl_real, NULL, &vt8231_vrm},
35329 +       {VT8231_SYSCTL_UCH, "uch_config", NULL, 0, 0644, NULL, &i2c_proc_real,
35330 +        &i2c_sysctl_real, NULL, &vt8231_uch},
35331 +       {0}
35332 +};
35333 +
35334 +static struct pci_dev *s_bridge;
35335 +
35336 +static int vt8231_attach_adapter(struct i2c_adapter *adapter)
35337 +{
35338 +       return i2c_detect(adapter, &addr_data, vt8231_detect);
35339 +}
35340 +
35341 +/* Locate chip and get correct base address */
35342 +static int vt8231_find(int *address)
35343 +{
35344 +       u16 val;
35345 +
35346 +       if (!pci_present())
35347 +               return -ENODEV;
35348 +
35349 +       if (!(s_bridge = pci_find_device(PCI_VENDOR_ID_VIA,
35350 +                                        0x8235, NULL)))
35351 +               return -ENODEV;
35352 +
35353 +       if (PCIBIOS_SUCCESSFUL !=
35354 +           pci_read_config_word(s_bridge, VIA686A_BASE_REG, &val))
35355 +               return -ENODEV;
35356 +       *address = val & ~(VIA686A_EXTENT - 1);
35357 +       if (*address == 0 && force_addr == 0) {
35358 +               printk("vt8231.o: base address not set - upgrade BIOS or use force_addr=0xaddr\n");
35359 +               return -ENODEV;
35360 +       }
35361 +       if (force_addr)
35362 +               *address = force_addr;  /* so detect will get called */
35363 +
35364 +       return 0;
35365 +}
35366 +
35367 +int vt8231_detect(struct i2c_adapter *adapter, int address,
35368 +                  unsigned short flags, int kind)
35369 +{
35370 +       int i;
35371 +       struct i2c_client *new_client;
35372 +       struct vt8231_data *data;
35373 +       int err = 0;
35374 +       const char *type_name = "vt8231";
35375 +       u16 val;
35376 +
35377 +       if (!i2c_is_isa_adapter(adapter)) {
35378 +               return 0;
35379 +       }
35380 +
35381 +       /* 8231 requires multiple of 256 */
35382 +       if(force_addr)
35383 +               address = force_addr & 0xFF00;
35384 +       if (check_region(address, VIA686A_EXTENT)) {
35385 +               printk("vt8231.o: region 0x%x already in use!\n",
35386 +                      address);
35387 +               return -ENODEV;
35388 +       }
35389 +
35390 +       if(force_addr) {
35391 +               printk("vt8231.o: forcing ISA address 0x%04X\n", address);
35392 +               if (PCIBIOS_SUCCESSFUL !=
35393 +                   pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
35394 +                       return -ENODEV;
35395 +       }
35396 +       if (PCIBIOS_SUCCESSFUL !=
35397 +           pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
35398 +               return -ENODEV;
35399 +       if (!(val & 0x0001)) {
35400 +               printk("vt8231.o: enabling sensors\n");
35401 +               if (PCIBIOS_SUCCESSFUL !=
35402 +                   pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
35403 +                                     val | 0x0001))
35404 +                       return -ENODEV;
35405 +       }
35406 +
35407 +       if (!(data = kmalloc(sizeof(struct vt8231_data), GFP_KERNEL))) {
35408 +               err = -ENOMEM;
35409 +               goto ERROR0;
35410 +       }
35411 +
35412 +       new_client = &data->client;
35413 +       new_client->addr = address;
35414 +       init_MUTEX(&data->lock);
35415 +       new_client->data = data;
35416 +       new_client->adapter = adapter;
35417 +       new_client->driver = &vt8231_driver;
35418 +       new_client->flags = 0;
35419 +
35420 +       /* Reserve the ISA region */
35421 +       request_region(address, VIA686A_EXTENT, "vt8231-sensors");
35422 +
35423 +       /* Fill in the remaining client fields and put into the global list */
35424 +       strcpy(new_client->name, "Via 8231 Integrated Sensors");
35425 +
35426 +       new_client->id = vt8231_id++;
35427 +       data->valid = 0;
35428 +       init_MUTEX(&data->update_lock);
35429 +
35430 +       /* Tell the I2C layer a new client has arrived */
35431 +       if ((err = i2c_attach_client(new_client)))
35432 +               goto ERROR3;
35433 +
35434 +       /* Register a new directory entry with module sensors */
35435 +       if ((i = i2c_register_entry((struct i2c_client *) new_client,
35436 +                                       type_name,
35437 +                                       vt8231_dir_table_template)) < 0) {
35438 +               err = i;
35439 +               goto ERROR4;
35440 +       }
35441 +       data->sysctl_id = i;
35442 +
35443 +       vt8231_init_client(new_client);
35444 +       return 0;
35445 +
35446 +      ERROR4:
35447 +       i2c_detach_client(new_client);
35448 +      ERROR3:
35449 +       release_region(address, VIA686A_EXTENT);
35450 +       kfree(data);
35451 +      ERROR0:
35452 +       return err;
35453 +}
35454 +
35455 +static int vt8231_detach_client(struct i2c_client *client)
35456 +{
35457 +       int err;
35458 +
35459 +       i2c_deregister_entry(((struct vt8231_data *) (client->data))->
35460 +                                sysctl_id);
35461 +
35462 +       if ((err = i2c_detach_client(client))) {
35463 +               printk
35464 +                   ("vt8231.o: Client deregistration failed, client not detached.\n");
35465 +               return err;
35466 +       }
35467 +
35468 +       release_region(client->addr, VIA686A_EXTENT);
35469 +       kfree(client->data);
35470 +
35471 +       return 0;
35472 +}
35473 +
35474 +
35475 +static inline int vt_rdval(struct i2c_client *client, u8 reg)
35476 +{
35477 +       return (inb_p(client->addr + reg));
35478 +}
35479 +
35480 +static inline void vt8231_write_value(struct i2c_client *client, u8 reg, u8 value)
35481 +{
35482 +       outb_p(value, client->addr + reg);
35483 +}
35484 +
35485 +static void vt8231_init_client(struct i2c_client *client)
35486 +{
35487 +       struct vt8231_data *data = client->data;
35488 +
35489 +       data->vrm = DEFAULT_VRM;
35490 +       /* set "default" interrupt mode for alarms, which isn't the default */
35491 +       vt8231_write_value(client, VT8231_REG_TEMP1_CONFIG, 0);
35492 +       vt8231_write_value(client, VT8231_REG_TEMP2_CONFIG, 0);
35493 +}
35494 +
35495 +static void vt8231_update_client(struct i2c_client *client)
35496 +{
35497 +       struct vt8231_data *data = client->data;
35498 +       int i, j;
35499 +
35500 +       down(&data->update_lock);
35501 +
35502 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
35503 +           (jiffies < data->last_updated) || !data->valid) {
35504 +               data->uch_config = vt_rdval(client, VT8231_REG_UCH_CONFIG);
35505 +               for (i = 0; i <= 5; i++) {
35506 +                       if(ISVOLT(i, data->uch_config)) {
35507 +                               data->in[i] = vt_rdval(client, VT8231_REG_IN(i));
35508 +                               data->in_min[i] = vt_rdval(client,
35509 +                                                       VT8231_REG_IN_MIN(i));
35510 +                               data->in_max[i] = vt_rdval(client,
35511 +                                                       VT8231_REG_IN_MAX(i));
35512 +                       } else {
35513 +                               data->in[i] = 0;
35514 +                               data->in_min[i] = 0;
35515 +                               data->in_max[i] = 0;
35516 +                       }
35517 +               }
35518 +               for (i = 1; i <= 2; i++) {
35519 +                       data->fan[i - 1] = vt_rdval(client, VT8231_REG_FAN(i));
35520 +                       data->fan_min[i - 1] = vt_rdval(client,
35521 +                                                    VT8231_REG_FAN_MIN(i));
35522 +               }
35523 +               for (i = 2; i <= 7; i++) {
35524 +                       if(ISTEMP(i, data->uch_config)) {
35525 +                               data->temp[i - 1] = vt_rdval(client,
35526 +                                                    VT8231_REG_TEMP(i)) << 2;
35527 +                               switch(i) {
35528 +                                       case 1:
35529 +                                               /* ? */
35530 +                                               j = 0;
35531 +                                               break;
35532 +                                       case 2:
35533 +                                               j = (vt_rdval(client,
35534 +                                                 VT8231_REG_TEMP_LOW2) &
35535 +                                                                   0x30) >> 4;
35536 +                                               break;
35537 +                                       case 3:
35538 +                                               j = (vt_rdval(client,
35539 +                                                 VT8231_REG_TEMP_LOW3) &
35540 +                                                                   0xc0) >> 6;
35541 +                                               break;
35542 +                                       case 4:
35543 +                                       case 5:
35544 +                                       case 6:
35545 +                                       case 7:
35546 +                                       default:
35547 +                                               j = (vt_rdval(client,
35548 +                                                 VT8231_REG_TEMP_LOW47) >>
35549 +                                                           ((i-4)*2)) & 0x03;  
35550 +                                               break;
35551 +       
35552 +                               }
35553 +                               data->temp[i - 1] |= j;
35554 +                               data->temp_over[i - 1] = vt_rdval(client,
35555 +                                                     VT8231_REG_TEMP_OVER(i));
35556 +                               data->temp_hyst[i - 1] = vt_rdval(client,
35557 +                                                     VT8231_REG_TEMP_HYST(i));
35558 +                       } else {
35559 +                               data->temp[i - 1] = 0;
35560 +                               data->temp_over[i - 1] = 0;
35561 +                               data->temp_hyst[i - 1] = 0;
35562 +                       }
35563 +               }
35564 +
35565 +               for (i = 1; i <= 2; i++) {
35566 +                       data->fan[i - 1] = vt_rdval(client, VT8231_REG_FAN(i));
35567 +                       data->fan_min[i - 1] = vt_rdval(client,
35568 +                                                       VT8231_REG_FAN_MIN(i));
35569 +                       data->pwm[i - 1] = vt_rdval(client, VT8231_REG_PWM(i));
35570 +               }
35571 +
35572 +               data->pwm_ctl = vt_rdval(client, VT8231_REG_PWM_CTL);
35573 +               i = vt_rdval(client, VT8231_REG_FANDIV);
35574 +               data->fan_div[0] = (i >> 4) & 0x03;
35575 +               data->fan_div[1] = i >> 6;
35576 +               data->alarms = vt_rdval(client, VT8231_REG_ALARM1) |
35577 +                                   (vt_rdval(client, VT8231_REG_ALARM2) << 8);
35578 +               data->vid= vt_rdval(client, VT8231_REG_VID) & 0x1f;
35579 +               data->last_updated = jiffies;
35580 +               data->valid = 1;
35581 +       }
35582 +
35583 +       up(&data->update_lock);
35584 +}
35585 +
35586 +
35587 +void vt8231_in(struct i2c_client *client, int operation, int ctl_name,
35588 +               int *nrels_mag, long *results)
35589 +{
35590 +       struct vt8231_data *data = client->data;
35591 +       int nr = ctl_name - VT8231_SYSCTL_IN0;
35592 +
35593 +       if (operation == SENSORS_PROC_REAL_INFO)
35594 +               *nrels_mag = 2;
35595 +       else if (operation == SENSORS_PROC_REAL_READ) {
35596 +               vt8231_update_client(client);
35597 +               results[0] = IN_FROM_REG(data->in_min[nr]);
35598 +               results[1] = IN_FROM_REG(data->in_max[nr]);
35599 +               results[2] = IN_FROM_REG(data->in[nr]);
35600 +               *nrels_mag = 3;
35601 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
35602 +               if (*nrels_mag >= 1) {
35603 +                       data->in_min[nr] = IN_TO_REG(results[0]);
35604 +                       vt8231_write_value(client, VT8231_REG_IN_MIN(nr),
35605 +                                           data->in_min[nr]);
35606 +               }
35607 +               if (*nrels_mag >= 2) {
35608 +                       data->in_max[nr] = IN_TO_REG(results[1]);
35609 +                       vt8231_write_value(client, VT8231_REG_IN_MAX(nr),
35610 +                                           data->in_max[nr]);
35611 +               }
35612 +       }
35613 +}
35614 +
35615 +void vt8231_fan(struct i2c_client *client, int operation, int ctl_name,
35616 +                int *nrels_mag, long *results)
35617 +{
35618 +       struct vt8231_data *data = client->data;
35619 +       int nr = ctl_name - VT8231_SYSCTL_FAN1 + 1;
35620 +
35621 +       if (operation == SENSORS_PROC_REAL_INFO)
35622 +               *nrels_mag = 0;
35623 +       else if (operation == SENSORS_PROC_REAL_READ) {
35624 +               vt8231_update_client(client);
35625 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
35626 +                                         DIV_FROM_REG(data->fan_div
35627 +                                                      [nr - 1]));
35628 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
35629 +                                DIV_FROM_REG(data->fan_div[nr - 1]));
35630 +               *nrels_mag = 2;
35631 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
35632 +               if (*nrels_mag >= 1) {
35633 +                       data->fan_min[nr - 1] = MIN_TO_REG(results[0],
35634 +                                                          DIV_FROM_REG
35635 +                                                          (data->
35636 +                                                           fan_div[nr-1]));
35637 +                       vt8231_write_value(client, VT8231_REG_FAN_MIN(nr),
35638 +                                           data->fan_min[nr - 1]);
35639 +               }
35640 +       }
35641 +}
35642 +
35643 +
35644 +void vt8231_temp(struct i2c_client *client, int operation, int ctl_name,
35645 +                 int *nrels_mag, long *results)
35646 +{
35647 +       struct vt8231_data *data = client->data;
35648 +       int nr = ctl_name - VT8231_SYSCTL_TEMP;
35649 +
35650 +       if (operation == SENSORS_PROC_REAL_INFO)
35651 +               *nrels_mag = 1;
35652 +       else if (operation == SENSORS_PROC_REAL_READ) {
35653 +               vt8231_update_client(client);
35654 +               results[0] = TEMP_FROM_REG(data->temp_over[nr]);
35655 +               results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
35656 +               results[2] = TEMP_FROM_REG10(data->temp[nr]);
35657 +               *nrels_mag = 3;
35658 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
35659 +               if (*nrels_mag >= 1) {
35660 +                       data->temp_over[nr] = TEMP_TO_REG(results[0]);
35661 +                       vt8231_write_value(client,
35662 +                                           VT8231_REG_TEMP_OVER(nr + 1),
35663 +                                           data->temp_over[nr]);
35664 +               }
35665 +               if (*nrels_mag >= 2) {
35666 +                       data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
35667 +                       vt8231_write_value(client,
35668 +                                           VT8231_REG_TEMP_HYST(nr + 1),
35669 +                                           data->temp_hyst[nr]);
35670 +               }
35671 +       }
35672 +}
35673 +
35674 +void vt8231_alarms(struct i2c_client *client, int operation, int ctl_name,
35675 +                   int *nrels_mag, long *results)
35676 +{
35677 +       struct vt8231_data *data = client->data;
35678 +       if (operation == SENSORS_PROC_REAL_INFO)
35679 +               *nrels_mag = 0;
35680 +       else if (operation == SENSORS_PROC_REAL_READ) {
35681 +               vt8231_update_client(client);
35682 +               results[0] = data->alarms;
35683 +               *nrels_mag = 1;
35684 +       }
35685 +}
35686 +
35687 +void vt8231_fan_div(struct i2c_client *client, int operation,
35688 +                    int ctl_name, int *nrels_mag, long *results)
35689 +{
35690 +       struct vt8231_data *data = client->data;
35691 +       int old;
35692 +
35693 +       if (operation == SENSORS_PROC_REAL_INFO)
35694 +               *nrels_mag = 0;
35695 +       else if (operation == SENSORS_PROC_REAL_READ) {
35696 +               vt8231_update_client(client);
35697 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
35698 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
35699 +               *nrels_mag = 2;
35700 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
35701 +               old = vt_rdval(client, VT8231_REG_FANDIV);
35702 +               if (*nrels_mag >= 2) {
35703 +                       data->fan_div[1] = DIV_TO_REG(results[1]);
35704 +                       old = (old & 0x3f) | (data->fan_div[1] << 6);
35705 +               }
35706 +               if (*nrels_mag >= 1) {
35707 +                       data->fan_div[0] = DIV_TO_REG(results[0]);
35708 +                       old = (old & 0xcf) | (data->fan_div[0] << 4);
35709 +                       vt8231_write_value(client, VT8231_REG_FANDIV, old);
35710 +               }
35711 +       }
35712 +}
35713 +
35714 +void vt8231_pwm(struct i2c_client *client, int operation, int ctl_name,
35715 +                int *nrels_mag, long *results)
35716 +{
35717 +       struct vt8231_data *data = client->data;
35718 +       int nr = 1 + ctl_name - VT8231_SYSCTL_PWM1;
35719 +
35720 +       if (operation == SENSORS_PROC_REAL_INFO)
35721 +               *nrels_mag = 0;
35722 +       else if (operation == SENSORS_PROC_REAL_READ) {
35723 +               vt8231_update_client(client);
35724 +               results[0] = PWM_FROM_REG(data->pwm[nr - 1]);
35725 +               results[1] = (data->pwm_ctl >> (3 + (4 * (nr - 1)))) & 1;
35726 +               *nrels_mag = 2;
35727 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
35728 +               if (*nrels_mag >= 1) {
35729 +                       data->pwm[nr - 1] = PWM_TO_REG(results[0]);
35730 +                       if (*nrels_mag >= 2) {
35731 +                               if(results[1]) {
35732 +                                       data->pwm_ctl |=
35733 +                                                 (0x08 << (4 * (nr - 1)));
35734 +                                       vt8231_write_value(client,
35735 +                                                          VT8231_REG_PWM_CTL, 
35736 +                                                          data->pwm_ctl);
35737 +                               } else {
35738 +                                       data->pwm_ctl &=
35739 +                                               ~ (0x08 << (4 * (nr - 1)));
35740 +                                       vt8231_write_value(client,
35741 +                                                          VT8231_REG_PWM_CTL, 
35742 +                                                          data->pwm_ctl);
35743 +                               }
35744 +                       }
35745 +                       vt8231_write_value(client, VT8231_REG_PWM(nr),
35746 +                                           data->pwm[nr - 1]);
35747 +               }
35748 +       }
35749 +}
35750 +
35751 +void vt8231_vid(struct i2c_client *client, int operation, int ctl_name,
35752 +                int *nrels_mag, long *results)
35753 +{
35754 +       struct vt8231_data *data = client->data;
35755 +       if (operation == SENSORS_PROC_REAL_INFO)
35756 +               *nrels_mag = 3;
35757 +       else if (operation == SENSORS_PROC_REAL_READ) {
35758 +               vt8231_update_client(client);
35759 +               results[0] = vid_from_reg(data->vid, data->vrm);
35760 +               *nrels_mag = 1;
35761 +       }
35762 +}
35763 +
35764 +void vt8231_vrm(struct i2c_client *client, int operation, int ctl_name,
35765 +                int *nrels_mag, long *results)
35766 +{
35767 +       struct vt8231_data *data = client->data;
35768 +       if (operation == SENSORS_PROC_REAL_INFO)
35769 +               *nrels_mag = 1;
35770 +       else if (operation == SENSORS_PROC_REAL_READ) {
35771 +               results[0] = data->vrm;
35772 +               *nrels_mag = 1;
35773 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
35774 +               if (*nrels_mag >= 1)
35775 +                       data->vrm = results[0];
35776 +       }
35777 +}
35778 +
35779 +void vt8231_uch(struct i2c_client *client, int operation, int ctl_name,
35780 +                int *nrels_mag, long *results)
35781 +{
35782 +       struct vt8231_data *data = client->data;
35783 +       if (operation == SENSORS_PROC_REAL_INFO)
35784 +               *nrels_mag = 0;
35785 +       else if (operation == SENSORS_PROC_REAL_READ) {
35786 +               results[0] = data->uch_config & 0x7c;
35787 +               *nrels_mag = 1;
35788 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
35789 +               if (*nrels_mag >= 1) {
35790 +                       data->uch_config = (data->uch_config & 0x83)|(results[0] & 0x7c);
35791 +                       vt8231_write_value(client, VT8231_REG_UCH_CONFIG,
35792 +                                          data->uch_config);
35793 +               }
35794 +       }
35795 +}
35796 +
35797 +static int __init sm_vt8231_init(void)
35798 +{
35799 +       int addr;
35800 +
35801 +       printk("vt8231.o version %s (%s)\n", LM_VERSION, LM_DATE);
35802 +
35803 +       if (vt8231_find(&addr)) {
35804 +               printk("vt8231.o: VT8231 not detected, module not inserted.\n");
35805 +               return -ENODEV;
35806 +       }
35807 +       normal_isa[0] = addr;
35808 +
35809 +       return i2c_add_driver(&vt8231_driver);}
35810 +
35811 +static void __exit sm_vt8231_exit(void)
35812 +{
35813 +       i2c_del_driver(&vt8231_driver);
35814 +}
35815 +
35816 +
35817 +
35818 +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
35819 +MODULE_DESCRIPTION("VT8231 sensors");
35820 +MODULE_LICENSE("GPL");
35821 +
35822 +module_init(sm_vt8231_init);
35823 +module_exit(sm_vt8231_exit);
35824 --- linux-old/drivers/sensors/w83627hf.c        Thu Jan  1 00:00:00 1970
35825 +++ linux/drivers/sensors/w83627hf.c    Mon Dec 13 20:18:53 2004
35826 @@ -0,0 +1,1422 @@
35827 +/*
35828 +    w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware
35829 +                monitoring
35830 +    Copyright (c) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
35831 +    Philip Edelbrock <phil@netroedge.com>,
35832 +    and Mark Studebaker <mdsxyz123@yahoo.com>
35833 +
35834 +    This program is free software; you can redistribute it and/or modify
35835 +    it under the terms of the GNU General Public License as published by
35836 +    the Free Software Foundation; either version 2 of the License, or
35837 +    (at your option) any later version.
35838 +
35839 +    This program is distributed in the hope that it will be useful,
35840 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
35841 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35842 +    GNU General Public License for more details.
35843 +
35844 +    You should have received a copy of the GNU General Public License
35845 +    along with this program; if not, write to the Free Software
35846 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35847 +*/
35848 +
35849 +/*
35850 +    Supports following chips:
35851 +
35852 +    Chip       #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
35853 +    w83627hf   9       3       2       3       0x20    0x5ca3  no      yes(LPC)
35854 +    w83627thf  7       3       3       3       0x90    0x5ca3  no      yes(LPC)
35855 +    w83637hf   7       3       3       3       0x80    0x5ca3  no      yes(LPC)
35856 +    w83697hf   8       2       2       2       0x60    0x5ca3  no      yes(LPC)
35857 +
35858 +    For other winbond chips, and for i2c support in the above chips,
35859 +    use w83781d.c.
35860 +
35861 +    Note: automatic ("cruise") fan control for 697, 637 & 627thf not
35862 +    supported yet.
35863 +*/
35864 +
35865 +#include <linux/module.h>
35866 +#include <linux/slab.h>
35867 +#include <linux/ioport.h>
35868 +#include <linux/i2c.h>
35869 +#include <linux/i2c-proc.h>
35870 +#include <linux/init.h>
35871 +#include <asm/io.h>
35872 +#define LM_DATE "20041007"
35873 +#define LM_VERSION "2.8.8"
35874 +#include <linux/sensors_vid.h>
35875 +#include "lm75.h"
35876 +
35877 +static int force_addr;
35878 +MODULE_PARM(force_addr, "i");
35879 +MODULE_PARM_DESC(force_addr,
35880 +                "Initialize the base address of the sensors");
35881 +static int force_i2c = 0x1f;
35882 +MODULE_PARM(force_i2c, "i");
35883 +MODULE_PARM_DESC(force_i2c,
35884 +                "Initialize the i2c address of the sensors");
35885 +
35886 +/* Addresses to scan */
35887 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
35888 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
35889 +static unsigned int normal_isa[] = { 0, SENSORS_ISA_END };
35890 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
35891 +
35892 +/* Insmod parameters */
35893 +SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
35894 +
35895 +static int init = 1;
35896 +MODULE_PARM(init, "i");
35897 +MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
35898 +
35899 +/* modified from kernel/include/traps.c */
35900 +#define        REG     0x2e    /* The register to read/write */
35901 +#define        DEV     0x07    /* Register: Logical device select */
35902 +#define        VAL     0x2f    /* The value to read/write */
35903 +
35904 +/* logical device numbers for superio_select (below) */
35905 +#define W83627HF_LD_FDC                0x00
35906 +#define W83627HF_LD_PRT                0x01
35907 +#define W83627HF_LD_UART1      0x02
35908 +#define W83627HF_LD_UART2      0x03
35909 +#define W83627HF_LD_KBC                0x05
35910 +#define W83627HF_LD_CIR                0x06 /* w83627hf only */
35911 +#define W83627HF_LD_GAME       0x07
35912 +#define W83627HF_LD_MIDI       0x07
35913 +#define W83627HF_LD_GPIO1      0x07
35914 +#define W83627HF_LD_GPIO5      0x07 /* w83627thf only */
35915 +#define W83627HF_LD_GPIO2      0x08
35916 +#define W83627HF_LD_GPIO3      0x09
35917 +#define W83627HF_LD_GPIO4      0x09 /* w83627thf only */
35918 +#define W83627HF_LD_ACPI       0x0a
35919 +#define W83627HF_LD_HWM                0x0b
35920 +
35921 +#define        DEVID   0x20    /* Register: Device ID */
35922 +
35923 +#define W83627THF_GPIO5_IOSR   0xf3 /* w83627thf only */
35924 +#define W83627THF_GPIO5_DR     0xf4 /* w83627thf only */
35925 +#define W83627THF_GPIO5_INVR   0xf5 /* w83627thf only */
35926 +
35927 +static inline void
35928 +superio_outb(int reg, int val)
35929 +{
35930 +       outb(reg, REG);
35931 +       outb(val, VAL);
35932 +}
35933 +
35934 +static inline int
35935 +superio_inb(int reg)
35936 +{
35937 +       outb(reg, REG);
35938 +       return inb(VAL);
35939 +}
35940 +
35941 +static inline void
35942 +superio_select(int ld)
35943 +{
35944 +       outb(DEV, REG);
35945 +       outb(ld, VAL);
35946 +}
35947 +
35948 +static inline void
35949 +superio_enter(void)
35950 +{
35951 +       outb(0x87, REG);
35952 +       outb(0x87, REG);
35953 +}
35954 +
35955 +static inline void
35956 +superio_exit(void)
35957 +{
35958 +       outb(0xAA, REG);
35959 +}
35960 +
35961 +#define W627_DEVID 0x52
35962 +#define W627THF_DEVID 0x82
35963 +#define W697_DEVID 0x60
35964 +#define W637_DEVID 0x70
35965 +#define WINB_ACT_REG 0x30
35966 +#define WINB_BASE_REG 0x60
35967 +/* Constants specified below */
35968 +
35969 +/* Length of ISA address segment */
35970 +#define WINB_EXTENT 8
35971 +
35972 +/* Where are the ISA address/data registers relative to the base address */
35973 +#define W83781D_ADDR_REG_OFFSET 5
35974 +#define W83781D_DATA_REG_OFFSET 6
35975 +
35976 +/* The W83781D registers */
35977 +/* The W83782D registers for nr=7,8 are in bank 5 */
35978 +#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
35979 +                                          (0x554 + (((nr) - 7) * 2)))
35980 +#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
35981 +                                          (0x555 + (((nr) - 7) * 2)))
35982 +#define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
35983 +                                          (0x550 + (nr) - 7))
35984 +
35985 +#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
35986 +#define W83781D_REG_FAN(nr) (0x27 + (nr))
35987 +
35988 +#define W83781D_REG_TEMP2 0x0150
35989 +#define W83781D_REG_TEMP3 0x0250
35990 +#define W83781D_REG_TEMP2_HYST 0x153
35991 +#define W83781D_REG_TEMP3_HYST 0x253
35992 +#define W83781D_REG_TEMP2_CONFIG 0x152
35993 +#define W83781D_REG_TEMP3_CONFIG 0x252
35994 +#define W83781D_REG_TEMP2_OVER 0x155
35995 +#define W83781D_REG_TEMP3_OVER 0x255
35996 +
35997 +#define W83781D_REG_TEMP 0x27
35998 +#define W83781D_REG_TEMP_OVER 0x39
35999 +#define W83781D_REG_TEMP_HYST 0x3A
36000 +#define W83781D_REG_BANK 0x4E
36001 +
36002 +#define W83781D_REG_CONFIG 0x40
36003 +#define W83781D_REG_ALARM1 0x41
36004 +#define W83781D_REG_ALARM2 0x42
36005 +#define W83781D_REG_ALARM3 0x450
36006 +
36007 +#define W83781D_REG_IRQ 0x4C
36008 +#define W83781D_REG_BEEP_CONFIG 0x4D
36009 +#define W83781D_REG_BEEP_INTS1 0x56
36010 +#define W83781D_REG_BEEP_INTS2 0x57
36011 +#define W83781D_REG_BEEP_INTS3 0x453
36012 +
36013 +#define W83781D_REG_VID_FANDIV 0x47
36014 +
36015 +#define W83781D_REG_CHIPID 0x49
36016 +#define W83781D_REG_WCHIPID 0x58
36017 +#define W83781D_REG_CHIPMAN 0x4F
36018 +#define W83781D_REG_PIN 0x4B
36019 +
36020 +#define W83781D_REG_VBAT 0x5D
36021 +
36022 +#define W83627HF_REG_PWM1 0x5A
36023 +#define W83627HF_REG_PWM2 0x5B
36024 +#define W83627HF_REG_PWMCLK12 0x5C
36025 +
36026 +#define W83627THF_REG_PWM1             0x01    /* 697HF and 637HF too */
36027 +#define W83627THF_REG_PWM2             0x03    /* 697HF and 637HF too */
36028 +#define W83627THF_REG_PWM3             0x11    /* 637HF too */
36029 +
36030 +#define W83627THF_REG_VRM_OVT_CFG      0x18    /* 637HF too */
36031 +
36032 +static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
36033 +static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
36034 +                             W83627THF_REG_PWM3 };
36035 +#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
36036 +                                     regpwm_627hf[(nr) - 1] : regpwm[(nr) - 1])
36037 +
36038 +#define W83781D_REG_I2C_ADDR 0x48
36039 +#define W83781D_REG_I2C_SUBADDR 0x4A
36040 +
36041 +/* Sensor selection */
36042 +#define W83781D_REG_SCFG1 0x5D
36043 +static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
36044 +#define W83781D_REG_SCFG2 0x59
36045 +static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
36046 +#define W83781D_DEFAULT_BETA 3435
36047 +
36048 +/* Conversions. Limit checking is only done on the TO_REG
36049 +   variants. Note that you should be a bit careful with which arguments
36050 +   these macros are called: arguments may be evaluated more than once.
36051 +   Fixing this is just not worth it. */
36052 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
36053 +#define IN_FROM_REG(val) (((val) * 16 + 5) / 10)
36054 +
36055 +#define IN_TO_REG_VRM9(val) \
36056 +       (SENSORS_LIMIT((((val) * 1000 - 70000 + 244) / 488), 0, 255))
36057 +#define IN_FROM_REG_VRM9(reg)  (((reg) * 488 + 70000 + 500) / 1000)
36058 +
36059 +static inline u8 FAN_TO_REG(long rpm, int div)
36060 +{
36061 +       if (rpm == 0)
36062 +               return 255;
36063 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
36064 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
36065 +                            254);
36066 +}
36067 +
36068 +#define TEMP_MIN (-1280)
36069 +#define TEMP_MAX ( 1270)
36070 +
36071 +/* TEMP: 1/10 degrees C (-128C to +127C)
36072 +   REG: 1C/bit, two's complement */
36073 +static u8 TEMP_TO_REG(int temp)
36074 +{
36075 +        int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
36076 +        ntemp += (ntemp<0 ? -5 : 5);
36077 +        return (u8)(ntemp / 10);
36078 +}
36079 +                                                                                
36080 +static int TEMP_FROM_REG(u8 reg)
36081 +{
36082 +        return (s8)reg * 10;
36083 +}
36084 +
36085 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
36086 +
36087 +#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
36088 +#define BEEPS_TO_REG(val) ((val) & 0xffffff)
36089 +
36090 +#define BEEP_ENABLE_TO_REG(val)   ((val)?1:0)
36091 +#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0)
36092 +
36093 +#define DIV_FROM_REG(val) (1 << (val))
36094 +
36095 +static inline u8 DIV_TO_REG(long val)
36096 +{
36097 +       int i;
36098 +       val = SENSORS_LIMIT(val, 1, 128) >> 1;
36099 +       for (i = 0; i < 6; i++) {
36100 +               if (val == 0)
36101 +                       break;
36102 +               val >>= 1;
36103 +       }
36104 +       return ((u8) i);
36105 +}
36106 +
36107 +/* For each registered chip, we need to keep some data in memory. That
36108 +   data is pointed to by w83627hf_list[NR]->data. The structure itself is
36109 +   dynamically allocated, at the same time when a new client is allocated. */
36110 +struct w83627hf_data {
36111 +       struct i2c_client client;
36112 +       struct semaphore lock;
36113 +       int sysctl_id;
36114 +       enum chips type;
36115 +
36116 +       struct semaphore update_lock;
36117 +       char valid;             /* !=0 if following fields are valid */
36118 +       unsigned long last_updated;     /* In jiffies */
36119 +
36120 +       struct i2c_client *lm75;        /* for secondary I2C addresses */
36121 +       /* pointer to array of 2 subclients */
36122 +
36123 +       u8 in[9];               /* Register value */
36124 +       u8 in_max[9];           /* Register value */
36125 +       u8 in_min[9];           /* Register value */
36126 +       u8 fan[3];              /* Register value */
36127 +       u8 fan_min[3];          /* Register value */
36128 +       u8 temp;
36129 +       u8 temp_over;           /* Register value */
36130 +       u8 temp_hyst;           /* Register value */
36131 +       u16 temp_add[2];        /* Register value */
36132 +       u16 temp_add_over[2];   /* Register value */
36133 +       u16 temp_add_hyst[2];   /* Register value */
36134 +       u8 fan_div[3];          /* Register encoding, shifted right */
36135 +       u8 vid;                 /* Register encoding, combined */
36136 +       u32 alarms;             /* Register encoding, combined */
36137 +       u32 beeps;              /* Register encoding, combined */
36138 +       u8 beep_enable;         /* Boolean */
36139 +       u8 pwm[3];              /* Register value */
36140 +       u8 pwmenable[3];        /* bool */
36141 +       u16 sens[3];            /* 782D/783S only.
36142 +                                  1 = pentium diode; 2 = 3904 diode;
36143 +                                  3000-5000 = thermistor beta.
36144 +                                  Default = 3435. 
36145 +                                  Other Betas unimplemented */
36146 +       u8 vrm;
36147 +       u8 vrm_ovt;             /* Register value, 627thf & 637hf only */
36148 +};
36149 +
36150 +
36151 +static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
36152 +static int w83627hf_detect(struct i2c_adapter *adapter, int address,
36153 +                         unsigned short flags, int kind);
36154 +static int w83627hf_detach_client(struct i2c_client *client);
36155 +
36156 +static int w83627hf_read_value(struct i2c_client *client, u16 register);
36157 +static int w83627hf_write_value(struct i2c_client *client, u16 register,
36158 +                              u16 value);
36159 +static void w83627hf_update_client(struct i2c_client *client);
36160 +static void w83627hf_init_client(struct i2c_client *client);
36161 +
36162 +
36163 +static void w83627hf_in(struct i2c_client *client, int operation,
36164 +                      int ctl_name, int *nrels_mag, long *results);
36165 +static void w83627hf_fan(struct i2c_client *client, int operation,
36166 +                       int ctl_name, int *nrels_mag, long *results);
36167 +static void w83627hf_temp(struct i2c_client *client, int operation,
36168 +                        int ctl_name, int *nrels_mag, long *results);
36169 +static void w83627hf_temp_add(struct i2c_client *client, int operation,
36170 +                            int ctl_name, int *nrels_mag, long *results);
36171 +static void w83627hf_vid(struct i2c_client *client, int operation,
36172 +                       int ctl_name, int *nrels_mag, long *results);
36173 +static void w83627hf_vrm(struct i2c_client *client, int operation,
36174 +                       int ctl_name, int *nrels_mag, long *results);
36175 +static void w83627hf_alarms(struct i2c_client *client, int operation,
36176 +                          int ctl_name, int *nrels_mag, long *results);
36177 +static void w83627hf_beep(struct i2c_client *client, int operation,
36178 +                        int ctl_name, int *nrels_mag, long *results);
36179 +static void w83627hf_fan_div(struct i2c_client *client, int operation,
36180 +                           int ctl_name, int *nrels_mag, long *results);
36181 +static void w83627hf_pwm(struct i2c_client *client, int operation,
36182 +                       int ctl_name, int *nrels_mag, long *results);
36183 +static void w83627hf_sens(struct i2c_client *client, int operation,
36184 +                        int ctl_name, int *nrels_mag, long *results);
36185 +
36186 +static int w83627hf_id = 0;
36187 +
36188 +static struct i2c_driver w83627hf_driver = {
36189 +       .owner          = THIS_MODULE,
36190 +       .name           = "W83627HF sensor driver",
36191 +       .id             = I2C_DRIVERID_W83627HF,
36192 +       .flags          = I2C_DF_NOTIFY,
36193 +       .attach_adapter = w83627hf_attach_adapter,
36194 +       .detach_client  = w83627hf_detach_client,
36195 +};
36196 +
36197 +/* The /proc/sys entries */
36198 +/* WARNING these are copied from w83781d.c and have not been renamed.
36199 +   Note that the 627hf and 697hf are supported by both drivers.
36200 +   Do not make incompatible changes here or we will have errors
36201 +   in the generated file ../include/sensors.h !!!
36202 +*/
36203 +/* -- SENSORS SYSCTL START -- */
36204 +
36205 +#define W83781D_SYSCTL_IN0 1000        /* Volts * 100 */
36206 +#define W83781D_SYSCTL_IN1 1001
36207 +#define W83781D_SYSCTL_IN2 1002
36208 +#define W83781D_SYSCTL_IN3 1003
36209 +#define W83781D_SYSCTL_IN4 1004
36210 +#define W83781D_SYSCTL_IN5 1005
36211 +#define W83781D_SYSCTL_IN6 1006
36212 +#define W83781D_SYSCTL_IN7 1007
36213 +#define W83781D_SYSCTL_IN8 1008
36214 +#define W83781D_SYSCTL_FAN1 1101       /* Rotations/min */
36215 +#define W83781D_SYSCTL_FAN2 1102
36216 +#define W83781D_SYSCTL_FAN3 1103
36217 +#define W83781D_SYSCTL_TEMP1 1200      /* Degrees Celcius * 10 */
36218 +#define W83781D_SYSCTL_TEMP2 1201      /* Degrees Celcius * 10 */
36219 +#define W83781D_SYSCTL_TEMP3 1202      /* Degrees Celcius * 10 */
36220 +#define W83781D_SYSCTL_VID 1300                /* Volts * 1000 */
36221 +#define W83781D_SYSCTL_VRM 1301
36222 +#define W83781D_SYSCTL_PWM1 1401
36223 +#define W83781D_SYSCTL_PWM2 1402
36224 +#define W83781D_SYSCTL_PWM3 1403
36225 +#define W83781D_SYSCTL_SENS1 1501      /* 1, 2, or Beta (3000-5000) */
36226 +#define W83781D_SYSCTL_SENS2 1502
36227 +#define W83781D_SYSCTL_SENS3 1503
36228 +#define W83781D_SYSCTL_FAN_DIV 2000    /* 1, 2, 4 or 8 */
36229 +#define W83781D_SYSCTL_ALARMS 2001     /* bitvector */
36230 +#define W83781D_SYSCTL_BEEP 2002       /* bitvector */
36231 +
36232 +#define W83781D_ALARM_IN0 0x0001
36233 +#define W83781D_ALARM_IN1 0x0002
36234 +#define W83781D_ALARM_IN2 0x0004
36235 +#define W83781D_ALARM_IN3 0x0008
36236 +#define W83781D_ALARM_IN4 0x0100
36237 +#define W83781D_ALARM_IN5 0x0200
36238 +#define W83781D_ALARM_IN6 0x0400
36239 +#define W83782D_ALARM_IN7 0x10000
36240 +#define W83782D_ALARM_IN8 0x20000
36241 +#define W83781D_ALARM_FAN1 0x0040
36242 +#define W83781D_ALARM_FAN2 0x0080
36243 +#define W83781D_ALARM_FAN3 0x0800
36244 +#define W83781D_ALARM_TEMP1 0x0010
36245 +#define W83781D_ALARM_TEMP23 0x0020    /* 781D only */
36246 +#define W83781D_ALARM_TEMP2 0x0020     /* 782D/783S */
36247 +#define W83781D_ALARM_TEMP3 0x2000     /* 782D only */
36248 +#define W83781D_ALARM_CHAS 0x1000
36249 +
36250 +/* -- SENSORS SYSCTL END -- */
36251 +
36252 +/* These files are created for each detected chip. This is just a template;
36253 +   though at first sight, you might think we could use a statically
36254 +   allocated list, we need some way to get back to the parent - which
36255 +   is done through one of the 'extra' fields which are initialized 
36256 +   when a new copy is allocated. */
36257 +
36258 +/* without pwm3-4 */
36259 +static ctl_table w83627hf_dir_table_template[] = {
36260 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
36261 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36262 +       {W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
36263 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36264 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
36265 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36266 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
36267 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36268 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
36269 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36270 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
36271 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36272 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
36273 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36274 +       {W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
36275 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36276 +       {W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
36277 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36278 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
36279 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36280 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
36281 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36282 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
36283 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36284 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
36285 +        &i2c_sysctl_real, NULL, &w83627hf_temp},
36286 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
36287 +        &i2c_sysctl_real, NULL, &w83627hf_temp_add},
36288 +       {W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
36289 +        &i2c_sysctl_real, NULL, &w83627hf_temp_add},
36290 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
36291 +        &i2c_sysctl_real, NULL, &w83627hf_vid},
36292 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
36293 +        &i2c_sysctl_real, NULL, &w83627hf_vrm},
36294 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
36295 +        &i2c_sysctl_real, NULL, &w83627hf_fan_div},
36296 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
36297 +        &i2c_sysctl_real, NULL, &w83627hf_alarms},
36298 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
36299 +        &i2c_sysctl_real, NULL, &w83627hf_beep},
36300 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
36301 +        &i2c_sysctl_real, NULL, &w83627hf_pwm},
36302 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
36303 +        &i2c_sysctl_real, NULL, &w83627hf_pwm},
36304 +       {W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
36305 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36306 +       {W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
36307 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36308 +       {W83781D_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL, &i2c_proc_real,
36309 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36310 +       {0}
36311 +};
36312 +
36313 +/* similar to w83782d but no fan3, no vid */
36314 +static ctl_table w83697hf_dir_table_template[] = {
36315 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
36316 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36317 +       /* no in1 to maintain compatibility with 781d and 782d. */
36318 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
36319 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36320 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
36321 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36322 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
36323 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36324 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
36325 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36326 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
36327 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36328 +       {W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
36329 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36330 +       {W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
36331 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36332 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
36333 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36334 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
36335 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36336 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
36337 +        &i2c_sysctl_real, NULL, &w83627hf_temp},
36338 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
36339 +        &i2c_sysctl_real, NULL, &w83627hf_temp_add},
36340 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
36341 +        &i2c_sysctl_real, NULL, &w83627hf_fan_div},
36342 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
36343 +        &i2c_sysctl_real, NULL, &w83627hf_alarms},
36344 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
36345 +        &i2c_sysctl_real, NULL, &w83627hf_beep},
36346 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
36347 +        &i2c_sysctl_real, NULL, &w83627hf_pwm},
36348 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
36349 +        &i2c_sysctl_real, NULL, &w83627hf_pwm},
36350 +       {W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
36351 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36352 +       {W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
36353 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36354 +       {0}
36355 +};
36356 +
36357 +/* no in5 and in6 */
36358 +/* We use this one for W83637HF too */
36359 +static ctl_table w83627thf_dir_table_template[] = {
36360 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
36361 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36362 +       {W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
36363 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36364 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
36365 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36366 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
36367 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36368 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
36369 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36370 +       {W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
36371 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36372 +       {W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
36373 +        &i2c_sysctl_real, NULL, &w83627hf_in},
36374 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
36375 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36376 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
36377 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36378 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
36379 +        &i2c_sysctl_real, NULL, &w83627hf_fan},
36380 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
36381 +        &i2c_sysctl_real, NULL, &w83627hf_temp},
36382 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
36383 +        &i2c_sysctl_real, NULL, &w83627hf_temp_add},
36384 +       {W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
36385 +        &i2c_sysctl_real, NULL, &w83627hf_temp_add},
36386 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
36387 +        &i2c_sysctl_real, NULL, &w83627hf_vid},
36388 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
36389 +        &i2c_sysctl_real, NULL, &w83627hf_vrm},
36390 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
36391 +        &i2c_sysctl_real, NULL, &w83627hf_fan_div},
36392 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
36393 +        &i2c_sysctl_real, NULL, &w83627hf_alarms},
36394 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
36395 +        &i2c_sysctl_real, NULL, &w83627hf_beep},
36396 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
36397 +        &i2c_sysctl_real, NULL, &w83627hf_pwm},
36398 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
36399 +        &i2c_sysctl_real, NULL, &w83627hf_pwm},
36400 +       {W83781D_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
36401 +        &i2c_sysctl_real, NULL, &w83627hf_pwm},
36402 +       {W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
36403 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36404 +       {W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
36405 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36406 +       {W83781D_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL, &i2c_proc_real,
36407 +        &i2c_sysctl_real, NULL, &w83627hf_sens},
36408 +       {0}
36409 +};
36410 +
36411 +
36412 +/* This function is called when:
36413 +     * w83627hf_driver is inserted (when this module is loaded), for each
36414 +       available adapter
36415 +     * when a new adapter is inserted (and w83627hf_driver is still present) */
36416 +static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
36417 +{
36418 +       return i2c_detect(adapter, &addr_data, w83627hf_detect);
36419 +}
36420 +
36421 +static int w83627hf_find(int *address)
36422 +{
36423 +       u16 val;
36424 +
36425 +       superio_enter();
36426 +       val= superio_inb(DEVID);
36427 +       if(val != W627_DEVID && val !=W627THF_DEVID && val != W697_DEVID && val != W637_DEVID) {
36428 +               superio_exit();
36429 +               return -ENODEV;
36430 +       }
36431 +
36432 +       superio_select(W83627HF_LD_HWM);
36433 +       val = (superio_inb(WINB_BASE_REG) << 8) |
36434 +              superio_inb(WINB_BASE_REG + 1);
36435 +       *address = val & ~(WINB_EXTENT - 1);
36436 +       if (*address == 0 && force_addr == 0) {
36437 +               printk("w83627hf.o: base address not set - use force_addr=0xaddr\n");
36438 +               superio_exit();
36439 +               return -ENODEV;
36440 +       }
36441 +       if (force_addr)
36442 +               *address = force_addr;  /* so detect will get called */
36443 +
36444 +       superio_exit();
36445 +       return 0;
36446 +}
36447 +
36448 +int w83627hf_detect(struct i2c_adapter *adapter, int address,
36449 +                  unsigned short flags, int kind)
36450 +{
36451 +       int i, val;
36452 +       struct i2c_client *new_client;
36453 +       struct w83627hf_data *data;
36454 +       int err = 0;
36455 +       const char *type_name = "";
36456 +       const char *client_name = "";
36457 +
36458 +       if (!i2c_is_isa_adapter(adapter))
36459 +               return 0;
36460 +
36461 +       if(force_addr)
36462 +               address = force_addr & ~(WINB_EXTENT - 1);
36463 +       if (check_region(address, WINB_EXTENT)) {
36464 +               printk("w83627hf.o: region 0x%x already in use!\n", address);
36465 +               return -ENODEV;
36466 +       }
36467 +       if(force_addr) {
36468 +               printk("w83627hf.o: forcing ISA address 0x%04X\n", address);
36469 +               superio_enter();
36470 +               superio_select(W83627HF_LD_HWM);
36471 +               superio_outb(WINB_BASE_REG, address >> 8);
36472 +               superio_outb(WINB_BASE_REG+1, address & 0xff);
36473 +               superio_exit();
36474 +       }
36475 +
36476 +       superio_enter();
36477 +       val= superio_inb(DEVID);
36478 +       if(val == W627_DEVID)
36479 +               kind = w83627hf;
36480 +       else if(val == W697_DEVID)
36481 +               kind = w83697hf;
36482 +       else if(val == W627THF_DEVID)
36483 +               kind = w83627thf;
36484 +       else if(val == W637_DEVID)
36485 +               kind = w83637hf;
36486 +               
36487 +       superio_select(W83627HF_LD_HWM);
36488 +       if((val = 0x01 & superio_inb(WINB_ACT_REG)) == 0)
36489 +               superio_outb(WINB_ACT_REG, 1);
36490 +       superio_exit();
36491 +
36492 +       /* OK. For now, we presume we have a valid client. We now create the
36493 +          client structure, even though we cannot fill it completely yet.
36494 +          But it allows us to access w83627hf_{read,write}_value. */
36495 +
36496 +       if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
36497 +               err = -ENOMEM;
36498 +               goto ERROR0;
36499 +       }
36500 +
36501 +       new_client = &data->client;
36502 +       new_client->addr = address;
36503 +       init_MUTEX(&data->lock);
36504 +       new_client->data = data;
36505 +       new_client->adapter = adapter;
36506 +       new_client->driver = &w83627hf_driver;
36507 +       new_client->flags = 0;
36508 +
36509 +
36510 +       if (kind == w83627hf) {
36511 +               type_name = "w83627hf";
36512 +               client_name = "W83627HF chip";
36513 +       } else if (kind == w83627thf) {
36514 +               type_name = "w83627thf";
36515 +               client_name = "W83627THF chip";
36516 +       } else if (kind == w83697hf) {
36517 +               type_name = "w83697hf";
36518 +               client_name = "W83697HF chip";
36519 +       } else if (kind == w83637hf) {
36520 +               type_name = "w83637hf";
36521 +               client_name = "W83637HF chip";
36522 +       } else {
36523 +               goto ERROR1;
36524 +       }
36525 +
36526 +       request_region(address, WINB_EXTENT, type_name);
36527 +
36528 +       /* Fill in the remaining client fields and put it into the global list */
36529 +       strcpy(new_client->name, client_name);
36530 +       data->type = kind;
36531 +       new_client->id = w83627hf_id++;
36532 +       data->valid = 0;
36533 +       init_MUTEX(&data->update_lock);
36534 +
36535 +       /* Tell the I2C layer a new client has arrived */
36536 +       if ((err = i2c_attach_client(new_client)))
36537 +               goto ERROR3;
36538 +
36539 +       data->lm75 = NULL;
36540 +
36541 +       /* Register a new directory entry with module sensors */
36542 +       if ((i = i2c_register_entry(new_client,
36543 +                               type_name,
36544 +                               (kind == w83697hf) ?
36545 +                                  w83697hf_dir_table_template :
36546 +                               (kind == w83627hf) ?
36547 +                                  w83627hf_dir_table_template :
36548 +                                  /* w83627thf table also used for 637 */
36549 +                                  w83627thf_dir_table_template)) < 0) {
36550 +               err = i;
36551 +               goto ERROR7;
36552 +       }
36553 +       data->sysctl_id = i;
36554 +
36555 +       /* Initialize the chip */
36556 +       w83627hf_init_client(new_client);
36557 +       return 0;
36558 +
36559 +/* OK, this is not exactly good programming practice, usually. But it is
36560 +   very code-efficient in this case. */
36561 +
36562 +      ERROR7:
36563 +       i2c_detach_client(new_client);
36564 +      ERROR3:
36565 +       release_region(address, WINB_EXTENT);
36566 +      ERROR1:
36567 +       kfree(data);
36568 +      ERROR0:
36569 +       return err;
36570 +}
36571 +
36572 +static int w83627hf_detach_client(struct i2c_client *client)
36573 +{
36574 +       int err;
36575 +
36576 +       i2c_deregister_entry(((struct w83627hf_data *) (client->data))->
36577 +                                sysctl_id);
36578 +
36579 +       if ((err = i2c_detach_client(client))) {
36580 +               printk
36581 +                   (KERN_ERR "w83627hf.o: Client deregistration failed, client not detached.\n");
36582 +               return err;
36583 +       }
36584 +
36585 +       release_region(client->addr, WINB_EXTENT);
36586 +       kfree(client->data);
36587 +
36588 +       return 0;
36589 +}
36590 +
36591 +
36592 +/*
36593 +   ISA access must always be locked explicitly! 
36594 +   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
36595 +   would slow down the W83781D access and should not be necessary. 
36596 +   There are some ugly typecasts here, but the good news is - they should
36597 +   nowhere else be necessary! */
36598 +static int w83627hf_read_value(struct i2c_client *client, u16 reg)
36599 +{
36600 +       int res, word_sized;
36601 +
36602 +       down(&(((struct w83627hf_data *) (client->data))->lock));
36603 +       word_sized = (((reg & 0xff00) == 0x100)
36604 +                     || ((reg & 0xff00) == 0x200))
36605 +           && (((reg & 0x00ff) == 0x50)
36606 +               || ((reg & 0x00ff) == 0x53)
36607 +               || ((reg & 0x00ff) == 0x55));
36608 +       if (reg & 0xff00) {
36609 +               outb_p(W83781D_REG_BANK,
36610 +                      client->addr + W83781D_ADDR_REG_OFFSET);
36611 +               outb_p(reg >> 8,
36612 +                      client->addr + W83781D_DATA_REG_OFFSET);
36613 +       }
36614 +       outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
36615 +       res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
36616 +       if (word_sized) {
36617 +               outb_p((reg & 0xff) + 1,
36618 +                      client->addr + W83781D_ADDR_REG_OFFSET);
36619 +               res =
36620 +                   (res << 8) + inb_p(client->addr +
36621 +                                      W83781D_DATA_REG_OFFSET);
36622 +       }
36623 +       if (reg & 0xff00) {
36624 +               outb_p(W83781D_REG_BANK,
36625 +                      client->addr + W83781D_ADDR_REG_OFFSET);
36626 +               outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
36627 +       }
36628 +       up(&(((struct w83627hf_data *) (client->data))->lock));
36629 +       return res;
36630 +}
36631 +
36632 +static int w83627thf_read_gpio5(struct i2c_client *client)
36633 +{
36634 +       int res, inv;
36635 +
36636 +       down(&(((struct w83627hf_data *) (client->data))->lock));
36637 +       superio_enter();
36638 +       superio_select(W83627HF_LD_GPIO5);
36639 +       res = superio_inb(W83627THF_GPIO5_DR);
36640 +       inv = superio_inb(W83627THF_GPIO5_INVR);
36641 +       superio_exit();
36642 +       up(&(((struct w83627hf_data *) (client->data))->lock));
36643 +       return res;
36644 +}
36645 +
36646 +static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
36647 +{
36648 +       int word_sized;
36649 +
36650 +       down(&(((struct w83627hf_data *) (client->data))->lock));
36651 +       word_sized = (((reg & 0xff00) == 0x100)
36652 +                     || ((reg & 0xff00) == 0x200))
36653 +           && (((reg & 0x00ff) == 0x53)
36654 +               || ((reg & 0x00ff) == 0x55));
36655 +       if (reg & 0xff00) {
36656 +               outb_p(W83781D_REG_BANK,
36657 +                      client->addr + W83781D_ADDR_REG_OFFSET);
36658 +               outb_p(reg >> 8,
36659 +                      client->addr + W83781D_DATA_REG_OFFSET);
36660 +       }
36661 +       outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
36662 +       if (word_sized) {
36663 +               outb_p(value >> 8,
36664 +                      client->addr + W83781D_DATA_REG_OFFSET);
36665 +               outb_p((reg & 0xff) + 1,
36666 +                      client->addr + W83781D_ADDR_REG_OFFSET);
36667 +       }
36668 +       outb_p(value & 0xff,
36669 +              client->addr + W83781D_DATA_REG_OFFSET);
36670 +       if (reg & 0xff00) {
36671 +               outb_p(W83781D_REG_BANK,
36672 +                      client->addr + W83781D_ADDR_REG_OFFSET);
36673 +               outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
36674 +       }
36675 +       up(&(((struct w83627hf_data *) (client->data))->lock));
36676 +       return 0;
36677 +}
36678 +
36679 +/* Called when we have found a new W83781D. It should set limits, etc. */
36680 +static void w83627hf_init_client(struct i2c_client *client)
36681 +{
36682 +       struct w83627hf_data *data = client->data;
36683 +       int i;
36684 +       int type = data->type;
36685 +       u8 tmp;
36686 +
36687 +       /* Minimize conflicts with other winbond i2c-only clients...  */
36688 +       /* disable i2c subclients... how to disable main i2c client?? */
36689 +       /* force i2c address to relatively uncommon address */
36690 +       w83627hf_write_value(client, W83781D_REG_I2C_SUBADDR, 0x89);
36691 +       w83627hf_write_value(client, W83781D_REG_I2C_ADDR, force_i2c);
36692 +
36693 +       /* Read VID only once */
36694 +       if (w83627hf == data->type || w83637hf == data->type) {
36695 +               int lo = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
36696 +               int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
36697 +               data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
36698 +       } else if (w83627thf == data->type) {
36699 +               data->vid = w83627thf_read_gpio5(client) & 0x1f;
36700 +       }
36701 +
36702 +       /* Read VRM & OVT Config only once */
36703 +       if (w83627thf == data->type || w83637hf == data->type)
36704 +               data->vrm_ovt =
36705 +                       w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
36706 +       else
36707 +               data->vrm_ovt = 0;
36708 +
36709 +       /* Choose VRM based on "VRM & OVT" register */
36710 +       data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
36711 +
36712 +       tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
36713 +       for (i = 1; i <= 3; i++) {
36714 +               if (!(tmp & BIT_SCFG1[i - 1])) {
36715 +                       data->sens[i - 1] = W83781D_DEFAULT_BETA;
36716 +               } else {
36717 +                       if (w83627hf_read_value
36718 +                           (client,
36719 +                            W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
36720 +                               data->sens[i - 1] = 1;
36721 +                       else
36722 +                               data->sens[i - 1] = 2;
36723 +               }
36724 +               if ((type == w83697hf) && (i == 2))
36725 +                       break;
36726 +       }
36727 +
36728 +       data->pwmenable[0] = 1;
36729 +       data->pwmenable[1] = 1;
36730 +       data->pwmenable[2] = 1;
36731 +
36732 +       if(init) {
36733 +               if (type == w83627hf) {
36734 +                       /* enable PWM2 control (can't hurt since PWM reg
36735 +                          should have been reset to 0xff) */
36736 +                       w83627hf_write_value(client, W83627HF_REG_PWMCLK12, 0x19);
36737 +               }
36738 +               /* enable comparator mode for temp2 and temp3 so
36739 +                  alarm indication will work correctly */
36740 +               i = w83627hf_read_value(client, W83781D_REG_IRQ);
36741 +               if (!(i & 0x40))
36742 +                       w83627hf_write_value(client, W83781D_REG_IRQ,
36743 +                                           i | 0x40);
36744 +       }
36745 +
36746 +       /* Start monitoring */
36747 +       w83627hf_write_value(client, W83781D_REG_CONFIG,
36748 +                           (w83627hf_read_value(client,
36749 +                                               W83781D_REG_CONFIG) & 0xf7)
36750 +                           | 0x01);
36751 +}
36752 +
36753 +static void w83627hf_update_client(struct i2c_client *client)
36754 +{
36755 +       struct w83627hf_data *data = client->data;
36756 +       int i;
36757 +
36758 +       down(&data->update_lock);
36759 +
36760 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
36761 +           (jiffies < data->last_updated) || !data->valid) {
36762 +               for (i = 0; i <= 8; i++) {
36763 +                       /* skip missing sensors */
36764 +                       if (((data->type == w83697hf) && (i == 1)) ||
36765 +                           ((data->type == w83627thf || data->type == w83637hf) &&
36766 +                            (i == 4 || i == 5)))
36767 +                               continue;
36768 +                       data->in[i] =
36769 +                           w83627hf_read_value(client, W83781D_REG_IN(i));
36770 +                       data->in_min[i] =
36771 +                           w83627hf_read_value(client,
36772 +                                              W83781D_REG_IN_MIN(i));
36773 +                       data->in_max[i] =
36774 +                           w83627hf_read_value(client,
36775 +                                              W83781D_REG_IN_MAX(i));
36776 +               }
36777 +               for (i = 1; i <= 3; i++) {
36778 +                       data->fan[i - 1] =
36779 +                           w83627hf_read_value(client, W83781D_REG_FAN(i));
36780 +                       data->fan_min[i - 1] =
36781 +                           w83627hf_read_value(client,
36782 +                                              W83781D_REG_FAN_MIN(i));
36783 +               }
36784 +               for (i = 1; i <= 3; i++) {
36785 +                       u8 tmp = w83627hf_read_value(client,
36786 +                               W836X7HF_REG_PWM(data->type, i));
36787 +                       if (data->type == w83627thf)
36788 +                               tmp &= 0xf0; /* bits 0-3 are reserved  in 627THF */
36789 +                       data->pwm[i - 1] = tmp;
36790 +                       if(i == 2 && (data->type == w83627hf || data->type == w83697hf))
36791 +                               break;
36792 +               }
36793 +
36794 +               data->temp = w83627hf_read_value(client, W83781D_REG_TEMP);
36795 +               data->temp_over =
36796 +                   w83627hf_read_value(client, W83781D_REG_TEMP_OVER);
36797 +               data->temp_hyst =
36798 +                   w83627hf_read_value(client, W83781D_REG_TEMP_HYST);
36799 +               data->temp_add[0] =
36800 +                   w83627hf_read_value(client, W83781D_REG_TEMP2);
36801 +               data->temp_add_over[0] =
36802 +                   w83627hf_read_value(client, W83781D_REG_TEMP2_OVER);
36803 +               data->temp_add_hyst[0] =
36804 +                   w83627hf_read_value(client, W83781D_REG_TEMP2_HYST);
36805 +               if (data->type != w83697hf) {
36806 +                       data->temp_add[1] =
36807 +                           w83627hf_read_value(client, W83781D_REG_TEMP3);
36808 +                       data->temp_add_over[1] =
36809 +                           w83627hf_read_value(client, W83781D_REG_TEMP3_OVER);
36810 +                       data->temp_add_hyst[1] =
36811 +                           w83627hf_read_value(client, W83781D_REG_TEMP3_HYST);
36812 +               }
36813 +
36814 +               i = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
36815 +               data->fan_div[0] = (i >> 4) & 0x03;
36816 +               data->fan_div[1] = (i >> 6) & 0x03;
36817 +               if (data->type != w83697hf) {
36818 +                       data->fan_div[2] = (w83627hf_read_value(client,
36819 +                                              W83781D_REG_PIN) >> 6) & 0x03;
36820 +               }
36821 +               i = w83627hf_read_value(client, W83781D_REG_VBAT);
36822 +               data->fan_div[0] |= (i >> 3) & 0x04;
36823 +               data->fan_div[1] |= (i >> 4) & 0x04;
36824 +               if (data->type != w83697hf)
36825 +                       data->fan_div[2] |= (i >> 5) & 0x04;
36826 +               data->alarms =
36827 +                   w83627hf_read_value(client, W83781D_REG_ALARM1) |
36828 +                   (w83627hf_read_value(client, W83781D_REG_ALARM2) << 8) |
36829 +                   (w83627hf_read_value(client, W83781D_REG_ALARM3) << 16);
36830 +               i = w83627hf_read_value(client, W83781D_REG_BEEP_INTS2);
36831 +               data->beep_enable = i >> 7;
36832 +               data->beeps = ((i & 0x7f) << 8) |
36833 +                   w83627hf_read_value(client, W83781D_REG_BEEP_INTS1) |
36834 +                   w83627hf_read_value(client, W83781D_REG_BEEP_INTS3) << 16;
36835 +               data->last_updated = jiffies;
36836 +               data->valid = 1;
36837 +       }
36838 +
36839 +       up(&data->update_lock);
36840 +}
36841 +
36842 +void w83627hf_in(struct i2c_client *client, int operation, int ctl_name,
36843 +               int *nrels_mag, long *results)
36844 +{
36845 +       struct w83627hf_data *data = client->data;
36846 +       int nr = ctl_name - W83781D_SYSCTL_IN0;
36847 +
36848 +       if (operation == SENSORS_PROC_REAL_INFO)
36849 +               *nrels_mag = 2;
36850 +       else if (operation == SENSORS_PROC_REAL_READ) {
36851 +               w83627hf_update_client(client);
36852 +
36853 +               if (nr == 0 && (data->vrm_ovt & 0x01)) {
36854 +                       /* use VRM9 calculation */
36855 +                       results[0] = IN_FROM_REG_VRM9(data->in_min[0]);
36856 +                       results[1] = IN_FROM_REG_VRM9(data->in_max[0]);
36857 +                       results[2] = IN_FROM_REG_VRM9(data->in[0]);
36858 +
36859 +               } else {
36860 +                       /* use VRM8 (standard) calculation */
36861 +                       results[0] = IN_FROM_REG(data->in_min[nr]);
36862 +                       results[1] = IN_FROM_REG(data->in_max[nr]);
36863 +                       results[2] = IN_FROM_REG(data->in[nr]);
36864 +               }
36865 +
36866 +               *nrels_mag = 3;
36867 +
36868 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
36869 +               if (*nrels_mag >= 1) {
36870 +                       if (nr == 0 && (data->vrm_ovt & 0x01))
36871 +                               /* use VRM9 calculation */
36872 +                               data->in_min[0] = IN_TO_REG_VRM9(results[0]);
36873 +                       else
36874 +                               /* use VRM8 (standard) calculation */
36875 +                               data->in_min[nr] = IN_TO_REG(results[0]);
36876 +
36877 +                       w83627hf_write_value(client, W83781D_REG_IN_MIN(nr),
36878 +                                           data->in_min[nr]);
36879 +               }
36880 +               if (*nrels_mag >= 2) {
36881 +                       if (nr == 0 && (data->vrm_ovt & 0x01))
36882 +                               /* use VRM9 calculation */
36883 +                               data->in_min[0] = IN_TO_REG_VRM9(results[1]);
36884 +                       else
36885 +                               /* use VRM8 (standard) calculation */
36886 +                               data->in_max[nr] = IN_TO_REG(results[1]);
36887 +
36888 +                       w83627hf_write_value(client, W83781D_REG_IN_MAX(nr),
36889 +                                           data->in_max[nr]);
36890 +               }
36891 +       }
36892 +}
36893 +
36894 +void w83627hf_fan(struct i2c_client *client, int operation, int ctl_name,
36895 +                int *nrels_mag, long *results)
36896 +{
36897 +       struct w83627hf_data *data = client->data;
36898 +       int nr = ctl_name - W83781D_SYSCTL_FAN1 + 1;
36899 +
36900 +       if (operation == SENSORS_PROC_REAL_INFO)
36901 +               *nrels_mag = 0;
36902 +       else if (operation == SENSORS_PROC_REAL_READ) {
36903 +               w83627hf_update_client(client);
36904 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
36905 +                                 DIV_FROM_REG(data->fan_div[nr - 1]));
36906 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
36907 +                                 DIV_FROM_REG(data->fan_div[nr - 1]));
36908 +               *nrels_mag = 2;
36909 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
36910 +               if (*nrels_mag >= 1) {
36911 +                       data->fan_min[nr - 1] =
36912 +                            FAN_TO_REG(results[0],
36913 +                                   DIV_FROM_REG(data->fan_div[nr-1]));
36914 +                       w83627hf_write_value(client,
36915 +                                           W83781D_REG_FAN_MIN(nr),
36916 +                                           data->fan_min[nr - 1]);
36917 +               }
36918 +       }
36919 +}
36920 +
36921 +void w83627hf_temp(struct i2c_client *client, int operation, int ctl_name,
36922 +                 int *nrels_mag, long *results)
36923 +{
36924 +       struct w83627hf_data *data = client->data;
36925 +       if (operation == SENSORS_PROC_REAL_INFO)
36926 +               *nrels_mag = 1;
36927 +       else if (operation == SENSORS_PROC_REAL_READ) {
36928 +               w83627hf_update_client(client);
36929 +               results[0] = TEMP_FROM_REG(data->temp_over);
36930 +               results[1] = TEMP_FROM_REG(data->temp_hyst);
36931 +               results[2] = TEMP_FROM_REG(data->temp);
36932 +               *nrels_mag = 3;
36933 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
36934 +               if (*nrels_mag >= 1) {
36935 +                       data->temp_over = TEMP_TO_REG(results[0]);
36936 +                       w83627hf_write_value(client, W83781D_REG_TEMP_OVER,
36937 +                                           data->temp_over);
36938 +               }
36939 +               if (*nrels_mag >= 2) {
36940 +                       data->temp_hyst = TEMP_TO_REG(results[1]);
36941 +                       w83627hf_write_value(client, W83781D_REG_TEMP_HYST,
36942 +                                           data->temp_hyst);
36943 +               }
36944 +       }
36945 +}
36946 +
36947 +void w83627hf_temp_add(struct i2c_client *client, int operation,
36948 +                     int ctl_name, int *nrels_mag, long *results)
36949 +{
36950 +       struct w83627hf_data *data = client->data;
36951 +       int nr = ctl_name - W83781D_SYSCTL_TEMP2;
36952 +
36953 +       if (operation == SENSORS_PROC_REAL_INFO)
36954 +               *nrels_mag = 1;
36955 +       else if (operation == SENSORS_PROC_REAL_READ) {
36956 +               w83627hf_update_client(client);
36957 +                       results[0] =
36958 +                           LM75_TEMP_FROM_REG(data->temp_add_over[nr]);
36959 +                       results[1] =
36960 +                           LM75_TEMP_FROM_REG(data->temp_add_hyst[nr]);
36961 +                       results[2] = LM75_TEMP_FROM_REG(data->temp_add[nr]);
36962 +               *nrels_mag = 3;
36963 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
36964 +               if (*nrels_mag >= 1) {
36965 +                               data->temp_add_over[nr] =
36966 +                                   LM75_TEMP_TO_REG(results[0]);
36967 +                       w83627hf_write_value(client,
36968 +                                           nr ? W83781D_REG_TEMP3_OVER :
36969 +                                           W83781D_REG_TEMP2_OVER,
36970 +                                           data->temp_add_over[nr]);
36971 +               }
36972 +               if (*nrels_mag >= 2) {
36973 +                               data->temp_add_hyst[nr] =
36974 +                                   LM75_TEMP_TO_REG(results[1]);
36975 +                       w83627hf_write_value(client,
36976 +                                           nr ? W83781D_REG_TEMP3_HYST :
36977 +                                           W83781D_REG_TEMP2_HYST,
36978 +                                           data->temp_add_hyst[nr]);
36979 +               }
36980 +       }
36981 +}
36982 +
36983 +void w83627hf_vid(struct i2c_client *client, int operation, int ctl_name,
36984 +                int *nrels_mag, long *results)
36985 +{
36986 +       struct w83627hf_data *data = client->data;
36987 +       if (operation == SENSORS_PROC_REAL_INFO)
36988 +               *nrels_mag = 3;
36989 +       else if (operation == SENSORS_PROC_REAL_READ) {
36990 +               w83627hf_update_client(client);
36991 +               results[0] = vid_from_reg(data->vid, data->vrm);
36992 +               *nrels_mag = 1;
36993 +       }
36994 +}
36995 +
36996 +void w83627hf_vrm(struct i2c_client *client, int operation, int ctl_name,
36997 +                int *nrels_mag, long *results)
36998 +{
36999 +       struct w83627hf_data *data = client->data;
37000 +       if (operation == SENSORS_PROC_REAL_INFO)
37001 +               *nrels_mag = 1;
37002 +       else if (operation == SENSORS_PROC_REAL_READ) {
37003 +               results[0] = data->vrm;
37004 +               *nrels_mag = 1;
37005 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
37006 +               if (*nrels_mag >= 1)
37007 +                       data->vrm = results[0];
37008 +       }
37009 +}
37010 +
37011 +void w83627hf_alarms(struct i2c_client *client, int operation, int ctl_name,
37012 +                   int *nrels_mag, long *results)
37013 +{
37014 +       struct w83627hf_data *data = client->data;
37015 +       if (operation == SENSORS_PROC_REAL_INFO)
37016 +               *nrels_mag = 0;
37017 +       else if (operation == SENSORS_PROC_REAL_READ) {
37018 +               w83627hf_update_client(client);
37019 +               results[0] = data->alarms;
37020 +               *nrels_mag = 1;
37021 +       }
37022 +}
37023 +
37024 +void w83627hf_beep(struct i2c_client *client, int operation, int ctl_name,
37025 +                 int *nrels_mag, long *results)
37026 +{
37027 +       struct w83627hf_data *data = client->data;
37028 +       int val;
37029 +
37030 +       if (operation == SENSORS_PROC_REAL_INFO)
37031 +               *nrels_mag = 0;
37032 +       else if (operation == SENSORS_PROC_REAL_READ) {
37033 +               w83627hf_update_client(client);
37034 +               results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable);
37035 +               results[1] = data->beeps;
37036 +               *nrels_mag = 2;
37037 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
37038 +               if (*nrels_mag >= 2) {
37039 +                       data->beeps = BEEPS_TO_REG(results[1]);
37040 +                       w83627hf_write_value(client, W83781D_REG_BEEP_INTS1,
37041 +                                           data->beeps & 0xff);
37042 +                               w83627hf_write_value(client,
37043 +                                                   W83781D_REG_BEEP_INTS3,
37044 +                                                   ((data-> beeps) >> 16) &
37045 +                                                     0xff);
37046 +                       val = (data->beeps >> 8) & 0x7f;
37047 +               } else if (*nrels_mag >= 1)
37048 +                       val =
37049 +                           w83627hf_read_value(client,
37050 +                                              W83781D_REG_BEEP_INTS2) &
37051 +                           0x7f;
37052 +               if (*nrels_mag >= 1) {
37053 +                       data->beep_enable = BEEP_ENABLE_TO_REG(results[0]);
37054 +                       w83627hf_write_value(client, W83781D_REG_BEEP_INTS2,
37055 +                                           val | data->beep_enable << 7);
37056 +               }
37057 +       }
37058 +}
37059 +
37060 +/* w83697hf only has two fans */
37061 +void w83627hf_fan_div(struct i2c_client *client, int operation,
37062 +                    int ctl_name, int *nrels_mag, long *results)
37063 +{
37064 +       struct w83627hf_data *data = client->data;
37065 +       int old, old2, old3 = 0;
37066 +
37067 +       if (operation == SENSORS_PROC_REAL_INFO)
37068 +               *nrels_mag = 0;
37069 +       else if (operation == SENSORS_PROC_REAL_READ) {
37070 +               w83627hf_update_client(client);
37071 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
37072 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
37073 +               if (data->type == w83697hf) {
37074 +                       *nrels_mag = 2;
37075 +               } else {
37076 +                       results[2] = DIV_FROM_REG(data->fan_div[2]);
37077 +                       *nrels_mag = 3;
37078 +               }
37079 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
37080 +               old = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
37081 +               /* w83627hf doesn't have extended divisor bits */
37082 +                       old3 =
37083 +                           w83627hf_read_value(client, W83781D_REG_VBAT);
37084 +               if (*nrels_mag >= 3 && data->type != w83697hf) {
37085 +                       data->fan_div[2] =
37086 +                           DIV_TO_REG(results[2]);
37087 +                       old2 = w83627hf_read_value(client, W83781D_REG_PIN);
37088 +                       old2 =
37089 +                           (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
37090 +                       w83627hf_write_value(client, W83781D_REG_PIN, old2);
37091 +                               old3 =
37092 +                                   (old3 & 0x7f) |
37093 +                                   ((data->fan_div[2] & 0x04) << 5);
37094 +               }
37095 +               if (*nrels_mag >= 2) {
37096 +                       data->fan_div[1] =
37097 +                           DIV_TO_REG(results[1]);
37098 +                       old =
37099 +                           (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
37100 +                               old3 =
37101 +                                   (old3 & 0xbf) |
37102 +                                   ((data->fan_div[1] & 0x04) << 4);
37103 +               }
37104 +               if (*nrels_mag >= 1) {
37105 +                       data->fan_div[0] =
37106 +                           DIV_TO_REG(results[0]);
37107 +                       old =
37108 +                           (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
37109 +                       w83627hf_write_value(client, W83781D_REG_VID_FANDIV,
37110 +                                           old);
37111 +                               old3 =
37112 +                                   (old3 & 0xdf) |
37113 +                                   ((data->fan_div[0] & 0x04) << 3);
37114 +                               w83627hf_write_value(client,
37115 +                                                   W83781D_REG_VBAT,
37116 +                                                   old3);
37117 +               }
37118 +       }
37119 +}
37120 +
37121 +/* we do not currently support disabling PWM with 2nd argument;
37122 +  set first argument to 255 to disable */
37123 +void w83627hf_pwm(struct i2c_client *client, int operation, int ctl_name,
37124 +                int *nrels_mag, long *results)
37125 +{
37126 +       struct w83627hf_data *data = client->data;
37127 +       int nr = 1 + ctl_name - W83781D_SYSCTL_PWM1;
37128 +
37129 +       if (operation == SENSORS_PROC_REAL_INFO)
37130 +               *nrels_mag = 0;
37131 +       else if (operation == SENSORS_PROC_REAL_READ) {
37132 +               w83627hf_update_client(client);
37133 +               results[0] = data->pwm[nr - 1];
37134 +               results[1] = data->pwmenable[nr - 1];
37135 +               *nrels_mag = 2;
37136 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
37137 +               if (*nrels_mag >= 1) {
37138 +                       if (data->type == w83627thf) {
37139 +                               /* bits 0-3 are reserved  in 627THF */
37140 +                               data->pwm[nr - 1] = PWM_TO_REG(results[0]) & 0xf0;
37141 +                               w83627hf_write_value(client,
37142 +                                                    W836X7HF_REG_PWM(data->type, nr),
37143 +                                                    data->pwm[nr - 1] |
37144 +                                                    (w83627hf_read_value(client,
37145 +                                                     W836X7HF_REG_PWM(data->type, nr)) & 0x0f));
37146 +                       } else {
37147 +                               data->pwm[nr - 1] = PWM_TO_REG(results[0]);
37148 +                               w83627hf_write_value(client,
37149 +                                                    W836X7HF_REG_PWM(data->type, nr),
37150 +                                                    data->pwm[nr - 1]);
37151 +                       }
37152 +               }
37153 +       }
37154 +}
37155 +
37156 +void w83627hf_sens(struct i2c_client *client, int operation, int ctl_name,
37157 +                 int *nrels_mag, long *results)
37158 +{
37159 +       struct w83627hf_data *data = client->data;
37160 +       int nr = 1 + ctl_name - W83781D_SYSCTL_SENS1;
37161 +       u8 tmp;
37162 +
37163 +       if (operation == SENSORS_PROC_REAL_INFO)
37164 +               *nrels_mag = 0;
37165 +       else if (operation == SENSORS_PROC_REAL_READ) {
37166 +               results[0] = data->sens[nr - 1];
37167 +               *nrels_mag = 1;
37168 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
37169 +               if (*nrels_mag >= 1) {
37170 +                       switch (results[0]) {
37171 +                       case 1: /* PII/Celeron diode */
37172 +                               tmp = w83627hf_read_value(client,
37173 +                                                      W83781D_REG_SCFG1);
37174 +                               w83627hf_write_value(client,
37175 +                                                   W83781D_REG_SCFG1,
37176 +                                                   tmp | BIT_SCFG1[nr -
37177 +                                                                   1]);
37178 +                               tmp = w83627hf_read_value(client,
37179 +                                                      W83781D_REG_SCFG2);
37180 +                               w83627hf_write_value(client,
37181 +                                                   W83781D_REG_SCFG2,
37182 +                                                   tmp | BIT_SCFG2[nr -
37183 +                                                                   1]);
37184 +                               data->sens[nr - 1] = results[0];
37185 +                               break;
37186 +                       case 2: /* 3904 */
37187 +                               tmp = w83627hf_read_value(client,
37188 +                                                      W83781D_REG_SCFG1);
37189 +                               w83627hf_write_value(client,
37190 +                                                   W83781D_REG_SCFG1,
37191 +                                                   tmp | BIT_SCFG1[nr -
37192 +                                                                   1]);
37193 +                               tmp = w83627hf_read_value(client,
37194 +                                                      W83781D_REG_SCFG2);
37195 +                               w83627hf_write_value(client,
37196 +                                                   W83781D_REG_SCFG2,
37197 +                                                   tmp & ~BIT_SCFG2[nr -
37198 +                                                                    1]);
37199 +                               data->sens[nr - 1] = results[0];
37200 +                               break;
37201 +                       case W83781D_DEFAULT_BETA:      /* thermistor */
37202 +                               tmp = w83627hf_read_value(client,
37203 +                                                      W83781D_REG_SCFG1);
37204 +                               w83627hf_write_value(client,
37205 +                                                   W83781D_REG_SCFG1,
37206 +                                                   tmp & ~BIT_SCFG1[nr -
37207 +                                                                    1]);
37208 +                               data->sens[nr - 1] = results[0];
37209 +                               break;
37210 +                       default:
37211 +                               printk
37212 +                                   (KERN_ERR "w83627hf.o: Invalid sensor type %ld; must be 1, 2, or %d\n",
37213 +                                    results[0], W83781D_DEFAULT_BETA);
37214 +                               break;
37215 +                       }
37216 +               }
37217 +       }
37218 +}
37219 +
37220 +static int __init sm_w83627hf_init(void)
37221 +{
37222 +       int addr;
37223 +
37224 +       printk(KERN_INFO "w83627hf.o version %s (%s)\n", LM_VERSION, LM_DATE);
37225 +       if (w83627hf_find(&addr)) {
37226 +               printk("w83627hf.o: W83627/697 not detected, module not inserted.\n");
37227 +               return -ENODEV;
37228 +       }
37229 +       normal_isa[0] = addr;
37230 +
37231 +       return i2c_add_driver(&w83627hf_driver);
37232 +}
37233 +
37234 +static void __exit sm_w83627hf_exit(void)
37235 +{
37236 +       i2c_del_driver(&w83627hf_driver);
37237 +}
37238 +
37239 +
37240 +
37241 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
37242 +             "Philip Edelbrock <phil@netroedge.com>, "
37243 +             "and Mark Studebaker <mdsxyz123@yahoo.com>");
37244 +MODULE_DESCRIPTION("W83627HF driver");
37245 +MODULE_LICENSE("GPL");
37246 +
37247 +module_init(sm_w83627hf_init);
37248 +module_exit(sm_w83627hf_exit);
37249 --- linux-old/drivers/sensors/w83781d.c Thu Jan  1 00:00:00 1970
37250 +++ linux/drivers/sensors/w83781d.c     Mon Dec 13 20:18:54 2004
37251 @@ -0,0 +1,1957 @@
37252 +/*
37253 +    w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
37254 +                monitoring
37255 +    Copyright (c) 1998 - 2003  Frodo Looijaard <frodol@dds.nl>,
37256 +    Philip Edelbrock <phil@netroedge.com>,
37257 +    and Mark Studebaker <mdsxyz123@yahoo.com>
37258 +
37259 +    This program is free software; you can redistribute it and/or modify
37260 +    it under the terms of the GNU General Public License as published by
37261 +    the Free Software Foundation; either version 2 of the License, or
37262 +    (at your option) any later version.
37263 +
37264 +    This program is distributed in the hope that it will be useful,
37265 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
37266 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37267 +    GNU General Public License for more details.
37268 +
37269 +    You should have received a copy of the GNU General Public License
37270 +    along with this program; if not, write to the Free Software
37271 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37272 +*/
37273 +
37274 +/*
37275 +    Supports following chips:
37276 +
37277 +    Chip       #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
37278 +    as99127f   7       3       0       3       0x31    0x12c3  yes     no
37279 +    as99127f rev.2 (type name = as99127f)      0x31    0x5ca3  yes     no
37280 +    w83627hf   9       3       2       3       0x21    0x5ca3  yes     yes(LPC)
37281 +    w83697hf   8       2       2       2       0x60    0x5ca3  no      yes(LPC)
37282 +    w83781d    7       3       0       3       0x10-1  0x5ca3  yes     yes
37283 +    w83782d    9       3       2-4     3       0x30    0x5ca3  yes     yes
37284 +    w83783s    5-6     3       2       1-2     0x40    0x5ca3  yes     no
37285 +    w83791d    10      5       5       3       0x71    0x5ca3  yes     no
37286 +
37287 +*/
37288 +
37289 +#include <linux/module.h>
37290 +#include <linux/slab.h>
37291 +#include <linux/ioport.h>
37292 +#include <linux/i2c.h>
37293 +#include <linux/i2c-proc.h>
37294 +#include <linux/init.h>
37295 +#include <asm/io.h>
37296 +#define LM_DATE "20041007"
37297 +#define LM_VERSION "2.8.8"
37298 +#include <linux/sensors_vid.h>
37299 +#include "lm75.h"
37300 +
37301 +/* RT Table support #defined so we can take it out if it gets bothersome */
37302 +#define W83781D_RT 1
37303 +
37304 +/* Addresses to scan */
37305 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
37306 +static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
37307 +static unsigned int normal_isa[] = { 0x0290, SENSORS_ISA_END };
37308 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
37309 +
37310 +/* Insmod parameters */
37311 +SENSORS_INSMOD_7(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf, w83791d);
37312 +SENSORS_MODULE_PARM(force_subclients, "List of subclient addresses: " \
37313 +                      "{bus, clientaddr, subclientaddr1, subclientaddr2}");
37314 +
37315 +static int init = 1;
37316 +MODULE_PARM(init, "i");
37317 +MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
37318 +
37319 +/* Constants specified below */
37320 +
37321 +/* Length of ISA address segment */
37322 +#define W83781D_EXTENT 8
37323 +
37324 +/* Where are the ISA address/data registers relative to the base address */
37325 +#define W83781D_ADDR_REG_OFFSET 5
37326 +#define W83781D_DATA_REG_OFFSET 6
37327 +
37328 +/* The W83781D registers */
37329 +/* The W83782D registers for nr=7,8 are in bank 5 */
37330 +#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
37331 +                                          (0x554 + (((nr) - 7) * 2)))
37332 +#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
37333 +                                          (0x555 + (((nr) - 7) * 2)))
37334 +#define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
37335 +                                          (0x550 + (nr) - 7))
37336 +
37337 +#define W83791D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \
37338 +                                          (0xb4 + (((nr) - 7) * 2)))
37339 +#define W83791D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \
37340 +                                          (0xb5 + (((nr) - 7) * 2)))
37341 +#define W83791D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
37342 +                                          (0xb0 + (nr) - 7))
37343 +
37344 +#define W83781D_REG_FAN_MIN(nr) ((nr < 4) ? (0x3a + (nr)) : \
37345 +                                            (0xba + (nr) - 4))
37346 +#define W83781D_REG_FAN(nr)     ((nr < 4) ? (0x27 + (nr)) : \
37347 +                                            (0xbc + (nr) - 4))
37348 +
37349 +#define W83781D_REG_TEMP2 0x0150
37350 +#define W83781D_REG_TEMP3 0x0250
37351 +#define W83781D_REG_TEMP2_HYST 0x153
37352 +#define W83781D_REG_TEMP3_HYST 0x253
37353 +#define W83781D_REG_TEMP2_CONFIG 0x152
37354 +#define W83781D_REG_TEMP3_CONFIG 0x252
37355 +#define W83781D_REG_TEMP2_OVER 0x155
37356 +#define W83781D_REG_TEMP3_OVER 0x255
37357 +
37358 +#define W83781D_REG_TEMP 0x27
37359 +#define W83781D_REG_TEMP_OVER 0x39
37360 +#define W83781D_REG_TEMP_HYST 0x3A
37361 +#define W83781D_REG_BANK 0x4E
37362 +
37363 +#define W83781D_REG_CONFIG 0x40
37364 +#define W83781D_REG_ALARM1 0x41
37365 +#define W83781D_REG_ALARM2 0x42
37366 +#define W83781D_REG_ALARM3 0x450       /* not on W83781D */
37367 +
37368 +#define W83781D_REG_IRQ 0x4C
37369 +#define W83781D_REG_BEEP_CONFIG 0x4D
37370 +#define W83781D_REG_BEEP_INTS1 0x56
37371 +#define W83781D_REG_BEEP_INTS2 0x57
37372 +#define W83781D_REG_BEEP_INTS3 0x453   /* not on W83781D */
37373 +
37374 +#define W83781D_REG_VID_FANDIV 0x47
37375 +
37376 +#define W83781D_REG_CHIPID 0x49
37377 +#define W83781D_REG_WCHIPID 0x58
37378 +#define W83781D_REG_CHIPMAN 0x4F
37379 +#define W83781D_REG_PIN 0x4B
37380 +
37381 +/* 782D/783S only */
37382 +#define W83781D_REG_VBAT 0x5D
37383 +
37384 +/* PWM 782D (1-4) and 783S (1-2) only */
37385 +#define W83781D_REG_PWM1 0x5B  /* 782d and 783s/627hf datasheets disagree */
37386 +                               /* on which is which; */
37387 +#define W83781D_REG_PWM2 0x5A  /* We follow the 782d convention here, */
37388 +                               /* However 782d is probably wrong. */
37389 +#define W83781D_REG_PWM3 0x5E
37390 +#define W83781D_REG_PWM4 0x5F
37391 +#define W83781D_REG_PWMCLK12 0x5C
37392 +#define W83781D_REG_PWMCLK34 0x45C
37393 +
37394 +#define W83791D_REG_PWM1 0x81
37395 +#define W83791D_REG_PWM2 0x83
37396 +#define W83791D_REG_PWM3 0x94
37397 +
37398 +#define W83627HF_REG_PWM1 0x01
37399 +#define W83627HF_REG_PWM2 0x03
37400 +#define W83627HF_REG_PWMCLK1 0x00
37401 +#define W83627HF_REG_PWMCLK2 0x02
37402 +
37403 +static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2,
37404 +       W83781D_REG_PWM3, W83781D_REG_PWM4
37405 +};
37406 +
37407 +static const u8 regpwm_w83791d[] = { W83791D_REG_PWM1, W83791D_REG_PWM2,
37408 +                                   W83791D_REG_PWM3
37409 +};
37410 +        
37411 +#define W83781D_REG_PWM(type, nr) (((type) == w83791d) ? \
37412 +                                         regpwm_w83791d[(nr) - 1] : \
37413 +                                   ((type) == w83697hf) ? \
37414 +                                         (((nr) * 2) - 1) : \
37415 +                                         regpwm[(nr) - 1])
37416 +
37417 +#define W83781D_REG_I2C_ADDR 0x48
37418 +#define W83781D_REG_I2C_SUBADDR 0x4A
37419 +
37420 +/* The following are undocumented in the data sheets however we
37421 +   received the information in an email from Winbond tech support */
37422 +/* Sensor selection - not on 781d */
37423 +#define W83781D_REG_SCFG1 0x5D
37424 +static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
37425 +#define W83781D_REG_SCFG2 0x59
37426 +static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
37427 +#define W83781D_DEFAULT_BETA 3435
37428 +
37429 +/* RT Table registers */
37430 +#define W83781D_REG_RT_IDX 0x50
37431 +#define W83781D_REG_RT_VAL 0x51
37432 +
37433 +/* Conversions. Rounding and limit checking is only done on the TO_REG
37434 +   variants. Note that you should be a bit careful with which arguments
37435 +   these macros are called: arguments may be evaluated more than once.
37436 +   Fixing this is just not worth it. */
37437 +#define IN_TO_REG(val)  (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
37438 +#define IN_FROM_REG(val) (((val) * 16 + 5) / 10)
37439 +
37440 +static inline u8 FAN_TO_REG(long rpm, int div)
37441 +{
37442 +       if (rpm == 0)
37443 +               return 255;
37444 +       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
37445 +       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
37446 +                            254);
37447 +}
37448 +
37449 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
37450 +
37451 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
37452 +                                                 ((val)+5)/10),0,255))
37453 +#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
37454 +
37455 +#define AS99127_TEMP_ADD_TO_REG(val) (SENSORS_LIMIT((((((val) + 2)*4)/10) \
37456 +                                               << 7),0,0xffff))
37457 +#define AS99127_TEMP_ADD_FROM_REG(val) ((((val) >> 7) * 10) / 4)
37458 +
37459 +#define ALARMS_FROM_REG(val) (val)
37460 +#define PWM_FROM_REG(val) (val)
37461 +#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
37462 +#define BEEPS_FROM_REG(val,type) ((type)==as99127f?(val)^0x7FFF:(val))
37463 +#define BEEPS_TO_REG(val,type) ((type)==as99127f?(~(val))&0x7FFF:(val)&0xffffff)
37464 +
37465 +#define BEEP_ENABLE_TO_REG(val)   ((val)?1:0)
37466 +#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0)
37467 +
37468 +#define DIV_FROM_REG(val) (1 << (val))
37469 +
37470 +static inline u8 DIV_TO_REG(long val, enum chips type)
37471 +{
37472 +       int i;
37473 +       val = SENSORS_LIMIT(val, 1,
37474 +               ((type == w83781d || type == as99127f) ? 8 : 128)) >> 1;
37475 +       for (i = 0; i < 6; i++) {
37476 +               if (val == 0)
37477 +                       break;
37478 +               val >>= 1;
37479 +       }
37480 +       return ((u8) i);
37481 +}
37482 +
37483 +/* There are some complications in a module like this. First off, W83781D chips
37484 +   may be both present on the SMBus and the ISA bus, and we have to handle
37485 +   those cases separately at some places. Second, there might be several
37486 +   W83781D chips available (well, actually, that is probably never done; but
37487 +   it is a clean illustration of how to handle a case like that). Finally,
37488 +   a specific chip may be attached to *both* ISA and SMBus, and we would
37489 +   not like to detect it double. Fortunately, in the case of the W83781D at
37490 +   least, a register tells us what SMBus address we are on, so that helps
37491 +   a bit - except if there could be more than one SMBus. Groan. No solution
37492 +   for this yet. */
37493 +
37494 +/* This module may seem overly long and complicated. In fact, it is not so
37495 +   bad. Quite a lot of bookkeeping is done. A real driver can often cut
37496 +   some corners. */
37497 +
37498 +/* For each registered W83781D, we need to keep some data in memory. That
37499 +   data is pointed to by w83781d_list[NR]->data. The structure itself is
37500 +   dynamically allocated, at the same time when a new w83781d client is
37501 +   allocated. */
37502 +struct w83781d_data {
37503 +       struct i2c_client client;
37504 +       struct semaphore lock;
37505 +       int sysctl_id;
37506 +       enum chips type;
37507 +
37508 +       struct semaphore update_lock;
37509 +       char valid;             /* !=0 if following fields are valid */
37510 +       unsigned long last_updated;     /* In jiffies */
37511 +
37512 +       struct i2c_client *lm75;        /* for secondary I2C addresses */
37513 +       /* pointer to array of 2 subclients */
37514 +
37515 +       u8 in[10];              /* Register value - 8 & 9 for 782D and 791D only 10 for 791D */
37516 +       u8 in_max[10];          /* Register value - 8 & 9 for 782D and 791D only 10 for 791D */
37517 +       u8 in_min[10];          /* Register value - 8 & 9 for 782D and 791D only 10 for 791D */
37518 +       u8 fan[5];              /* Register value - 4 & 5 for 791D only */
37519 +       u8 fan_min[5];          /* Register value - 4 & 5 for 791D only */
37520 +       u8 temp;
37521 +       u8 temp_over;           /* Register value */
37522 +       u8 temp_hyst;           /* Register value */
37523 +       u16 temp_add[2];        /* Register value */
37524 +       u16 temp_add_over[2];   /* Register value */
37525 +       u16 temp_add_hyst[2];   /* Register value */
37526 +       u8 fan_div[3];          /* Register encoding, shifted right */
37527 +       u8 vid;                 /* Register encoding, combined */
37528 +       u32 alarms;             /* Register encoding, combined */
37529 +       u32 beeps;              /* Register encoding, combined */
37530 +       u8 beep_enable;         /* Boolean */
37531 +       u8 pwm[4];              /* Register value */
37532 +       u8 pwmenable[4];        /* bool */
37533 +       u16 sens[3];            /* 782D/783S only.
37534 +                                  1 = pentium diode; 2 = 3904 diode;
37535 +                                  3000-5000 = thermistor beta.
37536 +                                  Default = 3435. 
37537 +                                  Other Betas unimplemented */
37538 +#ifdef W83781D_RT
37539 +       u8 rt[3][32];           /* Register value */
37540 +#endif
37541 +       u8 vrm;
37542 +};
37543 +
37544 +
37545 +static int w83781d_attach_adapter(struct i2c_adapter *adapter);
37546 +static int w83781d_detect(struct i2c_adapter *adapter, int address,
37547 +                         unsigned short flags, int kind);
37548 +static int w83781d_detach_client(struct i2c_client *client);
37549 +
37550 +static int w83781d_read_value(struct i2c_client *client, u16 register);
37551 +static int w83781d_write_value(struct i2c_client *client, u16 register,
37552 +                              u16 value);
37553 +static void w83781d_update_client(struct i2c_client *client);
37554 +static void w83781d_init_client(struct i2c_client *client);
37555 +
37556 +
37557 +static void w83781d_in(struct i2c_client *client, int operation,
37558 +                      int ctl_name, int *nrels_mag, long *results);
37559 +static void w83781d_fan(struct i2c_client *client, int operation,
37560 +                       int ctl_name, int *nrels_mag, long *results);
37561 +static void w83781d_temp(struct i2c_client *client, int operation,
37562 +                        int ctl_name, int *nrels_mag, long *results);
37563 +static void w83781d_temp_add(struct i2c_client *client, int operation,
37564 +                            int ctl_name, int *nrels_mag, long *results);
37565 +static void w83781d_vid(struct i2c_client *client, int operation,
37566 +                       int ctl_name, int *nrels_mag, long *results);
37567 +static void w83781d_vrm(struct i2c_client *client, int operation,
37568 +                       int ctl_name, int *nrels_mag, long *results);
37569 +static void w83781d_alarms(struct i2c_client *client, int operation,
37570 +                          int ctl_name, int *nrels_mag, long *results);
37571 +static void w83781d_beep(struct i2c_client *client, int operation,
37572 +                        int ctl_name, int *nrels_mag, long *results);
37573 +static void w83781d_fan_div(struct i2c_client *client, int operation,
37574 +                           int ctl_name, int *nrels_mag, long *results);
37575 +static void w83781d_pwm(struct i2c_client *client, int operation,
37576 +                       int ctl_name, int *nrels_mag, long *results);
37577 +static void w83781d_sens(struct i2c_client *client, int operation,
37578 +                        int ctl_name, int *nrels_mag, long *results);
37579 +#ifdef W83781D_RT
37580 +static void w83781d_rt(struct i2c_client *client, int operation,
37581 +                      int ctl_name, int *nrels_mag, long *results);
37582 +#endif
37583 +
37584 +static int w83781d_id = 0;
37585 +
37586 +static struct i2c_driver w83781d_driver = {
37587 +       .owner          = THIS_MODULE,
37588 +       .name           = "W83781D sensor driver",
37589 +       .id             = I2C_DRIVERID_W83781D,
37590 +       .flags          = I2C_DF_NOTIFY,
37591 +       .attach_adapter = w83781d_attach_adapter,
37592 +       .detach_client  = w83781d_detach_client,
37593 +};
37594 +
37595 +/* The /proc/sys entries */
37596 +/* -- SENSORS SYSCTL START -- */
37597 +
37598 +#define W83781D_SYSCTL_IN0 1000        /* Volts * 100 */
37599 +#define W83781D_SYSCTL_IN1 1001
37600 +#define W83781D_SYSCTL_IN2 1002
37601 +#define W83781D_SYSCTL_IN3 1003
37602 +#define W83781D_SYSCTL_IN4 1004
37603 +#define W83781D_SYSCTL_IN5 1005
37604 +#define W83781D_SYSCTL_IN6 1006
37605 +#define W83781D_SYSCTL_IN7 1007
37606 +#define W83781D_SYSCTL_IN8 1008
37607 +#define W83781D_SYSCTL_IN9 1009
37608 +#define W83781D_SYSCTL_FAN1 1101       /* Rotations/min */
37609 +#define W83781D_SYSCTL_FAN2 1102
37610 +#define W83781D_SYSCTL_FAN3 1103
37611 +#define W83781D_SYSCTL_FAN4 1104
37612 +#define W83781D_SYSCTL_FAN5 1105
37613 +
37614 +#define W83781D_SYSCTL_TEMP1 1200      /* Degrees Celcius * 10 */
37615 +#define W83781D_SYSCTL_TEMP2 1201      /* Degrees Celcius * 10 */
37616 +#define W83781D_SYSCTL_TEMP3 1202      /* Degrees Celcius * 10 */
37617 +#define W83781D_SYSCTL_VID 1300                /* Volts * 1000 */
37618 +#define W83781D_SYSCTL_VRM 1301
37619 +#define W83781D_SYSCTL_PWM1 1401
37620 +#define W83781D_SYSCTL_PWM2 1402
37621 +#define W83781D_SYSCTL_PWM3 1403
37622 +#define W83781D_SYSCTL_PWM4 1404
37623 +#define W83781D_SYSCTL_SENS1 1501      /* 1, 2, or Beta (3000-5000) */
37624 +#define W83781D_SYSCTL_SENS2 1502
37625 +#define W83781D_SYSCTL_SENS3 1503
37626 +#define W83781D_SYSCTL_RT1   1601      /* 32-entry table */
37627 +#define W83781D_SYSCTL_RT2   1602      /* 32-entry table */
37628 +#define W83781D_SYSCTL_RT3   1603      /* 32-entry table */
37629 +#define W83781D_SYSCTL_FAN_DIV 2000    /* 1, 2, 4 or 8 */
37630 +#define W83781D_SYSCTL_ALARMS 2001     /* bitvector */
37631 +#define W83781D_SYSCTL_BEEP 2002       /* bitvector */
37632 +
37633 +#define W83781D_ALARM_IN0 0x0001
37634 +#define W83781D_ALARM_IN1 0x0002
37635 +#define W83781D_ALARM_IN2 0x0004
37636 +#define W83781D_ALARM_IN3 0x0008
37637 +#define W83781D_ALARM_IN4 0x0100
37638 +#define W83781D_ALARM_IN5 0x0200
37639 +#define W83781D_ALARM_IN6 0x0400
37640 +#define W83782D_ALARM_IN7 0x10000
37641 +#define W83782D_ALARM_IN8 0x20000
37642 +#define W83781D_ALARM_FAN1 0x0040
37643 +#define W83781D_ALARM_FAN2 0x0080
37644 +#define W83781D_ALARM_FAN3 0x0800
37645 +#define W83781D_ALARM_TEMP1 0x0010
37646 +#define W83781D_ALARM_TEMP23 0x0020    /* 781D only */
37647 +#define W83781D_ALARM_TEMP2 0x0020     /* 782D/783S */
37648 +#define W83781D_ALARM_TEMP3 0x2000     /* 782D only */
37649 +#define W83781D_ALARM_CHAS 0x1000
37650 +
37651 +/* -- SENSORS SYSCTL END -- */
37652 +
37653 +/* These files are created for each detected chip. This is just a template;
37654 +   though at first sight, you might think we could use a statically
37655 +   allocated list, we need some way to get back to the parent - which
37656 +   is done through one of the 'extra' fields which are initialized 
37657 +   when a new copy is allocated. */
37658 +
37659 +/* just a guess - no datasheet */
37660 +static ctl_table as99127f_dir_table_template[] = {
37661 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
37662 +        &i2c_sysctl_real, NULL, &w83781d_in},
37663 +       {W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
37664 +        &i2c_sysctl_real, NULL, &w83781d_in},
37665 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
37666 +        &i2c_sysctl_real, NULL, &w83781d_in},
37667 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
37668 +        &i2c_sysctl_real, NULL, &w83781d_in},
37669 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
37670 +        &i2c_sysctl_real, NULL, &w83781d_in},
37671 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
37672 +        &i2c_sysctl_real, NULL, &w83781d_in},
37673 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
37674 +        &i2c_sysctl_real, NULL, &w83781d_in},
37675 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
37676 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37677 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
37678 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37679 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
37680 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37681 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
37682 +        &i2c_sysctl_real, NULL, &w83781d_temp},
37683 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
37684 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37685 +       {W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
37686 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37687 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
37688 +        &i2c_sysctl_real, NULL, &w83781d_vid},
37689 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
37690 +        &i2c_sysctl_real, NULL, &w83781d_vrm},
37691 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
37692 +        &i2c_sysctl_real, NULL, &w83781d_fan_div},
37693 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
37694 +        &i2c_sysctl_real, NULL, &w83781d_alarms},
37695 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
37696 +        &i2c_sysctl_real, NULL, &w83781d_beep},
37697 +       {0}
37698 +};
37699 +
37700 +static ctl_table w83781d_dir_table_template[] = {
37701 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
37702 +        &i2c_sysctl_real, NULL, &w83781d_in},
37703 +       {W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
37704 +        &i2c_sysctl_real, NULL, &w83781d_in},
37705 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
37706 +        &i2c_sysctl_real, NULL, &w83781d_in},
37707 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
37708 +        &i2c_sysctl_real, NULL, &w83781d_in},
37709 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
37710 +        &i2c_sysctl_real, NULL, &w83781d_in},
37711 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
37712 +        &i2c_sysctl_real, NULL, &w83781d_in},
37713 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
37714 +        &i2c_sysctl_real, NULL, &w83781d_in},
37715 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
37716 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37717 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
37718 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37719 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
37720 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37721 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
37722 +        &i2c_sysctl_real, NULL, &w83781d_temp},
37723 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
37724 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37725 +       {W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
37726 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37727 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
37728 +        &i2c_sysctl_real, NULL, &w83781d_vid},
37729 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
37730 +        &i2c_sysctl_real, NULL, &w83781d_vrm},
37731 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
37732 +        &i2c_sysctl_real, NULL, &w83781d_fan_div},
37733 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
37734 +        &i2c_sysctl_real, NULL, &w83781d_alarms},
37735 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
37736 +        &i2c_sysctl_real, NULL, &w83781d_beep},
37737 +#ifdef W83781D_RT
37738 +       {W83781D_SYSCTL_RT1, "rt1", NULL, 0, 0644, NULL, &i2c_proc_real,
37739 +        &i2c_sysctl_real, NULL, &w83781d_rt},
37740 +       {W83781D_SYSCTL_RT2, "rt2", NULL, 0, 0644, NULL, &i2c_proc_real,
37741 +        &i2c_sysctl_real, NULL, &w83781d_rt},
37742 +       {W83781D_SYSCTL_RT3, "rt3", NULL, 0, 0644, NULL, &i2c_proc_real,
37743 +        &i2c_sysctl_real, NULL, &w83781d_rt},
37744 +#endif
37745 +       {0}
37746 +};
37747 +
37748 +/* without pwm3-4 */
37749 +static ctl_table w83782d_isa_dir_table_template[] = {
37750 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
37751 +        &i2c_sysctl_real, NULL, &w83781d_in},
37752 +       {W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
37753 +        &i2c_sysctl_real, NULL, &w83781d_in},
37754 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
37755 +        &i2c_sysctl_real, NULL, &w83781d_in},
37756 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
37757 +        &i2c_sysctl_real, NULL, &w83781d_in},
37758 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
37759 +        &i2c_sysctl_real, NULL, &w83781d_in},
37760 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
37761 +        &i2c_sysctl_real, NULL, &w83781d_in},
37762 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
37763 +        &i2c_sysctl_real, NULL, &w83781d_in},
37764 +       {W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
37765 +        &i2c_sysctl_real, NULL, &w83781d_in},
37766 +       {W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
37767 +        &i2c_sysctl_real, NULL, &w83781d_in},
37768 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
37769 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37770 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
37771 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37772 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
37773 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37774 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
37775 +        &i2c_sysctl_real, NULL, &w83781d_temp},
37776 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
37777 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37778 +       {W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
37779 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37780 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
37781 +        &i2c_sysctl_real, NULL, &w83781d_vid},
37782 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
37783 +        &i2c_sysctl_real, NULL, &w83781d_vrm},
37784 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
37785 +        &i2c_sysctl_real, NULL, &w83781d_fan_div},
37786 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
37787 +        &i2c_sysctl_real, NULL, &w83781d_alarms},
37788 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
37789 +        &i2c_sysctl_real, NULL, &w83781d_beep},
37790 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
37791 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37792 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
37793 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37794 +       {W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
37795 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37796 +       {W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
37797 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37798 +       {W83781D_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL, &i2c_proc_real,
37799 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37800 +       {0}
37801 +};
37802 +
37803 +/* with pwm3-4 */
37804 +static ctl_table w83782d_i2c_dir_table_template[] = {
37805 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
37806 +        &i2c_sysctl_real, NULL, &w83781d_in},
37807 +       {W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
37808 +        &i2c_sysctl_real, NULL, &w83781d_in},
37809 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
37810 +        &i2c_sysctl_real, NULL, &w83781d_in},
37811 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
37812 +        &i2c_sysctl_real, NULL, &w83781d_in},
37813 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
37814 +        &i2c_sysctl_real, NULL, &w83781d_in},
37815 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
37816 +        &i2c_sysctl_real, NULL, &w83781d_in},
37817 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
37818 +        &i2c_sysctl_real, NULL, &w83781d_in},
37819 +       {W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
37820 +        &i2c_sysctl_real, NULL, &w83781d_in},
37821 +       {W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
37822 +        &i2c_sysctl_real, NULL, &w83781d_in},
37823 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
37824 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37825 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
37826 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37827 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
37828 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37829 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
37830 +        &i2c_sysctl_real, NULL, &w83781d_temp},
37831 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
37832 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37833 +       {W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
37834 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37835 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
37836 +        &i2c_sysctl_real, NULL, &w83781d_vid},
37837 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
37838 +        &i2c_sysctl_real, NULL, &w83781d_vrm},
37839 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
37840 +        &i2c_sysctl_real, NULL, &w83781d_fan_div},
37841 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
37842 +        &i2c_sysctl_real, NULL, &w83781d_alarms},
37843 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
37844 +        &i2c_sysctl_real, NULL, &w83781d_beep},
37845 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
37846 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37847 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
37848 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37849 +       {W83781D_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
37850 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37851 +       {W83781D_SYSCTL_PWM4, "pwm4", NULL, 0, 0644, NULL, &i2c_proc_real,
37852 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37853 +       {W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
37854 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37855 +       {W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
37856 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37857 +       {W83781D_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL, &i2c_proc_real,
37858 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37859 +       {0}
37860 +};
37861 +
37862 +/* w83791D has 10 voltages 5 fans and 3 temps.  2 of the temps are on other 
37863 + devices. */
37864 +static ctl_table w83791d_dir_table_template[] = {
37865 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
37866 +        &i2c_sysctl_real, NULL, &w83781d_in},
37867 +       {W83781D_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
37868 +        &i2c_sysctl_real, NULL, &w83781d_in},
37869 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
37870 +        &i2c_sysctl_real, NULL, &w83781d_in},
37871 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
37872 +        &i2c_sysctl_real, NULL, &w83781d_in},
37873 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
37874 +        &i2c_sysctl_real, NULL, &w83781d_in},
37875 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
37876 +        &i2c_sysctl_real, NULL, &w83781d_in},
37877 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
37878 +        &i2c_sysctl_real, NULL, &w83781d_in},
37879 +       {W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
37880 +        &i2c_sysctl_real, NULL, &w83781d_in},
37881 +       {W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
37882 +        &i2c_sysctl_real, NULL, &w83781d_in},
37883 +       {W83781D_SYSCTL_IN9, "in9", NULL, 0, 0644, NULL, &i2c_proc_real,
37884 +        &i2c_sysctl_real, NULL, &w83781d_in},
37885 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
37886 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37887 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
37888 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37889 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
37890 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37891 +       {W83781D_SYSCTL_FAN4, "fan4", NULL, 0, 0644, NULL, &i2c_proc_real,
37892 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37893 +       {W83781D_SYSCTL_FAN5, "fan5", NULL, 0, 0644, NULL, &i2c_proc_real,
37894 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37895 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
37896 +        &i2c_sysctl_real, NULL, &w83781d_temp},
37897 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
37898 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37899 +       {W83781D_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
37900 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37901 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
37902 +        &i2c_sysctl_real, NULL, &w83781d_vid},
37903 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
37904 +        &i2c_sysctl_real, NULL, &w83781d_fan_div},
37905 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
37906 +        &i2c_sysctl_real, NULL, &w83781d_alarms},
37907 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
37908 +        &i2c_sysctl_real, NULL, &w83781d_beep},
37909 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
37910 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37911 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
37912 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37913 +       {W83781D_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, &i2c_proc_real,
37914 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37915 +       {W83781D_SYSCTL_PWM4, "pwm4", NULL, 0, 0644, NULL, &i2c_proc_real,
37916 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37917 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
37918 +        &i2c_sysctl_real, NULL, &w83781d_vrm},
37919 +       {0}
37920 +};
37921 +
37922 +static ctl_table w83783s_dir_table_template[] = {
37923 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
37924 +        &i2c_sysctl_real, NULL, &w83781d_in},
37925 +       /* no in1 to maintain compatibility with 781d and 782d. */
37926 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
37927 +        &i2c_sysctl_real, NULL, &w83781d_in},
37928 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
37929 +        &i2c_sysctl_real, NULL, &w83781d_in},
37930 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
37931 +        &i2c_sysctl_real, NULL, &w83781d_in},
37932 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
37933 +        &i2c_sysctl_real, NULL, &w83781d_in},
37934 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
37935 +        &i2c_sysctl_real, NULL, &w83781d_in},
37936 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
37937 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37938 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
37939 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37940 +       {W83781D_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, &i2c_proc_real,
37941 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37942 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
37943 +        &i2c_sysctl_real, NULL, &w83781d_temp},
37944 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
37945 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37946 +       {W83781D_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
37947 +        &i2c_sysctl_real, NULL, &w83781d_vid},
37948 +       {W83781D_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
37949 +        &i2c_sysctl_real, NULL, &w83781d_vrm},
37950 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
37951 +        &i2c_sysctl_real, NULL, &w83781d_fan_div},
37952 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
37953 +        &i2c_sysctl_real, NULL, &w83781d_alarms},
37954 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
37955 +        &i2c_sysctl_real, NULL, &w83781d_beep},
37956 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
37957 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37958 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
37959 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
37960 +       {W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
37961 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37962 +       {W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
37963 +        &i2c_sysctl_real, NULL, &w83781d_sens},
37964 +       {0}
37965 +};
37966 +
37967 +/* similar to w83782d but no fan3, no vid */
37968 +static ctl_table w83697hf_dir_table_template[] = {
37969 +       {W83781D_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
37970 +        &i2c_sysctl_real, NULL, &w83781d_in},
37971 +       /* no in1 to maintain compatibility with 781d and 782d. */
37972 +       {W83781D_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
37973 +        &i2c_sysctl_real, NULL, &w83781d_in},
37974 +       {W83781D_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
37975 +        &i2c_sysctl_real, NULL, &w83781d_in},
37976 +       {W83781D_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
37977 +        &i2c_sysctl_real, NULL, &w83781d_in},
37978 +       {W83781D_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
37979 +        &i2c_sysctl_real, NULL, &w83781d_in},
37980 +       {W83781D_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
37981 +        &i2c_sysctl_real, NULL, &w83781d_in},
37982 +       {W83781D_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
37983 +        &i2c_sysctl_real, NULL, &w83781d_in},
37984 +       {W83781D_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, &i2c_proc_real,
37985 +        &i2c_sysctl_real, NULL, &w83781d_in},
37986 +       {W83781D_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
37987 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37988 +       {W83781D_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
37989 +        &i2c_sysctl_real, NULL, &w83781d_fan},
37990 +       {W83781D_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
37991 +        &i2c_sysctl_real, NULL, &w83781d_temp},
37992 +       {W83781D_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
37993 +        &i2c_sysctl_real, NULL, &w83781d_temp_add},
37994 +       {W83781D_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, &i2c_proc_real,
37995 +        &i2c_sysctl_real, NULL, &w83781d_fan_div},
37996 +       {W83781D_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
37997 +        &i2c_sysctl_real, NULL, &w83781d_alarms},
37998 +       {W83781D_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL, &i2c_proc_real,
37999 +        &i2c_sysctl_real, NULL, &w83781d_beep},
38000 +       {W83781D_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, &i2c_proc_real,
38001 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
38002 +       {W83781D_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, &i2c_proc_real,
38003 +        &i2c_sysctl_real, NULL, &w83781d_pwm},
38004 +       {W83781D_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL, &i2c_proc_real,
38005 +        &i2c_sysctl_real, NULL, &w83781d_sens},
38006 +       {W83781D_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL, &i2c_proc_real,
38007 +        &i2c_sysctl_real, NULL, &w83781d_sens},
38008 +       {0}
38009 +};
38010 +
38011 +
38012 +/* This function is called when:
38013 +     * w83781d_driver is inserted (when this module is loaded), for each
38014 +       available adapter
38015 +     * when a new adapter is inserted (and w83781d_driver is still present) */
38016 +static int w83781d_attach_adapter(struct i2c_adapter *adapter)
38017 +{
38018 +       return i2c_detect(adapter, &addr_data, w83781d_detect);
38019 +}
38020 +
38021 +static int w83781d_detect(struct i2c_adapter *adapter, int address,
38022 +                  unsigned short flags, int kind)
38023 +{
38024 +       int i, val1 = 0, val2, id;
38025 +       struct i2c_client *new_client;
38026 +       struct w83781d_data *data;
38027 +       int err = 0;
38028 +       const char *type_name = "";
38029 +       const char *client_name = "";
38030 +       int is_isa = i2c_is_isa_adapter(adapter);
38031 +       enum vendor { winbond, asus } vendid;
38032 +
38033 +       if (!is_isa
38034 +           && !i2c_check_functionality(adapter,
38035 +                                       I2C_FUNC_SMBUS_BYTE_DATA)) goto
38036 +                   ERROR0;
38037 +
38038 +       if (is_isa) {
38039 +               if (!request_region(address, W83781D_EXTENT, "w83781d"))
38040 +                       goto ERROR0;
38041 +               release_region(address, W83781D_EXTENT);
38042 +       }
38043 +
38044 +       /* Probe whether there is anything available on this address. Already
38045 +          done for SMBus clients */
38046 +       if (kind < 0) {
38047 +               if (is_isa) {
38048 +
38049 +#define REALLY_SLOW_IO
38050 +                       /* We need the timeouts for at least some LM78-like chips. But only
38051 +                          if we read 'undefined' registers. */
38052 +                       i = inb_p(address + 1);
38053 +                       if (inb_p(address + 2) != i)
38054 +                               goto ERROR0;
38055 +                       if (inb_p(address + 3) != i)
38056 +                               goto ERROR0;
38057 +                       if (inb_p(address + 7) != i)
38058 +                               goto ERROR0;
38059 +#undef REALLY_SLOW_IO
38060 +
38061 +                       /* Let's just hope nothing breaks here */
38062 +                       i = inb_p(address + 5) & 0x7f;
38063 +                       outb_p(~i & 0x7f, address + 5);
38064 +                       if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
38065 +                               outb_p(i, address + 5);
38066 +                               return 0;
38067 +                       }
38068 +               }
38069 +       }
38070 +
38071 +       /* OK. For now, we presume we have a valid client. We now create the
38072 +          client structure, even though we cannot fill it completely yet.
38073 +          But it allows us to access w83781d_{read,write}_value. */
38074 +
38075 +       if (!(data = kmalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
38076 +               err = -ENOMEM;
38077 +               goto ERROR0;
38078 +       }
38079 +
38080 +       new_client = &data->client;
38081 +       new_client->addr = address;
38082 +       init_MUTEX(&data->lock);
38083 +       new_client->data = data;
38084 +       new_client->adapter = adapter;
38085 +       new_client->driver = &w83781d_driver;
38086 +       new_client->flags = 0;
38087 +
38088 +       /* Now, we do the remaining detection. */
38089 +
38090 +       /* The w8378?d may be stuck in some other bank than bank 0. This may
38091 +          make reading other information impossible. Specify a force=... or
38092 +          force_*=... parameter, and the Winbond will be reset to the right
38093 +          bank. */
38094 +       if (kind < 0) {
38095 +               if (w83781d_read_value(new_client, W83781D_REG_CONFIG) &
38096 +                   0x80) {
38097 +                       err = -ENODEV;
38098 +                       goto ERROR1;
38099 +               }
38100 +               val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
38101 +               val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
38102 +               /* Check for Winbond or Asus ID if in bank 0 */
38103 +               if ((!(val1 & 0x07)) &&
38104 +                   (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
38105 +                    || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
38106 +                       err = -ENODEV;
38107 +                       goto ERROR1;
38108 +               }
38109 +               /* If Winbond SMBus, check address at 0x48.
38110 +                  Asus doesn't support, except for the as99127f rev.2 */
38111 +               if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
38112 +                                 ((val1 & 0x80) && (val2 == 0x5c)))) {
38113 +                       if (w83781d_read_value
38114 +                           (new_client, W83781D_REG_I2C_ADDR) != address) {
38115 +                               err = -ENODEV;
38116 +                               goto ERROR1;
38117 +                       }
38118 +               }
38119 +       }
38120 +
38121 +       /* We have either had a force parameter, or we have already detected the
38122 +          Winbond. Put it now into bank 0 and Vendor ID High Byte */
38123 +       w83781d_write_value(new_client, W83781D_REG_BANK,
38124 +                           (w83781d_read_value(new_client,
38125 +                                               W83781D_REG_BANK) & 0x78) |
38126 +                           0x80);
38127 +
38128 +       /* Determine the chip type. */
38129 +       if (kind <= 0) {
38130 +               /* get vendor ID */
38131 +               val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
38132 +               if (val2 == 0x5c)
38133 +                       vendid = winbond;
38134 +               else if (val2 == 0x12)
38135 +                       vendid = asus;
38136 +               else {
38137 +                       err = -ENODEV;
38138 +                       goto ERROR1;
38139 +               }
38140 +               val1 =
38141 +                   w83781d_read_value(new_client, W83781D_REG_WCHIPID);
38142 +               if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
38143 +                       kind = w83781d;
38144 +               else if (val1 == 0x30 && vendid == winbond)
38145 +                       kind = w83782d;
38146 +               else if (val1 == 0x40 && vendid == winbond && !is_isa && address == 0x2d)
38147 +                       kind = w83783s;
38148 +               else if (val1 == 0x21 && vendid == winbond)
38149 +                       kind = w83627hf;
38150 +               else if (val1 == 0x71 && vendid == winbond && address >= 0x2c)
38151 +                       kind = w83791d;
38152 +               else if (val1 == 0x31 && !is_isa && address >= 0x28)
38153 +                       kind = as99127f;
38154 +               else if (val1 == 0x60 && vendid == winbond && is_isa)
38155 +                       kind = w83697hf;
38156 +               else {
38157 +                       if (kind == 0)
38158 +                               printk
38159 +                                   (KERN_WARNING "w83781d.o: Ignoring 'force' parameter for unknown chip at"
38160 +                                    "adapter %d, address 0x%02x\n",
38161 +                                    i2c_adapter_id(adapter), address);
38162 +                       err = -EINVAL;
38163 +                       goto ERROR1;
38164 +               }
38165 +       }
38166 +
38167 +       if (kind == w83781d) {
38168 +               type_name = "w83781d";
38169 +               client_name = "W83781D chip";
38170 +       } else if (kind == w83782d) {
38171 +               type_name = "w83782d";
38172 +               client_name = "W83782D chip";
38173 +       } else if (kind == w83783s) {
38174 +               type_name = "w83783s";
38175 +               client_name = "W83783S chip";
38176 +       } else if (kind == w83627hf) {
38177 +               type_name = "w83627hf";
38178 +               client_name = "W83627HF chip";
38179 +       } else if (kind == as99127f) {
38180 +               type_name = "as99127f";
38181 +               client_name = "AS99127F chip";
38182 +       } else if (kind == w83697hf) {
38183 +               type_name = "w83697hf";
38184 +               client_name = "W83697HF chip";
38185 +        } else if (kind == w83791d) {
38186 +               type_name = "w83791d";
38187 +               client_name = "W83791D chip";
38188 +       } else {
38189 +#ifdef DEBUG
38190 +               printk(KERN_ERR "w83781d.o: Internal error: unknown kind (%d)?!?",
38191 +                      kind);
38192 +#endif
38193 +               err = -ENODEV;
38194 +               goto ERROR1;
38195 +       }
38196 +
38197 +       /* Reserve the ISA region */
38198 +       if (is_isa)
38199 +               request_region(address, W83781D_EXTENT, type_name);
38200 +
38201 +       /* Fill in the remaining client fields and put it into the global list */
38202 +       strcpy(new_client->name, client_name);
38203 +       data->type = kind;
38204 +
38205 +       new_client->id = w83781d_id++;
38206 +       data->valid = 0;
38207 +       init_MUTEX(&data->update_lock);
38208 +
38209 +       /* Tell the I2C layer a new client has arrived */
38210 +       if ((err = i2c_attach_client(new_client)))
38211 +               goto ERROR3;
38212 +
38213 +       /* attach secondary i2c lm75-like clients */
38214 +       if (!is_isa) {
38215 +               if (!(data->lm75 = kmalloc(2 * sizeof(struct i2c_client),
38216 +                                          GFP_KERNEL))) {
38217 +                       err = -ENOMEM;
38218 +                       goto ERROR4;
38219 +               }
38220 +               id = i2c_adapter_id(adapter);
38221 +               if(force_subclients[0] == id && force_subclients[1] == address) {
38222 +                       for(i = 2; i <= 3; i++) {
38223 +                               if(force_subclients[i] < 0x48 ||
38224 +                                  force_subclients[i] > 0x4f) {
38225 +                                       printk(KERN_ERR "w83781d.o: Invalid subclient address %d; must be 0x48-0x4f\n",
38226 +                                               force_subclients[i]);
38227 +                                       err = -EINVAL;
38228 +                                       goto ERROR5;
38229 +                               }
38230 +                       }
38231 +                       w83781d_write_value(new_client,
38232 +                                           W83781D_REG_I2C_SUBADDR,
38233 +                                           (force_subclients[2] & 0x07) |
38234 +                                           ((force_subclients[3] & 0x07) <<4));
38235 +                       data->lm75[0].addr = force_subclients[2];
38236 +               } else {
38237 +                       val1 = w83781d_read_value(new_client,
38238 +                                                 W83781D_REG_I2C_SUBADDR);
38239 +                       data->lm75[0].addr = 0x48 + (val1 & 0x07);
38240 +               }
38241 +               if (kind != w83783s) {
38242 +                       if(force_subclients[0] == id &&
38243 +                          force_subclients[1] == address) {
38244 +                               data->lm75[1].addr = force_subclients[3];
38245 +                       } else {
38246 +                               data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07);
38247 +                       }
38248 +                       if(data->lm75[0].addr == data->lm75[1].addr) {
38249 +                               printk(KERN_ERR "w83781d.o: Duplicate addresses 0x%x for subclients.\n",
38250 +                                       data->lm75[0].addr);
38251 +                               err = -EBUSY;
38252 +                               goto ERROR5;
38253 +                       }
38254 +               }
38255 +               if (kind == w83781d)
38256 +                       client_name = "W83781D subclient";
38257 +               else if (kind == w83782d)
38258 +                       client_name = "W83782D subclient";
38259 +               else if (kind == w83783s)
38260 +                       client_name = "W83783S subclient";
38261 +               else if (kind == w83627hf)
38262 +                       client_name = "W83627HF subclient";
38263 +               else if (kind == as99127f)
38264 +                       client_name = "AS99127F subclient";
38265 +                else if (kind == w83791d)
38266 +                       client_name = "W83791D subclient";
38267 +
38268 +
38269 +               for (i = 0; i <= 1; i++) {
38270 +                       data->lm75[i].data = NULL;      /* store all data in w83781d */
38271 +                       data->lm75[i].adapter = adapter;
38272 +                       data->lm75[i].driver = &w83781d_driver;
38273 +                       data->lm75[i].flags = 0;
38274 +                       strcpy(data->lm75[i].name, client_name);
38275 +                       data->lm75[i].id = w83781d_id++;
38276 +                       if ((err = i2c_attach_client(&(data->lm75[i])))) {
38277 +                               printk(KERN_ERR "w83781d.o: Subclient %d registration at address 0x%x failed.\n",
38278 +                                      i, data->lm75[i].addr);
38279 +                               if (i == 1)
38280 +                                       goto ERROR6;
38281 +                               goto ERROR5;
38282 +                       }
38283 +                       if (kind == w83783s)
38284 +                               break;
38285 +               }
38286 +       } else {
38287 +               data->lm75 = NULL;
38288 +       }
38289 +
38290 +       /* Register a new directory entry with module sensors */
38291 +       if ((i = i2c_register_entry(new_client,
38292 +                                       type_name,
38293 +                                       (kind == as99127f) ?
38294 +                                          as99127f_dir_table_template :
38295 +                                       (kind == w83781d) ?
38296 +                                          w83781d_dir_table_template :
38297 +                                       (kind == w83783s) ?
38298 +                                          w83783s_dir_table_template :
38299 +                                       (kind == w83697hf) ?
38300 +                                          w83697hf_dir_table_template :
38301 +                                        (kind == w83791d ) ?
38302 +                                            w83791d_dir_table_template :
38303 +                                        (is_isa || kind == w83627hf) ?
38304 +                                          w83782d_isa_dir_table_template :
38305 +                                          w83782d_i2c_dir_table_template)) < 0) {
38306 +               err = i;
38307 +               goto ERROR7;
38308 +       }
38309 +       data->sysctl_id = i;
38310 +
38311 +       /* Only PWM2 can be disabled */
38312 +       for(i = 0; i < 4; i++)
38313 +               data->pwmenable[i] = 1;
38314 +
38315 +       /* Initialize the chip */
38316 +       w83781d_init_client(new_client);
38317 +       return 0;
38318 +
38319 +/* OK, this is not exactly good programming practice, usually. But it is
38320 +   very code-efficient in this case. */
38321 +
38322 +      ERROR7:
38323 +       if (!is_isa)
38324 +               i2c_detach_client(&
38325 +                                 (((struct
38326 +                                    w83781d_data *) (new_client->data))->
38327 +                                  lm75[1]));
38328 +      ERROR6:
38329 +       if (!is_isa)
38330 +               i2c_detach_client(&
38331 +                                 (((struct
38332 +                                    w83781d_data *) (new_client->data))->
38333 +                                  lm75[0]));
38334 +      ERROR5:
38335 +       if (!is_isa)
38336 +               kfree(((struct w83781d_data *) (new_client->data))->lm75);
38337 +      ERROR4:
38338 +       i2c_detach_client(new_client);
38339 +      ERROR3:
38340 +       if (is_isa)
38341 +               release_region(address, W83781D_EXTENT);
38342 +      ERROR1:
38343 +       kfree(data);
38344 +      ERROR0:
38345 +       return err;
38346 +}
38347 +
38348 +static int w83781d_detach_client(struct i2c_client *client)
38349 +{
38350 +       int err;
38351 +       struct w83781d_data *data = client->data;
38352 +
38353 +       i2c_deregister_entry(data->sysctl_id);
38354 +
38355 +       if ((err = i2c_detach_client(client))) {
38356 +               printk
38357 +                   (KERN_ERR "w83781d.o: Client deregistration failed, client not detached.\n");
38358 +               return err;
38359 +       }
38360 +
38361 +       if(i2c_is_isa_client(client)) {
38362 +               release_region(client->addr, W83781D_EXTENT);
38363 +       } else {
38364 +               i2c_detach_client(&(data->lm75[0]));
38365 +               if (data->type != w83783s)
38366 +                       i2c_detach_client(&(data->lm75[1]));
38367 +               kfree(data->lm75);
38368 +       }
38369 +       kfree(data);
38370 +
38371 +       return 0;
38372 +}
38373 +
38374 +/* The SMBus locks itself, usually, but nothing may access the Winbond between
38375 +   bank switches. ISA access must always be locked explicitly! 
38376 +   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
38377 +   would slow down the W83781D access and should not be necessary. 
38378 +   There are some ugly typecasts here, but the good news is - they should
38379 +   nowhere else be necessary! */
38380 +static int w83781d_read_value(struct i2c_client *client, u16 reg)
38381 +{
38382 +       int res, word_sized, bank;
38383 +       struct i2c_client *cl;
38384 +
38385 +       down(&(((struct w83781d_data *) (client->data))->lock));
38386 +       if (i2c_is_isa_client(client)) {
38387 +               word_sized = (((reg & 0xff00) == 0x100)
38388 +                             || ((reg & 0xff00) == 0x200))
38389 +                   && (((reg & 0x00ff) == 0x50)
38390 +                       || ((reg & 0x00ff) == 0x53)
38391 +                       || ((reg & 0x00ff) == 0x55));
38392 +               if (reg & 0xff00) {
38393 +                       outb_p(W83781D_REG_BANK,
38394 +                              client->addr + W83781D_ADDR_REG_OFFSET);
38395 +                       outb_p(reg >> 8,
38396 +                              client->addr + W83781D_DATA_REG_OFFSET);
38397 +               }
38398 +               outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
38399 +               res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
38400 +               if (word_sized) {
38401 +                       outb_p((reg & 0xff) + 1,
38402 +                              client->addr + W83781D_ADDR_REG_OFFSET);
38403 +                       res =
38404 +                           (res << 8) + inb_p(client->addr +
38405 +                                              W83781D_DATA_REG_OFFSET);
38406 +               }
38407 +               if (reg & 0xff00) {
38408 +                       outb_p(W83781D_REG_BANK,
38409 +                              client->addr + W83781D_ADDR_REG_OFFSET);
38410 +                       outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
38411 +               }
38412 +       } else {
38413 +               bank = (reg >> 8) & 0x0f;
38414 +               if (bank > 2)
38415 +                       /* switch banks */
38416 +                       i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38417 +                                                 bank);
38418 +               if (bank == 0 || bank > 2) {
38419 +                       res = i2c_smbus_read_byte_data(client, reg & 0xff);
38420 +               } else {
38421 +                       /* switch to subclient */
38422 +                       cl =
38423 +                           &(((struct w83781d_data *) (client->data))->
38424 +                             lm75[bank - 1]);
38425 +                       /* convert from ISA to LM75 I2C addresses */
38426 +                       switch (reg & 0xff) {
38427 +                       case 0x50: /* TEMP */
38428 +                               res = swab16(i2c_smbus_read_word_data(cl, 0));
38429 +                               break;
38430 +                       case 0x52: /* CONFIG */
38431 +                               res = i2c_smbus_read_byte_data(cl, 1);
38432 +                               break;
38433 +                       case 0x53: /* HYST */
38434 +                               res = swab16(i2c_smbus_read_word_data(cl, 2));
38435 +                               break;
38436 +                       case 0x55: /* OVER */
38437 +                       default:
38438 +                               res = swab16(i2c_smbus_read_word_data(cl, 3));
38439 +                               break;
38440 +                       }
38441 +               }
38442 +               if (bank > 2)
38443 +                       i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38444 +                                                 0);
38445 +       }
38446 +       up(&(((struct w83781d_data *) (client->data))->lock));
38447 +       return res;
38448 +}
38449 +
38450 +static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
38451 +{
38452 +       int word_sized, bank;
38453 +       struct i2c_client *cl;
38454 +
38455 +       down(&(((struct w83781d_data *) (client->data))->lock));
38456 +       if (i2c_is_isa_client(client)) {
38457 +               word_sized = (((reg & 0xff00) == 0x100)
38458 +                             || ((reg & 0xff00) == 0x200))
38459 +                   && (((reg & 0x00ff) == 0x53)
38460 +                       || ((reg & 0x00ff) == 0x55));
38461 +               if (reg & 0xff00) {
38462 +                       outb_p(W83781D_REG_BANK,
38463 +                              client->addr + W83781D_ADDR_REG_OFFSET);
38464 +                       outb_p(reg >> 8,
38465 +                              client->addr + W83781D_DATA_REG_OFFSET);
38466 +               }
38467 +               outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
38468 +               if (word_sized) {
38469 +                       outb_p(value >> 8,
38470 +                              client->addr + W83781D_DATA_REG_OFFSET);
38471 +                       outb_p((reg & 0xff) + 1,
38472 +                              client->addr + W83781D_ADDR_REG_OFFSET);
38473 +               }
38474 +               outb_p(value & 0xff,
38475 +                      client->addr + W83781D_DATA_REG_OFFSET);
38476 +               if (reg & 0xff00) {
38477 +                       outb_p(W83781D_REG_BANK,
38478 +                              client->addr + W83781D_ADDR_REG_OFFSET);
38479 +                       outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
38480 +               }
38481 +       } else {
38482 +               bank = (reg >> 8) & 0x0f;
38483 +               if (bank > 2)
38484 +                       /* switch banks */
38485 +                       i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38486 +                                                 bank);
38487 +               if (bank == 0 || bank > 2) {
38488 +                       i2c_smbus_write_byte_data(client, reg & 0xff,
38489 +                                                 value & 0xff);
38490 +               } else {
38491 +                       /* switch to subclient */
38492 +                       cl = &(((struct w83781d_data *) (client->data))->
38493 +                             lm75[bank - 1]);
38494 +                       /* convert from ISA to LM75 I2C addresses */
38495 +                       switch (reg & 0xff) {
38496 +                       case 0x52: /* CONFIG */
38497 +                               i2c_smbus_write_byte_data(cl, 1, value & 0xff);
38498 +                               break;
38499 +                       case 0x53: /* HYST */
38500 +                               i2c_smbus_write_word_data(cl, 2, swab16(value));
38501 +                               break;
38502 +                       case 0x55: /* OVER */
38503 +                               i2c_smbus_write_word_data(cl, 3, swab16(value));
38504 +                               break;
38505 +                       }
38506 +               }
38507 +               if (bank > 2)
38508 +                       i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38509 +                                                 0);
38510 +       }
38511 +       up(&(((struct w83781d_data *) (client->data))->lock));
38512 +       return 0;
38513 +}
38514 +
38515 +/* Called when we have found a new W83781D. It should set limits, etc. */
38516 +static void w83781d_init_client(struct i2c_client *client)
38517 +{
38518 +       struct w83781d_data *data = client->data;
38519 +       int i, p;
38520 +       int type = data->type;
38521 +       u8 tmp;
38522 +
38523 +       if(init && type != as99127f) { /* this resets registers we don't have
38524 +                                         documentation for on the as99127f */
38525 +               /* save these registers */
38526 +               i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
38527 +               p = w83781d_read_value(client, W83781D_REG_PWMCLK12);
38528 +               /* Reset all except Watchdog values and last conversion values
38529 +                  This sets fan-divs to 2, among others */
38530 +               w83781d_write_value(client, W83781D_REG_CONFIG, 0x80);
38531 +               /* Restore the registers and disable power-on abnormal beep.
38532 +                  This saves FAN 1/2/3 input/output values set by BIOS. */
38533 +               w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
38534 +               w83781d_write_value(client, W83781D_REG_PWMCLK12, p);
38535 +               /* Disable master beep-enable (reset turns it on).
38536 +                  Individual beeps should be reset to off but for some reason
38537 +                  disabling this bit helps some people not get beeped */
38538 +               w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
38539 +       }
38540 +
38541 +       data->vrm = (type == w83791d) ? 90 : 82;
38542 +
38543 +       if ((type != w83781d) && (type != as99127f)) {
38544 +               tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
38545 +               for (i = 1; i <= 3; i++) {
38546 +                       if (!(tmp & BIT_SCFG1[i - 1])) {
38547 +                               data->sens[i - 1] = W83781D_DEFAULT_BETA;
38548 +                       } else {
38549 +                               if (w83781d_read_value
38550 +                                   (client,
38551 +                                    W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
38552 +                                       data->sens[i - 1] = 1;
38553 +                               else
38554 +                                       data->sens[i - 1] = 2;
38555 +                       }
38556 +                       if ((type == w83783s || type == w83697hf) && (i == 2))
38557 +                               break;
38558 +               }
38559 +       }
38560 +#ifdef W83781D_RT
38561 +/*
38562 +   Fill up the RT Tables.
38563 +   We assume that they are 32 bytes long, in order for temp 1-3.
38564 +   Data sheet documentation is sparse.
38565 +   We also assume that it is only for the 781D although I suspect
38566 +   that the others support it as well....
38567 +*/
38568 +
38569 +       if (init && type == w83781d) {
38570 +               u16 k = 0;
38571 +/*
38572 +    Auto-indexing doesn't seem to work...
38573 +    w83781d_write_value(client,W83781D_REG_RT_IDX,0);
38574 +*/
38575 +               for (i = 0; i < 3; i++) {
38576 +                       int j;
38577 +                       for (j = 0; j < 32; j++) {
38578 +                               w83781d_write_value(client,
38579 +                                                   W83781D_REG_RT_IDX,
38580 +                                                   k++);
38581 +                               data->rt[i][j] =
38582 +                                   w83781d_read_value(client,
38583 +                                                      W83781D_REG_RT_VAL);
38584 +                       }
38585 +               }
38586 +       }
38587 +#endif                         /* W83781D_RT */
38588 +
38589 +       if(init) {
38590 +               w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, 0x00);
38591 +               if (type != w83783s && type != w83697hf) {
38592 +                       w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG,
38593 +                                           0x00);
38594 +               }
38595 +               if (type != w83781d) {
38596 +                       /* enable comparator mode for temp2 and temp3 so
38597 +                          alarm indication will work correctly */
38598 +                       i = w83781d_read_value(client, W83781D_REG_IRQ);
38599 +                       if (!(i & 0x40))
38600 +                               w83781d_write_value(client, W83781D_REG_IRQ,
38601 +                                                   i | 0x40);
38602 +               }
38603 +       }
38604 +
38605 +       /* Start monitoring */
38606 +       w83781d_write_value(client, W83781D_REG_CONFIG,
38607 +                           (w83781d_read_value(client,
38608 +                                               W83781D_REG_CONFIG) & 0xf7)
38609 +                           | 0x01);
38610 +}
38611 +
38612 +static void w83781d_update_client(struct i2c_client *client)
38613 +{
38614 +       struct w83781d_data *data = client->data;
38615 +       int i;
38616 +
38617 +       down(&data->update_lock);
38618 +
38619 +       if (time_after(jiffies - data->last_updated, HZ + HZ / 2) ||
38620 +           time_before(jiffies, data->last_updated) || !data->valid) {
38621 +               pr_debug(KERN_DEBUG "Starting device update\n");
38622 +
38623 +               for (i = 0; i <= 9; i++) {
38624 +                       if ((data->type == w83783s || data->type == w83697hf)
38625 +                           && (i == 1))
38626 +                               continue;       /* 783S has no in1 */
38627 +                       if (data->type == w83791d) {
38628 +                                data->in[i] =
38629 +                                        w83781d_read_value(client, W83791D_REG_IN(i));
38630 +                                data->in_min[i] =
38631 +                                        w83781d_read_value(client,
38632 +                                                           W83791D_REG_IN_MIN(i));
38633 +                                data->in_max[i] =
38634 +                                        w83781d_read_value(client,
38635 +                                                           W83791D_REG_IN_MAX(i));
38636 +                       } else {
38637 +                       data->in[i] =
38638 +                           w83781d_read_value(client, W83781D_REG_IN(i));
38639 +                       data->in_min[i] =
38640 +                           w83781d_read_value(client,
38641 +                                              W83781D_REG_IN_MIN(i));
38642 +                       data->in_max[i] =
38643 +                           w83781d_read_value(client,
38644 +                                              W83781D_REG_IN_MAX(i));
38645 +                       }
38646 +                       if ((data->type != w83782d) && (data->type != w83697hf)
38647 +                           && (data->type != w83627hf) && (i == 6)
38648 +                           && (data->type != w83791d))
38649 +                               break;
38650 +
38651 +                       if (data->type != w83791d && i == 8) 
38652 +                         break;
38653 +               }
38654 +               for (i = 1; i <= 5; i++) {
38655 +                       data->fan[i - 1] =
38656 +                           w83781d_read_value(client, W83781D_REG_FAN(i));
38657 +                       data->fan_min[i - 1] =
38658 +                           w83781d_read_value(client,
38659 +                                              W83781D_REG_FAN_MIN(i));
38660 +                       if (data->type != w83791d && i == 3) break;
38661 +               }
38662 +               if (data->type != w83781d && data->type != as99127f) {
38663 +                       for (i = 1; i <= 4; i++) {
38664 +                               data->pwm[i - 1] =
38665 +                                   w83781d_read_value(client,
38666 +                                            W83781D_REG_PWM(data->type, i));
38667 +                               if (((data->type == w83783s)
38668 +                                    || (data->type == w83627hf)
38669 +                                    || (data->type == w83697hf)
38670 +                                    || ((data->type == w83782d)
38671 +                                       && i2c_is_isa_client(client)))
38672 +                                   && i == 2)
38673 +                                       break;
38674 +                       }
38675 +                       /* Only PWM2 can be disabled */
38676 +                       data->pwmenable[1] = (w83781d_read_value(client,
38677 +                                             W83781D_REG_PWMCLK12) & 0x08) >> 3;
38678 +               }
38679 +
38680 +               data->temp = w83781d_read_value(client, W83781D_REG_TEMP);
38681 +               data->temp_over =
38682 +                   w83781d_read_value(client, W83781D_REG_TEMP_OVER);
38683 +               data->temp_hyst =
38684 +                   w83781d_read_value(client, W83781D_REG_TEMP_HYST);
38685 +               data->temp_add[0] =
38686 +                   w83781d_read_value(client, W83781D_REG_TEMP2);
38687 +               data->temp_add_over[0] =
38688 +                   w83781d_read_value(client, W83781D_REG_TEMP2_OVER);
38689 +               data->temp_add_hyst[0] =
38690 +                   w83781d_read_value(client, W83781D_REG_TEMP2_HYST);
38691 +               if (data->type != w83783s && data->type != w83697hf) {
38692 +                       data->temp_add[1] =
38693 +                           w83781d_read_value(client, W83781D_REG_TEMP3);
38694 +                       data->temp_add_over[1] =
38695 +                           w83781d_read_value(client, W83781D_REG_TEMP3_OVER);
38696 +                       data->temp_add_hyst[1] =
38697 +                           w83781d_read_value(client, W83781D_REG_TEMP3_HYST);
38698 +               }
38699 +               i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
38700 +               if (data->type != w83697hf) {
38701 +                       data->vid = i & 0x0f;
38702 +                       data->vid |=
38703 +                           (w83781d_read_value(client, W83781D_REG_CHIPID) & 0x01)
38704 +                           << 4;
38705 +               }
38706 +               data->fan_div[0] = (i >> 4) & 0x03;
38707 +               data->fan_div[1] = (i >> 6) & 0x03;
38708 +               if (data->type != w83697hf) {
38709 +                       data->fan_div[2] = (w83781d_read_value(client,
38710 +                                              W83781D_REG_PIN) >> 6) & 0x03;
38711 +               }
38712 +               if ((data->type != w83781d) && (data->type != as99127f)) {
38713 +                       i = w83781d_read_value(client, W83781D_REG_VBAT);
38714 +                       data->fan_div[0] |= (i >> 3) & 0x04;
38715 +                       data->fan_div[1] |= (i >> 4) & 0x04;
38716 +                       if (data->type != w83697hf)
38717 +                               data->fan_div[2] |= (i >> 5) & 0x04;
38718 +               }
38719 +               data->alarms =
38720 +                   w83781d_read_value(client,
38721 +                                      W83781D_REG_ALARM1) +
38722 +                   (w83781d_read_value(client, W83781D_REG_ALARM2) << 8);
38723 +               if ((data->type == w83782d) || (data->type == w83627hf) ||
38724 +                  (data->type == w83697hf)) {
38725 +                       data->alarms |=
38726 +                           w83781d_read_value(client,
38727 +                                              W83781D_REG_ALARM3) << 16;
38728 +               }
38729 +               i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2);
38730 +               data->beep_enable = i >> 7;
38731 +               data->beeps = ((i & 0x7f) << 8) +
38732 +                   w83781d_read_value(client, W83781D_REG_BEEP_INTS1);
38733 +               if ((data->type != w83781d) && (data->type != as99127f)
38734 +                   && (data->type != w83791d)) {
38735 +                       data->beeps |=
38736 +                           w83781d_read_value(client,
38737 +                                              W83781D_REG_BEEP_INTS3) << 16;
38738 +               }
38739 +               data->last_updated = jiffies;
38740 +               data->valid = 1;
38741 +       }
38742 +
38743 +       up(&data->update_lock);
38744 +}
38745 +
38746 +
38747 +/* The next few functions are the call-back functions of the /proc/sys and
38748 +   sysctl files. Which function is used is defined in the ctl_table in
38749 +   the extra1 field.
38750 +   Each function must return the magnitude (power of 10 to divide the date
38751 +   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
38752 +   put a maximum of *nrels elements in results reflecting the data of this
38753 +   file, and set *nrels to the number it actually put in it, if operation==
38754 +   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
38755 +   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
38756 +   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
38757 +   large enough (by checking the incoming value of *nrels). This is not very
38758 +   good practice, but as long as you put less than about 5 values in results,
38759 +   you can assume it is large enough. */
38760 +static void w83781d_in(struct i2c_client *client, int operation, int ctl_name,
38761 +               int *nrels_mag, long *results)
38762 +{
38763 +       struct w83781d_data *data = client->data;
38764 +       int nr = ctl_name - W83781D_SYSCTL_IN0;
38765 +
38766 +       if (operation == SENSORS_PROC_REAL_INFO)
38767 +               *nrels_mag = 2;
38768 +       else if (operation == SENSORS_PROC_REAL_READ) {
38769 +               w83781d_update_client(client);
38770 +               results[0] = IN_FROM_REG(data->in_min[nr]);
38771 +               results[1] = IN_FROM_REG(data->in_max[nr]);
38772 +               results[2] = IN_FROM_REG(data->in[nr]);
38773 +               *nrels_mag = 3;
38774 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
38775 +               if (*nrels_mag >= 1) {
38776 +                       data->in_min[nr] = IN_TO_REG(results[0]);
38777 +                       w83781d_write_value(client, W83781D_REG_IN_MIN(nr),
38778 +                                           data->in_min[nr]);
38779 +               }
38780 +               if (*nrels_mag >= 2) {
38781 +                       data->in_max[nr] = IN_TO_REG(results[1]);
38782 +                       w83781d_write_value(client, W83781D_REG_IN_MAX(nr),
38783 +                                           data->in_max[nr]);
38784 +               }
38785 +       }
38786 +}
38787 +
38788 +void w83781d_fan(struct i2c_client *client, int operation, int ctl_name,
38789 +                int *nrels_mag, long *results)
38790 +{
38791 +       struct w83781d_data *data = client->data;
38792 +       int nr = ctl_name - W83781D_SYSCTL_FAN1 + 1;
38793 +
38794 +       if (operation == SENSORS_PROC_REAL_INFO)
38795 +               *nrels_mag = 0;
38796 +       else if (operation == SENSORS_PROC_REAL_READ) {
38797 +               w83781d_update_client(client);
38798 +               results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
38799 +                                 DIV_FROM_REG(data->fan_div[nr - 1]));
38800 +               results[1] = FAN_FROM_REG(data->fan[nr - 1],
38801 +                                 DIV_FROM_REG(data->fan_div[nr - 1]));
38802 +               *nrels_mag = 2;
38803 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
38804 +               if (*nrels_mag >= 1) {
38805 +                       data->fan_min[nr - 1] =
38806 +                            FAN_TO_REG(results[0],
38807 +                                   DIV_FROM_REG(data->fan_div[nr-1]));
38808 +                       w83781d_write_value(client,
38809 +                                           W83781D_REG_FAN_MIN(nr),
38810 +                                           data->fan_min[nr - 1]);
38811 +               }
38812 +       }
38813 +}
38814 +
38815 +void w83781d_temp(struct i2c_client *client, int operation, int ctl_name,
38816 +                 int *nrels_mag, long *results)
38817 +{
38818 +       struct w83781d_data *data = client->data;
38819 +       if (operation == SENSORS_PROC_REAL_INFO)
38820 +               *nrels_mag = 1;
38821 +       else if (operation == SENSORS_PROC_REAL_READ) {
38822 +               w83781d_update_client(client);
38823 +               results[0] = TEMP_FROM_REG(data->temp_over);
38824 +               results[1] = TEMP_FROM_REG(data->temp_hyst);
38825 +               results[2] = TEMP_FROM_REG(data->temp);
38826 +               *nrels_mag = 3;
38827 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
38828 +               if (*nrels_mag >= 1) {
38829 +                       data->temp_over = TEMP_TO_REG(results[0]);
38830 +                       w83781d_write_value(client, W83781D_REG_TEMP_OVER,
38831 +                                           data->temp_over);
38832 +               }
38833 +               if (*nrels_mag >= 2) {
38834 +                       data->temp_hyst = TEMP_TO_REG(results[1]);
38835 +                       w83781d_write_value(client, W83781D_REG_TEMP_HYST,
38836 +                                           data->temp_hyst);
38837 +               }
38838 +       }
38839 +}
38840 +
38841 +void w83781d_temp_add(struct i2c_client *client, int operation,
38842 +                     int ctl_name, int *nrels_mag, long *results)
38843 +{
38844 +       struct w83781d_data *data = client->data;
38845 +       int nr = ctl_name - W83781D_SYSCTL_TEMP2;
38846 +
38847 +       if (operation == SENSORS_PROC_REAL_INFO)
38848 +               *nrels_mag = 1;
38849 +       else if (operation == SENSORS_PROC_REAL_READ) {
38850 +               w83781d_update_client(client);
38851 +               if (data->type == as99127f) {
38852 +                       results[0] =
38853 +                           AS99127_TEMP_ADD_FROM_REG(data->
38854 +                                                     temp_add_over[nr]);
38855 +                       results[1] =
38856 +                           AS99127_TEMP_ADD_FROM_REG(data->
38857 +                                                     temp_add_hyst[nr]);
38858 +                       results[2] =
38859 +                           AS99127_TEMP_ADD_FROM_REG(data->temp_add[nr]);
38860 +               } else {
38861 +                       results[0] =
38862 +                           LM75_TEMP_FROM_REG(data->temp_add_over[nr]);
38863 +                       results[1] =
38864 +                           LM75_TEMP_FROM_REG(data->temp_add_hyst[nr]);
38865 +                       results[2] = LM75_TEMP_FROM_REG(data->temp_add[nr]);
38866 +               }
38867 +               *nrels_mag = 3;
38868 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
38869 +               if (*nrels_mag >= 1) {
38870 +                       if (data->type == as99127f)
38871 +                               data->temp_add_over[nr] =
38872 +                                   AS99127_TEMP_ADD_TO_REG(results[0]);
38873 +                       else
38874 +                               data->temp_add_over[nr] =
38875 +                                   LM75_TEMP_TO_REG(results[0]);
38876 +                       w83781d_write_value(client,
38877 +                                           nr ? W83781D_REG_TEMP3_OVER :
38878 +                                           W83781D_REG_TEMP2_OVER,
38879 +                                           data->temp_add_over[nr]);
38880 +               }
38881 +               if (*nrels_mag >= 2) {
38882 +                       if (data->type == as99127f)
38883 +                               data->temp_add_hyst[nr] =
38884 +                                   AS99127_TEMP_ADD_TO_REG(results[1]);
38885 +                       else
38886 +                               data->temp_add_hyst[nr] =
38887 +                                   LM75_TEMP_TO_REG(results[1]);
38888 +                       w83781d_write_value(client,
38889 +                                           nr ? W83781D_REG_TEMP3_HYST :
38890 +                                           W83781D_REG_TEMP2_HYST,
38891 +                                           data->temp_add_hyst[nr]);
38892 +               }
38893 +       }
38894 +}
38895 +
38896 +
38897 +void w83781d_vid(struct i2c_client *client, int operation, int ctl_name,
38898 +                int *nrels_mag, long *results)
38899 +{
38900 +       struct w83781d_data *data = client->data;
38901 +       if (operation == SENSORS_PROC_REAL_INFO)
38902 +               *nrels_mag = 3;
38903 +       else if (operation == SENSORS_PROC_REAL_READ) {
38904 +               w83781d_update_client(client);
38905 +               results[0] = vid_from_reg(data->vid, data->vrm);
38906 +               *nrels_mag = 1;
38907 +       }
38908 +}
38909 +
38910 +void w83781d_vrm(struct i2c_client *client, int operation, int ctl_name,
38911 +                int *nrels_mag, long *results)
38912 +{
38913 +       struct w83781d_data *data = client->data;
38914 +       if (operation == SENSORS_PROC_REAL_INFO)
38915 +               *nrels_mag = 1;
38916 +       else if (operation == SENSORS_PROC_REAL_READ) {
38917 +               results[0] = data->vrm;
38918 +               *nrels_mag = 1;
38919 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
38920 +               if (*nrels_mag >= 1)
38921 +                       data->vrm = results[0];
38922 +       }
38923 +}
38924 +
38925 +void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name,
38926 +                   int *nrels_mag, long *results)
38927 +{
38928 +       struct w83781d_data *data = client->data;
38929 +       if (operation == SENSORS_PROC_REAL_INFO)
38930 +               *nrels_mag = 0;
38931 +       else if (operation == SENSORS_PROC_REAL_READ) {
38932 +               w83781d_update_client(client);
38933 +               results[0] = ALARMS_FROM_REG(data->alarms);
38934 +               *nrels_mag = 1;
38935 +       }
38936 +}
38937 +
38938 +void w83781d_beep(struct i2c_client *client, int operation, int ctl_name,
38939 +                 int *nrels_mag, long *results)
38940 +{
38941 +       struct w83781d_data *data = client->data;
38942 +       int val;
38943 +
38944 +       if (operation == SENSORS_PROC_REAL_INFO)
38945 +               *nrels_mag = 0;
38946 +       else if (operation == SENSORS_PROC_REAL_READ) {
38947 +               w83781d_update_client(client);
38948 +               results[0] = BEEP_ENABLE_FROM_REG(data->beep_enable);
38949 +               results[1] = BEEPS_FROM_REG(data->beeps, data->type);
38950 +               *nrels_mag = 2;
38951 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
38952 +               if (*nrels_mag >= 2) {
38953 +                       data->beeps = BEEPS_TO_REG(results[1], data->type);
38954 +                       w83781d_write_value(client, W83781D_REG_BEEP_INTS1,
38955 +                                           data->beeps & 0xff);
38956 +                       if ((data->type != w83781d) &&
38957 +                           (data->type != as99127f)) {
38958 +                               w83781d_write_value(client,
38959 +                                                   W83781D_REG_BEEP_INTS3,
38960 +                                                   ((data-> beeps) >> 16) &
38961 +                                                     0xff);
38962 +                       }
38963 +                       val = (data->beeps >> 8) & 0x7f;
38964 +               } else if (*nrels_mag >= 1)
38965 +                       val =
38966 +                           w83781d_read_value(client,
38967 +                                              W83781D_REG_BEEP_INTS2) &
38968 +                           0x7f;
38969 +               if (*nrels_mag >= 1) {
38970 +                       data->beep_enable = BEEP_ENABLE_TO_REG(results[0]);
38971 +                       w83781d_write_value(client, W83781D_REG_BEEP_INTS2,
38972 +                                           val | data->beep_enable << 7);
38973 +               }
38974 +       }
38975 +}
38976 +
38977 +/* w83697hf only has two fans */
38978 +void w83781d_fan_div(struct i2c_client *client, int operation,
38979 +                    int ctl_name, int *nrels_mag, long *results)
38980 +{
38981 +       struct w83781d_data *data = client->data;
38982 +       int old, old2, old3 = 0;
38983 +
38984 +       if (operation == SENSORS_PROC_REAL_INFO)
38985 +               *nrels_mag = 0;
38986 +       else if (operation == SENSORS_PROC_REAL_READ) {
38987 +               w83781d_update_client(client);
38988 +               results[0] = DIV_FROM_REG(data->fan_div[0]);
38989 +               results[1] = DIV_FROM_REG(data->fan_div[1]);
38990 +               if (data->type == w83697hf) {
38991 +                       *nrels_mag = 2;
38992 +               } else {
38993 +                       results[2] = DIV_FROM_REG(data->fan_div[2]);
38994 +                       *nrels_mag = 3;
38995 +               }
38996 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
38997 +               old = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
38998 +               /* w83781d and as99127f don't have extended divisor bits */
38999 +               if ((data->type != w83781d) && data->type != as99127f) {
39000 +                       old3 =
39001 +                           w83781d_read_value(client, W83781D_REG_VBAT);
39002 +               }
39003 +               if (*nrels_mag >= 3 && data->type != w83697hf) {
39004 +                       data->fan_div[2] =
39005 +                           DIV_TO_REG(results[2], data->type);
39006 +                       old2 = w83781d_read_value(client, W83781D_REG_PIN);
39007 +                       old2 =
39008 +                           (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
39009 +                       w83781d_write_value(client, W83781D_REG_PIN, old2);
39010 +                       if ((data->type != w83781d) &&
39011 +                           (data->type != as99127f)) {
39012 +                               old3 =
39013 +                                   (old3 & 0x7f) |
39014 +                                   ((data->fan_div[2] & 0x04) << 5);
39015 +                       }
39016 +               }
39017 +               if (*nrels_mag >= 2) {
39018 +                       data->fan_div[1] =
39019 +                           DIV_TO_REG(results[1], data->type);
39020 +                       old =
39021 +                           (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
39022 +                       if ((data->type != w83781d) &&
39023 +                           (data->type != as99127f)) {
39024 +                               old3 =
39025 +                                   (old3 & 0xbf) |
39026 +                                   ((data->fan_div[1] & 0x04) << 4);
39027 +                       }
39028 +               }
39029 +               if (*nrels_mag >= 1) {
39030 +                       data->fan_div[0] =
39031 +                           DIV_TO_REG(results[0], data->type);
39032 +                       old =
39033 +                           (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
39034 +                       w83781d_write_value(client, W83781D_REG_VID_FANDIV,
39035 +                                           old);
39036 +                       if ((data->type != w83781d) &&
39037 +                           (data->type != as99127f)) {
39038 +                               old3 =
39039 +                                   (old3 & 0xdf) |
39040 +                                   ((data->fan_div[0] & 0x04) << 3);
39041 +                               w83781d_write_value(client,
39042 +                                                   W83781D_REG_VBAT,
39043 +                                                   old3);
39044 +                       }
39045 +               }
39046 +       }
39047 +}
39048 +
39049 +void w83781d_pwm(struct i2c_client *client, int operation, int ctl_name,
39050 +                int *nrels_mag, long *results)
39051 +{
39052 +       struct w83781d_data *data = client->data;
39053 +       int nr = 1 + ctl_name - W83781D_SYSCTL_PWM1;
39054 +       int j, k;
39055 +
39056 +       if (operation == SENSORS_PROC_REAL_INFO)
39057 +               *nrels_mag = 0;
39058 +       else if (operation == SENSORS_PROC_REAL_READ) {
39059 +               w83781d_update_client(client);
39060 +               results[0] = PWM_FROM_REG(data->pwm[nr - 1]);
39061 +               results[1] = data->pwmenable[nr - 1];
39062 +               *nrels_mag = 2;
39063 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
39064 +               if (*nrels_mag >= 1) {
39065 +                       data->pwm[nr - 1] = PWM_TO_REG(results[0]);
39066 +                       w83781d_write_value(client,
39067 +                                           W83781D_REG_PWM(data->type, nr),
39068 +                                           data->pwm[nr - 1]);
39069 +               }
39070 +               /* only PWM2 can be enabled/disabled */
39071 +               if (*nrels_mag >= 2 && nr == 2) {
39072 +                       j = w83781d_read_value(client, W83781D_REG_PWMCLK12);
39073 +                       k = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
39074 +                       if(results[1]) {
39075 +                               if(!(j & 0x08))
39076 +                                       w83781d_write_value(client,
39077 +                                            W83781D_REG_PWMCLK12, j | 0x08);
39078 +                               if(k & 0x10)
39079 +                                       w83781d_write_value(client,
39080 +                                            W83781D_REG_BEEP_CONFIG, k & 0xef);
39081 +                               data->pwmenable[1] = 1;
39082 +                       } else {
39083 +                               if(j & 0x08)
39084 +                                       w83781d_write_value(client,
39085 +                                            W83781D_REG_PWMCLK12, j & 0xf7);
39086 +                               if(!(k & 0x10))
39087 +                                       w83781d_write_value(client,
39088 +                                            W83781D_REG_BEEP_CONFIG, j | 0x10);
39089 +                               data->pwmenable[1] = 0;
39090 +                       }
39091 +               }
39092 +       }
39093 +}
39094 +
39095 +void w83781d_sens(struct i2c_client *client, int operation, int ctl_name,
39096 +                 int *nrels_mag, long *results)
39097 +{
39098 +       struct w83781d_data *data = client->data;
39099 +       int nr = 1 + ctl_name - W83781D_SYSCTL_SENS1;
39100 +       u8 tmp;
39101 +
39102 +       if (operation == SENSORS_PROC_REAL_INFO)
39103 +               *nrels_mag = 0;
39104 +       else if (operation == SENSORS_PROC_REAL_READ) {
39105 +               results[0] = data->sens[nr - 1];
39106 +               *nrels_mag = 1;
39107 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
39108 +               if (*nrels_mag >= 1) {
39109 +                       switch (results[0]) {
39110 +                       case 1: /* PII/Celeron diode */
39111 +                               tmp = w83781d_read_value(client,
39112 +                                                      W83781D_REG_SCFG1);
39113 +                               w83781d_write_value(client,
39114 +                                                   W83781D_REG_SCFG1,
39115 +                                                   tmp | BIT_SCFG1[nr -
39116 +                                                                   1]);
39117 +                               tmp = w83781d_read_value(client,
39118 +                                                      W83781D_REG_SCFG2);
39119 +                               w83781d_write_value(client,
39120 +                                                   W83781D_REG_SCFG2,
39121 +                                                   tmp | BIT_SCFG2[nr -
39122 +                                                                   1]);
39123 +                               data->sens[nr - 1] = results[0];
39124 +                               break;
39125 +                       case 2: /* 3904 */
39126 +                               tmp = w83781d_read_value(client,
39127 +                                                      W83781D_REG_SCFG1);
39128 +                               w83781d_write_value(client,
39129 +                                                   W83781D_REG_SCFG1,
39130 +                                                   tmp | BIT_SCFG1[nr -
39131 +                                                                   1]);
39132 +                               tmp = w83781d_read_value(client,
39133 +                                                      W83781D_REG_SCFG2);
39134 +                               w83781d_write_value(client,
39135 +                                                   W83781D_REG_SCFG2,
39136 +                                                   tmp & ~BIT_SCFG2[nr -
39137 +                                                                    1]);
39138 +                               data->sens[nr - 1] = results[0];
39139 +                               break;
39140 +                       case W83781D_DEFAULT_BETA:      /* thermistor */
39141 +                               tmp = w83781d_read_value(client,
39142 +                                                      W83781D_REG_SCFG1);
39143 +                               w83781d_write_value(client,
39144 +                                                   W83781D_REG_SCFG1,
39145 +                                                   tmp & ~BIT_SCFG1[nr -
39146 +                                                                    1]);
39147 +                               data->sens[nr - 1] = results[0];
39148 +                               break;
39149 +                       default:
39150 +                               printk
39151 +                                   (KERN_ERR "w83781d.o: Invalid sensor type %ld; must be 1, 2, or %d\n",
39152 +                                    results[0], W83781D_DEFAULT_BETA);
39153 +                               break;
39154 +                       }
39155 +               }
39156 +       }
39157 +}
39158 +
39159 +#ifdef W83781D_RT
39160 +static void w83781d_rt(struct i2c_client *client, int operation, int ctl_name,
39161 +               int *nrels_mag, long *results)
39162 +{
39163 +       struct w83781d_data *data = client->data;
39164 +       int nr = 1 + ctl_name - W83781D_SYSCTL_RT1;
39165 +       int i;
39166 +
39167 +       if (operation == SENSORS_PROC_REAL_INFO)
39168 +               *nrels_mag = 0;
39169 +       else if (operation == SENSORS_PROC_REAL_READ) {
39170 +               for (i = 0; i < 32; i++) {
39171 +                       results[i] = data->rt[nr - 1][i];
39172 +               }
39173 +               *nrels_mag = 32;
39174 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
39175 +               if (*nrels_mag > 32)
39176 +                       *nrels_mag = 32;
39177 +               for (i = 0; i < *nrels_mag; i++) {
39178 +                       /* fixme: no bounds checking 0-255 */
39179 +                       data->rt[nr - 1][i] = results[i];
39180 +                       w83781d_write_value(client, W83781D_REG_RT_IDX, i);
39181 +                       w83781d_write_value(client, W83781D_REG_RT_VAL,
39182 +                                           data->rt[nr - 1][i]);
39183 +               }
39184 +       }
39185 +}
39186 +#endif
39187 +
39188 +static int __init sm_w83781d_init(void)
39189 +{
39190 +       printk(KERN_INFO "w83781d.o version %s (%s)\n", LM_VERSION, LM_DATE);
39191 +       return i2c_add_driver(&w83781d_driver);
39192 +}
39193 +
39194 +static void __exit sm_w83781d_exit(void)
39195 +{
39196 +       i2c_del_driver(&w83781d_driver);
39197 +}
39198 +
39199 +
39200 +
39201 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
39202 +             "Philip Edelbrock <phil@netroedge.com>, "
39203 +             "and Mark Studebaker <mdsxyz123@yahoo.com>");
39204 +MODULE_DESCRIPTION("W83781D driver");
39205 +MODULE_LICENSE("GPL");
39206 +
39207 +module_init(sm_w83781d_init);
39208 +module_exit(sm_w83781d_exit);
39209 --- linux-old/drivers/sensors/w83l785ts.c       Thu Jan  1 00:00:00 1970
39210 +++ linux/drivers/sensors/w83l785ts.c   Mon Dec 13 20:18:54 2004
39211 @@ -0,0 +1,388 @@
39212 +/*
39213 + * w83l785ts.c - Part of lm_sensors, Linux kernel modules for hardware
39214 + *               monitoring
39215 + * Copyright (C) 2003-2004  Jean Delvare <khali@linux-fr.org>
39216 + *
39217 + * Inspired from the lm83 driver. The W83L785TS-S is a sensor chip made
39218 + * by Winbond. It reports a single external temperature with a 1 deg
39219 + * resolution and a 3 deg accuracy. Data sheet can be obtained from
39220 + * Winbond's website at:
39221 + *   http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83L785TS-S.pdf
39222 + *
39223 + * Thanks to James Bolt <james@evilpenguin.com> for benchmarking the read
39224 + * error handling mechanism.
39225 + *
39226 + * This program is free software; you can redistribute it and/or modify
39227 + * it under the terms of the GNU General Public License as published by
39228 + * the Free Software Foundation; either version 2 of the License, or
39229 + * (at your option) any later version.
39230 + *
39231 + * This program is distributed in the hope that it will be useful,
39232 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
39233 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39234 + * GNU General Public License for more details.
39235 + *
39236 + * You should have received a copy of the GNU General Public License
39237 + * along with this program; if not, write to the Free Software
39238 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39239 + */
39240 +
39241 +#include <linux/module.h>
39242 +#include <linux/slab.h>
39243 +#include <linux/i2c.h>
39244 +#include <linux/i2c-proc.h>
39245 +#include <linux/init.h>
39246 +#include <linux/delay.h>
39247 +#define LM_DATE "20041007"
39248 +#define LM_VERSION "2.8.8"
39249 +
39250 +#ifndef I2C_DRIVERID_W83L785TS
39251 +#define I2C_DRIVERID_W83L785TS 1047
39252 +#endif
39253 +
39254 +/* How many retries on register read error */
39255 +#define MAX_RETRIES    5
39256 +
39257 +/*
39258 + * Address to scan
39259 + * Address is fully defined internally and cannot be changed.
39260 + */
39261 +
39262 +static unsigned short normal_i2c[] = { 0x2e, SENSORS_I2C_END };
39263 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
39264 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
39265 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
39266 +
39267 +/*
39268 + * Insmod parameters
39269 + */
39270 +
39271 +SENSORS_INSMOD_1(w83l785ts);
39272 +
39273 +/*
39274 + * The W83L785TS-S registers
39275 + * Manufacturer ID is 0x5CA3 for Winbond.
39276 + */
39277 +
39278 +#define W83L785TS_REG_MAN_ID1          0x4D
39279 +#define W83L785TS_REG_MAN_ID2          0x4C
39280 +#define W83L785TS_REG_CHIP_ID          0x4E
39281 +#define W83L785TS_REG_CONFIG           0x40
39282 +#define W83L785TS_REG_TYPE             0x52
39283 +#define W83L785TS_REG_TEMP             0x27
39284 +#define W83L785TS_REG_TEMP_OVER                0x53 /* not sure about this one */
39285 +
39286 +/*
39287 + * Conversions
39288 + * The W83L785TS-S uses signed 8-bit values.
39289 + */
39290 +
39291 +#define TEMP_FROM_REG(val)     (val & 0x80 ? val-0x100 : val)
39292 +
39293 +/*
39294 + * Functions declaration
39295 + */
39296 +
39297 +static int w83l785ts_attach_adapter(struct i2c_adapter *adapter);
39298 +static int w83l785ts_detect(struct i2c_adapter *adapter, int address, unsigned
39299 +       short flags, int kind);
39300 +static int w83l785ts_detach_client(struct i2c_client *client);
39301 +static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval);
39302 +static void w83l785ts_update_client(struct i2c_client *client);
39303 +static void w83l785ts_temp(struct i2c_client *client, int operation, int
39304 +       ctl_name, int *nrels_mag, long *results);
39305 +
39306 +/*
39307 + * Driver data (common to all clients)
39308 + */
39309
39310 +static struct i2c_driver w83l785ts_driver = {
39311 +       .owner          = THIS_MODULE,
39312 +       .name           = "W83L785S-S sensor driver",
39313 +       .id             = I2C_DRIVERID_W83L785TS,
39314 +       .flags          = I2C_DF_NOTIFY,
39315 +       .attach_adapter = w83l785ts_attach_adapter,
39316 +       .detach_client  = w83l785ts_detach_client,
39317 +};
39318 +
39319 +/*
39320 + * Client data (each client gets its own)
39321 + */
39322 +
39323 +struct w83l785ts_data {
39324 +       struct i2c_client client;
39325 +       int sysctl_id;
39326 +
39327 +       struct semaphore update_lock;
39328 +       char valid; /* zero until following fields are valid */
39329 +       unsigned long last_updated; /* in jiffies */
39330 +
39331 +       /* registers values */
39332 +       u8 temp, temp_over;
39333 +};
39334 +
39335 +/*
39336 + * Proc entries
39337 + * These files are created for each detected W83L785TS-S.
39338 + */
39339 +
39340 +/* -- SENSORS SYSCTL START -- */
39341 +
39342 +#define W83L785TS_SYSCTL_TEMP  1200
39343 +
39344 +/* -- SENSORS SYSCTL END -- */
39345 +
39346 +
39347 +static ctl_table w83l785ts_dir_table_template[] =
39348 +{
39349 +       {W83L785TS_SYSCTL_TEMP, "temp", NULL, 0, 0444, NULL,
39350 +        &i2c_proc_real, &i2c_sysctl_real, NULL, &w83l785ts_temp},
39351 +       {0}
39352 +};
39353 +
39354 +/*
39355 + * Internal variables
39356 + */
39357 +
39358 +static int w83l785ts_id = 0;
39359 +
39360 +/*
39361 + * Real code
39362 + */
39363 +
39364 +static int w83l785ts_attach_adapter(struct i2c_adapter *adapter)
39365 +{
39366 +       return i2c_detect(adapter, &addr_data, w83l785ts_detect);
39367 +}
39368 +
39369 +/*
39370 + * The following function does more than just detection. If detection
39371 + * succeeds, it also registers the new chip.
39372 + */
39373 +static int w83l785ts_detect(struct i2c_adapter *adapter, int address,
39374 +       unsigned short flags, int kind)
39375 +{
39376 +       struct i2c_client *new_client;
39377 +       struct w83l785ts_data *data;
39378 +       int err = 0;
39379 +       const char *type_name = "";
39380 +       const char *client_name = "";
39381 +
39382 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
39383 +#ifdef DEBUG
39384 +               printk(KERN_DEBUG "w83l785ts.o: I2C bus doesn't support "
39385 +                       "byte read mode, skipping.\n");
39386 +#endif
39387 +               return 0;
39388 +       }
39389 +
39390 +       if (!(data = kmalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
39391 +               printk(KERN_ERR "w83l785ts.o: Out of memory in w83l785ts_detect "
39392 +                       "(new_client).\n");
39393 +               return -ENOMEM;
39394 +       }
39395 +
39396 +       /*
39397 +        * The common I2C client data is placed right after the
39398 +        * W83L785TS-specific. The W83L785TS-specific data is pointed to by the
39399 +        * data field from the I2C client data.
39400 +        */
39401 +
39402 +       new_client = &data->client;
39403 +       new_client->addr = address;
39404 +       new_client->data = data;
39405 +       new_client->adapter = adapter;
39406 +       new_client->driver = &w83l785ts_driver;
39407 +       new_client->flags = 0;
39408 +
39409 +       /*
39410 +        * Now we do the remaining detection. A negative kind means that
39411 +        * the driver was loaded with no force parameter (default), so we
39412 +        * must both detect and identify the chip (actually there is only
39413 +        * one possible kind of chip for now, W83L785TS-S). A zero kind means
39414 +        * that the driver was loaded with the force parameter, the detection
39415 +        * step shall be skipped. A positive kind means that the driver
39416 +        * was loaded with the force parameter and a given kind of chip is
39417 +        * requested, so both the detection and the identification steps
39418 +        * are skipped.
39419 +        */
39420 +
39421 +       if (kind < 0) { /* detection */
39422 +               if (((w83l785ts_read_value(new_client, W83L785TS_REG_CONFIG, 0)
39423 +                       & 0x80) != 0x00)
39424 +                || ((w83l785ts_read_value(new_client, W83L785TS_REG_TYPE, 0)
39425 +                       & 0xFC) != 0x00)) {
39426 +#ifdef DEBUG
39427 +                       printk(KERN_DEBUG "w83l785ts.o: Detection failed at "
39428 +                               "0x%02x.\n", address);
39429 +#endif
39430 +                       goto ERROR1;
39431 +               }
39432 +       }
39433 +
39434 +       if (kind <= 0) { /* identification */
39435 +               u16 man_id;
39436 +               u8 chip_id;
39437 +
39438 +               man_id = (w83l785ts_read_value(new_client, W83L785TS_REG_MAN_ID1, 0) << 8)
39439 +                      +  w83l785ts_read_value(new_client, W83L785TS_REG_MAN_ID2, 0);
39440 +               chip_id = w83l785ts_read_value(new_client, W83L785TS_REG_CHIP_ID, 0);
39441 +               if (man_id == 0x5CA3) { /* Winbond */
39442 +                       if (chip_id == 0x70)
39443 +                               kind = w83l785ts;
39444 +               }
39445 +       }
39446 +
39447 +       if (kind <= 0) { /* identification failed */
39448 +               printk(KERN_INFO "w83l785ts.o: Unsupported chip.\n");
39449 +               goto ERROR1;
39450 +       }
39451 +
39452 +       if (kind == w83l785ts) {
39453 +               type_name = "w83l785ts";
39454 +               client_name = "W83L785TS-S chip";
39455 +       } else {
39456 +               printk(KERN_ERR "w83l785ts.o: Unknown kind %d.\n", kind);
39457 +               goto ERROR1;
39458 +       }
39459 +       
39460 +       /*
39461 +        * OK, we got a valid chip so we can fill in the remaining client
39462 +        * fields.
39463 +        */
39464 +
39465 +       strcpy(new_client->name, client_name);
39466 +       new_client->id = w83l785ts_id++;
39467 +       data->valid = 0;
39468 +       init_MUTEX(&data->update_lock);
39469 +
39470 +       /*
39471 +        * Tell the I2C layer a new client has arrived.
39472 +        */
39473 +
39474 +       if ((err = i2c_attach_client(new_client))) {
39475 +#ifdef DEBUG
39476 +               printk(KERN_ERR "w83l785ts.o: Failed attaching client.\n");
39477 +#endif
39478 +               goto ERROR1;
39479 +       }
39480 +
39481 +       /*
39482 +        * Register a new directory entry.
39483 +        */
39484 +
39485 +       if ((err = i2c_register_entry(new_client, type_name,
39486 +           w83l785ts_dir_table_template)) < 0) {
39487 +#ifdef DEBUG
39488 +               printk(KERN_ERR "w83l785ts.o: Failed registering directory "
39489 +                       "entry.\n");
39490 +#endif
39491 +               goto ERROR2;
39492 +       }
39493 +       data->sysctl_id = err;
39494 +
39495 +       /*
39496 +        * Initialize the W83L785TS chip
39497 +        * Nothing yet, assume it is already started.
39498 +        */
39499 +
39500 +       return 0;
39501 +
39502 +       ERROR2:
39503 +       i2c_detach_client(new_client);
39504 +       ERROR1:
39505 +       kfree(data);
39506 +       return err;
39507 +}
39508 +
39509 +static int w83l785ts_detach_client(struct i2c_client *client)
39510 +{
39511 +       int err;
39512 +
39513 +       i2c_deregister_entry(((struct w83l785ts_data *) (client->data))->sysctl_id);
39514 +       if ((err = i2c_detach_client(client))) {
39515 +               printk(KERN_ERR "w83l785ts.o: Client deregistration failed, "
39516 +                       "client not detached.\n");
39517 +               return err;
39518 +       }
39519 +
39520 +       kfree(client->data);
39521 +       return 0;
39522 +}
39523 +
39524 +static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval)
39525 +{
39526 +       int value, i;
39527 +
39528 +       /* Frequent read errors have been reported on Asus boards, so we
39529 +        * retry on read errors. If it still fails (unlikely), return the
39530 +        * default value requested by the caller. */
39531 +       for (i = 1; i <= MAX_RETRIES; i++) {
39532 +               value = i2c_smbus_read_byte_data(client, reg);
39533 +               if (value >= 0)
39534 +                       return value;
39535 +               printk(KERN_WARNING "w83l785ts.o: Read failed, will retry "
39536 +                       "in %d.\n", i);
39537 +               mdelay(i);
39538 +       }
39539 +
39540 +       printk(KERN_ERR "w83l785ts.o: Couldn't read value from register. "
39541 +               "Please report.\n");
39542 +       return defval;
39543 +}
39544 +
39545 +static void w83l785ts_update_client(struct i2c_client *client)
39546 +{
39547 +       struct w83l785ts_data *data = client->data;
39548 +
39549 +       down(&data->update_lock);
39550 +
39551 +       if ((jiffies - data->last_updated > HZ * 2)
39552 +        || (jiffies < data->last_updated)
39553 +        || !data->valid) {
39554 +#ifdef DEBUG
39555 +               printk(KERN_DEBUG "w83l785ts.o: Updating data.\n");
39556 +#endif
39557 +               data->temp = w83l785ts_read_value(client, W83L785TS_REG_TEMP,
39558 +                       data->temp);
39559 +               data->temp_over = w83l785ts_read_value(client,
39560 +                       W83L785TS_REG_TEMP_OVER, data->temp_over);
39561 +               data->last_updated = jiffies;
39562 +               data->valid = 1;
39563 +       }
39564 +
39565 +       up(&data->update_lock);
39566 +}
39567 +
39568 +static void w83l785ts_temp(struct i2c_client *client, int operation,
39569 +       int ctl_name, int *nrels_mag, long *results)
39570 +{
39571 +       struct w83l785ts_data *data = client->data;
39572 +
39573 +       if (operation == SENSORS_PROC_REAL_INFO) {
39574 +               *nrels_mag = 0; /* magnitude */
39575 +       } else if (operation == SENSORS_PROC_REAL_READ) {
39576 +               w83l785ts_update_client(client);
39577 +               results[0] = TEMP_FROM_REG(data->temp_over);
39578 +               results[1] = TEMP_FROM_REG(data->temp);
39579 +               *nrels_mag = 2;
39580 +       }
39581 +}
39582 +
39583 +static int __init sm_w83l785ts_init(void)
39584 +{
39585 +       printk(KERN_INFO "w83l785ts.o version %s (%s)\n", LM_VERSION, LM_DATE);
39586 +       return i2c_add_driver(&w83l785ts_driver);
39587 +}
39588 +
39589 +static void __exit sm_w83l785ts_exit(void)
39590 +{
39591 +       i2c_del_driver(&w83l785ts_driver);
39592 +}
39593 +
39594 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
39595 +MODULE_DESCRIPTION("W83L785TS-S sensor driver");
39596 +MODULE_LICENSE("GPL");
39597 +
39598 +module_init(sm_w83l785ts_init);
39599 +module_exit(sm_w83l785ts_exit);
39600 --- linux-old/drivers/sensors/xeontemp.c        Thu Jan  1 00:00:00 1970
39601 +++ linux/drivers/sensors/xeontemp.c    Mon Dec 13 20:18:54 2004
39602 @@ -0,0 +1,388 @@
39603 +/*
39604 +    xeontemp.c - Part of lm_sensors, Linux kernel modules for hardware
39605 +             monitoring
39606 +    Copyright (c) 1998, 1999,2003  Frodo Looijaard <frodol@dds.nl>,
39607 +    Philip Edelbrock <phil@netroedge.com>, and
39608 +    Mark D. Studebaker <mdsxyz123@yahoo.com>
39609 +
39610 +    This program is free software; you can redistribute it and/or modify
39611 +    it under the terms of the GNU General Public License as published by
39612 +    the Free Software Foundation; either version 2 of the License, or
39613 +    (at your option) any later version.
39614 +
39615 +    This program is distributed in the hope that it will be useful,
39616 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
39617 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39618 +    GNU General Public License for more details.
39619 +
39620 +    You should have received a copy of the GNU General Public License
39621 +    along with this program; if not, write to the Free Software
39622 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39623 +*/
39624 +
39625 +/* The Xeon temperature sensor looks just like an ADM1021 with the remote
39626 +   sensor only. There is are no ID registers so detection is difficult. */
39627 +
39628 +#include <linux/module.h>
39629 +#include <linux/slab.h>
39630 +#include <linux/i2c.h>
39631 +#include <linux/i2c-proc.h>
39632 +#include <linux/init.h>
39633 +#define LM_DATE "20041007"
39634 +#define LM_VERSION "2.8.8"
39635 +
39636 +#ifndef I2C_DRIVERID_XEONTEMP
39637 +#define I2C_DRIVERID_XEONTEMP  1045
39638 +#endif
39639 +
39640 +/* Addresses to scan */
39641 +static unsigned short normal_i2c[] = { 0x18, 0x1a, 0x29, 0x2b,
39642 +       0x4c, 0x4e, SENSORS_I2C_END
39643 +};
39644 +static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
39645 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
39646 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
39647 +
39648 +/* Insmod parameters */
39649 +SENSORS_INSMOD_1(xeontemp);
39650 +
39651 +/* xeontemp constants specified below */
39652 +
39653 +/* The registers */
39654 +/* Read-only */
39655 +#define XEONTEMP_REG_REMOTE_TEMP 0x01
39656 +#define XEONTEMP_REG_STATUS 0x02
39657 +/* These use different addresses for reading/writing */
39658 +#define XEONTEMP_REG_CONFIG_R 0x03
39659 +#define XEONTEMP_REG_CONFIG_W 0x09
39660 +#define XEONTEMP_REG_CONV_RATE_R 0x04
39661 +#define XEONTEMP_REG_CONV_RATE_W 0x0A
39662 +/* limits */
39663 +#define XEONTEMP_REG_REMOTE_TOS_R 0x07
39664 +#define XEONTEMP_REG_REMOTE_TOS_W 0x0D
39665 +#define XEONTEMP_REG_REMOTE_THYST_R 0x08
39666 +#define XEONTEMP_REG_REMOTE_THYST_W 0x0E
39667 +/* write-only */
39668 +#define XEONTEMP_REG_ONESHOT 0x0F
39669 +
39670 +#define XEONTEMP_ALARM_RTEMP (XEONTEMP_ALARM_RTEMP_HIGH | XEONTEMP_ALARM_RTEMP_LOW\
39671 +                             | XEONTEMP_ALARM_RTEMP_NA)
39672 +#define XEONTEMP_ALARM_ALL  XEONTEMP_ALARM_RTEMP
39673 +
39674 +/* Conversions. Rounding and limit checking is only done on the TO_REG
39675 +   variants. Note that you should be a bit careful with which arguments
39676 +   these macros are called: arguments may be evaluated more than once.
39677 +   Fixing this is just not worth it. */
39678 +/* Conversions  note: 1021 uses normal integer signed-byte format*/
39679 +#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
39680 +#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
39681 +
39682 +/* Each client has this additional data */
39683 +struct xeontemp_data {
39684 +       struct i2c_client client;
39685 +       int sysctl_id;
39686 +       enum chips type;
39687 +
39688 +       struct semaphore update_lock;
39689 +       char valid;             /* !=0 if following fields are valid */
39690 +       unsigned long last_updated;     /* In jiffies */
39691 +
39692 +       u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms;
39693 +       u8 fail;
39694 +};
39695 +
39696 +static int xeontemp_attach_adapter(struct i2c_adapter *adapter);
39697 +static int xeontemp_detect(struct i2c_adapter *adapter, int address,
39698 +                         unsigned short flags, int kind);
39699 +static void xeontemp_init_client(struct i2c_client *client);
39700 +static int xeontemp_detach_client(struct i2c_client *client);
39701 +static int xeontemp_read_value(struct i2c_client *client, u8 reg);
39702 +static int xeontemp_rd_good(u8 *val, struct i2c_client *client, u8 reg, u8 mask);
39703 +static int xeontemp_write_value(struct i2c_client *client, u8 reg,
39704 +                              u16 value);
39705 +static void xeontemp_remote_temp(struct i2c_client *client, int operation,
39706 +                               int ctl_name, int *nrels_mag,
39707 +                               long *results);
39708 +static void xeontemp_alarms(struct i2c_client *client, int operation,
39709 +                          int ctl_name, int *nrels_mag, long *results);
39710 +static void xeontemp_update_client(struct i2c_client *client);
39711 +
39712 +/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
39713 +static int read_only = 0;
39714 +
39715 +
39716 +/* This is the driver that will be inserted */
39717 +static struct i2c_driver xeontemp_driver = {
39718 +       .owner          = THIS_MODULE,
39719 +       .name           = "Xeon temp sensor driver",
39720 +       .id             = I2C_DRIVERID_XEONTEMP,
39721 +       .flags          = I2C_DF_NOTIFY,
39722 +       .attach_adapter = xeontemp_attach_adapter,
39723 +       .detach_client  = xeontemp_detach_client,
39724 +};
39725 +
39726 +/* -- SENSORS SYSCTL START -- */
39727 +
39728 +#define XEONTEMP_SYSCTL_REMOTE_TEMP 1201
39729 +#define XEONTEMP_SYSCTL_ALARMS 1203
39730 +
39731 +#define XEONTEMP_ALARM_RTEMP_HIGH 0x10
39732 +#define XEONTEMP_ALARM_RTEMP_LOW 0x08
39733 +#define XEONTEMP_ALARM_RTEMP_NA 0x04
39734 +
39735 +/* -- SENSORS SYSCTL END -- */
39736 +
39737 +/* These files are created for each detected xeontemp. This is just a template;
39738 +   though at first sight, you might think we could use a statically
39739 +   allocated list, we need some way to get back to the parent - which
39740 +   is done through one of the 'extra' fields which are initialized
39741 +   when a new copy is allocated. */
39742 +static ctl_table xeontemp_dir_table_template[] = {
39743 +       {XEONTEMP_SYSCTL_REMOTE_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
39744 +        &i2c_sysctl_real, NULL, &xeontemp_remote_temp},
39745 +       {XEONTEMP_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
39746 +        &i2c_sysctl_real, NULL, &xeontemp_alarms},
39747 +       {0}
39748 +};
39749 +
39750 +static int xeontemp_id = 0;
39751 +
39752 +static int xeontemp_attach_adapter(struct i2c_adapter *adapter)
39753 +{
39754 +       return i2c_detect(adapter, &addr_data, xeontemp_detect);
39755 +}
39756 +
39757 +static int xeontemp_detect(struct i2c_adapter *adapter, int address,
39758 +                         unsigned short flags, int kind)
39759 +{
39760 +       int i;
39761 +       struct i2c_client *new_client;
39762 +       struct xeontemp_data *data;
39763 +       int err = 0;
39764 +       const char *type_name = "";
39765 +       const char *client_name = "";
39766 +
39767 +       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
39768 +               goto error0;
39769 +
39770 +       /* OK. For now, we presume we have a valid client. We now create the
39771 +          client structure, even though we cannot fill it completely yet.
39772 +          But it allows us to access xeontemp_{read,write}_value. */
39773 +
39774 +       if (!(data = kmalloc(sizeof(struct xeontemp_data), GFP_KERNEL))) {
39775 +               err = -ENOMEM;
39776 +               goto error0;
39777 +       }
39778 +
39779 +       new_client = &data->client;
39780 +       new_client->addr = address;
39781 +       new_client->data = data;
39782 +       new_client->adapter = adapter;
39783 +       new_client->driver = &xeontemp_driver;
39784 +       new_client->flags = 0;
39785 +
39786 +       /* Now, we do the remaining detection. */
39787 +
39788 +       if (kind < 0) {
39789 +               if (
39790 +                   (xeontemp_read_value(new_client, XEONTEMP_REG_STATUS) &
39791 +                    0x03) != 0x00)
39792 +                       goto error1;
39793 +       }
39794 +
39795 +       /* Determine the chip type. */
39796 +
39797 +       if (kind <= 0) {
39798 +               kind = xeontemp;
39799 +       }
39800 +
39801 +       type_name = "xeontemp";
39802 +       client_name = "xeon sensors";
39803 +
39804 +       /* Fill in the remaining client fields and put it into the global list */
39805 +       strcpy(new_client->name, client_name);
39806 +       data->type = kind;
39807 +
39808 +       new_client->id = xeontemp_id++;
39809 +       data->valid = 0;
39810 +       init_MUTEX(&data->update_lock);
39811 +
39812 +       /* Tell the I2C layer a new client has arrived */
39813 +       if ((err = i2c_attach_client(new_client)))
39814 +               goto error3;
39815 +
39816 +       /* Register a new directory entry with module sensors */
39817 +       if ((i = i2c_register_entry(new_client, type_name,
39818 +                                   xeontemp_dir_table_template)) < 0) {
39819 +               err = i;
39820 +               goto error4;
39821 +       }
39822 +       data->sysctl_id = i;
39823 +
39824 +       xeontemp_init_client(new_client);
39825 +       return 0;
39826 +
39827 +      error4:
39828 +       i2c_detach_client(new_client);
39829 +      error3:
39830 +      error1:
39831 +       kfree(data);
39832 +      error0:
39833 +       return err;
39834 +}
39835 +
39836 +static void xeontemp_init_client(struct i2c_client *client)
39837 +{
39838 +       /* Enable ADC and disable suspend mode */
39839 +       xeontemp_write_value(client, XEONTEMP_REG_CONFIG_W, 0);
39840 +       /* Set Conversion rate to 1/sec (this can be tinkered with) */
39841 +       xeontemp_write_value(client, XEONTEMP_REG_CONV_RATE_W, 0x04);
39842 +}
39843 +
39844 +static int xeontemp_detach_client(struct i2c_client *client)
39845 +{
39846 +
39847 +       int err;
39848 +
39849 +       i2c_deregister_entry(((struct xeontemp_data *) (client->data))->
39850 +                                sysctl_id);
39851 +
39852 +       if ((err = i2c_detach_client(client))) {
39853 +               printk
39854 +                   ("xeontemp.o: Client deregistration failed, client not detached.\n");
39855 +               return err;
39856 +       }
39857 +
39858 +       kfree(client->data);
39859 +
39860 +       return 0;
39861 +
39862 +}
39863 +
39864 +
39865 +/* All registers are byte-sized */
39866 +static int xeontemp_read_value(struct i2c_client *client, u8 reg)
39867 +{
39868 +       return i2c_smbus_read_byte_data(client, reg);
39869 +}
39870 +
39871 +/* only update value if read succeeded; set fail bit if failed */
39872 +static int xeontemp_rd_good(u8 *val, struct i2c_client *client, u8 reg, u8 mask)
39873 +{
39874 +       int i;
39875 +       struct xeontemp_data *data = client->data;
39876 +
39877 +       i = i2c_smbus_read_byte_data(client, reg);
39878 +       if (i < 0) {
39879 +               data->fail |= mask;
39880 +               return i;
39881 +       }
39882 +       *val = i;
39883 +       return 0;
39884 +}
39885 +
39886 +static int xeontemp_write_value(struct i2c_client *client, u8 reg, u16 value)
39887 +{
39888 +       if (read_only > 0)
39889 +               return 0;
39890 +
39891 +       return i2c_smbus_write_byte_data(client, reg, value);
39892 +}
39893 +
39894 +static void xeontemp_update_client(struct i2c_client *client)
39895 +{
39896 +       struct xeontemp_data *data = client->data;
39897 +
39898 +       down(&data->update_lock);
39899 +
39900 +       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
39901 +           (jiffies < data->last_updated) || !data->valid) {
39902 +
39903 +#ifdef DEBUG
39904 +               printk("Starting xeontemp update\n");
39905 +#endif
39906 +
39907 +               data->fail = 0;
39908 +               xeontemp_rd_good(&(data->remote_temp), client,
39909 +                               XEONTEMP_REG_REMOTE_TEMP, XEONTEMP_ALARM_RTEMP);
39910 +               xeontemp_rd_good(&(data->remote_temp_os), client,
39911 +                               XEONTEMP_REG_REMOTE_TOS_R, XEONTEMP_ALARM_RTEMP);
39912 +               xeontemp_rd_good(&(data->remote_temp_hyst), client,
39913 +                               XEONTEMP_REG_REMOTE_THYST_R,
39914 +                               XEONTEMP_ALARM_RTEMP);
39915 +               data->alarms = XEONTEMP_ALARM_ALL;
39916 +               if (!xeontemp_rd_good(&(data->alarms), client,
39917 +                                    XEONTEMP_REG_STATUS, 0))
39918 +                       data->alarms &= XEONTEMP_ALARM_ALL;
39919 +               data->last_updated = jiffies;
39920 +               data->valid = 1;
39921 +       }
39922 +
39923 +       up(&data->update_lock);
39924 +}
39925 +
39926 +void xeontemp_remote_temp(struct i2c_client *client, int operation,
39927 +                        int ctl_name, int *nrels_mag, long *results)
39928 +{
39929 +       struct xeontemp_data *data = client->data;
39930 +
39931 +       if (operation == SENSORS_PROC_REAL_INFO)
39932 +               *nrels_mag = 0;
39933 +       else if (operation == SENSORS_PROC_REAL_READ) {
39934 +               xeontemp_update_client(client);
39935 +               results[0] = TEMP_FROM_REG(data->remote_temp_os);
39936 +               results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
39937 +               results[2] = TEMP_FROM_REG(data->remote_temp);
39938 +               *nrels_mag = 3;
39939 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
39940 +               if (*nrels_mag >= 1) {
39941 +                       data->remote_temp_os = TEMP_TO_REG(results[0]);
39942 +                       xeontemp_write_value(client,
39943 +                                           XEONTEMP_REG_REMOTE_TOS_W,
39944 +                                           data->remote_temp_os);
39945 +               }
39946 +               if (*nrels_mag >= 2) {
39947 +                       data->remote_temp_hyst = TEMP_TO_REG(results[1]);
39948 +                       xeontemp_write_value(client,
39949 +                                           XEONTEMP_REG_REMOTE_THYST_W,
39950 +                                           data->remote_temp_hyst);
39951 +               }
39952 +       }
39953 +}
39954 +
39955 +void xeontemp_alarms(struct i2c_client *client, int operation, int ctl_name,
39956 +                   int *nrels_mag, long *results)
39957 +{
39958 +       struct xeontemp_data *data = client->data;
39959 +       if (operation == SENSORS_PROC_REAL_INFO)
39960 +               *nrels_mag = 0;
39961 +       else if (operation == SENSORS_PROC_REAL_READ) {
39962 +               xeontemp_update_client(client);
39963 +               results[0] = data->alarms | data->fail;
39964 +               *nrels_mag = 1;
39965 +       } else if (operation == SENSORS_PROC_REAL_WRITE) {
39966 +               /* Can't write to it */
39967 +       }
39968 +}
39969 +
39970 +static int __init sm_xeontemp_init(void)
39971 +{
39972 +       printk(KERN_INFO "xeontemp.o version %s (%s)\n", LM_VERSION, LM_DATE);
39973 +       return i2c_add_driver(&xeontemp_driver);
39974 +}
39975 +
39976 +static void __exit sm_xeontemp_exit(void)
39977 +{
39978 +       i2c_del_driver(&xeontemp_driver);
39979 +}
39980 +
39981 +MODULE_AUTHOR
39982 +    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
39983 +MODULE_DESCRIPTION("xeontemp driver");
39984 +MODULE_LICENSE("GPL");
39985 +
39986 +MODULE_PARM(read_only, "i");
39987 +MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
39988 +
39989 +module_init(sm_xeontemp_init)
39990 +module_exit(sm_xeontemp_exit)
39991 --- linux-old/include/linux/sensors_compat.h    Thu Jan  1 00:00:00 1970
39992 +++ linux/include/linux/sensors_compat.h        Mon Dec 13 20:18:54 2004
39993 @@ -0,0 +1,31 @@
39994 +/*
39995 + * Stolen from kernel 2.5.69
39996 + * device.h - generic, centralized driver model
39997 + * To make it easier to backport from 2.5
39998 + *
39999 + * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
40000 + *
40001 + */
40002 +
40003 +#ifndef _SENSORS_COMPAT_H_
40004 +#define _SENSORS_COMPAT_H_
40005 +
40006 +/* debugging and troubleshooting/diagnostic helpers. */
40007 +#define dev_printk(level, dev, format, arg...) \
40008 +       printk(level "%s: " format , (dev)->name , ## arg)
40009 +
40010 +#ifdef DEBUG
40011 +#define dev_dbg(dev, format, arg...)           \
40012 +       dev_printk(KERN_DEBUG , dev , format , ## arg)
40013 +#else
40014 +#define dev_dbg(dev, format, arg...) do {} while (0)
40015 +#endif
40016 +
40017 +#define dev_err(dev, format, arg...)           \
40018 +       dev_printk(KERN_ERR , dev , format , ## arg)
40019 +#define dev_info(dev, format, arg...)          \
40020 +       dev_printk(KERN_INFO , dev , format , ## arg)
40021 +#define dev_warn(dev, format, arg...)          \
40022 +       dev_printk(KERN_WARNING , dev , format , ## arg)
40023 +
40024 +#endif /* _SENSORS_COMPAT_H_ */
40025 --- linux-old/include/linux/sensors_vid.h       Thu Jan  1 00:00:00 1970
40026 +++ linux/include/linux/sensors_vid.h   Mon Dec 13 20:18:54 2004
40027 @@ -0,0 +1,95 @@
40028 +/*
40029 +    sensors_vid.h - Part of lm_sensors, Linux kernel modules for hardware
40030 +               monitoring
40031 +    Copyright (c) 2002-2004  Mark D. Studebaker <mdsxyz123@yahoo.com>
40032 +    With assistance from Trent Piepho <xyzzy@speakeasy.org>
40033 +
40034 +    This program is free software; you can redistribute it and/or modify
40035 +    it under the terms of the GNU General Public License as published by
40036 +    the Free Software Foundation; either version 2 of the License, or
40037 +    (at your option) any later version.
40038 +
40039 +    This program is distributed in the hope that it will be useful,
40040 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
40041 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40042 +    GNU General Public License for more details.
40043 +
40044 +    You should have received a copy of the GNU General Public License
40045 +    along with this program; if not, write to the Free Software
40046 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40047 +*/
40048 +
40049 +/*
40050 +    This file contains common code for decoding VID pins.
40051 +    This file is #included in various sensor chip drivers.
40052 +    As the user is unlikely to load more than one driver which
40053 +    includes this code we don't worry about the wasted space.
40054 +    References: VRM x.y DC-DC Converter Design Guidelines,
40055 +                VRD 10.0 Design Guide,
40056 +                available at http://developer.intel.com
40057 +*/
40058 +
40059 +/*
40060 +    AMD Opteron processors don't follow the Intel VRM spec.
40061 +    I'm going to "make up" 2.4 as the VRM spec for the Opterons.
40062 +    No good reason just a mnemonic for the 24x Opteron processor
40063 +    series
40064 +
40065 +    Opteron VID encoding is:
40066 +
40067 +       00000  =  1.550 V
40068 +       00001  =  1.525 V
40069 +        . . . .
40070 +       11110  =  0.800 V
40071 +       11111  =  0.000 V (off)
40072 + */
40073 +
40074 +/*
40075 +    Legal val values 00 - 1F except for VRD 10.0, 0x00-0x3f.
40076 +    vrm is the Intel VRM document version.
40077 +    Note: vrm version is scaled by 10 and the return value is scaled by 1000
40078 +    to avoid floating point in the kernel.
40079 +*/
40080 +
40081 +#define DEFAULT_VRM    82
40082 +
40083 +static inline int vid_from_reg(int val, int vrm)
40084 +{
40085 +       int vid;
40086 +
40087 +       switch(vrm) {
40088 +
40089 +       case 100:               /* VRD 10.0 */
40090 +               if((val & 0x1f) == 0x1f)
40091 +                       return 0;
40092 +               if((val & 0x1f) <= 0x09 || val == 0x0a)
40093 +                       vid = 10875 - (val & 0x1f) * 250;
40094 +               else
40095 +                       vid = 18625 - (val & 0x1f) * 250;
40096 +               if(val & 0x20)
40097 +                       vid -= 125;
40098 +               vid /= 10;      /* only return 3 dec. places for now */
40099 +               return vid;
40100 +
40101 +       case 24:                /* Opteron processor */
40102 +               return(val == 0x1f ? 0 : 1550 - val * 25);
40103 +
40104 +       case 91:                /* VRM 9.1 */
40105 +       case 90:                /* VRM 9.0 */
40106 +               return(val == 0x1f ? 0 :
40107 +                                      1850 - val * 25);
40108 +
40109 +       case 85:                /* VRM 8.5 */
40110 +               return((val & 0x10  ? 25 : 0) +
40111 +                      ((val & 0x0f) > 0x04 ? 2050 : 1250) -
40112 +                      ((val & 0x0f) * 50));
40113 +
40114 +       case 84:                /* VRM 8.4 */
40115 +               val &= 0x0f;
40116 +                               /* fall through */
40117 +       default:                /* VRM 8.2 */
40118 +               return(val == 0x1f ? 0 :
40119 +                      val & 0x10  ? 5100 - (val) * 100 :
40120 +                                    2050 - (val) * 50);
40121 +       }
40122 +}
40123 --- linux-old/drivers/sensors/Config.in Thu Jan  1 00:00:00 1970
40124 +++ linux/drivers/sensors/Config.in     Mon Dec 13 20:18:54 2004
40125 @@ -0,0 +1,62 @@
40126 +#
40127 +# Sensor device configuration
40128 +# All depend on CONFIG_I2C_PROC.
40129 +# ISA-only devices depend on CONFIG_I2C_ISA also.
40130 +#
40131 +
40132 +if [ "$CONFIG_I2C" = "m" -o "$CONFIG_I2C" = "y" ] ; then
40133 +if [ "$CONFIG_I2C_PROC" = "m" -o "$CONFIG_I2C_PROC" = "y" ] ; then
40134 +  mainmenu_option next_comment
40135 +  comment 'Hardware sensors support'
40136 +  
40137 +  dep_mbool 'Hardware sensors support' CONFIG_SENSORS $CONFIG_I2C $CONFIG_I2C_PROC
40138 +  
40139 +  if [ "$CONFIG_SENSORS" != "n" ]; then
40140 +    dep_tristate '  Analog Devices ADM1021 and compatibles' CONFIG_SENSORS_ADM1021 $CONFIG_I2C $CONFIG_I2C_PROC
40141 +    dep_tristate '  Analog Devices ADM1024' CONFIG_SENSORS_ADM1024 $CONFIG_I2C $CONFIG_I2C_PROC
40142 +    dep_tristate '  Analog Devices ADM1025' CONFIG_SENSORS_ADM1025 $CONFIG_I2C $CONFIG_I2C_PROC
40143 +    dep_tristate '  Analog Devices ADM1026' CONFIG_SENSORS_ADM1026 $CONFIG_I2C $CONFIG_I2C_PROC
40144 +    dep_tristate '  Analog Devices ADM9240 and compatibles' CONFIG_SENSORS_ADM9240 $CONFIG_I2C $CONFIG_I2C_PROC
40145 +    dep_tristate '  Asus ASB100' CONFIG_SENSORS_ASB100 $CONFIG_I2C $CONFIG_I2C_PROC
40146 +    dep_tristate '  Dallas DS1621 and DS1625' CONFIG_SENSORS_DS1621 $CONFIG_I2C $CONFIG_I2C_PROC
40147 +    dep_tristate '  Fujitsu-Siemens Poseidon' CONFIG_SENSORS_FSCPOS $CONFIG_I2C $CONFIG_I2C_PROC
40148 +    dep_tristate '  Fujitsu-Siemens Scylla' CONFIG_SENSORS_FSCSCY $CONFIG_I2C $CONFIG_I2C_PROC
40149 +    dep_tristate '  Genesys Logic GL518SM' CONFIG_SENSORS_GL518SM $CONFIG_I2C $CONFIG_I2C_PROC
40150 +    dep_tristate '  Genesys Logic GL520SM' CONFIG_SENSORS_GL520SM $CONFIG_I2C $CONFIG_I2C_PROC
40151 +    dep_tristate '  HP Maxilife' CONFIG_SENSORS_MAXILIFE $CONFIG_I2C $CONFIG_I2C_PROC
40152 +    dep_tristate '  Intel Xeon Thermal Sensor' CONFIG_SENSORS_XEONTEMP $CONFIG_I2C $CONFIG_I2C_PROC
40153 +    dep_tristate '  ITE 8705/8712, SiS950' CONFIG_SENSORS_IT87 $CONFIG_I2C $CONFIG_I2C_PROC
40154 +    dep_tristate '  Maxim MAX6650, MAX6651' CONFIG_SENSORS_MAX6650 $CONFIG_I2C $CONFIG_I2C_PROC
40155 +    dep_tristate '  Myson MTP008' CONFIG_SENSORS_MTP008 $CONFIG_I2C $CONFIG_I2C_PROC
40156 +    dep_tristate '  National Semiconductor LM75 and compatibles' CONFIG_SENSORS_LM75 $CONFIG_I2C $CONFIG_I2C_PROC
40157 +    dep_tristate '  National Semiconductor LM78' CONFIG_SENSORS_LM78 $CONFIG_I2C $CONFIG_I2C_PROC
40158 +    dep_tristate '  National Semiconductor LM80' CONFIG_SENSORS_LM80 $CONFIG_I2C $CONFIG_I2C_PROC
40159 +    dep_tristate '  National Semiconductor LM83' CONFIG_SENSORS_LM83 $CONFIG_I2C $CONFIG_I2C_PROC
40160 +    dep_tristate '  National Semiconductor LM85, Analog Devices ADM1027' CONFIG_SENSORS_LM85 $CONFIG_I2C $CONFIG_I2C_PROC
40161 +    dep_tristate '  National Semiconductor LM87' CONFIG_SENSORS_LM87 $CONFIG_I2C $CONFIG_I2C_PROC
40162 +    dep_tristate '  National Semiconductor LM90 and compatibles' CONFIG_SENSORS_LM90 $CONFIG_I2C $CONFIG_I2C_PROC
40163 +    dep_tristate '  National Semiconductor LM92' CONFIG_SENSORS_LM92 $CONFIG_I2C $CONFIG_I2C_PROC
40164 +    dep_tristate '  National Semiconductor PC8736x Sensors' CONFIG_SENSORS_PC87360 $CONFIG_I2C $CONFIG_I2C_PROC
40165 +    dep_tristate '  Silicon Integrated Systems Corp. SiS5595' CONFIG_SENSORS_SIS5595 $CONFIG_I2C $CONFIG_I2C_PROC $CONFIG_I2C_ISA
40166 +    dep_tristate '  SMSC47M1xx Integrated Sensors' CONFIG_SENSORS_SMSC47M1 $CONFIG_I2C $CONFIG_I2C_PROC $CONFIG_I2C_ISA
40167 +    dep_tristate '  Texas Instruments THMC50 and compatibles' CONFIG_SENSORS_THMC50 $CONFIG_I2C $CONFIG_I2C_PROC
40168 +    dep_tristate '  VIA 686a Integrated Hardware Monitor' CONFIG_SENSORS_VIA686A $CONFIG_I2C $CONFIG_I2C_PROC $CONFIG_I2C_ISA
40169 +    dep_tristate '  VIA VT1211 Integrated Sensors' CONFIG_SENSORS_VT1211 $CONFIG_I2C $CONFIG_I2C_PROC $CONFIG_I2C_ISA
40170 +    dep_tristate '  VIA VT8231 Integrated Sensors' CONFIG_SENSORS_VT8231 $CONFIG_I2C $CONFIG_I2C_PROC $CONFIG_I2C_ISA
40171 +    dep_tristate '  Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F' CONFIG_SENSORS_W83781D $CONFIG_I2C $CONFIG_I2C_PROC
40172 +    dep_tristate '  Winbond W83627HF, W83627THF, W83697HF' CONFIG_SENSORS_W83627HF $CONFIG_I2C $CONFIG_I2C_PROC $CONFIG_I2C_ISA
40173 +    dep_tristate '  Winbond W83L785TS-S' CONFIG_SENSORS_W83L785TS $CONFIG_I2C $CONFIG_I2C_PROC
40174 +    bool 'Other I2C devices' CONFIG_SENSORS_OTHER 
40175 +    if [ "$CONFIG_SENSORS_OTHER" = "y" ] ; then
40176 +      dep_tristate '  Brooktree BT869 Video Modulator' CONFIG_SENSORS_BT869 $CONFIG_I2C $CONFIG_I2C_PROC
40177 +      dep_tristate '  DDC Monitor EDID EEPROM' CONFIG_SENSORS_DDCMON $CONFIG_I2C $CONFIG_I2C_PROC
40178 +      dep_tristate '  EEprom (DIMM) reader ' CONFIG_SENSORS_EEPROM $CONFIG_I2C $CONFIG_I2C_PROC
40179 +      dep_tristate '  Matrix-Orbital LCD Displays' CONFIG_SENSORS_MATORB $CONFIG_I2C $CONFIG_I2C_PROC
40180 +      dep_tristate '  Philips PCF8574 Parallel I/O' CONFIG_SENSORS_PCF8574 $CONFIG_I2C $CONFIG_I2C_PROC
40181 +      dep_tristate '  Philips PCF8591 D/A and A/D' CONFIG_SENSORS_PCF8591 $CONFIG_I2C $CONFIG_I2C_PROC
40182 +    fi
40183 +  fi
40184 +  endmenu
40185 +fi
40186 +fi
40187 +
40188 --- linux-old/Makefile  Sat Aug 14 18:38:44 2004
40189 +++ linux/Makefile      Mon Dec 13 20:18:54 2004
40190 @@ -195,6 +195,7 @@
40191  DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
40192  DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o
40193  
40194 +DRIVERS-$(CONFIG_SENSORS) += drivers/sensors/sensor.o
40195  DRIVERS := $(DRIVERS-y)
40196  
40197  
40198 --- linux-old/drivers/Makefile  Mon Nov 17 01:07:35 2003
40199 +++ linux/drivers/Makefile      Mon Dec 13 20:18:54 2004
40200 @@ -8,7 +8,7 @@
40201  
40202  mod-subdirs := dio hil mtd sbus video macintosh usb input telephony ide \
40203                 message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
40204 -               fc4 net/hamradio i2c acpi bluetooth usb/gadget
40205 +               fc4 net/hamradio i2c acpi bluetooth usb/gadget sensors
40206  
40207  subdir-y :=    parport char block net sound misc media cdrom hotplug
40208  subdir-m :=    $(subdir-y)
40209 @@ -45,6 +45,7 @@
40210  # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set  -- ch
40211  subdir-$(CONFIG_HAMRADIO)      += net/hamradio
40212  subdir-$(CONFIG_I2C)           += i2c
40213 +subdir-$(CONFIG_SENSORS)       += sensors
40214  subdir-$(CONFIG_ACPI_BOOT)     += acpi
40215  
40216  subdir-$(CONFIG_BLUEZ)         += bluetooth
40217 --- linux-old/drivers/sensors/Makefile  Thu Jan  1 00:00:00 1970
40218 +++ linux/drivers/sensors/Makefile      Mon Dec 13 20:18:54 2004
40219 @@ -0,0 +1,49 @@
40220 +#
40221 +# Makefile for the kernel hardware sensors drivers.
40222 +#
40223 +
40224 +MOD_LIST_NAME := SENSORS_MODULES
40225 +O_TARGET := sensor.o
40226 +
40227 +obj-$(CONFIG_SENSORS_ADM1021)  += adm1021.o
40228 +obj-$(CONFIG_SENSORS_ADM1024)  += adm1024.o
40229 +obj-$(CONFIG_SENSORS_ADM1025)  += adm1025.o
40230 +obj-$(CONFIG_SENSORS_ADM1026)  += adm1026.o
40231 +obj-$(CONFIG_SENSORS_ADM9240)  += adm9240.o
40232 +obj-$(CONFIG_SENSORS_ASB100)   += asb100.o
40233 +obj-$(CONFIG_SENSORS_BT869)    += bt869.o
40234 +obj-$(CONFIG_SENSORS_DDCMON)   += ddcmon.o
40235 +obj-$(CONFIG_SENSORS_DS1621)   += ds1621.o
40236 +obj-$(CONFIG_SENSORS_EEPROM)   += eeprom.o
40237 +obj-$(CONFIG_SENSORS_FSCPOS)   += fscpos.o
40238 +obj-$(CONFIG_SENSORS_FSCSCY)   += fscscy.o
40239 +obj-$(CONFIG_SENSORS_GL518SM)  += gl518sm.o
40240 +obj-$(CONFIG_SENSORS_GL520SM)  += gl520sm.o
40241 +obj-$(CONFIG_SENSORS_IT87)     += it87.o
40242 +obj-$(CONFIG_SENSORS_LM75)     += lm75.o
40243 +obj-$(CONFIG_SENSORS_LM78)     += lm78.o
40244 +obj-$(CONFIG_SENSORS_LM80)     += lm80.o
40245 +obj-$(CONFIG_SENSORS_LM83)     += lm83.o
40246 +obj-$(CONFIG_SENSORS_LM85)     += lm85.o
40247 +obj-$(CONFIG_SENSORS_LM87)     += lm87.o
40248 +obj-$(CONFIG_SENSORS_LM90)     += lm90.o
40249 +obj-$(CONFIG_SENSORS_LM92)     += lm92.o
40250 +obj-$(CONFIG_SENSORS_MAX6650)  += max6650.o
40251 +obj-$(CONFIG_SENSORS_MAXILIFE) += maxilife.o
40252 +obj-$(CONFIG_SENSORS_MTP008)   += mtp008.o
40253 +obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
40254 +obj-$(CONFIG_SENSORS_PCF8574)  += pcf8574.o
40255 +obj-$(CONFIG_SENSORS_PCF8591)  += pcf8591.o
40256 +obj-$(CONFIG_SENSORS_SIS5595)  += sis5595.o
40257 +obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
40258 +obj-$(CONFIG_SENSORS_THMC50)   += thmc50.o
40259 +obj-$(CONFIG_SENSORS_VIA686A)  += via686a.o
40260 +obj-$(CONFIG_SENSORS_VT1211)   += vt1211.o
40261 +obj-$(CONFIG_SENSORS_VT8231)   += vt8231.o
40262 +obj-$(CONFIG_SENSORS_W83781D)  += w83781d.o
40263 +obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
40264 +obj-$(CONFIG_SENSORS_W83L785TS)        += w83l785ts.o
40265 +obj-$(CONFIG_SENSORS_XEONTEMP) += xeontemp.o
40266 +
40267 +include $(TOPDIR)/Rules.make
40268 +
40269 --- linux-old/drivers/char/Config.in    Sat Aug 14 18:38:49 2004
40270 +++ linux/drivers/char/Config.in        Mon Dec 13 20:18:54 2004
40271 @@ -191,6 +191,8 @@
40272  
40273  source drivers/i2c/Config.in
40274  
40275 +source drivers/sensors/Config.in
40276 +
40277  mainmenu_option next_comment
40278  comment 'Mice'
40279  tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
40280 --- linux-old/drivers/i2c/Config.in     Wed Jul  7 00:38:02 2004
40281 +++ linux/drivers/i2c/Config.in Mon Dec 13 20:18:54 2004
40282 @@ -63,6 +63,30 @@
40283     fi
40284   
40285  # This is needed for automatic patch generation: sensors code starts here
40286 +  bool 'I2C mainboard interfaces' CONFIG_I2C_MAINBOARD 
40287 +  if [ "$CONFIG_I2C_MAINBOARD" = "y" ]; then
40288 +    dep_tristate '  Acer Labs ALI 1535' CONFIG_I2C_ALI1535 $CONFIG_I2C
40289 +    dep_tristate '  Acer Labs ALI 1533 and 1543C' CONFIG_I2C_ALI15X3 $CONFIG_I2C
40290 +    dep_tristate '  Apple Hydra Mac I/O' CONFIG_I2C_HYDRA $CONFIG_I2C_ALGOBIT
40291 +    dep_tristate '  AMD 756/766/768/8111' CONFIG_I2C_AMD756 $CONFIG_I2C
40292 +    dep_tristate '  AMD 8111 SMBus 2.0' CONFIG_I2C_AMD8111 $CONFIG_I2C
40293 +    if [ "$CONFIG_ALPHA" = "y" ]; then
40294 +      dep_tristate '  DEC Tsunami I2C interface' CONFIG_I2C_TSUNAMI $CONFIG_I2C_ALGOBIT
40295 +    fi
40296 +    dep_tristate '  Intel 82801AA, AB, BA, DB' CONFIG_I2C_I801 $CONFIG_I2C
40297 +    dep_tristate '  Intel i810AA/AB/E and i815' CONFIG_I2C_I810 $CONFIG_I2C_ALGOBIT
40298 +    dep_tristate '  Intel 82371AB PIIX4(E), 443MX, ServerWorks OSB4/CSB5, SMSC Victory66' CONFIG_I2C_PIIX4 $CONFIG_I2C
40299 +    dep_tristate '  Nvidia Nforce2' CONFIG_I2C_NFORCE2 $CONFIG_I2C
40300 +    dep_tristate '  SiS 5595' CONFIG_I2C_SIS5595 $CONFIG_I2C
40301 +    dep_tristate '  SiS 630/730' CONFIG_I2C_SIS630 $CONFIG_I2C
40302 +    dep_tristate '  SiS 645/961,645DX/961,735' CONFIG_I2C_SIS645 $CONFIG_I2C $CONFIG_HOTPLUG
40303 +    dep_tristate '  Savage 4' CONFIG_I2C_SAVAGE4 $CONFIG_I2C_ALGOBIT
40304 +    dep_tristate '  VIA Technologies, Inc. VT82C586B' CONFIG_I2C_VIA $CONFIG_I2C_ALGOBIT
40305 +    dep_tristate '  VIA Technologies, Inc. VT596A/B, 686A/B, 8231, 8233, 8233A, 8235' CONFIG_I2C_VIAPRO $CONFIG_I2C
40306 +    dep_tristate '  Voodoo3 I2C interface' CONFIG_I2C_VOODOO3 $CONFIG_I2C_ALGOBIT
40307 +    dep_tristate '  Pseudo ISA adapter (for some hardware sensors)' CONFIG_I2C_ISA $CONFIG_I2C
40308 +  fi
40309 +
40310  # This is needed for automatic patch generation: sensors code ends here
40311  
40312     dep_tristate 'I2C device interface' CONFIG_I2C_CHARDEV $CONFIG_I2C
40313 --- linux-old/drivers/i2c/Makefile      Wed Jul  7 00:38:02 2004
40314 +++ linux/drivers/i2c/Makefile  Mon Dec 13 20:18:54 2004
40315 @@ -28,6 +28,24 @@
40316  obj-$(CONFIG_I2C_ALGO_AU1550)  += i2c-algo-au1550.o i2c-au1550.o
40317  
40318  # This is needed for automatic patch generation: sensors code starts here
40319 +obj-$(CONFIG_I2C_ALI1535)              += i2c-ali1535.o
40320 +obj-$(CONFIG_I2C_ALI15X3)              += i2c-ali15x3.o
40321 +obj-$(CONFIG_I2C_AMD756)               += i2c-amd756.o
40322 +obj-$(CONFIG_I2C_AMD8111)              += i2c-amd8111.o
40323 +obj-$(CONFIG_I2C_HYDRA)                        += i2c-hydra.o
40324 +obj-$(CONFIG_I2C_I801)                 += i2c-i801.o
40325 +obj-$(CONFIG_I2C_I810)                 += i2c-i810.o
40326 +obj-$(CONFIG_I2C_ISA)                  += i2c-isa.o
40327 +obj-$(CONFIG_I2C_NFORCE2)              += i2c-nforce2.o
40328 +obj-$(CONFIG_I2C_PIIX4)                        += i2c-piix4.o
40329 +obj-$(CONFIG_I2C_SIS5595)              += i2c-sis5595.o
40330 +obj-$(CONFIG_I2C_SIS630)               += i2c-sis630.o
40331 +obj-$(CONFIG_I2C_SIS645)               += i2c-sis645.o
40332 +obj-$(CONFIG_I2C_SAVAGE4)              += i2c-savage4.o
40333 +obj-$(CONFIG_I2C_TSUNAMI)              += i2c-tsunami.o
40334 +obj-$(CONFIG_I2C_VIA)                  += i2c-via.o
40335 +obj-$(CONFIG_I2C_VIAPRO)               += i2c-viapro.o
40336 +obj-$(CONFIG_I2C_VOODOO3)              += i2c-voodoo3.o
40337  # This is needed for automatic patch generation: sensors code ends here
40338  
40339  include $(TOPDIR)/Rules.make
40340 --- linux-old/Documentation/Configure.help      Mon Dec 13 20:09:52 2004
40341 +++ linux/Documentation/Configure.help  Mon Dec 13 20:18:56 2004
40342 @@ -29449,4 +29449,527 @@
40343  # fill-prefix:"  "
40344  # adaptive-fill:nil
40345  # fill-column:70
40346 +I2C mainboard interfaces
40347 +CONFIG_I2C_MAINBOARD
40348 +  Many modern mainboards have some kind of I2C interface integrated. This
40349 +  is often in the form of a SMBus, or System Management Bus, which is
40350 +  basically the same as I2C but which uses only a subset of the I2C
40351 +  protocol.
40352 +
40353 +  You will also want the latest user-space utilties: you can find them
40354 +  in the lm_sensors package, which you can download at 
40355 +  http://www.lm-sensors.nu
40356 +
40357 +Acer Labs ALI 1535
40358 +CONFIG_I2C_ALI1535
40359 +  If you say yes to this option, support will be included for the Acer
40360 +  Labs ALI 1535 mainboard I2C interface. This can also be 
40361 +  built as a module.
40362 +
40363 +Acer Labs ALI 1533 and 1543C
40364 +CONFIG_I2C_ALI15X3
40365 +  If you say yes to this option, support will be included for the Acer
40366 +  Labs ALI 1533 and 1543C mainboard I2C interfaces. This can also be 
40367 +  built as a module which can be inserted and removed while the kernel
40368 +  is running.
40369 +
40370 +AMD 756/766/768/8111
40371 +CONFIG_I2C_AMD756
40372 +  If you say yes to this option, support will be included for the AMD
40373 +  756/766/768/8111 mainboard I2C interfaces. This can also be 
40374 +  built as a module which can be inserted and removed while the kernel
40375 +  is running.
40376 +
40377 +AMD 8111 SMBus 2.0
40378 +CONFIG_I2C_AMD8111
40379 +  If you say yes to this option, support will be included for the AMD
40380 +  8111 mainboard SMBus 2.0 interface. This can also be 
40381 +  built as a module which can be inserted and removed while the kernel
40382 +  is running.
40383 +
40384 +Apple Hydra Mac I/O
40385 +CONFIG_I2C_HYDRA
40386 +  If you say yes to this option, support will be included for the 
40387 +  Hydra mainboard I2C interface. This can also be built as a module 
40388 +  which can be inserted and removed while the kernel is running.
40389 +
40390 +Intel I801
40391 +CONFIG_I2C_I801
40392 +  If you say yes to this option, support will be included for the 
40393 +  Intel I801 mainboard I2C interfaces. "I810" mainboard sensor chips are
40394 +  generally located on the I801's I2C bus. This can also be
40395 +  built as a module which can be inserted and removed while the kernel
40396 +  is running.
40397 +
40398 +Intel I810/I815 based Mainboard
40399 +CONFIG_I2C_I810
40400 +  If you say yes to this option, support will be included for the 
40401 +  Intel I810/I815 mainboard I2C interfaces. The I2C busses these chips
40402 +  are generally used only for video devices. For "810" mainboard sensor
40403 +  chips, use the I801 I2C driver instead. This can also be
40404 +  built as a module which can be inserted and removed while the kernel
40405 +  is running.
40406 +
40407 +Intel 82371AB PIIX4(E) / ServerWorks OSB4 and CSB5
40408 +CONFIG_I2C_PIIX4
40409 +  If you say yes to this option, support will be included for the 
40410 +  Intel PIIX4, PIIX4E, and 443MX, Serverworks OSB4/CSB5,
40411 +  and SMSC Victory66 mainboard
40412 +  I2C interfaces. This can also be
40413 +  built as a module which can be inserted and removed while the kernel
40414 +  is running.
40415 +
40416 +Nvidia Nforce2 based Mainboard
40417 +CONFIG_I2C_NFORCE2
40418 +  If you say yes to this option, support will be included for the 
40419 +  Nvidia Nforce2 family of mainboard I2C interfaces. This can also be
40420 +  built as a module which can be inserted and removed while the kernel
40421 +  is running.
40422 +
40423 +Silicon Integrated Systems Corp. SiS5595 based Mainboard
40424 +CONFIG_I2C_SIS5595
40425 +  If you say yes to this option, support will be included for the 
40426 +  SiS5595 mainboard I2C interfaces. For integrated sensors on the
40427 +  Sis5595, use CONFIG_SENSORS_SIS5595. This can also be
40428 +  built as a module which can be inserted and removed while the kernel
40429 +  is running.
40430 +
40431 +Silicon Integrated Systems Corp. SiS630/730 based Mainboard
40432 +CONFIG_I2C_SIS630
40433 +  If you say yes to this option, support will be included for the SiS 630
40434 +  and 730 mainboard I2C interfaces. This can also be built as a module 
40435 +  which can be inserted and removed while the kernel is running.
40436 +
40437 +Silicon Integrated Systems Corp. SiS645/961,645DX/961,735 based Mainboard
40438 +CONFIG_I2C_SIS645
40439 +  If you say yes to this option, support will be included for the SiS 645/961,
40440 +  645DX/961 and 735 mainboard I2C interfaces. This can also be built as a module
40441 +  which can be inserted and removed while the kernel is running.
40442 +
40443 +VIA Technologies, Inc. VT82C586B
40444 +CONFIG_I2C_VIA
40445 +  If you say yes to this option, support will be included for the VIA
40446 +  Technologies I2C adapter found on some motherboards. This can also 
40447 +  be built as a module which can be inserted and removed while the 
40448 +  kernel is running.
40449 +
40450 +VIA Technologies, Inc. VT82C596, 596B, 686A/B, 8233, 8235
40451 +CONFIG_I2C_VIAPRO
40452 +  If you say yes to this option, support will be included for the VIA
40453 +  Technologies I2C adapter on these chips. For integrated sensors on the
40454 +  Via 686A/B, use CONFIG_SENSORS_VIA686A. This can also be
40455 +  be built as a module which can be inserted and removed while the 
40456 +  kernel is running.
40457 +
40458 +3DFX Banshee / Voodoo3
40459 +CONFIG_I2C_VOODOO3
40460 +  If you say yes to this option, support will be included for the 
40461 +  3DFX Banshee and Voodoo3 I2C interfaces. The I2C busses on the these
40462 +  chips are generally used only for video devices.
40463 +  This can also be
40464 +  built as a module which can be inserted and removed while the kernel
40465 +  is running.
40466 +
40467 +DEC Tsunami 21272
40468 +CONFIG_I2C_TSUNAMI
40469 +  If you say yes to this option, support will be included for the DEC
40470 +  Tsunami chipset I2C adapter. Requires the Alpha architecture;
40471 +  do not enable otherwise. This can also be built as a module which
40472 +  can be inserted and removed while the kernel is running.
40473 +
40474 +Pseudo ISA adapter (for hardware sensors modules)
40475 +CONFIG_I2C_ISA
40476 +  This provides support for accessing some hardware sensor chips over
40477 +  the ISA bus rather than the I2C or SMBus. If you want to do this, 
40478 +  say yes here. This feature can also be built as a module which can 
40479 +  be inserted and removed while the kernel is running.
40480 +
40481 +  You will also need the latest user-space utilties: you can find them
40482 +  in the lm_sensors package, which you can download at 
40483 +  http://www.lm-sensors.nu
40484 +
40485 +Analog Devices ADM1021 and compatibles
40486 +CONFIG_SENSORS_ADM1021
40487 +  If you say yes here you get support for Analog Devices ADM1021 
40488 +  and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
40489 +  Genesys Logic GL523SM, National Semi LM84, TI THMC10 and Onsemi
40490 +  MC1066. This can also be built as a module which can be inserted
40491 +  and removed while the kernel is running.
40492 +
40493 +  You will also need the latest user-space utilties: you can find them
40494 +  in the lm_sensors package, which you can download at 
40495 +  http://www.lm-sensors.nu
40496 +
40497 +Analog Devices ADM1024
40498 +CONFIG_SENSORS_ADM1024
40499 +  If you say yes here you get support for Analog Devices ADM1024 sensor
40500 +  chips.  This can also be built as a module.
40501 +
40502 +  You will also need the latest user-space utilties: you can find them
40503 +  in the lm_sensors package, which you can download at 
40504 +  http://www.lm-sensors.nu
40505 +
40506 +Analog Devices ADM1025
40507 +CONFIG_SENSORS_ADM1025
40508 +  If you say yes here you get support for Analog Devices ADM1025 sensor
40509 +  chips.  This can also be built as a module which can be inserted and
40510 +  removed while the kernel is running.
40511 +
40512 +  You will also need the latest user-space utilties: you can find them
40513 +  in the lm_sensors package, which you can download at 
40514 +  http://www.lm-sensors.nu
40515 +
40516 +Analog Devices ADM1026
40517 +CONFIG_SENSORS_ADM1026
40518 +  If you say yes here you get support for Analog Devices ADM1026 sensor
40519 +  chips.  This can also be built as a module which can be inserted and
40520 +  removed while the kernel is running.
40521 +
40522 +  You will also need the latest user-space utilties: you can find them
40523 +  in the lm_sensors package, which you can download at 
40524 +  http://www.lm-sensors.nu
40525 +
40526 +Analog Devices ADM9240 and compatibles
40527 +CONFIG_SENSORS_ADM9240
40528 +  If you say yes here you get support for Analog Devices ADM9240 
40529 +  sensor chips and clones: the Dallas Semiconductor DS1780 and
40530 +  the National Semiconductor LM81. This can also be built as a 
40531 +  module which can be inserted and removed while the kernel is
40532 +  running.
40533 +
40534 +  You will also need the latest user-space utilties: you can find them
40535 +  in the lm_sensors package, which you can download at 
40536 +  http://www.lm-sensors.nu
40537 +
40538 +Asus ASB100
40539 +CONFIG_SENSORS_ASB100
40540 +  If you say yes here you get support for the Asus ASB100 (aka
40541 +  "Bach") sensor chip.  This can also be built as a module.
40542 +
40543 +  You will also need the latest user-space utilities: you can find
40544 +  them in the lm_sensors package, which you can download at
40545 +  http://www.lm-sensors.nu/
40546 +
40547 +Dallas DS1621 and DS1625
40548 +CONFIG_SENSORS_DS1621
40549 +  If you say yes here you get support for the Dallas DS1621 and DS1625x
40550 +  sensor chips.  This can also be built as a module.
40551 +
40552 +  You will also need the latest user-space utilties: you can find them
40553 +  in the lm_sensors package, which you can download at 
40554 +  http://www.lm-sensors.nu
40555 +
40556 +Fujitsu-Siemens Poseidon
40557 +CONFIG_SENSORS_FSCPOS
40558 +  If you say yes here you get support for the Fujitsu-Siemens Poseidon
40559 +  sensor chip.  This can also be built as a module.
40560 +
40561 +  You will also need the latest user-space utilties: you can find them
40562 +  in the lm_sensors package, which you can download at 
40563 +  http://www.lm-sensors.nu
40564 +
40565 +Fujitsu-Siemens Scylla
40566 +CONFIG_SENSORS_FSCSCY
40567 +  If you say yes here you get support for the Fujitsu-Siemens Scylla
40568 +  sensor chip.  This can also be built as a module. This driver may/should
40569 +  also work with the following Fujitsu-Siemens chips: "Poseidon",
40570 +  "Poseidon II" and "Hydra". You may have to force loading of the module
40571 +  for motherboards in these cases. Be careful - those motherboards have
40572 +  not been tested with this driver.
40573 +
40574 +  You will also need the latest user-space utilties: you can find them
40575 +  in the lm_sensors package, which you can download at 
40576 +  http://www.lm-sensors.nu
40577 +
40578 +Genesys Logic GL518SM
40579 +CONFIG_SENSORS_GL518SM
40580 +  If you say yes here you get support for Genesys Logic GL518SM sensor
40581 +  chips.  This can also be built as a module which can be inserted and
40582 +  removed while the kernel is running.
40583 +
40584 +  You will also need the latest user-space utilties: you can find them
40585 +  in the lm_sensors package, which you can download at 
40586 +  http://www.lm-sensors.nu
40587 +
40588 +Genesys Logic GL520SM
40589 +CONFIG_SENSORS_GL520SM
40590 +  If you say yes here you get support for Genesys Logic GL518SM sensor
40591 +  chips.  This can also be built as a module which can be inserted and
40592 +  removed while the kernel is running.
40593 +
40594 +  You will also need the latest user-space utilties: you can find them
40595 +  in the lm_sensors package, which you can download at 
40596 +  http://www.lm-sensors.nu
40597 +
40598 +HP Maxilife
40599 +CONFIG_SENSORS_MAXILIFE
40600 +  If you say yes here you get support for the HP Maxilife
40601 +  sensor chip.  This can also be built as a module.
40602 +
40603 +  You will also need the latest user-space utilties: you can find them
40604 +  in the lm_sensors package, which you can download at 
40605 +  http://www.lm-sensors.nu
40606 +
40607 +Intel Xeon Thermal Sensor
40608 +CONFIG_SENSORS_XEONTEMP
40609 +  If you say yes here you get support for the Intel Xeon processor
40610 +  built-in thermal sensor. This can also be built as a module which
40611 +  can be inserted and removed while the kernel is running.
40612 +
40613 +  You will also need the latest user-space utilities: you can find them
40614 +  in the lm_sensors package, which you can download at 
40615 +  http://www.lm-sensors.nu/
40616 +
40617 +ITE 8705, 8712, Sis950
40618 +CONFIG_SENSORS_IT87
40619 +  If you say yes here you get support for the ITE 8705 and 8712 and
40620 +  SiS950 sensor chips.  This can also be built as a module.
40621 +
40622 +  You will also need the latest user-space utilties: you can find them
40623 +  in the lm_sensors package, which you can download at 
40624 +  http://www.lm-sensors.nu
40625 +
40626 +Maxim MAX6650, MAX6651
40627 +CONFIG_SENSORS_MAX6650
40628 +  If you say yes here you get support for the Maxim MAX6650 and
40629 +  MAX6651 sensor chips.  This can also be built as a module.
40630 +
40631 +  You will also need the latest user-space utilties: you can find them
40632 +  in the lm_sensors package, which you can download at 
40633 +  http://www.lm-sensors.nu
40634 +
40635 +Myson MTP008
40636 +CONFIG_SENSORS_MTP008
40637 +  If you say yes here you get support for the Myson MTP008
40638 +  sensor chip.  This can also be built as a module.
40639 +
40640 +  You will also need the latest user-space utilties: you can find them
40641 +  in the lm_sensors package, which you can download at 
40642 +  http://www.lm-sensors.nu
40643 +
40644 +National Semiconductor LM75 and compatibles
40645 +CONFIG_SENSORS_LM75 
40646 +  If you say yes here you get support for National Semiconductor LM75
40647 +  sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
40648 +  9-bit precision mode), and TelCom (now Microchip) TCN75. This can
40649 +  also be built as a module which can be inserted and removed while
40650 +  the kernel is running.
40651 +
40652 +  You will also need the latest user-space utilties: you can find them
40653 +  in the lm_sensors package, which you can download at 
40654 +  http://www.lm-sensors.nu
40655 +
40656 +National Semiconductor LM78
40657 +CONFIG_SENSORS_LM78
40658 +  If you say yes here you get support for National Semiconductor LM78
40659 +  sensor chips family: the LM78-J and LM79. Many clone chips will
40660 +  also work at least somewhat with this driver. This can also be built
40661 +  as a module which can be inserted and removed while the kernel is 
40662 +  running.
40663 +
40664 +  You will also need the latest user-space utilties: you can find them
40665 +  in the lm_sensors package, which you can download at 
40666 +  http://www.lm-sensors.nu
40667 +
40668 +National Semiconductor LM80
40669 +CONFIG_SENSORS_LM80
40670 +  If you say yes here you get support for National Semiconductor LM80
40671 +  sensor chips. This can also be built as a module which can be 
40672 +  inserted and removed while the kernel is running.
40673 +
40674 +  You will also need the latest user-space utilties: you can find them
40675 +  in the lm_sensors package, which you can download at 
40676 +  http://www.lm-sensors.nu
40677 +
40678 +National Semiconductor LM83
40679 +CONFIG_SENSORS_LM83
40680 +  If you say yes here you get support for the National Semiconductor
40681 +  LM83 sensor chip.  This can also be built as a module.
40682 +
40683 +  You will also need the latest user-space utilities: you can find
40684 +  them in the lm_sensors package, which you can download at
40685 +  http://www.lm-sensors.nu/
40686 +
40687 +National Semiconductor LM85
40688 +CONFIG_SENSORS_LM85
40689 +  If you say yes here you get support for National Semiconductor LM85
40690 +  sensor chips and compatibles.  Compatible chips include the Analog
40691 +  Devices ADM1027 and ADT7463 and SMSC EMC6D100 and EMC6D101.  This
40692 +  can also be built as a module which can be inserted and removed
40693 +  while the kernel is running.
40694 +
40695 +  You will also need the latest user-space utilties: you can find them
40696 +  in the lm_sensors package, which you can download at 
40697 +  http://www.lm-sensors.nu
40698 +
40699 +National Semiconductor LM87
40700 +CONFIG_SENSORS_LM87
40701 +  If you say yes here you get support for National Semiconductor LM87
40702 +  sensor chips. This can also be built as a module which can be 
40703 +  inserted and removed while the kernel is running.
40704 +
40705 +  You will also need the latest user-space utilties: you can find them
40706 +  in the lm_sensors package, which you can download at 
40707 +  http://www.lm-sensors.nu
40708 +
40709 +National Semiconductor LM90
40710 +CONFIG_SENSORS_LM90
40711 +  If you say yes here you get support for the National Semiconductor
40712 +  LM90, LM89 and LM99, and Analog Devices ADM1032 sensor chips.  This
40713 +  can also be built as a module.
40714 +
40715 +  You will also need the latest user-space utilities: you can find
40716 +  them in the lm_sensors package, which you can download at
40717 +  http://www.lm-sensors.nu/
40718 +
40719 +National Semiconductor LM92
40720 +CONFIG_SENSORS_LM92
40721 +  If you say yes here you get support for National Semiconductor LM92
40722 +  sensor chips. This can also be built as a module which can be 
40723 +  inserted and removed while the kernel is running.
40724 +
40725 +  You will also need the latest user-space utilties: you can find them
40726 +  in the lm_sensors package, which you can download at 
40727 +  http://www.lm-sensors.nu
40728 +
40729 +National Semiconductor PC8736x Sensors
40730 +CONFIG_SENSORS_PC87360
40731 +  If you say yes here you get support for the integrated hardware
40732 +  monitoring in the National Semicoductor PC87360, PC87363, PC87364,
40733 +  PC87365 and PC87366 Super I/O chips. This can also be built as a
40734 +  module which can be inserted and removed while the kernel is
40735 +  running.
40736 +
40737 +  You will also need the latest user-space utilities: you can find them
40738 +  in the lm_sensors package, which you can download at 
40739 +  http://www.lm-sensors.nu/
40740 +
40741 +Philips PCF8574
40742 +CONFIG_SENSORS_PCF8574
40743 +  If you say yes here you get support for the Philips PCF8574
40744 +  I2C 8-bit Parallel I/O device.
40745 +  This can also be built as a module which can be 
40746 +  inserted and removed while the kernel is running.
40747 +
40748 +  You will also need the latest user-space utilties: you can find them
40749 +  in the lm_sensors package, which you can download at 
40750 +  http://www.lm-sensors.nu
40751 +
40752 +Philips PCF8591
40753 +CONFIG_SENSORS_PCF8591
40754 +  If you say yes here you get support for the Philips PCF8591
40755 +  I2C Quad D/A + Single A/D I/O device.
40756 +  This can also be built as a module which can be 
40757 +  inserted and removed while the kernel is running.
40758 +
40759 +  You will also need the latest user-space utilties: you can find them
40760 +  in the lm_sensors package, which you can download at 
40761 +  http://www.lm-sensors.nu
40762 +
40763 +Silicon Integrated Systems Corp. SiS5595 Sensor
40764 +CONFIG_SENSORS_SIS5595
40765 +  If you say yes here you get support for the integrated sensors in 
40766 +  SiS5595 South Bridges. This can also be built as a module 
40767 +  which can be inserted and removed while the kernel is running.
40768 +
40769 +  You will also need the latest user-space utilties: you can find them
40770 +  in the lm_sensors package, which you can download at 
40771 +  http://www.lm-sensors.nu
40772 +
40773 +SMSC47M1xx Super I/O Fan Support
40774 +CONFIG_SENSORS_SMSC47M1
40775 +  If you say yes here you get support for the integrated fan
40776 +  monitoring and control in the SMSC 47M1xx Super I/O chips.
40777 +  This can also be built as a module 
40778 +  which can be inserted and removed while the kernel is running.
40779 +
40780 +  You will also need the latest user-space utilties: you can find them
40781 +  in the lm_sensors package, which you can download at 
40782 +  http://www.lm-sensors.nu
40783 +
40784 +Texas Instruments THMC50 / Analog Devices ADM1022
40785 +CONFIG_SENSORS_THMC50
40786 +  If you say yes here you get support for Texas Instruments THMC50
40787 +  sensor chips and clones: the Analog Devices ADM1022.
40788 +  This can also be built as a module which
40789 +  can be inserted and removed while the kernel is running.
40790 +
40791 +  You will also need the latest user-space utilties: you can find them
40792 +  in the lm_sensors package, which you can download at 
40793 +  http://www.lm-sensors.nu
40794 +
40795 +Via VT82C686A/B
40796 +CONFIG_SENSORS_VIA686A
40797 +  If you say yes here you get support for the integrated sensors in 
40798 +  Via 686A/B South Bridges. This can also be built as a module 
40799 +  which can be inserted and removed while the kernel is running.
40800 +
40801 +  You will also need the latest user-space utilties: you can find them
40802 +  in the lm_sensors package, which you can download at 
40803 +  http://www.lm-sensors.nu
40804 +
40805 +Via VT1211 Sensors
40806 +CONFIG_SENSORS_VT1211
40807 +  If you say yes here you get support for the integrated sensors in 
40808 +  the Via VT1211 Super I/O device. This can also be built as a module 
40809 +  which can be inserted and removed while the kernel is running.
40810 +
40811 +  You will also need the latest user-space utilties: you can find them
40812 +  in the lm_sensors package, which you can download at 
40813 +  http://www.lm-sensors.nu
40814 +
40815 +Via VT8231 Sensors
40816 +CONFIG_SENSORS_VT8231
40817 +  If you say yes here you get support for the integrated sensors in 
40818 +  the Via VT8231 device. This can also be built as a module 
40819 +  which can be inserted and removed while the kernel is running.
40820 +
40821 +  You will also need the latest user-space utilties: you can find them
40822 +  in the lm_sensors package, which you can download at 
40823 +  http://www.lm-sensors.nu
40824 +
40825 +Winbond W83781D, W83782D, W83783S, W83627HF, AS99127F
40826 +CONFIG_SENSORS_W83781D
40827 +  If you say yes here you get support for the Winbond W8378x series 
40828 +  of sensor chips: the W83781D, W83782D, W83783S and W83682HF,
40829 +  and the similar Asus AS99127F. This
40830 +  can also be built as a module which can be inserted and removed
40831 +  while the kernel is running.
40832 +
40833 +  You will also need the latest user-space utilties: you can find them
40834 +  in the lm_sensors package, which you can download at 
40835 +  http://www.lm-sensors.nu
40836 +
40837 +Winbond W83627HF, W83627THF, W83697HF
40838 +CONFIG_SENSORS_W83627HF
40839 +  If you say yes here you get support for the Winbond W836x7 series 
40840 +  of sensor chips: the Winbond W83627HF, W83627THF and W83697HF. This
40841 +  can also be built as a module which can be inserted and removed
40842 +  while the kernel is running.
40843 +
40844 +  You will also need the latest user-space utilities: you can find
40845 +  them in the lm_sensors package, which you can download at
40846 +  http://www.lm-sensors.nu/
40847 +
40848 +Winbond W83L785TS-S
40849 +CONFIG_SENSORS_W83L785TS
40850 +  If you say yes here you get support for the Winbond W83L785TS-S
40851 +  sensor chip.  This can also be built as a module.
40852 +
40853 +  You will also need the latest user-space utilities: you can find
40854 +  them in the lm_sensors package, which you can download at
40855 +  http://www.lm-sensors.nu/
40856 +
40857 +EEprom (DIMM) reader
40858 +CONFIG_SENSORS_EEPROM
40859 +  If you say yes here you get read-only access to the EEPROM data 
40860 +  available on modern memory DIMMs, and which could theoretically
40861 +  also be available on other devices. This can also be built as a 
40862 +  module which can be inserted and removed while the kernel is 
40863 +  running.
40864 +
40865 +  You will also need the latest user-space utilties: you can find them
40866 +  in the lm_sensors package, which you can download at 
40867 +  http://www.lm-sensors.nu
40868 +
40869  # End:
40870 --- linux-old/MAINTAINERS       Sun Oct  3 01:33:28 2004
40871 +++ linux/MAINTAINERS   Mon Dec 13 20:18:56 2004
40872 @@ -1659,6 +1659,15 @@
40873  L:     linux-ide@vger.kernel.org
40874  S:     Supported
40875  
40876 +SENSORS DRIVERS
40877 +P:      Frodo Looijaard
40878 +M:      frodol@dds.nl
40879 +P:      Philip Edelbrock
40880 +M:      phil@netroedge.com
40881 +L:      sensors@stimpy.netroedge.com
40882 +W:      http://www.lm-sensors.nu/
40883 +S:      Maintained
40884 +
40885  SGI VISUAL WORKSTATION 320 AND 540
40886  P:     Bent Hagemark
40887  M:     bh@sgi.com
40888 --- linux-old/arch/i386/kernel/dmi_scan.c       Fri Apr 16 03:14:11 2004
40889 +++ linux/arch/i386/kernel/dmi_scan.c   Mon Dec 13 20:18:56 2004
40890 @@ -15,6 +15,7 @@
40891  #include "pci-i386.h"
40892  
40893  unsigned long dmi_broken;
40894 +int is_unsafe_smbus;
40895  int is_sony_vaio_laptop;
40896  
40897  struct dmi_header
40898 @@ -371,6 +372,19 @@
40899  }              
40900  
40901  /*
40902 + * Don't access SMBus on IBM systems which get corrupted eeproms 
40903 + */
40904 +
40905 +static __init int disable_smbus(struct dmi_blacklist *d)
40906 +{   
40907 +       if (is_unsafe_smbus == 0) {
40908 +               is_unsafe_smbus = 1;
40909 +               printk(KERN_INFO "%s machine detected. Disabling SMBus accesses.\n", d->ident);
40910 +       }
40911 +       return 0;
40912 +}
40913 +
40914 +/*
40915   * Check for a Sony Vaio system
40916   *
40917   * On a Sony system we want to enable the use of the sonypi
40918 @@ -675,6 +689,10 @@
40919                         NO_MATCH, NO_MATCH,
40920                         } },
40921  
40922 +       { disable_smbus, "IBM", {
40923 +                       MATCH(DMI_SYS_VENDOR, "IBM"),
40924 +                       NO_MATCH, NO_MATCH, NO_MATCH
40925 +                       } },
40926         { sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
40927                         MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
40928                         MATCH(DMI_PRODUCT_NAME, "PCG-"),
40929 --- linux-old/arch/i386/kernel/i386_ksyms.c     Fri Apr 16 03:14:11 2004
40930 +++ linux/arch/i386/kernel/i386_ksyms.c Mon Dec 13 20:18:56 2004
40931 @@ -179,6 +179,9 @@
40932  EXPORT_SYMBOL(atomic_dec_and_lock);
40933  #endif
40934  
40935 +extern int is_unsafe_smbus;
40936 +EXPORT_SYMBOL(is_unsafe_smbus);
40937 +
40938  extern int is_sony_vaio_laptop;
40939  EXPORT_SYMBOL(is_sony_vaio_laptop);
40940