Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
420 giacomo 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
   Note: we assume there can only be one device, with one SMBus interface.
33
*/
34
 
35
#include <linux/module.h>
36
#include <linux/pci.h>
37
#include <linux/kernel.h>
38
#include <linux/stddef.h>
39
#include <linux/sched.h>
40
#include <linux/ioport.h>
41
#include <linux/i2c.h>
42
#include <linux/init.h>
43
#include <asm/io.h>
44
 
45
#define SMBBA1           0x90
46
#define SMBBA2           0x80
47
#define SMBBA3           0xD0
48
 
49
/* SMBus address offsets */
50
static unsigned short vt596_smba;
51
#define SMBHSTSTS       (vt596_smba + 0)
52
#define SMBHSLVSTS      (vt596_smba + 1)
53
#define SMBHSTCNT       (vt596_smba + 2)
54
#define SMBHSTCMD       (vt596_smba + 3)
55
#define SMBHSTADD       (vt596_smba + 4)
56
#define SMBHSTDAT0      (vt596_smba + 5)
57
#define SMBHSTDAT1      (vt596_smba + 6)
58
#define SMBBLKDAT       (vt596_smba + 7)
59
#define SMBSLVCNT       (vt596_smba + 8)
60
#define SMBSHDWCMD      (vt596_smba + 9)
61
#define SMBSLVEVT       (vt596_smba + 0xA)
62
#define SMBSLVDAT       (vt596_smba + 0xC)
63
 
64
/* PCI Address Constants */
65
 
66
/* SMBus data in configuration space can be found in two places,
67
   We try to select the better one*/
68
 
69
static unsigned short smb_cf_hstcfg = 0xD2;
70
 
71
#define SMBHSTCFG   (smb_cf_hstcfg)
72
#define SMBSLVC     (smb_cf_hstcfg + 1)
73
#define SMBSHDW1    (smb_cf_hstcfg + 2)
74
#define SMBSHDW2    (smb_cf_hstcfg + 3)
75
#define SMBREV      (smb_cf_hstcfg + 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
 
89
/* If force is set to anything different from 0, we forcibly enable the
90
   VT596. DANGEROUS! */
91
static int force;
92
MODULE_PARM(force, "i");
93
MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
94
 
95
/* If force_addr is set to anything different from 0, we forcibly enable
96
   the VT596 at the given address. VERY DANGEROUS! */
97
static int force_addr;
98
MODULE_PARM(force_addr, "i");
99
MODULE_PARM_DESC(force_addr,
100
                 "Forcibly enable the SMBus at the given address. "
101
                 "EXTREMELY DANGEROUS!");
102
 
103
 
104
static struct i2c_adapter vt596_adapter;
105
 
106
/* Another internally used function */
107
static int vt596_transaction(void)
108
{
109
        int temp;
110
        int result = 0;
111
        int timeout = 0;
112
 
113
        dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
114
                "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
115
                inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
116
                inb_p(SMBHSTDAT1));
117
 
118
        /* Make sure the SMBus host is ready to start transmitting */
119
        if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
120
                dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
121
                                "Resetting...\n", temp);
122
 
123
                outb_p(temp, SMBHSTSTS);
124
                if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
125
                        dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp);
126
 
127
                        return -1;
128
                } else {
129
                        dev_dbg(&vt596_adapter.dev, "Successfull!\n");
130
                }
131
        }
132
 
133
        /* start the transaction by setting bit 6 */
134
        outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
135
 
136
        /* We will always wait for a fraction of a second!
137
           I don't know if VIA needs this, Intel did  */
138
        do {
139
                i2c_delay(1);
140
                temp = inb_p(SMBHSTSTS);
141
        } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
142
 
143
        /* If the SMBus is still busy, we give up */
144
        if (timeout >= MAX_TIMEOUT) {
145
                result = -1;
146
                dev_dbg(&vt596_adapter.dev, "SMBus Timeout!\n");
147
        }
148
 
149
        if (temp & 0x10) {
150
                result = -1;
151
                dev_dbg(&vt596_adapter.dev, "Error: Failed bus transaction\n");
152
        }
153
 
154
        if (temp & 0x08) {
155
                result = -1;
156
                dev_info(&vt596_adapter.dev, "Bus collision! SMBus may be "
157
                        "locked until next hard\nreset. (sorry!)\n");
158
                /* Clock stops and slave is stuck in mid-transmission */
159
        }
160
 
161
        if (temp & 0x04) {
162
                result = -1;
163
                dev_dbg(&vt596_adapter.dev, "Error: no response!\n");
164
        }
165
 
166
        if (inb_p(SMBHSTSTS) != 0x00)
167
                outb_p(inb(SMBHSTSTS), SMBHSTSTS);
168
 
169
        if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
170
                dev_dbg(&vt596_adapter.dev, "Failed reset at end of "
171
                        "transaction (%02x)\n", temp);
172
        }
173
        dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
174
                "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
175
                inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
176
                inb_p(SMBHSTDAT1));
177
 
178
        return result;
179
}
180
 
181
/* Return -1 on error. */
182
static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
183
                unsigned short flags,  char read_write, u8 command,
184
                int size,  union i2c_smbus_data *data)
185
{
186
        int i, len;
187
 
188
        switch (size) {
189
        case I2C_SMBUS_PROC_CALL:
190
                dev_info(&vt596_adapter.dev,
191
                         "I2C_SMBUS_PROC_CALL not supported!\n");
192
                return -1;
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 > 32)
232
                                len = 32;
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
        }
241
 
242
        outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
243
 
244
        if (vt596_transaction()) /* Error in transaction */
245
                return -1;
246
 
247
        if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
248
                return 0;
249
 
250
        switch (size) {
251
        case VT596_BYTE:
252
                /* Where is the result put? I assume here it is in
253
                 * SMBHSTDAT0 but it might just as well be in the
254
                 * SMBHSTCMD. No clue in the docs
255
                 */
256
                data->byte = inb_p(SMBHSTDAT0);
257
                break;
258
        case VT596_BYTE_DATA:
259
                data->byte = inb_p(SMBHSTDAT0);
260
                break;
261
        case VT596_WORD_DATA:
262
                data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
263
                break;
264
        case VT596_BLOCK_DATA:
265
                data->block[0] = inb_p(SMBHSTDAT0);
266
                i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
267
                for (i = 1; i <= data->block[0]; i++)
268
                        data->block[i] = inb_p(SMBBLKDAT);
269
                break;
270
        }
271
        return 0;
272
}
273
 
274
static u32 vt596_func(struct i2c_adapter *adapter)
275
{
276
        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
277
            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
278
            I2C_FUNC_SMBUS_BLOCK_DATA;
279
}
280
 
281
static struct i2c_algorithm smbus_algorithm = {
282
        .name           = "Non-I2C SMBus adapter",
283
        .id             = I2C_ALGO_SMBUS,
284
        .smbus_xfer     = vt596_access,
285
        .functionality  = vt596_func,
286
};
287
 
288
static struct i2c_adapter vt596_adapter = {
289
        .owner          = THIS_MODULE,
290
        .class          = I2C_ADAP_CLASS_SMBUS,
291
        .algo           = &smbus_algorithm,
292
        .name           = "unset",
293
};
294
 
295
static int __devinit vt596_probe(struct pci_dev *pdev,
296
                                 const struct pci_device_id *id)
297
{
298
        unsigned char temp;
299
        int error = -ENODEV;
300
 
301
        /* Determine the address of the SMBus areas */
302
        if (force_addr) {
303
                vt596_smba = force_addr & 0xfff0;
304
                force = 0;
305
                goto found;
306
        }
307
 
308
        if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) ||
309
            !(vt596_smba & 0x1)) {
310
                /* try 2nd address and config reg. for 596 */
311
                if (id->device == PCI_DEVICE_ID_VIA_82C596_3 &&
312
                    !pci_read_config_word(pdev, SMBBA2, &vt596_smba) &&
313
                    (vt596_smba & 0x1)) {
314
                        smb_cf_hstcfg = 0x84;
315
                } else {
316
                        /* no matches at all */
317
                        dev_err(&pdev->dev, "Cannot configure "
318
                                "SMBus I/O Base address\n");
319
                        return -ENODEV;
320
                }
321
        }
322
 
323
        vt596_smba &= 0xfff0;
324
        if (vt596_smba == 0) {
325
                dev_err(&pdev->dev, "SMBus base address "
326
                        "uninitialized - upgrade BIOS or use "
327
                        "force_addr=0xaddr\n");
328
                return -ENODEV;
329
        }
330
 
331
 found:
332
        if (!request_region(vt596_smba, 8, "viapro-smbus")) {
333
                dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
334
                        vt596_smba);
335
                return -ENODEV;
336
        }
337
 
338
        pci_read_config_byte(pdev, SMBHSTCFG, &temp);
339
        /* If force_addr is set, we program the new address here. Just to make
340
           sure, we disable the VT596 first. */
341
        if (force_addr) {
342
                pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe);
343
                pci_write_config_word(pdev, id->driver_data, vt596_smba);
344
                pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01);
345
                dev_warn(&pdev->dev, "WARNING: SMBus interface set to new "
346
                     "address 0x%04x!\n", vt596_smba);
347
        } else if ((temp & 1) == 0) {
348
                if (force) {
349
                        /* NOTE: This assumes I/O space and other allocations
350
                         * WERE done by the Bios!  Don't complain if your
351
                         * hardware does weird things after enabling this.
352
                         * :') Check for Bios updates before resorting to
353
                         * this.
354
                         */
355
                        pci_write_config_byte(pdev, SMBHSTCFG, temp | 1);
356
                        dev_info(&pdev->dev, "Enabling SMBus device\n");
357
                } else {
358
                        dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
359
                                "controller not enabled! - upgrade BIOS or "
360
                                "use force=1\n");
361
                        goto release_region;
362
                }
363
        }
364
 
365
        if ((temp & 0x0E) == 8)
366
                dev_dbg(&pdev->dev, "using Interrupt 9 for SMBus.\n");
367
        else if ((temp & 0x0E) == 0)
368
                dev_dbg(&pdev->dev, "using Interrupt SMI# for SMBus.\n");
369
        else
370
                dev_dbg(&pdev->dev, "Illegal Interrupt configuration "
371
                        "(or code out of date)!\n");
372
 
373
        pci_read_config_byte(pdev, SMBREV, &temp);
374
        dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
375
        dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
376
 
377
        vt596_adapter.dev.parent = &pdev->dev;
378
        snprintf(vt596_adapter.name, I2C_NAME_SIZE,
379
                        "SMBus Via Pro adapter at %04x", vt596_smba);
380
 
381
        return i2c_add_adapter(&vt596_adapter);
382
 
383
 release_region:
384
        release_region(vt596_smba, 8);
385
        return error;
386
}
387
 
388
static void __devexit vt596_remove(struct pci_dev *pdev)
389
{
390
        i2c_del_adapter(&vt596_adapter);
391
        release_region(vt596_smba, 8);
392
}
393
 
394
static struct pci_device_id vt596_ids[] = {
395
        {
396
                .vendor         = PCI_VENDOR_ID_VIA,
397
                .device         = PCI_DEVICE_ID_VIA_82C596_3,
398
                .subvendor      = PCI_ANY_ID,
399
                .subdevice      = PCI_ANY_ID,
400
                .driver_data    = SMBBA1,
401
        },
402
        {
403
                .vendor         = PCI_VENDOR_ID_VIA,
404
                .device         = PCI_DEVICE_ID_VIA_82C596B_3,
405
                .subvendor      = PCI_ANY_ID,
406
                .subdevice      = PCI_ANY_ID,
407
                .driver_data    = SMBBA1,
408
        },
409
        {
410
                .vendor         = PCI_VENDOR_ID_VIA,
411
                .device         = PCI_DEVICE_ID_VIA_82C686_4,
412
                .subvendor      = PCI_ANY_ID,
413
                .subdevice      = PCI_ANY_ID,
414
                .driver_data    = SMBBA1,
415
        },
416
        {
417
                .vendor         = PCI_VENDOR_ID_VIA,
418
                .device         = PCI_DEVICE_ID_VIA_8233_0,
419
                .subvendor      = PCI_ANY_ID,
420
                .subdevice      = PCI_ANY_ID,
421
                .driver_data    = SMBBA3
422
        },
423
        {
424
                .vendor         = PCI_VENDOR_ID_VIA,
425
                .device         = PCI_DEVICE_ID_VIA_8233A,
426
                .subvendor      = PCI_ANY_ID,
427
                .subdevice      = PCI_ANY_ID,
428
                .driver_data    = SMBBA3,
429
        },
430
        {
431
                .vendor         = PCI_VENDOR_ID_VIA,
432
                .device         = PCI_DEVICE_ID_VIA_8235,
433
                .subvendor      = PCI_ANY_ID,
434
                .subdevice      = PCI_ANY_ID,
435
                .driver_data    = SMBBA3
436
        },
437
        {
438
                .vendor         = PCI_VENDOR_ID_VIA,
439
                .device         = PCI_DEVICE_ID_VIA_8231_4,
440
                .subvendor      = PCI_ANY_ID,
441
                .subdevice      = PCI_ANY_ID,
442
                .driver_data    = SMBBA1,
443
        },
444
        { 0, }
445
};
446
 
447
static struct pci_driver vt596_driver = {
448
        .name           = "vt596 smbus",
449
        .id_table       = vt596_ids,
450
        .probe          = vt596_probe,
451
        .remove         = __devexit_p(vt596_remove),
452
};
453
 
454
static int __init i2c_vt596_init(void)
455
{
456
        return pci_module_init(&vt596_driver);
457
}
458
 
459
 
460
static void __exit i2c_vt596_exit(void)
461
{
462
        pci_unregister_driver(&vt596_driver);
463
}
464
 
465
MODULE_AUTHOR(
466
    "Frodo Looijaard <frodol@dds.nl> and "
467
    "Philip Edelbrock <phil@netroedge.com>");
468
MODULE_DESCRIPTION("vt82c596 SMBus driver");
469
MODULE_LICENSE("GPL");
470
 
471
module_init(i2c_vt596_init);
472
module_exit(i2c_vt596_exit);