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

Revision 558, 14.5 KB (checked in by frodo, 14 years ago)

Fixed module lists and ali15x3 module inclusion

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