xref: /openbmc/linux/drivers/i2c/busses/i2c-sis630.c (revision 1da177e4)
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;
98 static int force;
99 module_param(high_clock, bool, 0);
100 MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
101 module_param(force, bool, 0);
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)
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 && !(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) {
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 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
468 	{ 0, }
469 };
470 
471 MODULE_DEVICE_TABLE (pci, sis630_ids);
472 
473 static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
474 {
475 	if (sis630_setup(dev)) {
476 		dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
477 		return -ENODEV;
478 	}
479 
480 	/* set up the driverfs linkage to our parent device */
481 	sis630_adapter.dev.parent = &dev->dev;
482 
483 	sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
484 		acpi_base + SMB_STS);
485 
486 	return i2c_add_adapter(&sis630_adapter);
487 }
488 
489 static void __devexit sis630_remove(struct pci_dev *dev)
490 {
491 	if (acpi_base) {
492 		i2c_del_adapter(&sis630_adapter);
493 		release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
494 		acpi_base = 0;
495 	}
496 }
497 
498 
499 static struct pci_driver sis630_driver = {
500 	.name		= "sis630_smbus",
501 	.id_table	= sis630_ids,
502 	.probe		= sis630_probe,
503 	.remove		= __devexit_p(sis630_remove),
504 };
505 
506 static int __init i2c_sis630_init(void)
507 {
508 	return pci_register_driver(&sis630_driver);
509 }
510 
511 
512 static void __exit i2c_sis630_exit(void)
513 {
514 	pci_unregister_driver(&sis630_driver);
515 }
516 
517 
518 MODULE_LICENSE("GPL");
519 MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
520 MODULE_DESCRIPTION("SIS630 SMBus driver");
521 
522 module_init(i2c_sis630_init);
523 module_exit(i2c_sis630_exit);
524