root/lm-sensors/trunk/kernel/busses/i2c-i801.c @ 1382

Revision 1382, 18.9 KB (checked in by mds, 11 years ago)

add 82801DB (ICH4) support

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    i801.c - Part of lm_sensors, Linux kernel modules for hardware
3              monitoring
4    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>,
5    Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
6    <mdsxyz123@yahoo.com>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23/*
24    SUPPORTED DEVICES   PCI ID
25    82801AA             2413           
26    82801AB             2423           
27    82801BA             2443           
28    82801CA/CAM         2483           
29    82801DB             24C3           
30
31    This driver supports several versions of Intel's I/O Controller Hubs (ICH).
32    For SMBus support, they are similar to the PIIX4 and are part
33    of Intel's '810' and other chipsets.
34    See the doc/busses/i2c-i801 file for details.
35*/
36
37/* Note: we assume there can only be one I801, with one SMBus interface */
38
39#include <linux/version.h>
40#include <linux/module.h>
41#include <linux/pci.h>
42#include <asm/io.h>
43#include <linux/kernel.h>
44#include <linux/stddef.h>
45#include <linux/sched.h>
46#include <linux/ioport.h>
47#include <linux/init.h>
48#include <linux/i2c.h>
49#include "version.h"
50
51#ifdef MODULE_LICENSE
52MODULE_LICENSE("GPL");
53#endif
54
55#ifndef PCI_DEVICE_ID_INTEL_82801AA_3
56#define PCI_DEVICE_ID_INTEL_82801AA_3   0x2413
57#endif
58#ifndef PCI_DEVICE_ID_INTEL_82801AB_3
59#define PCI_DEVICE_ID_INTEL_82801AB_3   0x2423
60#endif
61#ifndef PCI_DEVICE_ID_INTEL_82801BA_2
62#define PCI_DEVICE_ID_INTEL_82801BA_2   0x2443
63#endif
64#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS       0x2483
65#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS       0x24C3
66
67static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3,
68                          PCI_DEVICE_ID_INTEL_82801AB_3,
69                          PCI_DEVICE_ID_INTEL_82801BA_2,
70                          PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
71                          PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
72                          0 };
73
74/* I801 SMBus address offsets */
75#define SMBHSTSTS (0 + i801_smba)
76#define SMBHSTCNT (2 + i801_smba)
77#define SMBHSTCMD (3 + i801_smba)
78#define SMBHSTADD (4 + i801_smba)
79#define SMBHSTDAT0 (5 + i801_smba)
80#define SMBHSTDAT1 (6 + i801_smba)
81#define SMBBLKDAT (7 + i801_smba)
82
83/* PCI Address Constants */
84#define SMBBA     0x020
85#define SMBHSTCFG 0x040
86#define SMBREV    0x008
87
88/* Host configuration bits for SMBHSTCFG */
89#define SMBHSTCFG_HST_EN      1
90#define SMBHSTCFG_SMB_SMI_EN  2
91#define SMBHSTCFG_I2C_EN      4
92
93/* Other settings */
94#define MAX_TIMEOUT 500
95#define  ENABLE_INT9 0
96
97/* I801 command constants */
98#define I801_QUICK          0x00
99#define I801_BYTE           0x04
100#define I801_BYTE_DATA      0x08
101#define I801_WORD_DATA      0x0C
102#define I801_BLOCK_DATA     0x14
103#define I801_I2C_BLOCK_DATA 0x18        /* unimplemented */
104#define I801_BLOCK_LAST     0x34
105#define I801_I2C_BLOCK_LAST 0x38        /* unimplemented */
106
107/* insmod parameters */
108
109/* If force is set to anything different from 0, we forcibly enable the
110   I801. DANGEROUS! */
111static int force = 0;
112MODULE_PARM(force, "i");
113MODULE_PARM_DESC(force, "Forcibly enable the I801. DANGEROUS!");
114
115/* If force_addr is set to anything different from 0, we forcibly enable
116   the I801 at the given address. VERY DANGEROUS! */
117static int force_addr = 0;
118MODULE_PARM(force_addr, "i");
119MODULE_PARM_DESC(force_addr,
120                 "Forcibly enable the I801 at the given address. "
121                 "EXTREMELY DANGEROUS!");
122
123#ifdef MODULE
124static
125#else
126extern
127#endif
128int __init i2c_i801_init(void);
129static int __init i801_cleanup(void);
130static int i801_setup(void);
131static s32 i801_access(struct i2c_adapter *adap, u16 addr,
132                       unsigned short flags, char read_write,
133                       u8 command, int size, union i2c_smbus_data *data);
134static void i801_do_pause(unsigned int amount);
135static int i801_transaction(void);
136static int i801_block_transaction(union i2c_smbus_data *data,
137                                  char read_write, int i2c_enable);
138static void i801_inc(struct i2c_adapter *adapter);
139static void i801_dec(struct i2c_adapter *adapter);
140static u32 i801_func(struct i2c_adapter *adapter);
141
142#ifdef MODULE
143extern int init_module(void);
144extern int cleanup_module(void);
145#endif                          /* MODULE */
146
147static struct i2c_algorithm smbus_algorithm = {
148        /* name */ "Non-I2C SMBus adapter",
149        /* id */ I2C_ALGO_SMBUS,
150        /* master_xfer */ NULL,
151        /* smbus_xfer */ i801_access,
152        /* slave_send */ NULL,
153        /* slave_rcv */ NULL,
154        /* algo_control */ NULL,
155        /* functionality */ i801_func,
156};
157
158static struct i2c_adapter i801_adapter = {
159        "unset",
160        I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
161        &smbus_algorithm,
162        NULL,
163        i801_inc,
164        i801_dec,
165        NULL,
166        NULL,
167};
168
169static int __initdata i801_initialized;
170static unsigned short i801_smba = 0;
171static struct pci_dev *I801_dev = NULL;
172
173
174/* Detect whether a I801 can be found, and initialize it, where necessary.
175   Note the differences between kernels with the old PCI BIOS interface and
176   newer kernels with the real PCI interface. In compat.h some things are
177   defined to make the transition easier. */
178int i801_setup(void)
179{
180        int error_return = 0;
181        int *num = supported;
182        unsigned char temp;
183
184        /* First check whether we can access PCI at all */
185        if (pci_present() == 0) {
186                printk("i2c-i801.o: Error: No PCI-bus found!\n");
187                error_return = -ENODEV;
188                goto END;
189        }
190
191        /* Look for each chip */
192        /* Note: we keep on searching until we have found 'function 3' */
193        I801_dev = NULL;
194        do {
195                if((I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
196                                              *num, I801_dev))) {
197                        if(PCI_FUNC(I801_dev->devfn) != 3)
198                                continue;
199                        break;
200                }
201                num++;
202        } while (*num != 0);
203
204        if (I801_dev == NULL) {
205                printk
206                    ("i2c-i801.o: Error: Can't detect I801, function 3!\n");
207                error_return = -ENODEV;
208                goto END;
209        }
210
211/* Determine the address of the SMBus areas */
212        if (force_addr) {
213                i801_smba = force_addr & 0xfff0;
214                force = 0;
215        } else {
216                pci_read_config_word(I801_dev, SMBBA, &i801_smba);
217                i801_smba &= 0xfff0;
218        }
219
220        if (check_region(i801_smba, 8)) {
221                printk
222                    ("i2c-i801.o: I801_smb region 0x%x already in use!\n",
223                     i801_smba);
224                error_return = -ENODEV;
225                goto END;
226        }
227
228        pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
229/* If force_addr is set, we program the new address here. Just to make
230   sure, we disable the I801 first. */
231        if (force_addr) {
232                pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
233                pci_write_config_word(I801_dev, SMBBA, i801_smba);
234                pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
235                printk
236                    ("i2c-i801.o: WARNING: I801 SMBus interface set to new "
237                     "address %04x!\n", i801_smba);
238        } else if ((temp & 1) == 0) {
239                if (force) {
240/* This should never need to be done, but has been noted that
241   many Dell machines have the SMBus interface on the PIIX4
242   disabled!? NOTE: This assumes I/O space and other allocations WERE
243   done by the Bios!  Don't complain if your hardware does weird
244   things after enabling this. :') Check for Bios updates before
245   resorting to this.  */
246                        pci_write_config_byte(I801_dev, SMBHSTCFG,
247                                              temp | 1);
248                        printk
249                            ("i2c-i801.o: WARNING: I801 SMBus interface has been FORCEFULLY "
250                             "ENABLED!\n");
251                } else {
252                        printk
253                            ("SMBUS: Error: Host SMBus controller not enabled!\n");
254                        error_return = -ENODEV;
255                        goto END;
256                }
257        }
258
259        /* note: we assumed that the BIOS picked SMBus or I2C Bus timing
260           appropriately (bit 2 in SMBHSTCFG) */
261        /* Everything is happy, let's grab the memory and set things up. */
262        request_region(i801_smba, 8, "i801-smbus");
263
264#ifdef DEBUG
265        if (temp & 0x02)
266                printk
267                    ("i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
268        else
269                printk
270                    ("i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
271
272        pci_read_config_byte(I801_dev, SMBREV, &temp);
273        printk("i2c-i801.o: SMBREV = 0x%X\n", temp);
274        printk("i2c-i801.o: I801_smba = 0x%X\n", i801_smba);
275#endif                          /* DEBUG */
276
277      END:
278        return error_return;
279}
280
281
282/* Internally used pause function */
283void i801_do_pause(unsigned int amount)
284{
285        current->state = TASK_INTERRUPTIBLE;
286        schedule_timeout(amount);
287}
288
289/* Another internally used function */
290int i801_transaction(void)
291{
292        int temp;
293        int result = 0;
294        int timeout = 0;
295
296#ifdef DEBUG
297        printk
298            ("i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
299             "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
300             inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
301#endif
302
303        /* Make sure the SMBus host is ready to start transmitting */
304        /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
305        if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
306#ifdef DEBUG
307                printk("i2c-i801.o: SMBus busy (%02x). Resetting... \n",
308                       temp);
309#endif
310                outb_p(temp, SMBHSTSTS);
311                if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
312#ifdef DEBUG
313                        printk("i2c-i801.o: Failed! (%02x)\n", temp);
314#endif
315                        return -1;
316                } else {
317#ifdef DEBUG
318                        printk("i2c-i801.o: Successfull!\n");
319#endif
320                }
321        }
322
323        /* start the transaction by setting bit 6 */
324        outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
325
326        /* We will always wait for a fraction of a second! */
327        do {
328                i801_do_pause(1);
329                temp = inb_p(SMBHSTSTS);
330        } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
331
332        /* If the SMBus is still busy, we give up */
333        if (timeout >= MAX_TIMEOUT) {
334#ifdef DEBUG
335                printk("i2c-i801.o: SMBus Timeout!\n");
336                result = -1;
337#endif
338        }
339
340        if (temp & 0x10) {
341                result = -1;
342#ifdef DEBUG
343                printk("i2c-i801.o: Error: Failed bus transaction\n");
344#endif
345        }
346
347        if (temp & 0x08) {
348                result = -1;
349                printk
350                    ("i2c-i801.o: Bus collision! SMBus may be locked until next hard\n"
351                     "reset. (sorry!)\n");
352                /* Clock stops and slave is stuck in mid-transmission */
353        }
354
355        if (temp & 0x04) {
356                result = -1;
357#ifdef DEBUG
358                printk("i2c-i801.o: Error: no response!\n");
359#endif
360        }
361
362        if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
363                outb_p(inb(SMBHSTSTS), SMBHSTSTS);
364
365        if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
366#ifdef DEBUG
367                printk
368                    ("i2c-i801.o: Failed reset at end of transaction (%02x)\n",
369                     temp);
370#endif
371        }
372#ifdef DEBUG
373        printk
374            ("i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
375             "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
376             inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
377#endif
378        return result;
379}
380
381/* All-inclusive block transaction function */
382int i801_block_transaction(union i2c_smbus_data *data, char read_write, 
383                           int i2c_enable)
384{
385        int i, len;
386        int smbcmd;
387        int temp;
388        int result = 0;
389        int timeout = 0;
390        unsigned char hostc, errmask;
391
392        if (i2c_enable) {
393                if (read_write == I2C_SMBUS_WRITE) {
394                        /* set I2C_EN bit in configuration register */
395                        pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
396                        pci_write_config_byte(I801_dev, SMBHSTCFG, 
397                                              hostc | SMBHSTCFG_I2C_EN);
398                } else {
399                        printk("i2c-i801.o: "
400                               "I2C_SMBUS_I2C_BLOCK_READ not supported!\n");
401                        return -1;
402                }
403        }
404
405        if (read_write == I2C_SMBUS_WRITE) {
406                len = data->block[0];
407                if (len < 1)
408                        len = 1;
409                if (len > 32)
410                        len = 32;
411                outb_p(len, SMBHSTDAT0);
412                outb_p(data->block[1], SMBBLKDAT);
413        } else {
414                len = 32;       /* max for reads */
415        }
416
417        for (i = 1; i <= len; i++) {
418                if (i == len && read_write == I2C_SMBUS_READ)
419                        smbcmd = I801_BLOCK_LAST;
420                else
421                        smbcmd = I801_BLOCK_DATA;
422
423                outb_p((smbcmd & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT);
424
425#ifdef DEBUG
426                printk
427                    ("i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, "
428                     "DAT0=%02x, BLKDAT=%02x\n", inb_p(SMBHSTCNT),
429                     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
430                     inb_p(SMBBLKDAT));
431#endif
432
433                /* Make sure the SMBus host is ready to start transmitting */
434                temp = inb_p(SMBHSTSTS);
435                if (i == 1) {
436                    /* Erronenous conditions before transaction:
437                     * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
438                    errmask=0x9f; 
439                } else {
440                    /* Erronenous conditions during transaction:
441                     * Failed, Bus_Err, Dev_Err, Intr */
442                    errmask=0x1e; 
443                }
444                if (temp & errmask) {
445#ifdef DEBUG
446                        printk
447                            ("i2c-i801.o: SMBus busy (%02x). Resetting... \n",
448                             temp);
449#endif
450                        outb_p(temp, SMBHSTSTS);
451                        if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
452                                printk
453                                    ("i2c-i801.o: Reset failed! (%02x)\n",
454                                     temp);
455                                result = -1;
456                                goto END;
457                        }
458                        if (i != 1) {
459                                result = -1;  /* if die in middle of block transaction, fail */
460                                goto END;
461                        }
462                }
463
464                /* start the transaction by setting bit 6 */
465                if (i==1) outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
466
467                /* We will always wait for a fraction of a second! */
468                do {
469                        temp = inb_p(SMBHSTSTS);
470                        i801_do_pause(1);
471                }
472                    while (
473                           (((i >= len) && (temp & 0x01))
474                            || ((i < len) && !(temp & 0x80)))
475                           && (timeout++ < MAX_TIMEOUT));
476
477                /* If the SMBus is still busy, we give up */
478                if (timeout >= MAX_TIMEOUT) {
479                        result = -1;
480#ifdef DEBUG
481                        printk("i2c-i801.o: SMBus Timeout!\n");
482#endif
483                }
484
485                if (temp & 0x10) {
486                        result = -1;
487#ifdef DEBUG
488                        printk
489                            ("i2c-i801.o: Error: Failed bus transaction\n");
490#endif
491                } else if (temp & 0x08) {
492                        result = -1;
493                        printk
494                            ("i2c-i801.o: Bus collision! SMBus may be locked until next hard"
495                             " reset. (sorry!)\n");
496                        /* Clock stops and slave is stuck in mid-transmission */
497                } else if (temp & 0x04) {
498                        result = -1;
499#ifdef DEBUG
500                        printk("i2c-i801.o: Error: no response!\n");
501#endif
502                }
503
504                if (i == 1 && read_write == I2C_SMBUS_READ) {
505                        len = inb_p(SMBHSTDAT0);
506                        if (len < 1)
507                                len = 1;
508                        if (len > 32)
509                                len = 32;
510                        data->block[0] = len;
511                }
512
513                /* Retrieve/store value in SMBBLKDAT */
514                if (read_write == I2C_SMBUS_READ)
515                        data->block[i] = inb_p(SMBBLKDAT);
516                if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
517                        outb_p(data->block[i+1], SMBBLKDAT);
518                if ((temp & 0x9e) != 0x00)
519                        outb_p(temp, SMBHSTSTS);  /* signals SMBBLKDAT ready */
520
521                temp = inb_p(SMBHSTSTS);
522                if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
523#ifdef DEBUG
524                        printk
525                            ("i2c-i801.o: Failed reset at end of transaction (%02x)\n",
526                             temp);
527#endif
528                }
529#ifdef DEBUG
530                printk
531                    ("i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
532                     "DAT0=%02x, BLKDAT=%02x\n", inb_p(SMBHSTCNT),
533                     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
534                     inb_p(SMBBLKDAT));
535#endif
536
537                if (result < 0) {
538                        goto END;
539                }
540        }
541        result = 0;
542END:
543        if (i2c_enable) {
544                /* restore saved configuration register value */
545                pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
546        }
547        return result;
548}
549
550/* Return -1 on error. See smbus.h for more information */
551s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
552                char read_write, u8 command, int size,
553                union i2c_smbus_data * data)
554{
555
556        switch (size) {
557        case I2C_SMBUS_PROC_CALL:
558                printk("i2c-i801.o: I2C_SMBUS_PROC_CALL not supported!\n");
559                return -1;
560        case I2C_SMBUS_QUICK:
561                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
562                       SMBHSTADD);
563                size = I801_QUICK;
564                break;
565        case I2C_SMBUS_BYTE:
566                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
567                       SMBHSTADD);
568                if (read_write == I2C_SMBUS_WRITE)
569                        outb_p(command, SMBHSTCMD);
570                size = I801_BYTE;
571                break;
572        case I2C_SMBUS_BYTE_DATA:
573                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
574                       SMBHSTADD);
575                outb_p(command, SMBHSTCMD);
576                if (read_write == I2C_SMBUS_WRITE)
577                        outb_p(data->byte, SMBHSTDAT0);
578                size = I801_BYTE_DATA;
579                break;
580        case I2C_SMBUS_WORD_DATA:
581                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
582                       SMBHSTADD);
583                outb_p(command, SMBHSTCMD);
584                if (read_write == I2C_SMBUS_WRITE) {
585                        outb_p(data->word & 0xff, SMBHSTDAT0);
586                        outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
587                }
588                size = I801_WORD_DATA;
589                break;
590        case I2C_SMBUS_BLOCK_DATA:
591        case I2C_SMBUS_I2C_BLOCK_DATA:
592                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
593                       SMBHSTADD);
594                outb_p(command, SMBHSTCMD);
595                /* Block transactions are very different from piix4 block
596                   and from the other i801 transactions. Handle in the
597                   i801_block_transaction() routine. */
598                return i801_block_transaction(data, read_write, 
599                                              size==I2C_SMBUS_I2C_BLOCK_DATA);
600        }
601
602        /* 'size' is really the transaction type */
603        outb_p((size & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT);
604
605        if (i801_transaction()) /* Error in transaction */
606                return -1;
607
608        if ((read_write == I2C_SMBUS_WRITE) || (size == I801_QUICK))
609                return 0;
610
611
612        switch (size) {
613        case I801_BYTE: /* Result put in SMBHSTDAT0 */
614                data->byte = inb_p(SMBHSTDAT0);
615                break;
616        case I801_BYTE_DATA:
617                data->byte = inb_p(SMBHSTDAT0);
618                break;
619        case I801_WORD_DATA:
620                data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
621                break;
622        }
623        return 0;
624}
625
626void i801_inc(struct i2c_adapter *adapter)
627{
628        MOD_INC_USE_COUNT;
629}
630
631void i801_dec(struct i2c_adapter *adapter)
632{
633        MOD_DEC_USE_COUNT;
634}
635
636u32 i801_func(struct i2c_adapter *adapter)
637{
638        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
639            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
640            I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK;
641}
642
643int __init i2c_i801_init(void)
644{
645        int res;
646        printk("i2c-i801.o version %s (%s)\n", LM_VERSION, LM_DATE);
647#ifdef DEBUG
648/* PE- It might be good to make this a permanent part of the code! */
649        if (i801_initialized) {
650                printk
651                    ("i2c-i801.o: Oops, i801_init called a second time!\n");
652                return -EBUSY;
653        }
654#endif
655        i801_initialized = 0;
656        if ((res = i801_setup())) {
657                printk
658                    ("i2c-i801.o: I801 not detected, module not inserted.\n");
659                i801_cleanup();
660                return res;
661        }
662        i801_initialized++;
663        sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
664                i801_smba);
665        if ((res = i2c_add_adapter(&i801_adapter))) {
666                printk
667                    ("i2c-i801.o: Adapter registration failed, module not inserted.\n");
668                i801_cleanup();
669                return res;
670        }
671        i801_initialized++;
672        printk("i2c-i801.o: I801 bus detected and initialized\n");
673        return 0;
674}
675
676int __init i801_cleanup(void)
677{
678        int res;
679        if (i801_initialized >= 2) {
680                if ((res = i2c_del_adapter(&i801_adapter))) {
681                        printk
682                            ("i2c-i801.o: i2c_del_adapter failed, module not removed\n");
683                        return res;
684                } else
685                        i801_initialized--;
686        }
687        if (i801_initialized >= 1) {
688                release_region(i801_smba, 8);
689                i801_initialized--;
690        }
691        return 0;
692}
693
694EXPORT_NO_SYMBOLS;
695
696#ifdef MODULE
697
698MODULE_AUTHOR
699    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
700MODULE_DESCRIPTION("I801 SMBus driver");
701
702int init_module(void)
703{
704        return i2c_i801_init();
705}
706
707int cleanup_module(void)
708{
709        return i801_cleanup();
710}
711
712#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.