]> err.no Git - linux-2.6/blob - drivers/i2c/busses/i2c-sis5595.c
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6] / drivers / i2c / busses / i2c-sis5595.c
1 /*
2     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
3     Philip Edelbrock <phil@netroedge.com>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /* Note: we assume there can only be one SIS5595 with one SMBus interface */
21
22 /*
23    Note: all have mfr. ID 0x1039.
24    SUPPORTED            PCI ID          
25         5595            0008
26
27    Note: these chips contain a 0008 device which is incompatible with the
28          5595. We recognize these by the presence of the listed
29          "blacklist" PCI ID and refuse to load.
30
31    NOT SUPPORTED        PCI ID          BLACKLIST PCI ID        
32          540            0008            0540
33          550            0008            0550
34         5513            0008            5511
35         5581            0008            5597
36         5582            0008            5597
37         5597            0008            5597
38         5598            0008            5597/5598
39          630            0008            0630
40          645            0008            0645
41          646            0008            0646
42          648            0008            0648
43          650            0008            0650
44          651            0008            0651
45          730            0008            0730
46          735            0008            0735
47          745            0008            0745
48          746            0008            0746
49 */
50
51 /* TO DO: 
52  * Add Block Transfers (ugly, but supported by the adapter)
53  * Add adapter resets
54  */
55
56 #include <linux/kernel.h>
57 #include <linux/module.h>
58 #include <linux/delay.h>
59 #include <linux/pci.h>
60 #include <linux/ioport.h>
61 #include <linux/init.h>
62 #include <linux/i2c.h>
63 #include <linux/acpi.h>
64 #include <asm/io.h>
65
66 static int blacklist[] = {
67         PCI_DEVICE_ID_SI_540,
68         PCI_DEVICE_ID_SI_550,
69         PCI_DEVICE_ID_SI_630,
70         PCI_DEVICE_ID_SI_645,
71         PCI_DEVICE_ID_SI_646,
72         PCI_DEVICE_ID_SI_648,
73         PCI_DEVICE_ID_SI_650,
74         PCI_DEVICE_ID_SI_651,
75         PCI_DEVICE_ID_SI_730,
76         PCI_DEVICE_ID_SI_735,
77         PCI_DEVICE_ID_SI_745,
78         PCI_DEVICE_ID_SI_746,
79         PCI_DEVICE_ID_SI_5511,  /* 5513 chip has the 0008 device but that ID
80                                    shows up in other chips so we use the 5511
81                                    ID for recognition */
82         PCI_DEVICE_ID_SI_5597,
83         PCI_DEVICE_ID_SI_5598,
84         0,                      /* terminates the list */
85 };
86
87 /* Length of ISA address segment */
88 #define SIS5595_EXTENT          8
89 /* SIS5595 SMBus registers */
90 #define SMB_STS_LO              0x00
91 #define SMB_STS_HI              0x01
92 #define SMB_CTL_LO              0x02
93 #define SMB_CTL_HI              0x03
94 #define SMB_ADDR                0x04
95 #define SMB_CMD                 0x05
96 #define SMB_PCNT                0x06
97 #define SMB_CNT                 0x07
98 #define SMB_BYTE                0x08
99 #define SMB_DEV                 0x10
100 #define SMB_DB0                 0x11
101 #define SMB_DB1                 0x12
102 #define SMB_HAA                 0x13
103
104 /* PCI Address Constants */
105 #define SMB_INDEX               0x38
106 #define SMB_DAT                 0x39
107 #define SIS5595_ENABLE_REG      0x40
108 #define ACPI_BASE               0x90
109
110 /* Other settings */
111 #define MAX_TIMEOUT             500
112
113 /* SIS5595 constants */
114 #define SIS5595_QUICK           0x00
115 #define SIS5595_BYTE            0x02
116 #define SIS5595_BYTE_DATA       0x04
117 #define SIS5595_WORD_DATA       0x06
118 #define SIS5595_PROC_CALL       0x08
119 #define SIS5595_BLOCK_DATA      0x0A
120
121 /* insmod parameters */
122
123 /* If force_addr is set to anything different from 0, we forcibly enable
124    the device at the given address. */
125 static u16 force_addr;
126 module_param(force_addr, ushort, 0);
127 MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
128
129 static struct pci_driver sis5595_driver;
130 static unsigned short sis5595_base;
131 static struct pci_dev *sis5595_pdev;
132
133 static u8 sis5595_read(u8 reg)
134 {
135         outb(reg, sis5595_base + SMB_INDEX);
136         return inb(sis5595_base + SMB_DAT);
137 }
138
139 static void sis5595_write(u8 reg, u8 data)
140 {
141         outb(reg, sis5595_base + SMB_INDEX);
142         outb(data, sis5595_base + SMB_DAT);
143 }
144
145 static int sis5595_setup(struct pci_dev *SIS5595_dev)
146 {
147         u16 a;
148         u8 val;
149         int *i;
150         int retval = -ENODEV;
151
152         /* Look for imposters */
153         for (i = blacklist; *i != 0; i++) {
154                 struct pci_dev *dev;
155                 dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
156                 if (dev) {
157                         dev_err(&SIS5595_dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
158                         pci_dev_put(dev);
159                         return -ENODEV;
160                 }
161         }
162
163         /* Determine the address of the SMBus areas */
164         pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base);
165         if (sis5595_base == 0 && force_addr == 0) {
166                 dev_err(&SIS5595_dev->dev, "ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
167                 return -ENODEV;
168         }
169
170         if (force_addr)
171                 sis5595_base = force_addr & ~(SIS5595_EXTENT - 1);
172         dev_dbg(&SIS5595_dev->dev, "ACPI Base address: %04x\n", sis5595_base);
173
174         /* NB: We grab just the two SMBus registers here, but this may still
175          * interfere with ACPI :-(  */
176         retval = acpi_check_region(sis5595_base + SMB_INDEX, 2,
177                                    sis5595_driver.name);
178         if (retval)
179                 return retval;
180
181         if (!request_region(sis5595_base + SMB_INDEX, 2,
182                             sis5595_driver.name)) {
183                 dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
184                         sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
185                 return -ENODEV;
186         }
187
188         if (force_addr) {
189                 dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base);
190                 if (pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base)
191                     != PCIBIOS_SUCCESSFUL)
192                         goto error;
193                 if (pci_read_config_word(SIS5595_dev, ACPI_BASE, &a)
194                     != PCIBIOS_SUCCESSFUL)
195                         goto error;
196                 if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) {
197                         /* doesn't work for some chips! */
198                         dev_err(&SIS5595_dev->dev, "force address failed - not supported?\n");
199                         goto error;
200                 }
201         }
202
203         if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
204             != PCIBIOS_SUCCESSFUL)
205                 goto error;
206         if ((val & 0x80) == 0) {
207                 dev_info(&SIS5595_dev->dev, "enabling ACPI\n");
208                 if (pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80)
209                     != PCIBIOS_SUCCESSFUL)
210                         goto error;
211                 if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
212                     != PCIBIOS_SUCCESSFUL)
213                         goto error;
214                 if ((val & 0x80) == 0) {
215                         /* doesn't work for some chips? */
216                         dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n");
217                         goto error;
218                 }
219         }
220
221         /* Everything is happy */
222         return 0;
223
224 error:
225         release_region(sis5595_base + SMB_INDEX, 2);
226         return retval;
227 }
228
229 static int sis5595_transaction(struct i2c_adapter *adap)
230 {
231         int temp;
232         int result = 0;
233         int timeout = 0;
234
235         /* Make sure the SMBus host is ready to start transmitting */
236         temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
237         if (temp != 0x00) {
238                 dev_dbg(&adap->dev, "SMBus busy (%04x). Resetting...\n", temp);
239                 sis5595_write(SMB_STS_LO, temp & 0xff);
240                 sis5595_write(SMB_STS_HI, temp >> 8);
241                 if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
242                         dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
243                         return -EBUSY;
244                 } else {
245                         dev_dbg(&adap->dev, "Successful!\n");
246                 }
247         }
248
249         /* start the transaction by setting bit 4 */
250         sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
251
252         /* We will always wait for a fraction of a second! */
253         do {
254                 msleep(1);
255                 temp = sis5595_read(SMB_STS_LO);
256         } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
257
258         /* If the SMBus is still busy, we give up */
259         if (timeout >= MAX_TIMEOUT) {
260                 dev_dbg(&adap->dev, "SMBus Timeout!\n");
261                 result = -ETIMEDOUT;
262         }
263
264         if (temp & 0x10) {
265                 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
266                 result = -ENXIO;
267         }
268
269         if (temp & 0x20) {
270                 dev_err(&adap->dev, "Bus collision! SMBus may be locked until "
271                         "next hard reset (or not...)\n");
272                 /* Clock stops and slave is stuck in mid-transmission */
273                 result = -EIO;
274         }
275
276         temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
277         if (temp != 0x00) {
278                 sis5595_write(SMB_STS_LO, temp & 0xff);
279                 sis5595_write(SMB_STS_HI, temp >> 8);
280         }
281
282         temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
283         if (temp != 0x00)
284                 dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp);
285
286         return result;
287 }
288
289 /* Return negative errno on error. */
290 static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
291                           unsigned short flags, char read_write,
292                           u8 command, int size, union i2c_smbus_data *data)
293 {
294         int status;
295
296         switch (size) {
297         case I2C_SMBUS_QUICK:
298                 sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
299                 size = SIS5595_QUICK;
300                 break;
301         case I2C_SMBUS_BYTE:
302                 sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
303                 if (read_write == I2C_SMBUS_WRITE)
304                         sis5595_write(SMB_CMD, command);
305                 size = SIS5595_BYTE;
306                 break;
307         case I2C_SMBUS_BYTE_DATA:
308                 sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
309                 sis5595_write(SMB_CMD, command);
310                 if (read_write == I2C_SMBUS_WRITE)
311                         sis5595_write(SMB_BYTE, data->byte);
312                 size = SIS5595_BYTE_DATA;
313                 break;
314         case I2C_SMBUS_PROC_CALL:
315         case I2C_SMBUS_WORD_DATA:
316                 sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
317                 sis5595_write(SMB_CMD, command);
318                 if (read_write == I2C_SMBUS_WRITE) {
319                         sis5595_write(SMB_BYTE, data->word & 0xff);
320                         sis5595_write(SMB_BYTE + 1,
321                                       (data->word & 0xff00) >> 8);
322                 }
323                 size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA;
324                 break;
325         default:
326                 dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
327                 return -EOPNOTSUPP;
328         }
329
330         sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
331
332         status = sis5595_transaction(adap);
333         if (status)
334                 return status;
335
336         if ((size != SIS5595_PROC_CALL) &&
337             ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
338                 return 0;
339
340
341         switch (size) {
342         case SIS5595_BYTE:
343         case SIS5595_BYTE_DATA:
344                 data->byte = sis5595_read(SMB_BYTE);
345                 break;
346         case SIS5595_WORD_DATA:
347         case SIS5595_PROC_CALL:
348                 data->word = sis5595_read(SMB_BYTE) + (sis5595_read(SMB_BYTE + 1) << 8);
349                 break;
350         }
351         return 0;
352 }
353
354 static u32 sis5595_func(struct i2c_adapter *adapter)
355 {
356         return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
357             I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
358             I2C_FUNC_SMBUS_PROC_CALL;
359 }
360
361 static const struct i2c_algorithm smbus_algorithm = {
362         .smbus_xfer     = sis5595_access,
363         .functionality  = sis5595_func,
364 };
365
366 static struct i2c_adapter sis5595_adapter = {
367         .owner          = THIS_MODULE,
368         .id             = I2C_HW_SMBUS_SIS5595,
369         .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
370         .algo           = &smbus_algorithm,
371 };
372
373 static struct pci_device_id sis5595_ids[] __devinitdata = {
374         { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, 
375         { 0, }
376 };
377
378 MODULE_DEVICE_TABLE (pci, sis5595_ids);
379
380 static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
381 {
382         int err;
383
384         if (sis5595_setup(dev)) {
385                 dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n");
386                 return -ENODEV;
387         }
388
389         /* set up the sysfs linkage to our parent device */
390         sis5595_adapter.dev.parent = &dev->dev;
391
392         sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
393                 sis5595_base + SMB_INDEX);
394         err = i2c_add_adapter(&sis5595_adapter);
395         if (err) {
396                 release_region(sis5595_base + SMB_INDEX, 2);
397                 return err;
398         }
399
400         /* Always return failure here.  This is to allow other drivers to bind
401          * to this pci device.  We don't really want to have control over the
402          * pci device, we only wanted to read as few register values from it.
403          */
404         sis5595_pdev =  pci_dev_get(dev);
405         return -ENODEV;
406 }
407
408 static struct pci_driver sis5595_driver = {
409         .name           = "sis5595_smbus",
410         .id_table       = sis5595_ids,
411         .probe          = sis5595_probe,
412 };
413
414 static int __init i2c_sis5595_init(void)
415 {
416         return pci_register_driver(&sis5595_driver);
417 }
418
419 static void __exit i2c_sis5595_exit(void)
420 {
421         pci_unregister_driver(&sis5595_driver);
422         if (sis5595_pdev) {
423                 i2c_del_adapter(&sis5595_adapter);
424                 release_region(sis5595_base + SMB_INDEX, 2);
425                 pci_dev_put(sis5595_pdev);
426                 sis5595_pdev = NULL;
427         }
428 }
429
430 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
431 MODULE_DESCRIPTION("SIS5595 SMBus driver");
432 MODULE_LICENSE("GPL");
433
434 module_init(i2c_sis5595_init);
435 module_exit(i2c_sis5595_exit);