root/lm-sensors/trunk/kernel/busses/i2c-piix4.c @ 3024

Revision 3024, 14.4 KB (checked in by khali, 8 years ago)

Strip useless whitespace before new line at end of string.
Backport from a Linux 2.6 patch from Denis Vlasenko.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    piix4.c - Part of lm_sensors, Linux kernel modules for hardware
3              monitoring
4    Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
5    Philip Edelbrock <phil@netroedge.com>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22/*
23   Supports:
24        Intel PIIX4, 440MX
25        Serverworks OSB4, CSB5, CSB6
26        SMSC Victory66
27
28   Note: we assume there can only be one device, with one SMBus interface.
29*/
30
31#include <linux/module.h>
32#include <linux/config.h>
33#include <linux/pci.h>
34#include <linux/kernel.h>
35#include <linux/stddef.h>
36#include <linux/sched.h>
37#include <linux/ioport.h>
38#include <linux/i2c.h>
39#include <linux/init.h>
40#include <linux/apm_bios.h>
41#include <asm/io.h>
42#include "version.h"
43#include "sensors_compat.h"
44
45
46struct sd {
47        const unsigned short mfr;
48        const unsigned short dev;
49        const unsigned char fn;
50        const char *name;
51};
52
53/* PIIX4 SMBus address offsets */
54#define SMBHSTSTS (0 + piix4_smba)
55#define SMBHSLVSTS (1 + piix4_smba)
56#define SMBHSTCNT (2 + piix4_smba)
57#define SMBHSTCMD (3 + piix4_smba)
58#define SMBHSTADD (4 + piix4_smba)
59#define SMBHSTDAT0 (5 + piix4_smba)
60#define SMBHSTDAT1 (6 + piix4_smba)
61#define SMBBLKDAT (7 + piix4_smba)
62#define SMBSLVCNT (8 + piix4_smba)
63#define SMBSHDWCMD (9 + piix4_smba)
64#define SMBSLVEVT (0xA + piix4_smba)
65#define SMBSLVDAT (0xC + piix4_smba)
66
67/* count for request_region */
68#define SMBIOSIZE 8
69
70/* PCI Address Constants */
71#define SMBBA     0x090
72#define SMBHSTCFG 0x0D2
73#define SMBSLVC   0x0D3
74#define SMBSHDW1  0x0D4
75#define SMBSHDW2  0x0D5
76#define SMBREV    0x0D6
77
78/* Other settings */
79#define MAX_TIMEOUT 500
80#define  ENABLE_INT9 0
81
82/* PIIX4 constants */
83#define PIIX4_QUICK      0x00
84#define PIIX4_BYTE       0x04
85#define PIIX4_BYTE_DATA  0x08
86#define PIIX4_WORD_DATA  0x0C
87#define PIIX4_BLOCK_DATA 0x14
88
89/* insmod parameters */
90
91/* If force is set to anything different from 0, we forcibly enable the
92   PIIX4. DANGEROUS! */
93static int force = 0;
94MODULE_PARM(force, "i");
95MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
96
97/* If force_addr is set to anything different from 0, we forcibly enable
98   the PIIX4 at the given address. VERY DANGEROUS! */
99static int force_addr = 0;
100MODULE_PARM(force_addr, "i");
101MODULE_PARM_DESC(force_addr,
102                 "Forcibly enable the PIIX4 at the given address. "
103                 "EXTREMELY DANGEROUS!");
104
105static int fix_hstcfg = 0;
106MODULE_PARM(fix_hstcfg, "i");
107MODULE_PARM_DESC(fix_hstcfg,
108                 "Fix config register. Needed on some boards (Force CPCI735).");
109
110static int piix4_transaction(void);
111
112static unsigned short piix4_smba = 0;
113
114#ifdef CONFIG_X86
115/*
116 * Get DMI information.
117 */
118
119static int __devinit ibm_dmi_probe(void)
120{
121        extern int is_unsafe_smbus;
122        return is_unsafe_smbus;
123}
124#endif
125
126/* Detect whether a PIIX4 can be found, and initialize it, where necessary.
127   Note the differences between kernels with the old PCI BIOS interface and
128   newer kernels with the real PCI interface. In compat.h some things are
129   defined to make the transition easier. */
130static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
131                                const struct pci_device_id *id)
132{
133        unsigned char temp;
134
135        /* match up the function */
136        if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
137                return -ENODEV;
138
139        printk(KERN_INFO "Found %s device\n", PIIX4_dev->name);
140
141#ifdef CONFIG_X86
142        if(ibm_dmi_probe() && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
143                printk(KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module "
144                        "may corrupt your serial eeprom! Refusing to load "
145                        "module!\n");
146                return -EPERM;
147        }
148#endif
149
150        /* Determine the address of the SMBus areas */
151        if (force_addr) {
152                piix4_smba = force_addr & 0xfff0;
153                force = 0;
154        } else {
155                pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
156                piix4_smba &= 0xfff0;
157                if(piix4_smba == 0) {
158                        printk(KERN_ERR "i2c-piix4.o: SMB base address "
159                                "uninitialized - upgrade BIOS or use "
160                                "force_addr=0xaddr\n");
161                        return -ENODEV;
162                }
163        }
164
165        if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) {
166                printk(KERN_ERR "i2c-piix4.o: SMB region 0x%x already in "
167                        "use!\n", piix4_smba);
168                return -ENODEV;
169        }
170
171        pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
172
173        /* Some BIOS will set up the chipset incorrectly and leave a register
174           in an undefined state (causing I2C to act very strangely). */
175        if (temp & 0x02) {
176                if (fix_hstcfg) {
177                        printk(KERN_INFO "i2c-piix4.o: Working around buggy "
178                                "BIOS (I2C)\n");
179                        temp &= 0xfd;
180                        pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp);
181                } else {
182                        printk(KERN_INFO "i2c-piix4.o: Unusual config register "
183                                "value\n");
184                        printk(KERN_INFO "i2c-piix4.o: Try using fix_hstcfg=1 "
185                                "if you experience problems\n");
186                }
187        }
188
189        /* If force_addr is set, we program the new address here. Just to make
190           sure, we disable the PIIX4 first. */
191        if (force_addr) {
192                pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
193                pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
194                pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
195                printk(KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to "
196                        "new address %04x!\n", piix4_smba);
197        } else if ((temp & 1) == 0) {
198                if (force) {
199                        /* This should never need to be done, but has been
200                         * noted that many Dell machines have the SMBus
201                         * interface on the PIIX4 disabled!? NOTE: This assumes
202                         * I/O space and other allocations WERE done by the
203                         * Bios!  Don't complain if your hardware does weird
204                         * things after enabling this. :') Check for Bios
205                         * updates before resorting to this.
206                         */
207                        pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
208                                              temp | 1);
209                        printk(KERN_NOTICE "i2c-piix4.o: WARNING: SMBus "
210                                "interface has been FORCEFULLY ENABLED!\n");
211                } else {
212                        printk(KERN_ERR "i2c-piix4.o: Host SMBus controller "
213                                "not enabled!\n");
214                        release_region(piix4_smba, SMBIOSIZE);
215                        piix4_smba = 0;
216                        return -ENODEV;
217                }
218        }
219
220#ifdef DEBUG
221        if ((temp & 0x0E) == 8)
222                printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for "
223                        "SMBus.\n");
224        else if ((temp & 0x0E) == 0)
225                printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# "
226                        "for SMBus.\n");
227        else
228                printk(KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration "
229                        "(or code out of date)!\n");
230
231        pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
232        printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp);
233        printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba);
234#endif                          /* DEBUG */
235
236        return 0;
237}
238
239
240/* Another internally used function */
241int piix4_transaction(void)
242{
243        int temp;
244        int result = 0;
245        int timeout = 0;
246
247#ifdef DEBUG
248        printk
249            (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
250             "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
251             inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
252#endif
253
254        /* Make sure the SMBus host is ready to start transmitting */
255        if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
256#ifdef DEBUG
257                printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting...\n",
258                       temp);
259#endif
260                outb_p(temp, SMBHSTSTS);
261                if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
262#ifdef DEBUG
263                        printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp);
264#endif
265                        return -1;
266                } else {
267#ifdef DEBUG
268                        printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n");
269#endif
270                }
271        }
272
273        /* start the transaction by setting bit 6 */
274        outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
275
276        /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
277        do {
278                i2c_delay(1);
279                temp = inb_p(SMBHSTSTS);
280        } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
281
282#ifdef DEBUG
283        /* If the SMBus is still busy, we give up */
284        if (timeout >= MAX_TIMEOUT) {
285                printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n");
286                result = -1;
287        }
288#endif
289
290        if (temp & 0x10) {
291                result = -1;
292#ifdef DEBUG
293                printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n");
294#endif
295        }
296
297        if (temp & 0x08) {
298                result = -1;
299                printk
300                    (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n"
301                     "reset. (sorry!)\n");
302                /* Clock stops and slave is stuck in mid-transmission */
303        }
304
305        if (temp & 0x04) {
306                result = -1;
307#ifdef DEBUG
308                printk(KERN_ERR "i2c-piix4.o: Error: no response!\n");
309#endif
310        }
311
312        if (inb_p(SMBHSTSTS) != 0x00)
313                outb_p(inb(SMBHSTSTS), SMBHSTSTS);
314
315#ifdef DEBUG
316        if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
317                printk
318                    (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n",
319                     temp);
320        }
321        printk
322            (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
323             "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
324             inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
325#endif
326        return result;
327}
328
329/* Return -1 on error. */
330s32 piix4_access(struct i2c_adapter * adap, u16 addr,
331                 unsigned short flags, char read_write,
332                 u8 command, int size, union i2c_smbus_data * data)
333{
334        int i, len;
335
336        switch (size) {
337        case I2C_SMBUS_QUICK:
338                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
339                       SMBHSTADD);
340                size = PIIX4_QUICK;
341                break;
342        case I2C_SMBUS_BYTE:
343                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
344                       SMBHSTADD);
345                if (read_write == I2C_SMBUS_WRITE)
346                        outb_p(command, SMBHSTCMD);
347                size = PIIX4_BYTE;
348                break;
349        case I2C_SMBUS_BYTE_DATA:
350                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
351                       SMBHSTADD);
352                outb_p(command, SMBHSTCMD);
353                if (read_write == I2C_SMBUS_WRITE)
354                        outb_p(data->byte, SMBHSTDAT0);
355                size = PIIX4_BYTE_DATA;
356                break;
357        case I2C_SMBUS_WORD_DATA:
358                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
359                       SMBHSTADD);
360                outb_p(command, SMBHSTCMD);
361                if (read_write == I2C_SMBUS_WRITE) {
362                        outb_p(data->word & 0xff, SMBHSTDAT0);
363                        outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
364                }
365                size = PIIX4_WORD_DATA;
366                break;
367        case I2C_SMBUS_BLOCK_DATA:
368                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
369                       SMBHSTADD);
370                outb_p(command, SMBHSTCMD);
371                if (read_write == I2C_SMBUS_WRITE) {
372                        len = data->block[0];
373                        if (len < 0)
374                                len = 0;
375                        if (len > 32)
376                                len = 32;
377                        outb_p(len, SMBHSTDAT0);
378                        i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
379                        for (i = 1; i <= len; i++)
380                                outb_p(data->block[i], SMBBLKDAT);
381                }
382                size = PIIX4_BLOCK_DATA;
383                break;
384        default:
385                printk
386                    (KERN_WARNING "i2c-piix4.o: Unsupported transaction %d\n", size);
387                return -1;
388        }
389
390        outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
391
392        if (piix4_transaction())        /* Error in transaction */
393                return -1;
394
395        if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
396                return 0;
397
398
399        switch (size) {
400        case PIIX4_BYTE:        /* Where is the result put? I assume here it is in
401                                   SMBHSTDAT0 but it might just as well be in the
402                                   SMBHSTCMD. No clue in the docs */
403
404                data->byte = inb_p(SMBHSTDAT0);
405                break;
406        case PIIX4_BYTE_DATA:
407                data->byte = inb_p(SMBHSTDAT0);
408                break;
409        case PIIX4_WORD_DATA:
410                data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
411                break;
412        case PIIX4_BLOCK_DATA:
413                data->block[0] = inb_p(SMBHSTDAT0);
414                i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
415                for (i = 1; i <= data->block[0]; i++)
416                        data->block[i] = inb_p(SMBBLKDAT);
417                break;
418        }
419        return 0;
420}
421
422static void piix4_inc(struct i2c_adapter *adapter)
423{
424#ifdef MODULE
425        MOD_INC_USE_COUNT;
426#endif
427}
428
429static void piix4_dec(struct i2c_adapter *adapter)
430{
431#ifdef MODULE
432        MOD_DEC_USE_COUNT;
433#endif
434}
435
436u32 piix4_func(struct i2c_adapter *adapter)
437{
438        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
439            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
440            I2C_FUNC_SMBUS_BLOCK_DATA;
441}
442
443static struct i2c_algorithm smbus_algorithm = {
444        .name           = "Non-I2C SMBus adapter",
445        .id             = I2C_ALGO_SMBUS,
446        .smbus_xfer     = piix4_access,
447        .functionality  = piix4_func,
448};
449
450static struct i2c_adapter piix4_adapter = {
451        .name           = "unset",
452        .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
453        .algo           = &smbus_algorithm,
454        .inc_use        = piix4_inc,
455        .dec_use        = piix4_dec,
456};
457
458#ifndef PCI_DEVICE_ID_SERVERWORKS_CSB6
459#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203
460#endif
461
462static struct pci_device_id piix4_ids[] __devinitdata = {
463        {
464                .vendor =       PCI_VENDOR_ID_INTEL,
465                .device =       PCI_DEVICE_ID_INTEL_82371AB_3,
466                .subvendor =    PCI_ANY_ID,
467                .subdevice =    PCI_ANY_ID,
468                .driver_data =  3
469        },
470        {
471                .vendor =       PCI_VENDOR_ID_SERVERWORKS,
472                .device =       PCI_DEVICE_ID_SERVERWORKS_OSB4,
473                .subvendor =    PCI_ANY_ID,
474                .subdevice =    PCI_ANY_ID,
475                .driver_data =  0,
476        },
477        {
478                .vendor =       PCI_VENDOR_ID_SERVERWORKS,
479                .device =       PCI_DEVICE_ID_SERVERWORKS_CSB5,
480                .subvendor =    PCI_ANY_ID,
481                .subdevice =    PCI_ANY_ID,
482                .driver_data =  0,
483        },
484        {
485                .vendor =       PCI_VENDOR_ID_SERVERWORKS,
486                .device =       PCI_DEVICE_ID_SERVERWORKS_CSB6,
487                .subvendor =    PCI_ANY_ID,
488                .subdevice =    PCI_ANY_ID,
489                .driver_data =  0,
490        },
491        {
492                .vendor =       PCI_VENDOR_ID_INTEL,
493                .device =       PCI_DEVICE_ID_INTEL_82443MX_3,
494                .subvendor =    PCI_ANY_ID,
495                .subdevice =    PCI_ANY_ID,
496                .driver_data =  3,
497        },
498        {
499                .vendor =       PCI_VENDOR_ID_EFAR,
500                .device =       PCI_DEVICE_ID_EFAR_SLC90E66_3,
501                .subvendor =    PCI_ANY_ID,
502                .subdevice =    PCI_ANY_ID,
503                .driver_data =  0,
504        },
505        { 0, }
506};
507
508static int __devinit piix4_probe(struct pci_dev *dev,
509                                const struct pci_device_id *id)
510{
511        int retval;
512
513        retval = piix4_setup(dev, id);
514        if (retval)
515                return retval;
516
517        sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
518                piix4_smba);
519
520        if ((retval = i2c_add_adapter(&piix4_adapter))) {
521                printk(KERN_ERR "i2c-piix4.o: Couldn't register adapter!\n");
522                release_region(piix4_smba, SMBIOSIZE);
523                piix4_smba = 0;
524        }
525
526        return retval;
527}
528
529static void __devexit piix4_remove(struct pci_dev *dev)
530{
531        if (piix4_smba) {
532                i2c_del_adapter(&piix4_adapter);
533                release_region(piix4_smba, SMBIOSIZE);
534                piix4_smba = 0;
535        }
536}
537
538static struct pci_driver piix4_driver = {
539        .name           = "piix4 smbus",
540        .id_table       = piix4_ids,
541        .probe          = piix4_probe,
542        .remove         = __devexit_p(piix4_remove),
543};
544
545static int __init i2c_piix4_init(void)
546{
547        printk("i2c-piix4.o version %s (%s)\n", LM_VERSION, LM_DATE);
548        return pci_module_init(&piix4_driver);
549}
550
551static void __exit i2c_piix4_exit(void)
552{
553        pci_unregister_driver(&piix4_driver);
554}
555
556MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
557                "Philip Edelbrock <phil@netroedge.com>");
558MODULE_DESCRIPTION("PIIX4 SMBus driver");
559MODULE_LICENSE("GPL");
560
561module_init(i2c_piix4_init);
562module_exit(i2c_piix4_exit);
Note: See TracBrowser for help on using the browser.