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

Revision 3138, 13.1 KB (checked in by khali, 8 years ago)

Coding style cleanups, backported from Linux 2.6.

  • 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 - 2002  Frodo Looijaard <frodol@dds.nl>,
5    Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
6    Mark D. Studebaker <mdsxyz123@yahoo.com>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23/*
24   Supports Via devices:
25        82C596A/B (0x3050)
26        82C596B (0x3051)
27        82C686A/B
28        8231
29        8233
30        8233A (0x3147 and 0x3177)
31        8235
32        8237
33   Note: we assume there can only be one device, with one SMBus interface.
34*/
35
36#include <linux/module.h>
37#include <linux/pci.h>
38#include <linux/kernel.h>
39#include <linux/stddef.h>
40#include <linux/sched.h>
41#include <linux/ioport.h>
42#include <linux/i2c.h>
43#include <linux/init.h>
44#include <asm/io.h>
45#include "version.h"
46#include "sensors_compat.h"
47
48#define SMBBA1          0x90
49#define SMBBA2          0x80
50#define SMBBA3          0xD0
51
52/* SMBus address offsets */
53static unsigned short vt596_smba;
54#define SMBHSTSTS       (vt596_smba + 0)
55#define SMBHSLVSTS      (vt596_smba + 1)
56#define SMBHSTCNT       (vt596_smba + 2)
57#define SMBHSTCMD       (vt596_smba + 3)
58#define SMBHSTADD       (vt596_smba + 4)
59#define SMBHSTDAT0      (vt596_smba + 5)
60#define SMBHSTDAT1      (vt596_smba + 6)
61#define SMBBLKDAT       (vt596_smba + 7)
62#define SMBSLVCNT       (vt596_smba + 8)
63#define SMBSHDWCMD      (vt596_smba + 9)
64#define SMBSLVEVT       (vt596_smba + 0xA)
65#define SMBSLVDAT       (vt596_smba + 0xC)
66
67/* PCI Address Constants */
68
69/* SMBus data in configuration space can be found in two places,
70   We try to select the better one */
71
72static unsigned short smb_cf_hstcfg = 0xD2;
73
74#define SMBHSTCFG       (smb_cf_hstcfg)
75#define SMBSLVC         (smb_cf_hstcfg + 1)
76#define SMBSHDW1        (smb_cf_hstcfg + 2)
77#define SMBSHDW2        (smb_cf_hstcfg + 3)
78#define SMBREV          (smb_cf_hstcfg + 4)
79
80/* Other settings */
81#define MAX_TIMEOUT     500
82#define ENABLE_INT9     0
83
84/* VT82C596 constants */
85#define VT596_QUICK             0x00
86#define VT596_BYTE              0x04
87#define VT596_BYTE_DATA         0x08
88#define VT596_WORD_DATA         0x0C
89#define VT596_BLOCK_DATA        0x14
90
91
92/* If force is set to anything different from 0, we forcibly enable the
93   VT596. DANGEROUS! */
94static int force;
95MODULE_PARM(force, "i");
96MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
97
98/* If force_addr is set to anything different from 0, we forcibly enable
99   the VT596 at the given address. VERY DANGEROUS! */
100static int force_addr;
101MODULE_PARM(force_addr, "i");
102MODULE_PARM_DESC(force_addr,
103                 "Forcibly enable the SMBus at the given address. "
104                 "EXTREMELY DANGEROUS!");
105
106
107static struct i2c_adapter vt596_adapter;
108
109/* Another internally used function */
110static int vt596_transaction(void)
111{
112        int temp;
113        int result = 0;
114        int timeout = 0;
115
116        dev_dbg(&vt596_adapter, "Transaction (pre): CNT=%02x, CMD=%02x, "
117                "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
118                inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
119                inb_p(SMBHSTDAT1));
120
121        /* Make sure the SMBus host is ready to start transmitting */
122        if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
123                dev_dbg(&vt596_adapter, "SMBus busy (0x%02x). "
124                        "Resetting...\n", temp);
125
126                outb_p(temp, SMBHSTSTS);
127                if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
128                        dev_dbg(&vt596_adapter, "Failed! (0x%02x)\n", temp);
129
130                        return -1;
131                } else {
132                        dev_dbg(&vt596_adapter, "Successfull!\n");
133                }
134        }
135
136        /* start the transaction by setting bit 6 */
137        outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
138
139        /* We will always wait for a fraction of a second!
140           I don't know if VIA needs this, Intel did  */
141        do {
142                i2c_delay(1);
143                temp = inb_p(SMBHSTSTS);
144        } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
145
146        /* If the SMBus is still busy, we give up */
147        if (timeout >= MAX_TIMEOUT) {
148                result = -1;
149                dev_dbg(&vt596_adapter, "SMBus Timeout!\n");
150        }
151
152        if (temp & 0x10) {
153                result = -1;
154                dev_dbg(&vt596_adapter, "Error: Failed bus transaction\n");
155        }
156
157        if (temp & 0x08) {
158                result = -1;
159                dev_info(&vt596_adapter, "Bus collision! SMBus may be "
160                        "locked until next hard\nreset. (sorry!)\n");
161                /* Clock stops and slave is stuck in mid-transmission */
162        }
163
164        if (temp & 0x04) {
165                result = -1;
166                dev_dbg(&vt596_adapter, "Error: no response!\n");
167        }
168
169        if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
170                outb_p(temp, SMBHSTSTS);
171                if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
172                        dev_warn(&vt596_adapter, "Failed reset at end "
173                                 "of transaction (%02x)\n", temp);
174                }
175        }
176
177        dev_dbg(&vt596_adapter, "Transaction (post): CNT=%02x, CMD=%02x, "
178                "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
179                inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
180                inb_p(SMBHSTDAT1));
181
182        return result;
183}
184
185/* Return -1 on error. */
186static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
187                unsigned short flags, char read_write, u8 command,
188                int size, union i2c_smbus_data *data)
189{
190        int i, len;
191
192        switch (size) {
193        case I2C_SMBUS_QUICK:
194                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
195                       SMBHSTADD);
196                size = VT596_QUICK;
197                break;
198        case I2C_SMBUS_BYTE:
199                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
200                       SMBHSTADD);
201                if (read_write == I2C_SMBUS_WRITE)
202                        outb_p(command, SMBHSTCMD);
203                size = VT596_BYTE;
204                break;
205        case I2C_SMBUS_BYTE_DATA:
206                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
207                       SMBHSTADD);
208                outb_p(command, SMBHSTCMD);
209                if (read_write == I2C_SMBUS_WRITE)
210                        outb_p(data->byte, SMBHSTDAT0);
211                size = VT596_BYTE_DATA;
212                break;
213        case I2C_SMBUS_WORD_DATA:
214                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
215                       SMBHSTADD);
216                outb_p(command, SMBHSTCMD);
217                if (read_write == I2C_SMBUS_WRITE) {
218                        outb_p(data->word & 0xff, SMBHSTDAT0);
219                        outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
220                }
221                size = VT596_WORD_DATA;
222                break;
223        case I2C_SMBUS_BLOCK_DATA:
224                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
225                       SMBHSTADD);
226                outb_p(command, SMBHSTCMD);
227                if (read_write == I2C_SMBUS_WRITE) {
228                        len = data->block[0];
229                        if (len < 0)
230                                len = 0;
231                        if (len > I2C_SMBUS_BLOCK_MAX)
232                                len = I2C_SMBUS_BLOCK_MAX;
233                        outb_p(len, SMBHSTDAT0);
234                        i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
235                        for (i = 1; i <= len; i++)
236                                outb_p(data->block[i], SMBBLKDAT);
237                }
238                size = VT596_BLOCK_DATA;
239                break;
240        default:
241                dev_warn(&vt596_adapter, "Unsupported transaction %d\n", size);
242                return -1;
243        }
244
245        outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
246
247        if (vt596_transaction()) /* Error in transaction */
248                return -1;
249
250        if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
251                return 0;
252
253        switch (size) {
254        case VT596_BYTE:
255                /* Where is the result put? I assume here it is in
256                 * SMBHSTDAT0 but it might just as well be in the
257                 * SMBHSTCMD. No clue in the docs
258                 */
259                data->byte = inb_p(SMBHSTDAT0);
260                break;
261        case VT596_BYTE_DATA:
262                data->byte = inb_p(SMBHSTDAT0);
263                break;
264        case VT596_WORD_DATA:
265                data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
266                break;
267        case VT596_BLOCK_DATA:
268                data->block[0] = inb_p(SMBHSTDAT0);
269                if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
270                        data->block[0] = I2C_SMBUS_BLOCK_MAX;
271                i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
272                for (i = 1; i <= data->block[0]; i++)
273                        data->block[i] = inb_p(SMBBLKDAT);
274                break;
275        }
276        return 0;
277}
278
279static void vt596_inc(struct i2c_adapter *adapter)
280{
281#ifdef MODULE
282        MOD_INC_USE_COUNT;
283#endif
284}
285
286static void vt596_dec(struct i2c_adapter *adapter)
287{
288#ifdef MODULE
289        MOD_DEC_USE_COUNT;
290#endif
291}
292
293static u32 vt596_func(struct i2c_adapter *adapter)
294{
295        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
296            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
297            I2C_FUNC_SMBUS_BLOCK_DATA;
298}
299
300static struct i2c_algorithm smbus_algorithm = {
301        .name           = "Non-I2C SMBus adapter",
302        .id             = I2C_ALGO_SMBUS,
303        .smbus_xfer     = vt596_access,
304        .functionality  = vt596_func,
305};
306
307static struct i2c_adapter vt596_adapter = {
308        .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2,
309        .algo           = &smbus_algorithm,
310        .name           = "unset",
311        .inc_use        = vt596_inc,
312        .dec_use        = vt596_dec,
313};
314
315static int __init vt596_probe(struct pci_dev *pdev,
316                              const struct pci_device_id *id)
317{
318        unsigned char temp;
319        int error = -ENODEV;
320
321        /* Determine the address of the SMBus areas */
322        if (force_addr) {
323                vt596_smba = force_addr & 0xfff0;
324                force = 0;
325                goto found;
326        }
327
328        if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
329            !(vt596_smba & 0x1)) {
330                /* try 2nd address and config reg. for 596 */
331                if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
332                    !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
333                    (vt596_smba & 0x1)) {
334                        smb_cf_hstcfg = 0x84;
335                } else {
336                        /* no matches at all */
337                        dev_err(pdev, "Cannot configure "
338                                "SMBus I/O Base address\n");
339                        return -ENODEV;
340                }
341        }
342
343        vt596_smba &= 0xfff0;
344        if (vt596_smba == 0) {
345                dev_err(pdev, "SMBus base address "
346                        "uninitialized - upgrade BIOS or use "
347                        "force_addr=0xaddr\n");
348                return -ENODEV;
349        }
350
351found:
352        if (!request_region(vt596_smba, 8, "viapro-smbus")) {
353                dev_err(pdev, "SMBus region 0x%x already in use!\n",
354                        vt596_smba);
355                return -ENODEV;
356        }
357
358        pci_read_config_byte(pdev, SMBHSTCFG, &temp);
359        /* If force_addr is set, we program the new address here. Just to make
360           sure, we disable the VT596 first. */
361        if (force_addr) {
362                pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
363                pci_write_config_word(pdev, id->driver_data, vt596_smba);
364                pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
365                dev_warn(pdev, "WARNING: SMBus interface set to new "
366                         "address 0x%04x!\n", vt596_smba);
367        } else if ((temp & 1) == 0) {
368                if (force) {
369                        /* NOTE: This assumes I/O space and other allocations
370                         * WERE done by the Bios!  Don't complain if your
371                         * hardware does weird things after enabling this.
372                         * :') Check for Bios updates before resorting to
373                         * this.
374                         */
375                        pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
376                        dev_info(pdev, "Enabling SMBus device\n");
377                } else {
378                        dev_err(pdev, "SMBUS: Error: Host SMBus "
379                                "controller not enabled! - upgrade BIOS or "
380                                "use force=1\n");
381                        goto release_region;
382                }
383        }
384
385        if ((temp & 0x0E) == 8)
386                dev_dbg(pdev, "using Interrupt 9 for SMBus.\n");
387        else if ((temp & 0x0E) == 0)
388                dev_dbg(pdev, "using Interrupt SMI# for SMBus.\n");
389        else
390                dev_dbg(pdev, "Illegal Interrupt configuration "
391                        "(or code out of date)!\n");
392
393        pci_read_config_byte(pdev, SMBREV, &temp);
394        dev_dbg(pdev, "SMBREV = 0x%X\n", temp);
395        dev_dbg(pdev, "VT596_smba = 0x%X\n", vt596_smba);
396
397        snprintf(vt596_adapter.name, 32,
398                 "SMBus Via Pro adapter at %04x", vt596_smba);
399
400        return i2c_add_adapter(&vt596_adapter);
401
402release_region:
403        release_region(vt596_smba, 8);
404        return error;
405}
406
407/* 8233A is undefined before kernel 2.4.19 */
408#ifndef PCI_DEVICE_ID_VIA_8233A
409#define PCI_DEVICE_ID_VIA_8233A 0x3147
410#endif
411/* 8235 is undefined before kernel 2.4.20 */
412#ifndef PCI_DEVICE_ID_VIA_8235
413#define PCI_DEVICE_ID_VIA_8235  0x3177
414#endif
415/* 8237 is undefined before kernel 2.4.21 */
416#ifndef PCI_DEVICE_ID_VIA_8237
417#define PCI_DEVICE_ID_VIA_8237  0x3227
418#endif
419static struct pci_device_id vt596_ids[] __initdata = {
420        {
421                .vendor         = PCI_VENDOR_ID_VIA,
422                .device         = PCI_DEVICE_ID_VIA_82C596_3,
423                .subvendor      = PCI_ANY_ID,
424                .subdevice      = PCI_ANY_ID,
425                .driver_data    = SMBBA1,
426        },
427        {
428                .vendor         = PCI_VENDOR_ID_VIA,
429                .device         = PCI_DEVICE_ID_VIA_82C596B_3,
430                .subvendor      = PCI_ANY_ID,
431                .subdevice      = PCI_ANY_ID,
432                .driver_data    = SMBBA1,
433        },
434        {
435                .vendor         = PCI_VENDOR_ID_VIA,
436                .device         = PCI_DEVICE_ID_VIA_82C686_4,
437                .subvendor      = PCI_ANY_ID,
438                .subdevice      = PCI_ANY_ID,
439                .driver_data    = SMBBA1,
440        },
441        {
442                .vendor         = PCI_VENDOR_ID_VIA,
443                .device         = PCI_DEVICE_ID_VIA_8233_0,
444                .subvendor      = PCI_ANY_ID,
445                .subdevice      = PCI_ANY_ID,
446                .driver_data    = SMBBA3
447        },
448        {
449                .vendor         = PCI_VENDOR_ID_VIA,
450                .device         = PCI_DEVICE_ID_VIA_8233A,
451                .subvendor      = PCI_ANY_ID,
452                .subdevice      = PCI_ANY_ID,
453                .driver_data    = SMBBA3,
454        },
455        {
456                .vendor         = PCI_VENDOR_ID_VIA,
457                .device         = PCI_DEVICE_ID_VIA_8235,
458                .subvendor      = PCI_ANY_ID,
459                .subdevice      = PCI_ANY_ID,
460                .driver_data    = SMBBA3
461        },
462        {
463                .vendor         = PCI_VENDOR_ID_VIA,
464                .device         = PCI_DEVICE_ID_VIA_8237,
465                .subvendor      = PCI_ANY_ID,
466                .subdevice      = PCI_ANY_ID,
467                .driver_data    = SMBBA3
468        },
469        {
470                .vendor         = PCI_VENDOR_ID_VIA,
471                .device         = PCI_DEVICE_ID_VIA_8231_4,
472                .subvendor      = PCI_ANY_ID,
473                .subdevice      = PCI_ANY_ID,
474                .driver_data    = SMBBA1,
475        },
476        { 0, }
477};
478
479static int __init i2c_vt596_init(void)
480{
481        struct pci_dev *dev;
482        const struct pci_device_id *id;
483
484        printk("i2c-viapro.o version %s (%s)\n", LM_VERSION, LM_DATE);
485        pci_for_each_dev(dev) {
486                id = pci_match_device(vt596_ids, dev);
487                if(id)
488                        if(vt596_probe(dev, id) >= 0)
489                                return 0;
490        }
491        return -ENODEV;
492}
493
494
495static void __exit i2c_vt596_exit(void)
496{
497        i2c_del_adapter(&vt596_adapter);
498        release_region(vt596_smba, 8);
499}
500
501MODULE_AUTHOR(
502    "Frodo Looijaard <frodol@dds.nl> and "
503    "Philip Edelbrock <phil@netroedge.com>");
504MODULE_DESCRIPTION("vt82c596 SMBus driver");
505MODULE_LICENSE("GPL");
506
507module_init(i2c_vt596_init);
508module_exit(i2c_vt596_exit);
Note: See TracBrowser for help on using the browser.