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

Revision 901, 14.3 KB (checked in by mds, 13 years ago)

(mds) add support for Via 596B with PCI ID 0x3051.

Found and patch submitted by Phil Langdale.

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