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