i2c: sis630: use hex to constants for SMBus commands
[linux-block.git] / drivers / i2c / busses / i2c-sis630.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17*/
18
19/*
20 Changes:
21 24.08.2002
22 Fixed the typo in sis630_access (Thanks to Mark M. Hoffman)
23 Changed sis630_transaction.(Thanks to Mark M. Hoffman)
24 18.09.2002
25 Added SIS730 as supported.
26 21.09.2002
27 Added high_clock module option.If this option is set
28 used Host Master Clock 56KHz (default 14KHz).For now we save old Host
29 Master Clock and after transaction completed restore (otherwise
30 it's confuse BIOS and hung Machine).
31 24.09.2002
32 Fixed typo in sis630_access
33 Fixed logical error by restoring of Host Master Clock
34 31.07.2003
35 Added block data read/write support.
36*/
37
38/*
39 Status: beta
40
41 Supports:
42 SIS 630
43 SIS 730
974d6a37
AD
44 SIS 964
45
46 Notable differences between chips:
47 +------------------------+--------------------+-------------------+
48 | | SIS630/730 | SIS964 |
49 +------------------------+--------------------+-------------------+
50 | Clock | 14kHz/56kHz | 55.56kHz/27.78kHz |
51 | SMBus registers offset | 0x80 | 0xE0 |
52 | SMB_CNT | Bit 1 = Slave Busy | Bit 1 = Bus probe |
53 | (not used yet) | Bit 3 is reserved | Bit 3 = Last byte |
54 | SMB_PCOUNT | Offset + 0x06 | Offset + 0x14 |
55 | SMB_COUNT | 4:0 bits | 5:0 bits |
56 +------------------------+--------------------+-------------------+
57 (Other differences don't affect the functions provided by the driver)
1da177e4
LT
58
59 Note: we assume there can only be one device, with one SMBus interface.
60*/
61
1da177e4
LT
62#include <linux/kernel.h>
63#include <linux/module.h>
64#include <linux/delay.h>
65#include <linux/pci.h>
66#include <linux/ioport.h>
67#include <linux/init.h>
68#include <linux/i2c.h>
54fb4a05 69#include <linux/acpi.h>
21782180 70#include <linux/io.h>
1da177e4 71
974d6a37
AD
72/* SIS964 id is defined here as we are the only file using it */
73#define PCI_DEVICE_ID_SI_964 0x0964
74
75/* SIS630/730/964 SMBus registers */
76#define SMB_STS 0x00 /* status */
77#define SMB_CNT 0x02 /* control */
78#define SMBHOST_CNT 0x03 /* host control */
79#define SMB_ADDR 0x04 /* address */
80#define SMB_CMD 0x05 /* command */
81#define SMB_COUNT 0x07 /* byte count */
82#define SMB_BYTE 0x08 /* ~0x8F data byte field */
83
a6e7d0ef
AD
84/* SMB_STS register */
85#define BYTE_DONE_STS 0x10 /* Byte Done Status / Block Array */
86#define SMBCOL_STS 0x04 /* Collision */
87#define SMBERR_STS 0x02 /* Device error */
88
89/* SMB_CNT register */
90#define MSTO_EN 0x40 /* Host Master Timeout Enable */
91#define SMBCLK_SEL 0x20 /* Host master clock selection */
92#define SMB_PROBE 0x02 /* Bus Probe/Slave busy */
93#define SMB_HOSTBUSY 0x01 /* Host Busy */
94
95/* SMBHOST_CNT register */
96#define SMB_KILL 0x20 /* Kill */
97#define SMB_START 0x10 /* Start */
98
974d6a37
AD
99/* register count for request_region
100 * As we don't use SMB_PCOUNT, 20 is ok for SiS630 and SiS964
101 */
1da177e4
LT
102#define SIS630_SMB_IOREGION 20
103
104/* PCI address constants */
105/* acpi base address register */
106#define SIS630_ACPI_BASE_REG 0x74
107/* bios control register */
108#define SIS630_BIOS_CTL_REG 0x40
109
110/* Other settings */
111#define MAX_TIMEOUT 500
112
113/* SIS630 constants */
114#define SIS630_QUICK 0x00
115#define SIS630_BYTE 0x01
116#define SIS630_BYTE_DATA 0x02
117#define SIS630_WORD_DATA 0x03
118#define SIS630_PCALL 0x04
119#define SIS630_BLOCK_DATA 0x05
120
d6072f84
JD
121static struct pci_driver sis630_driver;
122
1da177e4 123/* insmod parameters */
90ab5ee9
RR
124static bool high_clock;
125static bool force;
1da177e4 126module_param(high_clock, bool, 0);
974d6a37
AD
127MODULE_PARM_DESC(high_clock,
128 "Set Host Master Clock to 56KHz (default 14KHz) (SIS630/730 only).");
1da177e4
LT
129module_param(force, bool, 0);
130MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
131
974d6a37
AD
132/* SMBus base adress */
133static unsigned short smbus_base;
1da177e4
LT
134
135/* supported chips */
136static int supported[] = {
137 PCI_DEVICE_ID_SI_630,
138 PCI_DEVICE_ID_SI_730,
974d6a37 139 PCI_DEVICE_ID_SI_760,
1da177e4
LT
140 0 /* terminates the list */
141};
142
143static inline u8 sis630_read(u8 reg)
144{
974d6a37 145 return inb(smbus_base + reg);
1da177e4
LT
146}
147
148static inline void sis630_write(u8 reg, u8 data)
149{
974d6a37 150 outb(data, smbus_base + reg);
1da177e4
LT
151}
152
153static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock)
154{
155 int temp;
156
157 /* Make sure the SMBus host is ready to start transmitting. */
a6e7d0ef
AD
158 temp = sis630_read(SMB_CNT);
159 if ((temp & (SMB_PROBE | SMB_HOSTBUSY)) != 0x00) {
160 dev_dbg(&adap->dev, "SMBus busy (%02x). Resetting...\n", temp);
1da177e4 161 /* kill smbus transaction */
a6e7d0ef 162 sis630_write(SMBHOST_CNT, SMB_KILL);
1da177e4 163
a6e7d0ef
AD
164 temp = sis630_read(SMB_CNT);
165 if (temp & (SMB_PROBE | SMB_HOSTBUSY)) {
1da177e4 166 dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
97140342 167 return -EBUSY;
1da177e4 168 } else {
c5d21b7f 169 dev_dbg(&adap->dev, "Successful!\n");
1da177e4
LT
170 }
171 }
172
173 /* save old clock, so we can prevent machine for hung */
174 *oldclock = sis630_read(SMB_CNT);
175
176 dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
177
178 /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
179 if (high_clock)
a6e7d0ef 180 sis630_write(SMB_CNT, SMBCLK_SEL);
1da177e4 181 else
a6e7d0ef 182 sis630_write(SMB_CNT, (*oldclock & ~MSTO_EN));
1da177e4
LT
183
184 /* clear all sticky bits */
185 temp = sis630_read(SMB_STS);
186 sis630_write(SMB_STS, temp & 0x1e);
187
188 /* start the transaction by setting bit 4 and size */
a6e7d0ef 189 sis630_write(SMBHOST_CNT, SMB_START | (size & 0x07));
1da177e4
LT
190
191 return 0;
192}
193
194static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
195{
196 int temp, result = 0, timeout = 0;
197
198 /* We will always wait for a fraction of a second! */
199 do {
200 msleep(1);
201 temp = sis630_read(SMB_STS);
202 /* check if block transmitted */
a6e7d0ef 203 if (size == SIS630_BLOCK_DATA && (temp & BYTE_DONE_STS))
1da177e4
LT
204 break;
205 } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
206
207 /* If the SMBus is still busy, we give up */
4ccc28f7 208 if (timeout > MAX_TIMEOUT) {
1da177e4 209 dev_dbg(&adap->dev, "SMBus Timeout!\n");
97140342 210 result = -ETIMEDOUT;
1da177e4
LT
211 }
212
a6e7d0ef 213 if (temp & SMBERR_STS) {
1da177e4 214 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
97140342 215 result = -ENXIO;
1da177e4
LT
216 }
217
a6e7d0ef 218 if (temp & SMBCOL_STS) {
1da177e4 219 dev_err(&adap->dev, "Bus collision!\n");
499b9194 220 result = -EAGAIN;
1da177e4
LT
221 }
222
223 return result;
224}
225
226static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
227{
1da177e4 228 /* clear all status "sticky" bits */
aa9e7a39 229 sis630_write(SMB_STS, 0xFF);
1da177e4
LT
230
231 dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
232
233 /*
234 * restore old Host Master Clock if high_clock is set
235 * and oldclock was not 56KHz
236 */
a6e7d0ef
AD
237 if (high_clock && !(oldclock & SMBCLK_SEL))
238 sis630_write(SMB_CNT, sis630_read(SMB_CNT) & ~SMBCLK_SEL);
1da177e4
LT
239
240 dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
241}
242
243static int sis630_transaction(struct i2c_adapter *adap, int size)
244{
245 int result = 0;
246 u8 oldclock = 0;
247
248 result = sis630_transaction_start(adap, size, &oldclock);
249 if (!result) {
250 result = sis630_transaction_wait(adap, size);
251 sis630_transaction_end(adap, oldclock);
252 }
253
254 return result;
255}
256
257static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write)
258{
259 int i, len = 0, rc = 0;
260 u8 oldclock = 0;
261
262 if (read_write == I2C_SMBUS_WRITE) {
263 len = data->block[0];
264 if (len < 0)
265 len = 0;
266 else if (len > 32)
267 len = 32;
268 sis630_write(SMB_COUNT, len);
269 for (i=1; i <= len; i++) {
270 dev_dbg(&adap->dev, "set data 0x%02x\n", data->block[i]);
271 /* set data */
272 sis630_write(SMB_BYTE+(i-1)%8, data->block[i]);
273 if (i==8 || (len<8 && i==len)) {
274 dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i);
275 /* first transaction */
97140342
DB
276 rc = sis630_transaction_start(adap,
277 SIS630_BLOCK_DATA, &oldclock);
278 if (rc)
279 return rc;
1da177e4
LT
280 }
281 else if ((i-1)%8 == 7 || i==len) {
282 dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
283 if (i>8) {
284 dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
285 /*
286 If this is not first transaction,
287 we must clear sticky bit.
288 clear SMBARY_STS
289 */
a6e7d0ef 290 sis630_write(SMB_STS, BYTE_DONE_STS);
1da177e4 291 }
97140342
DB
292 rc = sis630_transaction_wait(adap,
293 SIS630_BLOCK_DATA);
294 if (rc) {
1da177e4 295 dev_dbg(&adap->dev, "trans_wait failed\n");
1da177e4
LT
296 break;
297 }
298 }
299 }
300 }
301 else {
302 /* read request */
303 data->block[0] = len = 0;
97140342
DB
304 rc = sis630_transaction_start(adap,
305 SIS630_BLOCK_DATA, &oldclock);
306 if (rc)
307 return rc;
1da177e4 308 do {
97140342
DB
309 rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
310 if (rc) {
1da177e4 311 dev_dbg(&adap->dev, "trans_wait failed\n");
1da177e4
LT
312 break;
313 }
314 /* if this first transaction then read byte count */
315 if (len == 0)
316 data->block[0] = sis630_read(SMB_COUNT);
317
318 /* just to be sure */
319 if (data->block[0] > 32)
320 data->block[0] = 32;
321
322 dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]);
323
324 for (i=0; i < 8 && len < data->block[0]; i++,len++) {
325 dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len);
326 data->block[len+1] = sis630_read(SMB_BYTE+i);
327 }
328
329 dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
330
331 /* clear SMBARY_STS */
a6e7d0ef 332 sis630_write(SMB_STS, BYTE_DONE_STS);
1da177e4
LT
333 } while(len < data->block[0]);
334 }
335
336 sis630_transaction_end(adap, oldclock);
337
338 return rc;
339}
340
97140342 341/* Return negative errno on error. */
1da177e4
LT
342static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
343 unsigned short flags, char read_write,
344 u8 command, int size, union i2c_smbus_data *data)
345{
97140342
DB
346 int status;
347
1da177e4
LT
348 switch (size) {
349 case I2C_SMBUS_QUICK:
350 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
351 size = SIS630_QUICK;
352 break;
353 case I2C_SMBUS_BYTE:
354 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
355 if (read_write == I2C_SMBUS_WRITE)
356 sis630_write(SMB_CMD, command);
357 size = SIS630_BYTE;
358 break;
359 case I2C_SMBUS_BYTE_DATA:
360 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
361 sis630_write(SMB_CMD, command);
362 if (read_write == I2C_SMBUS_WRITE)
363 sis630_write(SMB_BYTE, data->byte);
364 size = SIS630_BYTE_DATA;
365 break;
366 case I2C_SMBUS_PROC_CALL:
367 case I2C_SMBUS_WORD_DATA:
368 sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
369 sis630_write(SMB_CMD, command);
370 if (read_write == I2C_SMBUS_WRITE) {
371 sis630_write(SMB_BYTE, data->word & 0xff);
372 sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8);
373 }
374 size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
375 break;
376 case I2C_SMBUS_BLOCK_DATA:
377 sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
378 sis630_write(SMB_CMD, command);
379 size = SIS630_BLOCK_DATA;
380 return sis630_block_data(adap, data, read_write);
381 default:
ac7fc4fb
JD
382 dev_warn(&adap->dev, "Unsupported transaction %d\n",
383 size);
97140342 384 return -EOPNOTSUPP;
1da177e4
LT
385 }
386
97140342
DB
387 status = sis630_transaction(adap, size);
388 if (status)
389 return status;
1da177e4
LT
390
391 if ((size != SIS630_PCALL) &&
392 ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
393 return 0;
394 }
395
396 switch(size) {
397 case SIS630_BYTE:
398 case SIS630_BYTE_DATA:
399 data->byte = sis630_read(SMB_BYTE);
400 break;
401 case SIS630_PCALL:
402 case SIS630_WORD_DATA:
403 data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
404 break;
1da177e4
LT
405 }
406
407 return 0;
408}
409
410static u32 sis630_func(struct i2c_adapter *adapter)
411{
412 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
413 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
414 I2C_FUNC_SMBUS_BLOCK_DATA;
415}
416
0b255e92 417static int sis630_setup(struct pci_dev *sis630_dev)
1da177e4
LT
418{
419 unsigned char b;
420 struct pci_dev *dummy = NULL;
7c1f59c9 421 int retval, i;
974d6a37
AD
422 /* acpi base address */
423 unsigned short acpi_base;
1da177e4
LT
424
425 /* check for supported SiS devices */
426 for (i=0; supported[i] > 0 ; i++) {
427 if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy)))
428 break; /* found */
429 }
430
431 if (dummy) {
432 pci_dev_put(dummy);
433 }
434 else if (force) {
435 dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
436 "loading because of force option enabled\n");
437 }
438 else {
439 return -ENODEV;
440 }
441
442 /*
443 Enable ACPI first , so we can accsess reg 74-75
444 in acpi io space and read acpi base addr
445 */
446 if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
447 dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
7c1f59c9 448 retval = -ENODEV;
1da177e4
LT
449 goto exit;
450 }
451 /* if ACPI already enabled , do nothing */
452 if (!(b & 0x80) &&
453 pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
454 dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
7c1f59c9 455 retval = -ENODEV;
1da177e4
LT
456 goto exit;
457 }
458
459 /* Determine the ACPI base address */
460 if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
461 dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
7c1f59c9 462 retval = -ENODEV;
1da177e4
LT
463 goto exit;
464 }
465
466 dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
467
974d6a37
AD
468 if (supported[i] == PCI_DEVICE_ID_SI_760)
469 smbus_base = acpi_base + 0xE0;
470 else
471 smbus_base = acpi_base + 0x80;
472
473 dev_dbg(&sis630_dev->dev, "SMBus base at 0x%04hx\n", smbus_base);
474
475 retval = acpi_check_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
54fb4a05
JD
476 sis630_driver.name);
477 if (retval)
478 goto exit;
479
1da177e4 480 /* Everything is happy, let's grab the memory and set things up. */
974d6a37 481 if (!request_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
d6072f84 482 sis630_driver.name)) {
974d6a37
AD
483 dev_err(&sis630_dev->dev,
484 "I/O Region 0x%04hx-0x%04hx for SMBus already in use.\n",
485 smbus_base + SMB_STS,
486 smbus_base + SMB_STS + SIS630_SMB_IOREGION - 1);
7c1f59c9 487 retval = -EBUSY;
1da177e4
LT
488 goto exit;
489 }
490
491 retval = 0;
492
493exit:
494 if (retval)
974d6a37 495 smbus_base = 0;
1da177e4
LT
496 return retval;
497}
498
499
8f9082c5 500static const struct i2c_algorithm smbus_algorithm = {
1da177e4
LT
501 .smbus_xfer = sis630_access,
502 .functionality = sis630_func,
503};
504
505static struct i2c_adapter sis630_adapter = {
506 .owner = THIS_MODULE,
3401b2ff 507 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
1da177e4 508 .algo = &smbus_algorithm,
974d6a37 509 .retries = 3
1da177e4
LT
510};
511
3527bd50 512static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = {
1da177e4
LT
513 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
514 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
974d6a37 515 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_964) },
1da177e4
LT
516 { 0, }
517};
518
519MODULE_DEVICE_TABLE (pci, sis630_ids);
520
0b255e92 521static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
1da177e4
LT
522{
523 if (sis630_setup(dev)) {
524 dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
525 return -ENODEV;
526 }
527
405ae7d3 528 /* set up the sysfs linkage to our parent device */
1da177e4
LT
529 sis630_adapter.dev.parent = &dev->dev;
530
66c7acf6 531 snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
974d6a37 532 "SMBus SIS630 adapter at %04hx", smbus_base + SMB_STS);
1da177e4
LT
533
534 return i2c_add_adapter(&sis630_adapter);
535}
536
0b255e92 537static void sis630_remove(struct pci_dev *dev)
1da177e4 538{
974d6a37 539 if (smbus_base) {
1da177e4 540 i2c_del_adapter(&sis630_adapter);
974d6a37
AD
541 release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
542 smbus_base = 0;
1da177e4
LT
543 }
544}
545
546
547static struct pci_driver sis630_driver = {
548 .name = "sis630_smbus",
549 .id_table = sis630_ids,
550 .probe = sis630_probe,
0b255e92 551 .remove = sis630_remove,
1da177e4
LT
552};
553
56f21788 554module_pci_driver(sis630_driver);
1da177e4
LT
555
556MODULE_LICENSE("GPL");
557MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
558MODULE_DESCRIPTION("SIS630 SMBus driver");