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

Revision 4051, 14.6 KB (checked in by khali, 7 years ago)

i2c-piix4: Drop the fix_hstcfg parameter (2.6 backport)

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