root/lm-sensors/trunk/kernel/busses/i2c-viapro.c @ 509

Revision 509, 15.4 KB (checked in by kmalkki, 15 years ago)

(Kyösti)

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