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

Revision 705, 17.3 KB (checked in by frodo, 13 years ago)

Removing kernel 2.0 and 2.1 compatibility pass 2

Eliminated compat.h

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