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

Revision 528, 14.9 KB (checked in by mds, 14 years ago)

(mds) Add i801 bus driver.

  • 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, 1999  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    This driver supports the Intel 82801AA and 82801AB
24    I/O Controller Hubs (ICH). They are similar to the PIIX4 and are part
25    of Intel's '810' chipset. See the doc/busses directory for details.
26*/     
27
28/* Note: we assume there can only be one I801, with one SMBus interface */
29
30#include <linux/module.h>
31#include <linux/pci.h>
32#include <asm/io.h>
33#include <linux/kernel.h>
34#include <linux/stddef.h>
35#include <linux/sched.h>
36#include <linux/ioport.h>
37#include <linux/i2c.h>
38#include "version.h"
39#include "compat.h"
40
41#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,54))
42#include <linux/bios32.h>
43#endif
44
45#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,53)
46#include <linux/init.h>
47#else
48#define __init
49#define __initdata
50#endif
51
52/* I801 SMBus address offsets */
53#define SMBHSTSTS (0 + i801_smba)
54#define SMBHSTCNT (2 + i801_smba)
55#define SMBHSTCMD (3 + i801_smba)
56#define SMBHSTADD (4 + i801_smba)
57#define SMBHSTDAT0 (5 + i801_smba)
58#define SMBHSTDAT1 (6 + i801_smba)
59#define SMBBLKDAT (7 + i801_smba)
60
61/* PCI Address Constants */
62#define SMBBA     0x020
63#define SMBHSTCFG 0x040
64#define SMBREV    0x008
65
66/* Other settings */
67#define MAX_TIMEOUT 500
68#define  ENABLE_INT9 0
69
70/* I801 constants */
71#define I801_QUICK      0x00
72#define I801_BYTE       0x04
73#define I801_BYTE_DATA  0x08
74#define I801_WORD_DATA  0x0C
75#define I801_BLOCK_DATA 0x14
76
77/* insmod parameters */
78
79/* If force is set to anything different from 0, we forcibly enable the
80   I801. DANGEROUS! */
81static int force = 0;
82MODULE_PARM(force,"i");
83MODULE_PARM_DESC(force,"Forcibly enable the I801. DANGEROUS!");
84
85/* If force_addr is set to anything different from 0, we forcibly enable
86   the I801 at the given address. VERY DANGEROUS! */
87static int force_addr = 0;
88MODULE_PARM(force_addr,"i");
89MODULE_PARM_DESC(force_addr,"Forcibly enable the I801 at the given address. "
90                            "EXTREMELY DANGEROUS!");
91
92static int __init i801_cleanup(void);
93static int i801_setup(void);
94static s32 i801_access(struct i2c_adapter *adap, u8 addr, char read_write,
95                        u8 command, int size, union i2c_smbus_data * data);
96static void i801_do_pause( unsigned int amount );
97static int i801_transaction(void);
98static void i801_inc(struct i2c_adapter *adapter);
99static void i801_dec(struct i2c_adapter *adapter);
100
101#ifdef MODULE
102extern int init_module(void);
103extern int cleanup_module(void);
104#endif /* MODULE */
105
106static struct i2c_algorithm smbus_algorithm = {
107  /* name */            "Non-I2C SMBus adapter",
108  /* id */              I2C_ALGO_SMBUS,
109  /* master_xfer */     NULL,
110  /* smbus_access */    i801_access,
111  /* slave_send */      NULL,
112  /* slave_rcv */       NULL,
113  /* algo_control */    NULL,
114};
115
116static struct i2c_adapter i801_adapter = {
117  "unset",
118  I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
119  &smbus_algorithm,
120  NULL,
121  i801_inc,
122  i801_dec,
123  NULL,
124  NULL,
125};
126
127static int __initdata i801_initialized;
128static unsigned short i801_smba = 0;
129
130
131/* Detect whether a I801 can be found, and initialize it, where necessary.
132   Note the differences between kernels with the old PCI BIOS interface and
133   newer kernels with the real PCI interface. In compat.h some things are
134   defined to make the transition easier. */
135int i801_setup(void)
136{
137  int error_return=0;
138  unsigned char temp;
139
140#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,54))
141  struct pci_dev *I801_dev;
142#else
143  unsigned char I801_bus, I801_devfn;
144  int i,res;
145#endif
146
147  /* First check whether we can access PCI at all */
148  if (pci_present() == 0) {
149    printk("i2c-i801.o: Error: No PCI-bus found!\n");
150    error_return=-ENODEV;
151    goto END;
152  }
153
154  /* Look for the I801, function 3 */
155  /* Have to check for both the 82801AA and 82801AB */
156#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,54))
157  /* Note: we keep on searching until we have found 'function 3' */
158  I801_dev = NULL;
159  do
160    I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL, 
161                                PCI_DEVICE_ID_INTEL_82801AA_3, I801_dev);
162  while(I801_dev && (PCI_FUNC(I801_dev->devfn) != 3));
163  if(I801_dev == NULL) {
164    do
165      I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL, 
166                                  PCI_DEVICE_ID_INTEL_82801AB_3, I801_dev);
167    while(I801_dev && (PCI_FUNC(I801_dev->devfn) != 3));
168  }
169  if(I801_dev == NULL) {
170#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,54) */
171  for (i = 0; 
172       ! (res = pcibios_find_device(PCI_VENDOR_ID_INTEL,
173                                    PCI_DEVICE_ID_INTEL_82801AA_3,
174                                    i,&I801_bus, &I801_devfn)) && 
175         PCI_FUNC(I801_devfn) != 3; 
176       i++);
177  if (res) {
178    for (i = 0; 
179         ! (res = pcibios_find_device(PCI_VENDOR_ID_INTEL,
180                                      PCI_DEVICE_ID_INTEL_82801AB_3,
181                                      i,&I801_bus, &I801_devfn)) && 
182           PCI_FUNC(I801_devfn) != 3; 
183         i++);
184  }
185  if (res) {
186#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,54) */
187    printk("i2c-i801.o: Error: Can't detect I801, function 3!\n");
188    error_return=-ENODEV;
189    goto END;
190  } 
191
192/* Determine the address of the SMBus areas */
193  if (force_addr) {
194    i801_smba = force_addr & 0xfff0;
195    force = 0;
196  } else {
197
198    pci_read_config_word_united(I801_dev, I801_bus ,I801_devfn,
199                                SMBBA,&i801_smba);
200    i801_smba &= 0xfff0;
201  }
202
203  if (check_region(i801_smba, 8)) {
204    printk("i2c-i801.o: I801_smb region 0x%x already in use!\n", i801_smba);
205    error_return=-ENODEV;
206    goto END;
207  }
208
209  pci_read_config_byte_united(I801_dev, I801_bus, I801_devfn,
210                              SMBHSTCFG, &temp);
211/* If force_addr is set, we program the new address here. Just to make
212   sure, we disable the I801 first. */
213  if (force_addr) {
214    pci_write_config_byte_united(I801_dev, I801_bus, I801_devfn,
215                                SMBHSTCFG, temp & 0xfe);
216    pci_write_config_word_united(I801_dev, I801_bus ,I801_devfn,
217                                 SMBBA,i801_smba);
218    pci_write_config_byte_united(I801_dev, I801_bus, I801_devfn,
219                                SMBHSTCFG, temp | 0x01);
220    printk("i2c-i801.o: WARNING: I801 SMBus interface set to new "
221           "address %04x!\n",i801_smba);
222  } else if ((temp & 1) == 0) {
223    if (force) {
224/* This should never need to be done, but has been noted that
225   many Dell machines have the SMBus interface on the PIIX4
226   disabled!? NOTE: This assumes I/O space and other allocations WERE
227   done by the Bios!  Don't complain if your hardware does weird
228   things after enabling this. :') Check for Bios updates before
229   resorting to this.  */
230      pci_write_config_byte_united(I801_dev, I801_bus, I801_devfn,
231                                       SMBHSTCFG, temp | 1);
232      printk("i2c-i801.o: WARNING: I801 SMBus interface has been FORCEFULLY "
233             "ENABLED!\n");
234    } else {
235      printk("SMBUS: Error: Host SMBus controller not enabled!\n");     
236      error_return=-ENODEV;
237      goto END;
238    }
239  }
240
241  /* note: we assumed that the BIOS picked SMBus or I2C Bus timing
242     appropriately (bit 2 in SMBHSTCFG) */
243  /* Everything is happy, let's grab the memory and set things up. */
244  request_region(i801_smba, 8, "i801-smbus");       
245
246#ifdef DEBUG
247  if (temp & 0x02)
248     printk("i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
249  else 
250     printk("i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
251
252  pci_read_config_byte_united(I801_dev, I801_bus, I801_devfn, SMBREV, 
253                              &temp);
254  printk("i2c-i801.o: SMBREV = 0x%X\n",temp);
255  printk("i2c-i801.o: I801_smba = 0x%X\n",i801_smba);
256#endif /* DEBUG */
257
258END:
259  return error_return;
260}
261
262
263/* Internally used pause function */
264void i801_do_pause( unsigned int amount )
265{
266      current->state = TASK_INTERRUPTIBLE;
267      schedule_timeout(amount);
268}
269
270/* Another internally used function */
271int i801_transaction(void) 
272{
273  int temp;
274  int result=0;
275  int timeout=0;
276
277#ifdef DEBUG
278  printk("i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
279         "DAT1=%02x\n",
280         inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
281         inb_p(SMBHSTDAT1));
282#endif
283
284  /* Make sure the SMBus host is ready to start transmitting */
285  /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
286  if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
287#ifdef DEBUG
288    printk("i2c-i801.o: SMBus busy (%02x). Resetting... \n",temp);
289#endif
290    outb_p(temp, SMBHSTSTS);
291    if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
292#ifdef DEBUG
293      printk("i2c-i801.o: Failed! (%02x)\n",temp);
294#endif
295      return -1;
296    } else {
297#ifdef DEBUG
298      printk("i2c-i801.o: Successfull!\n");
299#endif
300    }
301  }
302
303  /* start the transaction by setting bit 6 */
304  outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); 
305
306  /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
307  do {
308    i801_do_pause(1);
309    temp=inb_p(SMBHSTSTS);
310  } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
311
312  /* If the SMBus is still busy, we give up */
313  if (timeout >= MAX_TIMEOUT) {
314#ifdef DEBUG
315    printk("i2c-i801.o: SMBus Timeout!\n"); 
316    result = -1;
317#endif
318  }
319
320  if (temp & 0x10) {
321    result = -1;
322#ifdef DEBUG
323    printk("i2c-i801.o: Error: Failed bus transaction\n");
324#endif
325  }
326
327  if (temp & 0x08) {
328    result = -1;
329    printk("i2c-i801.o: Bus collision! SMBus may be locked until next hard
330           reset. (sorry!)\n");
331    /* Clock stops and slave is stuck in mid-transmission */
332  }
333
334  if (temp & 0x04) {
335    result = -1;
336#ifdef DEBUG
337    printk("i2c-i801.o: Error: no response!\n");
338#endif
339  }
340
341  if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
342    outb_p( inb(SMBHSTSTS), SMBHSTSTS);
343
344  if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
345#ifdef DEBUG
346    printk("i2c-i801.o: Failed reset at end of transaction (%02x)\n",temp);
347#endif
348  }
349#ifdef DEBUG
350  printk("i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
351         "DAT0=%02x, DAT1=%02x\n",
352         inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
353         inb_p(SMBHSTDAT1));
354#endif
355  return result;
356}
357
358/* Return -1 on error. See smbus.h for more information */
359s32 i801_access(struct i2c_adapter *adap, u8 addr, char read_write,
360                 u8 command, int size, union i2c_smbus_data * data)
361{
362  int i,len;
363
364  switch(size) {
365    case I2C_SMBUS_PROC_CALL:
366      printk("i2c-i801.o: I2C_SMBUS_PROC_CALL not supported!\n");
367      return -1;
368    case I2C_SMBUS_QUICK:
369      outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
370      size = I801_QUICK;
371      break;
372    case I2C_SMBUS_BYTE:
373      outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
374      if (read_write == I2C_SMBUS_WRITE)
375        outb_p(command, SMBHSTCMD);
376      size = I801_BYTE;
377      break;
378    case I2C_SMBUS_BYTE_DATA:
379      outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
380      outb_p(command, SMBHSTCMD);
381      if (read_write == I2C_SMBUS_WRITE)
382        outb_p(data->byte,SMBHSTDAT0);
383      size = I801_BYTE_DATA;
384      break;
385    case I2C_SMBUS_WORD_DATA:
386      outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
387      outb_p(command, SMBHSTCMD);
388      if (read_write == I2C_SMBUS_WRITE) {
389        outb_p(data->word & 0xff,SMBHSTDAT0);
390        outb_p((data->word & 0xff00) >> 8,SMBHSTDAT1);
391      }
392      size = I801_WORD_DATA;
393      break;
394    case I2C_SMBUS_BLOCK_DATA:
395      outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
396      outb_p(command, SMBHSTCMD);
397      if (read_write == I2C_SMBUS_WRITE) {
398        len = data->block[0];
399        if (len < 0) 
400          len = 0;
401        if (len > 32)
402          len = 32;
403        outb_p(len,SMBHSTDAT0);
404        i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
405        for (i = 1; i <= len; i ++)
406          outb_p(data->block[i],SMBBLKDAT);
407      }
408      size = I801_BLOCK_DATA;
409      break;
410  }
411
412  outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
413
414  if (i801_transaction()) /* Error in transaction */ 
415    return -1; 
416 
417  if ((read_write == I2C_SMBUS_WRITE) || (size == I801_QUICK))
418    return 0;
419 
420
421  switch(size) {
422    case I801_BYTE: /* Where is the result put? I assume here it is in
423                        SMBHSTDAT0 but it might just as well be in the
424                        SMBHSTCMD. No clue in the docs */
425 
426      data->byte = inb_p(SMBHSTDAT0);
427      break;
428    case I801_BYTE_DATA:
429      data->byte = inb_p(SMBHSTDAT0);
430      break;
431    case I801_WORD_DATA:
432      data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
433      break;
434    case I801_BLOCK_DATA:
435      data->block[0] = inb_p(SMBHSTDAT0);
436      i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
437      for (i = 1; i <= data->block[0]; i++)
438        data->block[i] = inb_p(SMBBLKDAT);
439      break;
440  }
441  return 0;
442}
443
444void i801_inc(struct i2c_adapter *adapter)
445{
446        MOD_INC_USE_COUNT;
447}
448
449void i801_dec(struct i2c_adapter *adapter)
450{
451
452        MOD_DEC_USE_COUNT;
453}
454
455int __init i2c_i801_init(void)
456{
457  int res;
458  printk("i801.o version %s (%s)\n",LM_VERSION,LM_DATE);
459#ifdef DEBUG
460/* PE- It might be good to make this a permanent part of the code! */
461  if (i801_initialized) {
462    printk("i2c-i801.o: Oops, i801_init called a second time!\n");
463    return -EBUSY;
464  }
465#endif
466  i801_initialized = 0;
467  if ((res = i801_setup())) {
468    printk("i2c-i801.o: I801 not detected, module not inserted.\n");
469    i801_cleanup();
470    return res;
471  }
472  i801_initialized ++;
473  sprintf(i801_adapter.name,"SMBus I801 adapter at %04x",i801_smba);
474  if ((res = i2c_add_adapter(&i801_adapter))) {
475    printk("i2c-i801.o: Adapter registration failed, module not inserted.\n");
476    i801_cleanup();
477    return res;
478  }
479  i801_initialized++;
480  printk("i2c-i801.o: I801 bus detected and initialized\n");
481  return 0;
482}
483
484int __init i801_cleanup(void)
485{
486  int res;
487  if (i801_initialized >= 2)
488  {
489    if ((res = i2c_del_adapter(&i801_adapter))) {
490      printk("i2c-i801.o: i2c_del_adapter failed, module not removed\n");
491      return res;
492    } else
493      i801_initialized--;
494  }
495  if (i801_initialized >= 1) {
496    release_region(i801_smba, 8);
497    i801_initialized--;
498  }
499  return 0;
500}
501
502EXPORT_NO_SYMBOLS;
503
504#ifdef MODULE
505
506MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mds@eng.paradyne.com>");
507MODULE_DESCRIPTION("I801 SMBus driver");
508
509int init_module(void)
510{
511  return i2c_i801_init();
512}
513
514int cleanup_module(void)
515{
516  return i801_cleanup();
517}
518
519#endif /* MODULE */
520
Note: See TracBrowser for help on using the browser.