xref: /openbmc/linux/drivers/i2c/busses/i2c-sis630.c (revision 643d1f7f)
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 -1;
138                 } else {
139 			dev_dbg(&adap->dev, "Successfull!\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 = -1;
181 	}
182 
183 	if (temp & 0x02) {
184 		dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
185 		result = -1;
186 	}
187 
188 	if (temp & 0x04) {
189 		dev_err(&adap->dev, "Bus collision!\n");
190 		result = -1;
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 				if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock))
254 					return -1;
255 			}
256 			else if ((i-1)%8 == 7 || i==len) {
257 				dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
258 				if (i>8) {
259 					dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
260 					/*
261 					   If this is not first transaction,
262 					   we must clear sticky bit.
263 					   clear SMBARY_STS
264 					*/
265 					sis630_write(SMB_STS,0x10);
266 				}
267 				if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
268 					dev_dbg(&adap->dev, "trans_wait failed\n");
269 					rc = -1;
270 					break;
271 				}
272 			}
273 		}
274 	}
275 	else {
276 		/* read request */
277 		data->block[0] = len = 0;
278 		if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) {
279 			return -1;
280 		}
281 		do {
282 			if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
283 				dev_dbg(&adap->dev, "trans_wait failed\n");
284 				rc = -1;
285 				break;
286 			}
287 			/* if this first transaction then read byte count */
288 			if (len == 0)
289 				data->block[0] = sis630_read(SMB_COUNT);
290 
291 			/* just to be sure */
292 			if (data->block[0] > 32)
293 				data->block[0] = 32;
294 
295 			dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]);
296 
297 			for (i=0; i < 8 && len < data->block[0]; i++,len++) {
298 				dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len);
299 				data->block[len+1] = sis630_read(SMB_BYTE+i);
300 			}
301 
302 			dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
303 
304 			/* clear SMBARY_STS */
305 			sis630_write(SMB_STS,0x10);
306 		} while(len < data->block[0]);
307 	}
308 
309 	sis630_transaction_end(adap, oldclock);
310 
311 	return rc;
312 }
313 
314 /* Return -1 on error. */
315 static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
316 			 unsigned short flags, char read_write,
317 			 u8 command, int size, union i2c_smbus_data *data)
318 {
319 	switch (size) {
320 		case I2C_SMBUS_QUICK:
321 			sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
322 			size = SIS630_QUICK;
323 			break;
324 		case I2C_SMBUS_BYTE:
325 			sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
326 			if (read_write == I2C_SMBUS_WRITE)
327 				sis630_write(SMB_CMD, command);
328 			size = SIS630_BYTE;
329 			break;
330 		case I2C_SMBUS_BYTE_DATA:
331 			sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
332 			sis630_write(SMB_CMD, command);
333 			if (read_write == I2C_SMBUS_WRITE)
334 				sis630_write(SMB_BYTE, data->byte);
335 			size = SIS630_BYTE_DATA;
336 			break;
337 		case I2C_SMBUS_PROC_CALL:
338 		case I2C_SMBUS_WORD_DATA:
339 			sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
340 			sis630_write(SMB_CMD, command);
341 			if (read_write == I2C_SMBUS_WRITE) {
342 				sis630_write(SMB_BYTE, data->word & 0xff);
343 				sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8);
344 			}
345 			size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
346 			break;
347 		case I2C_SMBUS_BLOCK_DATA:
348 			sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
349 			sis630_write(SMB_CMD, command);
350 			size = SIS630_BLOCK_DATA;
351 			return sis630_block_data(adap, data, read_write);
352 		default:
353 			printk("Unsupported I2C size\n");
354 			return -1;
355 			break;
356 	}
357 
358 	if (sis630_transaction(adap, size))
359 		return -1;
360 
361 	if ((size != SIS630_PCALL) &&
362 		((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
363 		return 0;
364 	}
365 
366 	switch(size) {
367 		case SIS630_BYTE:
368 		case SIS630_BYTE_DATA:
369 			data->byte = sis630_read(SMB_BYTE);
370 			break;
371 		case SIS630_PCALL:
372 		case SIS630_WORD_DATA:
373 			data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
374 			break;
375 		default:
376 			return -1;
377 			break;
378 	}
379 
380 	return 0;
381 }
382 
383 static u32 sis630_func(struct i2c_adapter *adapter)
384 {
385 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
386 		I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
387 		I2C_FUNC_SMBUS_BLOCK_DATA;
388 }
389 
390 static int sis630_setup(struct pci_dev *sis630_dev)
391 {
392 	unsigned char b;
393 	struct pci_dev *dummy = NULL;
394 	int retval = -ENODEV, i;
395 
396 	/* check for supported SiS devices */
397 	for (i=0; supported[i] > 0 ; i++) {
398 		if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy)))
399 			break; /* found */
400 	}
401 
402 	if (dummy) {
403 		pci_dev_put(dummy);
404 	}
405         else if (force) {
406 		dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
407 			"loading because of force option enabled\n");
408  	}
409 	else {
410 		return -ENODEV;
411 	}
412 
413 	/*
414 	   Enable ACPI first , so we can accsess reg 74-75
415 	   in acpi io space and read acpi base addr
416 	*/
417 	if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
418 		dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
419 		goto exit;
420 	}
421 	/* if ACPI already enabled , do nothing */
422 	if (!(b & 0x80) &&
423 	    pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
424 		dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
425 		goto exit;
426 	}
427 
428 	/* Determine the ACPI base address */
429 	if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
430 		dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
431 		goto exit;
432 	}
433 
434 	dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
435 
436 	/* Everything is happy, let's grab the memory and set things up. */
437 	if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
438 			    sis630_driver.name)) {
439 		dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
440 			"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
441 		goto exit;
442 	}
443 
444 	retval = 0;
445 
446 exit:
447 	if (retval)
448 		acpi_base = 0;
449 	return retval;
450 }
451 
452 
453 static const struct i2c_algorithm smbus_algorithm = {
454 	.smbus_xfer	= sis630_access,
455 	.functionality	= sis630_func,
456 };
457 
458 static struct i2c_adapter sis630_adapter = {
459 	.owner		= THIS_MODULE,
460 	.id		= I2C_HW_SMBUS_SIS630,
461 	.class		= I2C_CLASS_HWMON,
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 sysfs 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