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