patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / i2c / busses / i2c-sis630.c
1 /*
2     i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware
3               monitoring
4
5     Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
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 /*
23    Changes:
24    24.08.2002
25         Fixed the typo in sis630_access (Thanks to Mark M. Hoffman)
26         Changed sis630_transaction.(Thanks to Mark M. Hoffman)
27    18.09.2002
28         Added SIS730 as supported.
29    21.09.2002
30         Added high_clock module option.If this option is set
31         used Host Master Clock 56KHz (default 14KHz).For now we save old Host
32         Master Clock and after transaction completed restore (otherwise
33         it's confuse BIOS and hung Machine).
34    24.09.2002
35         Fixed typo in sis630_access
36         Fixed logical error by restoring of Host Master Clock
37    31.07.2003
38         Added block data read/write support.
39 */
40
41 /*
42    Status: beta
43
44    Supports:
45         SIS 630
46         SIS 730
47
48    Note: we assume there can only be one device, with one SMBus interface.
49 */
50
51 #include <linux/config.h>
52 #include <linux/kernel.h>
53 #include <linux/module.h>
54 #include <linux/delay.h>
55 #include <linux/pci.h>
56 #include <linux/ioport.h>
57 #include <linux/init.h>
58 #include <linux/i2c.h>
59 #include <asm/io.h>
60
61 /* SIS630 SMBus registers */
62 #define SMB_STS                 0x80    /* status */
63 #define SMB_EN                  0x81    /* status enable */
64 #define SMB_CNT                 0x82
65 #define SMBHOST_CNT             0x83
66 #define SMB_ADDR                0x84
67 #define SMB_CMD                 0x85
68 #define SMB_PCOUNT              0x86    /* processed count */
69 #define SMB_COUNT               0x87
70 #define SMB_BYTE                0x88    /* ~0x8F data byte field */
71 #define SMBDEV_ADDR             0x90
72 #define SMB_DB0                 0x91
73 #define SMB_DB1                 0x92
74 #define SMB_SAA                 0x93
75
76 /* register count for request_region */
77 #define SIS630_SMB_IOREGION     20
78
79 /* PCI address constants */
80 /* acpi base address register  */
81 #define SIS630_ACPI_BASE_REG    0x74
82 /* bios control register */
83 #define SIS630_BIOS_CTL_REG     0x40
84
85 /* Other settings */
86 #define MAX_TIMEOUT             500
87
88 /* SIS630 constants */
89 #define SIS630_QUICK            0x00
90 #define SIS630_BYTE             0x01
91 #define SIS630_BYTE_DATA        0x02
92 #define SIS630_WORD_DATA        0x03
93 #define SIS630_PCALL            0x04
94 #define SIS630_BLOCK_DATA       0x05
95
96 /* insmod parameters */
97 static int high_clock = 0;
98 static int force = 0;
99 MODULE_PARM(high_clock, "i");
100 MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
101 MODULE_PARM(force, "i");
102 MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
103
104 /* acpi base address */
105 static unsigned short acpi_base = 0;
106
107 /* supported chips */
108 static int supported[] = {
109         PCI_DEVICE_ID_SI_630,
110         PCI_DEVICE_ID_SI_730,
111         0 /* terminates the list */
112 };
113
114 static inline u8 sis630_read(u8 reg)
115 {
116         return inb(acpi_base + reg);
117 }
118
119 static inline void sis630_write(u8 reg, u8 data)
120 {
121         outb(data, acpi_base + reg);
122 }
123
124 static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock)
125 {
126         int temp;
127
128         /* Make sure the SMBus host is ready to start transmitting. */
129         if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
130                 dev_dbg(&adap->dev, "SMBus busy (%02x).Resetting...\n",temp);
131                 /* kill smbus transaction */
132                 sis630_write(SMBHOST_CNT, 0x20);
133
134                 if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
135                         dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
136                         return -1;
137                 } else {
138                         dev_dbg(&adap->dev, "Successfull!\n");
139                 }
140         }
141
142         /* save old clock, so we can prevent machine for hung */
143         *oldclock = sis630_read(SMB_CNT);
144
145         dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
146
147         /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
148         if (high_clock > 0)
149                 sis630_write(SMB_CNT, 0x20);
150         else
151                 sis630_write(SMB_CNT, (*oldclock & ~0x40));
152
153         /* clear all sticky bits */
154         temp = sis630_read(SMB_STS);
155         sis630_write(SMB_STS, temp & 0x1e);
156
157         /* start the transaction by setting bit 4 and size */
158         sis630_write(SMBHOST_CNT,0x10 | (size & 0x07));
159
160         return 0;
161 }
162
163 static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
164 {
165         int temp, result = 0, timeout = 0;
166
167         /* We will always wait for a fraction of a second! */
168         do {
169                 msleep(1);
170                 temp = sis630_read(SMB_STS);
171                 /* check if block transmitted */
172                 if (size == SIS630_BLOCK_DATA && (temp & 0x10))
173                         break;
174         } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
175
176         /* If the SMBus is still busy, we give up */
177         if (timeout >= MAX_TIMEOUT) {
178                 dev_dbg(&adap->dev, "SMBus Timeout!\n");
179                 result = -1;
180         }
181
182         if (temp & 0x02) {
183                 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
184                 result = -1;
185         }
186
187         if (temp & 0x04) {
188                 dev_err(&adap->dev, "Bus collision!\n");
189                 result = -1;
190                 /*
191                   TBD: Datasheet say:
192                   the software should clear this bit and restart SMBUS operation.
193                   Should we do it or user start request again?
194                 */
195         }
196
197         return result;
198 }
199
200 static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
201 {
202         int temp = 0;
203
204         /* clear all status "sticky" bits */
205         sis630_write(SMB_STS, temp);
206
207         dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
208
209         /*
210          * restore old Host Master Clock if high_clock is set
211          * and oldclock was not 56KHz
212          */
213         if (high_clock > 0 && !(oldclock & 0x20))
214                 sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20));
215
216         dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
217 }
218
219 static int sis630_transaction(struct i2c_adapter *adap, int size)
220 {
221         int result = 0;
222         u8 oldclock = 0;
223
224         result = sis630_transaction_start(adap, size, &oldclock);
225         if (!result) {
226                 result = sis630_transaction_wait(adap, size);
227                 sis630_transaction_end(adap, oldclock);
228         }
229
230         return result;
231 }
232
233 static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write)
234 {
235         int i, len = 0, rc = 0;
236         u8 oldclock = 0;
237
238         if (read_write == I2C_SMBUS_WRITE) {
239                 len = data->block[0];
240                 if (len < 0)
241                         len = 0;
242                 else if (len > 32)
243                         len = 32;
244                 sis630_write(SMB_COUNT, len);
245                 for (i=1; i <= len; i++) {
246                         dev_dbg(&adap->dev, "set data 0x%02x\n", data->block[i]);
247                         /* set data */
248                         sis630_write(SMB_BYTE+(i-1)%8, data->block[i]);
249                         if (i==8 || (len<8 && i==len)) {
250                                 dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i);
251                                 /* first transaction */
252                                 if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock))
253                                         return -1;
254                         }
255                         else if ((i-1)%8 == 7 || i==len) {
256                                 dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
257                                 if (i>8) {
258                                         dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
259                                         /*
260                                            If this is not first transaction,
261                                            we must clear sticky bit.
262                                            clear SMBARY_STS
263                                         */
264                                         sis630_write(SMB_STS,0x10);
265                                 }
266                                 if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
267                                         dev_dbg(&adap->dev, "trans_wait failed\n");
268                                         rc = -1;
269                                         break;
270                                 }
271                         }
272                 }
273         }
274         else {
275                 /* read request */
276                 data->block[0] = len = 0;
277                 if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) {
278                         return -1;
279                 }
280                 do {
281                         if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
282                                 dev_dbg(&adap->dev, "trans_wait failed\n");
283                                 rc = -1;
284                                 break;
285                         }
286                         /* if this first transaction then read byte count */
287                         if (len == 0)
288                                 data->block[0] = sis630_read(SMB_COUNT);
289
290                         /* just to be sure */
291                         if (data->block[0] > 32)
292                                 data->block[0] = 32;
293
294                         dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]);
295
296                         for (i=0; i < 8 && len < data->block[0]; i++,len++) {
297                                 dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len);
298                                 data->block[len+1] = sis630_read(SMB_BYTE+i);
299                         }
300
301                         dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
302
303                         /* clear SMBARY_STS */
304                         sis630_write(SMB_STS,0x10);
305                 } while(len < data->block[0]);
306         }
307
308         sis630_transaction_end(adap, oldclock);
309
310         return rc;
311 }
312
313 /* Return -1 on error. */
314 static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
315                          unsigned short flags, char read_write,
316                          u8 command, int size, union i2c_smbus_data *data)
317 {
318         switch (size) {
319                 case I2C_SMBUS_QUICK:
320                         sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
321                         size = SIS630_QUICK;
322                         break;
323                 case I2C_SMBUS_BYTE:
324                         sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
325                         if (read_write == I2C_SMBUS_WRITE)
326                                 sis630_write(SMB_CMD, command);
327                         size = SIS630_BYTE;
328                         break;
329                 case I2C_SMBUS_BYTE_DATA:
330                         sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
331                         sis630_write(SMB_CMD, command);
332                         if (read_write == I2C_SMBUS_WRITE)
333                                 sis630_write(SMB_BYTE, data->byte);
334                         size = SIS630_BYTE_DATA;
335                         break;
336                 case I2C_SMBUS_PROC_CALL:
337                 case I2C_SMBUS_WORD_DATA:
338                         sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
339                         sis630_write(SMB_CMD, command);
340                         if (read_write == I2C_SMBUS_WRITE) {
341                                 sis630_write(SMB_BYTE, data->word & 0xff);
342                                 sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8);
343                         }
344                         size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
345                         break;
346                 case I2C_SMBUS_BLOCK_DATA:
347                         sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
348                         sis630_write(SMB_CMD, command);
349                         size = SIS630_BLOCK_DATA;
350                         return sis630_block_data(adap, data, read_write);
351                 default:
352                         printk("Unsupported I2C size\n");
353                         return -1;
354                         break;
355         }
356
357         if (sis630_transaction(adap, size))
358                 return -1;
359
360         if ((size != SIS630_PCALL) &&
361                 ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
362                 return 0;
363         }
364
365         switch(size) {
366                 case SIS630_BYTE:
367                 case SIS630_BYTE_DATA:
368                         data->byte = sis630_read(SMB_BYTE);
369                         break;
370                 case SIS630_PCALL:
371                 case SIS630_WORD_DATA:
372                         data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
373                         break;
374                 default:
375                         return -1;
376                         break;
377         }
378
379         return 0;
380 }
381
382 static u32 sis630_func(struct i2c_adapter *adapter)
383 {
384         return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
385                 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
386                 I2C_FUNC_SMBUS_BLOCK_DATA;
387 }
388
389 static int sis630_setup(struct pci_dev *sis630_dev)
390 {
391         unsigned char b;
392         struct pci_dev *dummy = NULL;
393         int retval = -ENODEV, i;
394
395         /* check for supported SiS devices */
396         for (i=0; supported[i] > 0 ; i++) {
397                 if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy)))
398                         break; /* found */
399         }
400
401         if (dummy) {
402                 pci_dev_put(dummy);
403         }
404         else if (force > 0) {
405                 dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
406                         "loading because of force option enabled\n");
407         }
408         else {
409                 return -ENODEV;
410         }
411
412         /*
413            Enable ACPI first , so we can accsess reg 74-75
414            in acpi io space and read acpi base addr
415         */
416         if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
417                 dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
418                 goto exit;
419         }
420         /* if ACPI already enabled , do nothing */
421         if (!(b & 0x80) &&
422             pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
423                 dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
424                 goto exit;
425         }
426
427         /* Determine the ACPI base address */
428         if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
429                 dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
430                 goto exit;
431         }
432
433         dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
434
435         /* Everything is happy, let's grab the memory and set things up. */
436         if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")) {
437                 dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
438                         "in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
439                 goto exit;
440         }
441
442         retval = 0;
443
444 exit:
445         if (retval)
446                 acpi_base = 0;
447         return retval;
448 }
449
450
451 static struct i2c_algorithm smbus_algorithm = {
452         .name           = "Non-I2C SMBus adapter",
453         .id             = I2C_ALGO_SMBUS,
454         .smbus_xfer     = sis630_access,
455         .functionality  = sis630_func,
456 };
457
458 static struct i2c_adapter sis630_adapter = {
459         .owner          = THIS_MODULE,
460         .class          = I2C_CLASS_HWMON,
461         .name           = "unset",
462         .algo           = &smbus_algorithm,
463 };
464
465 static struct pci_device_id sis630_ids[] __devinitdata = {
466         { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
467         { 0, }
468 };
469
470 static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
471 {
472         if (sis630_setup(dev)) {
473                 dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
474                 return -ENODEV;
475         }
476
477         /* set up the driverfs linkage to our parent device */
478         sis630_adapter.dev.parent = &dev->dev;
479
480         sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
481                 acpi_base + SMB_STS);
482
483         return i2c_add_adapter(&sis630_adapter);
484 }
485
486 static void __devexit sis630_remove(struct pci_dev *dev)
487 {
488         if (acpi_base) {
489                 i2c_del_adapter(&sis630_adapter);
490                 release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
491                 acpi_base = 0;
492         }
493 }
494
495
496 static struct pci_driver sis630_driver = {
497         .name           = "sis630 smbus",
498         .id_table       = sis630_ids,
499         .probe          = sis630_probe,
500         .remove         = __devexit_p(sis630_remove),
501 };
502
503 static int __init i2c_sis630_init(void)
504 {
505         return pci_module_init(&sis630_driver);
506 }
507
508
509 static void __exit i2c_sis630_exit(void)
510 {
511         pci_unregister_driver(&sis630_driver);
512 }
513
514
515 MODULE_LICENSE("GPL");
516 MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
517 MODULE_DESCRIPTION("SIS630 SMBus driver");
518
519 module_init(i2c_sis630_init);
520 module_exit(i2c_sis630_exit);