root/lm-sensors/trunk/kernel/busses/i2c-sis5595.c @ 4278

Revision 4278, 12.2 KB (checked in by khali, 8 years ago)

Fix typo: successful.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    sis5595.c - Part of lm_sensors, Linux kernel modules for hardware
3              monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
5    Philip Edelbrock <phil@netroedge.com>
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 SIS5595 with one SMBus interface */
23
24/*
25   Note: all have mfr. ID 0x1039.
26   SUPPORTED            PCI ID         
27        5595            0008
28
29   Note: these chips contain a 0008 device which is incompatible with the
30         5595. We recognize these by the presence of the listed
31         "blacklist" PCI ID and refuse to load.
32
33   NOT SUPPORTED        PCI ID          BLACKLIST PCI ID       
34         540            0008            0540
35         550            0008            0550
36        5513            0008            5511
37        5581            0008            5597
38        5582            0008            5597
39        5597            0008            5597
40        5598            0008            5597/5598
41         630            0008            0630
42         645            0008            0645
43         646            0008            0646
44         648            0008            0648
45         650            0008            0650
46         651            0008            0651
47         730            0008            0730
48         735            0008            0735
49         745            0008            0745
50         746            0008            0746
51*/
52
53/* TO DO:
54 * Add Block Transfers (ugly, but supported by the adapter)
55 * Add adapter resets
56 */
57
58#include <linux/module.h>
59#include <linux/pci.h>
60#include <linux/kernel.h>
61#include <linux/stddef.h>
62#include <linux/sched.h>
63#include <linux/ioport.h>
64#include <linux/i2c.h>
65#include <linux/init.h>
66#include <asm/io.h>
67#include "version.h"
68#include "sensors_compat.h"
69
70MODULE_LICENSE("GPL");
71
72static int blacklist[] = {
73                        PCI_DEVICE_ID_SI_540,
74                        PCI_DEVICE_ID_SI_550,
75                        PCI_DEVICE_ID_SI_630,
76                        PCI_DEVICE_ID_SI_730,
77                        PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but
78                                                  that ID shows up in other chips so we
79                                                  use the 5511 ID for recognition */
80                        PCI_DEVICE_ID_SI_5597,
81                        PCI_DEVICE_ID_SI_5598,
82                        0x645,
83                        0x646,
84                        0x648,
85                        0x650,
86                        0x651,
87                        0x735,
88                        0x745,
89                        0x746,
90                        0 };
91
92/* Length of ISA address segment */
93#define SIS5595_EXTENT 8
94/* SIS5595 SMBus registers */
95#define SMB_STS_LO 0x00
96#define SMB_STS_HI 0x01
97#define SMB_CTL_LO 0x02
98#define SMB_CTL_HI 0x03
99#define SMB_ADDR   0x04
100#define SMB_CMD    0x05
101#define SMB_PCNT   0x06
102#define SMB_CNT    0x07
103#define SMB_BYTE   0x08
104#define SMB_DEV    0x10
105#define SMB_DB0    0x11
106#define SMB_DB1    0x12
107#define SMB_HAA    0x13
108
109/* PCI Address Constants */
110#define SMB_INDEX  0x38
111#define SMB_DAT    0x39
112#define SIS5595_ENABLE_REG 0x40
113#define ACPI_BASE  0x90
114
115/* Other settings */
116#define MAX_TIMEOUT 500
117
118/* SIS5595 constants */
119#define SIS5595_QUICK      0x00
120#define SIS5595_BYTE       0x02
121#define SIS5595_BYTE_DATA  0x04
122#define SIS5595_WORD_DATA  0x06
123#define SIS5595_PROC_CALL  0x08
124#define SIS5595_BLOCK_DATA 0x0A
125
126/* insmod parameters */
127
128/* If force_addr is set to anything different from 0, we forcibly enable
129   the device at the given address. */
130static int force_addr = 0;
131MODULE_PARM(force_addr, "i");
132MODULE_PARM_DESC(force_addr,
133                 "Initialize the base address of the i2c controller");
134
135static int sis5595_transaction(void);
136
137static struct pci_driver sis5595_driver;
138static unsigned short sis5595_base = 0;
139
140static u8 sis5595_read(u8 reg)
141{
142        outb(reg, sis5595_base + SMB_INDEX);
143        return inb(sis5595_base + SMB_DAT);
144}
145
146static void sis5595_write(u8 reg, u8 data)
147{
148        outb(reg, sis5595_base + SMB_INDEX);
149        outb(data, sis5595_base + SMB_DAT);
150}
151
152
153/* Detect whether a SIS5595 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 sis5595_setup(struct pci_dev *SIS5595_dev)
158{
159        u16 a;
160        u8 val;
161        int *i;
162
163        /* Look for imposters */
164        for(i = blacklist; *i != 0; i++) {
165                if (pci_find_device(PCI_VENDOR_ID_SI, *i, NULL)) {
166                        printk("i2c-sis5595.o: Error: Looked for SIS5595 but found unsupported device %.4X\n", *i);
167                        return -ENODEV;
168                }
169        }
170
171/* Determine the address of the SMBus areas */
172        pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base);
173        if(sis5595_base == 0 && force_addr == 0) {
174                printk("i2c-sis5595.o: ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
175                return -ENODEV;
176        }
177
178        if(force_addr)
179                sis5595_base = force_addr & ~(SIS5595_EXTENT - 1);
180#ifdef DEBUG
181        printk("ACPI Base address: %04x\n", sis5595_base);
182#endif
183        /* NB: We grab just the two SMBus registers here, but this may still
184         * interfere with ACPI :-(  */
185        if (check_region(sis5595_base + SMB_INDEX, 2)) {
186                printk
187                    ("i2c-sis5595.o: SMBus registers 0x%04x-0x%04x already in use!\n",
188                     sis5595_base + SMB_INDEX,
189                     sis5595_base + SMB_INDEX + 1);
190                return -ENODEV;
191        }
192
193        if(force_addr) {
194                printk("i2c-sis5595.o: forcing ISA address 0x%04X\n", sis5595_base);
195                if (PCIBIOS_SUCCESSFUL !=
196                    pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base))
197                        return -ENODEV;
198                if (PCIBIOS_SUCCESSFUL !=
199                    pci_read_config_word(SIS5595_dev, ACPI_BASE, &a))
200                        return -ENODEV;
201                if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) {
202                        /* doesn't work for some chips! */
203                        printk("i2c-sis5595.o: force address failed - not supported?\n");
204                        return -ENODEV;
205                }
206        }
207
208        if (PCIBIOS_SUCCESSFUL !=
209            pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val))
210                return -ENODEV;
211        if((val & 0x80) == 0) {
212                printk("sis5595.o: enabling ACPI\n");
213                if (PCIBIOS_SUCCESSFUL !=
214                    pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG,
215                                      val | 0x80))
216                        return -ENODEV;
217                if (PCIBIOS_SUCCESSFUL !=
218                    pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val))
219                        return -ENODEV;
220                if((val & 0x80) == 0) { /* doesn't work for some chips? */
221                        printk("sis5595.o: ACPI enable failed - not supported?\n");
222                        return -ENODEV;
223                }
224        }
225
226        /* Everything is happy, let's grab the memory and set things up. */
227        request_region(sis5595_base + SMB_INDEX, 2, sis5595_driver.name);
228        return(0);
229}
230
231
232/* Another internally used function */
233int sis5595_transaction(void)
234{
235        int temp;
236        int result = 0;
237        int timeout = 0;
238
239        /* Make sure the SMBus host is ready to start transmitting */
240        if (
241            (temp =
242             sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
243            0x00) {
244#ifdef DEBUG
245                printk("i2c-sis5595.o: SMBus busy (%04x). Resetting...\n",
246                       temp);
247#endif
248                sis5595_write(SMB_STS_LO, temp & 0xff);
249                sis5595_write(SMB_STS_HI, temp >> 8);
250                if (
251                    (temp =
252                     sis5595_read(SMB_STS_LO) +
253                     (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
254#ifdef DEBUG
255                        printk("i2c-sis5595.o: Failed! (%02x)\n", temp);
256#endif
257                        return -1;
258                } else {
259#ifdef DEBUG
260                        printk("i2c-sis5595.o: Successful!\n");
261#endif
262                }
263        }
264
265        /* start the transaction by setting bit 4 */
266        sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
267
268        /* We will always wait for a fraction of a second! */
269        do {
270                i2c_delay(1);
271                temp = sis5595_read(SMB_STS_LO);
272        } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
273
274        /* If the SMBus is still busy, we give up */
275        if (timeout >= MAX_TIMEOUT) {
276#ifdef DEBUG
277                printk("i2c-sis5595.o: SMBus Timeout!\n");
278#endif
279                result = -1;
280        }
281
282        if (temp & 0x10) {
283                result = -1;
284#ifdef DEBUG
285                printk("i2c-sis5595.o: Error: Failed bus transaction\n");
286#endif
287        }
288
289        if (temp & 0x20) {
290                result = -1;
291                printk
292                    ("i2c-sis5595.o: Bus collision! SMBus may be locked until next hard\n"
293                     "reset (or not...)\n");
294                /* Clock stops and slave is stuck in mid-transmission */
295        }
296
297        if (
298            (temp =
299             sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
300            0x00) {
301                sis5595_write(SMB_STS_LO, temp & 0xff);
302                sis5595_write(SMB_STS_HI, temp >> 8);
303        }
304
305        if (
306            (temp =
307             sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
308            0x00) {
309
310#ifdef DEBUG
311                printk
312                    ("i2c-sis5595.o: Failed reset at end of transaction (%02x)\n",
313                     temp);
314#endif
315        }
316        return result;
317}
318
319/* Return -1 on error. */
320s32 sis5595_access(struct i2c_adapter * adap, u16 addr,
321                   unsigned short flags, char read_write,
322                   u8 command, int size, union i2c_smbus_data * data)
323{
324        switch (size) {
325        case I2C_SMBUS_QUICK:
326                sis5595_write(SMB_ADDR,
327                              ((addr & 0x7f) << 1) | (read_write & 0x01));
328                size = SIS5595_QUICK;
329                break;
330        case I2C_SMBUS_BYTE:
331                sis5595_write(SMB_ADDR,
332                              ((addr & 0x7f) << 1) | (read_write & 0x01));
333                if (read_write == I2C_SMBUS_WRITE)
334                        sis5595_write(SMB_CMD, command);
335                size = SIS5595_BYTE;
336                break;
337        case I2C_SMBUS_BYTE_DATA:
338                sis5595_write(SMB_ADDR,
339                              ((addr & 0x7f) << 1) | (read_write & 0x01));
340                sis5595_write(SMB_CMD, command);
341                if (read_write == I2C_SMBUS_WRITE)
342                        sis5595_write(SMB_BYTE, data->byte);
343                size = SIS5595_BYTE_DATA;
344                break;
345        case I2C_SMBUS_PROC_CALL:
346        case I2C_SMBUS_WORD_DATA:
347                sis5595_write(SMB_ADDR,
348                              ((addr & 0x7f) << 1) | (read_write & 0x01));
349                sis5595_write(SMB_CMD, command);
350                if (read_write == I2C_SMBUS_WRITE) {
351                        sis5595_write(SMB_BYTE, data->word & 0xff);
352                        sis5595_write(SMB_BYTE + 1,
353                                      (data->word & 0xff00) >> 8);
354                }
355                size =
356                    (size ==
357                     I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL :
358                    SIS5595_WORD_DATA;
359                break;
360/*
361        case I2C_SMBUS_BLOCK_DATA:
362                printk("sis5595.o: Block data not yet implemented!\n");
363                return -1;
364                break;
365*/
366        default:
367                printk
368                    (KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size);
369                return -1;
370        }
371
372        sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
373
374        if (sis5595_transaction())      /* Error in transaction */
375                return -1;
376
377        if ((size != SIS5595_PROC_CALL) &&
378            ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
379                return 0;
380
381
382        switch (size) {
383        case SIS5595_BYTE:      /* Where is the result put? I assume here it is in
384                                   SMB_DATA but it might just as well be in the
385                                   SMB_CMD. No clue in the docs */
386        case SIS5595_BYTE_DATA:
387                data->byte = sis5595_read(SMB_BYTE);
388                break;
389        case SIS5595_WORD_DATA:
390        case SIS5595_PROC_CALL:
391                data->word =
392                    sis5595_read(SMB_BYTE) +
393                    (sis5595_read(SMB_BYTE + 1) << 8);
394                break;
395        }
396        return 0;
397}
398
399static void sis5595_inc(struct i2c_adapter *adapter)
400{
401#ifdef MODULE
402        MOD_INC_USE_COUNT;
403#endif
404}
405
406static void sis5595_dec(struct i2c_adapter *adapter)
407{
408#ifdef MODULE
409        MOD_DEC_USE_COUNT;
410#endif
411}
412
413u32 sis5595_func(struct i2c_adapter *adapter)
414{
415        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
416            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
417            I2C_FUNC_SMBUS_PROC_CALL;
418}
419
420
421static struct i2c_algorithm smbus_algorithm = {
422        .name           = "Non-I2C SMBus adapter",
423        .id             = I2C_ALGO_SMBUS,
424        .smbus_xfer     = sis5595_access,
425        .functionality  = sis5595_func,
426};
427
428static struct i2c_adapter sis5595_adapter = {
429        .id             = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS5595,
430        .algo           = &smbus_algorithm,
431        .inc_use        = sis5595_inc,
432        .dec_use        = sis5595_dec,
433};
434
435
436static struct pci_device_id sis5595_ids[] __devinitdata = {
437        {
438                .vendor =       PCI_VENDOR_ID_SI,
439                .device =       PCI_DEVICE_ID_SI_503,
440                .subvendor =    PCI_ANY_ID,
441                .subdevice =    PCI_ANY_ID,
442        },
443        { 0, }
444};
445
446static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
447{
448
449        if (sis5595_setup(dev)) {
450                printk
451                    ("i2c-sis5595.o: SIS5595 not detected, module not inserted.\n");
452
453                return -ENODEV;
454        }
455
456        sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
457                sis5595_base + SMB_INDEX);
458        i2c_add_adapter(&sis5595_adapter);
459
460        return 0;
461}
462
463static void __devexit sis5595_remove(struct pci_dev *dev)
464{
465        i2c_del_adapter(&sis5595_adapter);
466        release_region(sis5595_base + SMB_INDEX, 2);
467}
468
469
470static struct pci_driver sis5595_driver = {
471        .name           = "sis5595 smbus",
472        .id_table       = sis5595_ids,
473        .probe          = sis5595_probe,
474        .remove         = __devexit_p(sis5595_remove),
475};
476
477static int __init i2c_sis5595_init(void)
478{
479        printk("i2c-sis5595.o version %s (%s)\n", LM_VERSION, LM_DATE);
480        return pci_module_init(&sis5595_driver);
481}
482
483
484static void __exit i2c_sis5595_exit(void)
485{
486        pci_unregister_driver(&sis5595_driver);
487}
488
489
490
491MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
492MODULE_DESCRIPTION("SIS5595 SMBus driver");
493
494module_init(i2c_sis5595_init);
495module_exit(i2c_sis5595_exit);
Note: See TracBrowser for help on using the browser.