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
5 + i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware
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>
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.
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.
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.
29 + This is the driver for the SMB Host controller on
30 + Acer Labs Inc. (ALI) M1535 South Bridge.
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
43 + The SMB controller is part of the 7101 device, which is an
44 + ACPI-compliant Power Management Unit (PMU).
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.
51 + This driver controls the SMB Host only.
53 + This driver does not use interrupts.
57 +/* Note: we assume there can only be one ALI1535, with one SMBus interface */
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>
68 +#include <asm/semaphore.h>
69 +#define LM_DATE "20041007"
70 +#define LM_VERSION "2.8.8"
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)
83 +/* PCI Address Constants */
88 +#define SMBHSTCFG 0x0F0
92 +#define MAX_TIMEOUT 500 /* times 1/100 sec */
93 +#define ALI1535_SMB_IOSIZE 32
97 +#define ALI1535_SMB_DEFAULTBASE 0x8040
99 +/* ALI1535 address lock bits */
100 +#define ALI1535_LOCK 0x06 < dwe >
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
110 +#define ALI1535_DEV10B_EN 0x80 /* Enable 10-bit addressing in */
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 */
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 */
121 +#define ALI1535_D_HI_MASK 0x03 /* Mask for isolating bits 9-8 */
122 + /* of 10-bit address in I2C */
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 */
134 +#define ALI1535_BLOCK_CLR 0x04 /* reset block data index */
136 +/* ALI1535 device address register bits */
137 +#define ALI1535_RD_ADDR 0x01 /* Read/Write Bit in Device */
138 + /* Address field */
141 +#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */
143 +static int ali1535_transaction(void);
145 +static unsigned short ali1535_smba = 0;
146 +DECLARE_MUTEX(i2c_ali1535_sem);
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)
155 + int error_return = 0;
156 + unsigned char temp;
158 +/* Check the following things:
159 + - SMB I/O address is initialized
160 + - Device is enabled
161 + - We can use the addresses
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) {
169 + ("i2c-ali1535.o: ALI1535_smb region uninitialized - upgrade BIOS?\n");
170 + error_return = -ENODEV;
173 + if (error_return == -ENODEV)
176 + if (check_region(ali1535_smba, ALI1535_SMB_IOSIZE)) {
178 + ("i2c-ali1535.o: ALI1535_smb region 0x%x already in use!\n",
180 + error_return = -ENODEV;
183 + if (error_return == -ENODEV)
186 + /* check if whole device is enabled */
187 + pci_read_config_byte(ALI1535_dev, SMBCFG, &temp);
188 + if ((temp & ALI1535_SMBIO_EN) == 0) {
190 + ("i2c-ali1535.o: SMB device not enabled - upgrade BIOS?\n");
191 + error_return = -ENODEV;
195 +/* Is SMB Host controller enabled? */
196 + pci_read_config_byte(ALI1535_dev, SMBHSTCFG, &temp);
197 + if ((temp & 1) == 0) {
199 + ("i2c-ali1535.o: SMBus controller not enabled - upgrade BIOS?\n");
200 + error_return = -ENODEV;
204 +/* set SMB clock to 74KHz as recommended in data sheet */
205 + pci_write_config_byte(ALI1535_dev, SMBCLK, 0x20);
207 + /* Everything is happy, let's grab the memory and set things up. */
208 + request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb");
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");
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);
224 + return error_return;
228 +/* Another internally used function */
229 +int ali1535_transaction(void)
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));
244 + temp = inb_p(SMBHSTSTS);
246 + /* Make sure the SMBus host is ready to start transmitting */
247 + /* Check the busy bit first */
248 + if (temp & ALI1535_STS_BUSY) {
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.
261 +/* Abort - reset the host controller */
264 + printk("i2c-ali1535.o: Resetting host controller to clear busy condition\n",temp);
266 + outb_p(ALI1535_KILL, SMBHSTTYP);
267 + temp = inb_p(SMBHSTSTS);
268 + if (temp & ALI1535_STS_BUSY) {
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.
278 + ("i2c-ali1535.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",
280 + outb_p(ALI1535_T_OUT, SMBHSTTYP);
281 + temp = inb_p(SMBHSTSTS);
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. */
297 + ("i2c-ali1535.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n",
302 + /* check and clear done bit */
303 + if (temp & ALI1535_STS_DONE) {
304 + outb_p(temp, SMBHSTSTS);
308 + /* start the transaction by writing anything to the start register */
309 + outb_p(0xFF, SMBHSTPORT);
311 + /* We will always wait for a fraction of a second! */
315 + temp = inb_p(SMBHSTSTS);
316 + } while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE))
317 + && (timeout++ < MAX_TIMEOUT));
319 + /* If the SMBus is still busy, we give up */
320 + if (timeout >= MAX_TIMEOUT) {
322 + printk("i2c-ali1535.o: SMBus Timeout!\n");
325 + if (temp & ALI1535_STS_FAIL) {
328 + printk("i2c-ali1535.o: Error: Failed bus transaction\n");
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.
337 + if (temp & ALI1535_STS_BUSERR) {
341 + ("i2c-ali1535.o: Error: no response or bus collision ADD=%02x\n",
346 +/* haven't ever seen this */
347 + if (temp & ALI1535_STS_DEV) {
349 + printk("i2c-ali1535.o: Error: device error\n");
353 + check to see if the "command complete" indication is set
355 + if (!(temp & ALI1535_STS_DONE)) {
357 + printk("i2c-ali1535.o: Error: command never completed\n");
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));
368 + take consequent actions for error conditions
370 + if (!(temp & ALI1535_STS_DONE)) {
371 + /* issue "kill" to reset host controller */
372 + outb_p(ALI1535_KILL,SMBHSTTYP);
373 + outb_p(0xFF,SMBHSTSTS);
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);
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)
394 + down(&i2c_ali1535_sem);
395 +/* make sure SMBus is idle */
396 + temp = inb_p(SMBHSTSTS);
398 + (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE);
401 + temp = inb_p(SMBHSTSTS);
403 + if (timeout >= MAX_TIMEOUT) {
404 + printk("i2c-ali1535.o: Idle wait Timeout! STS=0x%02x\n",
408 +/* clear status register (clear-on-write) */
409 + outb_p(0xFF, SMBHSTSTS);
412 + case I2C_SMBUS_QUICK:
413 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
415 + size = ALI1535_QUICK;
416 + outb_p(size, SMBHSTTYP); /* output command */
418 + case I2C_SMBUS_BYTE:
419 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
421 + size = ALI1535_BYTE;
422 + outb_p(size, SMBHSTTYP); /* output command */
423 + if (read_write == I2C_SMBUS_WRITE)
424 + outb_p(command, SMBHSTCMD);
426 + case I2C_SMBUS_BYTE_DATA:
427 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
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);
435 + case I2C_SMBUS_WORD_DATA:
436 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
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);
446 + case I2C_SMBUS_BLOCK_DATA:
447 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
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];
456 + data->block[0] = len;
460 + data->block[0] = len;
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);
470 + (KERN_WARNING "i2c-ali1535.o: Unsupported transaction %d\n", size);
475 + if (ali1535_transaction()) /* Error in transaction */
481 + if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK))
488 + case ALI1535_BYTE: /* Result put in SMBHSTDAT0 */
489 + data->byte = inb_p(SMBHSTDAT0);
491 + case ALI1535_BYTE_DATA:
492 + data->byte = inb_p(SMBHSTDAT0);
494 + case ALI1535_WORD_DATA:
495 + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
497 + case ALI1535_BLOCK_DATA:
498 + len = inb_p(SMBHSTDAT0);
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);
507 + ("i2c-ali1535.o: Blk: len=%d, i=%d, data=%02x\n",
508 + len, i, data->block[i]);
514 + up(&i2c_ali1535_sem);
519 +u32 ali1535_func(struct i2c_adapter *adapter)
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;
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,
533 +static struct i2c_adapter ali1535_adapter = {
534 + .owner = THIS_MODULE,
536 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI1535,
537 + .algo = &smbus_algorithm,
541 +static struct pci_device_id ali1535_ids[] __devinitdata = {
543 + .vendor = PCI_VENDOR_ID_AL,
544 + .device = PCI_DEVICE_ID_AL_M7101,
545 + .subvendor = PCI_ANY_ID,
546 + .subdevice = PCI_ANY_ID,
551 +static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
553 + if (ali1535_setup(dev)) {
555 + ("i2c-ali1535.o: ALI1535 not detected, module not inserted.\n");
559 + sprintf(ali1535_adapter.name, "SMBus ALI1535 adapter at %04x",
561 + return i2c_add_adapter(&ali1535_adapter);
564 +static void __devexit ali1535_remove(struct pci_dev *dev)
566 + i2c_del_adapter(&ali1535_adapter);
567 + release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
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),
578 +static int __init i2c_ali1535_init(void)
580 + printk("i2c-ali1535.o version %s (%s)\n", LM_VERSION, LM_DATE);
581 + return pci_module_init(&ali1535_driver);
585 +static void __exit i2c_ali1535_exit(void)
587 + pci_unregister_driver(&ali1535_driver);
591 +EXPORT_SYMBOL(ali1535_smba);
592 +EXPORT_SYMBOL(ali1535_access);
593 +EXPORT_SYMBOL(i2c_ali1535_sem);
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");
602 +module_init(i2c_ali1535_init);
603 +module_exit(i2c_ali1535_exit);
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
609 + ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
611 + Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and
612 + Philip Edelbrock <phil@netroedge.com> and
613 + Mark D. Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
631 + This is the driver for the SMB Host controller on
632 + Acer Labs Inc. (ALI) M1541 and M1543C South Bridges.
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
645 + The M1533/M1543C devices appear as FOUR separate devices
646 + on the PCI bus. An output of lspci will show something similar
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
654 + The SMB controller is part of the 7101 device, which is an
655 + ACPI-compliant Power Management Unit (PMU).
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.
662 + This driver controls the SMB Host only.
663 + The SMB Slave controller on the M15X3 is not enabled.
665 + This driver does not use interrupts.
668 +/* Note: we assume there can only be one ALI15X3, with one SMBus interface */
670 +/* #define DEBUG 1 */
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>
681 +#define LM_DATE "20041007"
682 +#define LM_VERSION "2.8.8"
683 +#include <linux/sensors_compat.h>
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)
695 +/* PCI Address Constants */
696 +#define SMBCOM 0x004
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
704 +/* Other settings */
705 +#define MAX_TIMEOUT 200 /* times 1/100 sec */
706 +#define ALI15X3_SMB_IOSIZE 32
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.
712 +#define ALI15X3_SMB_DEFAULTBASE 0xE800
714 +/* ALI15X3 address lock bits */
715 +#define ALI15X3_LOCK 0x06
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
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 */
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");
744 +static unsigned short ali15x3_smba = 0;
746 +static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
749 + unsigned char temp;
751 + /* Check the following things:
752 + - SMB I/O address is initialized
753 + - Device is enabled
754 + - We can use the addresses
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.
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);
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");
778 + ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
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",
788 + dev_info(ALI15X3_dev, "forcing ISA address 0x%04X\n",
790 + if (PCIBIOS_SUCCESSFUL !=
791 + pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba))
793 + if (PCIBIOS_SUCCESSFUL !=
794 + pci_read_config_word(ALI15X3_dev, SMBBA, &a))
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");
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);
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);
817 + /* set SMB clock to 74KHz as recommended in data sheet */
818 + pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
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");
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);
834 +/* Another internally used function */
835 +static int ali15x3_transaction(struct i2c_adapter *adap)
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));
847 + temp = inb_p(SMBHSTSTS);
849 + /* Make sure the SMBus host is ready to start transmitting */
850 + /* Check the busy bit first */
851 + if (temp & ALI15X3_STS_BUSY) {
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
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
863 + 3. Disable and reenable the controller in SMBHSTCFG
864 + Worst case, nothing seems to work except power reset.
866 + /* Abort - reset the host controller */
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.
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);
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",
894 + /* check and clear done bit */
895 + if (temp & ALI15X3_STS_DONE) {
896 + outb_p(temp, SMBHSTSTS);
900 + /* start the transaction by writing anything to the start register */
901 + outb_p(0xFF, SMBHSTSTART);
903 + /* We will always wait for a fraction of a second! */
907 + temp = inb_p(SMBHSTSTS);
908 + } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
909 + && (timeout++ < MAX_TIMEOUT));
911 + /* If the SMBus is still busy, we give up */
912 + if (timeout >= MAX_TIMEOUT) {
914 + dev_err(adap, "SMBus Timeout!\n");
917 + if (temp & ALI15X3_STS_TERM) {
919 + dev_dbg(adap, "Error: Failed bus transaction\n");
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
926 + This means that bus collisions go unreported.
928 + if (temp & ALI15X3_STS_COLL) {
931 + "Error: no response or bus collision ADD=%02x\n",
935 + /* haven't ever seen this */
936 + if (temp & ALI15X3_STS_DEV) {
938 + dev_err(adap, "Error: device error\n");
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));
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)
956 + /* clear all the bits (clear-on-write) */
957 + outb_p(0xFF, SMBHSTSTS);
958 + /* make sure SMBus is idle */
959 + temp = inb_p(SMBHSTSTS);
961 + (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
964 + temp = inb_p(SMBHSTSTS);
966 + if (timeout >= MAX_TIMEOUT) {
967 + dev_err(adap, "Idle wait Timeout! STS=0x%02x\n", temp);
971 + case I2C_SMBUS_QUICK:
972 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
974 + size = ALI15X3_QUICK;
976 + case I2C_SMBUS_BYTE:
977 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
979 + if (read_write == I2C_SMBUS_WRITE)
980 + outb_p(command, SMBHSTCMD);
981 + size = ALI15X3_BYTE;
983 + case I2C_SMBUS_BYTE_DATA:
984 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
986 + outb_p(command, SMBHSTCMD);
987 + if (read_write == I2C_SMBUS_WRITE)
988 + outb_p(data->byte, SMBHSTDAT0);
989 + size = ALI15X3_BYTE_DATA;
991 + case I2C_SMBUS_WORD_DATA:
992 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
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);
999 + size = ALI15X3_WORD_DATA;
1001 + case I2C_SMBUS_BLOCK_DATA:
1002 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
1004 + outb_p(command, SMBHSTCMD);
1005 + if (read_write == I2C_SMBUS_WRITE) {
1006 + len = data->block[0];
1009 + data->block[0] = len;
1013 + data->block[0] = len;
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);
1021 + size = ALI15X3_BLOCK_DATA;
1025 + (KERN_WARNING "i2c-ali15x3.o: Unsupported transaction %d\n", size);
1029 + outb_p(size, SMBHSTCNT); /* output command */
1031 + if (ali15x3_transaction(adap)) /* Error in transaction */
1034 + if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
1039 + case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */
1040 + data->byte = inb_p(SMBHSTDAT0);
1042 + case ALI15X3_BYTE_DATA:
1043 + data->byte = inb_p(SMBHSTDAT0);
1045 + case ALI15X3_WORD_DATA:
1046 + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
1048 + case ALI15X3_BLOCK_DATA:
1049 + len = inb_p(SMBHSTDAT0);
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]);
1065 +static u32 ali15x3_func(struct i2c_adapter *adapter)
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;
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,
1079 +static struct i2c_adapter ali15x3_adapter = {
1080 + .owner = THIS_MODULE,
1081 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
1082 + .algo = &smbus_algorithm,
1086 +static struct pci_device_id ali15x3_ids[] __devinitdata = {
1088 + .vendor = PCI_VENDOR_ID_AL,
1089 + .device = PCI_DEVICE_ID_AL_M7101,
1090 + .subvendor = PCI_ANY_ID,
1091 + .subdevice = PCI_ANY_ID,
1096 +static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
1098 + if (ali15x3_setup(dev)) {
1100 + "ALI15X3 not detected, module not inserted.\n");
1104 + snprintf(ali15x3_adapter.name, 32,
1105 + "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
1106 + return i2c_add_adapter(&ali15x3_adapter);
1109 +static void __devexit ali15x3_remove(struct pci_dev *dev)
1111 + i2c_del_adapter(&ali15x3_adapter);
1112 + release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
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),
1122 +static int __init i2c_ali15x3_init(void)
1124 + printk("i2c-ali15x3.o version %s (%s)\n", LM_VERSION, LM_DATE);
1125 + return pci_module_init(&ali15x3_driver);
1128 +static void __exit i2c_ali15x3_exit(void)
1130 + pci_unregister_driver(&ali15x3_driver);
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");
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
1145 + amd756.c - Part of lm_sensors, Linux kernel modules for hardware
1148 + Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
1150 + Shamelessly ripped from i2c-piix4.c:
1152 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
1153 + Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
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.
1176 + 2004-02-15: Don't register driver to avoid driver conflicts.
1177 + (Daniel Rune Jensen)
1181 + Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce
1182 + Note: we assume there can only be one device, with one SMBus interface.
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"
1197 +#define DRV_NAME "i2c-amd756"
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)
1213 +/* PCI Address Constants */
1215 +/* address of I/O space */
1216 +#define SMBBA 0x058 /* mh */
1217 +#define SMBBANFORCE 0x014
1219 +/* general configuration */
1220 +#define SMBGCFG 0x041 /* mh */
1222 +/* silicon revision code */
1223 +#define SMBREV 0x008
1225 +/* Other settings */
1226 +#define MAX_TIMEOUT 500
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
1237 +static unsigned short amd756_ioport = 0;
1240 + SMBUS event = I/O 28-29 bit 11
1241 + see E0 for the status bits and enabled in E2
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)
1253 +#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \
1254 + GS_HCYC_STS | GS_TO_STS )
1256 +#define GE_CYC_TYPE_MASK (7)
1257 +#define GE_HOST_STC (1 << 3)
1258 +#define GE_ABORT (1 << 5)
1261 +static int amd756_transaction(void)
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));
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);
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);
1288 + /* start the transaction by setting the start bit */
1289 + outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);
1291 + /* We will always wait for a fraction of a second! */
1294 + temp = inw_p(SMB_GLOBAL_STATUS);
1295 + } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
1297 + /* If the SMBus is still busy, we give up */
1298 + if (timeout >= MAX_TIMEOUT) {
1299 + pr_debug(DRV_NAME ": Completion timeout!\n");
1303 + if (temp & GS_PRERR_STS) {
1305 + pr_debug(DRV_NAME ": SMBus Protocol error (no response)!\n");
1308 + if (temp & GS_COL_STS) {
1310 + printk(KERN_WARNING DRV_NAME ": SMBus collision!\n");
1313 + if (temp & GS_TO_STS) {
1315 + pr_debug(DRV_NAME ": SMBus protocol timeout!\n");
1318 + if (temp & GS_HCYC_STS)
1319 + pr_debug(DRV_NAME ": SMBus protocol success!\n");
1321 + outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
1324 + if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
1326 + ": Failed reset at end of transaction (%04x)\n", temp);
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));
1338 + printk(KERN_WARNING DRV_NAME ": Sending abort.\n");
1339 + outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
1341 + outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
1345 +/* Return -1 on error. */
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)
1353 + /** TODO: Should I supporte the 10-bit transfers? */
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;
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;
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;
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;
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];
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);
1400 + size = AMD756_BLOCK_DATA;
1404 + (KERN_WARNING "i2c-amd756.o: Unsupported transaction %d\n", size);
1408 + /* How about enabling interrupts... */
1409 + outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
1411 + if (amd756_transaction()) /* Error in transaction */
1414 + if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
1420 + data->byte = inw_p(SMB_HOST_DATA);
1422 + case AMD756_BYTE_DATA:
1423 + data->byte = inw_p(SMB_HOST_DATA);
1425 + case AMD756_WORD_DATA:
1426 + data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */
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);
1441 +static u32 amd756_func(struct i2c_adapter *adapter)
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;
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,
1455 +static struct i2c_adapter amd756_adapter = {
1456 + .owner = THIS_MODULE,
1458 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
1459 + .algo = &smbus_algorithm,
1462 +enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
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 },
1473 +static int __devinit amd756_probe(struct pci_dev *pdev,
1474 + const struct pci_device_id *id)
1476 + int nforce = (id->driver_data == NFORCE);
1480 + if (amd756_ioport) {
1481 + printk(KERN_ERR DRV_NAME ": Only one device supported. "
1482 + "(you have a strange motherboard, btw..)\n");
1487 + if (PCI_FUNC(pdev->devfn) != 1)
1490 + pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport);
1491 + amd756_ioport &= 0xfffc;
1492 + } else { /* amd */
1493 + if (PCI_FUNC(pdev->devfn) != 3)
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");
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;
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);
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);
1522 + sprintf(amd756_adapter.name,
1523 + "SMBus AMD756 adapter at %04x", amd756_ioport);
1525 + error = i2c_add_adapter(&amd756_adapter);
1527 + printk(KERN_ERR DRV_NAME
1528 + ": Adapter registration failed, module not inserted.\n");
1535 + release_region(amd756_ioport, SMB_IOSIZE);
1540 +static int __init i2c_amd756_init(void)
1542 + struct pci_dev *dev;
1543 + const struct pci_device_id *id;
1545 + printk(KERN_INFO "i2c-amd756.o version %s (%s)\n", LM_VERSION, LM_DATE);
1547 + pci_for_each_dev(dev) {
1548 + id = pci_match_device(amd756_ids, dev);
1549 + if (id && amd756_probe(dev, id) >= 0)
1557 +static void __exit i2c_amd756_exit(void)
1559 + i2c_del_adapter(&amd756_adapter);
1560 + release_region(amd756_ioport, SMB_IOSIZE);
1563 +MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
1564 +MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver");
1565 +MODULE_LICENSE("GPL");
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
1573 + * SMBus 2.0 driver for AMD-8111 IO-Hub.
1575 + * Copyright (c) 2002 Vojtech Pavlik
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.
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"
1596 +#ifndef I2C_HW_SMBUS_AMD8111
1597 +#error Your i2c is too old - i2c-2.7.0 or greater required!
1600 +/* kernel 2.4.9 needs this */
1602 +#define min_t(type,x,y) min(type,x,y)
1605 +MODULE_LICENSE("GPL");
1606 +MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
1607 +MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
1610 + struct pci_dev *dev;
1611 + struct i2c_adapter adapter;
1617 + * AMD PCI control registers definitions.
1620 +#define AMD_PCI_MISC 0x48
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 */
1627 + * ACPI 2.0 chapter 13 PCI interface definitions.
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 */
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 */
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 */
1649 + * ACPI 2.0 chapter 13 access of registers of the EC
1652 +unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
1654 + int timeout = 500;
1656 + while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF))
1660 + printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for IBF to clear\n");
1667 +unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
1669 + int timeout = 500;
1671 + while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF))
1675 + printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for OBF to set\n");
1682 +unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data)
1684 + if (amd_ec_wait_write(smbus))
1686 + outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
1688 + if (amd_ec_wait_write(smbus))
1690 + outb(address, smbus->base + AMD_EC_DATA);
1692 + if (amd_ec_wait_read(smbus))
1694 + *data = inb(smbus->base + AMD_EC_DATA);
1699 +unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data)
1701 + if (amd_ec_wait_write(smbus))
1703 + outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
1705 + if (amd_ec_wait_write(smbus))
1707 + outb(address, smbus->base + AMD_EC_DATA);
1709 + if (amd_ec_wait_write(smbus))
1711 + outb(data, smbus->base + AMD_EC_DATA);
1717 + * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
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 */
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
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
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
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)
1762 + struct amd_smbus *smbus = adap->algo_data;
1763 + unsigned char protocol, len, pec, temp[2];
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;
1771 + case I2C_SMBUS_QUICK:
1772 + protocol |= AMD_SMB_PRTCL_QUICK;
1773 + read_write = I2C_SMBUS_WRITE;
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;
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;
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);
1795 + protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
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]);
1806 + protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
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;
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;
1827 + case I2C_SMBUS_BLOCK_PROC_CALL:
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;
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);
1846 + printk(KERN_WARNING "i2c-amd8111.c: Unsupported transaction %d\n", size);
1850 + amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
1851 + amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
1853 + amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
1855 + if (~temp[0] & AMD_SMB_STS_DONE) {
1857 + amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
1860 + if (~temp[0] & AMD_SMB_STS_DONE) {
1861 + i2c_delay(HZ/100);
1862 + amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
1865 + if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
1868 + if (read_write == I2C_SMBUS_WRITE)
1873 + case I2C_SMBUS_BYTE:
1874 + case I2C_SMBUS_BYTE_DATA:
1875 + amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
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];
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;
1900 +u32 amd8111_func(struct i2c_adapter *adapter)
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;
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,
1916 +static struct pci_device_id amd8111_ids[] __devinitdata = {
1917 + { 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
1921 +static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
1923 + struct amd_smbus *smbus;
1926 + if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
1929 + if (!(smbus = (void*)kmalloc(sizeof(struct amd_smbus), GFP_KERNEL)))
1931 + memset(smbus, 0, sizeof(struct amd_smbus));
1933 + pci_set_drvdata(dev, smbus);
1935 + smbus->base = pci_resource_start(dev, 0);
1936 + smbus->size = pci_resource_len(dev, 0);
1938 + if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0")) {
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;
1949 + error = i2c_add_adapter(&smbus->adapter);
1951 + printk(KERN_WARNING "i2c-amd8111.c: Failed to register adapter.\n");
1952 + release_region(smbus->base, smbus->size);
1957 + pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
1959 + printk(KERN_INFO "i2c-amd8111.c: AMD8111 SMBus 2.0 adapter at %#x\n", smbus->base);
1964 +static void __devexit amd8111_remove(struct pci_dev *dev)
1966 + struct amd_smbus *smbus = (void*) pci_get_drvdata(dev);
1967 + i2c_del_adapter(&smbus->adapter);
1968 + release_region(smbus->base, smbus->size);
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),
1979 +static int __init i2c_amd8111_init(void)
1981 + printk(KERN_INFO "i2c-amd8111.o version %s (%s)\n", LM_VERSION, LM_DATE);
1982 + return pci_module_init(&amd8111_driver);
1986 +static void __exit i2c_amd8111_exit(void)
1988 + pci_unregister_driver(&amd8111_driver);
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
1997 + i2c-hydra.c - Part of lm_sensors, Linux kernel modules
1998 + for hardware monitoring
2000 + i2c Support for the Apple `Hydra' Mac I/O
2002 + Copyright (c) 1999 Geert Uytterhoeven <geert@linux-m68k.org>
2004 + Based on i2c Support for Via Technologies 82C586B South Bridge
2005 + Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
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.
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.
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.
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 */
2033 +MODULE_LICENSE("GPL");
2036 +#define HYDRA_CACHE_PD 0x00000030
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
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
2048 +static unsigned long hydra_base;
2050 +static inline void pdregw(u32 val)
2052 + writel(val, hydra_base + HYDRA_CACHE_PD);
2055 +static inline u32 pdregr(void)
2057 + u32 val = readl(hydra_base + HYDRA_CACHE_PD);
2061 +static void bit_hydra_setscl(void *data, int state)
2063 + u32 val = pdregr();
2065 + val &= ~HYDRA_SCLK_OE;
2067 + val &= ~HYDRA_SCLK;
2068 + val |= HYDRA_SCLK_OE;
2071 + pdregr(); /* flush posted write */
2074 +static void bit_hydra_setsda(void *data, int state)
2076 + u32 val = pdregr();
2078 + val &= ~HYDRA_SDAT_OE;
2080 + val &= ~HYDRA_SDAT;
2081 + val |= HYDRA_SDAT_OE;
2084 + pdregr(); /* flush posted write */
2087 +static int bit_hydra_getscl(void *data)
2089 + return (pdregr() & HYDRA_SCLK) != 0;
2092 +static int bit_hydra_getsda(void *data)
2094 + return (pdregr() & HYDRA_SDAT) != 0;
2097 +/* ------------------------------------------------------------------------ */
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,
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,
2116 +static struct pci_device_id hydra_ids[] __devinitdata = {
2118 + .vendor = PCI_VENDOR_ID_APPLE,
2119 + .device = PCI_DEVICE_ID_APPLE_HYDRA,
2120 + .subvendor = PCI_ANY_ID,
2121 + .subdevice = PCI_ANY_ID,
2126 +static int __devinit hydra_probe(struct pci_dev *dev, const struct pci_device_id *id)
2128 + unsigned int base_addr;
2130 + base_addr = dev->resource[0].start;
2131 + hydra_base = (unsigned long) ioremap(base_addr, 0x100);
2133 + pdregw(0); /* clear SCLK_OE and SDAT_OE */
2134 + return i2c_bit_add_bus(&bit_hydra_ops);
2137 +static void __devexit hydra_remove(struct pci_dev *dev)
2139 + pdregw(0); /* clear SCLK_OE and SDAT_OE */
2140 + i2c_bit_del_bus(&bit_hydra_ops);
2141 + iounmap((void *) hydra_base);
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),
2152 +static int __init i2c_hydra_init(void)
2154 + return pci_module_init(&hydra_driver);
2158 +static void __exit i2c_hydra_exit(void)
2160 + pci_unregister_driver(&hydra_driver);
2165 +MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
2166 +MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O");
2168 +module_init(i2c_hydra_init);
2169 +module_exit(i2c_hydra_exit);
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
2175 + i801.c - Part of lm_sensors, Linux kernel modules for hardware
2177 + Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
2178 + Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
2179 + <mdsxyz123@yahoo.com>
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.
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.
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.
2197 + SUPPORTED DEVICES PCI ID
2202 + 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported)
2203 + 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported)
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.
2213 +/* Note: we assume there can only be one I801, with one SMBus interface */
2215 +/* #define DEBUG 1 */
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>
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
2235 +#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
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 */
2251 +/* PCI Address Constants */
2252 +#define SMBBA 0x020
2253 +#define SMBHSTCFG 0x040
2254 +#define SMBREV 0x008
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
2261 +/* Other settings */
2262 +#define MAX_TIMEOUT 100
2263 +#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
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 */
2278 +/* insmod parameters */
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!");
2288 +static int i801_transaction(void);
2289 +static int i801_block_transaction(union i2c_smbus_data *data,
2290 + char read_write, int command);
2292 +static unsigned short i801_smba;
2293 +static struct pci_dev *I801_dev;
2296 +static int i801_setup(struct pci_dev *dev)
2298 + int error_return = 0;
2299 + unsigned char temp;
2301 + /* Note: we keep on searching until we have found 'function 3' */
2302 + if(PCI_FUNC(dev->devfn) != 3)
2306 + if (dev->device == PCI_DEVICE_ID_INTEL_82801DB_3 ||
2307 + dev->device == 0x24d3 ||
2308 + dev->device == 0x25a4)
2313 + /* Determine the address of the SMBus areas */
2315 + i801_smba = force_addr & 0xfff0;
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");
2326 + if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) {
2327 + dev_err(dev, "I801_smb region 0x%x already in use!\n",
2329 + error_return = -EBUSY;
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);
2337 + /* If force_addr is set, we program the new address here. Just to make
2338 + sure, we disable the device first. */
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");
2351 + dev_dbg(dev, "I801 using Interrupt SMI# for SMBus.\n");
2353 + dev_dbg(dev, "I801 using PCI Interrupt for SMBus.\n");
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);
2360 + return error_return;
2364 +static int i801_transaction(void)
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));
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",
2380 + outb_p(temp, SMBHSTSTS);
2381 + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
2382 + dev_dbg(I801_dev, "Failed! (%02x)\n", temp);
2385 + dev_dbg(I801_dev, "Successfull!\n");
2389 + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
2391 + /* We will always wait for a fraction of a second! */
2394 + temp = inb_p(SMBHSTSTS);
2395 + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
2397 + /* If the SMBus is still busy, we give up */
2398 + if (timeout >= MAX_TIMEOUT) {
2399 + dev_dbg(I801_dev, "SMBus Timeout!\n");
2403 + if (temp & 0x10) {
2405 + dev_dbg(I801_dev, "Error: Failed bus transaction\n");
2408 + if (temp & 0x08) {
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 */
2415 + if (temp & 0x04) {
2417 + dev_dbg(I801_dev, "Error: no response!\n");
2420 + if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
2421 + outb_p(inb(SMBHSTSTS), SMBHSTSTS);
2423 + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
2424 + dev_dbg(I801_dev, "Failed reset at end of transaction"
2425 + "(%02x)\n", temp);
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));
2434 +/* All-inclusive block transaction function */
2435 +static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
2443 + unsigned char hostc, errmask;
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);
2453 + "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
2458 + if (read_write == I2C_SMBUS_WRITE) {
2459 + len = data->block[0];
2464 + outb_p(len, SMBHSTDAT0);
2465 + outb_p(data->block[1], SMBBLKDAT);
2467 + len = 32; /* max for reads */
2470 + if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
2471 + /* set 32 byte buffer */
2474 + for (i = 1; i <= len; i++) {
2475 + if (i == len && read_write == I2C_SMBUS_READ)
2476 + smbcmd = I801_BLOCK_LAST;
2478 + smbcmd = I801_BLOCK_DATA;
2479 + outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
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));
2486 + /* Make sure the SMBus host is ready to start transmitting */
2487 + temp = inb_p(SMBHSTSTS);
2489 + /* Erronenous conditions before transaction:
2490 + * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
2493 + /* Erronenous conditions during transaction:
2494 + * Failed, Bus_Err, Dev_Err, Intr */
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) {
2503 + "Reset failed! (%02x)\n", temp);
2508 + /* if die in middle of block transaction, fail */
2515 + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
2517 + /* We will always wait for a fraction of a second! */
2520 + temp = inb_p(SMBHSTSTS);
2523 + while ((!(temp & 0x80))
2524 + && (timeout++ < MAX_TIMEOUT));
2526 + /* If the SMBus is still busy, we give up */
2527 + if (timeout >= MAX_TIMEOUT) {
2529 + dev_dbg(I801_dev, "SMBus Timeout!\n");
2532 + if (temp & 0x10) {
2535 + "Error: Failed bus transaction\n");
2536 + } else if (temp & 0x08) {
2538 + dev_err(I801_dev, "Bus collision!\n");
2539 + } else if (temp & 0x04) {
2541 + dev_dbg(I801_dev, "Error: no response!\n");
2544 + if (i == 1 && read_write == I2C_SMBUS_READ) {
2545 + len = inb_p(SMBHSTDAT0);
2550 + data->block[0] = len;
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 */
2561 + if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
2563 + "Bad status (%02x) at end of transaction\n",
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));
2576 + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
2577 + /* wait for INTR bit as advised by Intel */
2580 + temp = inb_p(SMBHSTSTS);
2582 + } while ((!(temp & 0x02))
2583 + && (timeout++ < MAX_TIMEOUT));
2585 + if (timeout >= MAX_TIMEOUT) {
2586 + dev_dbg(I801_dev, "PEC Timeout!\n");
2588 + outb_p(temp, SMBHSTSTS);
2593 + if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
2594 + /* restore saved configuration register value */
2595 + pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
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)
2607 + int ret, xact = 0;
2611 + hwpec = (flags & I2C_CLIENT_PEC) != 0;
2615 + case I2C_SMBUS_QUICK:
2616 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2618 + xact = I801_QUICK;
2620 + case I2C_SMBUS_BYTE:
2621 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2623 + if (read_write == I2C_SMBUS_WRITE)
2624 + outb_p(command, SMBHSTCMD);
2627 + case I2C_SMBUS_BYTE_DATA:
2628 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2630 + outb_p(command, SMBHSTCMD);
2631 + if (read_write == I2C_SMBUS_WRITE)
2632 + outb_p(data->byte, SMBHSTDAT0);
2633 + xact = I801_BYTE_DATA;
2635 + case I2C_SMBUS_WORD_DATA:
2636 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
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);
2643 + xact = I801_WORD_DATA;
2645 + case I2C_SMBUS_BLOCK_DATA:
2646 + case I2C_SMBUS_I2C_BLOCK_DATA:
2648 + case I2C_SMBUS_BLOCK_DATA_PEC:
2649 + if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
2650 + size = I2C_SMBUS_BLOCK_DATA_PEC;
2652 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
2654 + outb_p(command, SMBHSTCMD);
2657 + case I2C_SMBUS_PROC_CALL:
2659 + dev_err(I801_dev, "Unsupported transaction %d\n", size);
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 */
2671 + ret = i801_block_transaction(data, read_write, size);
2673 + outb_p(xact | ENABLE_INT9, SMBHSTCNT);
2674 + ret = i801_transaction();
2678 + if(isich4 && hwpec) {
2679 + if(size != I2C_SMBUS_QUICK &&
2680 + size != I2C_SMBUS_I2C_BLOCK_DATA)
2681 + outb_p(0, SMBAUXCTL);
2689 + if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
2692 + switch (xact & 0x7f) {
2693 + case I801_BYTE: /* Result put in SMBHSTDAT0 */
2694 + case I801_BYTE_DATA:
2695 + data->byte = inb_p(SMBHSTDAT0);
2697 + case I801_WORD_DATA:
2698 + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
2705 +static u32 i801_func(struct i2c_adapter *adapter)
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
2711 + | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
2712 + I2C_FUNC_SMBUS_HWPEC_CALC
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,
2725 +static struct i2c_adapter i801_adapter = {
2726 + .owner = THIS_MODULE,
2727 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
2728 + .algo = &smbus_algorithm,
2732 +static struct pci_device_id i801_ids[] __devinitdata = {
2734 + .vendor = PCI_VENDOR_ID_INTEL,
2735 + .device = PCI_DEVICE_ID_INTEL_82801AA_3,
2736 + .subvendor = PCI_ANY_ID,
2737 + .subdevice = PCI_ANY_ID,
2740 + .vendor = PCI_VENDOR_ID_INTEL,
2741 + .device = PCI_DEVICE_ID_INTEL_82801AB_3,
2742 + .subvendor = PCI_ANY_ID,
2743 + .subdevice = PCI_ANY_ID,
2746 + .vendor = PCI_VENDOR_ID_INTEL,
2747 + .device = PCI_DEVICE_ID_INTEL_82801BA_2,
2748 + .subvendor = PCI_ANY_ID,
2749 + .subdevice = PCI_ANY_ID,
2752 + .vendor = PCI_VENDOR_ID_INTEL,
2753 + .device = PCI_DEVICE_ID_INTEL_82801CA_3,
2754 + .subvendor = PCI_ANY_ID,
2755 + .subdevice = PCI_ANY_ID,
2758 + .vendor = PCI_VENDOR_ID_INTEL,
2759 + .device = PCI_DEVICE_ID_INTEL_82801DB_3,
2760 + .subvendor = PCI_ANY_ID,
2761 + .subdevice = PCI_ANY_ID,
2764 + .vendor = PCI_VENDOR_ID_INTEL,
2765 + .device = 0x24d3, /* 82801EB ICH5 */
2766 + .subvendor = PCI_ANY_ID,
2767 + .subdevice = PCI_ANY_ID,
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,
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,
2784 +static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
2787 + if (i801_setup(dev)) {
2789 + "I801 not detected, module not inserted.\n");
2793 + snprintf(i801_adapter.name, 32,
2794 + "SMBus I801 adapter at %04x", i801_smba);
2795 + return i2c_add_adapter(&i801_adapter);
2798 +static void __devexit i801_remove(struct pci_dev *dev)
2800 + i2c_del_adapter(&i801_adapter);
2801 + release_region(i801_smba, (isich4 ? 16 : 8));
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),
2811 +static int __init i2c_i801_init(void)
2813 + printk(KERN_INFO "i2c-i801 version %s (%s)\n", LM_VERSION, LM_DATE);
2814 + return pci_module_init(&i801_driver);
2817 +static void __exit i2c_i801_exit(void)
2819 + pci_unregister_driver(&i801_driver);
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");
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
2834 + i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware
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>
2841 + Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
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.
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.
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.
2859 + This interfaces to the I810/I815 to provide access to
2860 + the DDC Bus and the I2C Bus.
2862 + SUPPORTED DEVICES PCI ID
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"
2880 +MODULE_LICENSE("GPL");
2882 +#ifndef PCI_DEVICE_ID_INTEL_82815_2
2883 +#define PCI_DEVICE_ID_INTEL_82815_2 0x1132
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
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
2904 +/* initialization states */
2910 +#define CYCLE_DELAY 10
2911 +#define TIMEOUT (HZ / 2)
2914 +static void config_i810(struct pci_dev *dev);
2917 +static unsigned long ioaddr;
2919 +/* The i810 GPIO registers have individual masks for each bit
2920 + so we never have to read before writing. Nice. */
2922 +static void bit_i810i2c_setscl(void *data, int val)
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 */
2929 +static void bit_i810i2c_setsda(void *data, int val)
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 */
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. */
2946 +static int bit_i810i2c_getscl(void *data)
2948 + writel(SCL_DIR_MASK, ioaddr + I810_GPIOB);
2949 + writel(0, ioaddr + I810_GPIOB);
2950 + return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN));
2953 +static int bit_i810i2c_getsda(void *data)
2955 + writel(SDA_DIR_MASK, ioaddr + I810_GPIOB);
2956 + writel(0, ioaddr + I810_GPIOB);
2957 + return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN));
2960 +static void bit_i810ddc_setscl(void *data, int val)
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 */
2967 +static void bit_i810ddc_setsda(void *data, int val)
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 */
2974 +static int bit_i810ddc_getscl(void *data)
2976 + writel(SCL_DIR_MASK, ioaddr + I810_GPIOA);
2977 + writel(0, ioaddr + I810_GPIOA);
2978 + return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN));
2981 +static int bit_i810ddc_getsda(void *data)
2983 + writel(SDA_DIR_MASK, ioaddr + I810_GPIOA);
2984 + writel(0, ioaddr + I810_GPIOA);
2985 + return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN));
2989 +/* Configures the chip */
2990 +void config_i810(struct pci_dev *dev)
2992 + unsigned long cadr;
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);
3000 + bit_i810i2c_setscl(NULL, 1);
3001 + bit_i810i2c_setsda(NULL, 1);
3002 + bit_i810ddc_setscl(NULL, 1);
3003 + bit_i810ddc_setsda(NULL, 1);
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,
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,
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,
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,
3043 +static struct pci_device_id i810_ids[] __devinitdata = {
3045 + .vendor = PCI_VENDOR_ID_INTEL,
3046 + .device = PCI_DEVICE_ID_INTEL_82810_IG1,
3047 + .subvendor = PCI_ANY_ID,
3048 + .subdevice = PCI_ANY_ID,
3051 + .vendor = PCI_VENDOR_ID_INTEL,
3052 + .device = PCI_DEVICE_ID_INTEL_82810_IG3,
3053 + .subvendor = PCI_ANY_ID,
3054 + .subdevice = PCI_ANY_ID,
3057 + .vendor = PCI_VENDOR_ID_INTEL,
3059 + .subvendor = PCI_ANY_ID,
3060 + .subdevice = PCI_ANY_ID,
3063 + .vendor = PCI_VENDOR_ID_INTEL,
3064 + .device = PCI_DEVICE_ID_INTEL_82815_2,
3065 + .subvendor = PCI_ANY_ID,
3066 + .subdevice = PCI_ANY_ID,
3069 + .vendor = PCI_VENDOR_ID_INTEL,
3071 + .subvendor = PCI_ANY_ID,
3072 + .subdevice = PCI_ANY_ID,
3077 +static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id)
3082 + printk("i2c-i810.o: i810/i815 found.\n");
3084 + retval = i2c_bit_add_bus(&i810_i2c_adapter);
3087 + retval = i2c_bit_add_bus(&i810_ddc_adapter);
3089 + i2c_bit_del_bus(&i810_i2c_adapter);
3093 +static void __devexit i810_remove(struct pci_dev *dev)
3095 + i2c_bit_del_bus(&i810_ddc_adapter);
3096 + i2c_bit_del_bus(&i810_i2c_adapter);
3100 +/* Don't register driver to avoid driver conflicts */
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),
3110 +static int __init i2c_i810_init(void)
3112 + struct pci_dev *dev;
3113 + const struct pci_device_id *id;
3115 + printk("i2c-i810.o version %s (%s)\n", LM_VERSION, LM_DATE);
3117 + return pci_module_init(&i810_driver);
3119 + pci_for_each_dev(dev) {
3120 + id = pci_match_device(i810_ids, dev);
3122 + if(i810_probe(dev, id) >= 0)
3128 +static void __exit i2c_i810_exit(void)
3131 + pci_unregister_driver(&i810_driver);
3133 + i810_remove(NULL);
3134 + iounmap((void *)ioaddr);
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");
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
3147 + i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware
3149 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
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.
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.
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.
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
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"
3180 +static u32 isa_func(struct i2c_adapter *adapter);
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,
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,
3197 +/* We can't do a thing... */
3198 +static u32 isa_func(struct i2c_adapter *adapter)
3203 +static int __init i2c_isa_init(void)
3205 + printk("i2c-isa.o version %s (%s)\n", LM_VERSION, LM_DATE);
3206 + return i2c_add_adapter(&isa_adapter);
3209 +static void __exit i2c_isa_exit(void)
3211 + i2c_del_adapter(&isa_adapter);
3214 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
3215 +MODULE_DESCRIPTION("ISA bus access through i2c");
3216 +MODULE_LICENSE("GPL");
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
3224 + SMBus driver for nVidia nForce2 MCP
3226 + Copyright (c) 2003 Hans-Frieder Vogt <hfvogt@arcor.de>,
3228 + SMBus 2.0 driver for AMD-8111 IO-Hub
3229 + Copyright (c) 2002 Vojtech Pavlik
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.
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.
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.
3247 + SUPPORTED DEVICES PCI ID
3250 + This driver supports the 2 SMBuses that are included in the MCP2 of the
3254 +/* Note: we assume there can only be one nForce2, with two SMBus interfaces */
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"
3270 +/* kernel 2.4.9 needs this */
3272 +#define min_t(type,x,y) min(type,x,y)
3275 +MODULE_LICENSE("GPL");
3276 +MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>");
3277 +MODULE_DESCRIPTION("nForce2 SMBus driver");
3279 +#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS
3280 +#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064
3284 +struct nforce2_smbus {
3285 + struct pci_dev *dev;
3286 + struct i2c_adapter adapter;
3293 + * nVidia nForce2 SMBus control register definitions
3295 +#define NFORCE_PCI_SMB1 0x50
3296 +#define NFORCE_PCI_SMB2 0x54
3300 + * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
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 */
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
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
3329 +/* Other settings */
3330 +#define MAX_TIMEOUT 256
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);
3338 +static int nforce2_block_transaction(union i2c_smbus_data *data,
3339 + char read_write, int i2c_enable);
3341 +static u32 nforce2_func(struct i2c_adapter *adapter);
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,
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)
3356 + struct nforce2_smbus *smbus = adap->algo_data;
3357 + unsigned char protocol, pec, temp;
3358 + unsigned char len = 0; /* to keep the compiler quiet */
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;
3367 + case I2C_SMBUS_QUICK:
3368 + protocol |= NVIDIA_SMB_PRTCL_QUICK;
3369 + read_write = I2C_SMBUS_WRITE;
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;
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;
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);
3391 + protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
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);
3402 + protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
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;
3415 + case I2C_SMBUS_PROC_CALL:
3416 + printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_PROC_CALL not supported!\n");
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;
3427 + case I2C_SMBUS_BLOCK_PROC_CALL:
3428 + printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
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;
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);
3450 + printk(KERN_WARNING "i2c-nforce2.c: Unsupported transaction %d\n", size);
3454 + outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
3455 + outb_p(protocol, NVIDIA_SMB_PRTCL);
3457 + temp = inb_p(NVIDIA_SMB_STS);
3462 + temp = inb_p(NVIDIA_SMB_STS);
3463 + } while (((temp & NVIDIA_SMB_STS_DONE) == 0) && (timeout++ < MAX_TIMEOUT));
3465 + if (~temp & NVIDIA_SMB_STS_DONE) {
3467 + temp = inb_p(NVIDIA_SMB_STS);
3469 + if (~temp & NVIDIA_SMB_STS_DONE) {
3470 + i2c_delay(HZ/100);
3471 + temp = inb_p(NVIDIA_SMB_STS);
3474 + if ((timeout >= MAX_TIMEOUT) || (~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS))
3477 + if (read_write == I2C_SMBUS_WRITE)
3482 + case I2C_SMBUS_BYTE:
3483 + case I2C_SMBUS_BYTE_DATA:
3484 + data->byte = inb_p(NVIDIA_SMB_DATA);
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);
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;
3507 +u32 nforce2_func(struct i2c_adapter *adapter)
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 */;
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 },
3523 +static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg, struct nforce2_smbus *smbus, char *name)
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);
3533 + smbus->base = iobase & 0xfffc;
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);
3541 + /* TODO: find a better way to find out whether this file is compiled
3542 + * with i2c 2.7.0 of earlier
3544 +#ifdef I2C_HW_SMBUS_AMD8111
3545 + smbus->adapter.owner = THIS_MODULE;
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;
3552 + error = i2c_add_adapter(&smbus->adapter);
3554 + printk(KERN_WARNING "i2c-nforce2.o: Failed to register adapter.\n");
3555 + release_region(smbus->base, smbus->size);
3558 + printk(KERN_INFO "i2c-nforce2.o: nForce2 SMBus adapter at %#x\n", smbus->base);
3563 +static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
3565 + struct nforce2_smbus *smbuses;
3568 + /* we support 2 SMBus adapters */
3569 + if (!(smbuses = (void *)kmalloc(2*sizeof(struct nforce2_smbus),
3572 + memset (smbuses, 0, 2*sizeof(struct nforce2_smbus));
3573 + pci_set_drvdata(dev, smbuses);
3575 + /* SMBus adapter 1 */
3576 + res1 = nforce2_probe_smb (dev, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
3578 + printk (KERN_ERR "i2c-nforce2.o: Error probing SMB1.\n");
3579 + smbuses[0].base = 0; /* to have a check value */
3581 + res2 = nforce2_probe_smb (dev, NFORCE_PCI_SMB2, &smbuses[1], "SMB2");
3583 + printk (KERN_ERR "i2c-nforce2.o: Error probing SMB2.\n");
3584 + smbuses[1].base = 0; /* to have a check value */
3586 + if ((res1 < 0) && (res2 < 0)) {
3587 + /* we did not find even one of the SMBuses, so we give up */
3596 +static void __devexit nforce2_remove(struct pci_dev *dev)
3598 + struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
3600 + if (smbuses[0].base) {
3601 + i2c_del_adapter(&smbuses[0].adapter);
3602 + release_region(smbuses[0].base, smbuses[0].size);
3604 + if (smbuses[1].base) {
3605 + i2c_del_adapter(&smbuses[1].adapter);
3606 + release_region(smbuses[1].base, smbuses[1].size);
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),
3618 +int __init nforce2_init(void)
3620 + printk(KERN_INFO "i2c-nforce2.o version %s (%s)\n", LM_VERSION, LM_DATE);
3621 + return pci_module_init(&nforce2_driver);
3624 +void __exit nforce2_exit(void)
3626 + pci_unregister_driver(&nforce2_driver);
3629 +module_init(nforce2_init);
3630 +module_exit(nforce2_exit);
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
3636 + piix4.c - Part of lm_sensors, Linux kernel modules for hardware
3638 + Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
3639 + Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
3658 + Intel PIIX4, 440MX
3659 + Serverworks OSB4, CSB5, CSB6
3662 + Note: we assume there can only be one device, with one SMBus interface.
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"
3682 + const unsigned short mfr;
3683 + const unsigned short dev;
3684 + const unsigned char fn;
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)
3702 +/* count for request_region */
3703 +#define SMBIOSIZE 8
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
3713 +/* Other settings */
3714 +#define MAX_TIMEOUT 500
3715 +#define ENABLE_INT9 0
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
3724 +/* insmod parameters */
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!");
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!");
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).");
3745 +static int piix4_transaction(void);
3747 +static unsigned short piix4_smba = 0;
3751 + * Get DMI information.
3754 +static int __devinit ibm_dmi_probe(void)
3756 + extern int is_unsafe_smbus;
3757 + return is_unsafe_smbus;
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)
3768 + unsigned char temp;
3770 + /* match up the function */
3771 + if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
3774 + printk(KERN_INFO "Found %s device\n", PIIX4_dev->name);
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 "
3785 + /* Determine the address of the SMBus areas */
3787 + piix4_smba = force_addr & 0xfff0;
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");
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);
3806 + pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
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) {
3812 + printk(KERN_INFO "i2c-piix4.o: Working around buggy "
3815 + pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp);
3817 + printk(KERN_INFO "i2c-piix4.o: Unusual config register "
3819 + printk(KERN_INFO "i2c-piix4.o: Try using fix_hstcfg=1 "
3820 + "if you experience problems\n");
3824 + /* If force_addr is set, we program the new address here. Just to make
3825 + sure, we disable the PIIX4 first. */
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) {
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.
3842 + pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
3844 + printk(KERN_NOTICE "i2c-piix4.o: WARNING: SMBus "
3845 + "interface has been FORCEFULLY ENABLED!\n");
3847 + printk(KERN_ERR "i2c-piix4.o: Host SMBus controller "
3848 + "not enabled!\n");
3849 + release_region(piix4_smba, SMBIOSIZE);
3856 + if ((temp & 0x0E) == 8)
3857 + printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for "
3859 + else if ((temp & 0x0E) == 0)
3860 + printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# "
3863 + printk(KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration "
3864 + "(or code out of date)!\n");
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);
3875 +/* Another internally used function */
3876 +int piix4_transaction(void)
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));
3889 + /* Make sure the SMBus host is ready to start transmitting */
3890 + if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
3892 + printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n",
3895 + outb_p(temp, SMBHSTSTS);
3896 + if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
3898 + printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp);
3903 + printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n");
3908 + /* start the transaction by setting bit 6 */
3909 + outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
3911 + /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
3914 + temp = inb_p(SMBHSTSTS);
3915 + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
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");
3925 + if (temp & 0x10) {
3928 + printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n");
3932 + if (temp & 0x08) {
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 */
3940 + if (temp & 0x04) {
3943 + printk(KERN_ERR "i2c-piix4.o: Error: no response!\n");
3947 + if (inb_p(SMBHSTSTS) != 0x00)
3948 + outb_p(inb(SMBHSTSTS), SMBHSTSTS);
3951 + if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
3953 + (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n",
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));
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)
3972 + case I2C_SMBUS_QUICK:
3973 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
3975 + size = PIIX4_QUICK;
3977 + case I2C_SMBUS_BYTE:
3978 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
3980 + if (read_write == I2C_SMBUS_WRITE)
3981 + outb_p(command, SMBHSTCMD);
3982 + size = PIIX4_BYTE;
3984 + case I2C_SMBUS_BYTE_DATA:
3985 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
3987 + outb_p(command, SMBHSTCMD);
3988 + if (read_write == I2C_SMBUS_WRITE)
3989 + outb_p(data->byte, SMBHSTDAT0);
3990 + size = PIIX4_BYTE_DATA;
3992 + case I2C_SMBUS_WORD_DATA:
3993 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
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);
4000 + size = PIIX4_WORD_DATA;
4002 + case I2C_SMBUS_BLOCK_DATA:
4003 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
4005 + outb_p(command, SMBHSTCMD);
4006 + if (read_write == I2C_SMBUS_WRITE) {
4007 + len = data->block[0];
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);
4017 + size = PIIX4_BLOCK_DATA;
4021 + (KERN_WARNING "i2c-piix4.o: Unsupported transaction %d\n", size);
4025 + outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
4027 + if (piix4_transaction()) /* Error in transaction */
4030 + if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
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 */
4039 + data->byte = inb_p(SMBHSTDAT0);
4041 + case PIIX4_BYTE_DATA:
4042 + data->byte = inb_p(SMBHSTDAT0);
4044 + case PIIX4_WORD_DATA:
4045 + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
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);
4058 +u32 piix4_func(struct i2c_adapter *adapter)
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;
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,
4072 +static struct i2c_adapter piix4_adapter = {
4073 + .owner = THIS_MODULE,
4075 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
4076 + .algo = &smbus_algorithm,
4079 +#ifndef PCI_DEVICE_ID_SERVERWORKS_CSB6
4080 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203
4083 +static struct pci_device_id piix4_ids[] __devinitdata = {
4085 + .vendor = PCI_VENDOR_ID_INTEL,
4086 + .device = PCI_DEVICE_ID_INTEL_82371AB_3,
4087 + .subvendor = PCI_ANY_ID,
4088 + .subdevice = PCI_ANY_ID,
4092 + .vendor = PCI_VENDOR_ID_SERVERWORKS,
4093 + .device = PCI_DEVICE_ID_SERVERWORKS_OSB4,
4094 + .subvendor = PCI_ANY_ID,
4095 + .subdevice = PCI_ANY_ID,
4099 + .vendor = PCI_VENDOR_ID_SERVERWORKS,
4100 + .device = PCI_DEVICE_ID_SERVERWORKS_CSB5,
4101 + .subvendor = PCI_ANY_ID,
4102 + .subdevice = PCI_ANY_ID,
4106 + .vendor = PCI_VENDOR_ID_SERVERWORKS,
4107 + .device = PCI_DEVICE_ID_SERVERWORKS_CSB6,
4108 + .subvendor = PCI_ANY_ID,
4109 + .subdevice = PCI_ANY_ID,
4113 + .vendor = PCI_VENDOR_ID_INTEL,
4114 + .device = PCI_DEVICE_ID_INTEL_82443MX_3,
4115 + .subvendor = PCI_ANY_ID,
4116 + .subdevice = PCI_ANY_ID,
4120 + .vendor = PCI_VENDOR_ID_EFAR,
4121 + .device = PCI_DEVICE_ID_EFAR_SLC90E66_3,
4122 + .subvendor = PCI_ANY_ID,
4123 + .subdevice = PCI_ANY_ID,
4129 +static int __devinit piix4_probe(struct pci_dev *dev,
4130 + const struct pci_device_id *id)
4134 + retval = piix4_setup(dev, id);
4138 + sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
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);
4150 +static void __devexit piix4_remove(struct pci_dev *dev)
4153 + i2c_del_adapter(&piix4_adapter);
4154 + release_region(piix4_smba, SMBIOSIZE);
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),
4166 +static int __init i2c_piix4_init(void)
4168 + printk("i2c-piix4.o version %s (%s)\n", LM_VERSION, LM_DATE);
4169 + return pci_module_init(&piix4_driver);
4172 +static void __exit i2c_piix4_exit(void)
4174 + pci_unregister_driver(&piix4_driver);
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");
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
4188 + i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware
4190 + Copyright (C) 1998-2003 The LM Sensors Team
4191 + Alexander Wold <awold@bigfoot.com>
4192 + Mark D. Studebaker <mdsxyz123@yahoo.com>
4194 + Based on i2c-voodoo3.c.
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.
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.
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.
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.
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"
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
4241 +#define REG 0xff20 /* Serial Port 1 Register */
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
4255 +/* initialization states */
4257 +/* #define INIT3 0x4 */
4260 +#define CYCLE_DELAY 10
4261 +#define TIMEOUT (HZ / 2)
4264 +static void config_s4(struct pci_dev *dev);
4266 +static unsigned long ioaddr;
4268 +/* The sav GPIO registers don't have individual masks for each bit
4269 + so we always have to read before writing. */
4271 +static void bit_savi2c_setscl(void *data, int val)
4274 + r = readl(ioaddr + REG);
4278 + r &= ~I2C_SCL_OUT;
4279 + writel(r, ioaddr + REG);
4280 + readl(ioaddr + REG); /* flush posted write */
4283 +static void bit_savi2c_setsda(void *data, int val)
4286 + r = readl(ioaddr + REG);
4290 + r &= ~I2C_SDA_OUT;
4291 + writel(r, ioaddr + REG);
4292 + readl(ioaddr + REG); /* flush posted write */
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. */
4299 +static int bit_savi2c_getscl(void *data)
4301 + return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
4304 +static int bit_savi2c_getsda(void *data)
4306 + return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
4309 +/* Configures the chip */
4311 +void config_s4(struct pci_dev *dev)
4313 + unsigned int cadr;
4316 + cadr = dev->resource[0].start;
4317 + cadr &= PCI_BASE_ADDRESS_MEM_MASK;
4318 + ioaddr = (unsigned long)ioremap_nocache(cadr, 0x0080000);
4320 +// writel(0x8160, ioaddr + REG2);
4321 + writel(0x00000020, ioaddr + REG);
4322 + printk("i2c-savage4: Using Savage4 at 0x%lx\n", ioaddr);
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
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,
4344 +static struct pci_device_id savage4_ids[] __devinitdata = {
4346 + .vendor = PCI_VENDOR_ID_S3,
4347 + .device = PCI_CHIP_SAVAGE4,
4348 + .subvendor = PCI_ANY_ID,
4349 + .subdevice = PCI_ANY_ID,
4352 + .vendor = PCI_VENDOR_ID_S3,
4353 + .device = PCI_CHIP_SAVAGE2000,
4354 + .subvendor = PCI_ANY_ID,
4355 + .subdevice = PCI_ANY_ID,
4360 +static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id)
4363 + return i2c_bit_add_bus(&savage4_i2c_adapter);
4366 +static void __devexit savage4_remove(struct pci_dev *dev)
4368 + i2c_bit_del_bus(&savage4_i2c_adapter);
4372 +/* Don't register driver to avoid driver conflicts */
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),
4382 +static int __init i2c_savage4_init(void)
4384 + struct pci_dev *dev;
4385 + const struct pci_device_id *id;
4387 + printk("i2c-savage4.o version %s (%s)\n", LM_VERSION, LM_DATE);
4389 + return pci_module_init(&savage4_driver);
4391 + pci_for_each_dev(dev) {
4392 + id = pci_match_device(savage4_ids, dev);
4394 + if(savage4_probe(dev, id) >= 0)
4400 +static void __exit i2c_savage4_exit(void)
4403 + pci_unregister_driver(&savage4_driver);
4405 + savage4_remove(NULL);
4406 + iounmap((void *)ioaddr);
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");
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
4420 + sis5595.c - Part of lm_sensors, Linux kernel modules for hardware
4422 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
4423 + Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
4440 +/* Note: we assume there can only be one SIS5595 with one SMBus interface */
4443 + Note: all have mfr. ID 0x1039.
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.
4451 + NOT SUPPORTED PCI ID BLACKLIST PCI ID
4458 + 5598 0008 5597/5598
4472 + * Add Block Transfers (ugly, but supported by the adapter)
4473 + * Add adapter resets
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"
4488 +MODULE_LICENSE("GPL");
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,
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
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
4533 +/* Other settings */
4534 +#define MAX_TIMEOUT 500
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
4544 +/* insmod parameters */
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");
4553 +static int sis5595_transaction(void);
4555 +static unsigned short sis5595_base = 0;
4557 +static u8 sis5595_read(u8 reg)
4559 + outb(reg, sis5595_base + SMB_INDEX);
4560 + return inb(sis5595_base + SMB_DAT);
4563 +static void sis5595_write(u8 reg, u8 data)
4565 + outb(reg, sis5595_base + SMB_INDEX);
4566 + outb(data, sis5595_base + SMB_DAT);
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)
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);
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");
4596 + sis5595_base = force_addr & ~(SIS5595_EXTENT - 1);
4598 + printk("ACPI Base address: %04x\n", sis5595_base);
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)) {
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);
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))
4615 + if (PCIBIOS_SUCCESSFUL !=
4616 + pci_read_config_word(SIS5595_dev, ACPI_BASE, &a))
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");
4625 + if (PCIBIOS_SUCCESSFUL !=
4626 + pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val))
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,
4634 + if (PCIBIOS_SUCCESSFUL !=
4635 + pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val))
4637 + if((val & 0x80) == 0) { /* doesn't work for some chips? */
4638 + printk("sis5595.o: ACPI enable failed - not supported?\n");
4643 + /* Everything is happy, let's grab the memory and set things up. */
4644 + request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus");
4649 +/* Another internally used function */
4650 +int sis5595_transaction(void)
4656 + /* Make sure the SMBus host is ready to start transmitting */
4659 + sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
4662 + printk("i2c-sis5595.o: SMBus busy (%04x). Resetting... \n",
4665 + sis5595_write(SMB_STS_LO, temp & 0xff);
4666 + sis5595_write(SMB_STS_HI, temp >> 8);
4669 + sis5595_read(SMB_STS_LO) +
4670 + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
4672 + printk("i2c-sis5595.o: Failed! (%02x)\n", temp);
4677 + printk("i2c-sis5595.o: Successfull!\n");
4682 + /* start the transaction by setting bit 4 */
4683 + sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
4685 + /* We will always wait for a fraction of a second! */
4688 + temp = sis5595_read(SMB_STS_LO);
4689 + } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
4691 + /* If the SMBus is still busy, we give up */
4692 + if (timeout >= MAX_TIMEOUT) {
4694 + printk("i2c-sis5595.o: SMBus Timeout!\n");
4699 + if (temp & 0x10) {
4702 + printk("i2c-sis5595.o: Error: Failed bus transaction\n");
4706 + if (temp & 0x20) {
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 */
4716 + sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
4718 + sis5595_write(SMB_STS_LO, temp & 0xff);
4719 + sis5595_write(SMB_STS_HI, temp >> 8);
4724 + sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
4729 + ("i2c-sis5595.o: Failed reset at end of transaction (%02x)\n",
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)
4742 + case I2C_SMBUS_QUICK:
4743 + sis5595_write(SMB_ADDR,
4744 + ((addr & 0x7f) << 1) | (read_write & 0x01));
4745 + size = SIS5595_QUICK;
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;
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;
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);
4774 + I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL :
4775 + SIS5595_WORD_DATA;
4778 + case I2C_SMBUS_BLOCK_DATA:
4779 + printk("sis5595.o: Block data not yet implemented!\n");
4785 + (KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size);
4789 + sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
4791 + if (sis5595_transaction()) /* Error in transaction */
4794 + if ((size != SIS5595_PROC_CALL) &&
4795 + ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
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);
4806 + case SIS5595_WORD_DATA:
4807 + case SIS5595_PROC_CALL:
4809 + sis5595_read(SMB_BYTE) +
4810 + (sis5595_read(SMB_BYTE + 1) << 8);
4817 +u32 sis5595_func(struct i2c_adapter *adapter)
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;
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,
4832 +static struct i2c_adapter sis5595_adapter = {
4833 + .owner = THIS_MODULE,
4835 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS5595,
4836 + .algo = &smbus_algorithm,
4840 +static struct pci_device_id sis5595_ids[] __devinitdata = {
4842 + .vendor = PCI_VENDOR_ID_SI,
4843 + .device = PCI_DEVICE_ID_SI_503,
4844 + .subvendor = PCI_ANY_ID,
4845 + .subdevice = PCI_ANY_ID,
4850 +static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
4853 + if (sis5595_setup(dev)) {
4855 + ("i2c-sis5595.o: SIS5595 not detected, module not inserted.\n");
4860 + sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
4861 + sis5595_base + SMB_INDEX);
4862 + i2c_add_adapter(&sis5595_adapter);
4867 +static void __devexit sis5595_remove(struct pci_dev *dev)
4869 + i2c_del_adapter(&sis5595_adapter);
4870 + release_region(sis5595_base + SMB_INDEX, 2);
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),
4881 +static int __init i2c_sis5595_init(void)
4883 + printk("i2c-sis5595.o version %s (%s)\n", LM_VERSION, LM_DATE);
4884 + return pci_module_init(&sis5595_driver);
4888 +static void __exit i2c_sis5595_exit(void)
4890 + pci_unregister_driver(&sis5595_driver);
4895 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
4896 +MODULE_DESCRIPTION("SIS5595 SMBus driver");
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
4904 + i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware
4907 + Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
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.
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.
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.
4927 + Fixed the typo in sis630_access (Thanks to Mark M. Hoffman)
4928 + Changed sis630_transaction.(Thanks to Mark M. Hoffman)
4930 + Added SIS730 as supported.
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).
4937 + Fixed typo in sis630_access
4938 + Fixed logical error by restoring of Host Master Clock
4940 + Added block data read/write support.
4950 + Note: we assume there can only be one device, with one SMBus interface.
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"
4967 +#define DBG(x...) printk(KERN_DEBUG "i2c-sis630.o: " x)
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
4987 +/* register count for request_region */
4988 +#define SIS630_SMB_IOREGION 20
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
4996 +/* Other settings */
4997 +#define MAX_TIMEOUT 500
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
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!");
5015 +/* acpi base address */
5016 +static unsigned short acpi_base = 0;
5018 +/* supported chips */
5019 +static int supported[] = {
5020 + PCI_DEVICE_ID_SI_630,
5021 + PCI_DEVICE_ID_SI_730,
5022 + 0 /* terminates the list */
5025 +static inline u8 sis630_read(u8 reg) {
5026 + return inb(acpi_base + reg);
5029 +static inline void sis630_write(u8 reg, u8 data) {
5030 + outb(data, acpi_base + reg);
5033 +static int sis630_transaction_start(int size, u8 *oldclock) {
5037 + Make sure the SMBus host is ready to start transmitting.
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);
5044 + if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
5045 + DBG("Failed! (%02x)\n", temp);
5048 + DBG("Successfull!\n");
5052 + /* save old clock, so we can prevent machine for hung */
5053 + *oldclock = sis630_read(SMB_CNT);
5055 + DBG("saved clock 0x%02x\n", *oldclock);
5057 + /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
5058 + if (high_clock > 0)
5059 + sis630_write(SMB_CNT, 0x20);
5061 + sis630_write(SMB_CNT, (*oldclock & ~0x40));
5063 + /* clear all sticky bits */
5064 + temp = sis630_read(SMB_STS);
5065 + sis630_write(SMB_STS, temp & 0x1e);
5067 + /* start the transaction by setting bit 4 and size */
5068 + sis630_write(SMBHOST_CNT,0x10 | (size & 0x07));
5073 +static int sis630_transaction_wait(int size) {
5074 + int temp, result = 0, timeout = 0;
5076 + /* We will always wait for a fraction of a second! */
5079 + temp = sis630_read(SMB_STS);
5080 + /* check if block transmitted */
5081 + if (size == SIS630_BLOCK_DATA && (temp & 0x10))
5083 + } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
5085 + /* If the SMBus is still busy, we give up */
5086 + if (timeout >= MAX_TIMEOUT) {
5087 + DBG("SMBus Timeout!\n");
5091 + if (temp & 0x02) {
5093 + DBG("Error: Failed bus transaction\n");
5096 + if (temp & 0x04) {
5098 + printk(KERN_ERR "i2c-sis630.o: Bus collision!\n");
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?
5109 +static void sis630_transaction_end(u8 oldclock) {
5112 + /* clear all status "sticky" bits */
5113 + sis630_write(SMB_STS, temp);
5115 + DBG("SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
5118 + * restore old Host Master Clock if high_clock is set
5119 + * and oldclock was not 56KHz
5121 + if (high_clock > 0 && !(oldclock & 0x20))
5122 + sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20));
5124 + DBG("SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
5127 +static int sis630_transaction(int size) {
5131 + if (!(result = sis630_transaction_start(size, &oldclock))) {
5132 + result = sis630_transaction_wait(size);
5133 + sis630_transaction_end(oldclock);
5139 +static int sis630_block_data(union i2c_smbus_data * data, int read_write) {
5140 + int i, len = 0, rc = 0;
5143 + if (read_write == I2C_SMBUS_WRITE) {
5144 + len = data->block[0];
5147 + else if (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]);
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))
5160 + else if ((i-1)%8 == 7 || i==len) {
5161 + DBG("trans_wait len=%d i=%d\n",len,i);
5163 + DBG("clear smbary_sts len=%d i=%d\n",len,i);
5165 + If this is not first transaction,
5166 + we must clear sticky bit.
5169 + sis630_write(SMB_STS,0x10);
5171 + if (sis630_transaction_wait(SIS630_BLOCK_DATA)) {
5172 + DBG("trans_wait failed\n");
5180 + else { /* read request */
5181 + data->block[0] = len = 0;
5182 + if (sis630_transaction_start(SIS630_BLOCK_DATA, &oldclock)) {
5186 + if (sis630_transaction_wait(SIS630_BLOCK_DATA)) {
5187 + DBG("trans_wait failed\n");
5191 + /* if this first transaction then read byte count */
5193 + data->block[0] = sis630_read(SMB_COUNT);
5195 + /* just to be sure */
5196 + if (data->block[0] > 32)
5197 + data->block[0] = 32;
5199 + DBG("block data read len=0x%x\n", data->block[0]);
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);
5206 + DBG("clear smbary_sts len=%d i=%d\n",len,i);
5208 + /* clear SMBARY_STS */
5209 + sis630_write(SMB_STS,0x10);
5210 + } while(len < data->block[0]);
5213 + sis630_transaction_end(oldclock);
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)
5225 + case I2C_SMBUS_QUICK:
5226 + sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5227 + size = SIS630_QUICK;
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;
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;
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);
5250 + size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
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);
5258 + printk("Unsupported I2C size\n");
5264 + if (sis630_transaction(size))
5267 + if ((size != SIS630_PCALL) &&
5268 + ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
5274 + case SIS630_BYTE_DATA:
5275 + data->byte = sis630_read(SMB_BYTE);
5277 + case SIS630_PCALL:
5278 + case SIS630_WORD_DATA:
5279 + data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
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;
5296 +static int __devinit sis630_setup(struct pci_dev *sis630_dev) {
5298 + struct pci_dev *dummy = NULL;
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 */
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");
5311 + else if (!dummy) {
5316 + Enable ACPI first , so we can accsess reg 74-75
5317 + in acpi io space and read acpi base addr
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");
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");
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");
5339 + DBG("ACPI base at 0x%04x\n", acpi_base);
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 */
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,
5360 +static struct i2c_adapter sis630_adapter = {
5361 + .owner = THIS_MODULE,
5363 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS630,
5364 + .algo = &smbus_algorithm,
5368 +static struct pci_device_id sis630_ids[] __devinitdata = {
5370 + .vendor = PCI_VENDOR_ID_SI,
5371 + .device = PCI_DEVICE_ID_SI_503,
5372 + .subvendor = PCI_ANY_ID,
5373 + .subdevice = PCI_ANY_ID,
5378 +static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
5380 + if (sis630_setup(dev)) {
5381 + printk(KERN_ERR "i2c-sis630.o: SIS630 comp. bus not detected, module not inserted.\n");
5385 + sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
5386 + acpi_base + SMB_STS);
5388 + return i2c_add_adapter(&sis630_adapter);
5391 +static void __devexit sis630_remove(struct pci_dev *dev)
5394 + i2c_del_adapter(&sis630_adapter);
5395 + release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
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),
5408 +static int __init i2c_sis630_init(void)
5410 + printk("i2c-sis630.o version %s (%s)\n", LM_VERSION, LM_DATE);
5411 + return pci_module_init(&sis630_driver);
5415 +static void __exit i2c_sis630_exit(void)
5417 + pci_unregister_driver(&sis630_driver);
5423 +MODULE_LICENSE("GPL");
5425 +MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
5426 +MODULE_DESCRIPTION("SIS630 SMBus driver");
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
5434 + sis645.c - Part of lm_sensors, Linux kernel modules for hardware
5437 + Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
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.
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.
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.
5455 + This module must be considered BETA unless and until
5456 + the chipset manufacturer releases a datasheet.
5458 + The register definitions are based on the SiS630.
5459 + The method for *finding* the registers is based on trial and error.
5461 + A history of changes to this file is available by anonymous CVS:
5462 + http://www2.lm-sensors.nu/~lm78/download.html
5466 + Support for Sis655 chipsets added by Ken Healy
5470 + Note: we assume there can only be one SiS645 with one SMBus interface
5473 +/* #define DEBUG 1 */
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>
5489 +#define DRV_NAME "i2c-sis645"
5491 +/* SiS645DX north bridge (defined in 2.4.21) */
5492 +#ifndef PCI_DEVICE_ID_SI_646
5493 +#define PCI_DEVICE_ID_SI_646 0x0646
5496 +/* SiS648 north bridge (defined in 2.4.21) */
5497 +#ifndef PCI_DEVICE_ID_SI_648
5498 +#define PCI_DEVICE_ID_SI_648 0x0648
5501 +/* SiS650 north bridge (defined in 2.4.19) */
5502 +#ifndef PCI_DEVICE_ID_SI_650
5503 +#define PCI_DEVICE_ID_SI_650 0x0650
5506 +/* SiS651 north bridge (defined in 2.4.21)*/
5507 +#ifndef PCI_DEVICE_ID_SI_651
5508 +#define PCI_DEVICE_ID_SI_651 0x0651
5511 +/* SiS655 north bridge (defined in 2.4.22)*/
5512 +#ifndef PCI_DEVICE_ID_SI_655
5513 +#define PCI_DEVICE_ID_SI_655 0x0655
5516 +/* SiS746 north bridge (defined in 2.4.21) */
5517 +#ifndef PCI_DEVICE_ID_SI_746
5518 +#define PCI_DEVICE_ID_SI_746 0x0746
5521 +/* SiS85C503/5513 (LPC Bridge) */
5522 +#ifndef PCI_DEVICE_ID_SI_LPC
5523 +#define PCI_DEVICE_ID_SI_LPC 0x0018
5526 +/* SiS961 south bridge */
5527 +#ifndef PCI_DEVICE_ID_SI_961
5528 +#define PCI_DEVICE_ID_SI_961 0x0961
5531 +/* SiS962 south bridge */
5532 +#ifndef PCI_DEVICE_ID_SI_962
5533 +#define PCI_DEVICE_ID_SI_962 0x0962
5536 +/* SiS963 south bridge */
5537 +#ifndef PCI_DEVICE_ID_SI_963
5538 +#define PCI_DEVICE_ID_SI_963 0x0963
5542 +#ifndef PCI_DEVICE_ID_SI_SMBUS
5543 +#define PCI_DEVICE_ID_SI_SMBUS 0x16
5546 +/* base address register in PCI config space */
5547 +#define SIS645_BAR 0x04
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
5564 +/* register count for request_region */
5565 +#define SMB_IOSIZE 0x20
5567 +/* Other settings */
5568 +#define MAX_TIMEOUT 500
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
5578 +static struct i2c_adapter sis645_adapter;
5579 +static u16 sis645_smbus_base = 0;
5581 +static inline u8 sis645_read(u8 reg)
5583 + return inb(sis645_smbus_base + reg) ;
5586 +static inline void sis645_write(u8 reg, u8 data)
5588 + outb(data, sis645_smbus_base + reg) ;
5591 +#ifdef CONFIG_HOTPLUG
5593 +/* Turns on SMBus device if it is not; return 0 iff successful
5595 +static int __devinit sis645_enable_smbus(struct pci_dev *dev)
5599 + pci_read_config_byte(dev, 0x77, &val);
5602 + printk(KERN_DEBUG DRV_NAME ": Config byte was 0x%02x.\n", val);
5605 + pci_write_config_byte(dev, 0x77, val & ~0x10);
5607 + pci_read_config_byte(dev, 0x77, &val);
5611 + printk(KERN_DEBUG DRV_NAME ": Config byte stuck!\n");
5619 +/* Builds the basic pci_dev for SiS645 SMBus
5621 +static int __devinit sis645_build_dev(struct pci_dev **smbus_dev,
5622 + struct pci_dev *bridge_dev)
5624 + struct pci_dev temp_dev;
5625 + u16 vid = 0, did = 0;
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;
5634 + /* the SMBus device is function 1 on the same unit as the ISA bridge */
5635 + temp_dev.devfn = bridge_dev->devfn + 1;
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");
5643 + temp_dev.vendor = vid;
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");
5650 + temp_dev.device = did;
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");
5659 + **smbus_dev = temp_dev;
5661 + ret = pci_setup_device(*smbus_dev);
5663 + printk(KERN_ERR DRV_NAME ": pci_setup_device failed (0x%08x)\n",ret);
5668 +/* See if a SMBus can be found, and enable it if possible.
5670 +static int __devinit sis645_hotplug_smbus(void)
5673 + struct pci_dev *smbus_dev, *bridge_dev ;
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");
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");
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");
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))) {
5692 + printk(KERN_INFO DRV_NAME ": Found SiS south bridge in compatability mode(?)\n");
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");
5717 + printk(KERN_ERR DRV_NAME ": Can't find suitable south bridge!\n");
5721 + /* if we get this far, we think the smbus device is present */
5723 + if ((ret = sis645_enable_smbus(bridge_dev)))
5726 + if ((ret = sis645_build_dev(&smbus_dev, bridge_dev)))
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);
5735 + pci_insert_device(smbus_dev, smbus_dev->bus);
5739 +#endif /* CONFIG_HOTPLUG */
5741 +/* Execute a SMBus transaction.
5742 + int size is from SIS645_QUICK to SIS645_BLOCK_DATA
5744 +static int sis645_transaction(int size)
5750 + /* Make sure the SMBus host is ready to start transmitting */
5751 + if (((temp = sis645_read(SMB_CNT)) & 0x03) != 0x00) {
5753 + printk(KERN_DEBUG DRV_NAME ": SMBus busy (0x%02x). Resetting...\n",
5757 + /* kill the transaction */
5758 + sis645_write(SMB_HOST_CNT, 0x20);
5760 + /* check it again */
5761 + if (((temp = sis645_read(SMB_CNT)) & 0x03) != 0x00) {
5763 + printk(KERN_DEBUG DRV_NAME ": Failed! (0x%02x)\n", temp);
5768 + printk(KERN_DEBUG DRV_NAME ": Successful!\n");
5773 + /* Turn off timeout interrupts, set fast host clock */
5774 + sis645_write(SMB_CNT, 0x20);
5776 + /* clear all (sticky) status flags */
5777 + temp = sis645_read(SMB_STS);
5778 + sis645_write(SMB_STS, temp & 0x1e);
5780 + /* start the transaction by setting bit 4 and size bits */
5781 + sis645_write(SMB_HOST_CNT, 0x10 | (size & 0x07));
5783 + /* We will always wait for a fraction of a second! */
5786 + temp = sis645_read(SMB_STS);
5787 + } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
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);
5795 + /* device error - probably missing ACK */
5796 + if (temp & 0x02) {
5798 + printk(KERN_DEBUG DRV_NAME ": Failed bus transaction!\n");
5803 + /* bus collision */
5804 + if (temp & 0x04) {
5806 + printk(KERN_DEBUG DRV_NAME ": Bus collision!\n");
5811 + /* Finish up by resetting the bus */
5812 + sis645_write(SMB_STS, temp);
5813 + if ((temp = sis645_read(SMB_STS))) {
5815 + printk(KERN_DEBUG DRV_NAME ": Failed reset at end of transaction!"
5816 + " (0x%02x)\n", temp);
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)
5830 + case I2C_SMBUS_QUICK:
5831 + sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
5832 + size = SIS645_QUICK;
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;
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;
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);
5858 + size = (size == I2C_SMBUS_PROC_CALL ? SIS645_PROC_CALL : SIS645_WORD_DATA);
5861 + case I2C_SMBUS_BLOCK_DATA:
5863 + printk(KERN_INFO DRV_NAME ": SMBus block not implemented!\n");
5868 + printk(KERN_INFO DRV_NAME ": Unsupported I2C size\n");
5873 + if (sis645_transaction(size))
5876 + if ((size != SIS645_PROC_CALL) &&
5877 + ((read_write == I2C_SMBUS_WRITE) || (size == SIS645_QUICK)))
5882 + case SIS645_BYTE_DATA:
5883 + data->byte = sis645_read(SMB_BYTE);
5886 + case SIS645_WORD_DATA:
5887 + case SIS645_PROC_CALL:
5888 + data->word = sis645_read(SMB_BYTE) +
5889 + (sis645_read(SMB_BYTE + 1) << 8);
5895 +static u32 sis645_func(struct i2c_adapter *adapter)
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;
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,
5909 +static struct i2c_adapter sis645_adapter = {
5910 + .owner = THIS_MODULE,
5912 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS645,
5913 + .algo = &smbus_algorithm,
5916 +static struct pci_device_id sis645_ids[] __devinitdata = {
5918 + .vendor = PCI_VENDOR_ID_SI,
5919 + .device = PCI_DEVICE_ID_SI_SMBUS,
5920 + .subvendor = PCI_ANY_ID,
5921 + .subdevice = PCI_ANY_ID,
5926 +static int __devinit sis645_probe(struct pci_dev *dev,
5927 + const struct pci_device_id *id)
5932 + if (sis645_smbus_base) {
5933 + dev_err(dev, "Only one device supported.\n");
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);
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");
5949 + dev_info(dev, "SiS645 SMBus base address: 0x%04x\n",
5950 + sis645_smbus_base);
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);
5958 + sis645_smbus_base = 0;
5962 + sprintf(sis645_adapter.name, "SiS645 SMBus adapter at 0x%04x",
5963 + sis645_smbus_base);
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;
5974 +static void __devexit sis645_remove(struct pci_dev *dev)
5976 + if (sis645_smbus_base) {
5977 + i2c_del_adapter(&sis645_adapter);
5978 + release_region(sis645_smbus_base, SMB_IOSIZE);
5979 + sis645_smbus_base = 0;
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),
5990 +static int __init i2c_sis645_init(void)
5992 + printk(KERN_INFO DRV_NAME ".o version %s (%s)\n", LM_VERSION, LM_DATE);
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)) {
5997 + printk(KERN_INFO DRV_NAME ": "
5998 + "Attempting to enable SiS645 SMBus device\n");
6000 +#ifdef CONFIG_HOTPLUG
6001 + sis645_hotplug_smbus();
6003 + printk(KERN_INFO DRV_NAME ": "
6004 + "Requires kernel with CONFIG_HOTPLUG, sorry!\n");
6008 + return pci_module_init(&sis645_driver);
6011 +static void __exit i2c_sis645_exit(void)
6013 + pci_unregister_driver(&sis645_driver);
6016 +MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
6017 +MODULE_DESCRIPTION("SiS645 SMBus driver");
6018 +MODULE_LICENSE("GPL");
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
6027 + i2c-tsunami.c - Part of lm_sensors, Linux kernel modules for hardware
6029 + Copyright (c) 2001 Oleg Vdovikin <vdovikin@jscc.ru>
6031 + Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
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.
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.
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.
6049 +/* This interfaces to the I2C bus of the Tsunami/Typhoon 21272 chipsets
6050 + to gain access to the on-board I2C devices.
6052 + For more information refer to Compaq's
6053 + "Tsunami/Typhoon 21272 Chipset Hardware Reference Manual"
6054 + Order Number: DS-0025-TE
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"
6067 +MODULE_LICENSE("GPL");
6069 +/* Memory Presence Detect Register (MPD-RW) bits
6070 + with except of reserved RAZ bits */
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 */
6077 +static inline void writempd(unsigned long value)
6079 + TSUNAMI_cchip->mpd.csr = value;
6083 +static inline unsigned long readmpd(void)
6085 + return TSUNAMI_cchip->mpd.csr;
6088 +static void bit_tsunami_setscl(void *data, int val)
6090 + /* read currently setted bits to modify them */
6091 + unsigned long bits = readmpd() >> 2; /* assume output == input */
6101 +static void bit_tsunami_setsda(void *data, int val)
6103 + /* read currently setted bits to modify them */
6104 + unsigned long bits = readmpd() >> 2; /* assume output == input */
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. */
6118 +static int bit_tsunami_getscl(void *data)
6120 + return (0 != (readmpd() & MPD_CKR));
6123 +static int bit_tsunami_getsda(void *data)
6125 + return (0 != (readmpd() & MPD_DR));
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,
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,
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),
6155 +static int __init i2c_tsunami_init(void)
6157 + printk("i2c-tsunami.o version %s (%s)\n", LM_VERSION, LM_DATE);
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);
6163 + printk("i2c-tsunami.o: using Cchip MPD at 0x%lx.\n", (long) &TSUNAMI_cchip->mpd);
6165 + return i2c_bit_add_bus(&tsunami_i2c_adapter);
6169 +static void __exit i2c_tsunami_exit(void)
6171 + i2c_bit_del_bus(&tsunami_i2c_adapter);
6176 +MODULE_AUTHOR("Oleg I. Vdovikin <vdovikin@jscc.ru>");
6177 +MODULE_DESCRIPTION("Tsunami I2C/SMBus driver");
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
6185 + i2c-via.c - Part of lm_sensors, Linux kernel modules
6186 + for hardware monitoring
6188 + i2c Support for Via Technologies 82C586B South Bridge
6190 + Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
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.
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.
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.
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"
6220 +/* Power management registers */
6222 +#define PM_CFG_REVID 0x08 /* silicon revision code */
6223 +#define PM_CFG_IOBASE0 0x20
6224 +#define PM_CFG_IOBASE1 0x48
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
6232 +/* io-region reservation */
6233 +#define IOSPACE 0x06
6234 +#define IOTEXT "via-i2c"
6236 +static u16 pm_io_base = 0;
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.
6246 +static void bit_via_setscl(void *data, int state)
6248 + outb(state ? inb(I2C_DIR) & ~I2C_SCL : inb(I2C_DIR) | I2C_SCL,
6252 +static void bit_via_setsda(void *data, int state)
6254 + outb(state ? inb(I2C_DIR) & ~I2C_SDA : inb(I2C_DIR) | I2C_SDA,
6258 +static int bit_via_getscl(void *data)
6260 + return (0 != (inb(I2C_IN) & I2C_SCL));
6263 +static int bit_via_getsda(void *data)
6265 + return (0 != (inb(I2C_IN) & I2C_SDA));
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,
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,
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 },
6292 +static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
6299 + printk(KERN_ERR "i2c-via.o: Will only support one host\n");
6303 + pci_read_config_byte(dev, PM_CFG_REVID, &rev);
6307 + base = PM_CFG_IOBASE0;
6311 + base = PM_CFG_IOBASE1;
6315 + base = PM_CFG_IOBASE1;
6316 + /* later revision */
6319 + pci_read_config_word(dev, base, &pm_io_base);
6320 + pm_io_base &= (0xff << 8);
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);
6327 + outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR);
6328 + outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT);
6330 + res = i2c_bit_add_bus(&vt586b_adapter);
6332 + release_region(I2C_DIR, IOSPACE);
6339 +static void __devexit vt586b_remove(struct pci_dev *dev)
6341 + i2c_bit_del_bus(&vt586b_adapter);
6342 + release_region(I2C_DIR, IOSPACE);
6347 +/* Don't register driver to avoid driver conflicts */
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),
6357 +static int __init i2c_vt586b_init(void)
6359 + struct pci_dev *dev;
6360 + const struct pci_device_id *id;
6362 + printk("i2c-via.o version %s (%s)\n", LM_VERSION, LM_DATE);
6364 + return pci_module_init(&vt586b_driver);
6366 + pci_for_each_dev(dev) {
6367 + id = pci_match_device(vt586b_ids, dev);
6369 + if(vt586b_probe(dev, id) >= 0)
6376 +static void __exit i2c_vt586b_exit(void)
6379 + pci_unregister_driver(&vt586b_driver);
6381 + vt586b_remove(NULL);
6385 +MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
6386 +MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge");
6387 +MODULE_LICENSE("GPL");
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
6395 + i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
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>
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.
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.
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.
6417 + Supports Via devices:
6418 + 82C596A/B (0x3050)
6423 + 8233A (0x3147 and 0x3177)
6426 + Note: we assume there can only be one device, with one SMBus interface.
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>
6442 +#define SMBBA1 0x90
6443 +#define SMBBA2 0x80
6444 +#define SMBBA3 0xD0
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)
6461 +/* PCI Address Constants */
6463 +/* SMBus data in configuration space can be found in two places,
6464 + We try to select the better one*/
6466 +static unsigned short smb_cf_hstcfg = 0xD2;
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)
6474 +/* Other settings */
6475 +#define MAX_TIMEOUT 500
6476 +#define ENABLE_INT9 0
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
6486 +/* If force is set to anything different from 0, we forcibly enable the
6487 + VT596. DANGEROUS! */
6489 +MODULE_PARM(force, "i");
6490 +MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
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!");
6501 +static struct i2c_adapter vt596_adapter;
6503 +/* Another internally used function */
6504 +static int vt596_transaction(void)
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));
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);
6520 + outb_p(temp, SMBHSTSTS);
6521 + if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
6522 + dev_dbg(&vt596_adapter, "Failed! (0x%02x)\n", temp);
6526 + dev_dbg(&vt596_adapter, "Successfull!\n");
6530 + /* start the transaction by setting bit 6 */
6531 + outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
6533 + /* We will always wait for a fraction of a second!
6534 + I don't know if VIA needs this, Intel did */
6537 + temp = inb_p(SMBHSTSTS);
6538 + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
6540 + /* If the SMBus is still busy, we give up */
6541 + if (timeout >= MAX_TIMEOUT) {
6543 + dev_dbg(&vt596_adapter, "SMBus Timeout!\n");
6546 + if (temp & 0x10) {
6548 + dev_dbg(&vt596_adapter, "Error: Failed bus transaction\n");
6551 + if (temp & 0x08) {
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 */
6558 + if (temp & 0x04) {
6560 + dev_dbg(&vt596_adapter, "Error: no response!\n");
6563 + if (inb_p(SMBHSTSTS) != 0x00)
6564 + outb_p(inb(SMBHSTSTS), SMBHSTSTS);
6566 + if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
6567 + dev_dbg(&vt596_adapter, "Failed reset at end of "
6568 + "transaction (%02x)\n", temp);
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));
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)
6586 + case I2C_SMBUS_QUICK:
6587 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6589 + size = VT596_QUICK;
6591 + case I2C_SMBUS_BYTE:
6592 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6594 + if (read_write == I2C_SMBUS_WRITE)
6595 + outb_p(command, SMBHSTCMD);
6596 + size = VT596_BYTE;
6598 + case I2C_SMBUS_BYTE_DATA:
6599 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6601 + outb_p(command, SMBHSTCMD);
6602 + if (read_write == I2C_SMBUS_WRITE)
6603 + outb_p(data->byte, SMBHSTDAT0);
6604 + size = VT596_BYTE_DATA;
6606 + case I2C_SMBUS_WORD_DATA:
6607 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
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);
6614 + size = VT596_WORD_DATA;
6616 + case I2C_SMBUS_BLOCK_DATA:
6617 + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
6619 + outb_p(command, SMBHSTCMD);
6620 + if (read_write == I2C_SMBUS_WRITE) {
6621 + len = data->block[0];
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);
6631 + size = VT596_BLOCK_DATA;
6634 + dev_warn(&vt596_adapter, "Unsupported transaction %d\n", size);
6638 + outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
6640 + if (vt596_transaction()) /* Error in transaction */
6643 + if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
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
6652 + data->byte = inb_p(SMBHSTDAT0);
6654 + case VT596_BYTE_DATA:
6655 + data->byte = inb_p(SMBHSTDAT0);
6657 + case VT596_WORD_DATA:
6658 + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
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);
6672 +static u32 vt596_func(struct i2c_adapter *adapter)
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;
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,
6686 +static struct i2c_adapter vt596_adapter = {
6687 + .owner = THIS_MODULE,
6688 + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2,
6689 + .algo = &smbus_algorithm,
6693 +static int __devinit vt596_probe(struct pci_dev *pdev,
6694 + const struct pci_device_id *id)
6696 + unsigned char temp;
6697 + int error = -ENODEV;
6699 + /* Determine the address of the SMBus areas */
6701 + vt596_smba = force_addr & 0xfff0;
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;
6714 + /* no matches at all */
6715 + dev_err(pdev, "Cannot configure "
6716 + "SMBus I/O Base address\n");
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");
6730 + if (!request_region(vt596_smba, 8, "viapro-smbus")) {
6731 + dev_err(pdev, "SMBus region 0x%x already in use!\n",
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. */
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) {
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
6753 + pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
6754 + dev_info(pdev, "Enabling SMBus device\n");
6756 + dev_err(pdev, "SMBUS: Error: Host SMBus "
6757 + "controller not enabled! - upgrade BIOS or "
6759 + goto release_region;
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");
6768 + dev_dbg(pdev, "Illegal Interrupt configuration "
6769 + "(or code out of date)!\n");
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);
6775 + snprintf(vt596_adapter.name, 32,
6776 + "SMBus Via Pro adapter at %04x", vt596_smba);
6778 + return i2c_add_adapter(&vt596_adapter);
6781 + release_region(vt596_smba, 8);
6785 +static void __devexit vt596_remove(struct pci_dev *pdev)
6787 + i2c_del_adapter(&vt596_adapter);
6788 + release_region(vt596_smba, 8);
6791 +/* 8233A is undefined before kernel 2.4.19 */
6792 +#ifndef PCI_DEVICE_ID_VIA_8233A
6793 +#define PCI_DEVICE_ID_VIA_8233A 0x3147
6795 +/* 8235 is undefined before kernel 2.4.20 */
6796 +#ifndef PCI_DEVICE_ID_VIA_8235
6797 +#define PCI_DEVICE_ID_VIA_8235 0x3177
6799 +/* 8237 is undefined before kernel 2.4.21 */
6800 +#ifndef PCI_DEVICE_ID_VIA_8237
6801 +#define PCI_DEVICE_ID_VIA_8237 0x3227
6803 +static struct pci_device_id vt596_ids[] __devinitdata = {
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,
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,
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,
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
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,
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
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
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,
6863 +/* Don't register driver to avoid driver conflicts */
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),
6873 +static int __init i2c_vt596_init(void)
6875 + struct pci_dev *dev;
6876 + const struct pci_device_id *id;
6878 + printk("i2c-viapro.o version %s (%s)\n", LM_VERSION, LM_DATE);
6880 + return pci_module_init(&vt596_driver);
6882 + pci_for_each_dev(dev) {
6883 + id = pci_match_device(vt596_ids, dev);
6885 + if(vt596_probe(dev, id) >= 0)
6892 +static void __exit i2c_vt596_exit(void)
6895 + pci_unregister_driver(&vt596_driver);
6897 + vt596_remove(NULL);
6901 + "Frodo Looijaard <frodol@dds.nl> and "
6902 + "Philip Edelbrock <phil@netroedge.com>");
6903 +MODULE_DESCRIPTION("vt82c596 SMBus driver");
6904 +MODULE_LICENSE("GPL");
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
6912 + voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware
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>
6919 + Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
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.
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.
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.
6937 +/* This interfaces to the I2C bus of the Voodoo3 to gain access to
6938 + the BT869 and possibly other I2C devices. */
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"
6950 +MODULE_LICENSE("GPL");
6952 +/* the only registers we use */
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
6968 +/* initialization states */
6973 +#define CYCLE_DELAY 10
6974 +#define TIMEOUT (HZ / 2)
6977 +static void config_v3(struct pci_dev *dev);
6979 +static unsigned long ioaddr;
6981 +/* The voo GPIO registers don't have individual masks for each bit
6982 + so we always have to read before writing. */
6984 +static void bit_vooi2c_setscl(void *data, int val)
6987 + r = readl(ioaddr + REG);
6991 + r &= ~I2C_SCL_OUT;
6992 + writel(r, ioaddr + REG);
6993 + readl(ioaddr + REG); /* flush posted write */
6996 +static void bit_vooi2c_setsda(void *data, int val)
6999 + r = readl(ioaddr + REG);
7003 + r &= ~I2C_SDA_OUT;
7004 + writel(r, ioaddr + REG);
7005 + readl(ioaddr + REG); /* flush posted write */
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. */
7012 +static int bit_vooi2c_getscl(void *data)
7014 + return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
7017 +static int bit_vooi2c_getsda(void *data)
7019 + return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
7022 +static void bit_vooddc_setscl(void *data, int val)
7025 + r = readl(ioaddr + REG);
7029 + r &= ~DDC_SCL_OUT;
7030 + writel(r, ioaddr + REG);
7031 + readl(ioaddr + REG); /* flush posted write */
7034 +static void bit_vooddc_setsda(void *data, int val)
7037 + r = readl(ioaddr + REG);
7041 + r &= ~DDC_SDA_OUT;
7042 + writel(r, ioaddr + REG);
7043 + readl(ioaddr + REG); /* flush posted write */
7046 +static int bit_vooddc_getscl(void *data)
7048 + return (0 != (readl(ioaddr + REG) & DDC_SCL_IN));
7051 +static int bit_vooddc_getsda(void *data)
7053 + return (0 != (readl(ioaddr + REG) & DDC_SDA_IN));
7057 +/* Configures the chip */
7059 +void config_v3(struct pci_dev *dev)
7061 + unsigned int cadr;
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);
7068 + writel(0x8160, ioaddr + REG2);
7069 + writel(0xcffc0020, ioaddr + REG);
7070 + printk("i2c-voodoo3: Using Banshee/Voodoo3 at 0x%lx\n", ioaddr);
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
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,
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
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,
7109 +static struct pci_device_id voodoo3_ids[] __devinitdata = {
7111 + .vendor = PCI_VENDOR_ID_3DFX,
7112 + .device = PCI_DEVICE_ID_3DFX_VOODOO3,
7113 + .subvendor = PCI_ANY_ID,
7114 + .subdevice = PCI_ANY_ID,
7117 + .vendor = PCI_VENDOR_ID_3DFX,
7118 + .device = PCI_DEVICE_ID_3DFX_BANSHEE,
7119 + .subvendor = PCI_ANY_ID,
7120 + .subdevice = PCI_ANY_ID,
7125 +static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id)
7129 + printk("voodoo3: in probe\n");
7131 + retval = i2c_bit_add_bus(&voodoo3_i2c_adapter);
7134 + retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
7136 + i2c_bit_del_bus(&voodoo3_i2c_adapter);
7140 +static void __devexit voodoo3_remove(struct pci_dev *dev)
7142 + i2c_bit_del_bus(&voodoo3_i2c_adapter);
7143 + i2c_bit_del_bus(&voodoo3_ddc_adapter);
7147 +/* Don't register driver to avoid driver conflicts */
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),
7157 +static int __init i2c_voodoo3_init(void)
7159 + struct pci_dev *dev;
7160 + const struct pci_device_id *id;
7162 + printk("i2c-voodoo3.o version %s (%s)\n", LM_VERSION, LM_DATE);
7164 + return pci_module_init(&voodoo3_driver);
7166 + pci_for_each_dev(dev) {
7167 + id = pci_match_device(voodoo3_ids, dev);
7169 + if(voodoo3_probe(dev, id) >= 0)
7176 +static void __exit i2c_voodoo3_exit(void)
7179 + pci_unregister_driver(&voodoo3_driver);
7181 + voodoo3_remove(NULL);
7182 + iounmap((void *)ioaddr);
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");
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
7196 + adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
7198 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
7199 + Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
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"
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
7229 +static unsigned int normal_isa[] = { SENSORS_ISA_END };
7230 +static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
7232 +/* Insmod parameters */
7233 +SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
7235 +/* adm1021 constants specified below */
7237 +/* The adm1021 registers */
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
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
7267 +#define ADM1021_REG_ONESHOT 0x0F
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)
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))
7282 +/* Each client has this additional data */
7283 +struct adm1021_data {
7284 + struct i2c_client client;
7288 + struct semaphore update_lock;
7289 + char valid; /* !=0 if following fields are valid */
7290 + unsigned long last_updated; /* In jiffies */
7292 + u8 temp, temp_os, temp_hyst; /* Register values */
7293 + u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
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;
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,
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,
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);
7320 +/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
7321 +static int read_only = 0;
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,
7334 +/* -- SENSORS SYSCTL START -- */
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
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
7347 +/* -- SENSORS SYSCTL END -- */
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},
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},
7376 +static int adm1021_id = 0;
7378 +static int adm1021_attach_adapter(struct i2c_adapter *adapter)
7380 + return i2c_detect(adapter, &addr_data, adm1021_detect);
7383 +static int adm1021_detect(struct i2c_adapter *adapter, int address,
7384 + unsigned short flags, int kind)
7387 + struct i2c_client *new_client;
7388 + struct adm1021_data *data;
7390 + const char *type_name = "";
7391 + const char *client_name = "";
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. */
7396 + if (i2c_is_isa_adapter(adapter)) {
7398 + ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
7403 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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. */
7410 + if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
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;
7422 + /* Now, we do the remaining detection. */
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) {
7433 + /* Determine the chip type. */
7436 + i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
7438 + if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0xF0) == 0x30)
7442 + else if (i == 0x49)
7444 + else if (i == 0x23)
7446 + else if ((i == 0x4d) &&
7447 + (adm1021_read_value
7448 + (new_client, ADM1021_REG_DEV_ID) == 0x01))
7450 + else if (i == 0x54)
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)))
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";
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;
7492 + new_client->id = adm1021_id++;
7494 + init_MUTEX(&data->update_lock);
7496 + /* Tell the I2C layer a new client has arrived */
7497 + if ((err = i2c_attach_client(new_client)))
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) {
7507 + data->sysctl_id = i;
7509 + /* Initialize the ADM1021 chip */
7511 + adm1021_init_client(new_client);
7515 + i2c_detach_client(new_client);
7523 +static void adm1021_init_client(struct i2c_client *client)
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);
7532 +static int adm1021_detach_client(struct i2c_client *client)
7536 + i2c_deregister_entry(((struct adm1021_data *) (client->data))->
7539 + if ((err = i2c_detach_client(client))) {
7541 + ("adm1021.o: Client deregistration failed, client not detached.\n");
7545 + kfree(client->data);
7551 +/* All registers are byte-sized */
7552 +static int adm1021_read_value(struct i2c_client *client, u8 reg)
7554 + return i2c_smbus_read_byte_data(client, reg);
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)
7561 + struct adm1021_data *data = client->data;
7563 + i = i2c_smbus_read_byte_data(client, reg);
7565 + data->fail |= mask;
7572 +static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
7574 + if (read_only > 0)
7577 + return i2c_smbus_write_byte_data(client, reg, value);
7580 +static void adm1021_update_client(struct i2c_client *client)
7582 + struct adm1021_data *data = client->data;
7584 + down(&data->update_lock);
7586 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
7587 + (jiffies < data->last_updated) || !data->valid) {
7590 + printk("Starting adm1021 update\n");
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);
7631 + data->last_updated = jiffies;
7635 + up(&data->update_lock);
7639 +void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
7640 + int *nrels_mag, long *results)
7642 + struct adm1021_data *data = client->data;
7643 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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,
7657 + if (*nrels_mag >= 2) {
7658 + data->temp_hyst = TEMP_TO_REG(results[1]);
7659 + adm1021_write_value(client, ADM1021_REG_THYST_W,
7665 +void adm1021_remote_temp(struct i2c_client *client, int operation,
7666 + int ctl_name, int *nrels_mag, long *results)
7668 + struct adm1021_data *data = client->data;
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);
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,
7699 + results[0]=results[0]/1000;
7700 + data->remote_temp_os_prec=prec;
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);
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,
7713 + results[1]=results[1]/1000;
7714 + data->remote_temp_hyst_prec=prec;
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);
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,
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);
7738 +void adm1021_die_code(struct i2c_client *client, int operation,
7739 + int ctl_name, int *nrels_mag, long *results)
7741 + struct adm1021_data *data = client->data;
7742 + if (operation == SENSORS_PROC_REAL_INFO)
7744 + else if (operation == SENSORS_PROC_REAL_READ) {
7745 + adm1021_update_client(client);
7746 + results[0] = data->die_code;
7748 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
7749 + /* Can't write to it */
7753 +void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
7754 + int *nrels_mag, long *results)
7756 + struct adm1021_data *data = client->data;
7757 + if (operation == SENSORS_PROC_REAL_INFO)
7759 + else if (operation == SENSORS_PROC_REAL_READ) {
7760 + adm1021_update_client(client);
7761 + results[0] = data->alarms | data->fail;
7763 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
7764 + /* Can't write to it */
7768 +static int __init sm_adm1021_init(void)
7770 + printk(KERN_INFO "adm1021.o version %s (%s)\n", LM_VERSION, LM_DATE);
7771 + return i2c_add_driver(&adm1021_driver);
7774 +static void __exit sm_adm1021_exit(void)
7776 + i2c_del_driver(&adm1021_driver);
7780 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
7781 +MODULE_DESCRIPTION("adm1021 driver");
7782 +MODULE_LICENSE("GPL");
7784 +MODULE_PARM(read_only, "i");
7785 +MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
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
7793 + adm1024.c - Part of lm_sensors, Linux kernel modules for hardware
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>
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.
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.
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.
7815 +/* Supports the Analog Devices ADM1024. See doc/chips/adm1024 for details */
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"
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 };
7831 +/* Insmod parameters */
7832 +SENSORS_INSMOD_1(adm1024);
7834 +/* Many ADM1024 constants specified below */
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))
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
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
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 */
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)
7905 +static inline u8 FAN_TO_REG(long rpm, int div)
7909 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
7910 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
7914 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
7915 + (val)==255?0:1350000/((div)*(val)))
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) \
7921 +#define EXT_TEMP_FROM_REG(temp) (((temp)>0x80?(temp)-0x100:(temp))*10)
7924 +#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
7926 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
7930 +#define ALARMS_FROM_REG(val) (val)
7932 +#define DIV_FROM_REG(val) (1 << (val))
7933 +#define DIV_TO_REG(val) ((val)==1?0:((val)==8?3:((val)==4?2:1)))
7935 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
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
7942 +struct adm1024_data {
7943 + struct i2c_client client;
7947 + struct semaphore update_lock;
7948 + char valid; /* !=0 if following fields are valid */
7949 + unsigned long last_updated; /* In jiffies */
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 */
7963 + int temp2; /* Ext Temp 2 */
7966 + u16 alarms; /* Register encoding, combined */
7967 + u8 analog_out; /* Register value */
7968 + u8 vid; /* Register value combined */
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);
7978 +static int adm1024_read_value(struct i2c_client *client, u8 register);
7979 +static int adm1024_write_value(struct i2c_client *client, u8 register,
7981 +static void adm1024_update_client(struct i2c_client *client);
7982 +static void adm1024_init_client(struct i2c_client *client);
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,
8002 +static void adm1024_vid(struct i2c_client *client, int operation,
8003 + int ctl_name, int *nrels_mag, long *results);
8005 +static int adm1024_id = 0;
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,
8016 +/* The /proc/sys entries */
8017 +/* -- SENSORS SYSCTL START -- */
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
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
8048 +/* -- SENSORS SYSCTL END -- */
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},
8089 +static int adm1024_attach_adapter(struct i2c_adapter *adapter)
8091 + return i2c_detect(adapter, &addr_data, adm1024_detect);
8094 +static int adm1024_detect(struct i2c_adapter *adapter, int address,
8095 + unsigned short flags, int kind)
8098 + struct i2c_client *new_client;
8099 + struct adm1024_data *data;
8101 + const char *type_name = "";
8102 + const char *client_name = "";
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. */
8107 + if (i2c_is_isa_adapter(adapter)) {
8109 + ("adm1024.o: adm1024_detect called for an ISA bus adapter?!?\n");
8114 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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. */
8121 + if (!(data = kmalloc(sizeof(struct adm1024_data), GFP_KERNEL))) {
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;
8133 + /* Now, we do the remaining detection. */
8136 + if((adm1024_read_value(new_client, ADM1024_REG_CONFIG) & 0x80) != 0x00)
8140 + /* Determine the chip type. */
8142 + i = adm1024_read_value(new_client, ADM1024_REG_COMPANY_ID);
8148 + ("adm1024.o: Ignoring 'force' parameter for unknown chip at "
8149 + "adapter %d, address 0x%02x\n",
8150 + i2c_adapter_id(adapter), address);
8155 + if (kind == adm1024) {
8156 + type_name = "adm1024";
8157 + client_name = "ADM1024 chip";
8160 + printk("adm1024.o: Internal error: unknown kind (%d)?!?",
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;
8170 + new_client->id = adm1024_id++;
8172 + init_MUTEX(&data->update_lock);
8174 + /* Tell the I2C layer a new client has arrived */
8175 + if ((err = i2c_attach_client(new_client)))
8178 + /* Register a new directory entry with module sensors */
8179 + if ((i = i2c_register_entry(new_client,
8181 + adm1024_dir_table_template)) < 0) {
8185 + data->sysctl_id = i;
8187 + /* Initialize the ADM1024 chip */
8188 + adm1024_init_client(new_client);
8191 +/* OK, this is not exactly good programming practice, usually. But it is
8192 + very code-efficient in this case. */
8195 + i2c_detach_client(new_client);
8203 +static int adm1024_detach_client(struct i2c_client *client)
8207 + i2c_deregister_entry(((struct adm1024_data *) (client->data))->
8210 + if ((err = i2c_detach_client(client))) {
8212 + ("adm1024.o: Client deregistration failed, client not detached.\n");
8216 + kfree(client->data);
8221 +static int adm1024_read_value(struct i2c_client *client, u8 reg)
8223 + return 0xFF & i2c_smbus_read_byte_data(client, reg);
8226 +static int adm1024_write_value(struct i2c_client *client, u8 reg, u8 value)
8228 + return i2c_smbus_write_byte_data(client, reg, value);
8231 +static void adm1024_init_client(struct i2c_client *client)
8233 + /* Enable temperature channel 2 */
8234 + adm1024_write_value(client, ADM1024_REG_CHANNEL_MODE, adm1024_read_value(client, ADM1024_REG_CHANNEL_MODE) | 0x04);
8236 + /* Start monitoring */
8237 + adm1024_write_value(client, ADM1024_REG_CONFIG, 0x07);
8240 +static void adm1024_update_client(struct i2c_client *client)
8242 + struct adm1024_data *data = client->data;
8245 + down(&data->update_lock);
8248 + (jiffies - data->last_updated >
8249 + (data->type == adm1024 ? HZ / 2 : HZ * 2))
8250 + || (jiffies < data->last_updated) || !data->valid) {
8253 + printk("Starting adm1024 update\n");
8255 + for (i = 0; i <= 5; i++) {
8257 + adm1024_read_value(client, ADM1024_REG_IN(i));
8259 + adm1024_read_value(client,
8260 + ADM1024_REG_IN_MIN(i));
8262 + adm1024_read_value(client,
8263 + ADM1024_REG_IN_MAX(i));
8266 + adm1024_read_value(client, ADM1024_REG_FAN1);
8267 + data->fan_min[0] =
8268 + adm1024_read_value(client, ADM1024_REG_FAN1_MIN);
8270 + adm1024_read_value(client, ADM1024_REG_FAN2);
8271 + data->fan_min[1] =
8272 + adm1024_read_value(client, ADM1024_REG_FAN2_MIN);
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);
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);
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);
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;
8299 + (adm1024_read_value(client, ADM1024_REG_VID4) & 0x01)
8303 + adm1024_read_value(client,
8304 + ADM1024_REG_INT1_STAT) +
8305 + (adm1024_read_value(client, ADM1024_REG_INT2_STAT) <<
8307 + data->analog_out =
8308 + adm1024_read_value(client, ADM1024_REG_ANALOG_OUT);
8309 + data->last_updated = jiffies;
8313 + up(&data->update_lock);
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
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)
8334 + int scales[6] = { 250, 225, 330, 500, 1200, 270 };
8336 + struct adm1024_data *data = client->data;
8337 + int nr = ctl_name - ADM1024_SYSCTL_IN0;
8339 + if (operation == SENSORS_PROC_REAL_INFO)
8341 + else if (operation == SENSORS_PROC_REAL_READ) {
8342 + adm1024_update_client(client);
8344 + IN_FROM_REG(data->in_min[nr], nr) * scales[nr] / 192;
8346 + IN_FROM_REG(data->in_max[nr], nr) * scales[nr] / 192;
8348 + IN_FROM_REG(data->in[nr], nr) * scales[nr] / 192;
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]);
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]);
8366 +void adm1024_fan(struct i2c_client *client, int operation, int ctl_name,
8367 + int *nrels_mag, long *results)
8369 + struct adm1024_data *data = client->data;
8370 + int nr = ctl_name - ADM1024_SYSCTL_FAN1 + 1;
8372 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
8380 + FAN_FROM_REG(data->fan[nr - 1],
8381 + DIV_FROM_REG(data->fan_div[nr - 1]));
8383 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
8384 + if (*nrels_mag >= 1) {
8385 + data->fan_min[nr - 1] = FAN_TO_REG(results[0],
8390 + adm1024_write_value(client,
8392 + 1 ? ADM1024_REG_FAN1_MIN :
8393 + ADM1024_REG_FAN2_MIN,
8394 + data->fan_min[nr - 1]);
8400 +void adm1024_temp(struct i2c_client *client, int operation, int ctl_name,
8401 + int *nrels_mag, long *results)
8403 + struct adm1024_data *data = client->data;
8404 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
8426 +void adm1024_temp1(struct i2c_client *client, int operation, int ctl_name,
8427 + int *nrels_mag, long *results)
8429 + struct adm1024_data *data = client->data;
8430 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
8452 +void adm1024_temp2(struct i2c_client *client, int operation, int ctl_name,
8453 + int *nrels_mag, long *results)
8455 + struct adm1024_data *data = client->data;
8456 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
8478 +void adm1024_alarms(struct i2c_client *client, int operation, int ctl_name,
8479 + int *nrels_mag, long *results)
8481 + struct adm1024_data *data = client->data;
8482 + if (operation == SENSORS_PROC_REAL_INFO)
8484 + else if (operation == SENSORS_PROC_REAL_READ) {
8485 + adm1024_update_client(client);
8486 + results[0] = ALARMS_FROM_REG(data->alarms);
8491 +void adm1024_fan_div(struct i2c_client *client, int operation,
8492 + int ctl_name, int *nrels_mag, long *results)
8494 + struct adm1024_data *data = client->data;
8497 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
8519 +void adm1024_analog_out(struct i2c_client *client, int operation,
8520 + int ctl_name, int *nrels_mag, long *results)
8522 + struct adm1024_data *data = client->data;
8524 + if (operation == SENSORS_PROC_REAL_INFO)
8526 + else if (operation == SENSORS_PROC_REAL_READ) {
8527 + adm1024_update_client(client);
8528 + results[0] = data->analog_out;
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);
8539 +void adm1024_vid(struct i2c_client *client, int operation, int ctl_name,
8540 + int *nrels_mag, long *results)
8542 + struct adm1024_data *data = client->data;
8544 + if (operation == SENSORS_PROC_REAL_INFO)
8546 + else if (operation == SENSORS_PROC_REAL_READ) {
8547 + adm1024_update_client(client);
8548 + results[0] = VID_FROM_REG(data->vid);
8553 +static int __init sm_adm1024_init(void)
8555 + printk("adm1024.o version %s (%s)\n", LM_VERSION, LM_DATE);
8556 + return i2c_add_driver(&adm1024_driver);
8559 +static void __exit sm_adm1024_exit(void)
8561 + i2c_del_driver(&adm1024_driver);
8567 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
8568 +MODULE_DESCRIPTION("ADM1024 driver");
8570 +MODULE_LICENSE("GPL");
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
8578 + adm1025.c - Part of lm_sensors, Linux kernel modules for hardware
8580 + Copyright (c) 2000 Chen-Yuan Wu <gwu@esoft.com>
8581 + Copyright (c) 2003-2004 Jean Delvare <khali@linux-fr.org>
8583 + Based on the adm9240 driver.
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.
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.
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.
8600 +/* Supports the Analog Devices ADM1025 and the Philips NE1619.
8601 + See doc/chips/adm1025 for details */
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>
8612 +MODULE_LICENSE("GPL");
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 };
8620 +/* Insmod parameters */
8621 +SENSORS_INSMOD_2(adm1025, ne1619);
8623 +/* Many ADM1025 constants specified below */
8626 +/* The ADM1025 registers */
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
8636 +#define ADM1025_REG_RTEMP 0x26 /* not used directly, see */
8637 +#define ADM1025_REG_LTEMP 0x27 /* ADM1025_REG_TEMP(nr) below */
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 */
8643 +#define ADM1025_REG_STATUS1 0x41
8644 +#define ADM1025_REG_STATUS2 0x42
8646 +#define ADM1025_REG_VID 0x47
8647 +#define ADM1025_REG_VID4 0x49 /* actually R/W
8648 + but we don't write to it */
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
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
8669 +#define ADM1025_REG_CONFIG 0x40
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)
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)
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)
8690 +#define ALARMS_FROM_REG(val) (val)
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
8696 +struct adm1025_data {
8697 + struct i2c_client client;
8701 + struct semaphore update_lock;
8702 + char valid; /* !=0 if following fields are valid */
8703 + unsigned long last_updated; /* In jiffies */
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 */
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);
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);
8736 +static int adm1025_id = 0;
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,
8747 +/* The /proc/sys entries */
8748 +/* -- SENSORS SYSCTL START -- */
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
8757 +#define ADM1025_SYSCTL_RTEMP 1250 /* Degrees Celcius * 10 */
8758 +#define ADM1025_SYSCTL_TEMP 1251
8760 +#define ADM1025_SYSCTL_ALARMS 2001 /* bitvector */
8761 +#define ADM1025_SYSCTL_VID 2003 /* Volts * 1000 */
8762 +#define ADM1025_SYSCTL_VRM 2004
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
8774 +/* -- SENSORS SYSCTL END -- */
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},
8807 +static int adm1025_attach_adapter(struct i2c_adapter *adapter)
8809 + return i2c_detect(adapter, &addr_data, adm1025_detect);
8812 +static int adm1025_detect(struct i2c_adapter *adapter, int address,
8813 + unsigned short flags, int kind)
8816 + struct i2c_client *new_client;
8817 + struct adm1025_data *data;
8819 + const char *type_name = "";
8820 + const char *client_name = "";
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. */
8825 + if (i2c_is_isa_adapter(adapter)) {
8827 + ("adm1025.o: adm1025_detect called for an ISA bus adapter?!?\n");
8832 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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. */
8839 + if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
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;
8851 + /* Now, we do the remaining detection. */
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)
8863 + /* Determine the chip type. */
8865 + u8 man_id, chip_id;
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);
8872 + if (man_id == 0x41) { /* Analog Devices */
8873 + if ((chip_id & 0xF0) == 0x20) /* ADM1025 */
8875 + } else if (man_id == 0xA1) { /* Philips */
8876 + if (address != 0x2E
8877 + && (chip_id & 0xF0) == 0x20) /* NE1619 */
8882 + if (kind <= 0) { /* Identification failed */
8883 + printk("adm1025.o: Unsupported chip.\n");
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";
8895 + printk("adm1025.o: Internal error: unknown kind (%d)?!?",
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;
8905 + new_client->id = adm1025_id++;
8907 + init_MUTEX(&data->update_lock);
8909 + /* Tell the I2C layer a new client has arrived */
8910 + if ((err = i2c_attach_client(new_client)))
8913 + /* Register a new directory entry with module sensors */
8914 + if ((i = i2c_register_entry(new_client,
8916 + adm1025_dir_table_template)) < 0) {
8920 + data->sysctl_id = i;
8922 + /* Initialize the ADM1025 chip */
8923 + adm1025_init_client(new_client);
8926 +/* OK, this is not exactly good programming practice, usually. But it is
8927 + very code-efficient in this case. */
8930 + i2c_detach_client(new_client);
8938 +static int adm1025_detach_client(struct i2c_client *client)
8942 + i2c_deregister_entry(((struct adm1025_data *) (client->data))->
8945 + if ((err = i2c_detach_client(client))) {
8947 + ("adm1025.o: Client deregistration failed, client not detached.\n");
8951 + kfree(client->data);
8956 +/* Called when we have found a new ADM1025. */
8957 +static void adm1025_init_client(struct i2c_client *client)
8959 + struct adm1025_data *data = client->data;
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));
8975 + i2c_smbus_write_byte_data(client,
8976 + ADM1025_REG_IN_MAX(i),
8979 + for (i=0; i<2; i++) {
8980 + reg = i2c_smbus_read_byte_data(client,
8981 + ADM1025_REG_TEMP_HIGH(i));
8983 + i2c_smbus_write_byte_data(client,
8984 + ADM1025_REG_TEMP_HIGH(i),
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);
8993 +static void adm1025_update_client(struct i2c_client *client)
8995 + struct adm1025_data *data = client->data;
8998 + down(&data->update_lock);
9000 + if ((jiffies - data->last_updated > 2 * HZ)
9001 + || (jiffies < data->last_updated) || !data->valid) {
9003 + printk("Starting adm1025 update\n");
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));
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));
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);
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);
9028 + data->last_updated = jiffies;
9032 + up(&data->update_lock);
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
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)
9052 + int scales[6] = { 250, 225, 330, 500, 1200, 330 };
9054 + struct adm1025_data *data = client->data;
9055 + int nr = ctl_name - ADM1025_SYSCTL_IN0;
9057 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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)
9069 + i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(nr),
9070 + data->in_min[nr]);
9072 + if (*nrels_mag >= 2) {
9073 + data->in_max[nr] = IN_TO_REG((results[1] * 192 + scales[nr] / 2)
9075 + i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(nr),
9076 + data->in_max[nr]);
9081 +void adm1025_temp(struct i2c_client *client, int operation, int ctl_name,
9082 + int *nrels_mag, long *results)
9084 + struct adm1025_data *data = client->data;
9085 + int nr = ctl_name - ADM1025_SYSCTL_RTEMP;
9087 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
9109 +void adm1025_alarms(struct i2c_client *client, int operation, int ctl_name,
9110 + int *nrels_mag, long *results)
9112 + struct adm1025_data *data = client->data;
9114 + if (operation == SENSORS_PROC_REAL_INFO)
9116 + else if (operation == SENSORS_PROC_REAL_READ) {
9117 + adm1025_update_client(client);
9118 + results[0] = ALARMS_FROM_REG(data->alarms);
9123 +void adm1025_vid(struct i2c_client *client, int operation, int ctl_name,
9124 + int *nrels_mag, long *results)
9126 + struct adm1025_data *data = client->data;
9128 + if (operation == SENSORS_PROC_REAL_INFO)
9130 + else if (operation == SENSORS_PROC_REAL_READ) {
9131 + adm1025_update_client(client);
9132 + results[0] = vid_from_reg(data->vid, data->vrm);
9137 +void adm1025_vrm(struct i2c_client *client, int operation, int ctl_name,
9138 + int *nrels_mag, long *results)
9140 + struct adm1025_data *data = client->data;
9141 + if (operation == SENSORS_PROC_REAL_INFO)
9143 + else if (operation == SENSORS_PROC_REAL_READ) {
9144 + results[0] = data->vrm;
9146 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
9147 + if (*nrels_mag >= 1)
9148 + data->vrm = results[0];
9152 +static int __init sm_adm1025_init(void)
9154 + printk("adm1025.o version %s (%s)\n", LM_VERSION, LM_DATE);
9155 + return i2c_add_driver(&adm1025_driver);
9158 +static void __exit sm_adm1025_exit(void)
9160 + i2c_del_driver(&adm1025_driver);
9165 +MODULE_AUTHOR("Chen-Yuan Wu <gwu@esoft.com>"
9166 + " and Jean Delvare <khali@linux-fr.org>");
9167 +MODULE_DESCRIPTION("ADM1025 driver");
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
9175 + adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
9177 + Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
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.
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.
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.
9195 + 2003-03-13 Initial development
9196 + 2003-05-07 First Release. Includes GPIO fixup and full
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.
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>
9223 +#ifndef I2C_DRIVERID_ADM1026
9224 +#define I2C_DRIVERID_ADM1026 1048
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 };
9233 +/* Insmod parameters */
9234 +SENSORS_INSMOD_1(adm1026);
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");
9256 +/* Many ADM1026 constants specified below */
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)
9283 +/* There are 10 general analog inputs and 7 dedicated inputs
9285 + * 0 - 9 = AIN0 - AIN9
9287 + * 11 = 3.3V Standby
9290 + * 14 = Vccp (CPU core voltage)
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
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
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
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)])
9313 +/* Temperatures are:
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)])
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)
9336 +#define ADM1026_REG_DAC (0x04)
9337 +#define ADM1026_REG_PWM (0x05)
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 */
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
9358 +#define ADM1026_REG_MASK1 0x18
9359 +#define ADM1026_REG_MASK2 0x19
9360 +#define ADM1026_REG_MASK3 0x1a
9361 +#define ADM1026_REG_MASK4 0x1b
9363 +#define ADM1026_REG_STATUS1 0x20
9364 +#define ADM1026_REG_STATUS2 0x21
9365 +#define ADM1026_REG_STATUS3 0x22
9366 +#define ADM1026_REG_STATUS4 0x23
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.
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
9382 +/* The values in this table are based on Table II, page 15 of the
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
9390 +#define NEG12_OFFSET 16000
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.
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
9404 +#define NEG12_OFFSET 16019
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))
9413 +#define INS_FROM_REG(n,val) (SCALE(val,192,adm1026_scaling[n]))
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
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)
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)
9431 +#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
9432 +#define PWM_FROM_REG(val) (val)
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.
9438 +#define DAC_TO_REG(val) (SENSORS_LIMIT(val,0,255))
9439 +#define DAC_FROM_REG(val) (val)
9441 +/* sensors_vid.h defines vid_from_reg() */
9442 +#define VID_FROM_REG(val,vrm) (vid_from_reg(val,vrm))
9444 +#define ALARMS_FROM_REG(val) (val)
9446 +/* Unlike some other drivers we DO NOT set initial limits. Use
9447 + * the config file to set limits.
9450 +/* Typically used with systems using a v9.1 VRM spec ? */
9451 +#define ADM1026_INIT_VRM 91
9452 +#define ADM1026_INIT_VID -1
9454 +/* Chip sampling rates
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.
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*
9465 +#define ADM1026_DATA_INTERVAL (1 * HZ)
9466 +#define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ)
9468 +/* We allow for multiple chips in a single system.
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. */
9474 +struct adm1026_data {
9475 + struct i2c_client client;
9476 + struct semaphore lock;
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 */
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 */
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);
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);
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);
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,
9570 +/* Unique ID assigned to each ADM1026 detected */
9571 +static int adm1026_id = 0;
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
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 -- */
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.
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},
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},
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},
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},
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},
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},
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},
9770 +#define CTLTBL_COMMON (sizeof(adm1026_common)/sizeof(adm1026_common[0]))
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)))
9776 +#define CTLTBL_MAX (CTLTBL_COMMON)
9778 +/* This function is called when:
9779 + * the module is loaded
9780 + * a new adapter is loaded
9782 +int adm1026_attach_adapter(struct i2c_adapter *adapter)
9784 + return i2c_detect(adapter, &addr_data, adm1026_detect);
9787 +/* This function is called by i2c_detect */
9788 +int adm1026_detect(struct i2c_adapter *adapter, int address,
9789 + unsigned short flags, int kind)
9792 + int company, verstep ;
9793 + struct i2c_client *new_client;
9794 + struct adm1026_data *data;
9796 + const char *type_name = "";
9797 + struct ctl_table template[CTLTBL_MAX] ;
9798 + struct ctl_table * template_next = template ;
9800 + if (i2c_is_isa_adapter(adapter)) {
9801 + /* This chip has no ISA interface */
9805 + if (!i2c_check_functionality(adapter,
9806 + I2C_FUNC_SMBUS_BYTE_DATA)) {
9807 + /* We need to be able to do byte I/O */
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. */
9815 + if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) {
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;
9827 + /* Now, we do the remaining detection. */
9829 + company = adm1026_read_value(new_client, ADM1026_REG_COMPANY);
9830 + verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP);
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,
9840 + /* If auto-detecting, Determine the chip type. */
9843 + printk("adm1026: Autodetecting device at %d,0x%02x ...\n",
9844 + i2c_adapter_id(adapter), address );
9846 + if( company == ADM1026_COMPANY_ANALOG_DEV
9847 + && verstep == ADM1026_VERSTEP_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 );
9854 + } else if( (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC ) {
9855 + printk("adm1026: Found version/stepping 0x%02x"
9856 + " Assuming generic ADM1026.\n", verstep );
9860 + printk("adm1026: Autodetection failed\n");
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 );
9873 + /* Fill in the chip specific driver values */
9876 + type_name = "adm1026";
9877 + strcpy(new_client->name, "Generic ADM1026");
9878 + template_next = template ; /* None used */
9881 + type_name = "adm1026";
9882 + strcpy(new_client->name, "Analog Devices ADM1026");
9883 + template_next = template ;
9886 + /* Example of another adm1026 "compatible" device */
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 ;
9895 + printk("adm1026: Internal error, invalid kind (%d)!", kind);
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),
9908 + /* Housekeeping values */
9909 + data->type = kind;
9912 + /* Set the VRM version */
9913 + data->vrm = ADM1026_INIT_VRM ;
9914 + data->vid = ADM1026_INIT_VID ;
9916 + init_MUTEX(&data->update_lock);
9918 + /* Initialize the ADM1026 chip */
9919 + adm1026_init_client(new_client);
9921 + /* Tell the I2C layer a new client has arrived */
9922 + if ((err = i2c_attach_client(new_client)))
9925 + /* Finish out the template */
9926 + memcpy(template_next, adm1026_common, sizeof(adm1026_common));
9928 + /* Register a new directory entry with module sensors */
9929 + if ((i = i2c_register_entry(new_client,
9935 + data->sysctl_id = i;
9939 + /* Error out and cleanup code */
9941 + i2c_detach_client(new_client);
9948 +int adm1026_detach_client(struct i2c_client *client)
9954 + i2c_deregister_entry(((struct adm1026_data *)(client->data))->sysctl_id);
9956 + if ((err = i2c_detach_client(client))) {
9957 + printk("adm1026(%d): Client deregistration failed,"
9958 + " client not detached.\n", id );
9962 + kfree(client->data);
9967 +int adm1026_read_value(struct i2c_client *client, u8 reg)
9971 + if( reg < 0x80 ) {
9972 + /* "RAM" locations */
9973 + res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
9975 + /* EEPROM, do nothing */
9982 +int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
9986 + if( reg < 0x80 ) {
9987 + /* "RAM" locations */
9988 + res = i2c_smbus_write_byte_data(client, reg, value);
9990 + /* EEPROM, do nothing */
9997 +/* Called when we have found a new ADM1026. */
9998 +void adm1026_init_client(struct i2c_client *client)
10002 + struct adm1026_data *data = client->data;
10005 + printk("adm1026(%d): Initializing device\n", client->id);
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);
10013 + /* Inform user of chip config */
10015 + printk("adm1026(%d): ADM1026_REG_CONFIG1 is: 0x%02x\n",
10016 + client->id, data->config1 );
10018 + if( (data->config1 & CFG1_MONITOR) == 0 ) {
10019 + printk("adm1026(%d): Monitoring not currently enabled.\n",
10022 + if( data->config1 & CFG1_INT_ENABLE ) {
10023 + printk("adm1026(%d): SMBALERT interrupts are enabled.\n",
10026 + if( data->config1 & CFG1_AIN8_9 ) {
10027 + printk("adm1026(%d): in8 and in9 enabled. temp3 disabled.\n",
10030 + printk("adm1026(%d): temp3 enabled. in8 and in9 disabled.\n",
10033 + if( data->config1 & CFG1_THERM_HOT ) {
10034 + printk("adm1026(%d): Automatic THERM, PWM, and temp limits enabled.\n",
10038 + value = data->config3 ;
10039 + if( data->config3 & CFG3_GPIO16_ENABLE ) {
10040 + printk("adm1026(%d): GPIO16 enabled. THERM pin disabled.\n",
10043 + printk("adm1026(%d): THERM pin enabled. GPIO16 disabled.\n",
10046 + if( data->config3 & CFG3_VREF_250 ) {
10047 + printk("adm1026(%d): Vref is 2.50 Volts.\n", client->id );
10049 + printk("adm1026(%d): Vref is 1.82 Volts.\n", client->id );
10052 + /* Read and pick apart the existing GPIO configuration */
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 );
10059 + data->gpio_config[i] = value & 0x03 ;
10062 + data->gpio_config[16] = (data->config3 >> 6) & 0x03 ;
10064 + /* ... and then print it */
10065 + adm1026_print_gpio(client);
10067 + /* If the user asks us to reprogram the GPIO config, then
10068 + * do it now. But only if this is the first ADM1026.
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);
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.
10084 + /* Start monitoring */
10085 + value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
10087 + /* Set MONITOR, clear interrupt acknowledge and s/w reset */
10088 + value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET) ;
10090 + printk("adm1026(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
10092 + data->config1 = value ;
10093 + adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
10097 +void adm1026_print_gpio(struct i2c_client *client)
10099 + struct adm1026_data *data = client->data;
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",
10111 + printk( " FAN%d", i );
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",
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" );
10126 + /* GPIO16 is THERM */
10127 + printk( " THERM\n" );
10131 +void adm1026_fixup_gpio(struct i2c_client *client)
10133 + struct adm1026_data *data = client->data;
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
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 ;
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] ;
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 ;
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] ;
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 ;
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 ;
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] );
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 ) {
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,
10202 + /* Print the new config */
10203 + adm1026_print_gpio(client);
10206 +void adm1026_update_client(struct i2c_client *client)
10208 + struct adm1026_data *data = client->data;
10210 + long value, alarms, gpio ;
10212 + down(&data->update_lock);
10215 + || (jiffies - data->last_reading > ADM1026_DATA_INTERVAL )) {
10216 + /* Things that change quickly */
10219 + printk("adm1026(%d): Reading sensor values\n", client->id);
10221 + for (i = 0 ; i <= 16 ; ++i) {
10223 + adm1026_read_value(client, ADM1026_REG_IN(i));
10226 + for (i = 0 ; i <= 7 ; ++i) {
10228 + adm1026_read_value(client, ADM1026_REG_FAN(i));
10231 + for (i = 0 ; i <= 2 ; ++i) {
10232 + /* NOTE: temp[] is s8 and we assume 2's complement
10233 + * "conversion" in the assignment */
10235 + adm1026_read_value(client, ADM1026_REG_TEMP(i));
10238 + data->pwm = adm1026_read_value(client, ADM1026_REG_PWM);
10239 + data->analog_out = adm1026_read_value(client, ADM1026_REG_DAC);
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 */
10246 + alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
10248 + alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
10250 + alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
10251 + data->alarms = alarms ;
10253 + /* Read the GPIO values */
10254 + gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_8_15);
10256 + gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_0_7);
10257 + data->gpio = gpio ;
10259 + data->last_reading = jiffies ;
10260 + }; /* last_reading */
10263 + || (jiffies - data->last_config > ADM1026_CONFIG_INTERVAL) ) {
10264 + /* Things that don't change often */
10267 + printk("adm1026(%d): Reading config values\n", client->id);
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));
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);
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));
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);
10306 + alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
10308 + alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
10309 + data->alarm_mask = alarms ;
10311 + /* Read the GPIO values */
10312 + gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_8_15);
10314 + gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
10315 + data->gpio_mask = gpio ;
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 ;
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 );
10328 + data->gpio_config[i] = value & 0x03 ;
10332 + data->last_config = jiffies;
10333 + }; /* last_config */
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.
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",
10346 + data->vid = (data->gpio >> 11) & 0x1f ;
10351 + up(&data->update_lock);
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
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.
10367 +void adm1026_in(struct i2c_client *client, int operation, int ctl_name,
10368 + int *nrels_mag, long *results)
10370 + struct adm1026_data *data = client->data;
10371 + int nr = ctl_name - ADM1026_SYSCTL_IN0;
10373 + /* We handle in0 - in15 here. in16 (-12V) is handled below */
10374 + if (nr < 0 || nr > 15)
10375 + return ; /* ERROR */
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]);
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]);
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]);
10397 + up(&data->update_lock);
10401 +void adm1026_in16(struct i2c_client *client, int operation, int ctl_name,
10402 + int *nrels_mag, long *results)
10404 + struct adm1026_data *data = client->data;
10405 + int nr = ctl_name - ADM1026_SYSCTL_IN0;
10407 + /* We handle in16 (-12V) here */
10409 + return ; /* ERROR */
10411 + /* Apply offset and swap min/max so that min is 90% of
10412 + * target and max is 110% of target.
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 ;
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]);
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]);
10435 + up(&data->update_lock);
10439 +void adm1026_fan(struct i2c_client *client, int operation, int ctl_name,
10440 + int *nrels_mag, long *results)
10442 + struct adm1026_data *data = client->data;
10443 + int nr = ctl_name - ADM1026_SYSCTL_FAN0 ;
10445 + if (nr < 0 || nr > 7)
10446 + return ; /* ERROR */
10448 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
10463 + up(&data->update_lock);
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)
10470 + struct adm1026_data *data = client->data;
10471 + int new_div = data->fan_div[fan] ;
10474 + /* 0 and 0xff are special. Don't adjust them */
10475 + if( data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff ) {
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);
10485 +void adm1026_fan_div(struct i2c_client *client, int operation, int ctl_name,
10486 + int *nrels_mag, long *results)
10488 + struct adm1026_data *data = client->data;
10490 + int value, div, old ;
10492 + if (ctl_name != ADM1026_SYSCTL_FAN_DIV)
10493 + return ; /* ERROR */
10495 + if (operation == SENSORS_PROC_REAL_INFO)
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] ;
10503 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
10504 + down(&data->update_lock);
10506 + for( i = 7 ; i >= 0 ; --i ) {
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);
10516 + div = DIV_TO_REG(data->fan_div[i]) ;
10520 + adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
10522 + adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
10523 + (value >> 8) & 0xff);
10524 + up(&data->update_lock);
10528 +void adm1026_temp(struct i2c_client *client, int operation, int ctl_name,
10529 + int *nrels_mag, long *results)
10531 + struct adm1026_data *data = client->data;
10532 + int nr = ctl_name - ADM1026_SYSCTL_TEMP1 ;
10534 + if (nr < 0 || nr > 2)
10535 + return ; /* ERROR */
10537 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
10557 + up(&data->update_lock);
10561 +void adm1026_temp_offset(struct i2c_client *client, int operation, int ctl_name,
10562 + int *nrels_mag, long *results)
10564 + struct adm1026_data *data = client->data;
10565 + int nr = ctl_name - ADM1026_SYSCTL_TEMP_OFFSET1 ;
10567 + if (nr < 0 || nr > 2)
10568 + return ; /* ERROR */
10570 + if (operation == SENSORS_PROC_REAL_INFO)
10572 + else if (operation == SENSORS_PROC_REAL_READ) {
10573 + adm1026_update_client(client);
10574 + results[0] = TEMP_FROM_REG(data->temp_offset[nr]);
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]);
10583 + up(&data->update_lock);
10587 +void adm1026_temp_tmin(struct i2c_client *client, int operation, int ctl_name,
10588 + int *nrels_mag, long *results)
10590 + struct adm1026_data *data = client->data;
10591 + int nr = ctl_name - ADM1026_SYSCTL_TEMP_TMIN1 ;
10593 + if (nr < 0 || nr > 2)
10594 + return ; /* ERROR */
10596 + if (operation == SENSORS_PROC_REAL_INFO)
10598 + else if (operation == SENSORS_PROC_REAL_READ) {
10599 + adm1026_update_client(client);
10600 + results[0] = TEMP_FROM_REG(data->temp_tmin[nr]);
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]);
10609 + up(&data->update_lock);
10613 +void adm1026_temp_therm(struct i2c_client *client, int operation, int ctl_name,
10614 + int *nrels_mag, long *results)
10616 + struct adm1026_data *data = client->data;
10617 + int nr = ctl_name - ADM1026_SYSCTL_TEMP_THERM1 ;
10619 + if (nr < 0 || nr > 2)
10620 + return ; /* ERROR */
10622 + if (operation == SENSORS_PROC_REAL_INFO)
10624 + else if (operation == SENSORS_PROC_REAL_READ) {
10625 + adm1026_update_client(client);
10626 + results[0] = TEMP_FROM_REG(data->temp_therm[nr]);
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]);
10635 + up(&data->update_lock);
10639 +void adm1026_pwm(struct i2c_client *client, int operation, int ctl_name,
10640 + int *nrels_mag, long *results)
10642 + struct adm1026_data *data = client->data;
10644 + if (ctl_name != ADM1026_SYSCTL_PWM)
10645 + return ; /* ERROR */
10647 + if (operation == SENSORS_PROC_REAL_INFO)
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 */
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,
10662 + up(&data->update_lock);
10666 +void adm1026_analog_out(struct i2c_client *client, int operation, int ctl_name,
10667 + int *nrels_mag, long *results)
10669 + struct adm1026_data *data = client->data;
10671 + if (ctl_name != ADM1026_SYSCTL_ANALOG_OUT)
10672 + return ; /* ERROR */
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);
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);
10687 + up(&data->update_lock);
10691 +void adm1026_afc(struct i2c_client *client, int operation, int ctl_name,
10692 + int *nrels_mag, long *results)
10694 + struct adm1026_data *data = client->data;
10696 + if (ctl_name != ADM1026_SYSCTL_AFC)
10697 + return ; /* ERROR */
10699 + /* PWM auto fan control, DAC auto fan control */
10701 + if (operation == SENSORS_PROC_REAL_INFO)
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 ;
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) ;
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,
10720 + up(&data->update_lock);
10724 +void adm1026_vid(struct i2c_client *client, int operation, int ctl_name,
10725 + int *nrels_mag, long *results)
10727 + struct adm1026_data *data = client->data;
10729 + if( ctl_name != ADM1026_SYSCTL_VID )
10730 + return ; /* ERROR */
10732 + if (operation == SENSORS_PROC_REAL_INFO)
10734 + else if (operation == SENSORS_PROC_REAL_READ) {
10735 + adm1026_update_client(client);
10736 + results[0] = VID_FROM_REG((data->vid)&0x3f,data->vrm);
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 ;
10745 + data->vid = ADM1026_INIT_VID ;
10748 + up(&data->update_lock);
10753 +void adm1026_vrm(struct i2c_client *client, int operation, int ctl_name,
10754 + int *nrels_mag, long *results)
10756 + struct adm1026_data *data = client->data;
10758 + if( ctl_name != ADM1026_SYSCTL_VRM )
10759 + return ; /* ERROR */
10761 + if (operation == SENSORS_PROC_REAL_INFO)
10763 + else if (operation == SENSORS_PROC_REAL_READ) {
10764 + results[0] = data->vrm ;
10766 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
10767 + if (*nrels_mag > 0) {
10768 + data->vrm = results[0] ;
10773 +void adm1026_alarms(struct i2c_client *client, int operation, int ctl_name,
10774 + int *nrels_mag, long *results)
10776 + struct adm1026_data *data = client->data;
10778 + if( ctl_name != ADM1026_SYSCTL_ALARMS )
10779 + return ; /* ERROR */
10781 + if (operation == SENSORS_PROC_REAL_INFO)
10783 + else if (operation == SENSORS_PROC_REAL_READ) {
10784 + adm1026_update_client(client);
10785 + results[0] = data->alarms ;
10788 + /* FIXME: Perhaps we should implement a write function
10789 + * to clear an alarm?
10793 +void adm1026_alarm_mask(struct i2c_client *client, int operation,
10794 + int ctl_name, int *nrels_mag, long *results)
10796 + struct adm1026_data *data = client->data;
10797 + unsigned long mask ;
10799 + if( ctl_name != ADM1026_SYSCTL_ALARM_MASK )
10800 + return ; /* ERROR */
10802 + if (operation == SENSORS_PROC_REAL_INFO)
10804 + else if (operation == SENSORS_PROC_REAL_READ) {
10805 + adm1026_update_client(client);
10806 + results[0] = data->alarm_mask ;
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,
10817 + adm1026_write_value(client, ADM1026_REG_MASK2,
10820 + adm1026_write_value(client, ADM1026_REG_MASK3,
10823 + adm1026_write_value(client, ADM1026_REG_MASK4,
10826 + up(&data->update_lock);
10830 +void adm1026_gpio(struct i2c_client *client, int operation, int ctl_name,
10831 + int *nrels_mag, long *results)
10833 + struct adm1026_data *data = client->data;
10836 + if( ctl_name != ADM1026_SYSCTL_GPIO )
10837 + return ; /* ERROR */
10839 + if (operation == SENSORS_PROC_REAL_INFO)
10841 + else if (operation == SENSORS_PROC_REAL_READ) {
10842 + adm1026_update_client(client);
10843 + results[0] = data->gpio ;
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,
10854 + adm1026_write_value(client,
10855 + ADM1026_REG_GPIO_STATUS_8_15,
10857 + gpio = ((gpio >> 1) & 0x80)
10858 + | (data->alarms >> 24 & 0x7f);
10859 + adm1026_write_value(client,
10860 + ADM1026_REG_STATUS4,
10863 + up(&data->update_lock);
10867 +void adm1026_gpio_mask(struct i2c_client *client, int operation,
10868 + int ctl_name, int *nrels_mag, long *results)
10870 + struct adm1026_data *data = client->data;
10873 + if( ctl_name != ADM1026_SYSCTL_GPIO_MASK )
10874 + return ; /* ERROR */
10876 + if (operation == SENSORS_PROC_REAL_INFO)
10878 + else if (operation == SENSORS_PROC_REAL_READ) {
10879 + adm1026_update_client(client);
10880 + results[0] = data->gpio_mask ;
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,
10890 + adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,
10892 + mask = ((mask >> 1) & 0x80)
10893 + | (data->alarm_mask >> 24 & 0x7f);
10894 + adm1026_write_value(client, ADM1026_REG_MASK1,
10897 + up(&data->update_lock);
10901 +static int __init sm_adm1026_init(void)
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);
10908 +static void __exit sm_adm1026_exit(void)
10910 + i2c_del_driver(&adm1026_driver);
10913 +MODULE_LICENSE("GPL");
10914 +MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com");
10915 +MODULE_DESCRIPTION("ADM1026 driver");
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
10923 + adm9240.c - Part of lm_sensors, Linux kernel modules for hardware
10925 + Copyright (C) 1999 Frodo Looijaard <frodol@dds.nl>
10926 + and Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
10943 +/* Supports ADM9240, DS1780, and LM81. See doc/chips/adm9240 for details */
10946 + A couple notes about the ADM9240:
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)
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...)
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.
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).
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"
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 };
10985 +/* Insmod parameters */
10986 +SENSORS_INSMOD_3(adm9240, ds1780, lm81);
10988 +/* Many ADM9240 constants specified below */
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))
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
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
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 */
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)
11052 +static inline u8 FAN_TO_REG(long rpm, int div)
11056 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
11057 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
11061 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
11062 + (val)==255?0:1350000/((div)*(val)))
11064 +#define TEMP_FROM_REG(temp) ((temp)<256 ? (temp) * 5 : \
11065 + ((temp) - 512) * 5)
11067 +#define TEMP_LIMIT_FROM_REG(val) (((val)>=0x80?(val)-0x100:(val))*10)
11069 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10)+256:\
11073 +#define ALARMS_FROM_REG(val) (val)
11075 +#define DIV_FROM_REG(val) (1 << (val))
11076 +#define DIV_TO_REG(val) ((val)==1?0:((val)==8?3:((val)==4?2:1)))
11078 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
11081 +/* For each registered ADM9240, we need to keep some data in memory. */
11082 +struct adm9240_data {
11083 + struct i2c_client client;
11087 + struct semaphore update_lock;
11088 + char valid; /* !=0 if following fields are valid */
11089 + unsigned long last_updated; /* In jiffies */
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 */
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);
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);
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,
11130 +static void adm9240_vid(struct i2c_client *client, int operation,
11131 + int ctl_name, int *nrels_mag, long *results);
11133 +static int adm9240_id = 0;
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,
11144 +/* The /proc/sys entries */
11146 +/* -- SENSORS SYSCTL START -- */
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
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
11173 +/* -- SENSORS SYSCTL END -- */
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},
11210 +static int adm9240_attach_adapter(struct i2c_adapter *adapter)
11212 + return i2c_detect(adapter, &addr_data, adm9240_detect);
11215 +static int adm9240_detect(struct i2c_adapter *adapter, int address,
11216 + unsigned short flags, int kind)
11219 + struct i2c_client *new_client;
11220 + struct adm9240_data *data;
11222 + const char *type_name = "";
11223 + const char *client_name = "";
11225 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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. */
11232 + if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
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;
11245 + /* Now, we do the remaining detection. */
11249 + ((adm9240_read_value
11250 + (new_client, ADM9240_REG_CONFIG) & 0x80) != 0x00)
11252 + (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
11257 + /* Determine the chip type. */
11259 + i = adm9240_read_value(new_client, ADM9240_REG_COMPANY_ID);
11262 + else if (i == 0xda)
11264 + else if (i == 0x01)
11269 + ("adm9240.o: Ignoring 'force' parameter for unknown chip at "
11270 + "adapter %d, address 0x%02x\n",
11271 + i2c_adapter_id(adapter), address);
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";
11287 + printk("adm9240.o: Internal error: unknown kind (%d)?!?",
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;
11297 + new_client->id = adm9240_id++;
11299 + init_MUTEX(&data->update_lock);
11301 + /* Tell the I2C layer a new client has arrived */
11302 + if ((err = i2c_attach_client(new_client)))
11305 + /* Register a new directory entry with module sensors */
11306 + if ((i = i2c_register_entry(new_client,
11308 + adm9240_dir_table_template)) < 0) {
11312 + data->sysctl_id = i;
11314 + /* Initialize the ADM9240 chip */
11315 + adm9240_init_client(new_client);
11318 +/* OK, this is not exactly good programming practice, usually. But it is
11319 + very code-efficient in this case. */
11322 + i2c_detach_client(new_client);
11330 +static int adm9240_detach_client(struct i2c_client *client)
11334 + i2c_deregister_entry(((struct adm9240_data *) (client->data))->
11337 + if ((err = i2c_detach_client(client))) {
11339 + ("adm9240.o: Client deregistration failed, client not detached.\n");
11343 + kfree(client->data);
11349 +static int adm9240_read_value(struct i2c_client *client, u8 reg)
11351 + return i2c_smbus_read_byte_data(client, reg);
11354 +static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
11356 + return i2c_smbus_write_byte_data(client, reg, value);
11359 +/* Called when we have found a new ADM9240. */
11360 +static void adm9240_init_client(struct i2c_client *client)
11362 + /* Start monitoring */
11363 + adm9240_write_value(client, ADM9240_REG_CONFIG, 0x01);
11366 +static void adm9240_update_client(struct i2c_client *client)
11368 + struct adm9240_data *data = client->data;
11371 + down(&data->update_lock);
11374 + (jiffies - data->last_updated >
11375 + (data->type == adm9240 ? HZ / 2 : HZ * 2))
11376 + || (jiffies < data->last_updated) || !data->valid) {
11379 + printk("Starting adm9240 update\n");
11381 + for (i = 0; i <= 5; 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));
11392 + adm9240_read_value(client, ADM9240_REG_FAN1);
11393 + data->fan_min[0] =
11394 + adm9240_read_value(client, ADM9240_REG_FAN1_MIN);
11396 + adm9240_read_value(client, ADM9240_REG_FAN2);
11397 + data->fan_min[1] =
11398 + adm9240_read_value(client, ADM9240_REG_FAN2_MIN);
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);
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;
11413 + (adm9240_read_value(client, ADM9240_REG_VID4) & 0x01)
11417 + adm9240_read_value(client,
11418 + ADM9240_REG_INT1_STAT) +
11419 + (adm9240_read_value(client, ADM9240_REG_INT2_STAT) <<
11421 + data->analog_out =
11422 + adm9240_read_value(client, ADM9240_REG_ANALOG_OUT);
11423 + data->last_updated = jiffies;
11427 + up(&data->update_lock);
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)
11448 + int scales[6] = { 250, 270, 330, 500, 1200, 270 };
11450 + struct adm9240_data *data = client->data;
11451 + int nr = ctl_name - ADM9240_SYSCTL_IN0;
11453 + if (operation == SENSORS_PROC_REAL_INFO)
11455 + else if (operation == SENSORS_PROC_REAL_READ) {
11456 + adm9240_update_client(client);
11458 + IN_FROM_REG(data->in_min[nr], nr) * scales[nr] / 192;
11460 + IN_FROM_REG(data->in_max[nr], nr) * scales[nr] / 192;
11462 + IN_FROM_REG(data->in[nr], nr) * scales[nr] / 192;
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]);
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]);
11480 +void adm9240_fan(struct i2c_client *client, int operation, int ctl_name,
11481 + int *nrels_mag, long *results)
11483 + struct adm9240_data *data = client->data;
11484 + int nr = ctl_name - ADM9240_SYSCTL_FAN1 + 1;
11486 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
11494 + FAN_FROM_REG(data->fan[nr - 1],
11495 + DIV_FROM_REG(data->fan_div[nr - 1]));
11497 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
11498 + if (*nrels_mag >= 1) {
11499 + data->fan_min[nr - 1] = FAN_TO_REG(results[0],
11504 + adm9240_write_value(client,
11506 + 1 ? ADM9240_REG_FAN1_MIN :
11507 + ADM9240_REG_FAN2_MIN,
11508 + data->fan_min[nr - 1]);
11514 +void adm9240_temp(struct i2c_client *client, int operation, int ctl_name,
11515 + int *nrels_mag, long *results)
11517 + struct adm9240_data *data = client->data;
11518 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
11540 +void adm9240_alarms(struct i2c_client *client, int operation, int ctl_name,
11541 + int *nrels_mag, long *results)
11543 + struct adm9240_data *data = client->data;
11544 + if (operation == SENSORS_PROC_REAL_INFO)
11546 + else if (operation == SENSORS_PROC_REAL_READ) {
11547 + adm9240_update_client(client);
11548 + results[0] = ALARMS_FROM_REG(data->alarms);
11553 +void adm9240_fan_div(struct i2c_client *client, int operation,
11554 + int ctl_name, int *nrels_mag, long *results)
11556 + struct adm9240_data *data = client->data;
11559 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
11581 +void adm9240_analog_out(struct i2c_client *client, int operation,
11582 + int ctl_name, int *nrels_mag, long *results)
11584 + struct adm9240_data *data = client->data;
11586 + if (operation == SENSORS_PROC_REAL_INFO)
11588 + else if (operation == SENSORS_PROC_REAL_READ) {
11589 + adm9240_update_client(client);
11590 + results[0] = data->analog_out;
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);
11601 +void adm9240_vid(struct i2c_client *client, int operation, int ctl_name,
11602 + int *nrels_mag, long *results)
11604 + struct adm9240_data *data = client->data;
11606 + if (operation == SENSORS_PROC_REAL_INFO)
11608 + else if (operation == SENSORS_PROC_REAL_READ) {
11609 + adm9240_update_client(client);
11610 + results[0] = VID_FROM_REG(data->vid);
11615 +static int __init sm_adm9240_init(void)
11617 + printk("adm9240.o version %s (%s)\n", LM_VERSION, LM_DATE);
11618 + return i2c_add_driver(&adm9240_driver);
11621 +static void __exit sm_adm9240_exit(void)
11623 + i2c_del_driver(&adm9240_driver);
11629 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
11630 +MODULE_LICENSE("GPL");
11631 +MODULE_DESCRIPTION("ADM9240 driver");
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
11639 + asb100.c - Part of lm_sensors, Linux kernel modules for hardware
11642 + Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
11644 + (derived from w83781d.c)
11646 + Copyright (c) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>,
11647 + Philip Edelbrock <phil@netroedge.com>, and
11648 + Mark Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
11666 + This driver supports the hardware sensor chips: Asus ASB100 and
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.
11672 + Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
11673 + asb100 7 3 1 4 0x31 0x0694 yes no
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>
11688 +#ifndef I2C_DRIVERID_ASB100
11689 +#define I2C_DRIVERID_ASB100 1043
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 };
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 };
11700 +/* default VRM to 9.0 instead of 8.2 */
11701 +#define ASB100_DEFAULT_VRM 90
11703 +/* Insmod parameters */
11704 +SENSORS_INSMOD_1(asb100);
11705 +SENSORS_MODULE_PARM(force_subclients, "List of subclient addresses: " \
11706 + "{bus, clientaddr, subclientaddr1, subclientaddr2}");
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))
11713 +/* FAN IN registers 1-3 */
11714 +#define ASB100_REG_FAN(nr) (0x27 + (nr))
11715 +#define ASB100_REG_FAN_MIN(nr) (0x3a + (nr))
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};
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])
11726 +#define ASB100_REG_TEMP2_CONFIG 0x0152
11727 +#define ASB100_REG_TEMP3_CONFIG 0x0252
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
11744 +#define ASB100_REG_WCHIPID 0x58
11746 +/* bit 7 -> enable, bits 0-3 -> duty cycle */
11747 +#define ASB100_REG_PWM1 0x59
11750 + Rounding and limit checking is only done on the TO_REG variants. */
11752 +/* These constants are a guess, consistent w/ w83781d */
11753 +#define ASB100_IN_MIN ( 0)
11754 +#define ASB100_IN_MAX (408)
11756 +/* IN: 1/100 V (0V to 4.08V)
11758 +static u8 IN_TO_REG(unsigned val)
11760 + unsigned nval = SENSORS_LIMIT(val, ASB100_IN_MIN, ASB100_IN_MAX);
11761 + return (nval * 10 + 8) / 16;
11764 +static unsigned IN_FROM_REG(u8 reg)
11766 + return (reg * 16 + 5) / 10;
11769 +static u8 FAN_TO_REG(long rpm, int div)
11773 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
11774 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
11777 +static int FAN_FROM_REG(u8 val, int div)
11779 + return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
11782 +/* These constants are a guess, consistent w/ w83781d */
11783 +#define ASB100_TEMP_MIN (-1280)
11784 +#define ASB100_TEMP_MAX ( 1270)
11786 +/* TEMP: 1/10 degrees C (-128C to +127C)
11787 + REG: 1C/bit, two's complement */
11788 +static u8 TEMP_TO_REG(int temp)
11790 + int ntemp = SENSORS_LIMIT(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX);
11791 + ntemp += (ntemp<0 ? -5 : 5);
11792 + return (u8)(ntemp / 10);
11795 +static int TEMP_FROM_REG(u8 reg)
11797 + return (s8)reg * 10;
11800 +/* PWM: 0 - 255 per sensors documentation
11801 + REG: (6.25% duty cycle per bit) */
11802 +static u8 ASB100_PWM_TO_REG(int pwm)
11804 + pwm = SENSORS_LIMIT(pwm, 0, 255);
11805 + return (u8)(pwm / 16);
11808 +static int ASB100_PWM_FROM_REG(u8 reg)
11813 +#define ALARMS_FROM_REG(val) (val)
11815 +#define DIV_FROM_REG(val) (1 << (val))
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)
11821 + return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
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;
11833 + struct semaphore update_lock;
11834 + unsigned long last_updated; /* In jiffies */
11836 + /* array of 2 pointers to subclients */
11837 + struct i2c_client *lm75[2];
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 */
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);
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);
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);
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,
11893 +/* The /proc/sys entries */
11894 +/* -- SENSORS SYSCTL START -- */
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
11904 +#define ASB100_SYSCTL_FAN1 1101 /* Rotations/min */
11905 +#define ASB100_SYSCTL_FAN2 1102
11906 +#define ASB100_SYSCTL_FAN3 1103
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
11913 +#define ASB100_SYSCTL_VID 1300 /* Volts * 1000 */
11914 +#define ASB100_SYSCTL_VRM 1301
11916 +#define ASB100_SYSCTL_PWM1 1401 /* 0-255 => 0-100% duty cycle */
11918 +#define ASB100_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
11919 +#define ASB100_SYSCTL_ALARMS 2001 /* bitvector */
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
11936 +#define ASB100_ALARM_IN7 0x10000 /* ? */
11937 +#define ASB100_ALARM_IN8 0x20000 /* ? */
11939 +/* -- SENSORS SYSCTL END -- */
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. */
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),
11964 + ASB100_SYSCTL_FAN(1),
11965 + ASB100_SYSCTL_FAN(2),
11966 + ASB100_SYSCTL_FAN(3),
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),
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},
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)
11991 +static int asb100_attach_adapter(struct i2c_adapter *adapter)
11993 + return i2c_detect(adapter, &addr_data, asb100_detect);
11996 +static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
11997 + int kind, struct i2c_client *new_client)
12000 + struct asb100_data *data = new_client->data;
12002 + data->lm75[0] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
12003 + if (!(data->lm75[0])) {
12007 + memset(data->lm75[0], 0x00, sizeof(struct i2c_client));
12009 + data->lm75[1] = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
12010 + if (!(data->lm75[1])) {
12014 + memset(data->lm75[1], 0x00, sizeof(struct i2c_client));
12016 + id = i2c_adapter_id(adapter);
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]);
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];
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);
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);
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");
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);
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);
12069 +/* Undo inits in case of errors */
12071 + i2c_detach_client(data->lm75[0]);
12073 + kfree(data->lm75[1]);
12075 + kfree(data->lm75[0]);
12080 +static int asb100_detect(struct i2c_adapter *adapter, int address,
12081 + unsigned short flags, int kind)
12084 + struct i2c_client *new_client;
12085 + struct asb100_data *data;
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");
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");
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. */
12106 + if (!(data = kmalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
12107 + pr_debug("asb100.o: detect failed, kmalloc failed!\n");
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;
12120 + /* Now, we do the remaining detection. */
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
12128 + int val1 = asb100_read_value(new_client, ASB100_REG_BANK);
12129 + int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN);
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);
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);
12150 + /* Determine the chip type. */
12152 + int val1 = asb100_read_value(new_client, ASB100_REG_WCHIPID);
12153 + int val2 = asb100_read_value(new_client, ASB100_REG_CHIPMAN);
12155 + if ((val1 == 0x31) && (val2 == 0x06))
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);
12168 + /* Fill in remaining client fields and put it into the global list */
12169 + strcpy(new_client->name, "ASB100 chip");
12170 + data->type = kind;
12173 + init_MUTEX(&data->update_lock);
12175 + /* Tell the I2C layer a new client has arrived */
12176 + if ((err = i2c_attach_client(new_client)))
12179 + /* Attach secondary lm75 clients */
12180 + if ((err = asb100_detect_subclients(adapter, address, kind,
12184 + /* Initialize the chip */
12185 + asb100_init_client(new_client);
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;
12197 + i2c_detach_client(data->lm75[0]);
12198 + kfree(data->lm75[1]);
12199 + kfree(data->lm75[0]);
12201 + i2c_detach_client(new_client);
12208 +static int asb100_detach_client(struct i2c_client *client)
12211 + struct asb100_data *data = client->data;
12213 + /* remove sysctl table (primary client only) */
12215 + i2c_deregister_entry(data->sysctl_id);
12217 + if ((err = i2c_detach_client(client))) {
12218 + printk (KERN_ERR "asb100.o: Client deregistration failed; "
12219 + "client not detached.\n");
12224 + /* primary client */
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)
12242 + struct asb100_data *data = client->data;
12243 + struct i2c_client *cl;
12246 + down(&data->lock);
12248 + bank = (reg >> 8) & 0x0f;
12250 + /* switch banks */
12251 + i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank);
12253 + if (bank == 0 || bank > 2) {
12254 + res = i2c_smbus_read_byte_data(client, reg & 0xff);
12256 + /* switch to subclient */
12257 + cl = data->lm75[bank - 1];
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));
12264 + case 0x52: /* CONFIG */
12265 + res = i2c_smbus_read_byte_data(cl, 1);
12267 + case 0x53: /* HYST */
12268 + res = swab16(i2c_smbus_read_word_data (cl, 2));
12270 + case 0x55: /* MAX */
12272 + res = swab16(i2c_smbus_read_word_data (cl, 3));
12278 + i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
12285 +static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value)
12287 + struct asb100_data *data = client->data;
12288 + struct i2c_client *cl;
12291 + down(&data->lock);
12293 + bank = (reg >> 8) & 0x0f;
12295 + /* switch banks */
12296 + i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank);
12298 + if (bank == 0 || bank > 2) {
12299 + i2c_smbus_write_byte_data(client, reg & 0xff, value & 0xff);
12301 + /* switch to subclient */
12302 + cl = data->lm75[bank - 1];
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);
12309 + case 0x53: /* HYST */
12310 + i2c_smbus_write_word_data(cl, 2, swab16(value));
12312 + case 0x55: /* MAX */
12313 + i2c_smbus_write_word_data(cl, 3, swab16(value));
12319 + i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0);
12324 +static void asb100_init_client(struct i2c_client *client)
12326 + struct asb100_data *data = client->data;
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);
12334 + /* Start monitoring */
12335 + asb100_write_value(client, ASB100_REG_CONFIG,
12336 + (asb100_read_value(client, ASB100_REG_CONFIG) & 0xf7) | 0x01);
12339 +static void asb100_update_client(struct i2c_client *client)
12341 + struct asb100_data *data = client->data;
12344 + down(&data->update_lock);
12346 + if (time_after(jiffies - data->last_updated, HZ + HZ / 2) ||
12347 + time_before(jiffies, data->last_updated) || !data->valid) {
12349 + pr_debug("asb100.o: starting device update...\n");
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));
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));
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));
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;
12390 + data->pwm = asb100_read_value(client, ASB100_REG_PWM1);
12393 + data->alarms = asb100_read_value(client, ASB100_REG_ALARM1) +
12394 + (asb100_read_value(client, ASB100_REG_ALARM2) << 8);
12396 + data->last_updated = jiffies;
12399 + pr_debug("asb100.o: ... update complete.\n");
12402 + up(&data->update_lock);
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)
12422 + struct asb100_data *data = client->data;
12423 + int nr = ctl_name - ASB100_SYSCTL_IN0;
12425 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
12447 +void asb100_fan(struct i2c_client *client, int operation, int ctl_name,
12448 + int *nrels_mag, long *results)
12450 + struct asb100_data *data = client->data;
12451 + int nr = ctl_name - ASB100_SYSCTL_FAN1 + 1;
12453 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
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]);
12474 +void asb100_temp(struct i2c_client *client, int operation, int ctl_name,
12475 + int *nrels_mag, long *results)
12477 + struct asb100_data *data = client->data;
12478 + int nr = ctl_name - ASB100_SYSCTL_TEMP1;
12480 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
12504 +void asb100_temp_add(struct i2c_client *client, int operation,
12505 + int ctl_name, int *nrels_mag, long *results)
12507 + struct asb100_data *data = client->data;
12508 + int nr = ctl_name - ASB100_SYSCTL_TEMP1;
12510 + if (operation == SENSORS_PROC_REAL_INFO)
12513 + else if (operation == SENSORS_PROC_REAL_READ) {
12514 + asb100_update_client(client);
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]);
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]);
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]);
12537 +void asb100_vid(struct i2c_client *client, int operation, int ctl_name,
12538 + int *nrels_mag, long *results)
12540 + struct asb100_data *data = client->data;
12541 + if (operation == SENSORS_PROC_REAL_INFO)
12543 + else if (operation == SENSORS_PROC_REAL_READ) {
12544 + asb100_update_client(client);
12545 + results[0] = vid_from_reg(data->vid, data->vrm);
12550 +void asb100_vrm(struct i2c_client *client, int operation, int ctl_name,
12551 + int *nrels_mag, long *results)
12553 + struct asb100_data *data = client->data;
12554 + if (operation == SENSORS_PROC_REAL_INFO)
12556 + else if (operation == SENSORS_PROC_REAL_READ) {
12557 + results[0] = data->vrm;
12559 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
12560 + if (*nrels_mag >= 1)
12561 + data->vrm = results[0];
12565 +void asb100_alarms(struct i2c_client *client, int operation, int ctl_name,
12566 + int *nrels_mag, long *results)
12568 + struct asb100_data *data = client->data;
12569 + if (operation == SENSORS_PROC_REAL_INFO)
12571 + else if (operation == SENSORS_PROC_REAL_READ) {
12572 + asb100_update_client(client);
12573 + results[0] = ALARMS_FROM_REG(data->alarms);
12578 +void asb100_fan_div(struct i2c_client *client, int operation,
12579 + int ctl_name, int *nrels_mag, long *results)
12581 + struct asb100_data *data = client->data;
12584 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
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);
12614 +void asb100_pwm(struct i2c_client *client, int operation, int ctl_name,
12615 + int *nrels_mag, long *results)
12617 + struct asb100_data *data = client->data;
12619 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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) {
12636 + asb100_write_value(client, ASB100_REG_PWM1, val);
12641 +static int __init asb100_init(void)
12643 + printk(KERN_INFO "asb100.o version %s (%s)\n", LM_VERSION, LM_DATE);
12644 + return i2c_add_driver(&asb100_driver);
12647 +static void __exit asb100_exit(void)
12649 + i2c_del_driver(&asb100_driver);
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>");
12657 +MODULE_DESCRIPTION("ASB100 'Bach' driver");
12658 +MODULE_LICENSE("GPL");
12660 +module_init(asb100_init);
12661 +module_exit(asb100_exit);
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
12667 + bt869.c - Part of lm_sensors, Linux kernel modules for hardware
12670 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
12671 + Copyright (c) 2001, 2002 Stephen Davies <steve@daviesfam.org>
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.
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.
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.
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"
12699 +MODULE_LICENSE("GPL");
12701 +/* Addresses to scan */
12702 +static unsigned short normal_i2c[] = { SENSORS_I2C_END };
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 };
12709 +/* Insmod parameters */
12710 +SENSORS_INSMOD_1(bt869);
12712 +/* Many bt869 constants specified below */
12714 +/* The bt869 registers */
12715 +/* Coming soon: Many, many registers */
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. */
12724 +/* Initial values */
12727 +/* Each client has this additional data */
12728 +struct bt869_data {
12729 + struct i2c_client client;
12732 + struct semaphore update_lock;
12733 + char valid; /* !=0 if following fields are valid */
12734 + unsigned long last_updated; /* In jiffies */
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 */
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);
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,
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
12789 +/* -- SENSORS SYSCTL END -- */
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},
12814 +/* ******************
12816 +720x576, 27.5MHz, PAL, no overscan compensation.
12818 +This mode should be use for digital video, DVD playback etc.
12820 +NOTE: This mode for PAL, see 720x480 for an equivalent NTSC mode
12821 +NOTE: -- Steve Davies <steve@daviesfam.org>
12824 +Compatible X modeline:
12826 + Mode "720x576-BT869"
12828 + HTimings 720 744 800 880
12829 + VTimings 576 581 583 625
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
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
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
12922 +***************** */
12924 +static u16 registers_720_576[] =
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 */
12976 +/* ******************
12978 +720x480, 27.5MHz, NTSC no overscan compensation.
12980 +This mode should be use for digital video, DVD playback etc.
12982 +NOTE: This mode for NTSC, see 720x576 for an equivalent PAL mode
12983 +NOTE: -- Steve Davies <steve@daviesfam.org>
12985 +Compatible X modeline:
12987 + Mode "720x480-BT869"
12989 + HTimings 720 744 800 872
12990 + VTimings 480 483 485 525
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
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
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
13083 +***************** */
13085 +static u16 registers_720_480[] =
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 */
13139 +static int bt869_attach_adapter(struct i2c_adapter *adapter)
13141 + return i2c_detect(adapter, &addr_data, bt869_detect);
13144 +/* This function is called by i2c_detect */
13145 +int bt869_detect(struct i2c_adapter *adapter, int address,
13146 + unsigned short flags, int kind)
13149 + struct i2c_client *new_client;
13150 + struct bt869_data *data;
13152 + const char *type_name, *client_name;
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. */
13159 + if (i2c_is_isa_adapter(adapter)) {
13161 + ("bt869.o: bt869_detect called for an ISA bus adapter?!?\n");
13166 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE |
13167 + I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
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))) {
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;
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)
13192 + /* Determine the chip type */
13193 + kind = ((cur & 0x20) >> 5);
13196 + type_name = "bt869";
13197 + client_name = "bt869 chip";
13198 + printk("bt869.o: BT869 detected\n");
13200 + type_name = "bt868";
13201 + client_name = "bt868 chip";
13202 + printk("bt869.o: BT868 detected\n");
13205 + /* Fill in the remaining client fields and put it into the global list */
13206 + strcpy(new_client->name, client_name);
13208 + new_client->id = bt869_id++;
13210 + init_MUTEX(&data->update_lock);
13212 + /* Tell the I2C layer a new client has arrived */
13213 + if ((err = i2c_attach_client(new_client)))
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) {
13222 + data->sysctl_id = i;
13224 + bt869_init_client((struct i2c_client *) new_client);
13227 +/* OK, this is not exactly good programming practice, usually. But it is
13228 + very code-efficient in this case. */
13231 + i2c_detach_client(new_client);
13239 +static int bt869_detach_client(struct i2c_client *client)
13243 + i2c_deregister_entry(((struct bt869_data *) (client->data))->
13246 + if ((err = i2c_detach_client(client))) {
13248 + ("bt869.o: Client deregistration failed, client not detached.\n");
13252 + kfree(client->data);
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)
13263 + return i2c_smbus_read_byte(client);
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)
13272 + printk("bt869.o: write_value(0x%X, 0x%X)\n", reg, value);
13274 + return i2c_smbus_write_byte_data(client, reg, value);
13277 +static void bt869_write_values(struct i2c_client *client, u16 *values)
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]);
13286 +static void bt869_init_client(struct i2c_client *client)
13288 + struct bt869_data *data = client->data;
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;
13305 + data->colorbars = 0;
13306 + data->svideo = 0;
13307 + data->depth = 16;
13311 +static void bt869_update_client(struct i2c_client *client)
13313 + struct bt869_data *data = client->data;
13315 + down(&data->update_lock);
13317 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
13318 + (jiffies < data->last_updated) || !data->valid) {
13320 + printk("Starting bt869 update\n");
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)));
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);
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);
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)) {
13348 + ("bt869.o: Warning: arbitrary resolutions not supported yet. Using 640x480.\n");
13349 + data->res[0] = 640;
13350 + data->res[1] = 480;
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);
13371 + case 1: /* Svideo*/
13372 + bt869_write_value(client, 0xce, 0x24);
13373 + bt869_write_value(client, 0xba, 0x21);
13375 + default: /* Composite */
13376 + bt869_write_value(client, 0xce, 0x0);
13377 + bt869_write_value(client, 0xba, 0x21);
13380 + /* Enable outputs */
13381 + bt869_write_value(client, 0xC4, 1);
13382 + /* Issue timing reset */
13383 + bt869_write_value(client, 0x6c, 0x80);
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;
13400 + up(&data->update_lock);
13404 +void bt869_status(struct i2c_client *client, int operation, int ctl_name,
13405 + int *nrels_mag, long *results)
13407 + struct bt869_data *data = client->data;
13408 + if (operation == SENSORS_PROC_REAL_INFO)
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];
13416 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
13418 + ("bt869.o: Warning: write was requested on read-only proc file: status\n");
13423 +void bt869_ntsc(struct i2c_client *client, int operation, int ctl_name,
13424 + int *nrels_mag, long *results)
13426 + struct bt869_data *data = client->data;
13427 + if (operation == SENSORS_PROC_REAL_INFO)
13429 + else if (operation == SENSORS_PROC_REAL_READ) {
13430 + bt869_update_client(client);
13431 + results[0] = data->ntsc;
13433 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
13434 + if (*nrels_mag >= 1) {
13435 + data->ntsc = (results[0] > 0);
13437 + bt869_update_client(client);
13442 +void bt869_svideo(struct i2c_client *client, int operation, int ctl_name,
13443 + int *nrels_mag, long *results)
13445 + struct bt869_data *data = client->data;
13446 + if (operation == SENSORS_PROC_REAL_INFO)
13448 + else if (operation == SENSORS_PROC_REAL_READ) {
13449 + bt869_update_client(client);
13450 + results[0] = data->svideo;
13452 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
13453 + if (*nrels_mag >= 1) {
13454 + data->svideo = results[0];
13456 + bt869_update_client(client);
13461 +void bt869_res(struct i2c_client *client, int operation, int ctl_name,
13462 + int *nrels_mag, long *results)
13464 + struct bt869_data *data = client->data;
13465 + if (operation == SENSORS_PROC_REAL_INFO)
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];
13472 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
13473 + if (*nrels_mag >= 1) {
13474 + data->res[0] = results[0];
13476 + if (*nrels_mag >= 2) {
13477 + data->res[1] = results[1];
13479 + bt869_update_client(client);
13484 +void bt869_half(struct i2c_client *client, int operation, int ctl_name,
13485 + int *nrels_mag, long *results)
13487 + struct bt869_data *data = client->data;
13488 + if (operation == SENSORS_PROC_REAL_INFO)
13490 + else if (operation == SENSORS_PROC_REAL_READ) {
13491 + bt869_update_client(client);
13492 + results[0] = data->half;
13494 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
13495 + if (*nrels_mag >= 1) {
13496 + data->half = (results[0] > 0);
13497 + bt869_update_client(client);
13502 +void bt869_colorbars(struct i2c_client *client, int operation,
13503 + int ctl_name, int *nrels_mag, long *results)
13505 + struct bt869_data *data = client->data;
13506 + if (operation == SENSORS_PROC_REAL_INFO)
13508 + else if (operation == SENSORS_PROC_REAL_READ) {
13509 + bt869_update_client(client);
13510 + results[0] = data->colorbars;
13512 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
13513 + if (*nrels_mag >= 1) {
13514 + data->colorbars = (results[0] > 0);
13515 + bt869_update_client(client);
13520 +void bt869_depth(struct i2c_client *client, int operation, int ctl_name,
13521 + int *nrels_mag, long *results)
13523 + struct bt869_data *data = client->data;
13524 + if (operation == SENSORS_PROC_REAL_INFO)
13526 + else if (operation == SENSORS_PROC_REAL_READ) {
13527 + bt869_update_client(client);
13528 + results[0] = data->depth;
13530 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
13531 + if (*nrels_mag >= 1) {
13532 + data->depth = results[0];
13533 + bt869_update_client(client);
13538 +static int __init sm_bt869_init(void)
13540 + printk("bt869.o version %s (%s)\n", LM_VERSION, LM_DATE);
13541 + return i2c_add_driver(&bt869_driver);
13544 +static void __exit sm_bt869_exit(void)
13546 + i2c_del_driver(&bt869_driver);
13552 + ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Stephen Davies <steve@daviesfam.org>");
13553 +MODULE_DESCRIPTION("bt869 driver");
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
13561 + ddcmon.c - Part of lm_sensors, Linux kernel modules for hardware
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>
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.
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.
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.
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"
13591 +MODULE_LICENSE("GPL");
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 };
13599 +/* Insmod parameters */
13600 +SENSORS_INSMOD_1(ddcmon);
13602 +static int checksum = 0;
13603 +MODULE_PARM(checksum, "i");
13604 +MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
13606 +/* Many constants specified below */
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
13630 +#define DDCMON_REG_CHECKSUM 0x7f
13632 +/* Size of DDCMON in bytes */
13633 +#define DDCMON_SIZE 128
13635 +/* Each client has this additional data */
13636 +struct ddcmon_data {
13637 + struct i2c_client client;
13640 + struct semaphore update_lock;
13641 + char valid; /* !=0 if following fields are valid */
13642 + unsigned long last_updated; /* In jiffies */
13644 + u8 data[DDCMON_SIZE]; /* Register values */
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);
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);
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,
13688 +/* -- SENSORS SYSCTL START -- */
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
13709 +/* -- SENSORS SYSCTL END -- */
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},
13756 +static int ddcmon_id = 0;
13758 +static int ddcmon_attach_adapter(struct i2c_adapter *adapter)
13760 + return i2c_detect(adapter, &addr_data, ddcmon_detect);
13763 +/* This function is called by i2c_detect */
13764 +int ddcmon_detect(struct i2c_adapter *adapter, int address,
13765 + unsigned short flags, int kind)
13768 + struct i2c_client *new_client;
13769 + struct ddcmon_data *data;
13771 + const char *type_name, *client_name;
13773 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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))) {
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;
13792 + /* prevent 24RF08 corruption (just in case) */
13793 + i2c_smbus_write_quick(new_client, 0);
13795 + /* Now, we do the remaining detection. */
13798 + for (i = 0; i < 0x80; i++)
13799 + cs += i2c_smbus_read_byte_data(new_client, i);
13800 + if ((cs & 0xff) != 0)
13804 + /* Verify the first 8 locations 0x00FFFFFFFFFFFF00 */
13805 + /* Allow force and force_ddcmon arguments */
13808 + for(i = 0; i < 8; i++) {
13809 + cs = i2c_smbus_read_byte_data(new_client, i);
13810 + if(i == 0 || i == 7) {
13813 + } else if(cs != 0xff)
13818 + type_name = "ddcmon";
13819 + client_name = "DDC Monitor";
13821 + /* Fill in the remaining client fields and put it in the global list */
13822 + strcpy(new_client->name, client_name);
13824 + new_client->id = ddcmon_id++;
13826 + init_MUTEX(&data->update_lock);
13828 + /* Tell the I2C layer a new client has arrived */
13829 + if ((err = i2c_attach_client(new_client)))
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) {
13838 + data->sysctl_id = i;
13843 + i2c_detach_client(new_client);
13851 +static int ddcmon_detach_client(struct i2c_client *client)
13855 + i2c_deregister_entry(((struct ddcmon_data *) (client->data))->
13857 + if ((err = i2c_detach_client(client))) {
13859 + ("ddcmon.o: Client deregistration failed, client not detached.\n");
13862 + kfree(client->data);
13866 +static void ddcmon_update_client(struct i2c_client *client)
13868 + struct ddcmon_data *data = client->data;
13871 + down(&data->update_lock);
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))
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);
13886 + if (i2c_smbus_write_byte(client, 0)) {
13887 + printk(KERN_WARNING "ddcmon.o: read start fail at 0!\n");
13890 + for (i = 0; i < DDCMON_SIZE; i++) {
13891 + j = i2c_smbus_read_byte(client);
13893 + printk(KERN_WARNING "eeprom.o: read fail at 0x%.2x!\n", i);
13896 + data->data[i] = (u8) j;
13899 + data->last_updated = jiffies;
13903 + up(&data->update_lock);
13907 +void ddcmon_idcall(struct i2c_client *client, int operation,
13908 + int ctl_name, int *nrels_mag, long *results)
13910 + struct ddcmon_data *data = client->data;
13912 + if (operation == SENSORS_PROC_REAL_INFO)
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);
13924 +void ddcmon_size(struct i2c_client *client, int operation,
13925 + int ctl_name, int *nrels_mag, long *results)
13927 + struct ddcmon_data *data = client->data;
13929 + if (operation == SENSORS_PROC_REAL_INFO)
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];
13939 +void ddcmon_sync(struct i2c_client *client, int operation,
13940 + int ctl_name, int *nrels_mag, long *results)
13943 + struct ddcmon_data *data = client->data;
13945 + if (operation == SENSORS_PROC_REAL_INFO)
13947 + else if (operation == SENSORS_PROC_REAL_READ) {
13948 + ddcmon_update_client(client);
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];
13964 + for(j = 0; j < 4; j++)
13969 +void ddcmon_maxclock(struct i2c_client *client, int operation,
13970 + int ctl_name, int *nrels_mag, long *results)
13973 + struct ddcmon_data *data = client->data;
13975 + if (operation == SENSORS_PROC_REAL_INFO)
13977 + else if (operation == SENSORS_PROC_REAL_READ) {
13978 + ddcmon_update_client(client);
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);
13998 +void ddcmon_timings(struct i2c_client *client, int operation,
13999 + int ctl_name, int *nrels_mag, long *results)
14001 + struct ddcmon_data *data = client->data;
14003 + if (operation == SENSORS_PROC_REAL_INFO)
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);
14014 +void ddcmon_serial(struct i2c_client *client, int operation,
14015 + int ctl_name, int *nrels_mag, long *results)
14017 + struct ddcmon_data *data = client->data;
14019 + if (operation == SENSORS_PROC_REAL_INFO)
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);
14031 +void ddcmon_time(struct i2c_client *client, int operation,
14032 + int ctl_name, int *nrels_mag, long *results)
14034 + struct ddcmon_data *data = client->data;
14036 + if (operation == SENSORS_PROC_REAL_INFO)
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];
14046 +void ddcmon_edid(struct i2c_client *client, int operation,
14047 + int ctl_name, int *nrels_mag, long *results)
14049 + struct ddcmon_data *data = client->data;
14051 + if (operation == SENSORS_PROC_REAL_INFO)
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];
14061 +void ddcmon_gamma(struct i2c_client *client, int operation,
14062 + int ctl_name, int *nrels_mag, long *results)
14064 + struct ddcmon_data *data = client->data;
14066 + if (operation == SENSORS_PROC_REAL_INFO)
14068 + else if (operation == SENSORS_PROC_REAL_READ) {
14069 + ddcmon_update_client(client);
14070 + results[0] = 100 + data->data[DDCMON_REG_GAMMA];
14075 +void ddcmon_dpms(struct i2c_client *client, int operation,
14076 + int ctl_name, int *nrels_mag, long *results)
14078 + struct ddcmon_data *data = client->data;
14080 + if (operation == SENSORS_PROC_REAL_INFO)
14082 + else if (operation == SENSORS_PROC_REAL_READ) {
14083 + ddcmon_update_client(client);
14084 + results[0] = data->data[DDCMON_REG_DPMS_FLAGS];
14089 +void ddcmon_standard_timing(struct i2c_client *client, int operation,
14090 + int ctl_name, int *nrels_mag, long *results)
14092 + struct ddcmon_data *data = client->data;
14093 + int nr = ctl_name - DDCMON_SYSCTL_TIMING1;
14095 + if (operation == SENSORS_PROC_REAL_INFO)
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. */
14108 + results[1] = results[0]; /* unconfirmed */
14111 + results[1] = results[0] * 3 / 4;
14114 + results[1] = results[0] * 4 / 5;
14117 + results[1] = results[0] * 9 / 16;
14120 + results[2] = (data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2 + 1] & 0x3f) + 60;
14130 +static int __init sm_ddcmon_init(void)
14132 + printk("ddcmon.o version %s (%s)\n", LM_VERSION, LM_DATE);
14133 + return i2c_add_driver(&ddcmon_driver);
14136 +static void __exit sm_ddcmon_exit(void)
14138 + i2c_del_driver(&ddcmon_driver);
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");
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
14155 + ds1621.c - Part of lm_sensors, Linux kernel modules for hardware
14157 + Christian W. Zuckschwerdt <zany@triq.net> 2000-11-23
14158 + based on lm75.c by Frodo Looijaard <frodol@dds.nl>
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.
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.
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.
14175 +/* Supports DS1621. See doc/chips/ds1621 for details */
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"
14185 +MODULE_LICENSE("GPL");
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 };
14193 +/* Insmod parameters */
14194 +SENSORS_INSMOD_1(ds1621);
14196 +/* Many DS1621 constants specified below */
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
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!
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 */
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))
14235 +/* Each client has this additional data */
14236 +struct ds1621_data {
14237 + struct i2c_client client;
14240 + struct semaphore update_lock;
14241 + char valid; /* !=0 if following fields are valid */
14242 + unsigned long last_updated; /* In jiffies */
14244 + u16 temp, temp_over, temp_hyst; /* Register values, word */
14245 + u8 conf; /* Register encoding, combined */
14247 + char enable; /* !=0 if we're expected to restart the conversion */
14248 + u8 temp_int, temp_counter, temp_slope; /* Register values, byte */
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);
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);
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,
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
14291 +/* -- SENSORS SYSCTL END -- */
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},
14312 +static int ds1621_id = 0;
14314 +static int ds1621_attach_adapter(struct i2c_adapter *adapter)
14316 + return i2c_detect(adapter, &addr_data, ds1621_detect);
14319 +/* This function is called by i2c_detect */
14320 +int ds1621_detect(struct i2c_adapter *adapter, int address,
14321 + unsigned short flags, int kind)
14324 + struct i2c_client *new_client;
14325 + struct ds1621_data *data;
14327 + const char *type_name, *client_name;
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. */
14332 + if (i2c_is_isa_adapter(adapter)) {
14334 + ("ds1621.o: ds1621_detect called for an ISA bus adapter?!?\n");
14339 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
14340 + I2C_FUNC_SMBUS_WORD_DATA |
14341 + I2C_FUNC_SMBUS_WRITE_BYTE))
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))) {
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;
14359 + /* Now, we do the remaining detection. It is lousy. */
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)
14368 + /* Determine the chip type - only one kind supported! */
14372 + if (kind == ds1621) {
14373 + type_name = "ds1621";
14374 + client_name = "DS1621 chip";
14377 + printk("ds1621.o: Internal error: unknown kind (%d)?!?",
14383 + /* Fill in remaining client fields and put it into the global list */
14384 + strcpy(new_client->name, client_name);
14386 + new_client->id = ds1621_id++;
14388 + init_MUTEX(&data->update_lock);
14390 + /* Tell the I2C layer a new client has arrived */
14391 + if ((err = i2c_attach_client(new_client)))
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) {
14400 + data->sysctl_id = i;
14402 + ds1621_init_client(new_client);
14405 +/* OK, this is not exactly good programming practice, usually. But it is
14406 + very code-efficient in this case. */
14409 + i2c_detach_client(new_client);
14417 +static int ds1621_detach_client(struct i2c_client *client)
14421 + i2c_deregister_entry(((struct ds1621_data *) (client->data))->
14424 + if ((err = i2c_detach_client(client))) {
14426 + ("ds1621.o: Client deregistration failed, client not detached.\n");
14430 + kfree(client->data);
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)
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);
14445 + return swab16(i2c_smbus_read_word_data(client, reg));
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)
14453 + if ( (reg == DS1621_COM_START) || (reg == DS1621_COM_STOP) )
14454 + return i2c_smbus_write_byte(client, reg);
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);
14460 + return i2c_smbus_write_word_data(client, reg, swab16(value));
14463 +static void ds1621_init_client(struct i2c_client *client)
14467 + reg = ds1621_read_value(client, DS1621_REG_CONF);
14468 + /* start the continous conversion */
14470 + ds1621_write_value(client, DS1621_REG_CONF, reg & 0xfe);
14473 +static void ds1621_update_client(struct i2c_client *client)
14475 + struct ds1621_data *data = client->data;
14478 + down(&data->update_lock);
14480 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
14481 + (jiffies < data->last_updated) || !data->valid) {
14484 + printk("Starting ds1621 update\n");
14487 + data->conf = ds1621_read_value(client, DS1621_REG_CONF);
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);
14496 + /* wait for the DONE bit before reading extended values */
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);
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,
14519 + data->last_updated = jiffies;
14523 + up(&data->update_lock);
14527 +void ds1621_temp(struct i2c_client *client, int operation, int ctl_name,
14528 + int *nrels_mag, long *results)
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)) {
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);
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);
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);
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);
14570 +void ds1621_alarms(struct i2c_client *client, int operation, int ctl_name,
14571 + int *nrels_mag, long *results)
14573 + struct ds1621_data *data = client->data;
14574 + if (operation == SENSORS_PROC_REAL_INFO)
14576 + else if (operation == SENSORS_PROC_REAL_READ) {
14577 + ds1621_update_client(client);
14578 + results[0] = ALARMS_FROM_REG(data->conf);
14583 +void ds1621_enable(struct i2c_client *client, int operation, int ctl_name,
14584 + int *nrels_mag, long *results)
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! */
14590 + struct ds1621_data *data = client->data;
14591 + if (operation == SENSORS_PROC_REAL_INFO)
14593 + else if (operation == SENSORS_PROC_REAL_READ) {
14594 + ds1621_update_client(client);
14595 + results[0] = !(data->conf & DS1621_REG_CONFIG_DONE);
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);
14603 + ds1621_write_value(client, DS1621_COM_STOP, 0);
14607 + ds1621_write_value(client, DS1621_COM_START, 0);
14613 +void ds1621_continuous(struct i2c_client *client, int operation, int ctl_name,
14614 + int *nrels_mag, long *results)
14616 + struct ds1621_data *data = client->data;
14617 + if (operation == SENSORS_PROC_REAL_INFO)
14619 + else if (operation == SENSORS_PROC_REAL_READ) {
14620 + ds1621_update_client(client);
14621 + results[0] = !(data->conf & DS1621_REG_CONFIG_1SHOT);
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);
14630 + ds1621_write_value(client, DS1621_REG_CONF,
14631 + data->conf | DS1621_REG_CONFIG_1SHOT);
14634 + ds1621_write_value(client, DS1621_REG_CONF,
14635 + data->conf & ~DS1621_REG_CONFIG_1SHOT);
14640 +void ds1621_polarity(struct i2c_client *client, int operation, int ctl_name,
14641 + int *nrels_mag, long *results)
14643 + struct ds1621_data *data = client->data;
14644 + if (operation == SENSORS_PROC_REAL_INFO)
14646 + else if (operation == SENSORS_PROC_REAL_READ) {
14647 + ds1621_update_client(client);
14648 + results[0] = !(!(data->conf & DS1621_REG_CONFIG_POLARITY));
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);
14657 + ds1621_write_value(client, DS1621_REG_CONF,
14658 + data->conf & ~DS1621_REG_CONFIG_POLARITY);
14664 +static int __init sm_ds1621_init(void)
14666 + printk("ds1621.o version %s (%s)\n", LM_VERSION, LM_DATE);
14667 + return i2c_add_driver(&ds1621_driver);
14670 +static void __exit sm_ds1621_exit(void)
14672 + i2c_del_driver(&ds1621_driver);
14677 +MODULE_AUTHOR("Christian W. Zuckschwerdt <zany@triq.net>");
14678 +MODULE_DESCRIPTION("DS1621 driver");
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
14686 + eeprom.c - Part of lm_sensors, Linux kernel modules for hardware
14688 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
14689 + Philip Edelbrock <phil@netroedge.com>
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
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.
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.
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.
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"
14720 +MODULE_LICENSE("GPL");
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 };
14728 +/* Insmod parameters */
14729 +SENSORS_INSMOD_1(eeprom);
14731 +static int checksum = 0;
14732 +MODULE_PARM(checksum, "i");
14733 +MODULE_PARM_DESC(checksum,
14734 + "Only accept eeproms whose checksum is correct");
14737 +/* Many constants specified below */
14739 +/* EEPROM registers */
14740 +#define EEPROM_REG_CHECKSUM 0x3f
14742 +/* possible natures */
14743 +#define NATURE_UNKNOWN 0
14744 +#define NATURE_VAIO 1
14746 +/* Size of EEPROM in bytes */
14747 +#define EEPROM_SIZE 256
14749 +/* Each client has this additional data */
14750 +struct eeprom_data {
14751 + struct i2c_client client;
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 */
14758 + u8 data[EEPROM_SIZE]; /* Register values */
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);
14769 +static int eeprom_write_value(struct i2c_client *client, u8 reg,
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);
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,
14788 +/* -- SENSORS SYSCTL START -- */
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
14807 +/* -- SENSORS SYSCTL END -- */
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},
14850 +static int eeprom_id = 0;
14852 +static int eeprom_attach_adapter(struct i2c_adapter *adapter)
14854 + return i2c_detect(adapter, &addr_data, eeprom_detect);
14857 +/* This function is called by i2c_detect */
14858 +int eeprom_detect(struct i2c_adapter *adapter, int address,
14859 + unsigned short flags, int kind)
14862 + struct i2c_client *new_client;
14863 + struct eeprom_data *data;
14865 + const char *type_name, *client_name;
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. */
14870 + if (i2c_is_isa_adapter(adapter)) {
14872 + ("eeprom.o: eeprom_detect called for an ISA bus adapter?!?\n");
14877 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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))) {
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;
14896 + /* prevent 24RF08 corruption */
14897 + i2c_smbus_write_quick(new_client, 0);
14899 + /* Now, we do the remaining detection. It is not there, unless you force
14900 + the checksum to work out. */
14903 + for (i = 0; i <= 0x3e; i++)
14904 + cs += i2c_smbus_read_byte_data(new_client, i);
14906 + if (i2c_smbus_read_byte_data
14907 + (new_client, EEPROM_REG_CHECKSUM) != cs)
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)
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;
14923 + /* Determine the chip type - only one kind supported! */
14927 + if (kind == eeprom) {
14928 + type_name = "eeprom";
14929 + client_name = "EEPROM chip";
14932 + printk("eeprom.o: Internal error: unknown kind (%d)?!?",
14938 + /* Fill in the remaining client fields and put it into the global list */
14939 + strcpy(new_client->name, client_name);
14941 + new_client->id = eeprom_id++;
14943 + init_MUTEX(&data->update_lock);
14945 + /* Tell the I2C layer a new client has arrived */
14946 + if ((err = i2c_attach_client(new_client)))
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) {
14955 + data->sysctl_id = i;
14959 +/* OK, this is not exactly good programming practice, usually. But it is
14960 + very code-efficient in this case. */
14963 + i2c_detach_client(new_client);
14971 +static int eeprom_detach_client(struct i2c_client *client)
14975 + i2c_deregister_entry(((struct eeprom_data *) (client->data))->
14978 + if ((err = i2c_detach_client(client))) {
14980 + ("eeprom.o: Client deregistration failed, client not detached.\n");
14984 + kfree(client->data);
14991 +/* No writes yet (PAE) */
14992 +static int eeprom_write_value(struct i2c_client *client, u8 reg, u8 value)
14994 + return i2c_smbus_write_byte_data(client, reg, value);
14998 +static void eeprom_update_client(struct i2c_client *client, u8 slice)
15000 + struct eeprom_data *data = client->data;
15003 + down(&data->update_lock);
15005 + if (!(data->valid & (1 << slice))
15006 + || (jiffies - data->last_updated[slice] > 300 * HZ)
15007 + || (jiffies < data->last_updated[slice])) {
15010 + printk("Starting eeprom update, slice %u\n", slice);
15013 + if (i2c_check_functionality(client->adapter,
15014 + I2C_FUNC_SMBUS_READ_I2C_BLOCK))
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);
15025 + if (i2c_smbus_write_byte(client, slice << 5)) {
15026 + printk(KERN_WARNING "eeprom.o: read start fail at 0x%.2x!\n", slice << 5);
15029 + for (i = slice << 5; i < (slice + 1) << 5; i++) {
15030 + j = i2c_smbus_read_byte(client);
15032 + printk(KERN_WARNING "eeprom.o: read fail at 0x%.2x!\n", i);
15035 + data->data[i] = (u8) j;
15038 + data->last_updated[slice] = jiffies;
15039 + data->valid |= (1 << slice);
15042 + up(&data->update_lock);
15046 +void eeprom_contents(struct i2c_client *client, int operation,
15047 + int ctl_name, int *nrels_mag, long *results)
15050 + int nr = ctl_name - EEPROM_SYSCTL1;
15051 + struct eeprom_data *data = client->data;
15053 + if (operation == SENSORS_PROC_REAL_INFO)
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++)
15063 + for (i = 0; i < 16; i++)
15064 + results[i] = data->data[i + nr * 16];
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");
15071 + for (i = 0; i < 16; i++)
15072 + printk(" 0x%02X", data->data[i + nr * 16]);
15077 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
15079 +/* No writes to the EEPROM (yet, anyway) (PAE) */
15080 + printk("eeprom.o: No writes to EEPROMs supported!\n");
15084 +static int __init sm_eeprom_init(void)
15086 + printk("eeprom.o version %s (%s)\n", LM_VERSION, LM_DATE);
15087 + return i2c_add_driver(&eeprom_driver);
15090 +static void __exit sm_eeprom_exit(void)
15092 + i2c_del_driver(&eeprom_driver);
15098 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
15099 +MODULE_DESCRIPTION("EEPROM driver");
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
15107 + fscpos.c - Part of lm_sensors, Linux kernel modules for hardware
15109 + Copyright (c) 2001 Hermann Jung <hej@odn.de>
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.
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.
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.
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>
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"
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 };
15147 +/* Insmod parameters */
15148 +SENSORS_INSMOD_1(fscpos);
15150 +/* The FSCPOS registers */
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
15158 +/* global control and status */
15159 +#define FSCPOS_REG_EVENT_STATE 0x04
15160 +#define FSCPOS_REG_CONTROL 0x05
15163 +#define FSCPOS_REG_WDOG_PRESET 0x28
15164 +#define FSCPOS_REG_WDOG_STATE 0x23
15165 +#define FSCPOS_REG_WDOG_CONTROL 0x21
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
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
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
15185 +/* voltage supervision */
15186 +#define FSCPOS_REG_VOLT_12 0x45
15187 +#define FSCPOS_REG_VOLT_5 0x42
15188 +#define FSCPOS_REG_VOLT_BATT 0x48
15190 +/* temperatures */
15192 +#define FSCPOS_REG_TEMP0_ACT 0x64
15193 +#define FSCPOS_REG_TEMP0_STATE 0x71
15196 +#define FSCPOS_REG_TEMP1_ACT 0x32
15197 +#define FSCPOS_REG_TEMP1_STATE 0x81
15200 +#define FSCPOS_REG_TEMP2_ACT 0x35
15201 +#define FSCPOS_REG_TEMP2_STATE 0x91
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. */
15211 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT((val),0,255))
15212 +#define IN_FROM_REG(val,nr) (val)
15214 +/* Initial limits */
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
15220 +struct fscpos_data {
15221 + struct i2c_client client;
15224 + struct semaphore update_lock;
15225 + char valid; /* !=0 if following fields are valid */
15226 + unsigned long last_updated; /* In jiffies */
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 */
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);
15247 +static int fscpos_read_value(struct i2c_client *client, u8 register);
15248 +static int fscpos_write_value(struct i2c_client *client, u8 register,
15250 +static void fscpos_update_client(struct i2c_client *client);
15251 +static void fscpos_init_client(struct i2c_client *client);
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);
15268 +static int fscpos_id = 0;
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,
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 -- */
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},
15330 +static int fscpos_attach_adapter(struct i2c_adapter *adapter)
15332 + return i2c_detect(adapter, &addr_data, fscpos_detect);
15335 +int fscpos_detect(struct i2c_adapter *adapter, int address,
15336 + unsigned short flags, int kind)
15339 + struct i2c_client *new_client;
15340 + struct fscpos_data *data;
15342 + const char *type_name, *client_name;
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. */
15347 + if (i2c_is_isa_adapter(adapter)) {
15349 + ("fscpos.o: fscpos_detect called for an ISA bus adapter?!?\n");
15354 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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))) {
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;
15372 + /* Do the remaining detection unless force or force_fscpos parameter */
15374 + if (fscpos_read_value(new_client, FSCPOS_REG_IDENT_0) != 0x50)
15376 + if (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1) != 0x45)
15378 + if (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2) != 0x47)
15384 + type_name = "fscpos";
15385 + client_name = "fsc poseidon chip";
15387 + /* Fill in the remaining client fields and put it into the global list */
15388 + strcpy(new_client->name, client_name);
15390 + new_client->id = fscpos_id++;
15392 + init_MUTEX(&data->update_lock);
15394 + /* Tell the I2C layer a new client has arrived */
15395 + if ((err = i2c_attach_client(new_client)))
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) {
15404 + data->sysctl_id = i;
15406 + fscpos_init_client(new_client);
15409 +/* OK, this is not exactly good programming practice, usually. But it is
15410 + very code-efficient in this case. */
15412 + i2c_detach_client(new_client);
15420 +static int fscpos_detach_client(struct i2c_client *client)
15424 + i2c_deregister_entry(((struct fscpos_data *) (client->data))->
15427 + if ((err = i2c_detach_client(client))) {
15429 + ("fscpos.o: Client deregistration failed, client not detached.\n");
15433 + kfree(client->data);
15438 +static int fscpos_read_value(struct i2c_client *client, u8 reg)
15441 + printk("fscpos: read reg 0x%02x\n",reg);
15443 + return i2c_smbus_read_byte_data(client, reg);
15446 +static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value)
15449 + printk("fscpos: write reg 0x%02x, val 0x%02x\n",reg, value);
15451 + return i2c_smbus_write_byte_data(client, reg, value);
15454 +/* Called when we have found a new FSCPOS. It should set limits, etc. */
15455 +static void fscpos_init_client(struct i2c_client *client)
15457 + struct fscpos_data *data = client->data;
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;
15465 +static void fscpos_update_client(struct i2c_client *client)
15467 + struct fscpos_data *data = client->data;
15469 + down(&data->update_lock);
15471 + if ((jiffies - data->last_updated > 2 * HZ) ||
15472 + (jiffies < data->last_updated) || !data->valid) {
15475 + printk("Starting fscpos update\n");
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);
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);
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);
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);
15505 + data->global_event = fscpos_read_value(client, FSCPOS_REG_EVENT_STATE);
15507 + data->last_updated = jiffies;
15511 + up(&data->update_lock);
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)
15531 + struct fscpos_data *data = client->data;
15533 + if (operation == SENSORS_PROC_REAL_INFO)
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 ;
15541 + case FSCPOS_SYSCTL_EVENT:
15542 + results[0] = data->global_event & 0x1f;
15544 + case FSCPOS_SYSCTL_CONTROL:
15545 + results[0] = data->global_control & 0x01;
15548 + printk("fscpos: ctl_name %d not supported\n",
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);
15563 + printk("fscpos: writing to chip not supported\n");
15567 +#define TEMP_FROM_REG(val) (val-128)
15570 +void fscpos_temp(struct i2c_client *client, int operation, int ctl_name,
15571 + int *nrels_mag, long *results)
15573 + struct fscpos_data *data = client->data;
15575 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
15584 + case FSCPOS_SYSCTL_TEMP1:
15585 + results[0] = data->temp_status[1] & 0x03;
15586 + results[1] = TEMP_FROM_REG(data->temp_act[1]);
15588 + case FSCPOS_SYSCTL_TEMP2:
15589 + results[0] = data->temp_status[2] & 0x03;
15590 + results[1] = TEMP_FROM_REG(data->temp_act[2]);
15593 + printk("fscpos: ctl_name %d not supported\n",
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);
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);
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);
15626 + printk("fscpos: ctl_name %d not supported\n",ctl_name);
15630 + printk("fscpos: writing to chip not supported\n");
15634 +#define VOLT_FROM_REG(val,mult) (val*mult/255)
15636 +void fscpos_volt(struct i2c_client *client, int operation, int ctl_name,
15637 + int *nrels_mag, long *results)
15639 + struct fscpos_data *data = client->data;
15640 + if (operation == SENSORS_PROC_REAL_INFO)
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);
15648 + case FSCPOS_SYSCTL_VOLT1:
15649 + results[0] = VOLT_FROM_REG(data->volt[1],660);
15651 + case FSCPOS_SYSCTL_VOLT2:
15652 + results[0] = VOLT_FROM_REG(data->volt[2],330);
15655 + printk("fscpos: ctl_name %d not supported\n",
15661 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
15662 + printk("fscpos: writing to chip not supported\n");
15666 +void fscpos_fan(struct i2c_client *client, int operation, int ctl_name,
15667 + int *nrels_mag, long *results)
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);
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);
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);
15687 + printk("fscpos: illegal fan nr %d\n",ctl_name);
15691 +#define RPM_FROM_REG(val) (val*60)
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 )
15697 + struct fscpos_data *data = client->data;
15699 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
15724 + if(*nrels_mag >= 3) {
15725 + if((results[2] & 0x03) == 0) {
15726 + printk("fscpos: fan%d ripple 0 not allowed\n",nr);
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]);
15738 +void fscpos_wdog(struct i2c_client *client, int operation, int ctl_name,
15739 + int *nrels_mag, long *results)
15741 + struct fscpos_data *data = client->data;
15743 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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]);
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]);
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]);
15776 +static int __init sm_fscpos_init(void)
15778 + printk("fscpos.o version %s (%s)\n", LM_VERSION, LM_DATE);
15779 + return i2c_add_driver(&fscpos_driver);
15782 +static void __exit sm_fscpos_exit(void)
15784 + i2c_del_driver(&fscpos_driver);
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");
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
15800 + fscscy.c - Part of lm_sensors, Linux kernel modules for hardware
15802 + Copyright (c) 2001 Martin Knoblauch <mkn@teraport.de, knobi@knobisoft.de>
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.
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.
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.
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>
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"
15834 +MODULE_LICENSE("GPL");
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 };
15842 +/* Insmod parameters */
15843 +SENSORS_INSMOD_1(fscscy);
15845 +/* The FSCSCY registers */
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
15853 +/* global control and status */
15854 +#define FSCSCY_REG_EVENT_STATE 0x04
15855 +#define FSCSCY_REG_CONTROL 0x05
15858 +#define FSCSCY_REG_WDOG_PRESET 0x28
15859 +#define FSCSCY_REG_WDOG_STATE 0x23
15860 +#define FSCSCY_REG_WDOG_CONTROL 0x21
15863 +** Fan definitions
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
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
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
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
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
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
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
15910 +/* voltage supervision */
15911 +#define FSCSCY_REG_VOLT_12 0x45
15912 +#define FSCSCY_REG_VOLT_5 0x42
15913 +#define FSCSCY_REG_VOLT_BATT 0x48
15915 +/* temperatures */
15917 +#define FSCSCY_REG_TEMP0_ACT 0x64
15918 +#define FSCSCY_REG_TEMP0_STATE 0x71
15919 +#define FSCSCY_REG_TEMP0_LIM 0x76
15922 +#define FSCSCY_REG_TEMP1_ACT 0xD0
15923 +#define FSCSCY_REG_TEMP1_STATE 0xD1
15924 +#define FSCSCY_REG_TEMP1_LIM 0xD6
15927 +#define FSCSCY_REG_TEMP2_ACT 0x32
15928 +#define FSCSCY_REG_TEMP2_STATE 0x81
15929 +#define FSCSCY_REG_TEMP2_LIM 0x86
15932 +#define FSCSCY_REG_TEMP3_ACT 0x35
15933 +#define FSCSCY_REG_TEMP3_STATE 0x91
15934 +#define FSCSCY_REG_TEMP3_LIM 0x96
15937 +#define FSCSCY_REG_PCILOAD 0x1a
15939 +/* Intrusion Sensor */
15940 +#define FSCSCY_REG_INTR_STATE 0x13
15941 +#define FSCSCY_REG_INTR_CTRL 0x12
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. */
15948 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT((val),0,255))
15949 +#define IN_FROM_REG(val,nr) (val)
15951 +/* Initial limits */
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
15957 +struct fscscy_data {
15958 + struct i2c_client client;
15961 + struct semaphore update_lock;
15962 + char valid; /* !=0 if following fields are valid */
15963 + unsigned long last_updated; /* In jiffies */
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 */
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);
15994 +static int fscscy_read_value(struct i2c_client *client, u8 register);
15995 +static int fscscy_write_value(struct i2c_client *client, u8 register,
15997 +static void fscscy_update_client(struct i2c_client *client);
15998 +static void fscscy_init_client(struct i2c_client *client);
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);
16019 +static int fscscy_id = 0;
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,
16030 +/* The /proc/sys entries */
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 */
16053 +/* -- SENSORS SYSCTL END -- */
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},
16102 +static int fscscy_attach_adapter(struct i2c_adapter *adapter)
16104 + return i2c_detect(adapter, &addr_data, fscscy_detect);
16107 +int fscscy_detect(struct i2c_adapter *adapter, int address,
16108 + unsigned short flags, int kind)
16111 + struct i2c_client *new_client;
16112 + struct fscscy_data *data;
16114 + const char *type_name, *client_name;
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. */
16119 + if (i2c_is_isa_adapter(adapter)) {
16121 + ("fscscy.o: fscscy_detect called for an ISA bus adapter?!?\n");
16126 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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))) {
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;
16144 + /* Do the remaining detection unless force or force_fscscy parameter */
16146 + if (fscscy_read_value(new_client, FSCSCY_REG_IDENT_0) != 0x53)
16148 + if (fscscy_read_value(new_client, FSCSCY_REG_IDENT_1) != 0x43)
16150 + if (fscscy_read_value(new_client, FSCSCY_REG_IDENT_2) != 0x59)
16156 + type_name = "fscscy";
16157 + client_name = "fsc scylla chip";
16159 + /* Fill in the remaining client fields and put it into the global list */
16160 + strcpy(new_client->name, client_name);
16162 + new_client->id = fscscy_id++;
16164 + init_MUTEX(&data->update_lock);
16166 + /* Tell the I2C layer a new client has arrived */
16167 + if ((err = i2c_attach_client(new_client)))
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) {
16176 + data->sysctl_id = i;
16178 + fscscy_init_client(new_client);
16181 +/* OK, this is not exactly good programming practice, usually. But it is
16182 + very code-efficient in this case. */
16184 + i2c_detach_client(new_client);
16192 +static int fscscy_detach_client(struct i2c_client *client)
16196 + i2c_deregister_entry(((struct fscscy_data *) (client->data))->
16199 + if ((err = i2c_detach_client(client))) {
16201 + ("fscscy.o: Client deregistration failed, client not detached.\n");
16205 + kfree(client->data);
16210 +static int fscscy_read_value(struct i2c_client *client, u8 reg)
16213 + printk("fscscy: read reg 0x%02x\n",reg);
16215 + return i2c_smbus_read_byte_data(client, reg);
16218 +static int fscscy_write_value(struct i2c_client *client, u8 reg, u8 value)
16221 + printk("fscscy: write reg 0x%02x, val 0x%02x\n",reg, value);
16223 + return i2c_smbus_write_byte_data(client, reg, value);
16226 +/* Called when we have found a new FSCSCY. It should set limits, etc. */
16227 +static void fscscy_init_client(struct i2c_client *client)
16229 + struct fscscy_data *data = client->data;
16231 + /* read revision from chip */
16232 + data->revision = fscscy_read_value(client,FSCSCY_REG_REVISION);
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);
16250 +static void fscscy_update_client(struct i2c_client *client)
16252 + struct fscscy_data *data = client->data;
16254 + down(&data->update_lock);
16256 + if ((jiffies - data->last_updated > 2 * HZ) ||
16257 + (jiffies < data->last_updated) || !data->valid) {
16260 + printk("Starting fscscy update\n");
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);
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];
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);
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);
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);
16340 + data->last_updated = jiffies;
16344 + up(&data->update_lock);
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)
16364 + struct fscscy_data *data = client->data;
16366 + if (operation == SENSORS_PROC_REAL_INFO)
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 ;
16374 + case FSCSCY_SYSCTL_EVENT:
16375 + results[0] = data->global_event & 0x9f; /* MKN */
16377 + case FSCSCY_SYSCTL_CONTROL:
16378 + results[0] = data->global_control & 0x19; /* MKN */
16381 + printk("fscscy: ctl_name %d not supported\n",
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);
16396 + printk("fscscy: writing to chip not supported\n");
16400 +#define TEMP_FROM_REG(val) (val-128)
16403 +void fscscy_temp(struct i2c_client *client, int operation, int ctl_name,
16404 + int *nrels_mag, long *results)
16406 + struct fscscy_data *data = client->data;
16408 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
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]);
16442 + printk("fscscy: ctl_name %d not supported\n",
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);
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);
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);
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);
16481 + printk("fscscy: ctl_name %d not supported\n",ctl_name);
16485 + printk("fscscy: writing to chip not supported\n");
16489 +#define VOLT_FROM_REG(val,mult) (val*mult/255)
16491 +void fscscy_volt(struct i2c_client *client, int operation, int ctl_name,
16492 + int *nrels_mag, long *results)
16494 + struct fscscy_data *data = client->data;
16495 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
16516 + printk("fscscy: ctl_name %d not supported\n",
16522 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
16523 + printk("fscscy: writing to chip not supported\n");
16527 +void fscscy_fan(struct i2c_client *client, int operation, int ctl_name,
16528 + int *nrels_mag, long *results)
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);
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);
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);
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);
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);
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);
16563 + printk("fscscy: illegal fan nr %d\n",ctl_name);
16567 +#define RPM_FROM_REG(val) (val*60)
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 )
16573 + struct fscscy_data *data = client->data;
16575 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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);
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]);
16605 + if(*nrels_mag >= 3) {
16606 + if((results[2] & 0x03) == 0) {
16607 + printk("fscscy: fan%d ripple 0 is nonsense/not allowed\n",nr);
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]);
16619 +void fscscy_wdog(struct i2c_client *client, int operation, int ctl_name,
16620 + int *nrels_mag, long *results)
16622 + struct fscscy_data *data = client->data;
16624 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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]);
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]);
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]);
16657 +void fscscy_pciload(struct i2c_client *client, int operation, int ctl_name,
16658 + int *nrels_mag, long *results)
16660 + struct fscscy_data *data = client->data;
16661 + if (operation == SENSORS_PROC_REAL_INFO)
16663 + else if (operation == SENSORS_PROC_REAL_READ) {
16664 + fscscy_update_client(client);
16665 + results[0] = data->pciload;
16667 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
16668 + printk("fscscy: writing PCILOAD to chip not supported\n");
16672 +void fscscy_intrusion(struct i2c_client *client, int operation, int ctl_name,
16673 + int *nrels_mag, long *results)
16675 + struct fscscy_data *data = client->data;
16677 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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);
16695 +static int __init sm_fscscy_init(void)
16697 + printk("fscscy.o version %s (%s)\n", LM_VERSION, LM_DATE);
16698 + return i2c_add_driver(&fscscy_driver);
16701 +static void __exit sm_fscscy_exit(void)
16703 + i2c_del_driver(&fscscy_driver);
16709 + ("Martin Knoblauch <mkn@teraport.de> based on work (fscpos) from Hermann Jung <hej@odn.de>");
16710 +MODULE_DESCRIPTION("fujitsu siemens scylla chip driver");
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
16718 + gl518sm.c - Part of lm_sensors, Linux kernel modules for hardware
16720 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>,
16721 + Kyösti Mälkki <kmalkki@cc.hut.fi>
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.
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.
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.
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>
16745 +#include <linux/smp_lock.h>
16747 +#define LM_DATE "20041007"
16748 +#define LM_VERSION "2.8.8"
16750 +MODULE_LICENSE("GPL");
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 };
16758 +/* Insmod parameters */
16759 +SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80);
16761 +/* Defining this will enable debug messages for the voltage iteration
16762 + code used with rev 0 ICs */
16765 +/* Many GL518 constants specified below */
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
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. */
16796 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-5:(val)+5) / 10)+119),\
16798 +#define TEMP_FROM_REG(val) (((val) - 119) * 10)
16800 +static inline u8 FAN_TO_REG(long rpm, int div)
16804 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
16805 + return SENSORS_LIMIT((960000 + rpm * div / 2) / (rpm * div), 1,
16809 +#define FAN_FROM_REG(val,div) \
16810 + ( (val)==0 ? 0 : (val)==255 ? 0 : (960000/((val)*(div))) )
16812 +#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*10+8)/19),0,255))
16813 +#define IN_FROM_REG(val) (((val)*19)/10)
16815 +#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*10+11)/23),0,255))
16816 +#define VDD_FROM_REG(val) (((val)*23)/10)
16818 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
16819 +#define DIV_FROM_REG(val) (1 << (val))
16821 +#define ALARMS_FROM_REG(val) val
16823 +#define BEEP_ENABLE_TO_REG(val) ((val)?0:1)
16824 +#define BEEP_ENABLE_FROM_REG(val) ((val)?0:1)
16826 +#define BEEPS_TO_REG(val) ((val) & 0x7f)
16827 +#define BEEPS_FROM_REG(val) ((val) & 0x7f)
16829 +/* Each client has this additional data */
16830 +struct gl518_data {
16831 + struct i2c_client client;
16835 + struct semaphore update_lock;
16837 + int iterate_lock;
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) */
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 */
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 */
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);
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);
16872 +static void gl518_update_client_rev00(struct i2c_client *client);
16873 +static void gl518_update_iterate(struct i2c_client *client);
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);
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,
16902 +/* -- SENSORS SYSCTL START -- */
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
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
16925 +/* -- SENSORS SYSCTL END -- */
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},
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];
16966 +static int gl518_attach_adapter(struct i2c_adapter *adapter)
16968 + return i2c_detect(adapter, &addr_data, gl518_detect);
16971 +static int gl518_detect(struct i2c_adapter *adapter, int address,
16972 + unsigned short flags, int kind)
16975 + struct i2c_client *new_client;
16976 + struct gl518_data *data;
16978 + const char *type_name = "";
16979 + const char *client_name = "";
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. */
16984 + if (i2c_is_isa_adapter(adapter)) {
16986 + ("gl518sm.o: gl518_detect called for an ISA bus adapter?!?\n");
16991 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
16992 + I2C_FUNC_SMBUS_WORD_DATA))
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. */
16999 + if (!(data = kmalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
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;
17011 + /* Now, we do the remaining detection. */
17015 + (gl518_read_value(new_client, GL518_REG_CHIP_ID) !=
17017 + || (gl518_read_value(new_client, GL518_REG_CONF) &
17018 + 0x80)) goto ERROR1;
17021 + /* Determine the chip type. */
17023 + i = gl518_read_value(new_client, GL518_REG_REVISION);
17025 + kind = gl518sm_r00;
17026 + else if (i == 0x80)
17027 + kind = gl518sm_r80;
17031 + ("gl518sm.o: Ignoring 'force' parameter for unknown chip at "
17032 + "adapter %d, address 0x%02x\n",
17033 + i2c_adapter_id(adapter), address);
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";
17045 + printk("gl518sm.o: Internal error: unknown kind (%d)?!?",
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;
17055 + for (i = 0; i < MAX_GL518_NR; i++)
17056 + if (!gl518_list[i])
17058 + if (i == MAX_GL518_NR) {
17060 + ("gl518sm.o: No empty slots left, recompile and heighten "
17061 + "MAX_GL518_NR!\n");
17065 + gl518_list[i] = new_client;
17066 + new_client->id = i;
17068 + init_MUTEX(&data->update_lock);
17070 + /* Tell the I2C layer a new client has arrived */
17071 + if ((err = i2c_attach_client(new_client)))
17074 + /* Register a new directory entry with module sensors */
17075 + if ((i = i2c_register_entry((struct i2c_client *) new_client,
17077 + gl518_dir_table_template)) < 0) {
17081 + data->sysctl_id = i;
17083 + /* Initialize the GL518SM chip */
17084 + if (kind == gl518sm_r00)
17085 + data->iterate = 0;
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);
17096 +/* OK, this is not exactly good programming practice, usually. But it is
17097 + very code-efficient in this case. */
17100 + i2c_detach_client(new_client);
17102 + for (i = 0; i < MAX_GL518_NR; i++)
17103 + if (new_client == gl518_list[i])
17104 + gl518_list[i] = NULL;
17113 +/* Called when we have found a new GL518SM. It should set limits, etc. */
17114 +static void gl518_init_client(struct i2c_client *client)
17116 + /* Power-on defaults (bit 7=1) */
17117 + gl518_write_value(client, GL518_REG_CONF, 0x80);
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);
17123 + /* Never interrupts */
17124 + gl518_write_value(client, GL518_REG_MASK, 0x00);
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);
17131 +static int gl518_detach_client(struct i2c_client *client)
17134 + struct gl518_data *data = client->data;
17136 + i2c_deregister_entry(((struct gl518_data *) (client->data))->
17139 + if ((err = i2c_detach_client(client))) {
17141 + ("gl518sm.o: Client deregistration failed, client not detached.\n");
17145 + for (i = 0; i < MAX_GL518_NR; i++)
17146 + if (client == gl518_list[i])
17148 + if ((i == MAX_GL518_NR)) {
17149 + printk("gl518sm.o: Client to detach not found.\n");
17152 + gl518_list[i] = NULL;
17154 + if (data->thread) {
17155 + data->quit_thread = 1;
17156 + wake_up_interruptible(&data->wq);
17159 + kfree(client->data);
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)
17170 + if ((reg >= 0x07) && (reg <= 0x0c))
17171 + return swab16(i2c_smbus_read_word_data(client, reg));
17173 + return i2c_smbus_read_byte_data(client, reg);
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)
17181 + if ((reg >= 0x07) && (reg <= 0x0c))
17182 + return i2c_smbus_write_word_data(client, reg, swab16(value));
17184 + return i2c_smbus_write_byte_data(client, reg, value);
17187 +static void gl518_update_client(struct i2c_client *client)
17189 + struct gl518_data *data = client->data;
17192 + down(&data->update_lock);
17194 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
17195 + (jiffies < data->last_updated) || !data->valid) {
17198 + printk("Starting gl518 update\n");
17201 + data->alarms = gl518_read_value(client, GL518_REG_INT);
17202 + data->beeps = gl518_read_value(client, GL518_REG_ALARM);
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;
17217 + val = gl518_read_value(client, GL518_REG_FAN_COUNT);
17218 + data->fan[0] = (val >> 8) & 0xff;
17219 + data->fan[1] = val & 0xff;
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;
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);
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;
17235 + data->alarms &= data->alarm_mask;
17237 + val = gl518_read_value(client, GL518_REG_CONF);
17238 + data->beep_enable = (val >> 2) & 1;
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);
17251 + gl518_update_client_rev00(client);
17253 + gl518_update_client_rev00(client);
17256 + data->last_updated = jiffies;
17260 + up(&data->update_lock);
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)
17268 + struct gl518_data *data = client->data;
17271 + if (data->iterate == 1) { /* 10 sec delay */
17272 + /* as that update is slow, we consider the data valid for 30 seconds */
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;
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);
17293 +static int gl518_update_thread(void *c)
17295 + struct i2c_client *client = c;
17296 + struct gl518_data *data = client->data;
17301 + exit_mm(current);
17302 + current->session = 1;
17303 + current->pgrp = 1;
17304 + sigfillset(¤t->blocked);
17305 + current->fs->umask = 0;
17306 + strcpy(current->comm, "gl518sm");
17308 + init_waitqueue_head(&(data->wq));
17309 + data->thread = current;
17316 + if (!data->iterate_lock) {
17317 + data->iterate_lock = 1;
17318 + gl518_update_iterate(client);
17319 + data->iterate_lock = 0;
17322 + if ((data->quit_thread) || signal_pending(current))
17324 + interruptible_sleep_on(&data->wq);
17327 + data->thread = NULL;
17328 + data->quit_thread = 0;
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 */
17336 +static void gl518_update_iterate(struct i2c_client *client)
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;
17342 +#define VIN_REG(c) c==0?GL518_REG_VDD_LIMIT:\
17343 + c==1?GL518_REG_VIN1_LIMIT:\
17344 + GL518_REG_VIN2_LIMIT
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);
17352 + alarm = data->alarms;
17354 + for (i = 0; i < 3; i++) {
17355 + if (alarm & (1 << i)) {
17359 + min[i] = data->voltage_min[i];
17361 + (data->voltage_max[i] +
17362 + data->voltage_min[i]) / 2;
17364 + delta[i] = (max[i] - min[i]) / 2;
17367 + for (j = 0; (j < 10 && loop_more); j++) {
17369 + for (i = 0; i < 3; i++)
17370 + gl518_write_value(client, VIN_REG(i),
17371 + max[i] << 8 | min[i]);
17373 + if ((data->thread) &&
17374 + ((data->quit_thread) || signal_pending(current)))
17377 + /* we wait now 1.5 seconds before comparing */
17378 + current->state = TASK_INTERRUPTIBLE;
17379 + schedule_timeout(HZ + HZ / 2);
17381 + alarm = gl518_read_value(client, GL518_REG_INT);
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) ? '!' : ' ');
17390 + for (loop_more = 0, i = 0; i < 3; i++) {
17391 + if (alarm & (1 << i))
17392 + max[i] += delta[i];
17394 + max[i] -= delta[i];
17403 + for (i = 0; i < 3; i++)
17404 + if (alarm & (1 << i))
17408 + printk("gl518sm: final :%5d %5d %5d\n", max[0], max[1],
17410 + printk("gl518sm: meter :%5d %5d %5d\n", data->voltage[0],
17411 + data->voltage[1], data->voltage[2]);
17414 + /* update values, including vin3 */
17415 + for (i = 0; i < 3; i++) {
17416 + data->iter_voltage[i] = max[i];
17418 + data->iter_voltage[3] = gl518_read_value(client, GL518_REG_VIN3);
17419 + data->last_updated_v00 = jiffies;
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->
17430 + gl518_write_value(client, GL518_REG_ALARM, beeps);
17431 + gl518_write_value(client, GL518_REG_MASK, irqs);
17436 +void gl518_temp(struct i2c_client *client, int operation, int ctl_name,
17437 + int *nrels_mag, long *results)
17439 + struct gl518_data *data = client->data;
17440 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
17462 +void gl518_vin(struct i2c_client *client, int operation, int ctl_name,
17463 + int *nrels_mag, long *results)
17465 + struct gl518_data *data = client->data;
17466 + int nr = ctl_name - GL518_SYSCTL_VDD;
17467 + int regnr, old = 0;
17469 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
17480 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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;
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);
17504 +void gl518_fan(struct i2c_client *client, int operation, int ctl_name,
17505 + int *nrels_mag, long *results)
17507 + struct gl518_data *data = client->data;
17508 + int nr = ctl_name - GL518_SYSCTL_FAN1;
17511 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
17518 + FAN_FROM_REG(data->fan[nr],
17519 + DIV_FROM_REG(data->fan_div[nr]));
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->
17528 + gl518_read_value(client, GL518_REG_FAN_LIMIT);
17532 + (old & 0x00ff) | (data->
17533 + fan_min[0] << 8);
17534 + if (results[0] == 0)
17535 + data->alarm_mask &= ~0x20;
17537 + data->alarm_mask |= 0x20;
17539 + old = (old & 0xff00) | data->fan_min[1];
17540 + if (results[0] == 0)
17541 + data->alarm_mask &= ~0x40;
17543 + data->alarm_mask |= 0x40;
17545 + gl518_write_value(client, GL518_REG_FAN_LIMIT,
17552 +void gl518_alarms(struct i2c_client *client, int operation, int ctl_name,
17553 + int *nrels_mag, long *results)
17555 + struct gl518_data *data = client->data;
17556 + if (operation == SENSORS_PROC_REAL_INFO)
17558 + else if (operation == SENSORS_PROC_REAL_READ) {
17559 + gl518_update_client(client);
17560 + results[0] = ALARMS_FROM_REG(data->alarms);
17565 +void gl518_beep(struct i2c_client *client, int operation, int ctl_name,
17566 + int *nrels_mag, long *results)
17568 + struct gl518_data *data = client->data;
17569 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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,
17582 + & 0xfb) | (data->
17583 + beep_enable << 2));
17585 + if (*nrels_mag >= 2) {
17587 + BEEPS_TO_REG(results[1]) & data->alarm_mask;
17588 + gl518_write_value(client, GL518_REG_ALARM,
17595 +void gl518_fan_div(struct i2c_client *client, int operation, int ctl_name,
17596 + int *nrels_mag, long *results)
17598 + struct gl518_data *data = client->data;
17600 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
17613 + if (*nrels_mag >= 1) {
17614 + data->fan_div[0] = DIV_TO_REG(results[0]);
17615 + old = (old & 0x3f) | (data->fan_div[0] << 6);
17617 + gl518_write_value(client, GL518_REG_MISC, old);
17621 +void gl518_fan1off(struct i2c_client *client, int operation, int ctl_name,
17622 + int *nrels_mag, long *results)
17625 + if (operation == SENSORS_PROC_REAL_INFO)
17627 + else if (operation == SENSORS_PROC_REAL_READ) {
17629 + ((gl518_read_value(client, GL518_REG_MISC) & 0x08) !=
17632 + ((gl518_read_value(client, GL518_REG_CONF) & 0x10) !=
17635 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
17636 + if (*nrels_mag >= 1) {
17638 + gl518_read_value(client,
17639 + GL518_REG_MISC) & 0xf7;
17642 + gl518_write_value(client, GL518_REG_MISC, old);
17644 + if (*nrels_mag >= 2) {
17646 + gl518_read_value(client,
17647 + GL518_REG_CONF) & 0xef;
17650 + gl518_write_value(client, GL518_REG_CONF, old);
17655 +void gl518_iterate(struct i2c_client *client, int operation, int ctl_name,
17656 + int *nrels_mag, long *results)
17658 + struct gl518_data *data = client->data;
17660 + if (operation == SENSORS_PROC_REAL_INFO)
17662 + else if (operation == SENSORS_PROC_REAL_READ) {
17663 + results[0] = data->iterate;
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;
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);
17687 +static int __init sm_gl518sm_init(void)
17689 + printk("gl518sm.o version %s (%s)\n", LM_VERSION, LM_DATE);
17690 + return i2c_add_driver(&gl518_driver);
17693 +static void __exit sm_gl518sm_exit(void)
17695 + i2c_del_driver(&gl518_driver);
17701 + ("Frodo Looijaard <frodol@dds.nl> and Kyösti Mälkki <kmalkki@cc.hut.fi>");
17702 +MODULE_DESCRIPTION("GL518SM driver");
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
17710 + gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
17712 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>,
17713 + Kyösti Mälkki <kmalkki@cc.hut.fi>
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.
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.
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.
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"
17739 +MODULE_LICENSE("GPL");
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 };
17747 +/* Insmod parameters */
17748 +SENSORS_INSMOD_1(gl520sm);
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
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
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. */
17790 +#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-5:(val)+5) / 10)+130),\
17792 +#define TEMP_FROM_REG(val) (((val) - 130) * 10)
17794 +static inline u8 FAN_TO_REG(long rpm, int div)
17798 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
17799 + return SENSORS_LIMIT((960000 + rpm * div / 2) / (rpm * div), 1,
17803 +#define FAN_FROM_REG(val,div) \
17804 + ( (val)==0 ? 0 : (val)==255 ? 0 : (960000/((val)*(div))) )
17806 +#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*10+8)/19),0,255))
17807 +#define IN_FROM_REG(val) (((val)*19)/10)
17809 +#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*10+11)/23),0,255))
17810 +#define VDD_FROM_REG(val) (((val)*23)/10)
17812 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
17813 +#define DIV_FROM_REG(val) (1 << (val))
17815 +#define ALARMS_FROM_REG(val) val
17817 +#define BEEP_ENABLE_TO_REG(val) ((val)?0:1)
17818 +#define BEEP_ENABLE_FROM_REG(val) ((val)?0:1)
17820 +#define BEEPS_TO_REG(val) (val)
17821 +#define BEEPS_FROM_REG(val) (val)
17823 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
17826 +/* Each client has this additional data */
17827 +struct gl520_data {
17828 + struct i2c_client client;
17832 + struct semaphore update_lock;
17833 + char valid; /* !=0 if following fields are valid */
17834 + unsigned long last_updated; /* In jiffies */
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 */
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 */
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);
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);
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);
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,
17889 +/* -- SENSORS SYSCTL START -- */
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
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
17917 +/* -- SENSORS SYSCTL END -- */
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},
17958 +static int gl520_id = 0;
17960 +static int gl520_attach_adapter(struct i2c_adapter *adapter)
17962 + return i2c_detect(adapter, &addr_data, gl520_detect);
17965 +static int gl520_detect(struct i2c_adapter *adapter, int address,
17966 + unsigned short flags, int kind)
17969 + struct i2c_client *new_client;
17970 + struct gl520_data *data;
17972 + const char *type_name = "";
17973 + char client_name[32];
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. */
17978 + if (i2c_is_isa_adapter(adapter)) {
17980 + ("gl520sm.o: gl520_detect called for an ISA bus adapter?!?\n");
17985 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
17986 + I2C_FUNC_SMBUS_WORD_DATA))
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. */
17993 + if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
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;
18005 + /* Determine the chip type. */
18007 + if (gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) {
18009 + ("gl520sm.o: Ignoring 'force' parameter for unknown chip at "
18010 + "adapter %d, address 0x%02x\n",
18011 + i2c_adapter_id(adapter), address);
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);
18023 + printk("gl520sm.o: Internal error: unknown kind (%d)?!?",
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;
18033 + new_client->id = gl520_id++;
18035 + init_MUTEX(&data->update_lock);
18037 + /* Tell the I2C layer a new client has arrived */
18038 + if ((err = i2c_attach_client(new_client)))
18041 + /* Register a new directory entry with module sensors */
18042 + if ((i = i2c_register_entry(new_client,
18044 + gl520_dir_table_template)) < 0) {
18048 + data->sysctl_id = i;
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;
18057 + data->temp_hyst[1] = data->temp_over[1] =
18058 + data->temp[1] = 0;
18062 +/* OK, this is not exactly good programming practice, usually. But it is
18063 + very code-efficient in this case. */
18066 + i2c_detach_client(new_client);
18075 +/* Called when we have found a new GL520SM. */
18076 +static void gl520_init_client(struct i2c_client *client)
18078 + struct gl520_data *data = (struct gl520_data *)(client->data);
18079 + u8 oldconf, conf;
18081 + conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
18082 + data->two_temps = !(conf & 0x10);
18084 + /* If IRQ# is disabled, we can safely force comparator mode */
18085 + if (!(conf & 0x20))
18088 + /* Enable monitoring if needed */
18091 + if (conf != oldconf)
18092 + gl520_write_value(client, GL520_REG_CONF, conf);
18095 +static int gl520_detach_client(struct i2c_client *client)
18099 + i2c_deregister_entry(((struct gl520_data *) (client->data))->
18102 + if ((err = i2c_detach_client(client))) {
18104 + ("gl520sm.o: Client deregistration failed, client not detached.\n");
18108 + kfree(client->data);
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)
18119 + if ((reg >= 0x07) && (reg <= 0x0c))
18120 + return swab16(i2c_smbus_read_word_data(client, reg));
18122 + return i2c_smbus_read_byte_data(client, reg);
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)
18130 + if ((reg >= 0x07) && (reg <= 0x0c))
18131 + return i2c_smbus_write_word_data(client, reg, swab16(value));
18133 + return i2c_smbus_write_byte_data(client, reg, value);
18136 +static void gl520_update_client(struct i2c_client *client)
18138 + struct gl520_data *data = client->data;
18141 + down(&data->update_lock);
18143 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
18144 + (jiffies < data->last_updated) || !data->valid) {
18147 + printk("Starting gl520 update\n");
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;
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;
18167 + val = gl520_read_value(client, GL520_REG_FAN_COUNT);
18168 + data->fan[0] = (val >> 8) & 0xff;
18169 + data->fan[1] = val & 0xff;
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;
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);
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;
18185 + data->alarms &= data->alarm_mask;
18187 + val = gl520_read_value(client, GL520_REG_CONF);
18188 + data->beep_enable = (val >> 2) & 1;
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);
18198 + /* Temp1 and Vin4 are the same input */
18199 + if (data->two_temps) {
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);
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);
18215 + data->last_updated = jiffies;
18219 + up(&data->update_lock);
18222 +void gl520_temp(struct i2c_client *client, int operation, int ctl_name,
18223 + int *nrels_mag, long *results)
18225 + struct gl520_data *data = client->data;
18226 + int nr = ctl_name - GL520_SYSCTL_TEMP1;
18229 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
18237 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
18238 + if ((nr == 1) && (!data->two_temps))
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]);
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]);
18257 +void gl520_vin(struct i2c_client *client, int operation, int ctl_name,
18258 + int *nrels_mag, long *results)
18260 + struct gl520_data *data = client->data;
18261 + int nr = ctl_name - GL520_SYSCTL_VDD;
18262 + int regnr, old = 0;
18264 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
18275 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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)
18284 + gl520_read_value(client,
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;
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);
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]));
18313 +void gl520_fan(struct i2c_client *client, int operation, int ctl_name,
18314 + int *nrels_mag, long *results)
18316 + struct gl520_data *data = client->data;
18317 + int nr = ctl_name - GL520_SYSCTL_FAN1;
18320 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
18327 + FAN_FROM_REG(data->fan[nr],
18328 + DIV_FROM_REG(data->fan_div[nr]));
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->
18337 + gl520_read_value(client, GL520_REG_FAN_LIMIT);
18341 + (old & 0x00ff) | (data->
18342 + fan_min[nr] << 8);
18343 + if (results[0] == 0)
18344 + data->alarm_mask &= ~0x20;
18346 + data->alarm_mask |= 0x20;
18348 + old = (old & 0xff00) | data->fan_min[nr];
18349 + if (results[0] == 0)
18350 + data->alarm_mask &= ~0x40;
18352 + data->alarm_mask |= 0x40;
18354 + gl520_write_value(client, GL520_REG_FAN_LIMIT,
18361 +void gl520_alarms(struct i2c_client *client, int operation, int ctl_name,
18362 + int *nrels_mag, long *results)
18364 + struct gl520_data *data = client->data;
18365 + if (operation == SENSORS_PROC_REAL_INFO)
18367 + else if (operation == SENSORS_PROC_REAL_READ) {
18368 + gl520_update_client(client);
18369 + results[0] = ALARMS_FROM_REG(data->alarms);
18374 +void gl520_beep(struct i2c_client *client, int operation, int ctl_name,
18375 + int *nrels_mag, long *results)
18377 + struct gl520_data *data = client->data;
18378 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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,
18391 + & 0xfb) | (data->
18392 + beep_enable << 2));
18394 + if (*nrels_mag >= 2) {
18396 + BEEPS_TO_REG(results[1]) & data->alarm_mask;
18397 + gl520_write_value(client, GL520_REG_ALARM,
18404 +void gl520_fan_div(struct i2c_client *client, int operation, int ctl_name,
18405 + int *nrels_mag, long *results)
18407 + struct gl520_data *data = client->data;
18409 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
18422 + if (*nrels_mag >= 1) {
18423 + data->fan_div[0] = DIV_TO_REG(results[0]);
18424 + old = (old & 0x3f) | (data->fan_div[0] << 6);
18426 + gl520_write_value(client, GL520_REG_MISC, old);
18430 +void gl520_vid(struct i2c_client *client, int operation, int ctl_name,
18431 + int *nrels_mag, long *results)
18433 + struct gl520_data *data = client->data;
18434 + if (operation == SENSORS_PROC_REAL_INFO)
18436 + else if (operation == SENSORS_PROC_REAL_READ) {
18437 + gl520_update_client(client);
18438 + results[0] = VID_FROM_REG(data->vid);
18443 +void gl520_fan1off(struct i2c_client *client, int operation, int ctl_name,
18444 + int *nrels_mag, long *results)
18447 + if (operation == SENSORS_PROC_REAL_INFO)
18449 + else if (operation == SENSORS_PROC_REAL_READ) {
18451 + ((gl520_read_value(client, GL520_REG_MISC) & 0x04) !=
18454 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
18455 + if (*nrels_mag >= 1) {
18457 + gl520_read_value(client,
18458 + GL520_REG_MISC) & 0xfb;
18461 + gl520_write_value(client, GL520_REG_MISC, old);
18466 +void gl520_config(struct i2c_client *client, int operation, int ctl_name,
18467 + int *nrels_mag, long *results)
18469 + struct gl520_data *data = client->data;
18471 + if (operation == SENSORS_PROC_REAL_INFO)
18473 + else if (operation == SENSORS_PROC_REAL_READ) {
18475 + ((gl520_read_value(client, GL520_REG_CONF) & 0x10) ==
18477 + data->two_temps = results[0];
18479 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
18480 + if (*nrels_mag >= 1) {
18482 + gl520_read_value(client,
18483 + GL520_REG_CONF) & 0xef;
18484 + if (!results[1]) {
18486 + data->two_temps = 0;
18487 + data->temp_hyst[1] = data->temp_over[1] =
18488 + data->temp[1] = 0;
18490 + data->two_temps = 1;
18491 + data->voltage_max[4] = data->voltage_min[4] =
18492 + data->voltage[4] = 0;
18494 + gl520_write_value(client, GL520_REG_CONF, old);
18499 +static int __init sm_gl520sm_init(void)
18501 + printk("gl520sm.o version %s (%s)\n", LM_VERSION, LM_DATE);
18502 + return i2c_add_driver(&gl520_driver);
18505 +static void __exit sm_gl520sm_exit(void)
18507 + i2c_del_driver(&gl520_driver);
18513 + ("Frodo Looijaard <frodol@dds.nl> and Kyösti Mälkki <kmalkki@cc.hut.fi>");
18514 +MODULE_DESCRIPTION("GL520SM driver");
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
18522 + it87.c - Part of lm_sensors, Linux kernel modules for hardware
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
18529 + Copyright (c) 2001 Chris Gauthron <chrisg@0-in.com>
18530 + Largely inspired by lm78.c of the same package
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.
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.
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.
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.
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.
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"
18571 +MODULE_LICENSE("GPL");
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 };
18579 +/* Insmod parameters */
18580 +SENSORS_INSMOD_4(it87, it8705, it8712, sis950);
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 */
18589 +static inline void
18590 +superio_outb(int reg, int val)
18597 +superio_inb(int reg)
18603 +static inline void
18604 +superio_select(void)
18610 +static inline void
18611 +superio_enter(void)
18619 +static inline void
18620 +superio_exit(void)
18626 +/* just IT8712F for now - this should be extended to support the other
18628 +#define IT87_DEVID_MATCH(id) ((id) == 0x8712)
18630 +#define IT87_ACT_REG 0x30
18631 +#define IT87_BASE_REG 0x60
18633 +/* Update battery voltage after every reading if true */
18634 +static int update_vbat = 0;
18636 +/* Reset the registers on init */
18637 +static int reset = 0;
18639 +/* Many IT87 constants specified below */
18641 +/* Length of ISA address segment */
18642 +#define IT87_EXTENT 8
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
18648 +/*----- The IT87 registers -----*/
18650 +#define IT87_REG_CONFIG 0x00
18652 +#define IT87_REG_ALARM1 0x01
18653 +#define IT87_REG_ALARM2 0x02
18654 +#define IT87_REG_ALARM3 0x03
18656 +#define IT87_REG_VID 0x0a
18657 +#define IT87_REG_FAN_DIV 0x0b
18659 +#define IT87_REG_FAN(nr) (0x0c + (nr))
18660 +#define IT87_REG_FAN_MIN(nr) (0x0f + (nr))
18661 +#define IT87_REG_FAN_CTRL 0x13
18663 +/* pwm and smart guardian registers */
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)
18676 +/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
18678 +#define IT87_REG_VIN(nr) (0x20 + (nr))
18679 +#define IT87_REG_TEMP(nr) (0x28 + (nr))
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)
18686 +#define IT87_REG_I2C_ADDR 0x48
18688 +#define IT87_REG_VIN_ENABLE 0x50
18689 +#define IT87_REG_TEMP_ENABLE 0x51
18691 +#define IT87_REG_CHIPID 0x58
18693 +/* sensor pin types */
18695 +#define THERMISTOR 2
18696 +#define PIIDIODE 3
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)
18705 +static inline u8 FAN_TO_REG(long rpm, int div)
18709 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
18710 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
18714 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
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)
18720 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
18722 +#define ALARMS_FROM_REG(val) (val)
18724 +extern inline u8 DIV_TO_REG(long val)
18727 + for( i = 0; i <= 7; i++ )
18729 + if( val>>i == 1 )
18734 +#define DIV_FROM_REG(val) (1 << (val))
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
18740 +struct it87_data {
18741 + struct i2c_client client;
18742 + struct semaphore lock;
18746 + struct semaphore update_lock;
18747 + char valid; /* !=0 if following fields are valid */
18748 + unsigned long last_updated; /* In jiffies */
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 */
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);
18776 +static int it87_read_value(struct i2c_client *client, u8 register);
18777 +static int it87_write_value(struct i2c_client *client, u8 register,
18779 +static void it87_update_client(struct i2c_client *client);
18780 +static void it87_init_client(struct i2c_client *client);
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);
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,
18815 +static int it87_id = 0;
18817 +/* The /proc/sys entries */
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 */
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
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
18863 +/* -- SENSORS SYSCTL END -- */
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},
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)
18945 + return i2c_detect(adapter, &addr_data, it87_detect);
18948 +static int it87_find(int *address)
18953 + val = (superio_inb(DEVID) << 8) |
18954 + superio_inb(DEVID + 1);
18955 + if (!IT87_DEVID_MATCH(val)) {
18960 + superio_select();
18961 + val = (superio_inb(IT87_BASE_REG) << 8) |
18962 + superio_inb(IT87_BASE_REG + 1);
18964 + *address = val & ~(IT87_EXTENT - 1);
18965 + if (*address == 0) {
18971 +/* This function is called by i2c_detect */
18972 +int it87_detect(struct i2c_adapter *adapter, int address,
18973 + unsigned short flags, int kind)
18976 + struct i2c_client *new_client;
18977 + struct it87_data *data;
18979 + const char *type_name = "";
18980 + const char *client_name = "";
18981 + int is_isa = i2c_is_isa_adapter(adapter);
18984 + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
18988 + && check_region(address, IT87_EXTENT))
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)
19002 +#undef REALLY_SLOW_IO
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);
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. */
19017 + if (!(data = kmalloc(sizeof(struct it87_data), GFP_KERNEL))) {
19022 + new_client = &data->client;
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;
19031 + /* Now, we do the remaining detection. */
19034 + if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
19036 + && it87_read_value(new_client, IT87_REG_I2C_ADDR) != address)) {
19042 + /* Determine the chip type. */
19044 + i = it87_read_value(new_client, IT87_REG_CHIPID);
19051 + ("it87.o: Ignoring 'force' parameter for unknown chip at "
19052 + "adapter %d, address 0x%02x\n",
19053 + i2c_adapter_id(adapter), address);
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";
19067 + printk("it87.o: Internal error: unknown kind (%d)?!?",
19073 + /* Reserve the ISA region */
19075 + request_region(address, IT87_EXTENT, type_name);
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;
19081 + new_client->id = it87_id++;
19083 + init_MUTEX(&data->update_lock);
19085 + /* Tell the I2C layer a new client has arrived */
19086 + if ((err = i2c_attach_client(new_client)))
19089 + /* Register a new directory entry with module sensors */
19090 + if ((i = i2c_register_entry(new_client,
19092 + it87_dir_table_template)) < 0) {
19096 + data->sysctl_id = i;
19098 + /* Initialize the IT87 chip */
19099 + it87_init_client(new_client);
19102 +/* OK, this is not exactly good programming practice, usually. But it is
19103 + very code-efficient in this case. */
19106 + i2c_detach_client(new_client);
19109 + release_region(address, IT87_EXTENT);
19116 +static int it87_detach_client(struct i2c_client *client)
19120 + i2c_deregister_entry(((struct it87_data *) (client->data))->
19123 + if ((err = i2c_detach_client(client))) {
19125 + ("it87.o: Client deregistration failed, client not detached.\n");
19129 + if(i2c_is_isa_client(client))
19130 + release_region(client->addr, IT87_EXTENT);
19131 + kfree(client->data);
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
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)
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));
19153 + return i2c_smbus_read_byte_data(client, reg);
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
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)
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));
19172 + return i2c_smbus_write_byte_data(client, reg, value);
19175 +/* Called when we have found a new IT87. */
19176 +static void it87_init_client(struct i2c_client *client)
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);
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);
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);
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);
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));
19215 +static void it87_update_client(struct i2c_client *client)
19217 + struct it87_data *data = client->data;
19218 + int i, tmp, tmp2;
19220 + down(&data->update_lock);
19222 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
19223 + (jiffies < data->last_updated) || !data->valid) {
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);
19231 + for (i = 0; i <= 7; 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));
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;
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));
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));
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;
19267 + data->vid = 0x1f;
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 );
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));
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);
19293 + tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
19294 + for(i = 0; i < 3; i++) {
19295 + tmp2 = (tmp >> i) & 0x09;
19297 + data->sens[i] = PIIDIODE;
19298 + else if(tmp2 == 0x08)
19299 + data->sens[i] = THERMISTOR;
19301 + data->sens[i] = UNUSED;
19304 + data->last_updated = jiffies;
19308 + up(&data->update_lock);
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)
19329 + struct it87_data *data = client->data;
19330 + int nr = ctl_name - IT87_SYSCTL_IN0;
19332 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
19354 +void it87_fan(struct i2c_client *client, int operation, int ctl_name,
19355 + int *nrels_mag, long *results)
19357 + struct it87_data *data = client->data;
19358 + int nr = ctl_name - IT87_SYSCTL_FAN1 + 1;
19360 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
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]);
19380 +void it87_temp(struct i2c_client *client, int operation, int ctl_name,
19381 + int *nrels_mag, long *results)
19383 + struct it87_data *data = client->data;
19384 + int nr = ctl_name - IT87_SYSCTL_TEMP1 + 1;
19385 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
19407 +void it87_pwm(struct i2c_client *client, int operation, int ctl_name,
19408 + int *nrels_mag, long *results)
19410 + struct it87_data *data = client->data;
19411 + int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
19412 + if (operation == SENSORS_PROC_REAL_INFO)
19414 + else if (operation == SENSORS_PROC_REAL_READ) {
19415 + it87_update_client(client);
19416 + results[0] = data->pwm[nr - 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]);
19426 +void it87_sgpwm(struct i2c_client *client, int operation, int ctl_name,
19427 + int *nrels_mag, long *results)
19429 + struct it87_data *data = client->data;
19430 + int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
19431 + if (operation == SENSORS_PROC_REAL_INFO)
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];
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]);
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]);
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]);
19455 +void it87_sgtl(struct i2c_client *client, int operation, int ctl_name,
19456 + int *nrels_mag, long *results)
19458 + struct it87_data *data = client->data;
19459 + int nr = ctl_name - IT87_SYSCTL_PWM1 + 1;
19460 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
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]);
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]);
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]);
19494 +void it87_vid(struct i2c_client *client, int operation, int ctl_name,
19495 + int *nrels_mag, long *results)
19497 + struct it87_data *data = client->data;
19498 + if (operation == SENSORS_PROC_REAL_INFO)
19500 + else if (operation == SENSORS_PROC_REAL_READ) {
19501 + it87_update_client(client);
19502 + results[0] = VID_FROM_REG(data->vid);
19507 +void it87_alarms(struct i2c_client *client, int operation,
19508 + int ctl_name, int *nrels_mag, long *results)
19510 + struct it87_data *data = client->data;
19511 + if (operation == SENSORS_PROC_REAL_INFO)
19513 + else if (operation == SENSORS_PROC_REAL_READ) {
19514 + it87_update_client(client);
19515 + results[0] = ALARMS_FROM_REG(data->alarms);
19520 +void it87_fan_div(struct i2c_client *client, int operation, int ctl_name,
19521 + int *nrels_mag, long *results)
19523 + struct it87_data *data = client->data;
19526 + if (operation == SENSORS_PROC_REAL_INFO)
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]);;
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);
19542 + old = (old | 0x40);
19545 + if (*nrels_mag >= 2) {
19546 + data->fan_div[1] = DIV_TO_REG(results[1]);
19547 + old = (old & 0xc3) | (data->fan_div[1] << 3);
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);
19557 +void it87_fan_ctl(struct i2c_client *client, int operation, int ctl_name,
19558 + int *nrels_mag, long *results)
19560 + struct it87_data *data = client->data;
19561 + int index = ctl_name - IT87_SYSCTL_FAN_CTL;
19562 + if (operation == SENSORS_PROC_REAL_INFO)
19564 + else if (operation == SENSORS_PROC_REAL_READ) {
19565 + it87_update_client(client);
19566 + results[0] = data->fan_ctl[index];
19568 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
19569 + if (*nrels_mag >= 1) {
19570 + data->fan_ctl[index] = results[0];
19572 + it87_write_value(client, IT87_REG_FAN_CTRL, data->fan_ctl[index] );
19574 + it87_write_value(client, IT87_REG_FAN_ONOFF, data->fan_ctl[index] );
19579 +void it87_sens(struct i2c_client *client, int operation, int ctl_name,
19580 + int *nrels_mag, long *results)
19582 + struct it87_data *data = client->data;
19583 + int nr = 1 + ctl_name - IT87_SYSCTL_SENS1;
19584 + u8 tmp, val1, val2;
19586 + if (operation == SENSORS_PROC_REAL_INFO)
19588 + else if (operation == SENSORS_PROC_REAL_READ) {
19589 + results[0] = data->sens[nr - 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]) {
19610 + printk(KERN_ERR "it87.o: Invalid sensor type %ld; "
19611 + "must be 0 (unused), 2 (thermistor) "
19612 + "or 3 (diode)\n", results[0]);
19615 + it87_write_value(client,
19616 + IT87_REG_TEMP_ENABLE, tmp);
19617 + data->sens[nr - 1] = results[0];
19622 +static int __init sm_it87_init(void)
19626 + printk("it87.o version %s (%s)\n", LM_VERSION, LM_DATE);
19627 + if (!it87_find(&addr)) {
19628 + normal_isa[0] = addr;
19630 + return i2c_add_driver(&it87_driver);
19633 +static void __exit sm_it87_exit(void)
19635 + i2c_del_driver(&it87_driver);
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");
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
19653 + lm75.c - Part of lm_sensors, Linux kernel modules for hardware
19655 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
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.
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.
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.
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"
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 };
19687 +/* Insmod parameters */
19688 +SENSORS_INSMOD_1(lm75);
19690 +/* Many LM75 constants specified below */
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
19698 +/* Each client has this additional data */
19699 +struct lm75_data {
19700 + struct i2c_client client;
19703 + struct semaphore update_lock;
19704 + char valid; /* !=0 if following fields are valid */
19705 + unsigned long last_updated; /* In jiffies */
19707 + u16 temp, temp_os, temp_hyst; /* Register values */
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);
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);
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,
19733 +/* -- SENSORS SYSCTL START -- */
19735 +#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
19737 +/* -- SENSORS SYSCTL END -- */
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},
19750 +static int lm75_id = 0;
19752 +static int lm75_attach_adapter(struct i2c_adapter *adapter)
19754 + return i2c_detect(adapter, &addr_data, lm75_detect);
19757 +/* This function is called by i2c_detect */
19758 +int lm75_detect(struct i2c_adapter *adapter, int address,
19759 + unsigned short flags, int kind)
19762 + struct i2c_client *new_client;
19763 + struct lm75_data *data;
19765 + const char *type_name, *client_name;
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. */
19770 + if (i2c_is_isa_adapter(adapter)) {
19772 + ("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
19777 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
19778 + I2C_FUNC_SMBUS_WORD_DATA))
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))) {
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;
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. */
19804 + int cur, conf, hyst, os;
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)
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)
19822 + /* Unused bits */
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)
19834 + /* Determine the chip type - only one kind supported! */
19838 + if (kind == lm75) {
19839 + type_name = "lm75";
19840 + client_name = "LM75 chip";
19842 + pr_debug("lm75.o: Internal error: unknown kind (%d)?!?", kind);
19846 + /* Fill in the remaining client fields and put it into the global list */
19847 + strcpy(new_client->name, client_name);
19849 + new_client->id = lm75_id++;
19851 + init_MUTEX(&data->update_lock);
19853 + /* Tell the I2C layer a new client has arrived */
19854 + if ((err = i2c_attach_client(new_client)))
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) {
19863 + data->sysctl_id = i;
19865 + lm75_init_client(new_client);
19868 +/* OK, this is not exactly good programming practice, usually. But it is
19869 + very code-efficient in this case. */
19872 + i2c_detach_client(new_client);
19880 +static int lm75_detach_client(struct i2c_client *client)
19882 + struct lm75_data *data = client->data;
19884 + i2c_deregister_entry(data->sysctl_id);
19885 + i2c_detach_client(client);
19886 + kfree(client->data);
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)
19895 + if (reg == LM75_REG_CONF)
19896 + return i2c_smbus_read_byte_data(client, reg);
19898 + return swab16(i2c_smbus_read_word_data(client, reg));
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)
19906 + if (reg == LM75_REG_CONF)
19907 + return i2c_smbus_write_byte_data(client, reg, value);
19909 + return i2c_smbus_write_word_data(client, reg, swab16(value));
19912 +static void lm75_init_client(struct i2c_client *client)
19914 + /* Initialize the LM75 chip */
19915 + lm75_write_value(client, LM75_REG_CONF, 0);
19918 +static void lm75_update_client(struct i2c_client *client)
19920 + struct lm75_data *data = client->data;
19922 + down(&data->update_lock);
19924 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
19925 + (jiffies < data->last_updated) || !data->valid) {
19926 + pr_debug("Starting lm75 update\n");
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;
19936 + up(&data->update_lock);
19940 +void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
19941 + int *nrels_mag, long *results)
19943 + struct lm75_data *data = client->data;
19944 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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,
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);
19966 +static int __init sm_lm75_init(void)
19968 + printk(KERN_INFO "lm75.o version %s (%s)\n", LM_VERSION, LM_DATE);
19969 + return i2c_add_driver(&lm75_driver);
19972 +static void __exit sm_lm75_exit(void)
19974 + i2c_del_driver(&lm75_driver);
19977 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
19978 +MODULE_DESCRIPTION("LM75 driver");
19979 +MODULE_LICENSE("GPL");
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
19987 + lm75.h - Part of lm_sensors, Linux kernel modules for hardware
19989 + Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
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.
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.
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.
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.
20013 +#include <linux/i2c-proc.h>
20015 +/* straight from the datasheet */
20016 +#define LM75_TEMP_MIN (-550)
20017 +#define LM75_TEMP_MAX 1250
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)
20023 + int ntemp = SENSORS_LIMIT(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
20024 + ntemp += (ntemp<0 ? -2 : 2);
20025 + return (u16)((ntemp / 5) << 7);
20028 +static inline int LM75_TEMP_FROM_REG(u16 reg)
20030 + /* use integer division instead of equivalent right shift to
20031 + guarantee arithmetic shift and preserve the sign */
20032 + return ((s16)reg / 128) * 5;
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
20039 + lm78.c - Part of lm_sensors, Linux kernel modules for hardware
20041 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
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.
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.
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.
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"
20068 +MODULE_LICENSE("GPL");
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 };
20076 +/* Insmod parameters */
20077 +SENSORS_INSMOD_3(lm78, lm78j, lm79);
20079 +/* Many LM78 constants specified below */
20081 +/* Length of ISA address segment */
20082 +#define LM78_EXTENT 8
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
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))
20093 +#define LM78_REG_FAN_MIN(nr) (0x3a + (nr))
20094 +#define LM78_REG_FAN(nr) (0x27 + (nr))
20096 +#define LM78_REG_TEMP 0x27
20097 +#define LM78_REG_TEMP_OVER 0x39
20098 +#define LM78_REG_TEMP_HYST 0x3a
20100 +#define LM78_REG_ALARM1 0x41
20101 +#define LM78_REG_ALARM2 0x42
20103 +#define LM78_REG_VID_FANDIV 0x47
20105 +#define LM78_REG_CONFIG 0x40
20106 +#define LM78_REG_CHIPID 0x49
20107 +#define LM78_REG_I2C_ADDR 0x48
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)
20117 +static inline u8 FAN_TO_REG(long rpm, int div)
20121 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
20122 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
20126 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
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)
20132 +#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
20134 +#define ALARMS_FROM_REG(val) (val)
20136 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
20137 +#define DIV_FROM_REG(val) (1 << (val))
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
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
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
20158 +struct lm78_data {
20159 + struct i2c_client client;
20160 + struct semaphore lock;
20164 + struct semaphore update_lock;
20165 + char valid; /* !=0 if following fields are valid */
20166 + unsigned long last_updated; /* In jiffies */
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 */
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);
20187 +static int lm78_read_value(struct i2c_client *client, u8 register);
20188 +static int lm78_write_value(struct i2c_client *client, u8 register,
20190 +static void lm78_update_client(struct i2c_client *client);
20191 +static void lm78_init_client(struct i2c_client *client);
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);
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,
20216 +static int lm78_id = 0;
20218 +/* The /proc/sys entries */
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 */
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
20252 +/* -- SENSORS SYSCTL END -- */
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},
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)
20298 + return i2c_detect(adapter, &addr_data, lm78_detect);
20301 +/* This function is called by i2c_detect */
20302 +int lm78_detect(struct i2c_adapter *adapter, int address,
20303 + unsigned short flags, int kind)
20306 + struct i2c_client *new_client;
20307 + struct lm78_data *data;
20309 + const char *type_name = "";
20310 + const char *client_name = "";
20311 + int is_isa = i2c_is_isa_adapter(adapter);
20314 + && !i2c_check_functionality(adapter,
20315 + I2C_FUNC_SMBUS_BYTE_DATA)) goto
20319 + if (check_region(address, LM78_EXTENT))
20323 + /* Probe whether there is anything available on this address. Already
20324 + done for SMBus clients */
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)
20334 + if (inb_p(address + 3) != i)
20336 + if (inb_p(address + 7) != i)
20338 +#undef REALLY_SLOW_IO
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);
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. */
20354 + if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
20359 + new_client = &data->client;
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;
20368 + /* Now, we do the remaining detection. */
20371 + if (lm78_read_value(new_client, LM78_REG_CONFIG) & 0x80)
20374 + && (lm78_read_value(new_client, LM78_REG_I2C_ADDR) !=
20375 + address)) goto ERROR1;
20378 + /* Determine the chip type. */
20380 + i = lm78_read_value(new_client, LM78_REG_CHIPID);
20381 + if (i == 0x00 || i == 0x20)
20383 + else if (i == 0x40)
20385 + else if ((i & 0xfe) == 0xc0)
20390 + ("lm78.o: Ignoring 'force' parameter for unknown chip at "
20391 + "adapter %d, address 0x%02x\n",
20392 + i2c_adapter_id(adapter), address);
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";
20408 + printk("lm78.o: Internal error: unknown kind (%d)?!?",
20414 + /* Reserve the ISA region */
20416 + request_region(address, LM78_EXTENT, type_name);
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;
20422 + new_client->id = lm78_id++;
20424 + init_MUTEX(&data->update_lock);
20426 + /* Tell the I2C layer a new client has arrived */
20427 + if ((err = i2c_attach_client(new_client)))
20430 + /* Register a new directory entry with module sensors */
20431 + if ((i = i2c_register_entry(new_client,
20433 + lm78_dir_table_template)) < 0) {
20437 + data->sysctl_id = i;
20439 + /* Initialize the LM78 chip */
20440 + lm78_init_client(new_client);
20443 +/* OK, this is not exactly good programming practice, usually. But it is
20444 + very code-efficient in this case. */
20447 + i2c_detach_client(new_client);
20450 + release_region(address, LM78_EXTENT);
20457 +static int lm78_detach_client(struct i2c_client *client)
20461 + i2c_deregister_entry(((struct lm78_data *) (client->data))->
20464 + if ((err = i2c_detach_client(client))) {
20466 + ("lm78.o: Client deregistration failed, client not detached.\n");
20470 + if(i2c_is_isa_client(client))
20471 + release_region(client->addr, LM78_EXTENT);
20472 + kfree(client->data);
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
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)
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));
20494 + return i2c_smbus_read_byte_data(client, reg);
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
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)
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));
20513 + return i2c_smbus_write_byte_data(client, reg, value);
20516 +/* Called when we have found a new LM78. */
20517 +static void lm78_init_client(struct i2c_client *client)
20519 + u8 config = lm78_read_value(client, LM78_REG_CONFIG);
20521 + /* Start monitoring */
20522 + if (!(config & 0x01))
20523 + lm78_write_value(client, LM78_REG_CONFIG,
20524 + (config & 0xf7) | 0x01);
20527 +static void lm78_update_client(struct i2c_client *client)
20529 + struct lm78_data *data = client->data;
20532 + down(&data->update_lock);
20534 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
20535 + (jiffies < data->last_updated) || !data->valid) {
20538 + printk("Starting lm78 update\n");
20540 + for (i = 0; i <= 6; 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));
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));
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)
20563 + (lm78_read_value(client, LM78_REG_CHIPID) &
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;
20574 + data->fan_div[2] = 1;
20577 + up(&data->update_lock);
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)
20597 + struct lm78_data *data = client->data;
20598 + int nr = ctl_name - LM78_SYSCTL_IN0;
20600 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
20622 +void lm78_fan(struct i2c_client *client, int operation, int ctl_name,
20623 + int *nrels_mag, long *results)
20625 + struct lm78_data *data = client->data;
20626 + int nr = ctl_name - LM78_SYSCTL_FAN1 + 1;
20628 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
20636 + FAN_FROM_REG(data->fan[nr - 1],
20637 + DIV_FROM_REG(data->fan_div[nr - 1]));
20639 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
20640 + if (*nrels_mag >= 1) {
20641 + data->fan_min[nr - 1] = FAN_TO_REG(results[0],
20646 + lm78_write_value(client, LM78_REG_FAN_MIN(nr),
20647 + data->fan_min[nr - 1]);
20653 +void lm78_temp(struct i2c_client *client, int operation, int ctl_name,
20654 + int *nrels_mag, long *results)
20656 + struct lm78_data *data = client->data;
20657 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
20679 +void lm78_vid(struct i2c_client *client, int operation, int ctl_name,
20680 + int *nrels_mag, long *results)
20682 + struct lm78_data *data = client->data;
20683 + if (operation == SENSORS_PROC_REAL_INFO)
20685 + else if (operation == SENSORS_PROC_REAL_READ) {
20686 + lm78_update_client(client);
20687 + results[0] = VID_FROM_REG(data->vid);
20692 +void lm78_alarms(struct i2c_client *client, int operation, int ctl_name,
20693 + int *nrels_mag, long *results)
20695 + struct lm78_data *data = client->data;
20696 + if (operation == SENSORS_PROC_REAL_INFO)
20698 + else if (operation == SENSORS_PROC_REAL_READ) {
20699 + lm78_update_client(client);
20700 + results[0] = ALARMS_FROM_REG(data->alarms);
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)
20712 + struct lm78_data *data = client->data;
20715 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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);
20749 +static int __init sm_lm78_init(void)
20751 + printk("lm78.o version %s (%s)\n", LM_VERSION, LM_DATE);
20752 + return i2c_add_driver(&lm78_driver);
20755 +static void __exit sm_lm78_exit(void)
20757 + i2c_del_driver(&lm78_driver);
20762 +MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
20763 +MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
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
20771 + lm80.c - Part of lm_sensors, Linux kernel modules for hardware
20773 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
20774 + and Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
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"
20799 +MODULE_LICENSE("GPL");
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 };
20807 +/* Insmod parameters */
20808 +SENSORS_INSMOD_1(lm80);
20810 +/* Many LM80 constants specified below */
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))
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
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
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
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. */
20842 +#define IN_TO_REG(val) (SENSORS_LIMIT((val),0,255))
20843 +#define IN_FROM_REG(val) (val)
20845 +static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)
20849 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
20850 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
20854 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
20855 + (val)==255?0:1350000/((div)*(val)))
20857 +static inline long TEMP_FROM_REG(u16 temp)
20862 + if (temp < 0x0800)
20863 + res = 625 * (long) temp;
20865 + res = ((long) temp - 0x01000) * 625;
20867 + return res / 100;
20870 +#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*100)
20872 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-50)/100):\
20873 + ((val)+50)/100), \
20876 +#define ALARMS_FROM_REG(val) (val)
20878 +#define DIV_FROM_REG(val) (1 << (val))
20879 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
20881 +struct lm80_data {
20882 + struct i2c_client client;
20885 + struct semaphore update_lock;
20886 + char valid; /* !=0 if following fields are valid */
20887 + unsigned long last_updated; /* In jiffies */
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 */
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);
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);
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);
20927 +static int lm80_id = 0;
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,
20938 +/* The /proc/sys entries */
20940 +/* -- SENSORS SYSCTL START -- */
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 */
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
20970 +/* -- SENSORS SYSCTL END -- */
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},
21005 +static int lm80_attach_adapter(struct i2c_adapter *adapter)
21007 + return i2c_detect(adapter, &addr_data, lm80_detect);
21010 +int lm80_detect(struct i2c_adapter *adapter, int address,
21011 + unsigned short flags, int kind)
21014 + struct i2c_client *new_client;
21015 + struct lm80_data *data;
21017 + const char *type_name, *client_name;
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. */
21022 + if (i2c_is_isa_adapter(adapter)) {
21024 + ("lm80.o: lm80_detect called for an ISA bus adapter?!?\n");
21029 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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))) {
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;
21047 + /* Now, we do the remaining detection. It is lousy. */
21048 + if (lm80_read_value(new_client, LM80_REG_ALARM2) & 0xc0)
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) !=
21055 + || (i2c_smbus_read_byte_data(new_client, i + 0xc0) !=
21056 + cur)) goto ERROR1;
21059 + /* Determine the chip type - only one kind supported! */
21063 + if (kind == lm80) {
21064 + type_name = "lm80";
21065 + client_name = "LM80 chip";
21068 + printk("lm80.o: Internal error: unknown kind (%d)?!?",
21074 + /* Fill in the remaining client fields and put it into the global list */
21075 + strcpy(new_client->name, client_name);
21077 + new_client->id = lm80_id++;
21079 + init_MUTEX(&data->update_lock);
21081 + /* Tell the I2C layer a new client has arrived */
21082 + if ((err = i2c_attach_client(new_client)))
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) {
21091 + data->sysctl_id = i;
21093 + lm80_init_client(new_client);
21096 +/* OK, this is not exactly good programming practice, usually. But it is
21097 + very code-efficient in this case. */
21099 + i2c_detach_client(new_client);
21107 +static int lm80_detach_client(struct i2c_client *client)
21111 + i2c_deregister_entry(((struct lm80_data *) (client->data))->
21114 + if ((err = i2c_detach_client(client))) {
21116 + ("lm80.o: Client deregistration failed, client not detached.\n");
21120 + kfree(client->data);
21125 +static int lm80_read_value(struct i2c_client *client, u8 reg)
21127 + return i2c_smbus_read_byte_data(client, reg);
21130 +static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value)
21132 + return i2c_smbus_write_byte_data(client, reg, value);
21135 +/* Called when we have found a new LM80. */
21136 +static void lm80_init_client(struct i2c_client *client)
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);
21145 + /* Start monitoring */
21146 + lm80_write_value(client, LM80_REG_CONFIG, 0x01);
21149 +static void lm80_update_client(struct i2c_client *client)
21151 + struct lm80_data *data = client->data;
21154 + down(&data->update_lock);
21156 + if ((jiffies - data->last_updated > 2 * HZ) ||
21157 + (jiffies < data->last_updated) || !data->valid) {
21160 + printk("Starting lm80 update\n");
21162 + for (i = 0; i <= 6; 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));
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);
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);
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;
21198 + up(&data->update_lock);
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)
21218 + struct lm80_data *data = client->data;
21219 + int nr = ctl_name - LM80_SYSCTL_IN0;
21221 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
21243 +void lm80_fan(struct i2c_client *client, int operation, int ctl_name,
21244 + int *nrels_mag, long *results)
21246 + struct lm80_data *data = client->data;
21247 + int nr = ctl_name - LM80_SYSCTL_FAN1 + 1;
21249 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
21257 + FAN_FROM_REG(data->fan[nr - 1],
21258 + DIV_FROM_REG(data->fan_div[nr - 1]));
21260 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
21261 + if (*nrels_mag >= 1) {
21262 + data->fan_min[nr - 1] = FAN_TO_REG(results[0],
21267 + lm80_write_value(client,
21269 + 1 ? LM80_REG_FAN1_MIN :
21270 + LM80_REG_FAN2_MIN,
21271 + data->fan_min[nr - 1]);
21277 +void lm80_temp(struct i2c_client *client, int operation, int ctl_name,
21278 + int *nrels_mag, long *results)
21280 + struct lm80_data *data = client->data;
21281 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
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);
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);
21316 +void lm80_alarms(struct i2c_client *client, int operation, int ctl_name,
21317 + int *nrels_mag, long *results)
21319 + struct lm80_data *data = client->data;
21320 + if (operation == SENSORS_PROC_REAL_INFO)
21322 + else if (operation == SENSORS_PROC_REAL_READ) {
21323 + lm80_update_client(client);
21324 + results[0] = ALARMS_FROM_REG(data->alarms);
21329 +void lm80_fan_div(struct i2c_client *client, int operation, int ctl_name,
21330 + int *nrels_mag, long *results)
21332 + struct lm80_data *data = client->data;
21335 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
21357 +static int __init sm_lm80_init(void)
21359 + printk("lm80.o version %s (%s)\n", LM_VERSION, LM_DATE);
21360 + return i2c_add_driver(&lm80_driver);
21363 +static void __exit sm_lm80_exit(void)
21365 + i2c_del_driver(&lm80_driver);
21371 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
21372 +MODULE_DESCRIPTION("LM80 driver");
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
21380 + * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
21382 + * Copyright (C) 2003 Jean Delvare <khali@linux-fr.org>
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).
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.
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.
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.
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"
21417 + * Addresses to scan
21418 + * Address is selected using 2 three-level pins, resulting in 9 possible
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 };
21429 + * Insmod parameters
21432 +SENSORS_INSMOD_1(lm83);
21435 + * The LM83 registers
21436 + * Manufacturer ID is 0x01 for National Semiconductor.
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
21461 + * Conversions and various macros
21462 + * The LM83 uses signed 8-bit values.
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) : \
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
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
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
21493 + * Functions declaration
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);
21509 + * Driver data (common to all clients)
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,
21522 + * Client data (each client gets its own)
21527 + struct i2c_client client;
21530 + struct semaphore update_lock;
21531 + char valid; /* zero until following fields are valid */
21532 + unsigned long last_updated; /* in jiffies */
21534 + /* registers values */
21535 + u8 temp[4], temp_high[4], tcrit;
21536 + u16 alarms; /* bitvector, combined */
21541 + * These files are created for each detected LM83.
21544 +/* -- SENSORS SYSCTL START -- */
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
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
21565 +/* -- SENSORS SYSCTL END -- */
21568 +static ctl_table lm83_dir_table_template[] =
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},
21586 + * Internal variables
21589 +static int lm83_id = 0;
21595 +static int lm83_attach_adapter(struct i2c_adapter *adapter)
21597 + return i2c_detect(adapter, &addr_data, lm83_detect);
21601 + * The following function does more than just detection. If detection
21602 + * succeeds, it also registers the new chip.
21604 +static int lm83_detect(struct i2c_adapter *adapter, int address, unsigned
21605 + short flags, int kind)
21607 + struct i2c_client *new_client;
21608 + struct lm83_data *data;
21610 + const char *type_name = "";
21611 + const char *client_name = "";
21614 + if (i2c_is_isa_adapter(adapter))
21616 + printk("lm83.o: Called for an ISA bus adapter, aborting.\n");
21621 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
21624 + printk("lm83.o: I2C bus doesn't support byte read mode, "
21630 + if (!(data = kmalloc(sizeof(struct lm83_data), GFP_KERNEL)))
21632 + printk("lm83.o: Out of memory in lm83_detect (new_client).\n");
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.
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;
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
21661 + /* Default to an LM83 if forced */
21665 + if (kind < 0) /* detection */
21667 + if (((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1)
21669 + || ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2)
21671 + || ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG)
21672 + & 0x41) != 0x00))
21675 + printk(KERN_DEBUG "lm83.o: Detection failed at 0x%02x.\n",
21682 + if (kind <= 0) /* identification */
21684 + u8 man_id, chip_id;
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 */
21690 + if (chip_id == 0x03)
21695 + if (kind <= 0) /* identification failed */
21697 + printk("lm83.o: Unsupported chip.\n");
21701 + if (kind == lm83)
21703 + type_name = "lm83";
21704 + client_name = "LM83 chip";
21708 + printk("lm83.o: Unknown kind %d.\n", kind);
21713 + * OK, we got a valid chip so we can fill in the remaining client
21717 + strcpy(new_client->name, client_name);
21718 + new_client->id = lm83_id++;
21720 + init_MUTEX(&data->update_lock);
21723 + * Tell the I2C layer a new client has arrived.
21726 + if ((err = i2c_attach_client(new_client)))
21729 + printk("lm83.o: Failed attaching client.\n");
21735 + * Register a new directory entry.
21738 + if ((err = i2c_register_entry(new_client, type_name,
21739 + lm83_dir_table_template)) < 0)
21742 + printk("lm83.o: Failed registering directory entry.\n");
21746 + data->sysctl_id = err;
21749 + * Initialize the LM83 chip
21750 + * (Nothing to do for this one.)
21756 + i2c_detach_client(new_client);
21762 +static int lm83_detach_client(struct i2c_client *client)
21766 + i2c_deregister_entry(((struct lm83_data *) (client->data))->sysctl_id);
21767 + if ((err = i2c_detach_client(client)))
21769 + printk("lm83.o: Client deregistration failed, client not "
21774 + kfree(client->data);
21778 +static void lm83_update_client(struct i2c_client *client)
21780 + struct lm83_data *data = client->data;
21782 + down(&data->update_lock);
21784 + if ((jiffies - data->last_updated > HZ * 2) ||
21785 + (jiffies < data->last_updated) || !data->valid)
21789 + printk("lm83.o: Updating LM83 data.\n");
21791 + for (nr = 0; nr < 4 ; 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]);
21798 + data->tcrit = i2c_smbus_read_byte_data(client, LM83_REG_R_TCRIT);
21800 + i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1) +
21801 + (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2) << 8);
21803 + data->last_updated = jiffies;
21807 + up(&data->update_lock);
21810 +static void lm83_temp(struct i2c_client *client, int operation, int
21811 + ctl_name, int *nrels_mag, long *results)
21813 + struct lm83_data *data = client->data;
21814 + int nr = ctl_name - LM83_SYSCTL_LOCAL_TEMP;
21816 + if (operation == SENSORS_PROC_REAL_INFO)
21817 + *nrels_mag = 0; /* magnitude */
21818 + else if (operation == SENSORS_PROC_REAL_READ)
21820 + lm83_update_client(client);
21821 + results[0] = TEMP_FROM_REG(data->temp_high[nr]);
21822 + results[1] = TEMP_FROM_REG(data->temp[nr]);
21825 + else if (operation == SENSORS_PROC_REAL_WRITE)
21827 + if (*nrels_mag >= 1)
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]);
21836 +static void lm83_tcrit(struct i2c_client *client, int operation, int
21837 + ctl_name, int *nrels_mag, long *results)
21839 + struct lm83_data *data = client->data;
21841 + if (operation == SENSORS_PROC_REAL_INFO)
21842 + *nrels_mag = 0; /* magnitude */
21843 + else if (operation == SENSORS_PROC_REAL_READ)
21845 + lm83_update_client(client);
21846 + results[0] = TEMP_FROM_REG(data->tcrit);
21849 + else if (operation == SENSORS_PROC_REAL_WRITE)
21851 + if (*nrels_mag >= 1)
21853 + data->tcrit = TEMP_TO_REG(results[0]);
21854 + i2c_smbus_write_byte_data(client, LM83_REG_W_TCRIT,
21860 +static void lm83_alarms(struct i2c_client *client, int operation, int
21861 + ctl_name, int *nrels_mag, long *results)
21863 + struct lm83_data *data = client->data;
21865 + if (operation == SENSORS_PROC_REAL_INFO)
21866 + *nrels_mag = 0; /* magnitude */
21867 + else if (operation == SENSORS_PROC_REAL_READ)
21869 + lm83_update_client(client);
21870 + results[0] = data->alarms;
21875 +static int __init sm_lm83_init(void)
21877 + printk(KERN_INFO "lm83.o version %s (%s)\n", LM_VERSION, LM_DATE);
21878 + return i2c_add_driver(&lm83_driver);
21881 +static void __exit sm_lm83_exit(void)
21883 + i2c_del_driver(&lm83_driver);
21886 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
21887 +MODULE_DESCRIPTION("LM83 sensor driver");
21888 +MODULE_LICENSE("GPL");
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
21896 + lm85.c - Part of lm_sensors, Linux kernel modules for hardware
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>
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.
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.
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.
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
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.
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>
21962 +#ifndef I2C_DRIVERID_LM85
21963 +#define I2C_DRIVERID_LM85 1039
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 };
21972 +/* Insmod parameters */
21973 +SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
21975 +/* Many LM85 constants specified below */
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)
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)
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)
21990 +#define LM85_REG_PWM(nr) (0x30 + (nr))
21992 +#define ADT7463_REG_OPPOINT(nr) (0x33 + (nr))
21994 +#define ADT7463_REG_TMIN_CTL1 0x36
21995 +#define ADT7463_REG_TMIN_CTL2 0x37
21996 +#define ADT7463_REG_TMIN_CTL 0x0136
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
22016 +#define LM85_REG_CONFIG 0x40
22018 +#define LM85_REG_ALARM1 0x41
22019 +#define LM85_REG_ALARM2 0x42
22020 +#define LM85_REG_ALARM 0x0141
22022 +#define LM85_REG_VID 0x43
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
22035 +#define LM85_REG_TACH_MODE 0x74
22036 +#define LM85_REG_SPINUP_CTL 0x75
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
22049 +#define ADT7463_REG_THERM 0x79
22050 +#define ADT7463_REG_THERM_LIMIT 0x7A
22051 +#define ADT7463_REG_CONFIG4 0x7D
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)
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.
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))
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 */
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))
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))
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)
22094 +#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
22095 +#define PWM_FROM_REG(val) (val)
22097 +#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03)
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
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
22113 + * Some chips filter the temp, others the fan.
22114 + * Filter constant (or disabled) .1 seconds
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
22123 +static int RANGE_TO_REG( int range )
22127 + if( range >= lm85_range_map[15] ) { return 15 ; }
22128 + for( i = 0 ; i < 15 ; ++i )
22129 + if( range <= lm85_range_map[i] )
22131 + return( i & 0x0f );
22133 +#define RANGE_FROM_REG(val) (lm85_range_map[(val)&0x0f])
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.
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 */
22144 +static int SMOOTH_TO_REG( int smooth )
22148 + if( smooth <= 0 ) { return 0 ; } /* Disabled */
22149 + for( i = 0 ; i < 7 ; ++i )
22150 + if( smooth >= lm85_smooth_map[i] )
22152 + return( (i & 0x07) | 0x08 );
22154 +#define SMOOTH_FROM_REG(val) ((val)&0x08?lm85_smooth_map[(val)&0x07]:0)
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
22160 +static int SPINUP_TO_REG( int spinup )
22164 + if( spinup >= lm85_spinup_map[7] ) { return 7 ; }
22165 + for( i = 0 ; i < 7 ; ++i )
22166 + if( spinup <= lm85_spinup_map[i] )
22168 + return( i & 0x07 );
22170 +#define SPINUP_FROM_REG(val) (lm85_spinup_map[(val)&0x07])
22172 +/* These are the PWM frequency encodings */
22173 +static int lm85_freq_map[] = { /* .1 Hz */
22174 + 100, 150, 230, 300, 380, 470, 620, 980
22176 +static int FREQ_TO_REG( int freq )
22180 + if( freq >= lm85_freq_map[7] ) { return 7 ; }
22181 + for( i = 0 ; i < 7 ; ++i )
22182 + if( freq <= lm85_freq_map[i] )
22184 + return( i & 0x07 );
22186 +#define FREQ_FROM_REG(val) (lm85_freq_map[(val)&0x07])
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
22199 +static int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 };
22200 +static int ZONE_TO_REG( int zone )
22204 + for( i = 0 ; i <= 7 ; ++i )
22205 + if( zone == lm85_zone_map[i] )
22207 + if( i > 7 ) /* Not found. */
22208 + i = 3; /* Always 100% */
22209 + return( (i & 0x07)<<5 );
22211 +#define ZONE_FROM_REG(val) (lm85_zone_map[((val)>>5)&0x07])
22213 +#define HYST_TO_REG(val) (SENSORS_LIMIT((-(val)+5)/10,0,15))
22214 +#define HYST_FROM_REG(val) (-(val)*10)
22216 +#define OFFSET_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
22217 +#define OFFSET_FROM_REG(val) ((val)*25)
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)
22223 +/* sensors_vid.h defines vid_from_reg() */
22224 +#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
22226 +#define ALARMS_FROM_REG(val) (val)
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))
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
22240 +/* Typically used with Pentium 4 systems v9.1 VRM spec */
22241 +#define LM85_INIT_VRM 91
22243 +/* Chip sampling rates
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.
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*
22256 +#define LM85_DATA_INTERVAL (1 * HZ)
22257 +#define LM85_CONFIG_INTERVAL (5 * 60 * HZ)
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. */
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
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 */
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 */
22281 +struct lm85_data {
22282 + struct i2c_client client;
22283 + struct semaphore lock;
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 */
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];
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);
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);
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);
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);
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);
22373 +static void emc6d100_in(struct i2c_client *client, int operation,
22374 + int ctl_name, int *nrels_mag, long *results);
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,
22385 +/* Unique ID assigned to each LM85 detected */
22386 +static int lm85_id = 0;
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
22421 +/* Vendor specific values */
22422 +#define LM85_SYSCTL_SPINUP_CTL 1100
22423 +#define LM85_SYSCTL_TACH_MODE 1101
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
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
22439 +/* SMSC variant of the LM85 */
22440 +#define EMC6D100_SYSCTL_IN5 1400
22441 +#define EMC6D100_SYSCTL_IN6 1401
22442 +#define EMC6D100_SYSCTL_IN7 1402
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 -- */
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.
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},
22538 +#define CTLTBL_COMMON (sizeof(lm85_common)/sizeof(lm85_common[0]))
22540 +/* NOTE: tach_mode is a shared name, but implemented with
22541 + * different functions
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. */
22550 +#define CTLTBL_LM85 (sizeof(lm85_specific)/sizeof(lm85_specific[0]))
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. */
22567 +#define CTLTBL_ADM1027 (sizeof(adm1027_specific)/sizeof(adm1027_specific[0]))
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. */
22580 +#define CTLTBL_ADT7463 (sizeof(adt7463_specific)/sizeof(adt7463_specific[0]))
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. */
22591 +#define CTLTBL_EMC6D100 (sizeof(emc6d100_specific)/sizeof(emc6d100_specific[0]))
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)))
22598 +#define CTLTBL_MAX (CTLTBL_COMMON + MAX3(CTLTBL_LM85, CTLTBL_ADM1027+CTLTBL_ADT7463, CTLTBL_EMC6D100))
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)
22606 + return i2c_detect(adapter, &addr_data, lm85_detect);
22609 +/* This function is called by i2c_detect */
22610 +int lm85_detect(struct i2c_adapter *adapter, int address,
22611 + unsigned short flags, int kind)
22614 + int company, verstep ;
22615 + struct i2c_client *new_client;
22616 + struct lm85_data *data;
22618 + const char *type_name = "";
22619 + struct ctl_table template[CTLTBL_MAX] ;
22620 + int template_used ;
22622 + if (i2c_is_isa_adapter(adapter)) {
22623 + /* This chip has no ISA interface */
22627 + if (!i2c_check_functionality(adapter,
22628 + I2C_FUNC_SMBUS_BYTE_DATA)) {
22629 + /* We need to be able to do byte I/O */
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. */
22637 + if (!(data = kmalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
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;
22649 + /* Now, we do the remaining detection. */
22651 + company = lm85_read_value(new_client, LM85_REG_COMPANY);
22652 + verstep = lm85_read_value(new_client, LM85_REG_VERSTEP);
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,
22662 + /* If auto-detecting, Determine the chip type. */
22665 + printk("lm85: Autodetecting device at %d,0x%02x ...\n",
22666 + i2c_adapter_id(adapter), address );
22668 + if( company == LM85_COMPANY_NATIONAL
22669 + && verstep == LM85_VERSTEP_LM85C ) {
22671 + } else if( company == LM85_COMPANY_NATIONAL
22672 + && verstep == LM85_VERSTEP_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 ) {
22683 + } else if( company == LM85_COMPANY_ANALOG_DEV
22684 + && verstep == LM85_VERSTEP_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.
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" */
22714 + printk("lm85: Autodetection failed\n");
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 );
22727 + /* Fill in the chip specific driver values */
22730 + type_name = "lm85";
22731 + strcpy(new_client->name, "Generic LM85");
22732 + template_used = 0 ;
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 ;
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 ;
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 ;
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 ;
22761 + type_name = "emc6d100";
22762 + strcpy(new_client->name, "SMSC EMC6D100");
22763 + memcpy(template, emc6d100_specific, sizeof(emc6d100_specific));
22764 + template_used = CTLTBL_EMC6D100 ;
22767 + printk("lm85: Internal error, invalid kind (%d)!", kind);
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),
22780 + /* Housekeeping values */
22781 + data->type = kind;
22784 + /* Set the VRM version */
22785 + data->vrm = LM85_INIT_VRM ;
22787 + /* Zero the accumulators */
22788 + data->therm_total = 0;
22789 + data->therm_ovfl = 0;
22791 + init_MUTEX(&data->update_lock);
22793 + /* Initialize the LM85 chip */
22794 + lm85_init_client(new_client);
22796 + /* Tell the I2C layer a new client has arrived */
22797 + if ((err = i2c_attach_client(new_client)))
22800 + /* Finish out the template */
22801 + memcpy( template + template_used, lm85_common, sizeof(lm85_common) );
22803 + /* Register a new directory entry with module sensors */
22804 + if ((i = i2c_register_entry(new_client,
22806 + template)) < 0) {
22810 + data->sysctl_id = i;
22814 + /* Error out and cleanup code */
22816 + i2c_detach_client(new_client);
22823 +int lm85_detach_client(struct i2c_client *client)
22829 + i2c_deregister_entry(((struct lm85_data *)(client->data))->sysctl_id);
22831 + if ((err = i2c_detach_client(client))) {
22832 + printk("lm85(%d): Client deregistration failed,"
22833 + " client not detached.\n", id );
22837 + kfree(client->data);
22842 +int lm85_read_value(struct i2c_client *client, u16 reg)
22846 + /* What size location is it? */
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 ;
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 ;
22868 + default: /* Read BYTE data */
22869 + res = i2c_smbus_read_byte_data(client, reg & 0xff) & 0xff ;
22876 +int lm85_write_value(struct i2c_client *client, u16 reg, int value)
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) ;
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) ;
22900 + default: /* Write BYTE data */
22901 + res = i2c_smbus_write_byte_data(client, reg & 0xff, value);
22908 +/* Called when we have found a new LM85. It should set limits, etc. */
22909 +void lm85_init_client(struct i2c_client *client)
22912 + struct lm85_data *data = client->data;
22915 + printk("lm85(%d): Initializing device\n", client->id);
22918 + /* Warn if part was not "READY" */
22919 + value = lm85_read_value(client, LM85_REG_CONFIG);
22921 + printk("lm85(%d): LM85_REG_CONFIG is: 0x%02x\n", client->id, value );
22923 + if( value & 0x02 ) {
22924 + printk("lm85(%d): Client (%d,0x%02x) config is locked.\n",
22926 + i2c_adapter_id(client->adapter), client->addr );
22928 + if( ! (value & 0x04) ) {
22929 + printk("lm85(%d): Client (%d,0x%02x) is not ready.\n",
22931 + i2c_adapter_id(client->adapter), client->addr );
22933 + if( (data->type == adm1027 || data->type == adt7463)
22934 + && (value & 0x10)
22936 + printk("lm85(%d): Client (%d,0x%02x) VxI mode is set. "
22937 + "Please report this to the lm85 maintainer.\n",
22939 + i2c_adapter_id(client->adapter), client->addr );
22942 + /* See if SYNC to PWM3 is set */
22943 + if( data->type == adt7463
22944 + && (lm85_read_value(client, LM85_REG_AFAN_SPIKE1) & 0x10)
22946 + printk("lm85(%d): Sync to PWM3 is set. Expect PWM3 "
22947 + "to control fans 2, 3, and 4\n",
22951 + /* See if PWM2 is #SMBALERT */
22952 + if( (data->type == adm1027 || data->type == adt7463)
22953 + && (lm85_read_value(client, ADM1027_REG_CONFIG3) & 0x01)
22955 + printk("lm85(%d): PWM2 is SMBALERT. PWM2 not available.\n",
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 );
22966 + if( value & 0x02 ) {
22967 + printk("lm85(%d): 5V input (in3) is THERM. "
22968 + "in3 not available.\n", client->id );
22972 + /* FIXME? Display EMC6D100 config info? */
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.
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 ;
22987 + printk("lm85(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
22989 + lm85_write_value(client, LM85_REG_CONFIG, value);
22993 +void lm85_update_client(struct i2c_client *client)
22995 + struct lm85_data *data = client->data;
22998 + down(&data->update_lock);
23001 + || (jiffies - data->last_reading > LM85_DATA_INTERVAL )) {
23002 + /* Things that change quickly */
23005 + printk("lm85(%d): Reading sensor values\n", client->id);
23007 + /* Have to read extended bits first to "freeze" the
23008 + * more significant bits that are read later.
23010 + switch( data->type ) {
23013 + data->extend_adc =
23014 + lm85_read_value(client, ADM1027_REG_EXTEND_ADC);
23017 + data->extend_adc = 0 ;
23021 + for (i = 0; i <= 4; ++i) {
23023 + lm85_read_value(client, LM85_REG_IN(i));
23026 + for (i = 0; i <= 3; ++i) {
23028 + lm85_read_value(client, LM85_REG_FAN(i));
23031 + for (i = 0; i <= 2; ++i) {
23033 + lm85_read_value(client, LM85_REG_TEMP(i));
23036 + for (i = 0; i <= 2; ++i) {
23038 + lm85_read_value(client, LM85_REG_PWM(i));
23041 + data->alarms = lm85_read_value(client, LM85_REG_ALARM);
23043 + switch( ((struct lm85_data *)(client->data))->type ) {
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 ;
23051 + ++data->therm_ovfl ;
23055 + /* Three more voltage sensors */
23056 + for (i = 5; i <= 7; ++i) {
23058 + lm85_read_value(client, EMC6D100_REG_IN(i));
23060 + /* More alarm bits */
23062 + lm85_read_value(client, EMC6D100_REG_ALARM3) << 16;
23065 + default : break ; /* no warnings */
23068 + data->last_reading = jiffies ;
23069 + }; /* last_reading */
23072 + || (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
23073 + /* Things that don't change often */
23076 + printk("lm85(%d): Reading config values\n", client->id);
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));
23085 + for (i = 0; i <= 3; ++i) {
23086 + data->fan_min[i] =
23087 + lm85_read_value(client, LM85_REG_FAN_MIN(i));
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));
23097 + data->vid = lm85_read_value(client, LM85_REG_VID);
23099 + for (i = 0; i <= 2; ++i) {
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));
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 ;
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 ;
23128 + i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
23129 + data->zone[2].hyst = (i>>4) & 0x0f ;
23131 + switch( ((struct lm85_data *)(client->data))->type ) {
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 );
23140 + for (i = 0; i <= 2; ++i) {
23141 + data->oppoint[i] = lm85_read_value(client,
23142 + ADT7463_REG_OPPOINT(i) );
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 */
23150 + for (i = 0; i <= 2; ++i) {
23151 + data->temp_offset[i] = lm85_read_value(client,
23152 + ADM1027_REG_TEMP_OFFSET(i) );
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 );
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));
23169 + default : break ; /* no warnings */
23172 + data->last_config = jiffies;
23173 + }; /* last_config */
23177 + up(&data->update_lock);
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.
23191 +void lm85_in(struct i2c_client *client, int operation, int ctl_name,
23192 + int *nrels_mag, long *results)
23194 + struct lm85_data *data = client->data;
23195 + int nr = ctl_name - LM85_SYSCTL_IN0;
23197 + if (nr < 0 || nr > 4)
23198 + return ; /* ERROR */
23200 + if (operation == SENSORS_PROC_REAL_INFO)
23201 + *nrels_mag = 3; /* 1.000 */
23202 + else if (operation == SENSORS_PROC_REAL_READ) {
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);
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]);
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]);
23222 + up(&data->update_lock);
23226 +void lm85_fan(struct i2c_client *client, int operation, int ctl_name,
23227 + int *nrels_mag, long *results)
23229 + struct lm85_data *data = client->data;
23230 + int nr = ctl_name - LM85_SYSCTL_FAN1 ;
23232 + if (nr < 0 || nr > 3)
23233 + return ; /* ERROR */
23235 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
23249 + up(&data->update_lock);
23254 +void lm85_temp(struct i2c_client *client, int operation, int ctl_name,
23255 + int *nrels_mag, long *results)
23257 + struct lm85_data *data = client->data;
23258 + int nr = ctl_name - LM85_SYSCTL_TEMP1 ;
23260 + if (nr < 0 || nr > 2)
23261 + return ; /* ERROR */
23263 + if (operation == SENSORS_PROC_REAL_INFO)
23265 + else if (operation == SENSORS_PROC_REAL_READ) {
23267 + lm85_update_client(client);
23269 + /* +5 for offset of temp data in ext reg */
23270 + ext = EXT_FROM_REG(data->extend_adc, nr+5);
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);
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]);
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]);
23288 + up(&data->update_lock);
23292 +void lm85_pwm(struct i2c_client *client, int operation, int ctl_name,
23293 + int *nrels_mag, long *results)
23295 + struct lm85_data *data = client->data;
23296 + int nr = ctl_name - LM85_SYSCTL_PWM1 ;
23299 + if (nr < 0 || nr > 2)
23300 + return ; /* ERROR */
23302 + if (operation == SENSORS_PROC_REAL_INFO)
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 ;
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),
23319 + up(&data->update_lock);
23323 +void lm85_vid(struct i2c_client *client, int operation, int ctl_name,
23324 + int *nrels_mag, long *results)
23326 + struct lm85_data *data = client->data;
23328 + if( ctl_name != LM85_SYSCTL_VID )
23329 + return ; /* ERROR */
23331 + if (operation == SENSORS_PROC_REAL_INFO)
23333 + else if (operation == SENSORS_PROC_REAL_READ) {
23334 + lm85_update_client(client);
23335 + results[0] = VID_FROM_REG((data->vid)&0x3f,data->vrm);
23340 +void lm85_vrm(struct i2c_client *client, int operation, int ctl_name,
23341 + int *nrels_mag, long *results)
23343 + struct lm85_data *data = client->data;
23345 + if( ctl_name != LM85_SYSCTL_VRM )
23346 + return ; /* ERROR */
23348 + if (operation == SENSORS_PROC_REAL_INFO)
23350 + else if (operation == SENSORS_PROC_REAL_READ) {
23351 + results[0] = data->vrm ;
23353 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
23354 + down(&data->update_lock);
23355 + if (*nrels_mag > 0) {
23356 + data->vrm = results[0] ;
23358 + up(&data->update_lock);
23362 +void lm85_alarms(struct i2c_client *client, int operation, int ctl_name,
23363 + int *nrels_mag, long *results)
23365 + struct lm85_data *data = client->data;
23367 + if( ctl_name != LM85_SYSCTL_ALARMS )
23368 + return ; /* ERROR */
23370 + if (operation == SENSORS_PROC_REAL_INFO)
23372 + else if (operation == SENSORS_PROC_REAL_READ) {
23373 + lm85_update_client(client);
23374 + results[0] = ALARMS_FROM_REG(data->alarms);
23379 +void lm85_spinup_ctl(struct i2c_client *client, int operation, int ctl_name,
23380 + int *nrels_mag, long *results)
23382 + struct lm85_data *data = client->data;
23385 + if( ctl_name != LM85_SYSCTL_SPINUP_CTL )
23386 + return ; /* ERROR */
23388 + if (operation == SENSORS_PROC_REAL_INFO)
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 ;
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) ;
23402 + if (*nrels_mag > 1) {
23403 + old = (old & (~2)) | (results[1]?2:0) ;
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 ;
23410 + up(&data->update_lock);
23414 +void lm85_tach_mode(struct i2c_client *client, int operation, int ctl_name,
23415 + int *nrels_mag, long *results)
23417 + struct lm85_data *data = client->data;
23420 + /* Tach Mode 1, Tach Mode 2, Tach Mode 3 & 4 */
23422 + if( ctl_name != LM85_SYSCTL_TACH_MODE )
23423 + return ; /* ERROR */
23425 + if (operation == SENSORS_PROC_REAL_INFO)
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 ;
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) ;
23439 + if (*nrels_mag > 1) {
23440 + old = (old & (~0x0c)) | ((results[1]&3) << 2) ;
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 ;
23447 + up(&data->update_lock);
23451 +void adm1027_tach_mode(struct i2c_client *client, int operation, int ctl_name,
23452 + int *nrels_mag, long *results)
23454 + struct lm85_data *data = client->data;
23457 + /* Tach/DC 1, Tach/DC 2, Tach/DC 3, Tach/DC 4 */
23459 + if( ctl_name != ADM1027_SYSCTL_TACH_MODE )
23460 + return ; /* ERROR */
23462 + if (operation == SENSORS_PROC_REAL_INFO)
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 ;
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) ;
23477 + if (*nrels_mag > 2) {
23478 + old = (old & (~0x40)) | (results[2] ? 0x40 : 0) ;
23480 + if (*nrels_mag > 1) {
23481 + old = (old & (~0x20)) | (results[1] ? 0x20 : 0) ;
23483 + if (*nrels_mag > 0) {
23484 + old = (old & (~0x10)) | (results[0] ? 0x10 : 0) ;
23486 + /* Enable fast measurements if any TACH's are DC */
23487 + old = (old & (~0x08)) | ((old&0xf0) ? 0x08 : 0) ;
23489 + lm85_write_value(client, ADM1027_REG_CONFIG3, old);
23490 + data->tach_mode = old ;
23492 + up(&data->update_lock);
23496 +void lm85_pwm_config(struct i2c_client *client, int operation, int ctl_name,
23497 + int *nrels_mag, long *results)
23499 + struct lm85_data *data = client->data;
23500 + int nr = ctl_name - LM85_SYSCTL_PWM_CFG1 ;
23502 + /* Spinup, min PWM, PWM Frequency, min below limit, Invert */
23504 + if (nr < 0 || nr > 2)
23505 + return ; /* ERROR */
23507 + if (operation == SENSORS_PROC_REAL_INFO)
23509 + else if (operation == SENSORS_PROC_REAL_READ) {
23510 + lm85_update_client(client);
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 ;
23518 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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) ;
23526 + if (*nrels_mag > 3) {
23527 + data->autofan[nr].min_off = results[3] != 0 ;
23528 + lm85_write_value(client, LM85_REG_AFAN_SPIKE1,
23531 + | (data->autofan[0].min_off ? 0x20 : 0)
23532 + | (data->autofan[1].min_off ? 0x40 : 0)
23533 + | (data->autofan[2].min_off ? 0x80 : 0)
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
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
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 ;
23554 + up(&data->update_lock);
23558 +void lm85_smooth(struct i2c_client *client, int operation, int ctl_name,
23559 + int *nrels_mag, long *results)
23561 + struct lm85_data *data = client->data;
23562 + int nr = ctl_name - LM85_SYSCTL_SMOOTH1 ;
23564 + if (nr < 0 || nr > 2)
23565 + return ; /* ERROR */
23567 + if (operation == SENSORS_PROC_REAL_INFO)
23569 + else if (operation == SENSORS_PROC_REAL_READ) {
23570 + lm85_update_client(client);
23571 + results[0] = SMOOTH_FROM_REG(data->smooth[nr]);
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]);
23580 + lm85_write_value(client, LM85_REG_AFAN_SPIKE1,
23583 + | (data->autofan[0].min_off ? 0x20 : 0)
23584 + | (data->autofan[1].min_off ? 0x40 : 0)
23585 + | (data->autofan[2].min_off ? 0x80 : 0)
23588 + lm85_write_value(client, LM85_REG_AFAN_SPIKE2,
23589 + (data->smooth[1] << 4) | data->smooth[2]);
23591 + up(&data->update_lock);
23595 +void lm85_zone(struct i2c_client *client, int operation, int ctl_name,
23596 + int *nrels_mag, long *results)
23598 + struct lm85_data *data = client->data;
23599 + int nr = ctl_name - LM85_SYSCTL_ZONE1 ;
23601 + /* Limit, Hysteresis (neg), Range, Critical */
23603 + if (nr < 0 || nr > 2)
23604 + return ; /* ERROR */
23606 + if (operation == SENSORS_PROC_REAL_INFO)
23608 + else if (operation == SENSORS_PROC_REAL_READ) {
23609 + lm85_update_client(client);
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;
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 );
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
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
23639 + lm85_write_value(client, LM85_REG_AFAN_HYST2,
23640 + (data->zone[2].hyst << 4)
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
23650 + up(&data->update_lock);
23654 +void lm85_pwm_zone(struct i2c_client *client, int operation, int ctl_name,
23655 + int *nrels_mag, long *results)
23657 + struct lm85_data *data = client->data;
23658 + int nr = ctl_name - LM85_SYSCTL_PWM_ZONE1 ;
23660 + if (nr < 0 || nr > 2)
23661 + return ; /* ERROR */
23663 + if (operation == SENSORS_PROC_REAL_INFO)
23665 + else if (operation == SENSORS_PROC_REAL_READ) {
23666 + lm85_update_client(client);
23667 + results[0] = ZONE_FROM_REG(data->autofan[nr].config);
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);
23678 + up(&data->update_lock);
23682 +void adm1027_temp_offset(struct i2c_client *client, int operation, int ctl_name,
23683 + int *nrels_mag, long *results)
23685 + struct lm85_data *data = client->data;
23686 + int nr = ctl_name - ADM1027_SYSCTL_TEMP_OFFSET1 ;
23688 + if (nr < 0 || nr > 2)
23689 + return ; /* ERROR */
23691 + if (operation == SENSORS_PROC_REAL_INFO)
23693 + else if (operation == SENSORS_PROC_REAL_READ) {
23694 + lm85_update_client(client);
23695 + switch( data->type ) {
23698 + results[0] = TEMP_FROM_REG(data->temp_offset[nr]);
23701 + results[0] = TEMPEXT_FROM_REG(0,data->temp_offset[nr]);
23705 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
23706 + down(&data->update_lock);
23707 + if (*nrels_mag > 0) {
23708 + switch( data->type ) {
23711 + data->temp_offset[nr] = TEMP_TO_REG(results[0]);
23714 + data->temp_offset[nr] = EXTTEMP_TO_REG(results[0]);
23717 + lm85_write_value(client, ADM1027_REG_TEMP_OFFSET(nr),
23718 + data->temp_offset[nr]);
23720 + up(&data->update_lock);
23724 +void adm1027_fan_ppr(struct i2c_client *client, int operation, int ctl_name,
23725 + int *nrels_mag, long *results)
23727 + struct lm85_data *data = client->data;
23730 + if (ctl_name != ADM1027_SYSCTL_FAN_PPR)
23731 + return ; /* ERROR */
23733 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
23748 + if (*nrels_mag > 2) {
23749 + old = (old & ~PPR_MASK(2)) | PPR_TO_REG(results[2],2);
23751 + if (*nrels_mag > 1) {
23752 + old = (old & ~PPR_MASK(1)) | PPR_TO_REG(results[1],1);
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 ;
23759 + up(&data->update_lock);
23763 +void adm1027_alarm_mask(struct i2c_client *client, int operation,
23764 + int ctl_name, int *nrels_mag, long *results)
23766 + struct lm85_data *data = client->data;
23768 + if( ctl_name != ADM1027_SYSCTL_ALARM_MASK )
23769 + return ; /* ERROR */
23771 + if (operation == SENSORS_PROC_REAL_INFO)
23773 + else if (operation == SENSORS_PROC_REAL_READ) {
23774 + lm85_update_client(client);
23775 + results[0] = INTMASK_FROM_REG(data->alarm_mask);
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);
23784 + up(&data->update_lock);
23788 +void adt7463_tmin_ctl(struct i2c_client *client, int operation, int ctl_name,
23789 + int *nrels_mag, long *results)
23791 + struct lm85_data *data = client->data;
23792 + int nr = ctl_name - ADT7463_SYSCTL_TMIN_CTL1 ;
23795 + if (nr < 0 || nr > 2)
23796 + return ; /* ERROR */
23798 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
23815 + if (*nrels_mag > 2) {
23816 + if( results[2] ) {
23817 + old |= (0x0400 << nr) ;
23819 + old &= ~(0x0400 << nr) ;
23822 + if (*nrels_mag > 1) {
23823 + old &= ~(0x07 << (nr*3)) ;
23824 + old |= (results[1] & 0x07) << (nr*3) ;
23826 + if (*nrels_mag > 0) {
23827 + if( results[0] ) {
23828 + old |= 0x2000 << nr ;
23830 + old &= ~(0x2000 << nr) ;
23832 + lm85_write_value(client, ADT7463_REG_TMIN_CTL, old);
23833 + data->tmin_ctl = old ;
23835 + up(&data->update_lock);
23839 +void adt7463_therm_signal(struct i2c_client *client, int operation,
23840 + int ctl_name, int *nrels_mag, long *results)
23842 + struct lm85_data *data = client->data;
23845 + if (ctl_name != ADT7463_SYSCTL_THERM_SIGNAL)
23846 + return ; /* ERROR */
23848 + if (operation == SENSORS_PROC_REAL_INFO)
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
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 ;
23860 + if( counts >= 255 ) {
23861 + ++data->therm_ovfl ;
23863 + up(&data->update_lock);
23865 + results[0] = data->therm_limit ;
23866 + results[1] = data->therm_total ;
23867 + results[2] = data->therm_ovfl ;
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);
23877 + up(&data->update_lock);
23882 +void emc6d100_in(struct i2c_client *client, int operation, int ctl_name,
23883 + int *nrels_mag, long *results)
23885 + struct lm85_data *data = client->data;
23886 + int nr = ctl_name - EMC6D100_SYSCTL_IN5 +5;
23888 + if (nr < 5 || nr > 7)
23889 + return ; /* ERROR */
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]);
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]);
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]);
23911 + up(&data->update_lock);
23916 +static int __init sm_lm85_init(void)
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);
23923 +static void __exit sm_lm85_exit(void)
23925 + i2c_del_driver(&lm85_driver);
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
23932 +MODULE_LICENSE("GPL");
23933 +MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com");
23934 +MODULE_DESCRIPTION("LM85-B, LM85-C driver");
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
23942 + LM87.c - Part of lm_sensors, Linux kernel modules for hardware
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>
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.
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.
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.
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>
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
23980 +Set to '1' the appropriate defines, as nessesary:
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. */
23988 +/* #define LM87_EXT2 1 */
23990 +/* Aux analog input. When enabled, the Fan 1 reading
23991 + will be disabled */
23993 +/* #define LM87_AIN1 1 */
23995 +/* Aux analog input 2. When enabled, the Fan 2 reading
23996 + will be disabled */
23998 +/* #define LM87_AIN2 1 */
24000 +/* Internal Vcc is 5V instead of 3.3V */
24002 +/* #define LM87_5V_VCC 1 */
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. ;') */
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 };
24015 +/* Insmod parameters */
24016 +SENSORS_INSMOD_1(lm87);
24018 +/* The following is the calculation for the register offset
24019 + * for the monitored items minimum and maximum locations.
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))
24025 +/* Initial limits */
24028 + * LM87 register definition
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
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
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
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
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. */
24097 +#define IN_TO_REG(val,nr) (SENSORS_LIMIT(((val) & 0xff),0,255))
24098 +#define IN_FROM_REG(val,nr) (val)
24100 +static inline u8 FAN_TO_REG(long rpm, int div)
24104 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
24105 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
24109 +#define FAN_FROM_REG(val,div) ((val)==0?-1:\
24110 + (val)==255?0:1350000/((div)*(val)))
24112 +#define TEMP_FROM_REG(temp) (temp * 10)
24114 +#define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
24116 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
24117 + ((val)+5)/10),0,255)
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) \
24123 +#define TEMP_LIMIT_FROM_REG(val) (val)
24125 +#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val),0,255)
24129 +#define ALARMS_FROM_REG(val) (val)
24131 +#define DIV_FROM_REG(val) (1 << (val))
24132 +#define DIV_TO_REG(val) ((val)==1?0:((val)==8?3:((val)==4?2:1)))
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
24138 +struct lm87_data {
24139 + struct i2c_client client;
24143 + struct semaphore update_lock;
24144 + char valid; /* !=0 if following fields are valid */
24145 + unsigned long last_updated; /* In jiffies */
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 */
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);
24182 +static int lm87_read_value(struct i2c_client *client, u8 register);
24183 +static int lm87_write_value(struct i2c_client *client, u8 register,
24185 +static void lm87_update_client(struct i2c_client *client);
24186 +static void lm87_init_client(struct i2c_client *client);
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);
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,
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);
24211 +static int lm87_id = 0;
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,
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
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
24260 +/* -- SENSORS SYSCTL END -- */
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. */
24269 +static ctl_table LM87_dir_table_template[] = {
24271 + {LM87_SYSCTL_AIN1, "in6", NULL, 0, 0644, NULL, &i2c_proc_real,
24272 + &i2c_sysctl_real, NULL, &lm87_ain},
24275 + {LM87_SYSCTL_AIN2, "in7", NULL, 0, 0644, NULL, &i2c_proc_real,
24276 + &i2c_sysctl_real, NULL, &lm87_ain},
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},
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},
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
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 */
24308 + {LM87_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, &i2c_proc_real,
24309 + &i2c_sysctl_real, NULL, &lm87_temp},
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},
24326 +static int lm87_attach_adapter(struct i2c_adapter *adapter)
24329 + struct i2c_client_address_data lm87_client_data;
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;
24339 + error = i2c_probe(adapter, &lm87_client_data, lm87_detect);
24340 + i2c_detect(adapter, &addr_data, lm87_detect);
24345 +static int lm87_detect(struct i2c_adapter *adapter, int address,
24346 + unsigned short flags, int kind)
24349 + struct i2c_client *new_client;
24350 + struct lm87_data *data;
24352 + const char *type_name = "";
24353 + const char *client_name = "";
24355 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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. */
24362 + if (!(data = kmalloc(sizeof(struct lm87_data), GFP_KERNEL))) {
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;
24374 + /* Now, we do the remaining detection. */
24377 + if (((lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)
24379 + (lm87_read_value(new_client, LM87_REG_COMPANY_ID) != 0x02))
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;
24389 + new_client->id = lm87_id++;
24391 + init_MUTEX(&data->update_lock);
24393 + /* Tell the I2C layer a new client has arrived */
24394 + if ((err = i2c_attach_client(new_client)))
24397 + /* Register a new directory entry with module sensors */
24398 + if ((i = i2c_register_entry(new_client,
24400 + LM87_dir_table_template)) < 0) {
24404 + data->sysctl_id = i;
24406 + /* Initialize the LM87 chip */
24407 + lm87_init_client(new_client);
24410 +/* OK, this is not exactly good programming practice, usually. But it is
24411 + very code-efficient in this case. */
24414 + i2c_detach_client(new_client);
24422 +static int lm87_detach_client(struct i2c_client *client)
24426 + i2c_deregister_entry(((struct lm87_data *) (client->data))->
24429 + if ((err = i2c_detach_client(client))) {
24431 + ("lm87.o: Client deregistration failed, client not detached.\n");
24435 + kfree(client->data);
24440 +static int lm87_read_value(struct i2c_client *client, u8 reg)
24442 + return 0xFF & i2c_smbus_read_byte_data(client, reg);
24445 +static int lm87_write_value(struct i2c_client *client, u8 reg, u8 value)
24447 + return i2c_smbus_write_byte_data(client, reg, value);
24450 +/* Called when we have found a new LM87. It should set limits, etc. */
24451 +static void lm87_init_client(struct i2c_client *client)
24453 + struct lm87_data *data = client->data;
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);
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
24472 +/* I know, not clean, but it works. :'p */
24473 + lm87_write_value(client, LM87_REG_CHANNEL_MODE,
24492 +#ifdef LM87_5V_VCC
24499 + data->vrm = DEFAULT_VRM;
24501 + /* Start monitoring */
24502 + lm87_write_value(client, LM87_REG_CONFIG, 0x01);
24505 +static void lm87_update_client(struct i2c_client *client)
24507 + struct lm87_data *data = client->data;
24510 + down(&data->update_lock);
24512 + if ((jiffies - data->last_updated > HZ) || /* 1 sec cache */
24513 + (jiffies < data->last_updated) ||
24515 + for (i = 0; i <= 5; 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));
24524 + lm87_read_value(client,LM87_REG_FAN1_AIN1);
24526 + lm87_read_value(client,LM87_REG_AIN1_LOW);
24528 + lm87_read_value(client,LM87_REG_FAN1_AIN1_LIMIT);
24530 + lm87_read_value(client,LM87_REG_FAN2_AIN2);
24532 + lm87_read_value(client,LM87_REG_AIN2_LOW);
24534 + lm87_read_value(client,LM87_REG_FAN2_AIN2_LIMIT);
24537 + lm87_read_value(client, LM87_REG_FAN1_AIN1);
24539 + lm87_read_value(client, LM87_REG_FAN1_AIN1_LIMIT);
24541 + lm87_read_value(client, LM87_REG_FAN2_AIN2);
24543 + lm87_read_value(client, LM87_REG_FAN2_AIN2_LIMIT);
24545 + data->ext2_temp =
24546 + lm87_read_value(client, LM87_REG_2_5V_EXT_TEMP_2);
24548 + lm87_read_value(client, LM87_REG_EXT_TEMP_1);
24550 + lm87_read_value(client, LM87_REG_INT_TEMP);
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);
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);
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);
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;
24572 + (lm87_read_value(client, LM87_REG_VID4) & 0x01)
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;
24582 + up(&data->update_lock);
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)
24602 + long scales[6] = { 250, 270,
24603 +#ifdef LM87_5V_VCC
24608 + 500, 1200, 270 };
24610 + struct lm87_data *data = client->data;
24611 + int nr = ctl_name - LM87_SYSCTL_IN0;
24613 + if (operation == SENSORS_PROC_REAL_INFO)
24615 + else if (operation == SENSORS_PROC_REAL_READ) {
24616 + lm87_update_client(client);
24618 + ((long)data->in_min[nr] * scales[nr]) / 192;
24620 + ((long)data->in_max[nr] * scales[nr]) / 192;
24622 + ((long)data->in[nr] * scales[nr]) / 192;
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]);
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]);
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)
24644 + struct lm87_data *data = client->data;
24646 + if (operation == SENSORS_PROC_REAL_INFO)
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;
24655 + results[0] = data->ain2_min;
24656 + results[1] = data->ain2_max;
24657 + results[2] = data->ain2;
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,
24667 + data->ain2_min = results[0];
24668 + lm87_write_value(client, LM87_REG_AIN2_LOW,
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,
24678 + data->ain2_max = results[1];
24679 + lm87_write_value(client, LM87_REG_FAN2_AIN2_LIMIT,
24687 +void lm87_fan(struct i2c_client *client, int operation, int ctl_name,
24688 + int *nrels_mag, long *results)
24690 + struct lm87_data *data = client->data;
24692 + if (operation == SENSORS_PROC_REAL_INFO)
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));
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));
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],
24713 + (data->fan_div));
24714 + lm87_write_value(client, LM87_REG_FAN1_AIN1_LIMIT,
24717 + data->fan2_min = FAN_TO_REG(results[0],
24719 + (data->fan2_div));
24720 + lm87_write_value(client, LM87_REG_FAN2_AIN2_LIMIT,
24728 +void lm87_temp(struct i2c_client *client, int operation, int ctl_name,
24729 + int *nrels_mag, long *results)
24731 + struct lm87_data *data = client->data;
24733 + if (operation == SENSORS_PROC_REAL_INFO)
24735 + else if (operation == SENSORS_PROC_REAL_READ)
24737 + lm87_update_client(client);
24739 + /* find out which temp. is being requested */
24740 + if (ctl_name == LM87_SYSCTL_TEMP3)
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);
24746 + else if(ctl_name == LM87_SYSCTL_TEMP2)
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);
24752 + else if(ctl_name == LM87_SYSCTL_TEMP1)
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);
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);
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);
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);
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);
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);
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);
24797 +void lm87_alarms(struct i2c_client *client, int operation, int ctl_name,
24798 + int *nrels_mag, long *results)
24800 + struct lm87_data *data = client->data;
24801 + if (operation == SENSORS_PROC_REAL_INFO)
24803 + else if (operation == SENSORS_PROC_REAL_READ) {
24804 + lm87_update_client(client);
24805 + results[0] = ALARMS_FROM_REG(data->alarms);
24810 +void lm87_fan_div(struct i2c_client *client, int operation,
24811 + int ctl_name, int *nrels_mag, long *results)
24813 +/* This gets a little hairy depending on the hardware config */
24815 + struct lm87_data *data = client->data;
24818 + if (operation == SENSORS_PROC_REAL_INFO)
24820 + else if (operation == SENSORS_PROC_REAL_READ) {
24821 + lm87_update_client(client);
24823 + results[0] = DIV_FROM_REG(data->fan_div);
24824 +# ifndef LM87_AIN2
24825 + results[1] = DIV_FROM_REG(data->fan2_div);
24830 +#else /* Must be referring to fan 2 */
24831 + results[0] = DIV_FROM_REG(data->fan2_div);
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 */
24838 + if (*nrels_mag >= 2) {
24839 + data->fan2_div = DIV_TO_REG(results[1]);
24840 + old = (old & 0x3f) | (data->fan2_div << 6);
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);
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);
24857 +void lm87_analog_out(struct i2c_client *client, int operation,
24858 + int ctl_name, int *nrels_mag, long *results)
24860 + struct lm87_data *data = client->data;
24862 + if (operation == SENSORS_PROC_REAL_INFO)
24864 + else if (operation == SENSORS_PROC_REAL_READ) {
24865 + lm87_update_client(client);
24866 + results[0] = data->analog_out;
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);
24877 +void lm87_vid(struct i2c_client *client, int operation, int ctl_name,
24878 + int *nrels_mag, long *results)
24880 + struct lm87_data *data = client->data;
24882 + if (operation == SENSORS_PROC_REAL_INFO)
24884 + else if (operation == SENSORS_PROC_REAL_READ) {
24885 + lm87_update_client(client);
24886 + results[0] = vid_from_reg(data->vid, data->vrm);
24891 +void lm87_vrm(struct i2c_client *client, int operation, int ctl_name,
24892 + int *nrels_mag, long *results)
24894 + struct lm87_data *data = client->data;
24895 + if (operation == SENSORS_PROC_REAL_INFO)
24897 + else if (operation == SENSORS_PROC_REAL_READ) {
24898 + results[0] = data->vrm;
24900 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
24901 + if (*nrels_mag >= 1)
24902 + data->vrm = results[0];
24906 +static int __init sm_lm87_init(void)
24908 + printk("lm87.o version %s (%s)\n", LM_VERSION, LM_DATE);
24909 + return i2c_add_driver(&LM87_driver);
24912 +static void __exit sm_lm87_exit(void)
24914 + i2c_del_driver(&LM87_driver);
24919 +MODULE_LICENSE("GPL");
24922 + ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, "
24923 + "Mark Studebaker <mdsxyz123@yahoo.com>, and Stephen Rousset <stephen.rousset@rocketlogix.com>");
24925 +MODULE_DESCRIPTION("LM87 driver");
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
24933 + * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
24935 + * Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
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
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.
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
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
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).
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.
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.
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.
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.
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"
25003 +#ifndef I2C_DRIVERID_LM90
25004 +#define I2C_DRIVERID_LM90 1042
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.
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 };
25020 + * Insmod parameters
25023 +SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657);
25026 + * The LM90 registers
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
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?
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)
25081 + * Functions declaration
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);
25105 + * Driver data (common to all clients)
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
25118 + * Client data (each client gets its own)
25123 + struct i2c_client client;
25126 + struct semaphore update_lock;
25127 + char valid; /* zero until following fields are valid */
25128 + unsigned long last_updated; /* in jiffies */
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 */
25140 + * These files are created for each detected LM90.
25143 +/* -- SENSORS SYSCTL START -- */
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
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
25161 +/* -- SENSORS SYSCTL END -- */
25164 +static ctl_table lm90_dir_table_template[] =
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},
25184 + * Internal variables
25187 +static int lm90_id = 0;
25193 +static int lm90_attach_adapter(struct i2c_adapter *adapter)
25195 + return i2c_detect(adapter, &addr_data, lm90_detect);
25199 + * The following function does more than just detection. If detection
25200 + * succeeds, it also registers the new chip.
25202 +static int lm90_detect(struct i2c_adapter *adapter, int address,
25203 + unsigned short flags, int kind)
25205 + struct i2c_client *new_client;
25206 + struct lm90_data *data;
25208 + const char *type_name = "";
25209 + const char *client_name = "";
25212 + if (i2c_is_isa_adapter(adapter))
25214 + printk("lm90.o: Called for an ISA bus adapter, aborting.\n");
25219 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
25222 + printk("lm90.o: I2C bus doesn't support byte read mode, "
25228 + if (!(data = kmalloc(sizeof(struct lm90_data), GFP_KERNEL)))
25230 + printk("lm90.o: Out of memory in lm90_detect (new_client).\n");
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.
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;
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
25258 + /* Default to an LM90 if forced */
25262 + if (kind < 0) /* detection and identification */
25264 + u8 man_id, chip_id, reg_config1, reg_convrate;
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);
25275 + if (man_id == 0x01) /* National Semiconductor */
25279 + reg_config2 = i2c_smbus_read_byte_data(new_client,
25280 + LM90_REG_R_CONFIG2);
25282 + if ((reg_config1 & 0x2A) == 0x00
25283 + && (reg_config2 & 0xF8) == 0x00
25284 + && reg_convrate <= 0x09)
25286 + if (address == 0x4C
25287 + && (chip_id & 0xF0) == 0x20) /* LM90 */
25289 + else if ((chip_id & 0xF0) == 0x30) /* LM89/LM99 */
25291 + else if (address == 0x4C
25292 + && (chip_id & 0xF0) == 0x10) /* LM86 */
25296 + else if (man_id == 0x41) /* Analog Devices */
25298 + if (address == 0x4C
25299 + && (chip_id & 0xF0) == 0x40 /* ADM1032 */
25300 + && (reg_config1 & 0x3F) == 0x00
25301 + && reg_convrate <= 0x0A)
25304 + else if (man_id == 0x4D) /* Maxim */
25306 + if (address == 0x4C
25307 + && (reg_config1 & 0x1F) == 0
25308 + && reg_convrate <= 0x09)
25313 + if (kind <= 0) /* identification failed */
25315 + printk("lm90.o: Unsupported chip.\n");
25319 + if (kind == lm90)
25321 + type_name = "lm90";
25322 + client_name = "LM90 chip";
25324 + else if (kind == adm1032)
25326 + type_name = "adm1032";
25327 + client_name = "ADM1032 chip";
25329 + else if (kind == lm99)
25331 + type_name = "lm99";
25332 + client_name = "LM99 chip";
25334 + else if (kind == lm86)
25336 + type_name = "lm86";
25337 + client_name = "LM86 chip";
25339 + else if (kind == max6657)
25341 + type_name = "max6657";
25342 + client_name = "MAX6657 chip";
25346 + printk("lm90.o: Unknown kind %d.\n", kind);
25351 + * OK, we got a valid chip so we can fill in the remaining client
25355 + strcpy(new_client->name, client_name);
25356 + new_client->id = lm90_id++;
25358 + init_MUTEX(&data->update_lock);
25361 + * Tell the I2C layer a new client has arrived.
25364 + if ((err = i2c_attach_client(new_client)))
25367 + printk("lm90.o: Failed attaching client.\n");
25373 + * Register a new directory entry.
25376 + if ((err = i2c_register_entry(new_client, type_name,
25377 + lm90_dir_table_template)) < 0)
25380 + printk("lm90.o: Failed registering directory entry.\n");
25384 + data->sysctl_id = err;
25387 + * Initialize the LM90 chip.
25390 + lm90_init_client(new_client);
25394 + i2c_detach_client(new_client);
25400 +static void lm90_init_client(struct i2c_client *client)
25405 + * Start the conversions.
25408 + i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE,
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 */
25417 +static int lm90_detach_client(struct i2c_client *client)
25421 + i2c_deregister_entry(((struct lm90_data *) (client->data))->sysctl_id);
25422 + if ((err = i2c_detach_client(client)))
25424 + printk("lm90.o: Client deregistration failed, client not "
25429 + kfree(client->data);
25433 +static void lm90_update_client(struct i2c_client *client)
25435 + struct lm90_data *data = client->data;
25437 + down(&data->update_lock);
25439 + if ((jiffies - data->last_updated > HZ * 2) ||
25440 + (jiffies < data->last_updated) || !data->valid)
25444 + printk("lm90.o: Updating data.\n");
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);
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.
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);
25476 + i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_TEMPH);
25477 + if (newh != oldh)
25479 + data->remote_temp =
25480 + i2c_smbus_read_byte_data(client, LM90_REG_R_REMOTE_TEMPL);
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");
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);
25499 + i2c_smbus_read_byte_data(client, LM90_REG_R_TCRIT_HYST);
25501 + i2c_smbus_read_byte_data(client, LM90_REG_R_STATUS);
25503 + data->last_updated = jiffies;
25507 + up(&data->update_lock);
25510 +static void lm90_local_temp(struct i2c_client *client, int operation,
25511 + int ctl_name, int *nrels_mag, long *results)
25513 + struct lm90_data *data = client->data;
25515 + if (operation == SENSORS_PROC_REAL_INFO)
25516 + *nrels_mag = 0; /* magnitude */
25517 + else if (operation == SENSORS_PROC_REAL_READ)
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);
25525 + else if (operation == SENSORS_PROC_REAL_WRITE)
25527 + if (*nrels_mag >= 1)
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);
25533 + if (*nrels_mag >= 2)
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);
25542 +static void lm90_remote_temp(struct i2c_client *client, int operation,
25543 + int ctl_name, int *nrels_mag, long *results)
25545 + struct lm90_data *data = client->data;
25547 + if (operation == SENSORS_PROC_REAL_INFO)
25548 + *nrels_mag = 1; /* magnitude */
25549 + else if (operation == SENSORS_PROC_REAL_READ)
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);
25557 + else if (operation == SENSORS_PROC_REAL_WRITE)
25559 + if (*nrels_mag >= 1)
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);
25567 + if (*nrels_mag >= 2)
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);
25578 +static void lm90_local_tcrit(struct i2c_client *client, int operation,
25579 + int ctl_name, int *nrels_mag, long *results)
25581 + struct lm90_data *data = client->data;
25583 + if (operation == SENSORS_PROC_REAL_INFO)
25584 + *nrels_mag = 0; /* magnitude */
25585 + else if (operation == SENSORS_PROC_REAL_READ)
25587 + lm90_update_client(client);
25588 + results[0] = TEMP1_FROM_REG(data->local_crit);
25591 + else if (operation == SENSORS_PROC_REAL_WRITE)
25593 + if (*nrels_mag >= 1)
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);
25602 +static void lm90_remote_tcrit(struct i2c_client *client, int operation,
25603 + int ctl_name, int *nrels_mag, long *results)
25605 + struct lm90_data *data = client->data;
25607 + if (operation == SENSORS_PROC_REAL_INFO)
25608 + *nrels_mag = 0; /* magnitude */
25609 + else if (operation == SENSORS_PROC_REAL_READ)
25611 + lm90_update_client(client);
25612 + results[0] = TEMP1_FROM_REG(data->remote_crit);
25615 + else if (operation == SENSORS_PROC_REAL_WRITE)
25617 + if (*nrels_mag >= 1)
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);
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).
25641 +static void lm90_local_hyst(struct i2c_client *client, int operation,
25642 + int ctl_name, int *nrels_mag, long *results)
25644 + struct lm90_data *data = client->data;
25646 + if (operation == SENSORS_PROC_REAL_INFO)
25647 + *nrels_mag = 0; /* magnitude */
25648 + else if (operation == SENSORS_PROC_REAL_READ)
25650 + lm90_update_client(client);
25651 + results[0] = TEMP1_FROM_REG(data->local_crit) -
25652 + TEMP1_FROM_REG(data->hyst);
25655 + else if (operation == SENSORS_PROC_REAL_WRITE)
25657 + if (*nrels_mag >= 1)
25659 + data->hyst = HYST_TO_REG(data->local_crit - results[0]);
25660 + i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
25666 +static void lm90_remote_hyst(struct i2c_client *client, int operation,
25667 + int ctl_name, int *nrels_mag, long *results)
25669 + struct lm90_data *data = client->data;
25671 + if (operation == SENSORS_PROC_REAL_INFO)
25672 + *nrels_mag = 0; /* magnitude */
25673 + else if (operation == SENSORS_PROC_REAL_READ)
25675 + lm90_update_client(client);
25676 + results[0] = TEMP1_FROM_REG(data->remote_crit) -
25677 + TEMP1_FROM_REG(data->hyst);
25682 +static void lm90_alarms(struct i2c_client *client, int operation,
25683 + int ctl_name, int *nrels_mag, long *results)
25685 + struct lm90_data *data = client->data;
25687 + if (operation == SENSORS_PROC_REAL_INFO)
25688 + *nrels_mag = 0; /* magnitude */
25689 + else if (operation == SENSORS_PROC_REAL_READ)
25691 + lm90_update_client(client);
25692 + results[0] = data->alarms;
25697 +static int __init sm_lm90_init(void)
25699 + printk(KERN_INFO "lm90.o version %s (%s)\n", LM_VERSION, LM_DATE);
25700 + return i2c_add_driver(&lm90_driver);
25703 +static void __exit sm_lm90_exit(void)
25705 + i2c_del_driver(&lm90_driver);
25708 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
25709 +MODULE_DESCRIPTION("LM90/ADM1032 sensor driver");
25710 +MODULE_LICENSE("GPL");
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
25719 + * LM92 - Part of lm_sensors, Linux kernel modules for hardware
25722 + * Author: Abraham van der Merwe <abraham@2d3d.co.za>
25724 + * Linux support for the National Semiconductor LM92 Temperature
25727 + * Based on code from the lm-sensors project which is available
25728 + * at http://www.lm-sensors.nu/. lm87.c have been particularly
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.
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"
25750 +/* if defined, 4 faults must occur consecutively to set alarm flags */
25751 +/* #define ENABLE_FAULT_QUEUE */
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 */
25761 +#define LM92_MANUFACTURER_ID 0x8001
25763 +#define TEMP_MIN (-4096)
25764 +#define TEMP_MAX 4095
25766 +#define LIMIT(x) do { \
25767 + if ((x) < TEMP_MIN) (x) = TEMP_MIN; \
25768 + if ((x) > TEMP_MAX) (x) = TEMP_MAX; \
25771 +#define PROC_TO_NATIVE(x) ((x) / 625)
25772 +#define NATIVE_TO_PROC(x) ((x) * 625)
25773 +#define CELSIUS(x) ((x) * 16)
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);
25778 +/* -- SENSORS SYSCTL START -- */
25779 +#define LM92_SYSCTL_ALARMS 2001 /* high, low, critical */
25780 +#define LM92_SYSCTL_TEMP 1200 /* high, low, critical, hysteresis, input */
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
25791 +/* -- SENSORS SYSCTL END -- */
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},
25801 +/* NOTE: all temperatures are degrees centigrade * 16 */
25803 + struct i2c_client client;
25805 + unsigned long timestamp;
25820 +/* this is needed for each client driver method */
25821 +static struct i2c_driver lm92_driver;
25823 +/* ensure exclusive access to chip and static variables */
25824 +static DECLARE_MUTEX (mutex);
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 };
25832 +/* insmod parameters */
25833 +SENSORS_INSMOD_1 (lm92);
25835 +static inline int lm92_write8 (struct i2c_client *client,u8 reg,u8 value)
25837 + return (i2c_smbus_write_byte_data (client,reg,value) < 0 ? -EIO : 0);
25840 +static inline int lm92_read16 (struct i2c_client *client,u8 reg,u16 *value)
25842 + s32 tmp = i2c_smbus_read_word_data (client,reg);
25844 + if (tmp < 0) return (-EIO);
25846 + /* convert the data to little endian format */
25847 + *value = swab16((u16) tmp);
25852 +static inline int lm92_write16 (struct i2c_client *client,u8 reg,u16 value)
25854 + /* convert the data to big endian format */
25855 + if (i2c_smbus_write_word_data(client, reg, swab16(value)) < 0)
25861 +static int lm92_read (struct i2c_client *client)
25863 + lm92_t *data = (lm92_t *) client->data;
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)
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;
25880 + data->alarms.low = value[0] & 1;
25881 + data->alarms.high = (value[0] & 2) >> 1;
25882 + data->alarms.crit = (value[0] & 4) >> 2;
25884 + data->timestamp = jiffies;
25890 +static int lm92_write (struct i2c_client *client)
25892 + lm92_t *data = (lm92_t *) client->data;
25894 + LIMIT (data->temp.hyst);
25895 + LIMIT (data->temp.crit);
25896 + LIMIT (data->temp.low);
25897 + LIMIT (data->temp.high);
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)
25908 +static void lm92_temp (struct i2c_client *client,int operation,int ctl_name,int *nrels_mag,long *results)
25910 + if (!down_interruptible (&mutex)) {
25911 + lm92_t *data = (lm92_t *) client->data;
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);
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) {
25935 +static void lm92_alarms (struct i2c_client *client,int operation,int ctl_name,int *nrels_mag,long *results)
25937 + if (!down_interruptible (&mutex)) {
25938 + lm92_t *data = (lm92_t *) client->data;
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);
25944 + } else if (operation == SENSORS_PROC_REAL_INFO) {
25952 +static int max6635_check(struct i2c_client *client)
25955 + u16 temp_low, temp_high, temp_hyst, temp_crit;
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);
25963 + if ((temp_low & 0x7f00) || (temp_high & 0x7f00)
25964 + || (temp_hyst & 0x7f00) || (temp_crit & 0x7f00))
25967 + conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIGURATION);
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))
25981 +static int lm92_init_client (struct i2c_client *client)
25983 + lm92_t *data = (lm92_t *) client->data;
25987 + /* force reads to query the chip */
25988 + data->timestamp = 0;
25990 + /* setup the configuration register */
25992 +#ifdef ENABLE_FAULT_QUEUE
25994 +#endif /* #ifdef ENABLE_FAULT_QUEUE */
25996 + if (lm92_write8 (client,LM92_REG_CONFIGURATION,value) < 0)
25997 + return (-ENODEV);
25999 + /* set default alarm trigger values */
26001 + data->temp.high = CELSIUS (64);
26002 + data->temp.low = CELSIUS (10);
26003 + data->temp.crit = CELSIUS (80);
26004 + data->temp.hyst = CELSIUS (2);
26006 + if ((result = lm92_write (client)) < 0)
26009 + /* read everything once so that our cached data is updated */
26011 + if ((result = lm92_read (client)) < 0)
26017 +static int lm92_detect (struct i2c_adapter *adapter,int address,unsigned short flags,int kind)
26019 + static int id = 0;
26020 + struct i2c_client *client;
26023 + u16 manufacturer;
26025 + if (!i2c_check_functionality (adapter,I2C_FUNC_SMBUS_BYTE_DATA))
26026 + return (-ENODEV);
26028 + if (!(data = kmalloc(sizeof(lm92_t), GFP_KERNEL)))
26029 + return (-ENOMEM);
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);
26039 + if (down_interruptible (&mutex)) {
26040 + result = -ERESTARTSYS;
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;
26057 + if ((result = i2c_attach_client (client))) {
26061 + if ((result = i2c_register_entry (client,client->name,lm92_dir_table)) < 0) {
26064 + data->sysctl_id = result;
26066 + if ((result = lm92_init_client (client)) < 0) {
26070 + client->id = id++;
26077 + i2c_deregister_entry(data->sysctl_id);
26079 + i2c_detach_client(client);
26087 +static int lm92_attach_adapter (struct i2c_adapter *adapter)
26089 + return i2c_detect (adapter,&addr_data,lm92_detect);
26092 +static int lm92_detach_client (struct i2c_client *client)
26096 + i2c_deregister_entry (((lm92_t *) (client->data))->sysctl_id);
26098 + if ((result = i2c_detach_client (client)))
26101 + kfree(client->data);
26107 +static struct i2c_driver lm92_driver = {
26108 + .owner = THIS_MODULE,
26110 + .id = I2C_DRIVERID_LM92,
26111 + .flags = I2C_DF_NOTIFY,
26112 + .attach_adapter = lm92_attach_adapter,
26113 + .detach_client = lm92_detach_client,
26116 +static int __init sm_lm92_init(void)
26118 + printk ("lm92.o version %s (%s)\n",LM_VERSION,LM_DATE);
26119 + return i2c_add_driver(&lm92_driver);
26123 +static void __exit sm_lm92_exit(void)
26125 + i2c_del_driver(&lm92_driver);
26130 +MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
26131 +MODULE_DESCRIPTION ("Linux support for LM92 Temperature Sensor");
26133 +MODULE_LICENSE ("GPL");
26135 +module_init(sm_lm92_init);
26136 +module_exit(sm_lm92_exit);
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
26142 + matorb.c - Part of lm_sensors, Linux kernel modules for hardware
26144 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
26145 + and Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
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"
26173 +MODULE_LICENSE("GPL");
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 };
26181 +/* Insmod parameters */
26182 +SENSORS_INSMOD_1(matorb);
26184 +/* Many MATORB constants specified below */
26187 +/* Each client has this additional data */
26188 +struct matorb_data {
26189 + struct i2c_client client;
26192 + struct semaphore update_lock;
26193 + char valid; /* !=0 if following fields are valid */
26194 + unsigned long last_updated; /* In jiffies */
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);
26204 +static int matorb_write_value(struct i2c_client *client, u8 reg,
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);
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,
26221 +/* -- SENSORS SYSCTL START -- */
26222 +#define MATORB_SYSCTL_DISP 1000
26223 +/* -- SENSORS SYSCTL END -- */
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},
26236 +static int matorb_id = 0;
26238 +static int matorb_attach_adapter(struct i2c_adapter *adapter)
26240 + return i2c_detect(adapter, &addr_data, matorb_detect);
26243 +/* This function is called by i2c_detect */
26244 +int matorb_detect(struct i2c_adapter *adapter, int address,
26245 + unsigned short flags, int kind)
26248 + struct i2c_client *new_client;
26249 + struct matorb_data *data;
26251 + const char *type_name = "matorb";
26252 + const char *client_name = "matorb";
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. */
26257 + if (i2c_is_isa_adapter(adapter)) {
26259 + ("matorb.o: matorb_detect called for an ISA bus adapter?!?\n");
26264 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE |
26265 + I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
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))) {
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;
26284 + /* Now, we do the remaining detection. It is lousy. */
26285 + cur = i2c_smbus_write_byte_data(new_client, 0x0FE, 0x58); /* clear screen */
26287 + printk("matorb.o: debug detect 0x%X\n", cur);
26289 + /* Fill in the remaining client fields and put it into the global list */
26290 + strcpy(new_client->name, client_name);
26292 + new_client->id = matorb_id++;
26294 + init_MUTEX(&data->update_lock);
26296 + /* Tell the I2C layer a new client has arrived */
26297 + if ((err = i2c_attach_client(new_client)))
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) {
26306 + data->sysctl_id = i;
26308 + matorb_init_client(new_client);
26311 +/* OK, this is not exactly good programming practice, usually. But it is
26312 + very code-efficient in this case. */
26315 + i2c_detach_client(new_client);
26322 +static int matorb_detach_client(struct i2c_client *client)
26326 + i2c_deregister_entry(((struct matorb_data *) (client->data))->
26329 + if ((err = i2c_detach_client(client))) {
26331 + ("matorb.o: Client deregistration failed, client not detached.\n");
26335 + kfree(client->data);
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)
26347 + return -1; /* Doesn't support reads */
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)
26357 + return i2c_smbus_write_byte(client, value);
26359 + return i2c_smbus_write_byte_data(client, reg, value);
26363 +static void matorb_init_client(struct i2c_client *client)
26365 + /* Initialize the MATORB chip */
26368 +static void matorb_update_client(struct i2c_client *client)
26370 + struct matorb_data *data = client->data;
26372 + down(&data->update_lock);
26374 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
26375 + (jiffies < data->last_updated) || !data->valid) {
26378 + printk("Starting matorb update\n");
26382 + data->last_updated = jiffies;
26386 + up(&data->update_lock);
26390 +void matorb_disp(struct i2c_client *client, int operation, int ctl_name,
26391 + int *nrels_mag, long *results)
26395 + if (operation == SENSORS_PROC_REAL_INFO)
26397 + else if (operation == SENSORS_PROC_REAL_READ) {
26398 + matorb_update_client(client);
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]);
26408 +static int __init sm_matorb_init(void)
26410 + printk("matorb.o version %s (%s)\n", LM_VERSION, LM_DATE);
26411 + return i2c_add_driver(&matorb_driver);
26414 +static void __exit sm_matorb_exit(void)
26416 + i2c_del_driver(&matorb_driver);
26422 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
26423 +MODULE_DESCRIPTION("MATORB driver");
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
26431 + * max6650.c - Part of lm_sensors, Linux kernel modules for hardware
26434 + * Author: John Morris <john.morris@spirentcom.com>
26436 + * Copyright (c) 2003 Spirent Communications
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.
26442 + * Tha datasheet was last seen at:
26444 + * http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
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.
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.
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.
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"
26470 +#ifndef I2C_DRIVERID_MAX6650
26471 +#define I2C_DRIVERID_MAX6650 1044
26475 + * Addresses to scan. There are four disjoint possibilities, by pin config.
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 };
26484 + * Insmod parameters
26487 +SENSORS_INSMOD_1(max6650);
26490 + * MAX 6650/6651 registers
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
26507 + * Config register bits
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
26516 +static const u8 tach_reg[] =
26518 + MAX6650_REG_TACH0, MAX6650_REG_TACH1,
26519 + MAX6650_REG_TACH2, MAX6650_REG_TACH3
26522 +#define MAX6650_INT_CLK 254000 /* Default clock speed - 254 kHz */
26525 + * Functions declaration
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);
26542 + * Driver data (common to all clients)
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
26556 + * Client data (each client gets its own)
26559 +struct max6650_data
26561 + struct i2c_client client;
26563 + struct semaphore update_lock;
26564 + char valid; /* zero until following fields are valid */
26565 + unsigned long last_updated; /* in jiffies */
26567 + /* register values */
26577 + * These files are created for each detected max6650.
26580 +/* -- SENSORS SYSCTL START -- */
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
26590 +/* -- SENSORS SYSCTL END -- */
26593 +static ctl_table max6650_dir_table_template[] =
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},
26611 + * Internal variables
26614 +static int max6650_id = 0;
26620 +static int max6650_attach_adapter(struct i2c_adapter *adapter)
26622 + return i2c_detect(adapter, &addr_data, max6650_detect);
26626 + * The following function does more than just detection. If detection
26627 + * succeeds, it also registers the new chip.
26630 +static int max6650_detect(struct i2c_adapter *adapter, int address, unsigned
26631 + short flags, int kind)
26633 + struct i2c_client *new_client;
26634 + struct max6650_data *data;
26636 + const char *type_name = "";
26637 + const char *client_name = "";
26640 + if (i2c_is_isa_adapter(adapter)) {
26641 + printk("max6650.o: Called for an ISA bus adapter, aborting.\n");
26646 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
26648 + printk("max6650.o: I2C bus doesn't support byte read mode, skipping.\n");
26653 + if (!(data = kmalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
26654 + printk("max6650.o: Out of memory in max6650_detect (new_client).\n");
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.
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;
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
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.
26686 + if (kind < 0) { /* detection */
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)
26696 + printk("max6650.o: max6650 detection failed at 0x%02x.\n",
26703 + if (kind <= 0) { /* identification */
26707 + if (kind <= 0) { /* identification failed */
26708 + printk("max6650.o: Unsupported chip.\n");
26712 + if (kind == max6650) {
26713 + type_name = "max6650";
26714 + client_name = "max6650 chip";
26716 + printk("max6650.o: Unknown kind %d.\n", kind);
26721 + * OK, we got a valid chip so we can fill in the remaining client
26725 + strcpy(new_client->name, client_name);
26726 + new_client->id = max6650_id++;
26728 + init_MUTEX(&data->update_lock);
26731 + * Tell the I2C layer a new client has arrived.
26734 + if ((err = i2c_attach_client(new_client))) {
26736 + printk("max6650.o: Failed attaching client.\n");
26742 + * Register a new directory entry.
26744 + if ((err = i2c_register_entry(new_client, type_name,
26745 + max6650_dir_table_template)) < 0) {
26747 + printk("max6650.o: Failed registering directory entry.\n");
26751 + data->sysctl_id = err;
26754 + * Initialize the max6650 chip
26756 + max6650_init_client(new_client);
26760 + i2c_detach_client(new_client);
26766 +static void max6650_init_client(struct i2c_client *client)
26768 + /* Nothing to do here - assume the BIOS has initialized the chip */
26771 +static int max6650_detach_client(struct i2c_client *client)
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");
26782 + kfree(client->data);
26786 +static int max6650_read(struct i2c_client *client, u8 reg)
26788 + return i2c_smbus_read_byte_data(client, reg);
26791 +static int max6650_write(struct i2c_client *client, u8 reg, u8 value)
26793 + return i2c_smbus_write_byte_data(client, reg, value);
26796 +static void max6650_update_client(struct i2c_client *client)
26799 + struct max6650_data *data = client->data;
26801 + down(&data->update_lock);
26803 + if ((jiffies - data->last_updated > HZ) ||
26804 + (jiffies < data->last_updated) || !data->valid) {
26806 + printk("max6650.o: Updating max6650 data.\n");
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]);
26813 + data->count = max6650_read (client, MAX6650_REG_COUNT);
26814 + data->last_updated = jiffies;
26817 + up(&data->update_lock);
26820 +static void max6650_fan (struct i2c_client *client, int operation, int
26821 + ctl_name, int *nrels_mag, long *results)
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 */
26827 + if (operation == SENSORS_PROC_REAL_INFO) {
26829 + } else if (operation == SENSORS_PROC_REAL_READ) {
26830 + max6650_update_client(client);
26833 + * Calculation details:
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).
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 */
26849 + * Set the fan speed to the specified RPM (or read back the RPM setting).
26851 + * The MAX6650/1 will automatically control fan speed when in closed loop
26856 + * 1) The MAX6650/1 is running from its internal 254kHz clock (perhaps
26857 + * this should be made a module parameter).
26859 + * 2) The prescaler (low three bits of the config register) has already
26860 + * been set to an appropriate value.
26862 + * The relevant equations are given on pages 21 and 22 of the datasheet.
26864 + * From the datasheet, the relevant equation when in regulation is:
26866 + * [fCLK / (128 x (KTACH + 1))] = 2 x FanSpeed / KSCALE
26870 + * fCLK is the oscillator frequency (either the 254kHz internal
26871 + * oscillator or the externally applied clock)
26873 + * KTACH is the value in the speed register
26875 + * FanSpeed is the speed of the fan in rps
26877 + * KSCALE is the prescaler value (1, 2, 4, 8, or 16)
26879 + * When reading, we need to solve for FanSpeed. When writing, we need to
26880 + * solve for KTACH.
26882 + * Note: this tachometer is completely separate from the tachometers
26883 + * used to measure the fan speeds. Only one fan's speed (fan1) is
26887 +static void max6650_speed (struct i2c_client *client, int operation, int
26888 + ctl_name, int *nrels_mag, long *results)
26890 + struct max6650_data *data = client->data;
26891 + int kscale, ktach, fclk, rpm;
26893 + if (operation == SENSORS_PROC_REAL_INFO) {
26895 + } else if (operation == SENSORS_PROC_REAL_READ) {
26897 + * Use the datasheet equation:
26899 + * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)]
26901 + * then multiply by 60 to give rpm.
26904 + max6650_update_client(client);
26906 + kscale = 1 << (data->config & 7);
26907 + ktach = data->speed;
26908 + fclk = MAX6650_INT_CLK;
26909 + rpm = 60 * kscale * fclk / (256 * (ktach + 1));
26911 + results[0] = rpm;
26913 + } else if (operation == SENSORS_PROC_REAL_WRITE && *nrels_mag >= 1) {
26915 + * Divide the required speed by 60 to get from rpm to rps, then
26916 + * use the datasheet equation:
26918 + * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1
26921 + max6650_update_client(client);
26923 + rpm = results[0];
26924 + kscale = 1 << (data->config & 7);
26925 + fclk = MAX6650_INT_CLK;
26926 + ktach = ((fclk * kscale) / (256 * rpm / 60)) - 1;
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);
26937 + * Debug - dump all registers except the tach counts.
26940 +static void max6650_xdump (struct i2c_client *client, int operation, int
26941 + ctl_name, int *nrels_mag, long *results)
26943 + if (operation == SENSORS_PROC_REAL_INFO) {
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);
26958 +static int __init sm_max6650_init(void)
26960 + printk(KERN_INFO "max6650.o version %s (%s)\n", LM_VERSION, LM_DATE);
26961 + return i2c_add_driver(&max6650_driver);
26964 +static void __exit sm_max6650_exit(void)
26966 + i2c_del_driver(&max6650_driver);
26969 +MODULE_AUTHOR("john.morris@spirentcom.com");
26970 +MODULE_DESCRIPTION("max6650 sensor driver");
26971 +MODULE_LICENSE("GPL");
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
26979 + maxilife.c - Part of lm_sensors, Linux kernel modules for hardware
26981 + Copyright (c) 1999-2000 Fons Rademakers <Fons.Rademakers@cern.ch>
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.
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.
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.
26998 +/* The is the driver for the HP MaxiLife Health monitoring system
26999 + as used in the line of HP Kayak Workstation PC's.
27001 + The driver supports the following MaxiLife firmware versions:
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)
27007 + Currently firmware auto detection is not implemented. To use the
27008 + driver load it with the correct option for you Kayak. For example:
27010 + insmod maxilife.o maxi_version=0 | 1 | 2
27012 + maxi_version=0 is the default
27014 + This version of MaxiLife is called MaxiLife'98 and has been
27015 + succeeded by MaxiLife'99, see below.
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.
27028 +static const char *version_str = "2.00 29/2/2000 Fons Rademakers";
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"
27039 +MODULE_LICENSE("GPL");
27041 +#undef AUTODETECT /* try to autodetect MaxiLife version */
27042 +/*#define AUTODETECT*/
27043 +#define NOWRITE /* don't allow writing to MaxiLife registers */
27046 +#include <linux/vmalloc.h>
27047 +#include <linux/ctype.h>
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 };
27056 +/* Insmod parameters */
27057 +SENSORS_INSMOD_1(maxilife);
27059 +/* Macro definitions */
27060 +#define LOW(MyWord) ((u8) (MyWord))
27061 +#define HIGH(MyWord) ((u8) (((u16)(MyWord) >> 8) & 0xFF))
27063 +/*----------------- MaxiLife'98 registers and conversion formulas ------------*/
27064 +#define MAXI_REG_TEMP(nr) (0x60 + (nr))
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)
27071 +#define MAXI_REG_PLL 0xb9
27072 +#define MAXI_REG_PLL_MIN 0xba
27073 +#define MAXI_REG_PLL_MAX 0xbb
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
27080 +#define MAXI_REG_DIAG_RT1 0x2c
27081 +#define MAXI_REG_DIAG_RT2 0x2d
27083 +#define MAXI_REG_BIOS_CTRL 0x2a
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. */
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)))
27095 +static inline u8 FAN_TO_REG(long rpm)
27099 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
27100 + return SENSORS_LIMIT((1171860 + rpm / 2) / (rpm), 1, 254);
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),\
27108 +#define VID_FROM_REG(val) ((val) ? (((val) * 27390) / 256) + 3208 : 0)
27109 +#define VID_TO_REG(val) (SENSORS_LIMIT((((val) - 3208) * 256) / 27390, \
27111 +#define ALARMS_FROM_REG(val) (val)
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
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 */
27127 +/* Mailbox command register opcodes */
27128 +#define MAXI_CMD_READ 0x02
27129 +#define MAXI_CMD_WRITE 0x03
27130 +/* other values not used */
27132 +/* MaxiLife NBA Hardware monitoring tokens */
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 */
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 */
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 */
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 */
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 */
27177 +/* Threshold tokens (0x3xxx) */
27178 +#define MAXI_TOK_MIN(token) ((token) + 0x1000)
27179 +#define MAXI_TOK_MAX(token) ((token) + 0x1800)
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
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))
27192 + /* when no CPU2 temp is 127 (0x7f) */
27193 +#define TEMP99_FROM_REG(val) ((val)==0x7f ? -1 : (val)==0xff ? -1 : (val))
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)
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, ... */
27210 +enum maxi_type { cristal, cognac, ashaki, nba };
27211 +enum sensor_type { fan, temp, vid, pll, lcd, alarm };
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;
27222 + enum maxi_type type;
27224 + struct semaphore update_lock;
27225 + char valid; /* !=0 if following fields are valid */
27226 + unsigned long last_updated; /* In jiffies */
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 */
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);
27251 +static int maxi_read_value(struct i2c_client *client, u8 register);
27252 +static int maxi_read_token(struct i2c_client *client, u16 token);
27254 +static int maxi_write_value(struct i2c_client *client, u8 register,
27257 +static int maxi_write_token_loop(struct i2c_client *client, u16 token,
27258 + u8 len, u8 * values);
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);
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);
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,
27295 +static int maxi_id = 0;
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;
27301 +/* The /proc/sys entries */
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) */
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
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 */
27343 +/* -- SENSORS SYSCTL END -- */
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},
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)
27402 + return i2c_detect(adapter, &addr_data, maxi_detect);
27405 +/* This function is called by i2c_detect */
27406 +int maxi_detect(struct i2c_adapter *adapter, int address,
27407 + unsigned short flags, int kind)
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;
27415 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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))) {
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;
27434 + /* Now we do the remaining detection. */
27436 + if (i2c_smbus_read_byte_data
27437 + (new_client, MAXI_REG_MBX_STATUS) < 0)
27441 + /* Determine the chip type - only one kind supported */
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) */
27454 + i2c_smbus_write_byte_data(new_client, MAXI_REG_MBX_STATUS,
27457 + i2c_smbus_read_byte_data(new_client,
27458 + MAXI_REG_MBX_STATUS);
27460 + /*if (stat == MAXI_STAT_IDLE || stat == MAXI_STAT_OK) */
27461 + if (stat != 0x55)
27462 + maxi_version = nba;
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] */
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,
27479 + err = eeprom_read_byte_data(adapter, 0x54, 0x45);
27480 + i2c_smbus_write_byte_data(new_client,
27481 + MAXI_REG_BIOS_CTRL,
27485 + char *biosmem, *bm;
27486 + bm = biosmem = ioremap(0xe0000, 0x20000);
27488 + printk("begin of bios search\n");
27489 + for (i = 0; i < 0x20000; i++) {
27490 + if (*bm == 'C') {
27492 + while (s && isprint(*s)) {
27493 + printk("%c", *s);
27498 + (bm, "CG 00.04", 8)) {
27502 + ("maxilife: found MaxiLife Rev CG 00.04\n");
27506 + (bm, "CO 00.03", 8)) {
27510 + ("maxilife: found MaxiLife Rev CO 00.03\n");
27514 + if (*bm == 'A' && *(bm + 1) == 'S') {
27516 + while (s && isprint(*s)) {
27517 + printk("%c", *s);
27522 + (bm, "AS 00.01", 8)) {
27526 + ("maxilife: found MaxiLife Rev AS 00.01\n");
27532 + printk("end of bios search\n");
27534 + printk("could not map bios memory\n");
27538 + if (maxi_version == cristal) {
27540 + type_name = "maxilife-cg";
27541 + client_name = "HP MaxiLife Rev CG 00.04";
27543 + ("maxilife: HP KAYAK XU/XAs (Dual Pentium II Slot 1)\n");
27544 + } else if (maxi_version == cognac) {
27546 + type_name = "maxilife-co";
27547 + client_name = "HP MaxiLife Rev CO 00.03";
27549 + ("maxilife: HP KAYAK XU (Dual Xeon Slot 2 400/450 Mhz)\n");
27550 + } else if (maxi_version == ashaki) {
27552 + type_name = "maxilife-as";
27553 + client_name = "HP MaxiLife Rev AS 00.01";
27555 + ("maxilife: HP KAYAK XA (Pentium II Slot 1, monoprocessor)\n");
27556 + } else if (maxi_version == nba) {
27558 + type_name = "maxilife-nba";
27559 + client_name = "HP MaxiLife NBA";
27560 + printk("maxilife: HP KAYAK XU800/XM600\n");
27564 + ("maxilife: Warning: probed non-maxilife chip?!? (%x)\n",
27568 + ("maxilife: Error: specified wrong maxi_version (%d)\n",
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;
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;
27584 + new_client->id = maxi_id++;
27587 + init_MUTEX(&data->lock);
27588 + init_MUTEX(&data->update_lock);
27590 + /* Tell i2c-core that a new client has arrived */
27591 + if ((err = i2c_attach_client(new_client)))
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)
27598 + data->sysctl_id = err;
27600 + /* Initialize the MaxiLife chip */
27601 + maxi_init_client(new_client);
27604 + /* OK, this is not exactly good programming practice, usually.
27605 + But it is very code-efficient in this case. */
27607 + i2c_detach_client(new_client);
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)
27622 + i2c_deregister_entry(((struct maxi_data *) (client->data))->
27625 + if ((err = i2c_detach_client(client))) {
27627 + ("maxilife: Client deregistration failed, client not detached.\n");
27630 + kfree(client->data);
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)
27637 + return i2c_smbus_read_byte_data(client, reg);
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)
27643 + u8 lowToken, highToken;
27644 + int error, value;
27646 + lowToken = LOW(token);
27647 + highToken = HIGH(token);
27649 + /* Set mailbox status register to idle state. */
27651 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
27656 + /* Check for mailbox idle state. */
27657 + error = i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27658 + if (error != MAXI_STAT_IDLE)
27661 + /* Write the most significant byte of the token we want to read. */
27663 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_H,
27668 + /* Write the least significant byte of the token we want to read. */
27670 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_L,
27675 + /* Write the read token opcode to the mailbox. */
27677 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_CMD,
27682 + /* Check for transaction completion */
27685 + i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27686 + } while (error == MAXI_STAT_BUSY);
27687 + if (error != MAXI_STAT_OK)
27690 + /* Read the value of the token. */
27691 + value = i2c_smbus_read_byte_data(client, MAXI_REG_MBX_DATA);
27695 + /* set mailbox status to idle to complete transaction. */
27697 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
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)
27709 + return i2c_smbus_write_byte_data(client, reg, value);
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,
27717 + u8 lowToken, highToken, bCounter;
27720 + lowToken = LOW(token);
27721 + highToken = HIGH(token);
27723 + /* Set mailbox status register to idle state. */
27725 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
27730 + /* Check for mailbox idle state. */
27731 + error = i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27732 + if (error != MAXI_STAT_IDLE)
27735 + for (bCounter = 0; (bCounter < len && bCounter < 32); bCounter++) {
27737 + i2c_smbus_write_byte_data(client,
27738 + (u8) (MAXI_REG_MBX_DATA +
27740 + values[bCounter]);
27745 + /* Write the most significant byte of the token we want to read. */
27747 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_H,
27752 + /* Write the least significant byte of the token we want to read. */
27754 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_TOKEN_L,
27759 + /* Write the write token opcode to the mailbox. */
27761 + i2c_smbus_write_byte_data(client, MAXI_REG_MBX_CMD,
27766 + /* Check for transaction completion */
27769 + i2c_smbus_read_byte_data(client, MAXI_REG_MBX_STATUS);
27770 + } while (error == MAXI_STAT_BUSY);
27771 + if (error != MAXI_STAT_OK)
27774 + /* set mailbox status to idle to complete transaction. */
27775 + return i2c_smbus_write_byte_data(client, MAXI_REG_MBX_STATUS,
27779 +/* Called when we have found a new MaxiLife. It should set limits, etc. */
27780 +static void maxi_init_client(struct i2c_client *client)
27782 + struct maxi_data *data = client->data;
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,
27792 +static void maxi_update_client(struct i2c_client *client)
27794 + struct maxi_data *data = client->data;
27797 + if (data->type == nba) {
27799 + ("maxi_update_client should never be called by nba\n");
27803 + down(&data->update_lock);
27805 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
27806 + (jiffies < data->last_updated) || !data->valid) {
27809 + printk("maxilife: Starting MaxiLife update\n");
27811 + for (i = 0; i < 5; i++)
27813 + maxi_read_value(client, MAXI_REG_TEMP(i));
27814 + switch (data->type) {
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;
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;
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;
27858 + printk("maxilife: Unknown MaxiLife chip\n");
27860 + data->temp[5] = 0; /* only used by MaxiLife'99 */
27861 + data->temp_max[5] = 0;
27862 + data->temp_hyst[5] = 0;
27864 + for (i = 0; i < 3; 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));
27875 + data->fan_min[i] =
27876 + maxi_read_value(client,
27877 + MAXI_REG_FAN_MIN(i));
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;
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);
27888 + for (i = 0; i < 4; 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));
27896 + switch (data->type) {
27898 + data->vid[3] = 0; /* no voltage cache L2 */
27899 + data->vid_min[3] = 0;
27900 + data->vid_max[3] = 0;
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;
27916 + printk("maxilife: Unknown MaxiLife chip\n");
27918 + data->vid[4] = 0; /* only used by MaxliLife'99 */
27919 + data->vid_min[4] = 0;
27920 + data->vid_max[4] = 0;
27922 + data->alarms = maxi_read_value(client, MAXI_REG_DIAG_RT1) +
27923 + (maxi_read_value(client, MAXI_REG_DIAG_RT2) << 8);
27925 + data->last_updated = jiffies;
27929 + up(&data->update_lock);
27932 +void maxi99_update_client(struct i2c_client *client,
27933 + enum sensor_type sensor, int which)
27935 + static unsigned long last_updated[6][6]; /* sensor, which */
27936 + struct maxi_data *data = client->data;
27938 + down(&data->update_lock);
27940 + /*maxi_write_token_loop(client, MAXI_TOK_LCD_LINE3, 13, "Linux 2.2.13"); */
27942 + if ((jiffies - last_updated[sensor][which] > 2 * HZ) ||
27943 + (jiffies < last_updated[sensor][which]
27944 + || !last_updated[sensor][which])) {
27948 + switch (sensor) {
27950 + for (i = 0; i < 4; i++) {
27951 + if (i == which) {
27953 + maxi_read_token(client,
27957 + maxi_read_token(client,
27960 + data->fan_speed[i] =
27961 + maxi_read_token(client,
27965 + data->fan_div[i] = 1;
27966 + data->fan_min[i] = 0;
27972 + for (i = 0; i < 6; i++) {
27973 + if (i == which) {
27975 + maxi_read_token(client,
27978 + data->temp_max[i] =
27979 + maxi_read_token(client,
27983 + data->temp_hyst[i] =
27984 + data->temp_max[i] - 5;
27990 + for (i = 0; i < 5; i++) {
27991 + if (i == which) {
27993 + maxi_read_token(client,
27996 + data->vid_min[i] =
27997 + maxi_read_token(client,
28001 + data->vid_max[i] =
28002 + maxi_read_token(client,
28012 + data->pll_min = 0;
28013 + data->pll_max = 0;
28018 + (maxi_read_token(client, MAXI_TOK_ALARM_EVENT)
28020 + if (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)
28038 + printk("maxilife: Unknown sensor type\n");
28041 + last_updated[sensor][which] = jiffies;
28045 + up(&data->update_lock);
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)
28064 + struct maxi_data *data = client->data;
28067 + if (data->type == nba) {
28068 + maxi99_fan(client, operation, ctl_name, nrels_mag,
28073 + nr = ctl_name - MAXI_SYSCTL_FAN1 + 1;
28075 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
28083 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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]);
28094 +void maxi99_fan(struct i2c_client *client, int operation, int ctl_name,
28095 + int *nrels_mag, long *results)
28097 + struct maxi_data *data = client->data;
28100 + nr = ctl_name - MAXI_SYSCTL_FAN1 + 1;
28102 + if (operation == SENSORS_PROC_REAL_INFO)
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 */
28110 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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]);
28122 +void maxi_temp(struct i2c_client *client, int operation, int ctl_name,
28123 + int *nrels_mag, long *results)
28125 + struct maxi_data *data = client->data;
28128 + if (data->type == nba) {
28129 + maxi99_temp(client, operation, ctl_name, nrels_mag,
28134 + nr = ctl_name - MAXI_SYSCTL_TEMP1 + 1;
28136 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
28144 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
28145 + /* temperature range can not be changed */
28149 +void maxi99_temp(struct i2c_client *client, int operation, int ctl_name,
28150 + int *nrels_mag, long *results)
28152 + struct maxi_data *data = client->data;
28155 + nr = ctl_name - MAXI_SYSCTL_TEMP1 + 1;
28157 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
28165 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
28166 + /* temperature range can not be changed */
28170 +void maxi_pll(struct i2c_client *client, int operation, int ctl_name,
28171 + int *nrels_mag, long *results)
28173 + struct maxi_data *data = client->data;
28175 + if (operation == SENSORS_PROC_REAL_INFO)
28177 + else if (operation == SENSORS_PROC_REAL_READ) {
28178 + if (data->type == nba)
28179 + maxi99_update_client(client, pll, 0);
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);
28186 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
28188 + if (*nrels_mag >= 1) {
28189 + data->pll_min = PLL_TO_REG(results[0]);
28190 + maxi_write_value(client, MAXI_REG_PLL_MIN,
28193 + if (*nrels_mag >= 2) {
28194 + data->pll_max = PLL_TO_REG(results[1]);
28195 + maxi_write_value(client, MAXI_REG_PLL_MAX,
28202 +void maxi_vid(struct i2c_client *client, int operation, int ctl_name,
28203 + int *nrels_mag, long *results)
28205 + struct maxi_data *data = client->data;
28208 + if (data->type == nba) {
28209 + maxi99_vid(client, operation, ctl_name, nrels_mag,
28214 + nr = ctl_name - MAXI_SYSCTL_VID1 + 1;
28216 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
28224 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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]);
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]);
28240 +void maxi99_vid(struct i2c_client *client, int operation, int ctl_name,
28241 + int *nrels_mag, long *results)
28243 + struct maxi_data *data = client->data;
28244 + int nr = ctl_name - MAXI_SYSCTL_VID1 + 1;
28246 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
28254 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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]);
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]);
28271 +void maxi_lcd(struct i2c_client *client, int operation, int ctl_name,
28272 + int *nrels_mag, long *results)
28274 + /* Allows writing and reading from LCD display */
28276 + struct maxi_data *data = client->data;
28279 + if (data->type != nba)
28282 + nr = ctl_name - MAXI_SYSCTL_LCD1 + 1;
28284 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
28292 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
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
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]);
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]);
28327 +void maxi_alarms(struct i2c_client *client, int operation, int ctl_name,
28328 + int *nrels_mag, long *results)
28330 + struct maxi_data *data = client->data;
28332 + if (operation == SENSORS_PROC_REAL_INFO)
28334 + else if (operation == SENSORS_PROC_REAL_READ) {
28335 + if (data->type == nba)
28336 + maxi99_update_client(client, alarm, 0);
28338 + maxi_update_client(client);
28339 + results[0] = ALARMS_FROM_REG(data->alarms);
28344 +static int __init sm_maxilife_init(void)
28346 + printk("maxilife: Version %s (lm_sensors %s (%s))\n", version_str,
28347 + LM_VERSION, LM_DATE);
28348 + return i2c_add_driver(&maxi_driver);
28351 +static void __exit sm_maxilife_exit(void)
28353 + i2c_del_driver(&maxi_driver);
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");
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
28369 + mtp008.c - Part of lm_sensors, Linux kernel modules for hardware
28371 + Copyright (C) 2001, 2004 Kris Van Hees <aedil@alchar.org>
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.
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.
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.
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"
28396 +MODULE_LICENSE("GPL");
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};
28404 +/* Insmod parameters */
28405 +SENSORS_INSMOD_1(mtp008);
28407 +/* The MTP008 registers */
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)
28414 +#define MTP008_REG_TEMP 0x27
28415 +#define MTP008_REG_TEMP_MAX 0x39
28416 +#define MTP008_REG_TEMP_MIN 0x3a
28418 +/* fan1 .. fan3 */
28419 +#define MTP008_REG_FAN(nr) (0x27 + (nr))
28420 +#define MTP008_REG_FAN_MIN(nr) (0x3a + (nr))
28422 +#define MTP008_REG_CONFIG 0x40
28423 +#define MTP008_REG_INT_STAT1 0x41
28424 +#define MTP008_REG_INT_STAT2 0x42
28426 +#define MTP008_REG_SMI_MASK1 0x43
28427 +#define MTP008_REG_SMI_MASK2 0x44
28429 +#define MTP008_REG_NMI_MASK1 0x45
28430 +#define MTP008_REG_NMI_MASK2 0x46
28432 +#define MTP008_REG_VID_FANDIV 0x47
28434 +#define MTP008_REG_I2C_ADDR 0x48
28436 +#define MTP008_REG_RESET_VID4 0x49
28438 +#define MTP008_REG_OVT_PROP 0x50
28440 +#define MTP008_REG_BEEP_CTRL1 0x51
28441 +#define MTP008_REG_BEEP_CTRL2 0x52
28443 +/* pwm1 .. pwm3 nr range 1-3 */
28444 +#define MTP008_REG_PWM_CTRL(nr) (0x52 + (nr))
28446 +#define MTP008_REG_PIN_CTRL1 0x56
28447 +#define MTP008_REG_PIN_CTRL2 0x57
28449 +#define MTP008_REG_CHIPID 0x58
28452 + * Pin control register configuration constants.
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
28461 +/* sensor pin types */
28463 +#define THERMISTOR 2
28464 +#define PIIDIODE 3
28467 + * Conversion routines and macros. Limit checking is only done on
28468 + * the TO_REG variants.
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).
28474 +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8) / 16), 0, 255))
28475 +#define IN_FROM_REG(val) (((val) * 16 + 5) / 10)
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)
28484 +static inline u8 FAN_TO_REG(long rpm, int div)
28489 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
28491 + return SENSORS_LIMIT(
28492 + (1350000 + rpm * div / 2) / (rpm * div),
28497 +#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 \
28498 + : (val) == 255 ? 0 \
28500 + ((val) * (div)) \
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
28508 +#define TEMP_TO_REG(val) ( \
28510 + ? SENSORS_LIMIT(((val) - 5) / 10, 0, 255) \
28511 + : SENSORS_LIMIT(((val) + 5) / 10, 0, 255) \
28513 +#define TEMP_FROM_REG(val) ( \
28515 + (val) > 0x80 ? (val) - 0x100 \
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)
28526 +#define VID_FROM_REG(val) ((val) == 0x1f \
28528 + : (val) < 0x10 ? 205 - (val) * 5 \
28529 + : 510 - (val) * 10)
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 \
28541 + * Alarms (interrupt status).
28543 +#define ALARMS_FROM_REG(val) (val)
28548 +#define BEEPS_FROM_REG(val) (val)
28549 +#define BEEPS_TO_REG(val) (val)
28552 + * PWM control. nr range 1 to 3
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)
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.
28563 +struct mtp008_data {
28564 + struct i2c_client client;
28568 + struct semaphore update_lock;
28569 + char valid; /* !=0 if fields are valid */
28570 + unsigned long last_updated; /* In jiffies */
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,
28587 + 3 = PII/Celeron diode */
28588 + u8 pwmenable; /* Register 0x57 value */
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);
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);
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);
28623 +static int mtp008_id = 0;
28625 +static struct i2c_driver mtp008_driver =
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,
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 */
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
28674 +/* -- SENSORS SYSCTL END -- */
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. */
28683 +static ctl_table mtp008_dir_table_template[] =
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},
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)
28738 +static int mtp008_attach_adapter(struct i2c_adapter *adapter)
28740 + struct i2c_client_address_data mtp008_addr_data;
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;
28750 + return i2c_probe(adapter, &mtp008_addr_data, mtp008_detect);
28753 +int mtp008_detect(struct i2c_adapter *adapter, int address,
28754 + unsigned short flags, int kind)
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;
28764 + is_isa = i2c_is_isa_adapter(adapter);
28766 + !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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().
28774 + if (!(data = kmalloc(sizeof(struct mtp008_data), GFP_KERNEL))) {
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;
28787 + * Remaining detection.
28790 + if (mtp008_read_value(new_client, MTP008_REG_CHIPID) != 0xac)
28794 + * Fill in the remaining client fields and put it into the global list.
28796 + type_name = "mtp008";
28797 + client_name = "MTP008 chip";
28798 + strcpy(new_client->name, client_name);
28799 + data->type = kind;
28801 + new_client->id = mtp008_id++;
28803 + init_MUTEX(&data->update_lock);
28806 + * Tell the I2C layer that a new client has arrived.
28808 + if ((err = i2c_attach_client(new_client)))
28812 + * Register a new directory entry with the sensors module.
28814 + if ((sysid = i2c_register_entry(new_client, type_name,
28815 + mtp008_dir_table_template)) < 0) {
28819 + data->sysctl_id = sysid;
28822 + * Initialize the MTP008 chip.
28824 + mtp008_init_client(new_client);
28829 + * Error handling. Bad programming practise but very code efficient.
28832 + i2c_detach_client(new_client);
28840 +static int mtp008_detach_client(struct i2c_client *client)
28844 + i2c_deregister_entry(
28845 + ((struct mtp008_data *) (client->data))->sysctl_id);
28847 + if ((err = i2c_detach_client(client))) {
28848 + printk("mtp008.o: Deregistration failed, "
28849 + "client not detached.\n");
28852 + kfree(client->data);
28858 +static int mtp008_read_value(struct i2c_client *client, u8 reg)
28860 + return i2c_smbus_read_byte_data(client, reg) & 0xff;
28863 +static int mtp008_write_value(struct i2c_client *client, u8 reg, u8 value)
28865 + return i2c_smbus_write_byte_data(client, reg, value);
28868 +/* Called when we have found a new MTP008. It should set limits, etc. */
28869 +static void mtp008_init_client(struct i2c_client *client)
28872 + struct mtp008_data *data;
28874 + data = client->data;
28877 + * Initialize the Myson MTP008 hardware monitoring chip.
28878 + * Save the pin settings that the BIOS hopefully set.
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);
28887 + mtp008_getsensortype(data, save2);
28891 + * Start monitoring.
28893 + mtp008_write_value(
28894 + client, MTP008_REG_CONFIG,
28895 + (mtp008_read_value(client, MTP008_REG_CONFIG) & 0xf7) | 0x01
28899 +static void mtp008_update_client(struct i2c_client *client)
28903 + struct mtp008_data *data;
28905 + data = client->data;
28907 + down(&data->update_lock);
28909 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
28910 + (jiffies < data->last_updated) || !data->valid) {
28912 + printk("Starting MTP008 update\n");
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.
28921 + for (i = 0; i < 7; 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));
28931 + * Read the temperature sensor.
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);
28938 + * Read the first 2 fan dividers and the VID setting. Read the
28939 + * third fan divider from a different register.
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;
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;
28952 + * Read the interrupt status registers.
28955 + (mtp008_read_value(client,
28956 + MTP008_REG_INT_STAT1) & 0xdf) |
28957 + (mtp008_read_value(client,
28958 + MTP008_REG_INT_STAT2) & 0x0f) << 8;
28961 + * Read the beep control registers.
28964 + (mtp008_read_value(client,
28965 + MTP008_REG_BEEP_CTRL1) & 0xdf) |
28966 + (mtp008_read_value(client,
28967 + MTP008_REG_BEEP_CTRL2) & 0x8f) << 8;
28970 + * Read the sensor configuration.
28972 + inp = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
28973 + mtp008_getsensortype(data, inp);
28974 + data->pwmenable = inp;
28977 + * Read the PWM registers if enabled.
28979 + for (i = 1; i <= 3; i++)
28981 + if(PWMENABLE_FROM_REG(i, inp))
28982 + data->pwm[i-1] = mtp008_read_value(client,
28983 + MTP008_REG_PWM_CTRL(i));
28985 + data->pwm[i-1] = 255;
28989 + * Read the fan sensors. Skip 3 if PWM1 enabled.
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;
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));
29003 + data->last_updated = jiffies;
29006 + up(&data->update_lock);
29009 +static void mtp008_getsensortype(struct mtp008_data *data, u8 inp)
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 */
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)
29034 + struct mtp008_data *data;
29036 + nr = ctl_name - MTP008_SYSCTL_IN0;
29037 + data = client->data;
29039 + switch (operation) {
29040 + case SENSORS_PROC_REAL_INFO:
29044 + case SENSORS_PROC_REAL_READ:
29045 + mtp008_update_client(client);
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]);
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]);
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]);
29076 +void mtp008_fan(struct i2c_client *client, int operation, int ctl_name,
29077 + int *nrels_mag, long *results)
29080 + struct mtp008_data *data;
29082 + nr = ctl_name - MTP008_SYSCTL_FAN1;
29083 + data = client->data;
29085 + switch (operation) {
29086 + case SENSORS_PROC_REAL_INFO:
29090 + case SENSORS_PROC_REAL_READ:
29091 + mtp008_update_client(client);
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]));
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]);
29112 +void mtp008_temp(struct i2c_client *client, int operation, int ctl_name,
29113 + int *nrels_mag, long *results)
29115 + struct mtp008_data *data;
29117 + data = client->data;
29119 + switch (operation) {
29120 + case SENSORS_PROC_REAL_INFO:
29124 + case SENSORS_PROC_REAL_READ:
29125 + mtp008_update_client(client);
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);
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,
29139 + if (*nrels_mag >= 2) {
29140 + data->temp_min = TEMP_TO_REG(results[1]);
29141 + mtp008_write_value(client, MTP008_REG_TEMP_MIN,
29147 +void mtp008_temp_add(struct i2c_client *client, int operation, int ctl_name,
29148 + int *nrels_mag, long *results)
29151 + struct mtp008_data *data;
29153 + nr = 3 + ctl_name - MTP008_SYSCTL_TEMP1; /* AIN4 or AIN5 */
29154 + data = client->data;
29156 + switch (operation) {
29157 + case SENSORS_PROC_REAL_INFO:
29161 + case SENSORS_PROC_REAL_READ:
29162 + mtp008_update_client(client);
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]);
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]);
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]);
29194 +void mtp008_vid(struct i2c_client *client, int operation, int ctl_name,
29195 + int *nrels_mag, long *results)
29197 + struct mtp008_data *data;
29199 + data = client->data;
29201 + switch (operation) {
29202 + case SENSORS_PROC_REAL_INFO:
29206 + case SENSORS_PROC_REAL_READ:
29207 + mtp008_update_client(client);
29209 + results[0] = VID_FROM_REG(data->vid);
29215 +void mtp008_fan_div(struct i2c_client *client, int operation,
29216 + int ctl_name, int *nrels_mag, long *results)
29218 + struct mtp008_data *data;
29221 + data = client->data;
29223 + switch (operation) {
29224 + case SENSORS_PROC_REAL_INFO:
29228 + case SENSORS_PROC_REAL_READ:
29229 + mtp008_update_client(client);
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]);
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);
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;
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);
29259 +void mtp008_alarms(struct i2c_client *client, int operation, int ctl_name,
29260 + int *nrels_mag, long *results)
29262 + struct mtp008_data *data;
29264 + data = client->data;
29266 + switch (operation) {
29267 + case SENSORS_PROC_REAL_INFO:
29271 + case SENSORS_PROC_REAL_READ:
29272 + mtp008_update_client(client);
29274 + results[0] = ALARMS_FROM_REG(data->alarms);
29280 +void mtp008_beep(struct i2c_client *client, int operation, int ctl_name,
29281 + int *nrels_mag, long *results)
29283 + struct mtp008_data *data;
29285 + data = client->data;
29287 + switch (operation) {
29288 + case SENSORS_PROC_REAL_INFO:
29292 + case SENSORS_PROC_REAL_READ:
29293 + mtp008_update_client(client);
29295 + results[0] = BEEPS_FROM_REG(data->beeps);
29300 + case SENSORS_PROC_REAL_WRITE:
29301 + if (*nrels_mag >= 1) {
29302 + data->beeps = BEEPS_TO_REG(results[0]) & 0xdf8f;
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);
29312 +void mtp008_pwm(struct i2c_client *client, int operation, int ctl_name,
29313 + int *nrels_mag, long *results)
29316 + struct mtp008_data *data;
29318 + nr = ctl_name - MTP008_SYSCTL_PWM1;
29319 + data = client->data;
29321 + switch (operation) {
29322 + case SENSORS_PROC_REAL_INFO:
29326 + case SENSORS_PROC_REAL_READ:
29327 + mtp008_update_client(client);
29329 + results[0] = PWM_FROM_REG(data->pwm[nr]);
29330 + results[1] = PWMENABLE_FROM_REG(nr + 1, data->pwmenable);
29334 + case SENSORS_PROC_REAL_WRITE:
29335 + if (*nrels_mag >= 1) {
29336 + if (*nrels_mag >= 2) {
29338 + data->pwmenable |= 0x10 << nr;
29340 + data->pwmenable &= ~(0x10 << nr);
29341 + mtp008_write_value(client, MTP008_REG_PIN_CTRL2,
29342 + data->pwmenable);
29344 + data->pwm[nr] = PWM_TO_REG(results[0]);
29345 + mtp008_write_value(client, MTP008_REG_PWM_CTRL(nr),
29351 +void mtp008_sens(struct i2c_client *client, int operation, int ctl_name,
29352 + int *nrels_mag, long *results)
29354 + const char *opts = "";
29357 + struct mtp008_data *data;
29359 + nr = 1 + ctl_name - MTP008_SYSCTL_SENS1;
29360 + data = client->data;
29362 + switch (operation) {
29363 + case SENSORS_PROC_REAL_INFO:
29367 + case SENSORS_PROC_REAL_READ:
29368 + results[0] = data->sens[nr - 1];
29373 + case SENSORS_PROC_REAL_WRITE:
29374 + if (*nrels_mag >= 1) {
29375 + tmp = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
29378 + case 1: /* VT or PII */
29381 + switch (results[0]) {
29383 + mtp008_write_value(
29384 + client, MTP008_REG_PIN_CTRL2,
29385 + tmp & ~MTP008_CFG_VT1_PII);
29386 + data->sens[0] = 2;
29389 + mtp008_write_value(
29390 + client, MTP008_REG_PIN_CTRL2,
29391 + tmp | MTP008_CFG_VT1_PII);
29392 + data->sens[0] = 3;
29397 + case 2: /* AIN, VT or PII */
29398 + tmp &= ~MTP008_CFG_VT2_MASK;
29399 + opts = "1, 2 or 3";
29401 + switch (results[0]) {
29403 + mtp008_write_value(
29404 + client, MTP008_REG_PIN_CTRL2,
29405 + tmp | MTP008_CFG_VT2_AIN);
29406 + data->sens[1] = 1;
29409 + mtp008_write_value(
29410 + client, MTP008_REG_PIN_CTRL2,
29411 + tmp | MTP008_CFG_VT2_VT);
29412 + data->sens[1] = 2;
29415 + mtp008_write_value(
29416 + client, MTP008_REG_PIN_CTRL2,
29417 + tmp | MTP008_CFG_VT2_PII);
29418 + data->sens[1] = 3;
29423 + case 3: /* AIN or VT */
29426 + switch (results[0]) {
29428 + mtp008_write_value(
29429 + client, MTP008_REG_PIN_CTRL2,
29430 + tmp & ~MTP008_CFG_VT3_VT);
29431 + data->sens[2] = 1;
29434 + mtp008_write_value(
29435 + client, MTP008_REG_PIN_CTRL2,
29436 + tmp | MTP008_CFG_VT3_VT);
29437 + data->sens[2] = 2;
29444 + printk("mtp008.o: Invalid sensor type %ld "
29445 + "for sensor %d; must be %s.\n",
29446 + results[0], nr, opts);
29451 +static int __init sm_mtp008_init(void)
29453 + printk("mtp008.o version %s (%s)\n", LM_VERSION, LM_DATE);
29454 + return i2c_add_driver(&mtp008_driver);
29457 +static void __exit sm_mtp008_exit(void)
29459 + i2c_del_driver(&mtp008_driver);
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");
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
29475 + * pc87360.c - Part of lm_sensors, Linux kernel modules
29476 + * for hardware monitoring
29477 + * Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
29479 + * Copied from smsc47m1.c:
29480 + * Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
29496 + * Supports the following chips:
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
29505 + * This driver assumes that no more than one chip is present, and the
29506 + * standard Super-I/O address is used (0x2E/0x2F).
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>
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}};
29526 +static unsigned int extra_isa[] = { 0x0000, 0x0000, 0x0000 };
29527 +static u8 confreg[4];
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,
29542 +static int init = 1;
29543 +MODULE_PARM(init, "i");
29544 +MODULE_PARM_DESC(init,
29545 + "Chip initialization level:\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");
29552 + * Super-I/O registers and operations
29555 +#define REG 0x2e /* The register to read/write */
29556 +#define VAL 0x2f /* The value to read/write */
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 */
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 };
29572 +static inline void superio_outb(int reg, int val)
29578 +static inline int superio_inb(int reg)
29584 +static inline void superio_exit(void)
29591 + * Logical devices
29594 +#define PC87360_EXTENT 0x10
29595 +#define PC87365_REG_BANK 0x09
29596 +#define NO_BANK 0xff
29599 + * Fan registers and conversions
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))
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)
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)
29622 +#define PWM_FROM_REG(val,inv) ((inv) ? 255 - (val) : (val))
29623 +static inline u8 PWM_TO_REG(int val, int inv)
29635 + * Voltage registers and conversions
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
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))
29654 + * Temperature registers and conversions
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
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))
29669 +struct pc87360_data {
29670 + struct i2c_client client;
29671 + struct semaphore lock;
29675 + struct semaphore update_lock;
29676 + char valid; /* !=0 if following fields are valid */
29677 + unsigned long last_updated; /* In jiffies */
29679 + u8 fannr, innr, tempnr;
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 */
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 */
29696 + u8 vid; /* Register value */
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 */
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);
29712 +static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
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);
29721 +void pc87365_alarms(struct i2c_client *client, int operation, int ctl_name,
29722 + int *nrels_mag, long *results);
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);
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);
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);
29747 +static int pc87360_id = 0;
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,
29757 +/* -- SENSORS SYSCTL START -- */
29759 +#define PC87365_SYSCTL_ALARMS 100 /* bit field */
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 */
29772 +#define PC87360_STATUS_FAN_READY 0x01
29773 +#define PC87360_STATUS_FAN_LOW 0x02
29774 +#define PC87360_STATUS_FAN_OVERFLOW 0x04
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 */
29805 +#define PC87365_SYSCTL_VID 2400
29806 +#define PC87365_SYSCTL_VRM 2401
29808 +#define PC87365_STATUS_IN_MIN 0x02
29809 +#define PC87365_STATUS_IN_MAX 0x04
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 */
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
29823 +/* -- SENSORS SYSCTL END -- */
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},
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},
29947 +static int pc87360_attach_adapter(struct i2c_adapter *adapter)
29949 + return i2c_detect(adapter, &addr_data, pc87360_detect);
29952 +static int pc87360_find(u8 *devid, int *address)
29956 + int nrdev; /* logical device count */
29958 + /* No superio_enter */
29960 + /* Identify device */
29961 + val = superio_inb(DEVID);
29963 + case 0xE1: /* PC87360 */
29964 + case 0xE8: /* PC87363 */
29965 + case 0xE4: /* PC87364 */
29968 + case 0xE5: /* PC87365 */
29969 + case 0xE9: /* PC87366 */
29976 + /* Remember the device id */
29979 + for (i = 0; i < nrdev; i++) {
29980 + /* select logical device */
29981 + superio_outb(DEV, logdev[i]);
29983 + val = superio_inb(ACT);
29984 + if (!(val & 0x01)) {
29985 + printk(KERN_INFO "pc87360.o: Device 0x%02x not "
29986 + "activated\n", logdev[i]);
29990 + val = (superio_inb(BASE) << 8)
29991 + | superio_inb(BASE + 1);
29993 + printk(KERN_INFO "pc87360.o: Base address not set for "
29994 + "device 0x%02x\n", logdev[i]);
29998 + address[i] = val;
30000 + if (i==0) { /* Fans */
30001 + confreg[0] = superio_inb(0xF0);
30002 + confreg[1] = superio_inb(0xF1);
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);
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);
30024 + if (confreg[2] & 0x40) {
30025 + printk(KERN_INFO "pc87360.o: Using "
30026 + "thermistors for temperature "
30029 + if (confreg[3] & 0xE0) {
30030 + printk(KERN_INFO "pc87360.o: VID "
30031 + "inputs routed (mode %u)\n",
30032 + confreg[3] >> 5);
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)
30048 + struct i2c_client *new_client;
30049 + struct pc87360_data *data;
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;
30056 + if (!i2c_is_isa_adapter(adapter)) {
30060 + for (i = 0; i < 3; 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);
30070 + if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL))) {
30073 + memset(data, 0x00, sizeof(struct pc87360_data));
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;
30085 + data->tempnr = 0;
30089 + type_name = "pc87363";
30092 + type_name = "pc87364";
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;
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;
30111 + /* Retrieve the fans configuration from Super-I/O space */
30113 + data->fan_conf = confreg[0] | (confreg[1] << 8);
30115 + for (i = 0; i < 3; i++) {
30116 + if ((data->address[i] = extra_isa[i])) {
30117 + request_region(extra_isa[i], PC87360_EXTENT, "pc87360");
30120 + strcpy(new_client->name, client_name);
30122 + new_client->id = pc87360_id++;
30124 + init_MUTEX(&data->update_lock);
30126 + if ((err = i2c_attach_client(new_client)))
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);
30139 + data->in_vref = (i&0x02) ? 3025 : 2966;
30141 + printk(KERN_DEBUG "pc87360.o: Using %s reference voltage\n",
30142 + (i&0x02) ? "external" : "internal");
30145 + data->vid_conf = confreg[3];
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));
30156 + if (devid == 0xe9 && data->address[1]) /* PC87366 */
30157 + use_thermistors = confreg[2] & 0x40;
30159 + pc87360_init_client(new_client, use_thermistors);
30162 + if ((i = i2c_register_entry((struct i2c_client *) new_client,
30163 + type_name, template)) < 0) {
30167 + data->sysctl_id = i;
30172 + i2c_detach_client(new_client);
30174 + for (i = 0; i < 3; i++) {
30175 + if (data->address[i]) {
30176 + release_region(data->address[i], PC87360_EXTENT);
30183 +static int pc87360_detach_client(struct i2c_client *client)
30185 + struct pc87360_data *data = client->data;
30188 + i2c_deregister_entry(data->sysctl_id);
30190 + if ((err = i2c_detach_client(client))) {
30191 + printk(KERN_ERR "pc87360.o: Client deregistration failed, "
30192 + "client not detached.\n");
30196 + for (i = 0; i < 3; i++) {
30197 + if (data->address[i]) {
30198 + release_region(data->address[i], PC87360_EXTENT);
30201 + kfree(client->data);
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,
30213 + down(&(data->lock));
30214 + if (bank != NO_BANK) {
30215 + outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
30217 + res = inb_p(data->address[ldi] + reg);
30218 + up(&(data->lock));
30222 +static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
30223 + u8 reg, u8 value)
30225 + down(&(data->lock));
30226 + if (bank != NO_BANK) {
30227 + outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
30229 + outb_p(value, data->address[ldi] + reg);
30230 + up(&(data->lock));
30233 +static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
30235 + struct pc87360_data *data = client->data;
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 };
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);
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)) {
30259 + printk(KERN_DEBUG "pc87360.o: Forcibly "
30260 + "enabling in%d\n", i);
30262 + pc87360_write_value(data, LD_IN, i,
30263 + PC87365_REG_IN_STATUS,
30264 + (reg & 0x68) | 0x87);
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);
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)) {
30285 + printk(KERN_DEBUG "pc87360.o: Forcibly "
30286 + "enabling temp%d\n", i+1);
30288 + pc87360_write_value(data, LD_TEMP, i,
30289 + PC87365_REG_TEMP_STATUS,
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
30300 + reg = pc87360_read_value(data, LD_TEMP, (i-11)/2,
30301 + PC87365_REG_TEMP_STATUS);
30302 + if (reg & 0x01) {
30304 + printk(KERN_DEBUG "pc87360.o: Skipping "
30305 + "temp%d, pin already in use by ",
30306 + "temp%d\n", i-7, (i-11)/2);
30311 + /* Forcibly enable thermistor channel */
30312 + reg = pc87360_read_value(data, LD_IN, i,
30313 + PC87365_REG_IN_STATUS);
30314 + if (!(reg & 0x01)) {
30316 + printk(KERN_DEBUG "pc87360.o: Forcibly "
30317 + "enabling temp%d\n", i-7);
30319 + pc87360_write_value(data, LD_IN, i,
30320 + PC87365_REG_TEMP_STATUS,
30321 + (reg & 0x60) | 0x8F);
30327 + if (data->innr) {
30328 + reg = pc87360_read_value(data, LD_IN, NO_BANK,
30329 + PC87365_REG_IN_CONFIG);
30330 + if (reg & 0x01) {
30332 + printk(KERN_DEBUG "pc87360.o: Forcibly "
30333 + "enabling monitoring (VLM)\n");
30335 + pc87360_write_value(data, LD_IN, NO_BANK,
30336 + PC87365_REG_IN_CONFIG,
30341 + if (data->tempnr) {
30342 + reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
30343 + PC87365_REG_TEMP_CONFIG);
30344 + if (reg & 0x01) {
30346 + printk(KERN_DEBUG "pc87360.o: Forcibly "
30347 + "enabling monitoring (TMS)\n");
30349 + pc87360_write_value(data, LD_TEMP, NO_BANK,
30350 + PC87365_REG_TEMP_CONFIG,
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);
30369 +static void pc87360_autodiv(struct pc87360_data *data, int nr)
30371 + u8 old_min = data->fan_min[nr];
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;
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]),
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;
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]),
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]);
30412 +static void pc87360_update_client(struct i2c_client *client)
30414 + struct pc87360_data *data = client->data;
30417 + down(&data->update_lock);
30419 + if ((jiffies - data->last_updated > HZ * 2) ||
30420 + (jiffies < data->last_updated) || !data->valid) {
30422 + printk(KERN_DEBUG "pc87360.o: Data update\n");
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,
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,
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]);
30443 + data->pwm[i] = pc87360_read_value(data, LD_FAN,
30444 + NO_BANK, PC87360_REG_PWM(i));
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);
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);
30459 + if (data->in_status[i] & 0x01) {
30460 + data->in_min[i] = pc87360_read_value(data,
30462 + PC87365_REG_IN_MIN);
30463 + data->in_max[i] = pc87360_read_value(data,
30465 + PC87365_REG_IN_MAX);
30467 + data->in_crit[i-11] =
30468 + pc87360_read_value(data, LD_IN,
30469 + i, PC87365_REG_TEMP_CRIT);
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)
30478 + data->vid = (data->vid_conf & 0xE0) ?
30479 + pc87360_read_value(data, LD_IN,
30480 + NO_BANK, PC87365_REG_VID) : 0x1F;
30483 + /* Temperatures */
30484 + for (i = 0; i < data->tempnr; i++) {
30485 + data->temp_status[i] = pc87360_read_value(data,
30487 + PC87365_REG_TEMP_STATUS);
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,
30495 + PC87365_REG_TEMP);
30497 + if (data->temp_status[i] & 0x01) {
30498 + data->temp_min[i] = pc87360_read_value(data,
30500 + PC87365_REG_TEMP_MIN);
30501 + data->temp_max[i] = pc87360_read_value(data,
30503 + PC87365_REG_TEMP_MAX);
30504 + data->temp_crit[i] = pc87360_read_value(data,
30506 + PC87365_REG_TEMP_CRIT);
30509 + if (data->tempnr) {
30510 + data->temp_alarms = pc87360_read_value(data, LD_TEMP,
30511 + NO_BANK, PC87365_REG_TEMP_ALARMS)
30515 + data->last_updated = jiffies;
30519 + up(&data->update_lock);
30523 +void pc87365_alarms(struct i2c_client *client, int operation, int ctl_name,
30524 + int *nrels_mag, long *results)
30526 + struct pc87360_data *data = client->data;
30528 + if (operation == SENSORS_PROC_REAL_INFO)
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;
30538 +void pc87360_fan(struct i2c_client *client, int operation, int ctl_name,
30539 + int *nrels_mag, long *results)
30541 + struct pc87360_data *data = client->data;
30542 + int nr = ctl_name - PC87360_SYSCTL_FAN1;
30544 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
30554 + /* We ignore National's recommendation */
30555 + else if (operation == SENSORS_PROC_REAL_WRITE) {
30556 + if (nr >= data->fannr)
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) {
30565 + data->fan[nr] >>= 1;
30566 + data->fan_status[nr] += 0x20;
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);
30580 +void pc87360_fan_div(struct i2c_client *client, int operation,
30581 + int ctl_name, int *nrels_mag, long *results)
30583 + struct pc87360_data *data = client->data;
30586 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
30593 + for (; i < 3; i++) {
30600 +void pc87360_pwm(struct i2c_client *client, int operation, int ctl_name,
30601 + int *nrels_mag, long *results)
30603 + struct pc87360_data *data = client->data;
30604 + int nr = ctl_name - PC87360_SYSCTL_PWM1;
30606 + if (operation == SENSORS_PROC_REAL_INFO)
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);
30615 + else if (operation == SENSORS_PROC_REAL_WRITE) {
30616 + if (nr >= data->fannr)
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),
30628 +void pc87360_fan_status(struct i2c_client *client, int operation, int ctl_name,
30629 + int *nrels_mag, long *results)
30631 + struct pc87360_data *data = client->data;
30632 + int nr = ctl_name - PC87360_SYSCTL_FAN1_STATUS;
30634 + if (operation == SENSORS_PROC_REAL_INFO)
30636 + else if (operation == SENSORS_PROC_REAL_READ) {
30637 + pc87360_update_client(client);
30638 + results[0] = FAN_STATUS_FROM_REG(data->fan_status[nr]);
30643 +void pc87365_in(struct i2c_client *client, int operation, int ctl_name,
30644 + int *nrels_mag, long *results)
30646 + struct pc87360_data *data = client->data;
30647 + int nr = ctl_name - PC87365_SYSCTL_IN0;
30649 + if (operation == SENSORS_PROC_REAL_INFO)
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);
30658 + results[2] = IN_FROM_REG(data->in_crit[nr-11],
30662 + results[(*nrels_mag)-1] = IN_FROM_REG(data->in[nr],
30665 + else if (operation == SENSORS_PROC_REAL_WRITE) {
30666 + if (*nrels_mag >= 1) {
30667 + data->in_min[nr] = IN_TO_REG(results[0],
30669 + pc87360_write_value(data, LD_IN, nr,
30670 + PC87365_REG_IN_MIN,
30671 + data->in_min[nr]);
30673 + if (*nrels_mag >= 2) {
30674 + data->in_max[nr] = IN_TO_REG(results[1],
30676 + pc87360_write_value(data, LD_IN, nr,
30677 + PC87365_REG_IN_MAX,
30678 + data->in_max[nr]);
30680 + if (*nrels_mag >= 3 && nr >= 11) {
30681 + data->in_crit[nr-11] = IN_TO_REG(results[2],
30683 + pc87360_write_value(data, LD_IN, nr,
30684 + PC87365_REG_TEMP_CRIT,
30685 + data->in_crit[nr-11]);
30690 +void pc87365_in_status(struct i2c_client *client, int operation, int ctl_name,
30691 + int *nrels_mag, long *results)
30693 + struct pc87360_data *data = client->data;
30694 + int nr = ctl_name - PC87365_SYSCTL_IN0_STATUS;
30696 + if (operation == SENSORS_PROC_REAL_INFO)
30698 + else if (operation == SENSORS_PROC_REAL_READ) {
30699 + pc87360_update_client(client);
30700 + results[0] = data->in_status[nr];
30705 +void pc87365_vid(struct i2c_client *client, int operation, int ctl_name,
30706 + int *nrels_mag, long *results)
30708 + struct pc87360_data *data = client->data;
30709 + if (operation == SENSORS_PROC_REAL_INFO)
30711 + else if (operation == SENSORS_PROC_REAL_READ) {
30712 + pc87360_update_client(client);
30713 + results[0] = vid_from_reg(data->vid & 0x1f, data->vrm);
30718 +void pc87365_vrm(struct i2c_client *client, int operation, int ctl_name,
30719 + int *nrels_mag, long *results)
30721 + struct pc87360_data *data = client->data;
30722 + if (operation == SENSORS_PROC_REAL_INFO)
30724 + else if (operation == SENSORS_PROC_REAL_READ) {
30725 + results[0] = data->vrm;
30727 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
30728 + if (*nrels_mag >= 1)
30729 + data->vrm = results[0];
30733 +void pc87365_temp(struct i2c_client *client, int operation, int ctl_name,
30734 + int *nrels_mag, long *results)
30736 + struct pc87360_data *data = client->data;
30737 + int nr = ctl_name - PC87365_SYSCTL_TEMP1;
30739 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
30749 + else if (operation == SENSORS_PROC_REAL_WRITE) {
30750 + if (nr >= data->tempnr)
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]);
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]);
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]);
30773 +void pc87365_temp_status(struct i2c_client *client, int operation, int ctl_name,
30774 + int *nrels_mag, long *results)
30776 + struct pc87360_data *data = client->data;
30777 + int nr = ctl_name - PC87365_SYSCTL_TEMP1_STATUS;
30779 + if (operation == SENSORS_PROC_REAL_INFO)
30781 + else if (operation == SENSORS_PROC_REAL_READ) {
30782 + pc87360_update_client(client);
30783 + results[0] = data->temp_status[nr];
30789 +static int __init pc87360_init(void)
30793 + printk(KERN_INFO "pc87360.o version %s (%s)\n", LM_VERSION, LM_DATE);
30795 + if (pc87360_find(&devid, extra_isa)) {
30796 + printk(KERN_WARNING "pc87360.o: PC8736x not detected, "
30797 + "module not inserted.\n");
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];
30809 + if (normal_isa[0] == 0x0000) {
30810 + printk(KERN_WARNING "pc87360.o: No active logical device, "
30811 + "module not inserted.\n");
30816 + return i2c_add_driver(&pc87360_driver);
30819 +static void __exit pc87360_exit(void)
30821 + i2c_del_driver(&pc87360_driver);
30825 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
30826 +MODULE_DESCRIPTION("PC8736x hardware monitor");
30827 +MODULE_LICENSE("GPL");
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
30835 + pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware
30837 + Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>,
30838 + Philip Edelbrock <phil@netroedge.com>,
30839 + Dan Eaton <dan.eaton@rocketlogix.com>
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.
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.
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.
30856 +/* A few notes about the PCF8574:
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.
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.
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.
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"
30882 +MODULE_LICENSE("GPL");
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 };
30890 +/* Insmod parameters */
30891 +SENSORS_INSMOD_2(pcf8574, pcf8574a);
30893 +/* The PCF8574 registers */
30895 +/* (No registers. [Wow! This thing is SIMPLE!] ) */
30897 +/* Initial values */
30898 +#define PCF8574_INIT 255 /* All outputs on (input mode) */
30900 +/* Each client has this additional data */
30901 +struct pcf8574_data {
30902 + struct i2c_client client;
30905 + struct semaphore update_lock;
30907 + u8 read, write; /* Register values */
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);
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);
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,
30933 +/* -- SENSORS SYSCTL START -- */
30934 +#define PCF8574_SYSCTL_READ 1000
30935 +#define PCF8574_SYSCTL_WRITE 1001
30937 +/* -- SENSORS SYSCTL END -- */
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},
30952 +static int pcf8574_id = 0;
30954 +static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
30956 + return i2c_detect(adapter, &addr_data, pcf8574_detect);
30959 +/* This function is called by i2c_detect */
30960 +int pcf8574_detect(struct i2c_adapter *adapter, int address,
30961 + unsigned short flags, int kind)
30964 + struct i2c_client *new_client;
30965 + struct pcf8574_data *data;
30967 + const char *type_name, *client_name;
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. */
30972 + if (i2c_is_isa_adapter(adapter)) {
30974 + ("pcf8574.o: pcf8574_detect called for an ISA bus adapter?!?\n");
30979 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
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))) {
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;
30996 + /* Now, we would do the remaining detection. But the PCF8574 is plainly
30997 + impossible to detect! Stupid chip. */
30999 + /* Determine the chip type */
31001 + if (address >= 0x38 && address <= 0x3f)
31007 + if (kind == pcf8574a) {
31008 + type_name = "pcf8574a";
31009 + client_name = "PCF8574A chip";
31011 + type_name = "pcf8574a";
31012 + client_name = "PCF8574A chip";
31015 + /* Fill in the remaining client fields and put it into the global list */
31016 + strcpy(new_client->name, client_name);
31018 + new_client->id = pcf8574_id++;
31019 + init_MUTEX(&data->update_lock);
31021 + /* Tell the I2C layer a new client has arrived */
31022 + if ((err = i2c_attach_client(new_client)))
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) {
31031 + data->sysctl_id = i;
31033 + /* Initialize the PCF8574 chip */
31034 + pcf8574_init_client(new_client);
31037 +/* OK, this is not exactly good programming practice, usually. But it is
31038 + very code-efficient in this case. */
31041 + i2c_detach_client(new_client);
31048 +static int pcf8574_detach_client(struct i2c_client *client)
31052 + i2c_deregister_entry(((struct pcf8574_data *) (client->data))->
31055 + if ((err = i2c_detach_client(client))) {
31056 + printk("pcf8574.o: Client deregistration failed, "
31057 + "client not detached.\n");
31061 + kfree(client->data);
31066 +/* Called when we have found a new PCF8574. */
31067 +static void pcf8574_init_client(struct i2c_client *client)
31069 + struct pcf8574_data *data = client->data;
31070 + data->write = PCF8574_INIT;
31071 + i2c_smbus_write_byte(client, data->write);
31075 +static void pcf8574_update_client(struct i2c_client *client)
31077 + struct pcf8574_data *data = client->data;
31079 + down(&data->update_lock);
31082 + printk("Starting pcf8574 update\n");
31085 + data->read = i2c_smbus_read_byte(client);
31087 + up(&data->update_lock);
31091 +void pcf8574_read(struct i2c_client *client, int operation,
31092 + int ctl_name, int *nrels_mag, long *results)
31094 + struct pcf8574_data *data = client->data;
31096 + if (operation == SENSORS_PROC_REAL_INFO)
31098 + else if (operation == SENSORS_PROC_REAL_READ) {
31099 + pcf8574_update_client(client);
31100 + results[0] = data->read;
31104 +void pcf8574_write(struct i2c_client *client, int operation,
31105 + int ctl_name, int *nrels_mag, long *results)
31107 + struct pcf8574_data *data = client->data;
31109 + if (operation == SENSORS_PROC_REAL_INFO)
31111 + else if (operation == SENSORS_PROC_REAL_READ) {
31112 + results[0] = data->write;
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);
31123 +static int __init sm_pcf8574_init(void)
31125 + printk("pcf8574.o version %s (%s)\n", LM_VERSION, LM_DATE);
31126 + return i2c_add_driver(&pcf8574_driver);
31129 +static void __exit sm_pcf8574_exit(void)
31131 + i2c_del_driver(&pcf8574_driver);
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");
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
31147 + pcf8591.c - Part of lm_sensors, Linux kernel modules for hardware
31149 + Copyright (c) 2001 Aurelien Jarno <aurelien@aurel32.net>
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.
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.
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.
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"
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 };
31180 +/* Insmod parameters */
31181 +SENSORS_INSMOD_1(pcf8591);
31183 +/* The PCF8591 control byte */
31184 +/* 7 6 5 4 3 2 1 0 */
31185 +/* | 0 |AOEF| AIP | 0 |AINC| AICH | */
31187 +#define PCF8591_CONTROL_BYTE_AOEF 0x40 /* Analog Output Enable Flag */
31188 + /* (analog output active if 1) */
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 */
31196 +#define PCF8591_CONTROL_BYTE_AINC 0x04 /* Autoincrement Flag */
31197 + /* (switch on if 1) */
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 */
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 */
31210 +#define PCF8591_INIT_AOUT 0 /* DAC out = 0 */
31213 +/* Conversions. */
31214 +#define REG_TO_SIGNED(reg) (reg & 0x80)?(reg - 256):(reg)
31215 + /* Convert signed 8 bit value to signed value */
31218 +struct pcf8591_data {
31219 + struct i2c_client client;
31222 + struct semaphore update_lock;
31223 + char valid; /* !=0 if following fields are valid */
31224 + unsigned long last_updated; /* In jiffies */
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);
31236 +static void pcf8591_update_client(struct i2c_client *client);
31237 +static void pcf8591_init_client(struct i2c_client *client);
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);
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,
31259 +static int pcf8591_id = 0;
31261 +/* The /proc/sys entries */
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 -- */
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},
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)
31303 + return i2c_detect(adapter, &addr_data, pcf8591_detect);
31306 +/* This function is called by i2c_detect */
31307 +int pcf8591_detect(struct i2c_adapter *adapter, int address,
31308 + unsigned short flags, int kind)
31311 + struct i2c_client *new_client;
31312 + struct pcf8591_data *data;
31315 + const char *type_name = "";
31316 + const char *client_name = "";
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. */
31320 + if (i2c_is_isa_adapter(adapter)) {
31322 + (KERN_ERR "pcf8591.o: pcf8591_detect called for an ISA bus adapter?!?\n");
31327 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE
31328 + | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
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))) {
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;
31345 + /* Now, we would do the remaining detection. But the PCF8591 is plainly
31346 + impossible to detect! Stupid chip. */
31348 + /* Determine the chip type - only one kind supported! */
31352 + type_name = "pcf8591";
31353 + client_name = "PCF8591 chip";
31355 + /* Fill in the remaining client fields and put it into the global list */
31356 + strcpy(new_client->name, client_name);
31358 + new_client->id = pcf8591_id++;
31360 + init_MUTEX(&data->update_lock);
31362 + /* Tell the I2C layer a new client has arrived */
31363 + if ((err = i2c_attach_client(new_client)))
31366 + /* Register a new directory entry with module sensors */
31367 + if ((i = i2c_register_entry(new_client,
31369 + pcf8591_dir_table_template)) < 0) {
31373 + data->sysctl_id = i;
31375 + /* Initialize the PCF8591 chip */
31376 + pcf8591_init_client(new_client);
31379 +/* OK, this is not exactly good programming practice, usually. But it is
31380 + very code-efficient in this case. */
31383 + i2c_detach_client(new_client);
31390 +static int pcf8591_detach_client(struct i2c_client *client)
31394 + i2c_deregister_entry(((struct pcf8591_data *) (client->data))->
31397 + if ((err = i2c_detach_client(client))) {
31399 + (KERN_ERR "pcf8591.o: Client deregistration failed, client not detached.\n");
31403 + kfree(client->data);
31408 +/* Called when we have found a new PCF8591. */
31409 +static void pcf8591_init_client(struct i2c_client *client)
31411 + struct pcf8591_data *data = client->data;
31412 + data->control_byte = PCF8591_INIT_CONTROL_BYTE;
31413 + data->aout = PCF8591_INIT_AOUT;
31415 + i2c_smbus_write_byte_data(client, data->control_byte, data->aout);
31418 +static void pcf8591_update_client(struct i2c_client *client)
31420 + struct pcf8591_data *data = client->data;
31422 + down(&data->update_lock);
31424 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
31425 + (jiffies < data->last_updated) || !data->valid) {
31428 + printk(KERN_DEBUG "Starting pcf8591 update\n");
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 */
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 */
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 */
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 */
31450 + data->last_updated = jiffies;
31454 + up(&data->update_lock);
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)
31463 + struct pcf8591_data *data = client->data;
31465 + if (operation == SENSORS_PROC_REAL_INFO)
31467 + else if (operation == SENSORS_PROC_REAL_READ) {
31468 + results[0] = (data->control_byte & PCF8591_CONTROL_BYTE_AIP) >> 4;
31470 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
31471 + if (*nrels_mag >= 1) {
31472 + if (results[0] >= 0 && results[0] <= 3)
31474 + data->control_byte &= ~PCF8591_CONTROL_BYTE_AIP;
31475 + data->control_byte |= (results[0] << 4);
31476 + i2c_smbus_write_byte(client, data->control_byte);
31483 +void pcf8591_ain(struct i2c_client *client, int operation, int ctl_name,
31484 + int *nrels_mag, long *results)
31486 + struct pcf8591_data *data = client->data;
31487 + int nr = ctl_name - PCF8591_SYSCTL_CH0;
31489 + if (operation == SENSORS_PROC_REAL_INFO)
31491 + else if (operation == SENSORS_PROC_REAL_READ) {
31492 + pcf8591_update_client(client);
31494 + /* Number of data to show and conversion to signed depend on */
31495 + /* the analog input mode */
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 */
31503 + results[0] = REG_TO_SIGNED(data->ch[0]);/* differential */
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 */
31510 + results[0] = REG_TO_SIGNED(data->ch[1]);/* differential */
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 */
31518 + results[0] = REG_TO_SIGNED(data->ch[2]);/* differential */
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 */
31525 + results[0] = 0; /* channel not used */
31532 +void pcf8591_aout_enable(struct i2c_client *client, int operation, int ctl_name,
31533 + int *nrels_mag, long *results)
31535 + struct pcf8591_data *data = client->data;
31537 + if (operation == SENSORS_PROC_REAL_INFO)
31539 + else if (operation == SENSORS_PROC_REAL_READ) {
31540 + results[0] = !(!(data->control_byte & PCF8591_CONTROL_BYTE_AOEF));
31542 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
31543 + if (*nrels_mag >= 1) {
31545 + data->control_byte |= PCF8591_CONTROL_BYTE_AOEF;
31547 + data->control_byte &= ~PCF8591_CONTROL_BYTE_AOEF;
31549 + i2c_smbus_write_byte(client, data->control_byte);
31554 +void pcf8591_aout(struct i2c_client *client, int operation, int ctl_name,
31555 + int *nrels_mag, long *results)
31557 + struct pcf8591_data *data = client->data;
31559 + if (operation == SENSORS_PROC_REAL_INFO)
31561 + else if (operation == SENSORS_PROC_REAL_READ) {
31562 + results[0] = data->aout;
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 */
31568 + data->aout = results[0];
31569 + i2c_smbus_write_byte_data(client, data->control_byte, data->aout);
31575 +static int __init sm_pcf8591_init(void)
31577 + printk(KERN_INFO "pcf8591.o version %s (%s)\n", LM_VERSION, LM_DATE);
31578 + return i2c_add_driver(&pcf8591_driver);
31581 +static void __exit sm_pcf8591_exit(void)
31583 + i2c_del_driver(&pcf8591_driver);
31588 +MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
31589 +MODULE_DESCRIPTION("PCF8591 driver");
31590 +MODULE_LICENSE("GPL");
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
31598 + sis5595.c - Part of lm_sensors, Linux kernel modules
31599 + for hardware monitoring
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>
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.
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.
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.
31621 + Supports following revisions:
31622 + Version PCI ID PCI Revision
31623 + 1 1039/0008 AF or less
31624 + 2 1039/0008 B0 or greater
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.
31630 + NOT SUPPORTED PCI ID BLACKLIST PCI ID
31637 + 5598 0008 5597/5598
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"
31655 +MODULE_LICENSE("GPL");
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");
31664 +/* Addresses to scan.
31665 + Note that we can't determine the ISA address until we have initialized
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 };
31672 +/* Insmod parameters */
31673 +SENSORS_INSMOD_1(sis5595);
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,
31689 + SiS southbridge has a LM78-like chip integrated on the same IC.
31690 + This driver is a customized copy of lm78.c
31693 +/* Many SIS5595 constants specified below */
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
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
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))
31712 +#define SIS5595_REG_FAN_MIN(nr) (0x3a + (nr))
31713 +#define SIS5595_REG_FAN(nr) (0x27 + (nr))
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. */
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
31729 +#define SIS5595_REG_CONFIG 0x40
31730 +#define SIS5595_REG_ALARM1 0x41
31731 +#define SIS5595_REG_ALARM2 0x42
31732 +#define SIS5595_REG_FANDIV 0x47
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. */
31739 +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
31740 +#define IN_FROM_REG(val) (((val) * 16 + 5) / 10)
31742 +static inline u8 FAN_TO_REG(long rpm, int div)
31746 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
31747 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
31751 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
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))
31760 +#define ALARMS_FROM_REG(val) (val)
31762 +#define DIV_FROM_REG(val) (1 << (val))
31763 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
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
31769 +struct sis5595_data {
31770 + struct i2c_client client;
31771 + struct semaphore lock;
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 */
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 */
31792 +static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
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);
31799 +static int sis5595_read_value(struct i2c_client *client, u8 register);
31800 +static int sis5595_write_value(struct i2c_client *client, u8 register,
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);
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);
31818 +static int sis5595_id = 0;
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,
31831 +/* The /proc/sys entries */
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 */
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
31855 +/* -- SENSORS SYSCTL END -- */
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},
31886 +/* This is called when the module is loaded */
31887 +static int sis5595_attach_adapter(struct i2c_adapter *adapter)
31889 + return i2c_detect(adapter, &addr_data, sis5595_detect);
31892 +/* Locate SiS bridge and correct base address for SIS5595 */
31893 +static int sis5595_find_sis(int *address)
31898 + if (!pci_present())
31902 + pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503,
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);
31914 + if (PCIBIOS_SUCCESSFUL !=
31915 + pci_read_config_word(s_bridge, SIS5595_BASE_REG, &val))
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");
31924 + *address = force_addr; /* so detect will get called */
31929 +int sis5595_detect(struct i2c_adapter *adapter, int address,
31930 + unsigned short flags, int kind)
31933 + struct i2c_client *new_client;
31934 + struct sis5595_data *data;
31936 + const char *type_name = "sis5595";
31937 + const char *client_name = "SIS5595 chip";
31941 + /* Make sure we are probing the ISA bus!! */
31942 + if (!i2c_is_isa_adapter(adapter)) {
31944 + ("sis5595.o: sis5595_detect called for an I2C bus adapter?!?\n");
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);
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))
31959 + if (PCIBIOS_SUCCESSFUL !=
31960 + pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
31962 + if ((a & ~(SIS5595_EXTENT - 1)) != address) {
31963 + /* doesn't work for some chips? */
31964 + printk("sis5595.o: force address failed\n");
31969 + if (PCIBIOS_SUCCESSFUL !=
31970 + pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
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,
31978 + if (PCIBIOS_SUCCESSFUL !=
31979 + pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
31981 + if((val & 0x80) == 0) { /* doesn't work for some chips! */
31982 + printk("sis5595.o: sensors enable failed - not supported?\n");
31987 + if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
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;
31999 + /* Reserve the ISA region */
32000 + request_region(address, SIS5595_EXTENT, type_name);
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;
32007 + pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val);
32009 + /* 3 voltages, 1 temp */
32010 + data->maxins = 3;
32012 + /* 4 voltages, no temps */
32013 + data->maxins = 4;
32016 + /* Fill in the remaining client fields and put it into the global list */
32017 + strcpy(new_client->name, client_name);
32019 + new_client->id = sis5595_id++;
32021 + init_MUTEX(&data->update_lock);
32023 + /* Tell the I2C layer a new client has arrived */
32024 + if ((err = i2c_attach_client(new_client)))
32027 + /* Register a new directory entry with module sensors */
32028 + if ((i = i2c_register_entry((struct i2c_client *) new_client,
32030 + sis5595_dir_table_template)) < 0) {
32034 + data->sysctl_id = i;
32036 + /* Initialize the SIS5595 chip */
32037 + sis5595_init_client(new_client);
32041 + i2c_detach_client(new_client);
32043 + release_region(address, SIS5595_EXTENT);
32048 +static int sis5595_detach_client(struct i2c_client *client)
32052 + i2c_deregister_entry(((struct sis5595_data *) (client->data))->
32055 + if ((err = i2c_detach_client(client))) {
32057 + ("sis5595.o: Client deregistration failed, client not detached.\n");
32061 + release_region(client->addr, SIS5595_EXTENT);
32062 + kfree(client->data);
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)
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));
32082 +static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
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));
32091 +/* Called when we have found a new SIS5595. */
32092 +static void sis5595_init_client(struct i2c_client *client)
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);
32101 +static void sis5595_update_client(struct i2c_client *client)
32103 + struct sis5595_data *data = client->data;
32106 + down(&data->update_lock);
32108 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
32109 + (jiffies < data->last_updated) || !data->valid) {
32111 + for (i = 0; i <= data->maxins; 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));
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));
32128 + if(data->maxins == 3) {
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);
32136 + i = sis5595_read_value(client, SIS5595_REG_FANDIV);
32137 + data->fan_div[0] = (i >> 4) & 0x03;
32138 + data->fan_div[1] = i >> 6;
32140 + sis5595_read_value(client, SIS5595_REG_ALARM1) |
32141 + (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8);
32142 + data->last_updated = jiffies;
32146 + up(&data->update_lock);
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. */
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)
32168 + struct sis5595_data *data = client->data;
32169 + int nr = ctl_name - SIS5595_SYSCTL_IN0;
32171 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
32201 +void sis5595_fan(struct i2c_client *client, int operation, int ctl_name,
32202 + int *nrels_mag, long *results)
32204 + struct sis5595_data *data = client->data;
32205 + int nr = ctl_name - SIS5595_SYSCTL_FAN1 + 1;
32207 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
32216 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
32217 + if (*nrels_mag >= 1) {
32218 + data->fan_min[nr - 1] = FAN_TO_REG(results[0],
32222 + sis5595_write_value(client,
32223 + SIS5595_REG_FAN_MIN(nr),
32224 + data->fan_min[nr - 1]);
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)
32234 + struct sis5595_data *data = client->data;
32235 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
32265 +void sis5595_alarms(struct i2c_client *client, int operation, int ctl_name,
32266 + int *nrels_mag, long *results)
32268 + struct sis5595_data *data = client->data;
32269 + if (operation == SENSORS_PROC_REAL_INFO)
32271 + else if (operation == SENSORS_PROC_REAL_READ) {
32272 + sis5595_update_client(client);
32273 + results[0] = ALARMS_FROM_REG(data->alarms);
32278 +void sis5595_fan_div(struct i2c_client *client, int operation,
32279 + int ctl_name, int *nrels_mag, long *results)
32281 + struct sis5595_data *data = client->data;
32284 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
32305 +static int __init sm_sis5595_init(void)
32309 + printk("sis5595.o version %s (%s)\n", LM_VERSION, LM_DATE);
32311 + if (sis5595_find_sis(&addr)) {
32312 + printk("sis5595.o: SIS5595 not detected, module not inserted.\n");
32315 + normal_isa[0] = addr;
32317 + return i2c_add_driver(&sis5595_driver);
32320 +static void __exit sm_sis5595_exit(void)
32322 + i2c_del_driver(&sis5595_driver);
32327 +MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
32328 +MODULE_DESCRIPTION("SiS 5595 Sensor device");
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
32336 + smsc47m1.c - Part of lm_sensors, Linux kernel modules
32337 + for hardware monitoring
32339 + Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
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"
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");
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 };
32376 +SENSORS_INSMOD_1(smsc47m1);
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 */
32385 +static inline void
32386 +superio_outb(int reg, int val)
32393 +superio_inb(int reg)
32399 +static inline void
32400 +superio_select(void)
32406 +static inline void
32407 +superio_enter(void)
32412 +static inline void
32413 +superio_exit(void)
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).
32424 +#define SMSC_DEVID_MATCH(id) ((id) == 0x51 || (id) == 0x59 || (id) == 0x5F)
32426 +#define SMSC_ACT_REG 0x30
32427 +#define SMSC_BASE_REG 0x60
32429 +#define SMSC_EXTENT 0x80
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))
32440 +static inline u8 MIN_TO_REG(long rpm, int div)
32444 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
32445 + return SENSORS_LIMIT(192 - ((983040 + rpm * div / 2) / (rpm * div)),
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)
32459 +struct smsc47m1_data {
32460 + struct i2c_client client;
32461 + struct semaphore lock;
32464 + struct semaphore update_lock;
32465 + char valid; /* !=0 if following fields are valid */
32466 + unsigned long last_updated; /* In jiffies */
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) */
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);
32481 +static int smsc47m1_read_value(struct i2c_client *client, u8 register);
32482 +static int smsc47m1_write_value(struct i2c_client *client, u8 register,
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);
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);
32498 +static int smsc47m1_id = 0;
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,
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 */
32517 +#define SMSC47M1_ALARM_FAN1 0x0001
32518 +#define SMSC47M1_ALARM_FAN2 0x0002
32520 +/* -- SENSORS SYSCTL END -- */
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},
32538 +static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
32540 + return i2c_detect(adapter, &addr_data, smsc47m1_detect);
32543 +static int smsc47m1_find(int *address)
32548 + val= superio_inb(DEVID);
32549 + if (!SMSC_DEVID_MATCH(val)) {
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");
32564 + *address = force_addr; /* so detect will get called */
32570 +int smsc47m1_detect(struct i2c_adapter *adapter, int address,
32571 + unsigned short flags, int kind)
32574 + struct i2c_client *new_client;
32575 + struct smsc47m1_data *data;
32577 + const char *type_name = "smsc47m1";
32578 + const char *client_name = "47M1xx chip";
32580 + if (!i2c_is_isa_adapter(adapter)) {
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);
32591 + printk("smsc47m1.o: forcing ISA address 0x%04X\n", address);
32593 + superio_select();
32594 + superio_outb(SMSC_BASE_REG, address >> 8);
32595 + superio_outb(SMSC_BASE_REG+1, address & 0xff);
32599 + if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
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;
32611 + request_region(address, SMSC_EXTENT, "smsc47m1-fans");
32612 + strcpy(new_client->name, client_name);
32614 + new_client->id = smsc47m1_id++;
32616 + init_MUTEX(&data->update_lock);
32618 + if ((err = i2c_attach_client(new_client)))
32621 + if ((i = i2c_register_entry((struct i2c_client *) new_client,
32623 + smsc47m1_dir_table_template)) < 0) {
32627 + data->sysctl_id = i;
32629 + smsc47m1_init_client(new_client);
32633 + i2c_detach_client(new_client);
32635 + release_region(address, SMSC_EXTENT);
32640 +static int smsc47m1_detach_client(struct i2c_client *client)
32644 + i2c_deregister_entry(((struct smsc47m1_data *) (client->data))->
32647 + if ((err = i2c_detach_client(client))) {
32649 + ("smsc47m1.o: Client deregistration failed, client not detached.\n");
32653 + release_region(client->addr, SMSC_EXTENT);
32654 + kfree(client->data);
32659 +static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
32663 + down(&(((struct smsc47m1_data *) (client->data))->lock));
32664 + res = inb_p(client->addr + reg);
32665 + up(&(((struct smsc47m1_data *) (client->data))->lock));
32669 +static int smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
32671 + down(&(((struct smsc47m1_data *) (client->data))->lock));
32672 + outb_p(value, client->addr + reg);
32673 + up(&(((struct smsc47m1_data *) (client->data))->lock));
32677 +static void smsc47m1_init_client(struct i2c_client *client)
32679 + /* configure pins for tach function */
32680 + smsc47m1_write_value(client, SMSC47M1_REG_TPIN1, 0x05);
32681 + smsc47m1_write_value(client, SMSC47M1_REG_TPIN2, 0x05);
32684 +static void smsc47m1_update_client(struct i2c_client *client)
32686 + struct smsc47m1_data *data = client->data;
32689 + down(&data->update_lock);
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));
32702 + i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
32703 + data->fan_div[0] = (i >> 4) & 0x03;
32704 + data->fan_div[1] = i >> 6;
32706 + smsc47m1_read_value(client, SMSC47M1_REG_ALARM1) >> 6;
32708 + smsc47m1_write_value(client, SMSC47M1_REG_ALARM1, 0xc0);
32709 + data->last_updated = jiffies;
32713 + up(&data->update_lock);
32717 +void smsc47m1_fan(struct i2c_client *client, int operation, int ctl_name,
32718 + int *nrels_mag, long *results)
32720 + struct smsc47m1_data *data = client->data;
32721 + int nr = ctl_name - SMSC47M1_SYSCTL_FAN1 + 1;
32723 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
32733 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
32734 + if (*nrels_mag >= 1) {
32735 + data->fan_min[nr - 1] = MIN_TO_REG(results[0],
32739 + smsc47m1_write_value(client, SMSC47M1_REG_FAN_MIN(nr),
32740 + data->fan_min[nr - 1]);
32746 +void smsc47m1_alarms(struct i2c_client *client, int operation, int ctl_name,
32747 + int *nrels_mag, long *results)
32749 + struct smsc47m1_data *data = client->data;
32750 + if (operation == SENSORS_PROC_REAL_INFO)
32752 + else if (operation == SENSORS_PROC_REAL_READ) {
32753 + smsc47m1_update_client(client);
32754 + results[0] = data->alarms;
32759 +void smsc47m1_fan_div(struct i2c_client *client, int operation,
32760 + int ctl_name, int *nrels_mag, long *results)
32762 + struct smsc47m1_data *data = client->data;
32765 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
32786 +void smsc47m1_pwm(struct i2c_client *client, int operation, int ctl_name,
32787 + int *nrels_mag, long *results)
32789 + struct smsc47m1_data *data = client->data;
32790 + int nr = 1 + ctl_name - SMSC47M1_SYSCTL_PWM1;
32792 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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)) {
32806 +/* hope BIOS did it already
32807 + smsc47m1_write_value(client,
32808 + SMSC47M1_REG_PPIN(nr), 0x04);
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;
32816 + smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
32817 + data->pwm[nr - 1]);
32822 +static int __init sm_smsc47m1_init(void)
32826 + printk("smsc47m1.o version %s (%s)\n", LM_VERSION, LM_DATE);
32828 + if (smsc47m1_find(&addr)) {
32829 + printk("smsc47m1.o: SMSC 47M1xx not detected, module not inserted.\n");
32832 + normal_isa[0] = addr;
32834 + return i2c_add_driver(&smsc47m1_driver);
32837 +static void __exit sm_smsc47m1_exit(void)
32839 + i2c_del_driver(&smsc47m1_driver);
32844 +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
32845 +MODULE_DESCRIPTION("SMSC 47M1xx Fan sensors");
32846 +MODULE_LICENSE("GPL");
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
32854 + thmc50.c - Part of lm_sensors, Linux kernel modules for hardware
32856 + Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
32857 + Philip Edelbrock <phil@netroedge.com>
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.
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.
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.
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"
32884 +MODULE_LICENSE("GPL");
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 };
32892 +/* Insmod parameters */
32893 +SENSORS_INSMOD_1(thmc50);
32895 +/* Many THMC50 constants specified below */
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
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
32912 +#define THMC50_REG_INTER 0x41
32913 +#define THMC50_REG_INTER_MIRROR 0x4C
32914 +#define THMC50_REG_INTER_MASK 0x43
32916 +#define THMC50_REG_COMPANY_ID 0x3E
32917 +#define THMC50_REG_DIE_CODE 0x3F
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)
32927 +/* Each client has this additional data */
32928 +struct thmc50_data {
32929 + struct i2c_client client;
32932 + struct semaphore update_lock;
32933 + char valid; /* !=0 if following fields are valid */
32934 + unsigned long last_updated; /* In jiffies */
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 */
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);
32947 +static int thmc50_read_value(struct i2c_client *client, u8 reg);
32948 +static int thmc50_write_value(struct i2c_client *client, u8 reg,
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,
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);
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,
32976 +/* -- SENSORS SYSCTL START -- */
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
32985 +/* -- SENSORS SYSCTL END -- */
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},
33009 +static int thmc50_id = 0;
33011 +static int thmc50_attach_adapter(struct i2c_adapter *adapter)
33013 + return i2c_detect(adapter, &addr_data, thmc50_detect);
33016 +/* This function is called by i2c_detect */
33017 +int thmc50_detect(struct i2c_adapter *adapter, int address,
33018 + unsigned short flags, int kind)
33021 + struct i2c_client *new_client;
33022 + struct thmc50_data *data;
33024 + const char *type_name, *client_name;
33027 + printk("thmc50.o: Probing for THMC50 at 0x%2X on bus %d\n",
33028 + address, adapter->id);
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. */
33034 + if (i2c_is_isa_adapter(adapter)) {
33036 + ("thmc50.o: thmc50_detect called for an ISA bus adapter?!?\n");
33041 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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))) {
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;
33059 + /* Now, we do the remaining detection. */
33061 + i2c_smbus_read_byte_data(new_client, THMC50_REG_COMPANY_ID);
33063 + if (company != 0x49) {
33066 + ("thmc50.o: Detect of THMC50 failed (reg 3E: 0x%X)\n",
33072 + /* Determine the chip type - only one kind supported! */
33075 + if (kind == thmc50) {
33076 + type_name = "thmc50";
33077 + client_name = "THMC50 chip";
33080 + printk("thmc50.o: Internal error: unknown kind (%d)?!?",
33086 + /* Fill in the remaining client fields and put it into the global list */
33087 + strcpy(new_client->name, client_name);
33089 + new_client->id = thmc50_id++;
33091 + init_MUTEX(&data->update_lock);
33093 + /* Tell the I2C layer a new client has arrived */
33094 + if ((err = i2c_attach_client(new_client)))
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) {
33103 + data->sysctl_id = i;
33105 + thmc50_init_client(new_client);
33108 +/* OK, this is not exactly good programming practice, usually. But it is
33109 + very code-efficient in this case. */
33112 + i2c_detach_client(new_client);
33120 +static int thmc50_detach_client(struct i2c_client *client)
33124 + i2c_deregister_entry(((struct thmc50_data *) (client->data))->
33127 + if ((err = i2c_detach_client(client))) {
33129 + ("thmc50.o: Client deregistration failed, client not detached.\n");
33133 + kfree(client->data);
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)
33144 + return i2c_smbus_read_byte_data(client, reg);
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)
33152 + return i2c_smbus_write_byte_data(client, reg, value);
33155 +static void thmc50_init_client(struct i2c_client *client)
33157 + thmc50_write_value(client, THMC50_REG_CONF, 1);
33160 +static void thmc50_update_client(struct i2c_client *client)
33162 + struct thmc50_data *data = client->data;
33164 + down(&data->update_lock);
33166 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
33167 + (jiffies < data->last_updated) || !data->valid) {
33170 + printk("Starting thmc50 update\n");
33173 + data->temp = thmc50_read_value(client, THMC50_REG_TEMP);
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);
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;
33195 + up(&data->update_lock);
33199 +void thmc50_temp(struct i2c_client *client, int operation, int ctl_name,
33200 + int *nrels_mag, long *results)
33202 + struct thmc50_data *data = client->data;
33203 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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,
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);
33226 +void thmc50_remote_temp(struct i2c_client *client, int operation,
33227 + int ctl_name, int *nrels_mag, long *results)
33229 + struct thmc50_data *data = client->data;
33230 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
33255 +void thmc50_inter(struct i2c_client *client, int operation, int ctl_name,
33256 + int *nrels_mag, long *results)
33258 + struct thmc50_data *data = client->data;
33259 + if (operation == SENSORS_PROC_REAL_INFO)
33261 + else if (operation == SENSORS_PROC_REAL_READ) {
33262 + thmc50_update_client(client);
33263 + results[0] = data->inter;
33265 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
33266 + printk("thmc50.o: No writes to Interrupt register!\n");
33271 +void thmc50_inter_mask(struct i2c_client *client, int operation,
33272 + int ctl_name, int *nrels_mag, long *results)
33274 + struct thmc50_data *data = client->data;
33275 + if (operation == SENSORS_PROC_REAL_INFO)
33277 + else if (operation == SENSORS_PROC_REAL_READ) {
33278 + thmc50_update_client(client);
33279 + results[0] = data->inter_mask;
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);
33291 +void thmc50_die_code(struct i2c_client *client, int operation,
33292 + int ctl_name, int *nrels_mag, long *results)
33294 + struct thmc50_data *data = client->data;
33295 + if (operation == SENSORS_PROC_REAL_INFO)
33297 + else if (operation == SENSORS_PROC_REAL_READ) {
33298 + thmc50_update_client(client);
33299 + results[0] = data->die_code;
33301 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
33302 + printk("thmc50.o: No writes to Die-Code register!\n");
33307 +void thmc50_analog_out(struct i2c_client *client, int operation,
33308 + int ctl_name, int *nrels_mag, long *results)
33310 + struct thmc50_data *data = client->data;
33311 + if (operation == SENSORS_PROC_REAL_INFO)
33313 + else if (operation == SENSORS_PROC_REAL_READ) {
33314 + thmc50_update_client(client);
33315 + results[0] = data->analog_out;
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);
33329 +static int __init sm_thmc50_init(void)
33331 + printk("thmc50.o version %s (%s)\n", LM_VERSION, LM_DATE);
33333 + return i2c_add_driver(&thmc50_driver);
33336 +static void __exit sm_thmc50_exit(void)
33338 + i2c_del_driver(&thmc50_driver);
33344 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
33345 +MODULE_DESCRIPTION("THMC50 driver");
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
33353 + via686a.c - Part of lm_sensors, Linux kernel modules
33354 + for hardware monitoring
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>.)
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.
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.
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.
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.
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"
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");
33404 +/* Addresses to scan.
33405 + Note that we can't determine the ISA address until we have initialized
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 };
33412 +/* Insmod parameters */
33413 +SENSORS_INSMOD_1(via686a);
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
33420 +/* Many VIA686A constants specified below */
33422 +/* Length of ISA address segment */
33423 +#define VIA686A_EXTENT 0x80
33424 +#define VIA686A_BASE_REG 0x70
33425 +#define VIA686A_ENABLE_REG 0x74
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))
33433 +/* fans numbered 1-2 */
33434 +#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
33435 +#define VIA686A_REG_FAN(nr) (0x28 + (nr))
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 };
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
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
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)
33464 +/* Conversions. Limit checking is only done on the TO_REG
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];
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)
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. */
33489 + SENSORS_LIMIT((val * 21024 - 120500) / 25000, 0, 255);
33490 + else if (inNum == 2)
33492 + SENSORS_LIMIT((val * 15737 - 120500) / 25000, 0, 255);
33493 + else if (inNum == 3)
33495 + SENSORS_LIMIT((val * 10108 - 120500) / 25000, 0, 255);
33498 + SENSORS_LIMIT((val * 41714 - 1205000) / 250000, 0, 255);
33501 +static inline long IN_FROM_REG(u8 val, int inNum)
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. */
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);
33513 + return (long) ((250000 * val + 1330000 + 41714 / 2) / 41714);
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)
33524 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
33525 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
33528 +#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
33530 +/******** TEMP CONVERSIONS (Bob Dougherty) *********/
33531 +// linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
33533 +// return double(temp)*0.427-32.08;
33534 +// else if(temp>=169 && temp<=202)
33535 +// return double(temp)*0.582-58.16;
33537 +// return double(temp)*0.924-127.33;
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.
33546 +// (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
33547 +// finding my typos in this formula!)
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
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};
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,
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)
33629 + return viaLUT[val <= -500 ? 0 : val >= 1100 ? 160 :
33630 + (val < 0 ? val - 5 : val + 5) / 10 + 50];
33633 +/* for 8-bit temperature hyst and over registers */
33634 +#define TEMP_FROM_REG(val) (tempLUT[(val)])
33636 +/* for 10-bit temperature readings */
33637 +// You might _think_ this is too long to inline, but's it's really only
33639 +static inline long TEMP_FROM_REG10(u16 val)
33641 + // the temp values are already *10, so we don't need to do that.
33643 + u16 eightBits = val >> 2;
33644 + u16 twoBits = val & 3;
33646 + /* no interpolation for these */
33647 + if (twoBits == 0 || eightBits == 255)
33648 + return (long) tempLUT[eightBits];
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;
33657 +#define ALARMS_FROM_REG(val) (val)
33659 +#define DIV_FROM_REG(val) (1 << (val))
33660 +#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
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;
33670 + struct semaphore update_lock;
33671 + char valid; /* !=0 if following fields are valid */
33672 + unsigned long last_updated; /* In jiffies */
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 */
33686 +static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
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);
33693 +static int via686a_read_value(struct i2c_client *client, u8 register);
33694 +static void via686a_write_value(struct i2c_client *client, u8 register,
33696 +static void via686a_update_client(struct i2c_client *client);
33697 +static void via686a_init_client(struct i2c_client *client);
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);
33711 +static int via686a_id = 0;
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,
33726 +/* The /proc/sys entries */
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
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
33754 +/* -- SENSORS SYSCTL END -- */
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},
33789 +static inline int via686a_read_value(struct i2c_client *client, u8 reg)
33791 + return (inb_p(client->addr + reg));
33794 +static inline void via686a_write_value(struct i2c_client *client, u8 reg,
33797 + outb_p(value, client->addr + reg);
33800 +/* This is called when the module is loaded */
33801 +static int via686a_attach_adapter(struct i2c_adapter *adapter)
33803 + return i2c_detect(adapter, &addr_data, via686a_detect);
33806 +int via686a_detect(struct i2c_adapter *adapter, int address,
33807 + unsigned short flags, int kind)
33810 + struct i2c_client *new_client;
33811 + struct via686a_data *data;
33813 + const char *type_name = "via686a";
33816 + /* Make sure we are probing the ISA bus!! */
33817 + if (!i2c_is_isa_adapter(adapter)) {
33819 + ("via686a.o: via686a_detect called for an I2C bus adapter?!?\n");
33823 + /* 8231 requires multiple of 256, we enforce that on 686 as well */
33825 + address = force_addr & 0xFF00;
33826 + if (check_region(address, VIA686A_EXTENT)) {
33827 + printk("via686a.o: region 0x%x already in use!\n",
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))
33838 + if (PCIBIOS_SUCCESSFUL !=
33839 + pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
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,
33849 + if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
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;
33862 + /* Reserve the ISA region */
33863 + request_region(address, VIA686A_EXTENT, "via686a-sensors");
33865 + /* Fill in the remaining client fields and put into the global list */
33866 + strcpy(new_client->name, "Via 686A Integrated Sensors");
33868 + new_client->id = via686a_id++;
33870 + init_MUTEX(&data->update_lock);
33872 + /* Tell the I2C layer a new client has arrived */
33873 + if ((err = i2c_attach_client(new_client)))
33876 + /* Register a new directory entry with module sensors */
33877 + if ((i = i2c_register_entry((struct i2c_client *) new_client,
33879 + via686a_dir_table_template)) < 0) {
33883 + data->sysctl_id = i;
33885 + /* Initialize the VIA686A chip */
33886 + via686a_init_client(new_client);
33890 + i2c_detach_client(new_client);
33892 + release_region(address, VIA686A_EXTENT);
33898 +static int via686a_detach_client(struct i2c_client *client)
33902 + i2c_deregister_entry(((struct via686a_data *)
33903 + (client->data))->sysctl_id);
33905 + if ((err = i2c_detach_client(client))) {
33907 + ("via686a.o: Client deregistration failed, client not detached.\n");
33911 + release_region(client->addr, VIA686A_EXTENT);
33912 + kfree(client->data);
33917 +/* Called when we have found a new VIA686A. */
33918 +static void via686a_init_client(struct i2c_client *client)
33922 + /* Start monitoring */
33923 + reg = via686a_read_value(client, VIA686A_REG_CONFIG);
33924 + via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
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));
33932 +static void via686a_update_client(struct i2c_client *client)
33934 + struct via686a_data *data = client->data;
33937 + down(&data->update_lock);
33939 + if (time_after(jiffies - data->last_updated, HZ + HZ / 2) ||
33940 + time_before(jiffies, data->last_updated) || !data->valid) {
33942 + for (i = 0; i <= 4; i++) {
33944 + via686a_read_value(client, VIA686A_REG_IN(i));
33945 + data->in_min[i] = via686a_read_value(client,
33946 + VIA686A_REG_IN_MIN
33948 + data->in_max[i] =
33949 + via686a_read_value(client, VIA686A_REG_IN_MAX(i));
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));
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));
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
33972 + data->temp[0] |= (via686a_read_value(client,
33973 + VIA686A_REG_TEMP_LOW1)
33976 + (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
33979 + (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
33982 + i = via686a_read_value(client, VIA686A_REG_FANDIV);
33983 + data->fan_div[0] = (i >> 4) & 0x03;
33984 + data->fan_div[1] = i >> 6;
33986 + via686a_read_value(client,
33987 + VIA686A_REG_ALARM1) |
33988 + (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);
33989 + data->last_updated = jiffies;
33993 + up(&data->update_lock);
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)
34013 + struct via686a_data *data = client->data;
34014 + int nr = ctl_name - VIA686A_SYSCTL_IN0;
34016 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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]);
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]);
34038 +void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
34039 + int *nrels_mag, long *results)
34041 + struct via686a_data *data = client->data;
34042 + int nr = ctl_name - VIA686A_SYSCTL_FAN1 + 1;
34044 + if (operation == SENSORS_PROC_REAL_INFO)
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
34051 + results[1] = FAN_FROM_REG(data->fan[nr - 1],
34052 + DIV_FROM_REG(data->fan_div[nr - 1]));
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]);
34066 +void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
34067 + int *nrels_mag, long *results)
34069 + struct via686a_data *data = client->data;
34070 + int nr = ctl_name - VIA686A_SYSCTL_TEMP;
34072 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
34096 +void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
34097 + int *nrels_mag, long *results)
34099 + struct via686a_data *data = client->data;
34100 + if (operation == SENSORS_PROC_REAL_INFO)
34102 + else if (operation == SENSORS_PROC_REAL_READ) {
34103 + via686a_update_client(client);
34104 + results[0] = ALARMS_FROM_REG(data->alarms);
34109 +void via686a_fan_div(struct i2c_client *client, int operation,
34110 + int ctl_name, int *nrels_mag, long *results)
34112 + struct via686a_data *data = client->data;
34115 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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,
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 },
34143 +static int __devinit via686a_pci_probe(struct pci_dev *dev,
34144 + const struct pci_device_id *id)
34149 + if (PCIBIOS_SUCCESSFUL !=
34150 + pci_read_config_word(dev, VIA686A_BASE_REG, &val))
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");
34159 + addr = force_addr; /* so detect will get called */
34162 + printk("via686a.o: No Via 686A sensors found.\n");
34165 + normal_isa[0] = addr;
34167 + return i2c_add_driver(&via686a_driver);
34170 +static void __devexit via686a_pci_remove(struct pci_dev *dev)
34172 + i2c_del_driver(&via686a_driver);
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),
34182 +static int __init sm_via686a_init(void)
34184 + printk("via686a.o version %s (%s)\n", LM_VERSION, LM_DATE);
34185 + return pci_module_init(&via686a_pci_driver);
34188 +static void __exit sm_via686a_exit(void)
34190 + pci_unregister_driver(&via686a_pci_driver);
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");
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
34205 + vt1211.c - Part of lm_sensors, Linux kernel modules
34206 + for hardware monitoring
34208 + Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
34225 +/* Supports VIA VT1211 Super I/O sensors via ISA (LPC) accesses only. */
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>
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");
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 };
34248 +SENSORS_INSMOD_1(vt1211);
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 */
34257 +static inline void
34258 +superio_outb(int reg, int val)
34265 +superio_inb(int reg)
34271 +static inline void
34272 +superio_select(void)
34278 +static inline void
34279 +superio_enter(void)
34285 +static inline void
34286 +superio_exit(void)
34291 +#define VT1211_DEVID 0x3c
34292 +#define VT1211_ACT_REG 0x30
34293 +#define VT1211_BASE_REG 0x60
34295 +#define VT1211_EXTENT 0x80
34297 +/* pwm numbered 1-2 */
34298 +#define VT1211_REG_PWM(nr) (0x5f + (nr))
34299 +#define VT1211_REG_PWM_CTL 0x51
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 + -------- ------------ ---------
34307 + Reading 3 temp1 not in vt1211
34308 + UCH1/Reading2 in0 temp2
34314 + -12V in6 not in vt1211
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))
34322 +/* fans numbered 1-2 */
34323 +#define VT1211_REG_FAN_MIN(nr) (0x3a + (nr))
34324 +#define VT1211_REG_FAN(nr) (0x28 + (nr))
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 };
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
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
34347 +/* temps 1-7; voltages 0-6 */
34348 +#define ISTEMP(i, ch_config) ((i) == 1 ? 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))
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)
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))
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)
34374 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
34375 + return SENSORS_LIMIT((1310720 + rpm * div / 2) / (rpm * div), 1, 255);
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)))
34381 +struct vt1211_data {
34382 + struct i2c_client client;
34383 + struct semaphore lock;
34386 + struct semaphore update_lock;
34387 + char valid; /* !=0 if following fields are valid */
34388 + unsigned long last_updated; /* In jiffies */
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 */
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);
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,
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);
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);
34439 +static int vt1211_id = 0;
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,
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
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
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
34494 +/* -- SENSORS SYSCTL END -- */
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},
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},
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},
34549 +static int vt1211_attach_adapter(struct i2c_adapter *adapter)
34551 + return i2c_detect(adapter, &addr_data, vt1211_detect);
34554 +static int vt1211_find(int *address)
34559 + val= superio_inb(DEVID);
34560 + if(VT1211_DEVID != val) {
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");
34575 + *address = force_addr; /* so detect will get called */
34581 +int vt1211_detect(struct i2c_adapter *adapter, int address,
34582 + unsigned short flags, int kind)
34585 + struct i2c_client *new_client;
34586 + struct vt1211_data *data;
34589 + const char *type_name = "vt1211";
34590 + const char *client_name = "VT1211 chip";
34592 + if (!i2c_is_isa_adapter(adapter)) {
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);
34603 + printk("vt1211.o: forcing ISA address 0x%04X\n", address);
34605 + superio_select();
34606 + superio_outb(VT1211_BASE_REG, address >> 8);
34607 + superio_outb(VT1211_BASE_REG+1, address & 0xff);
34612 + superio_select();
34613 + if((val = 0x01 & superio_inb(VT1211_ACT_REG)) == 0)
34614 + superio_outb(VT1211_ACT_REG, 1);
34617 + if (!(data = kmalloc(sizeof(struct vt1211_data), GFP_KERNEL))) {
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;
34629 + request_region(address, VT1211_EXTENT, "vt1211-sensors");
34630 + strcpy(new_client->name, client_name);
34632 + new_client->id = vt1211_id++;
34634 + init_MUTEX(&data->update_lock);
34636 + if ((err = i2c_attach_client(new_client)))
34639 + if ((i = i2c_register_entry((struct i2c_client *) new_client,
34641 + vt1211_dir_table_template)) < 0) {
34645 + data->sysctl_id = i;
34647 + vt1211_init_client(new_client);
34651 + i2c_detach_client(new_client);
34653 + release_region(address, VT1211_EXTENT);
34658 +static int vt1211_detach_client(struct i2c_client *client)
34662 + i2c_deregister_entry(((struct vt1211_data *) (client->data))->
34665 + if ((err = i2c_detach_client(client))) {
34667 + ("vt1211.o: Client deregistration failed, client not detached.\n");
34671 + release_region(client->addr, VT1211_EXTENT);
34672 + kfree(client->data);
34677 +static inline int vt_rdval(struct i2c_client *client, u8 reg)
34679 + return (inb_p(client->addr + reg));
34682 +static inline void vt1211_write_value(struct i2c_client *client, u8 reg, u8 value)
34684 + outb_p(value, client->addr + reg);
34687 +static void vt1211_init_client(struct i2c_client *client)
34689 + struct vt1211_data *data = client->data;
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);
34697 +static void vt1211_update_client(struct i2c_client *client)
34699 + struct vt1211_data *data = client->data;
34702 + down(&data->update_lock);
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));
34716 + data->in_min[i] = 0;
34717 + data->in_max[i] = 0;
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));
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;
34735 + j = (vt_rdval(client,
34736 + VT1211_REG_TEMP_LOW2) &
34740 + j = (vt_rdval(client,
34741 + VT1211_REG_TEMP_LOW3) &
34749 + j = (vt_rdval(client,
34750 + VT1211_REG_TEMP_LOW47) >>
34751 + ((i-4)*2)) & 0x03;
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));
34761 + data->temp[i - 1] = 0;
34762 + data->temp_over[i - 1] = 0;
34763 + data->temp_hyst[i - 1] = 0;
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));
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;
34785 + up(&data->update_lock);
34789 +void vt1211_in(struct i2c_client *client, int operation, int ctl_name,
34790 + int *nrels_mag, long *results)
34792 + struct vt1211_data *data = client->data;
34793 + int nr = ctl_name - VT1211_SYSCTL_IN0;
34795 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
34817 +void vt1211_fan(struct i2c_client *client, int operation, int ctl_name,
34818 + int *nrels_mag, long *results)
34820 + struct vt1211_data *data = client->data;
34821 + int nr = ctl_name - VT1211_SYSCTL_FAN1 + 1;
34823 + if (operation == SENSORS_PROC_REAL_INFO)
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
34830 + results[1] = FAN_FROM_REG(data->fan[nr - 1],
34831 + DIV_FROM_REG(data->fan_div[nr - 1]));
34833 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
34834 + if (*nrels_mag >= 1) {
34835 + data->fan_min[nr - 1] = MIN_TO_REG(results[0],
34839 + vt1211_write_value(client, VT1211_REG_FAN_MIN(nr),
34840 + data->fan_min[nr - 1]);
34846 +void vt1211_temp(struct i2c_client *client, int operation, int ctl_name,
34847 + int *nrels_mag, long *results)
34849 + struct vt1211_data *data = client->data;
34850 + int nr = ctl_name - VT1211_SYSCTL_TEMP;
34852 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
34876 +void vt1211_alarms(struct i2c_client *client, int operation, int ctl_name,
34877 + int *nrels_mag, long *results)
34879 + struct vt1211_data *data = client->data;
34880 + if (operation == SENSORS_PROC_REAL_INFO)
34882 + else if (operation == SENSORS_PROC_REAL_READ) {
34883 + vt1211_update_client(client);
34884 + results[0] = data->alarms;
34889 +void vt1211_fan_div(struct i2c_client *client, int operation,
34890 + int ctl_name, int *nrels_mag, long *results)
34892 + struct vt1211_data *data = client->data;
34895 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
34916 +void vt1211_pwm(struct i2c_client *client, int operation, int ctl_name,
34917 + int *nrels_mag, long *results)
34919 + struct vt1211_data *data = client->data;
34920 + int nr = 1 + ctl_name - VT1211_SYSCTL_PWM1;
34922 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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) {
34935 + (0x08 << (4 * (nr - 1)));
34936 + vt1211_write_value(client,
34937 + VT1211_REG_PWM_CTL,
34941 + ~ (0x08 << (4 * (nr - 1)));
34942 + vt1211_write_value(client,
34943 + VT1211_REG_PWM_CTL,
34947 + vt1211_write_value(client, VT1211_REG_PWM(nr),
34948 + data->pwm[nr - 1]);
34953 +void vt1211_vid(struct i2c_client *client, int operation, int ctl_name,
34954 + int *nrels_mag, long *results)
34956 + struct vt1211_data *data = client->data;
34957 + if (operation == SENSORS_PROC_REAL_INFO)
34959 + else if (operation == SENSORS_PROC_REAL_READ) {
34960 + vt1211_update_client(client);
34961 + results[0] = vid_from_reg(data->vid, data->vrm);
34966 +void vt1211_vrm(struct i2c_client *client, int operation, int ctl_name,
34967 + int *nrels_mag, long *results)
34969 + struct vt1211_data *data = client->data;
34970 + if (operation == SENSORS_PROC_REAL_INFO)
34972 + else if (operation == SENSORS_PROC_REAL_READ) {
34973 + results[0] = data->vrm;
34975 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
34976 + if (*nrels_mag >= 1)
34977 + data->vrm = results[0];
34981 +void vt1211_uch(struct i2c_client *client, int operation, int ctl_name,
34982 + int *nrels_mag, long *results)
34984 + struct vt1211_data *data = client->data;
34985 + if (operation == SENSORS_PROC_REAL_INFO)
34987 + else if (operation == SENSORS_PROC_REAL_READ) {
34988 + results[0] = data->uch_config & 0x7c;
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);
34999 +static int __init sm_vt1211_init(void)
35003 + printk("vt1211.o version %s (%s)\n", LM_VERSION, LM_DATE);
35005 + if (vt1211_find(&addr)) {
35006 + printk("vt1211.o: VT1211 not detected, module not inserted.\n");
35009 + normal_isa[0] = addr;
35011 + return i2c_add_driver(&vt1211_driver);
35014 +static void __exit sm_vt1211_exit(void)
35016 + i2c_del_driver(&vt1211_driver);
35021 +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
35022 +MODULE_DESCRIPTION("VT1211 sensors");
35023 +MODULE_LICENSE("GPL");
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
35031 + vt8231.c - Part of lm_sensors, Linux kernel modules
35032 + for hardware monitoring
35034 + Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
35051 +/* Supports VIA VT8231 South Bridge embedded sensors */
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>
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");
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 };
35076 +SENSORS_INSMOD_1(vt8231);
35078 +#define VIA686A_EXTENT 0x80
35079 +#define VIA686A_BASE_REG 0x70
35080 +#define VIA686A_ENABLE_REG 0x74
35082 +/* pwm numbered 1-2 */
35083 +#define VT8231_REG_PWM(nr) (0x5f + (nr))
35084 +#define VT8231_REG_PWM_CTL 0x51
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 + -------- ------------ ---------
35092 + Reading 3 temp1 not in vt8231
35093 + UCH1/Reading2 in0 temp2
35099 + -12V in6 not in vt8231
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))
35107 +/* fans numbered 1-2 */
35108 +#define VT8231_REG_FAN_MIN(nr) (0x3a + (nr))
35109 +#define VT8231_REG_FAN(nr) (0x28 + (nr))
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 };
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
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
35132 +/* temps 1-7; voltages 0-6 */
35133 +#define ISTEMP(i, ch_config) ((i) == 1 ? 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))
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)
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))
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)
35159 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
35160 + return SENSORS_LIMIT((1310720 + rpm * div / 2) / (rpm * div), 1, 255);
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)))
35166 +struct vt8231_data {
35167 + struct i2c_client client;
35168 + struct semaphore lock;
35171 + struct semaphore update_lock;
35172 + char valid; /* !=0 if following fields are valid */
35173 + unsigned long last_updated; /* In jiffies */
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 */
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);
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,
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);
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);
35224 +static int vt8231_id = 0;
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,
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
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
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
35279 +/* -- SENSORS SYSCTL END -- */
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},
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},
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},
35334 +static struct pci_dev *s_bridge;
35336 +static int vt8231_attach_adapter(struct i2c_adapter *adapter)
35338 + return i2c_detect(adapter, &addr_data, vt8231_detect);
35341 +/* Locate chip and get correct base address */
35342 +static int vt8231_find(int *address)
35346 + if (!pci_present())
35349 + if (!(s_bridge = pci_find_device(PCI_VENDOR_ID_VIA,
35353 + if (PCIBIOS_SUCCESSFUL !=
35354 + pci_read_config_word(s_bridge, VIA686A_BASE_REG, &val))
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");
35362 + *address = force_addr; /* so detect will get called */
35367 +int vt8231_detect(struct i2c_adapter *adapter, int address,
35368 + unsigned short flags, int kind)
35371 + struct i2c_client *new_client;
35372 + struct vt8231_data *data;
35374 + const char *type_name = "vt8231";
35377 + if (!i2c_is_isa_adapter(adapter)) {
35381 + /* 8231 requires multiple of 256 */
35383 + address = force_addr & 0xFF00;
35384 + if (check_region(address, VIA686A_EXTENT)) {
35385 + printk("vt8231.o: region 0x%x already in use!\n",
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))
35396 + if (PCIBIOS_SUCCESSFUL !=
35397 + pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
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,
35407 + if (!(data = kmalloc(sizeof(struct vt8231_data), GFP_KERNEL))) {
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;
35420 + /* Reserve the ISA region */
35421 + request_region(address, VIA686A_EXTENT, "vt8231-sensors");
35423 + /* Fill in the remaining client fields and put into the global list */
35424 + strcpy(new_client->name, "Via 8231 Integrated Sensors");
35426 + new_client->id = vt8231_id++;
35428 + init_MUTEX(&data->update_lock);
35430 + /* Tell the I2C layer a new client has arrived */
35431 + if ((err = i2c_attach_client(new_client)))
35434 + /* Register a new directory entry with module sensors */
35435 + if ((i = i2c_register_entry((struct i2c_client *) new_client,
35437 + vt8231_dir_table_template)) < 0) {
35441 + data->sysctl_id = i;
35443 + vt8231_init_client(new_client);
35447 + i2c_detach_client(new_client);
35449 + release_region(address, VIA686A_EXTENT);
35455 +static int vt8231_detach_client(struct i2c_client *client)
35459 + i2c_deregister_entry(((struct vt8231_data *) (client->data))->
35462 + if ((err = i2c_detach_client(client))) {
35464 + ("vt8231.o: Client deregistration failed, client not detached.\n");
35468 + release_region(client->addr, VIA686A_EXTENT);
35469 + kfree(client->data);
35475 +static inline int vt_rdval(struct i2c_client *client, u8 reg)
35477 + return (inb_p(client->addr + reg));
35480 +static inline void vt8231_write_value(struct i2c_client *client, u8 reg, u8 value)
35482 + outb_p(value, client->addr + reg);
35485 +static void vt8231_init_client(struct i2c_client *client)
35487 + struct vt8231_data *data = client->data;
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);
35495 +static void vt8231_update_client(struct i2c_client *client)
35497 + struct vt8231_data *data = client->data;
35500 + down(&data->update_lock);
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));
35514 + data->in_min[i] = 0;
35515 + data->in_max[i] = 0;
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));
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;
35533 + j = (vt_rdval(client,
35534 + VT8231_REG_TEMP_LOW2) &
35538 + j = (vt_rdval(client,
35539 + VT8231_REG_TEMP_LOW3) &
35547 + j = (vt_rdval(client,
35548 + VT8231_REG_TEMP_LOW47) >>
35549 + ((i-4)*2)) & 0x03;
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));
35559 + data->temp[i - 1] = 0;
35560 + data->temp_over[i - 1] = 0;
35561 + data->temp_hyst[i - 1] = 0;
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));
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;
35583 + up(&data->update_lock);
35587 +void vt8231_in(struct i2c_client *client, int operation, int ctl_name,
35588 + int *nrels_mag, long *results)
35590 + struct vt8231_data *data = client->data;
35591 + int nr = ctl_name - VT8231_SYSCTL_IN0;
35593 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
35615 +void vt8231_fan(struct i2c_client *client, int operation, int ctl_name,
35616 + int *nrels_mag, long *results)
35618 + struct vt8231_data *data = client->data;
35619 + int nr = ctl_name - VT8231_SYSCTL_FAN1 + 1;
35621 + if (operation == SENSORS_PROC_REAL_INFO)
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
35628 + results[1] = FAN_FROM_REG(data->fan[nr - 1],
35629 + DIV_FROM_REG(data->fan_div[nr - 1]));
35631 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
35632 + if (*nrels_mag >= 1) {
35633 + data->fan_min[nr - 1] = MIN_TO_REG(results[0],
35637 + vt8231_write_value(client, VT8231_REG_FAN_MIN(nr),
35638 + data->fan_min[nr - 1]);
35644 +void vt8231_temp(struct i2c_client *client, int operation, int ctl_name,
35645 + int *nrels_mag, long *results)
35647 + struct vt8231_data *data = client->data;
35648 + int nr = ctl_name - VT8231_SYSCTL_TEMP;
35650 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
35674 +void vt8231_alarms(struct i2c_client *client, int operation, int ctl_name,
35675 + int *nrels_mag, long *results)
35677 + struct vt8231_data *data = client->data;
35678 + if (operation == SENSORS_PROC_REAL_INFO)
35680 + else if (operation == SENSORS_PROC_REAL_READ) {
35681 + vt8231_update_client(client);
35682 + results[0] = data->alarms;
35687 +void vt8231_fan_div(struct i2c_client *client, int operation,
35688 + int ctl_name, int *nrels_mag, long *results)
35690 + struct vt8231_data *data = client->data;
35693 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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);
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);
35714 +void vt8231_pwm(struct i2c_client *client, int operation, int ctl_name,
35715 + int *nrels_mag, long *results)
35717 + struct vt8231_data *data = client->data;
35718 + int nr = 1 + ctl_name - VT8231_SYSCTL_PWM1;
35720 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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) {
35733 + (0x08 << (4 * (nr - 1)));
35734 + vt8231_write_value(client,
35735 + VT8231_REG_PWM_CTL,
35739 + ~ (0x08 << (4 * (nr - 1)));
35740 + vt8231_write_value(client,
35741 + VT8231_REG_PWM_CTL,
35745 + vt8231_write_value(client, VT8231_REG_PWM(nr),
35746 + data->pwm[nr - 1]);
35751 +void vt8231_vid(struct i2c_client *client, int operation, int ctl_name,
35752 + int *nrels_mag, long *results)
35754 + struct vt8231_data *data = client->data;
35755 + if (operation == SENSORS_PROC_REAL_INFO)
35757 + else if (operation == SENSORS_PROC_REAL_READ) {
35758 + vt8231_update_client(client);
35759 + results[0] = vid_from_reg(data->vid, data->vrm);
35764 +void vt8231_vrm(struct i2c_client *client, int operation, int ctl_name,
35765 + int *nrels_mag, long *results)
35767 + struct vt8231_data *data = client->data;
35768 + if (operation == SENSORS_PROC_REAL_INFO)
35770 + else if (operation == SENSORS_PROC_REAL_READ) {
35771 + results[0] = data->vrm;
35773 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
35774 + if (*nrels_mag >= 1)
35775 + data->vrm = results[0];
35779 +void vt8231_uch(struct i2c_client *client, int operation, int ctl_name,
35780 + int *nrels_mag, long *results)
35782 + struct vt8231_data *data = client->data;
35783 + if (operation == SENSORS_PROC_REAL_INFO)
35785 + else if (operation == SENSORS_PROC_REAL_READ) {
35786 + results[0] = data->uch_config & 0x7c;
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);
35797 +static int __init sm_vt8231_init(void)
35801 + printk("vt8231.o version %s (%s)\n", LM_VERSION, LM_DATE);
35803 + if (vt8231_find(&addr)) {
35804 + printk("vt8231.o: VT8231 not detected, module not inserted.\n");
35807 + normal_isa[0] = addr;
35809 + return i2c_add_driver(&vt8231_driver);}
35811 +static void __exit sm_vt8231_exit(void)
35813 + i2c_del_driver(&vt8231_driver);
35818 +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
35819 +MODULE_DESCRIPTION("VT8231 sensors");
35820 +MODULE_LICENSE("GPL");
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
35828 + w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware
35830 + Copyright (c) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>,
35831 + Philip Edelbrock <phil@netroedge.com>,
35832 + and Mark Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
35850 + Supports following chips:
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)
35858 + For other winbond chips, and for i2c support in the above chips,
35861 + Note: automatic ("cruise") fan control for 697, 637 & 627thf not
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>
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");
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 };
35892 +/* Insmod parameters */
35893 +SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
35895 +static int init = 1;
35896 +MODULE_PARM(init, "i");
35897 +MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
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 */
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
35921 +#define DEVID 0x20 /* Register: Device ID */
35923 +#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */
35924 +#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */
35925 +#define W83627THF_GPIO5_INVR 0xf5 /* w83627thf only */
35927 +static inline void
35928 +superio_outb(int reg, int val)
35935 +superio_inb(int reg)
35941 +static inline void
35942 +superio_select(int ld)
35948 +static inline void
35949 +superio_enter(void)
35955 +static inline void
35956 +superio_exit(void)
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 */
35969 +/* Length of ISA address segment */
35970 +#define WINB_EXTENT 8
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
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))
35985 +#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
35986 +#define W83781D_REG_FAN(nr) (0x27 + (nr))
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
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
36002 +#define W83781D_REG_CONFIG 0x40
36003 +#define W83781D_REG_ALARM1 0x41
36004 +#define W83781D_REG_ALARM2 0x42
36005 +#define W83781D_REG_ALARM3 0x450
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
36013 +#define W83781D_REG_VID_FANDIV 0x47
36015 +#define W83781D_REG_CHIPID 0x49
36016 +#define W83781D_REG_WCHIPID 0x58
36017 +#define W83781D_REG_CHIPMAN 0x4F
36018 +#define W83781D_REG_PIN 0x4B
36020 +#define W83781D_REG_VBAT 0x5D
36022 +#define W83627HF_REG_PWM1 0x5A
36023 +#define W83627HF_REG_PWM2 0x5B
36024 +#define W83627HF_REG_PWMCLK12 0x5C
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 */
36030 +#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */
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])
36038 +#define W83781D_REG_I2C_ADDR 0x48
36039 +#define W83781D_REG_I2C_SUBADDR 0x4A
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
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)
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)
36059 +static inline u8 FAN_TO_REG(long rpm, int div)
36063 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
36064 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
36068 +#define TEMP_MIN (-1280)
36069 +#define TEMP_MAX ( 1270)
36071 +/* TEMP: 1/10 degrees C (-128C to +127C)
36072 + REG: 1C/bit, two's complement */
36073 +static u8 TEMP_TO_REG(int temp)
36075 + int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
36076 + ntemp += (ntemp<0 ? -5 : 5);
36077 + return (u8)(ntemp / 10);
36080 +static int TEMP_FROM_REG(u8 reg)
36082 + return (s8)reg * 10;
36085 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
36087 +#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
36088 +#define BEEPS_TO_REG(val) ((val) & 0xffffff)
36090 +#define BEEP_ENABLE_TO_REG(val) ((val)?1:0)
36091 +#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0)
36093 +#define DIV_FROM_REG(val) (1 << (val))
36095 +static inline u8 DIV_TO_REG(long val)
36098 + val = SENSORS_LIMIT(val, 1, 128) >> 1;
36099 + for (i = 0; i < 6; i++) {
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;
36116 + struct semaphore update_lock;
36117 + char valid; /* !=0 if following fields are valid */
36118 + unsigned long last_updated; /* In jiffies */
36120 + struct i2c_client *lm75; /* for secondary I2C addresses */
36121 + /* pointer to array of 2 subclients */
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 */
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.
36145 + Other Betas unimplemented */
36147 + u8 vrm_ovt; /* Register value, 627thf & 637hf only */
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);
36156 +static int w83627hf_read_value(struct i2c_client *client, u16 register);
36157 +static int w83627hf_write_value(struct i2c_client *client, u16 register,
36159 +static void w83627hf_update_client(struct i2c_client *client);
36160 +static void w83627hf_init_client(struct i2c_client *client);
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);
36186 +static int w83627hf_id = 0;
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,
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 !!!
36203 +/* -- SENSORS SYSCTL START -- */
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 */
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
36250 +/* -- SENSORS SYSCTL END -- */
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. */
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},
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},
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},
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)
36418 + return i2c_detect(adapter, &addr_data, w83627hf_detect);
36421 +static int w83627hf_find(int *address)
36426 + val= superio_inb(DEVID);
36427 + if(val != W627_DEVID && val !=W627THF_DEVID && val != W697_DEVID && val != W637_DEVID) {
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");
36442 + *address = force_addr; /* so detect will get called */
36448 +int w83627hf_detect(struct i2c_adapter *adapter, int address,
36449 + unsigned short flags, int kind)
36452 + struct i2c_client *new_client;
36453 + struct w83627hf_data *data;
36455 + const char *type_name = "";
36456 + const char *client_name = "";
36458 + if (!i2c_is_isa_adapter(adapter))
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);
36468 + printk("w83627hf.o: forcing ISA address 0x%04X\n", address);
36470 + superio_select(W83627HF_LD_HWM);
36471 + superio_outb(WINB_BASE_REG, address >> 8);
36472 + superio_outb(WINB_BASE_REG+1, address & 0xff);
36477 + val= superio_inb(DEVID);
36478 + if(val == W627_DEVID)
36480 + else if(val == W697_DEVID)
36482 + else if(val == W627THF_DEVID)
36483 + kind = w83627thf;
36484 + else if(val == W637_DEVID)
36487 + superio_select(W83627HF_LD_HWM);
36488 + if((val = 0x01 & superio_inb(WINB_ACT_REG)) == 0)
36489 + superio_outb(WINB_ACT_REG, 1);
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. */
36496 + if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
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;
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";
36526 + request_region(address, WINB_EXTENT, type_name);
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++;
36533 + init_MUTEX(&data->update_lock);
36535 + /* Tell the I2C layer a new client has arrived */
36536 + if ((err = i2c_attach_client(new_client)))
36539 + data->lm75 = NULL;
36541 + /* Register a new directory entry with module sensors */
36542 + if ((i = i2c_register_entry(new_client,
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) {
36553 + data->sysctl_id = i;
36555 + /* Initialize the chip */
36556 + w83627hf_init_client(new_client);
36559 +/* OK, this is not exactly good programming practice, usually. But it is
36560 + very code-efficient in this case. */
36563 + i2c_detach_client(new_client);
36565 + release_region(address, WINB_EXTENT);
36572 +static int w83627hf_detach_client(struct i2c_client *client)
36576 + i2c_deregister_entry(((struct w83627hf_data *) (client->data))->
36579 + if ((err = i2c_detach_client(client))) {
36581 + (KERN_ERR "w83627hf.o: Client deregistration failed, client not detached.\n");
36585 + release_region(client->addr, WINB_EXTENT);
36586 + kfree(client->data);
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)
36600 + int res, word_sized;
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);
36612 + client->addr + W83781D_DATA_REG_OFFSET);
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);
36620 + (res << 8) + inb_p(client->addr +
36621 + W83781D_DATA_REG_OFFSET);
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);
36628 + up(&(((struct w83627hf_data *) (client->data))->lock));
36632 +static int w83627thf_read_gpio5(struct i2c_client *client)
36636 + down(&(((struct w83627hf_data *) (client->data))->lock));
36638 + superio_select(W83627HF_LD_GPIO5);
36639 + res = superio_inb(W83627THF_GPIO5_DR);
36640 + inv = superio_inb(W83627THF_GPIO5_INVR);
36642 + up(&(((struct w83627hf_data *) (client->data))->lock));
36646 +static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
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);
36659 + client->addr + W83781D_DATA_REG_OFFSET);
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);
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);
36675 + up(&(((struct w83627hf_data *) (client->data))->lock));
36679 +/* Called when we have found a new W83781D. It should set limits, etc. */
36680 +static void w83627hf_init_client(struct i2c_client *client)
36682 + struct w83627hf_data *data = client->data;
36684 + int type = data->type;
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);
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;
36702 + /* Read VRM & OVT Config only once */
36703 + if (w83627thf == data->type || w83637hf == data->type)
36705 + w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
36707 + data->vrm_ovt = 0;
36709 + /* Choose VRM based on "VRM & OVT" register */
36710 + data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
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;
36717 + if (w83627hf_read_value
36719 + W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
36720 + data->sens[i - 1] = 1;
36722 + data->sens[i - 1] = 2;
36724 + if ((type == w83697hf) && (i == 2))
36728 + data->pwmenable[0] = 1;
36729 + data->pwmenable[1] = 1;
36730 + data->pwmenable[2] = 1;
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);
36738 + /* enable comparator mode for temp2 and temp3 so
36739 + alarm indication will work correctly */
36740 + i = w83627hf_read_value(client, W83781D_REG_IRQ);
36742 + w83627hf_write_value(client, W83781D_REG_IRQ,
36746 + /* Start monitoring */
36747 + w83627hf_write_value(client, W83781D_REG_CONFIG,
36748 + (w83627hf_read_value(client,
36749 + W83781D_REG_CONFIG) & 0xf7)
36753 +static void w83627hf_update_client(struct i2c_client *client)
36755 + struct w83627hf_data *data = client->data;
36758 + down(&data->update_lock);
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)))
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));
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));
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))
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);
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;
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;
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;
36839 + up(&data->update_lock);
36842 +void w83627hf_in(struct i2c_client *client, int operation, int ctl_name,
36843 + int *nrels_mag, long *results)
36845 + struct w83627hf_data *data = client->data;
36846 + int nr = ctl_name - W83781D_SYSCTL_IN0;
36848 + if (operation == SENSORS_PROC_REAL_INFO)
36850 + else if (operation == SENSORS_PROC_REAL_READ) {
36851 + w83627hf_update_client(client);
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]);
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]);
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]);
36874 + /* use VRM8 (standard) calculation */
36875 + data->in_min[nr] = IN_TO_REG(results[0]);
36877 + w83627hf_write_value(client, W83781D_REG_IN_MIN(nr),
36878 + data->in_min[nr]);
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]);
36885 + /* use VRM8 (standard) calculation */
36886 + data->in_max[nr] = IN_TO_REG(results[1]);
36888 + w83627hf_write_value(client, W83781D_REG_IN_MAX(nr),
36889 + data->in_max[nr]);
36894 +void w83627hf_fan(struct i2c_client *client, int operation, int ctl_name,
36895 + int *nrels_mag, long *results)
36897 + struct w83627hf_data *data = client->data;
36898 + int nr = ctl_name - W83781D_SYSCTL_FAN1 + 1;
36900 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
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]);
36921 +void w83627hf_temp(struct i2c_client *client, int operation, int ctl_name,
36922 + int *nrels_mag, long *results)
36924 + struct w83627hf_data *data = client->data;
36925 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
36947 +void w83627hf_temp_add(struct i2c_client *client, int operation,
36948 + int ctl_name, int *nrels_mag, long *results)
36950 + struct w83627hf_data *data = client->data;
36951 + int nr = ctl_name - W83781D_SYSCTL_TEMP2;
36953 + if (operation == SENSORS_PROC_REAL_INFO)
36955 + else if (operation == SENSORS_PROC_REAL_READ) {
36956 + w83627hf_update_client(client);
36958 + LM75_TEMP_FROM_REG(data->temp_add_over[nr]);
36960 + LM75_TEMP_FROM_REG(data->temp_add_hyst[nr]);
36961 + results[2] = LM75_TEMP_FROM_REG(data->temp_add[nr]);
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]);
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]);
36983 +void w83627hf_vid(struct i2c_client *client, int operation, int ctl_name,
36984 + int *nrels_mag, long *results)
36986 + struct w83627hf_data *data = client->data;
36987 + if (operation == SENSORS_PROC_REAL_INFO)
36989 + else if (operation == SENSORS_PROC_REAL_READ) {
36990 + w83627hf_update_client(client);
36991 + results[0] = vid_from_reg(data->vid, data->vrm);
36996 +void w83627hf_vrm(struct i2c_client *client, int operation, int ctl_name,
36997 + int *nrels_mag, long *results)
36999 + struct w83627hf_data *data = client->data;
37000 + if (operation == SENSORS_PROC_REAL_INFO)
37002 + else if (operation == SENSORS_PROC_REAL_READ) {
37003 + results[0] = data->vrm;
37005 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
37006 + if (*nrels_mag >= 1)
37007 + data->vrm = results[0];
37011 +void w83627hf_alarms(struct i2c_client *client, int operation, int ctl_name,
37012 + int *nrels_mag, long *results)
37014 + struct w83627hf_data *data = client->data;
37015 + if (operation == SENSORS_PROC_REAL_INFO)
37017 + else if (operation == SENSORS_PROC_REAL_READ) {
37018 + w83627hf_update_client(client);
37019 + results[0] = data->alarms;
37024 +void w83627hf_beep(struct i2c_client *client, int operation, int ctl_name,
37025 + int *nrels_mag, long *results)
37027 + struct w83627hf_data *data = client->data;
37030 + if (operation == SENSORS_PROC_REAL_INFO)
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;
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) &
37046 + val = (data->beeps >> 8) & 0x7f;
37047 + } else if (*nrels_mag >= 1)
37049 + w83627hf_read_value(client,
37050 + W83781D_REG_BEEP_INTS2) &
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);
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)
37064 + struct w83627hf_data *data = client->data;
37065 + int old, old2, old3 = 0;
37067 + if (operation == SENSORS_PROC_REAL_INFO)
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) {
37076 + results[2] = DIV_FROM_REG(data->fan_div[2]);
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 */
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);
37089 + (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
37090 + w83627hf_write_value(client, W83781D_REG_PIN, old2);
37093 + ((data->fan_div[2] & 0x04) << 5);
37095 + if (*nrels_mag >= 2) {
37096 + data->fan_div[1] =
37097 + DIV_TO_REG(results[1]);
37099 + (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
37102 + ((data->fan_div[1] & 0x04) << 4);
37104 + if (*nrels_mag >= 1) {
37105 + data->fan_div[0] =
37106 + DIV_TO_REG(results[0]);
37108 + (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
37109 + w83627hf_write_value(client, W83781D_REG_VID_FANDIV,
37113 + ((data->fan_div[0] & 0x04) << 3);
37114 + w83627hf_write_value(client,
37115 + W83781D_REG_VBAT,
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)
37126 + struct w83627hf_data *data = client->data;
37127 + int nr = 1 + ctl_name - W83781D_SYSCTL_PWM1;
37129 + if (operation == SENSORS_PROC_REAL_INFO)
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];
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));
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]);
37156 +void w83627hf_sens(struct i2c_client *client, int operation, int ctl_name,
37157 + int *nrels_mag, long *results)
37159 + struct w83627hf_data *data = client->data;
37160 + int nr = 1 + ctl_name - W83781D_SYSCTL_SENS1;
37163 + if (operation == SENSORS_PROC_REAL_INFO)
37165 + else if (operation == SENSORS_PROC_REAL_READ) {
37166 + results[0] = data->sens[nr - 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 -
37178 + tmp = w83627hf_read_value(client,
37179 + W83781D_REG_SCFG2);
37180 + w83627hf_write_value(client,
37181 + W83781D_REG_SCFG2,
37182 + tmp | BIT_SCFG2[nr -
37184 + data->sens[nr - 1] = results[0];
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 -
37193 + tmp = w83627hf_read_value(client,
37194 + W83781D_REG_SCFG2);
37195 + w83627hf_write_value(client,
37196 + W83781D_REG_SCFG2,
37197 + tmp & ~BIT_SCFG2[nr -
37199 + data->sens[nr - 1] = results[0];
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 -
37208 + data->sens[nr - 1] = results[0];
37212 + (KERN_ERR "w83627hf.o: Invalid sensor type %ld; must be 1, 2, or %d\n",
37213 + results[0], W83781D_DEFAULT_BETA);
37220 +static int __init sm_w83627hf_init(void)
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");
37229 + normal_isa[0] = addr;
37231 + return i2c_add_driver(&w83627hf_driver);
37234 +static void __exit sm_w83627hf_exit(void)
37236 + i2c_del_driver(&w83627hf_driver);
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");
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
37253 + w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
37255 + Copyright (c) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>,
37256 + Philip Edelbrock <phil@netroedge.com>,
37257 + and Mark Studebaker <mdsxyz123@yahoo.com>
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.
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.
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.
37275 + Supports following chips:
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
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>
37301 +/* RT Table support #defined so we can take it out if it gets bothersome */
37302 +#define W83781D_RT 1
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 };
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}");
37315 +static int init = 1;
37316 +MODULE_PARM(init, "i");
37317 +MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
37319 +/* Constants specified below */
37321 +/* Length of ISA address segment */
37322 +#define W83781D_EXTENT 8
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
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))
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))
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))
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
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
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 */
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 */
37374 +#define W83781D_REG_VID_FANDIV 0x47
37376 +#define W83781D_REG_CHIPID 0x49
37377 +#define W83781D_REG_WCHIPID 0x58
37378 +#define W83781D_REG_CHIPMAN 0x4F
37379 +#define W83781D_REG_PIN 0x4B
37381 +/* 782D/783S only */
37382 +#define W83781D_REG_VBAT 0x5D
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
37394 +#define W83791D_REG_PWM1 0x81
37395 +#define W83791D_REG_PWM2 0x83
37396 +#define W83791D_REG_PWM3 0x94
37398 +#define W83627HF_REG_PWM1 0x01
37399 +#define W83627HF_REG_PWM2 0x03
37400 +#define W83627HF_REG_PWMCLK1 0x00
37401 +#define W83627HF_REG_PWMCLK2 0x02
37403 +static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2,
37404 + W83781D_REG_PWM3, W83781D_REG_PWM4
37407 +static const u8 regpwm_w83791d[] = { W83791D_REG_PWM1, W83791D_REG_PWM2,
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])
37417 +#define W83781D_REG_I2C_ADDR 0x48
37418 +#define W83781D_REG_I2C_SUBADDR 0x4A
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
37429 +/* RT Table registers */
37430 +#define W83781D_REG_RT_IDX 0x50
37431 +#define W83781D_REG_RT_VAL 0x51
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)
37440 +static inline u8 FAN_TO_REG(long rpm, int div)
37444 + rpm = SENSORS_LIMIT(rpm, 1, 1000000);
37445 + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
37449 +#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
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)
37455 +#define AS99127_TEMP_ADD_TO_REG(val) (SENSORS_LIMIT((((((val) + 2)*4)/10) \
37457 +#define AS99127_TEMP_ADD_FROM_REG(val) ((((val) >> 7) * 10) / 4)
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)
37465 +#define BEEP_ENABLE_TO_REG(val) ((val)?1:0)
37466 +#define BEEP_ENABLE_FROM_REG(val) ((val)?1:0)
37468 +#define DIV_FROM_REG(val) (1 << (val))
37470 +static inline u8 DIV_TO_REG(long val, enum chips type)
37473 + val = SENSORS_LIMIT(val, 1,
37474 + ((type == w83781d || type == as99127f) ? 8 : 128)) >> 1;
37475 + for (i = 0; i < 6; i++) {
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
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
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
37502 +struct w83781d_data {
37503 + struct i2c_client client;
37504 + struct semaphore lock;
37508 + struct semaphore update_lock;
37509 + char valid; /* !=0 if following fields are valid */
37510 + unsigned long last_updated; /* In jiffies */
37512 + struct i2c_client *lm75; /* for secondary I2C addresses */
37513 + /* pointer to array of 2 subclients */
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 */
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.
37537 + Other Betas unimplemented */
37539 + u8 rt[3][32]; /* Register value */
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);
37550 +static int w83781d_read_value(struct i2c_client *client, u16 register);
37551 +static int w83781d_write_value(struct i2c_client *client, u16 register,
37553 +static void w83781d_update_client(struct i2c_client *client);
37554 +static void w83781d_init_client(struct i2c_client *client);
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);
37580 +static void w83781d_rt(struct i2c_client *client, int operation,
37581 + int ctl_name, int *nrels_mag, long *results);
37584 +static int w83781d_id = 0;
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,
37595 +/* The /proc/sys entries */
37596 +/* -- SENSORS SYSCTL START -- */
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
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 */
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
37651 +/* -- SENSORS SYSCTL END -- */
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. */
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},
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},
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},
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},
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},
37862 +/* w83791D has 10 voltages 5 fans and 3 temps. 2 of the temps are on other
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},
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},
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},
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)
38018 + return i2c_detect(adapter, &addr_data, w83781d_detect);
38021 +static int w83781d_detect(struct i2c_adapter *adapter, int address,
38022 + unsigned short flags, int kind)
38024 + int i, val1 = 0, val2, id;
38025 + struct i2c_client *new_client;
38026 + struct w83781d_data *data;
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;
38034 + && !i2c_check_functionality(adapter,
38035 + I2C_FUNC_SMBUS_BYTE_DATA)) goto
38039 + if (!request_region(address, W83781D_EXTENT, "w83781d"))
38041 + release_region(address, W83781D_EXTENT);
38044 + /* Probe whether there is anything available on this address. Already
38045 + done for SMBus clients */
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)
38055 + if (inb_p(address + 3) != i)
38057 + if (inb_p(address + 7) != i)
38059 +#undef REALLY_SLOW_IO
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);
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. */
38075 + if (!(data = kmalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
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;
38088 + /* Now, we do the remaining detection. */
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
38095 + if (w83781d_read_value(new_client, W83781D_REG_CONFIG) &
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)))) {
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) {
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) |
38128 + /* Determine the chip type. */
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)
38141 + w83781d_read_value(new_client, W83781D_REG_WCHIPID);
38142 + if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
38144 + else if (val1 == 0x30 && vendid == winbond)
38146 + else if (val1 == 0x40 && vendid == winbond && !is_isa && address == 0x2d)
38148 + else if (val1 == 0x21 && vendid == winbond)
38150 + else if (val1 == 0x71 && vendid == winbond && address >= 0x2c)
38152 + else if (val1 == 0x31 && !is_isa && address >= 0x28)
38154 + else if (val1 == 0x60 && vendid == winbond && is_isa)
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);
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";
38190 + printk(KERN_ERR "w83781d.o: Internal error: unknown kind (%d)?!?",
38197 + /* Reserve the ISA region */
38199 + request_region(address, W83781D_EXTENT, type_name);
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;
38205 + new_client->id = w83781d_id++;
38207 + init_MUTEX(&data->update_lock);
38209 + /* Tell the I2C layer a new client has arrived */
38210 + if ((err = i2c_attach_client(new_client)))
38213 + /* attach secondary i2c lm75-like clients */
38215 + if (!(data->lm75 = kmalloc(2 * sizeof(struct i2c_client),
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]);
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];
38237 + val1 = w83781d_read_value(new_client,
38238 + W83781D_REG_I2C_SUBADDR);
38239 + data->lm75[0].addr = 0x48 + (val1 & 0x07);
38241 + if (kind != w83783s) {
38242 + if(force_subclients[0] == id &&
38243 + force_subclients[1] == address) {
38244 + data->lm75[1].addr = force_subclients[3];
38246 + data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07);
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);
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";
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);
38283 + if (kind == w83783s)
38287 + data->lm75 = NULL;
38290 + /* Register a new directory entry with module sensors */
38291 + if ((i = i2c_register_entry(new_client,
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) {
38309 + data->sysctl_id = i;
38311 + /* Only PWM2 can be disabled */
38312 + for(i = 0; i < 4; i++)
38313 + data->pwmenable[i] = 1;
38315 + /* Initialize the chip */
38316 + w83781d_init_client(new_client);
38319 +/* OK, this is not exactly good programming practice, usually. But it is
38320 + very code-efficient in this case. */
38324 + i2c_detach_client(&
38326 + w83781d_data *) (new_client->data))->
38330 + i2c_detach_client(&
38332 + w83781d_data *) (new_client->data))->
38336 + kfree(((struct w83781d_data *) (new_client->data))->lm75);
38338 + i2c_detach_client(new_client);
38341 + release_region(address, W83781D_EXTENT);
38348 +static int w83781d_detach_client(struct i2c_client *client)
38351 + struct w83781d_data *data = client->data;
38353 + i2c_deregister_entry(data->sysctl_id);
38355 + if ((err = i2c_detach_client(client))) {
38357 + (KERN_ERR "w83781d.o: Client deregistration failed, client not detached.\n");
38361 + if(i2c_is_isa_client(client)) {
38362 + release_region(client->addr, W83781D_EXTENT);
38364 + i2c_detach_client(&(data->lm75[0]));
38365 + if (data->type != w83783s)
38366 + i2c_detach_client(&(data->lm75[1]));
38367 + kfree(data->lm75);
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)
38382 + int res, word_sized, bank;
38383 + struct i2c_client *cl;
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);
38396 + client->addr + W83781D_DATA_REG_OFFSET);
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);
38404 + (res << 8) + inb_p(client->addr +
38405 + W83781D_DATA_REG_OFFSET);
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);
38413 + bank = (reg >> 8) & 0x0f;
38415 + /* switch banks */
38416 + i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38418 + if (bank == 0 || bank > 2) {
38419 + res = i2c_smbus_read_byte_data(client, reg & 0xff);
38421 + /* switch to subclient */
38423 + &(((struct w83781d_data *) (client->data))->
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));
38430 + case 0x52: /* CONFIG */
38431 + res = i2c_smbus_read_byte_data(cl, 1);
38433 + case 0x53: /* HYST */
38434 + res = swab16(i2c_smbus_read_word_data(cl, 2));
38436 + case 0x55: /* OVER */
38438 + res = swab16(i2c_smbus_read_word_data(cl, 3));
38443 + i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38446 + up(&(((struct w83781d_data *) (client->data))->lock));
38450 +static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
38452 + int word_sized, bank;
38453 + struct i2c_client *cl;
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);
38465 + client->addr + W83781D_DATA_REG_OFFSET);
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);
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);
38482 + bank = (reg >> 8) & 0x0f;
38484 + /* switch banks */
38485 + i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38487 + if (bank == 0 || bank > 2) {
38488 + i2c_smbus_write_byte_data(client, reg & 0xff,
38491 + /* switch to subclient */
38492 + cl = &(((struct w83781d_data *) (client->data))->
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);
38499 + case 0x53: /* HYST */
38500 + i2c_smbus_write_word_data(cl, 2, swab16(value));
38502 + case 0x55: /* OVER */
38503 + i2c_smbus_write_word_data(cl, 3, swab16(value));
38508 + i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
38511 + up(&(((struct w83781d_data *) (client->data))->lock));
38515 +/* Called when we have found a new W83781D. It should set limits, etc. */
38516 +static void w83781d_init_client(struct i2c_client *client)
38518 + struct w83781d_data *data = client->data;
38520 + int type = data->type;
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);
38541 + data->vrm = (type == w83791d) ? 90 : 82;
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;
38549 + if (w83781d_read_value
38551 + W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
38552 + data->sens[i - 1] = 1;
38554 + data->sens[i - 1] = 2;
38556 + if ((type == w83783s || type == w83697hf) && (i == 2))
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....
38569 + if (init && type == w83781d) {
38572 + Auto-indexing doesn't seem to work...
38573 + w83781d_write_value(client,W83781D_REG_RT_IDX,0);
38575 + for (i = 0; i < 3; i++) {
38577 + for (j = 0; j < 32; j++) {
38578 + w83781d_write_value(client,
38579 + W83781D_REG_RT_IDX,
38582 + w83781d_read_value(client,
38583 + W83781D_REG_RT_VAL);
38587 +#endif /* W83781D_RT */
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,
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);
38600 + w83781d_write_value(client, W83781D_REG_IRQ,
38605 + /* Start monitoring */
38606 + w83781d_write_value(client, W83781D_REG_CONFIG,
38607 + (w83781d_read_value(client,
38608 + W83781D_REG_CONFIG) & 0xf7)
38612 +static void w83781d_update_client(struct i2c_client *client)
38614 + struct w83781d_data *data = client->data;
38617 + down(&data->update_lock);
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");
38623 + for (i = 0; i <= 9; i++) {
38624 + if ((data->type == w83783s || data->type == w83697hf)
38626 + continue; /* 783S has no in1 */
38627 + if (data->type == w83791d) {
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));
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));
38646 + if ((data->type != w83782d) && (data->type != w83697hf)
38647 + && (data->type != w83627hf) && (i == 6)
38648 + && (data->type != w83791d))
38651 + if (data->type != w83791d && i == 8)
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;
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)))
38675 + /* Only PWM2 can be disabled */
38676 + data->pwmenable[1] = (w83781d_read_value(client,
38677 + W83781D_REG_PWMCLK12) & 0x08) >> 3;
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);
38699 + i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
38700 + if (data->type != w83697hf) {
38701 + data->vid = i & 0x0f;
38703 + (w83781d_read_value(client, W83781D_REG_CHIPID) & 0x01)
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;
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;
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)) {
38726 + w83781d_read_value(client,
38727 + W83781D_REG_ALARM3) << 16;
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)) {
38736 + w83781d_read_value(client,
38737 + W83781D_REG_BEEP_INTS3) << 16;
38739 + data->last_updated = jiffies;
38743 + up(&data->update_lock);
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)
38763 + struct w83781d_data *data = client->data;
38764 + int nr = ctl_name - W83781D_SYSCTL_IN0;
38766 + if (operation == SENSORS_PROC_REAL_INFO)
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]);
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]);
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]);
38788 +void w83781d_fan(struct i2c_client *client, int operation, int ctl_name,
38789 + int *nrels_mag, long *results)
38791 + struct w83781d_data *data = client->data;
38792 + int nr = ctl_name - W83781D_SYSCTL_FAN1 + 1;
38794 + if (operation == SENSORS_PROC_REAL_INFO)
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]));
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]);
38815 +void w83781d_temp(struct i2c_client *client, int operation, int ctl_name,
38816 + int *nrels_mag, long *results)
38818 + struct w83781d_data *data = client->data;
38819 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
38841 +void w83781d_temp_add(struct i2c_client *client, int operation,
38842 + int ctl_name, int *nrels_mag, long *results)
38844 + struct w83781d_data *data = client->data;
38845 + int nr = ctl_name - W83781D_SYSCTL_TEMP2;
38847 + if (operation == SENSORS_PROC_REAL_INFO)
38849 + else if (operation == SENSORS_PROC_REAL_READ) {
38850 + w83781d_update_client(client);
38851 + if (data->type == as99127f) {
38853 + AS99127_TEMP_ADD_FROM_REG(data->
38854 + temp_add_over[nr]);
38856 + AS99127_TEMP_ADD_FROM_REG(data->
38857 + temp_add_hyst[nr]);
38859 + AS99127_TEMP_ADD_FROM_REG(data->temp_add[nr]);
38862 + LM75_TEMP_FROM_REG(data->temp_add_over[nr]);
38864 + LM75_TEMP_FROM_REG(data->temp_add_hyst[nr]);
38865 + results[2] = LM75_TEMP_FROM_REG(data->temp_add[nr]);
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]);
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]);
38881 + if (*nrels_mag >= 2) {
38882 + if (data->type == as99127f)
38883 + data->temp_add_hyst[nr] =
38884 + AS99127_TEMP_ADD_TO_REG(results[1]);
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]);
38897 +void w83781d_vid(struct i2c_client *client, int operation, int ctl_name,
38898 + int *nrels_mag, long *results)
38900 + struct w83781d_data *data = client->data;
38901 + if (operation == SENSORS_PROC_REAL_INFO)
38903 + else if (operation == SENSORS_PROC_REAL_READ) {
38904 + w83781d_update_client(client);
38905 + results[0] = vid_from_reg(data->vid, data->vrm);
38910 +void w83781d_vrm(struct i2c_client *client, int operation, int ctl_name,
38911 + int *nrels_mag, long *results)
38913 + struct w83781d_data *data = client->data;
38914 + if (operation == SENSORS_PROC_REAL_INFO)
38916 + else if (operation == SENSORS_PROC_REAL_READ) {
38917 + results[0] = data->vrm;
38919 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
38920 + if (*nrels_mag >= 1)
38921 + data->vrm = results[0];
38925 +void w83781d_alarms(struct i2c_client *client, int operation, int ctl_name,
38926 + int *nrels_mag, long *results)
38928 + struct w83781d_data *data = client->data;
38929 + if (operation == SENSORS_PROC_REAL_INFO)
38931 + else if (operation == SENSORS_PROC_REAL_READ) {
38932 + w83781d_update_client(client);
38933 + results[0] = ALARMS_FROM_REG(data->alarms);
38938 +void w83781d_beep(struct i2c_client *client, int operation, int ctl_name,
38939 + int *nrels_mag, long *results)
38941 + struct w83781d_data *data = client->data;
38944 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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) &
38963 + val = (data->beeps >> 8) & 0x7f;
38964 + } else if (*nrels_mag >= 1)
38966 + w83781d_read_value(client,
38967 + W83781D_REG_BEEP_INTS2) &
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);
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)
38981 + struct w83781d_data *data = client->data;
38982 + int old, old2, old3 = 0;
38984 + if (operation == SENSORS_PROC_REAL_INFO)
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) {
38993 + results[2] = DIV_FROM_REG(data->fan_div[2]);
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) {
39001 + w83781d_read_value(client, W83781D_REG_VBAT);
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);
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)) {
39014 + ((data->fan_div[2] & 0x04) << 5);
39017 + if (*nrels_mag >= 2) {
39018 + data->fan_div[1] =
39019 + DIV_TO_REG(results[1], data->type);
39021 + (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
39022 + if ((data->type != w83781d) &&
39023 + (data->type != as99127f)) {
39026 + ((data->fan_div[1] & 0x04) << 4);
39029 + if (*nrels_mag >= 1) {
39030 + data->fan_div[0] =
39031 + DIV_TO_REG(results[0], data->type);
39033 + (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
39034 + w83781d_write_value(client, W83781D_REG_VID_FANDIV,
39036 + if ((data->type != w83781d) &&
39037 + (data->type != as99127f)) {
39040 + ((data->fan_div[0] & 0x04) << 3);
39041 + w83781d_write_value(client,
39042 + W83781D_REG_VBAT,
39049 +void w83781d_pwm(struct i2c_client *client, int operation, int ctl_name,
39050 + int *nrels_mag, long *results)
39052 + struct w83781d_data *data = client->data;
39053 + int nr = 1 + ctl_name - W83781D_SYSCTL_PWM1;
39056 + if (operation == SENSORS_PROC_REAL_INFO)
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];
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]);
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);
39076 + w83781d_write_value(client,
39077 + W83781D_REG_PWMCLK12, j | 0x08);
39079 + w83781d_write_value(client,
39080 + W83781D_REG_BEEP_CONFIG, k & 0xef);
39081 + data->pwmenable[1] = 1;
39084 + w83781d_write_value(client,
39085 + W83781D_REG_PWMCLK12, j & 0xf7);
39087 + w83781d_write_value(client,
39088 + W83781D_REG_BEEP_CONFIG, j | 0x10);
39089 + data->pwmenable[1] = 0;
39095 +void w83781d_sens(struct i2c_client *client, int operation, int ctl_name,
39096 + int *nrels_mag, long *results)
39098 + struct w83781d_data *data = client->data;
39099 + int nr = 1 + ctl_name - W83781D_SYSCTL_SENS1;
39102 + if (operation == SENSORS_PROC_REAL_INFO)
39104 + else if (operation == SENSORS_PROC_REAL_READ) {
39105 + results[0] = data->sens[nr - 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 -
39117 + tmp = w83781d_read_value(client,
39118 + W83781D_REG_SCFG2);
39119 + w83781d_write_value(client,
39120 + W83781D_REG_SCFG2,
39121 + tmp | BIT_SCFG2[nr -
39123 + data->sens[nr - 1] = results[0];
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 -
39132 + tmp = w83781d_read_value(client,
39133 + W83781D_REG_SCFG2);
39134 + w83781d_write_value(client,
39135 + W83781D_REG_SCFG2,
39136 + tmp & ~BIT_SCFG2[nr -
39138 + data->sens[nr - 1] = results[0];
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 -
39147 + data->sens[nr - 1] = results[0];
39151 + (KERN_ERR "w83781d.o: Invalid sensor type %ld; must be 1, 2, or %d\n",
39152 + results[0], W83781D_DEFAULT_BETA);
39160 +static void w83781d_rt(struct i2c_client *client, int operation, int ctl_name,
39161 + int *nrels_mag, long *results)
39163 + struct w83781d_data *data = client->data;
39164 + int nr = 1 + ctl_name - W83781D_SYSCTL_RT1;
39167 + if (operation == SENSORS_PROC_REAL_INFO)
39169 + else if (operation == SENSORS_PROC_REAL_READ) {
39170 + for (i = 0; i < 32; i++) {
39171 + results[i] = data->rt[nr - 1][i];
39174 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
39175 + if (*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]);
39188 +static int __init sm_w83781d_init(void)
39190 + printk(KERN_INFO "w83781d.o version %s (%s)\n", LM_VERSION, LM_DATE);
39191 + return i2c_add_driver(&w83781d_driver);
39194 +static void __exit sm_w83781d_exit(void)
39196 + i2c_del_driver(&w83781d_driver);
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");
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
39213 + * w83l785ts.c - Part of lm_sensors, Linux kernel modules for hardware
39215 + * Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
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
39223 + * Thanks to James Bolt <james@evilpenguin.com> for benchmarking the read
39224 + * error handling mechanism.
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.
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.
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.
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"
39250 +#ifndef I2C_DRIVERID_W83L785TS
39251 +#define I2C_DRIVERID_W83L785TS 1047
39254 +/* How many retries on register read error */
39255 +#define MAX_RETRIES 5
39258 + * Address to scan
39259 + * Address is fully defined internally and cannot be changed.
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 };
39268 + * Insmod parameters
39271 +SENSORS_INSMOD_1(w83l785ts);
39274 + * The W83L785TS-S registers
39275 + * Manufacturer ID is 0x5CA3 for Winbond.
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 */
39288 + * The W83L785TS-S uses signed 8-bit values.
39291 +#define TEMP_FROM_REG(val) (val & 0x80 ? val-0x100 : val)
39294 + * Functions declaration
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);
39307 + * Driver data (common to all clients)
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,
39320 + * Client data (each client gets its own)
39323 +struct w83l785ts_data {
39324 + struct i2c_client client;
39327 + struct semaphore update_lock;
39328 + char valid; /* zero until following fields are valid */
39329 + unsigned long last_updated; /* in jiffies */
39331 + /* registers values */
39332 + u8 temp, temp_over;
39337 + * These files are created for each detected W83L785TS-S.
39340 +/* -- SENSORS SYSCTL START -- */
39342 +#define W83L785TS_SYSCTL_TEMP 1200
39344 +/* -- SENSORS SYSCTL END -- */
39347 +static ctl_table w83l785ts_dir_table_template[] =
39349 + {W83L785TS_SYSCTL_TEMP, "temp", NULL, 0, 0444, NULL,
39350 + &i2c_proc_real, &i2c_sysctl_real, NULL, &w83l785ts_temp},
39355 + * Internal variables
39358 +static int w83l785ts_id = 0;
39364 +static int w83l785ts_attach_adapter(struct i2c_adapter *adapter)
39366 + return i2c_detect(adapter, &addr_data, w83l785ts_detect);
39370 + * The following function does more than just detection. If detection
39371 + * succeeds, it also registers the new chip.
39373 +static int w83l785ts_detect(struct i2c_adapter *adapter, int address,
39374 + unsigned short flags, int kind)
39376 + struct i2c_client *new_client;
39377 + struct w83l785ts_data *data;
39379 + const char *type_name = "";
39380 + const char *client_name = "";
39382 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
39384 + printk(KERN_DEBUG "w83l785ts.o: I2C bus doesn't support "
39385 + "byte read mode, skipping.\n");
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");
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.
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;
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
39421 + if (kind < 0) { /* detection */
39422 + if (((w83l785ts_read_value(new_client, W83L785TS_REG_CONFIG, 0)
39424 + || ((w83l785ts_read_value(new_client, W83L785TS_REG_TYPE, 0)
39425 + & 0xFC) != 0x00)) {
39427 + printk(KERN_DEBUG "w83l785ts.o: Detection failed at "
39428 + "0x%02x.\n", address);
39434 + if (kind <= 0) { /* identification */
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;
39447 + if (kind <= 0) { /* identification failed */
39448 + printk(KERN_INFO "w83l785ts.o: Unsupported chip.\n");
39452 + if (kind == w83l785ts) {
39453 + type_name = "w83l785ts";
39454 + client_name = "W83L785TS-S chip";
39456 + printk(KERN_ERR "w83l785ts.o: Unknown kind %d.\n", kind);
39461 + * OK, we got a valid chip so we can fill in the remaining client
39465 + strcpy(new_client->name, client_name);
39466 + new_client->id = w83l785ts_id++;
39468 + init_MUTEX(&data->update_lock);
39471 + * Tell the I2C layer a new client has arrived.
39474 + if ((err = i2c_attach_client(new_client))) {
39476 + printk(KERN_ERR "w83l785ts.o: Failed attaching client.\n");
39482 + * Register a new directory entry.
39485 + if ((err = i2c_register_entry(new_client, type_name,
39486 + w83l785ts_dir_table_template)) < 0) {
39488 + printk(KERN_ERR "w83l785ts.o: Failed registering directory "
39493 + data->sysctl_id = err;
39496 + * Initialize the W83L785TS chip
39497 + * Nothing yet, assume it is already started.
39503 + i2c_detach_client(new_client);
39509 +static int w83l785ts_detach_client(struct i2c_client *client)
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");
39520 + kfree(client->data);
39524 +static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval)
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);
39535 + printk(KERN_WARNING "w83l785ts.o: Read failed, will retry "
39540 + printk(KERN_ERR "w83l785ts.o: Couldn't read value from register. "
39541 + "Please report.\n");
39545 +static void w83l785ts_update_client(struct i2c_client *client)
39547 + struct w83l785ts_data *data = client->data;
39549 + down(&data->update_lock);
39551 + if ((jiffies - data->last_updated > HZ * 2)
39552 + || (jiffies < data->last_updated)
39553 + || !data->valid) {
39555 + printk(KERN_DEBUG "w83l785ts.o: Updating data.\n");
39557 + data->temp = w83l785ts_read_value(client, W83L785TS_REG_TEMP,
39559 + data->temp_over = w83l785ts_read_value(client,
39560 + W83L785TS_REG_TEMP_OVER, data->temp_over);
39561 + data->last_updated = jiffies;
39565 + up(&data->update_lock);
39568 +static void w83l785ts_temp(struct i2c_client *client, int operation,
39569 + int ctl_name, int *nrels_mag, long *results)
39571 + struct w83l785ts_data *data = client->data;
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);
39583 +static int __init sm_w83l785ts_init(void)
39585 + printk(KERN_INFO "w83l785ts.o version %s (%s)\n", LM_VERSION, LM_DATE);
39586 + return i2c_add_driver(&w83l785ts_driver);
39589 +static void __exit sm_w83l785ts_exit(void)
39591 + i2c_del_driver(&w83l785ts_driver);
39594 +MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
39595 +MODULE_DESCRIPTION("W83L785TS-S sensor driver");
39596 +MODULE_LICENSE("GPL");
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
39604 + xeontemp.c - Part of lm_sensors, Linux kernel modules for hardware
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>
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.
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.
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.
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. */
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"
39636 +#ifndef I2C_DRIVERID_XEONTEMP
39637 +#define I2C_DRIVERID_XEONTEMP 1045
39640 +/* Addresses to scan */
39641 +static unsigned short normal_i2c[] = { 0x18, 0x1a, 0x29, 0x2b,
39642 + 0x4c, 0x4e, SENSORS_I2C_END
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 };
39648 +/* Insmod parameters */
39649 +SENSORS_INSMOD_1(xeontemp);
39651 +/* xeontemp constants specified below */
39653 +/* The registers */
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
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
39668 +#define XEONTEMP_REG_ONESHOT 0x0F
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
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))
39682 +/* Each client has this additional data */
39683 +struct xeontemp_data {
39684 + struct i2c_client client;
39688 + struct semaphore update_lock;
39689 + char valid; /* !=0 if following fields are valid */
39690 + unsigned long last_updated; /* In jiffies */
39692 + u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms;
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,
39705 +static void xeontemp_remote_temp(struct i2c_client *client, int operation,
39706 + int ctl_name, int *nrels_mag,
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);
39712 +/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
39713 +static int read_only = 0;
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,
39726 +/* -- SENSORS SYSCTL START -- */
39728 +#define XEONTEMP_SYSCTL_REMOTE_TEMP 1201
39729 +#define XEONTEMP_SYSCTL_ALARMS 1203
39731 +#define XEONTEMP_ALARM_RTEMP_HIGH 0x10
39732 +#define XEONTEMP_ALARM_RTEMP_LOW 0x08
39733 +#define XEONTEMP_ALARM_RTEMP_NA 0x04
39735 +/* -- SENSORS SYSCTL END -- */
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},
39750 +static int xeontemp_id = 0;
39752 +static int xeontemp_attach_adapter(struct i2c_adapter *adapter)
39754 + return i2c_detect(adapter, &addr_data, xeontemp_detect);
39757 +static int xeontemp_detect(struct i2c_adapter *adapter, int address,
39758 + unsigned short flags, int kind)
39761 + struct i2c_client *new_client;
39762 + struct xeontemp_data *data;
39764 + const char *type_name = "";
39765 + const char *client_name = "";
39767 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
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. */
39774 + if (!(data = kmalloc(sizeof(struct xeontemp_data), GFP_KERNEL))) {
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;
39786 + /* Now, we do the remaining detection. */
39790 + (xeontemp_read_value(new_client, XEONTEMP_REG_STATUS) &
39795 + /* Determine the chip type. */
39801 + type_name = "xeontemp";
39802 + client_name = "xeon sensors";
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;
39808 + new_client->id = xeontemp_id++;
39810 + init_MUTEX(&data->update_lock);
39812 + /* Tell the I2C layer a new client has arrived */
39813 + if ((err = i2c_attach_client(new_client)))
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) {
39822 + data->sysctl_id = i;
39824 + xeontemp_init_client(new_client);
39828 + i2c_detach_client(new_client);
39836 +static void xeontemp_init_client(struct i2c_client *client)
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);
39844 +static int xeontemp_detach_client(struct i2c_client *client)
39849 + i2c_deregister_entry(((struct xeontemp_data *) (client->data))->
39852 + if ((err = i2c_detach_client(client))) {
39854 + ("xeontemp.o: Client deregistration failed, client not detached.\n");
39858 + kfree(client->data);
39865 +/* All registers are byte-sized */
39866 +static int xeontemp_read_value(struct i2c_client *client, u8 reg)
39868 + return i2c_smbus_read_byte_data(client, reg);
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)
39875 + struct xeontemp_data *data = client->data;
39877 + i = i2c_smbus_read_byte_data(client, reg);
39879 + data->fail |= mask;
39886 +static int xeontemp_write_value(struct i2c_client *client, u8 reg, u16 value)
39888 + if (read_only > 0)
39891 + return i2c_smbus_write_byte_data(client, reg, value);
39894 +static void xeontemp_update_client(struct i2c_client *client)
39896 + struct xeontemp_data *data = client->data;
39898 + down(&data->update_lock);
39900 + if ((jiffies - data->last_updated > HZ + HZ / 2) ||
39901 + (jiffies < data->last_updated) || !data->valid) {
39904 + printk("Starting xeontemp update\n");
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;
39923 + up(&data->update_lock);
39926 +void xeontemp_remote_temp(struct i2c_client *client, int operation,
39927 + int ctl_name, int *nrels_mag, long *results)
39929 + struct xeontemp_data *data = client->data;
39931 + if (operation == SENSORS_PROC_REAL_INFO)
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);
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);
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);
39955 +void xeontemp_alarms(struct i2c_client *client, int operation, int ctl_name,
39956 + int *nrels_mag, long *results)
39958 + struct xeontemp_data *data = client->data;
39959 + if (operation == SENSORS_PROC_REAL_INFO)
39961 + else if (operation == SENSORS_PROC_REAL_READ) {
39962 + xeontemp_update_client(client);
39963 + results[0] = data->alarms | data->fail;
39965 + } else if (operation == SENSORS_PROC_REAL_WRITE) {
39966 + /* Can't write to it */
39970 +static int __init sm_xeontemp_init(void)
39972 + printk(KERN_INFO "xeontemp.o version %s (%s)\n", LM_VERSION, LM_DATE);
39973 + return i2c_add_driver(&xeontemp_driver);
39976 +static void __exit sm_xeontemp_exit(void)
39978 + i2c_del_driver(&xeontemp_driver);
39982 + ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
39983 +MODULE_DESCRIPTION("xeontemp driver");
39984 +MODULE_LICENSE("GPL");
39986 +MODULE_PARM(read_only, "i");
39987 +MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
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
39995 + * Stolen from kernel 2.5.69
39996 + * device.h - generic, centralized driver model
39997 + * To make it easier to backport from 2.5
39999 + * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
40003 +#ifndef _SENSORS_COMPAT_H_
40004 +#define _SENSORS_COMPAT_H_
40006 +/* debugging and troubleshooting/diagnostic helpers. */
40007 +#define dev_printk(level, dev, format, arg...) \
40008 + printk(level "%s: " format , (dev)->name , ## arg)
40011 +#define dev_dbg(dev, format, arg...) \
40012 + dev_printk(KERN_DEBUG , dev , format , ## arg)
40014 +#define dev_dbg(dev, format, arg...) do {} while (0)
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)
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
40029 + sensors_vid.h - Part of lm_sensors, Linux kernel modules for hardware
40031 + Copyright (c) 2002-2004 Mark D. Studebaker <mdsxyz123@yahoo.com>
40032 + With assistance from Trent Piepho <xyzzy@speakeasy.org>
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.
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.
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.
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
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
40065 + Opteron VID encoding is:
40071 + 11111 = 0.000 V (off)
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.
40081 +#define DEFAULT_VRM 82
40083 +static inline int vid_from_reg(int val, int vrm)
40089 + case 100: /* VRD 10.0 */
40090 + if((val & 0x1f) == 0x1f)
40092 + if((val & 0x1f) <= 0x09 || val == 0x0a)
40093 + vid = 10875 - (val & 0x1f) * 250;
40095 + vid = 18625 - (val & 0x1f) * 250;
40098 + vid /= 10; /* only return 3 dec. places for now */
40101 + case 24: /* Opteron processor */
40102 + return(val == 0x1f ? 0 : 1550 - val * 25);
40104 + case 91: /* VRM 9.1 */
40105 + case 90: /* VRM 9.0 */
40106 + return(val == 0x1f ? 0 :
40107 + 1850 - val * 25);
40109 + case 85: /* VRM 8.5 */
40110 + return((val & 0x10 ? 25 : 0) +
40111 + ((val & 0x0f) > 0x04 ? 2050 : 1250) -
40112 + ((val & 0x0f) * 50));
40114 + case 84: /* VRM 8.4 */
40116 + /* fall through */
40117 + default: /* VRM 8.2 */
40118 + return(val == 0x1f ? 0 :
40119 + val & 0x10 ? 5100 - (val) * 100 :
40120 + 2050 - (val) * 50);
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
40127 +# Sensor device configuration
40128 +# All depend on CONFIG_I2C_PROC.
40129 +# ISA-only devices depend on CONFIG_I2C_ISA also.
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'
40137 + dep_mbool 'Hardware sensors support' CONFIG_SENSORS $CONFIG_I2C $CONFIG_I2C_PROC
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
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
40194 +DRIVERS-$(CONFIG_SENSORS) += drivers/sensors/sensor.o
40195 DRIVERS := $(DRIVERS-y)
40198 --- linux-old/drivers/Makefile Mon Nov 17 01:07:35 2003
40199 +++ linux/drivers/Makefile Mon Dec 13 20:18:54 2004
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
40207 subdir-y := parport char block net sound misc media cdrom hotplug
40208 subdir-m := $(subdir-y)
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
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
40221 +# Makefile for the kernel hardware sensors drivers.
40224 +MOD_LIST_NAME := SENSORS_MODULES
40225 +O_TARGET := sensor.o
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
40267 +include $(TOPDIR)/Rules.make
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 @@
40273 source drivers/i2c/Config.in
40275 +source drivers/sensors/Config.in
40277 mainmenu_option next_comment
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
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
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
40310 # This is needed for automatic patch generation: sensors code ends here
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
40316 obj-$(CONFIG_I2C_ALGO_AU1550) += i2c-algo-au1550.o i2c-au1550.o
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
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 @@
40344 # adaptive-fill:nil
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
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
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.
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
40370 +AMD 756/766/768/8111
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
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
40384 +Apple Hydra Mac I/O
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.
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
40398 +Intel I810/I815 based Mainboard
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
40407 +Intel 82371AB PIIX4(E) / ServerWorks OSB4 and CSB5
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
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
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
40431 +Silicon Integrated Systems Corp. SiS630/730 based Mainboard
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.
40437 +Silicon Integrated Systems Corp. SiS645/961,645DX/961,735 based Mainboard
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.
40443 +VIA Technologies, Inc. VT82C586B
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.
40450 +VIA Technologies, Inc. VT82C596, 596B, 686A/B, 8233, 8235
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.
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.
40464 + built as a module which can be inserted and removed while the kernel
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.
40474 +Pseudo ISA adapter (for hardware sensors modules)
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.
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
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.
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
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.
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
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.
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
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.
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
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
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
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.
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/
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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/
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.
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
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.
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
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.
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
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.
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
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
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
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.
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
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.
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/
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.
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
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.
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
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.
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/
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.
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
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
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/
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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/
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.
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/
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
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
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
40877 +P: Frodo Looijaard
40879 +P: Philip Edelbrock
40880 +M: phil@netroedge.com
40881 +L: sensors@stimpy.netroedge.com
40882 +W: http://www.lm-sensors.nu/
40885 SGI VISUAL WORKSTATION 320 AND 540
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
40891 #include "pci-i386.h"
40893 unsigned long dmi_broken;
40894 +int is_unsafe_smbus;
40895 int is_sony_vaio_laptop;
40898 @@ -371,6 +372,19 @@
40902 + * Don't access SMBus on IBM systems which get corrupted eeproms
40905 +static __init int disable_smbus(struct dmi_blacklist *d)
40907 + if (is_unsafe_smbus == 0) {
40908 + is_unsafe_smbus = 1;
40909 + printk(KERN_INFO "%s machine detected. Disabling SMBus accesses.\n", d->ident);
40915 * Check for a Sony Vaio system
40917 * On a Sony system we want to enable the use of the sonypi
40918 @@ -675,6 +689,10 @@
40919 NO_MATCH, NO_MATCH,
40922 + { disable_smbus, "IBM", {
40923 + MATCH(DMI_SYS_VENDOR, "IBM"),
40924 + NO_MATCH, NO_MATCH, NO_MATCH
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);
40935 +extern int is_unsafe_smbus;
40936 +EXPORT_SYMBOL(is_unsafe_smbus);
40938 extern int is_sony_vaio_laptop;
40939 EXPORT_SYMBOL(is_sony_vaio_laptop);