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

Revision 522, 15.7 KB (checked in by kmalkki, 14 years ago)

(Kyösti)

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