1 /*
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
44 
45    Note: we assume there can only be one device, with one SMBus interface.
46 */
47 
48 #include <linux/kernel.h>
49 #include <linux/module.h>
50 #include <linux/delay.h>
51 #include <linux/pci.h>
52 #include <linux/ioport.h>
53 #include <linux/init.h>
54 #include <linux/i2c.h>
55 #include <linux/acpi.h>
56 #include <linux/io.h>
57 
58 /* SIS630 SMBus registers */
59 #define SMB_STS			0x80	/* status */
60 #define SMB_EN			0x81	/* status enable */
61 #define SMB_CNT			0x82
62 #define SMBHOST_CNT		0x83
63 #define SMB_ADDR		0x84
64 #define SMB_CMD			0x85
65 #define SMB_PCOUNT		0x86	/* processed count */
66 #define SMB_COUNT		0x87
67 #define SMB_BYTE		0x88	/* ~0x8F data byte field */
68 #define SMBDEV_ADDR		0x90
69 #define SMB_DB0			0x91
70 #define SMB_DB1			0x92
71 #define SMB_SAA			0x93
72 
73 /* register count for request_region */
74 #define SIS630_SMB_IOREGION	20
75 
76 /* PCI address constants */
77 /* acpi base address register  */
78 #define SIS630_ACPI_BASE_REG	0x74
79 /* bios control register */
80 #define SIS630_BIOS_CTL_REG	0x40
81 
82 /* Other settings */
83 #define MAX_TIMEOUT		500
84 
85 /* SIS630 constants */
86 #define SIS630_QUICK		0x00
87 #define SIS630_BYTE		0x01
88 #define SIS630_BYTE_DATA	0x02
89 #define SIS630_WORD_DATA	0x03
90 #define SIS630_PCALL		0x04
91 #define SIS630_BLOCK_DATA	0x05
92 
93 static struct pci_driver sis630_driver;
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;
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 
sis630_read(u8 reg)113 static inline u8 sis630_read(u8 reg)
114 {
115 	return inb(acpi_base + reg);
116 }
117 
sis630_write(u8 reg,u8 data)118 static inline void sis630_write(u8 reg, u8 data)
119 {
120 	outb(data, acpi_base + reg);
121 }
122 
sis630_transaction_start(struct i2c_adapter * adap,int size,u8 * oldclock)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 -EBUSY;
136                 } else {
137 			dev_dbg(&adap->dev, "Successful!\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 
sis630_transaction_wait(struct i2c_adapter * adap,int size)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 = -ETIMEDOUT;
179 	}
180 
181 	if (temp & 0x02) {
182 		dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
183 		result = -ENXIO;
184 	}
185 
186 	if (temp & 0x04) {
187 		dev_err(&adap->dev, "Bus collision!\n");
188 		result = -EIO;
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 
sis630_transaction_end(struct i2c_adapter * adap,u8 oldclock)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 
sis630_transaction(struct i2c_adapter * adap,int size)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 
sis630_block_data(struct i2c_adapter * adap,union i2c_smbus_data * data,int read_write)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 				rc = sis630_transaction_start(adap,
252 						SIS630_BLOCK_DATA, &oldclock);
253 				if (rc)
254 					return rc;
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 				rc = sis630_transaction_wait(adap,
268 						SIS630_BLOCK_DATA);
269 				if (rc) {
270 					dev_dbg(&adap->dev, "trans_wait failed\n");
271 					break;
272 				}
273 			}
274 		}
275 	}
276 	else {
277 		/* read request */
278 		data->block[0] = len = 0;
279 		rc = sis630_transaction_start(adap,
280 				SIS630_BLOCK_DATA, &oldclock);
281 		if (rc)
282 			return rc;
283 		do {
284 			rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
285 			if (rc) {
286 				dev_dbg(&adap->dev, "trans_wait failed\n");
287 				break;
288 			}
289 			/* if this first transaction then read byte count */
290 			if (len == 0)
291 				data->block[0] = sis630_read(SMB_COUNT);
292 
293 			/* just to be sure */
294 			if (data->block[0] > 32)
295 				data->block[0] = 32;
296 
297 			dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]);
298 
299 			for (i=0; i < 8 && len < data->block[0]; i++,len++) {
300 				dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len);
301 				data->block[len+1] = sis630_read(SMB_BYTE+i);
302 			}
303 
304 			dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
305 
306 			/* clear SMBARY_STS */
307 			sis630_write(SMB_STS,0x10);
308 		} while(len < data->block[0]);
309 	}
310 
311 	sis630_transaction_end(adap, oldclock);
312 
313 	return rc;
314 }
315 
316 /* Return negative errno on error. */
sis630_access(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)317 static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
318 			 unsigned short flags, char read_write,
319 			 u8 command, int size, union i2c_smbus_data *data)
320 {
321 	int status;
322 
323 	switch (size) {
324 		case I2C_SMBUS_QUICK:
325 			sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
326 			size = SIS630_QUICK;
327 			break;
328 		case I2C_SMBUS_BYTE:
329 			sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
330 			if (read_write == I2C_SMBUS_WRITE)
331 				sis630_write(SMB_CMD, command);
332 			size = SIS630_BYTE;
333 			break;
334 		case I2C_SMBUS_BYTE_DATA:
335 			sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
336 			sis630_write(SMB_CMD, command);
337 			if (read_write == I2C_SMBUS_WRITE)
338 				sis630_write(SMB_BYTE, data->byte);
339 			size = SIS630_BYTE_DATA;
340 			break;
341 		case I2C_SMBUS_PROC_CALL:
342 		case I2C_SMBUS_WORD_DATA:
343 			sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
344 			sis630_write(SMB_CMD, command);
345 			if (read_write == I2C_SMBUS_WRITE) {
346 				sis630_write(SMB_BYTE, data->word & 0xff);
347 				sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8);
348 			}
349 			size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
350 			break;
351 		case I2C_SMBUS_BLOCK_DATA:
352 			sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
353 			sis630_write(SMB_CMD, command);
354 			size = SIS630_BLOCK_DATA;
355 			return sis630_block_data(adap, data, read_write);
356 		default:
357 			dev_warn(&adap->dev, "Unsupported transaction %d\n",
358 				 size);
359 			return -EOPNOTSUPP;
360 	}
361 
362 	status = sis630_transaction(adap, size);
363 	if (status)
364 		return status;
365 
366 	if ((size != SIS630_PCALL) &&
367 		((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
368 		return 0;
369 	}
370 
371 	switch(size) {
372 		case SIS630_BYTE:
373 		case SIS630_BYTE_DATA:
374 			data->byte = sis630_read(SMB_BYTE);
375 			break;
376 		case SIS630_PCALL:
377 		case SIS630_WORD_DATA:
378 			data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
379 			break;
380 	}
381 
382 	return 0;
383 }
384 
sis630_func(struct i2c_adapter * adapter)385 static u32 sis630_func(struct i2c_adapter *adapter)
386 {
387 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
388 		I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
389 		I2C_FUNC_SMBUS_BLOCK_DATA;
390 }
391 
sis630_setup(struct pci_dev * sis630_dev)392 static int __devinit sis630_setup(struct pci_dev *sis630_dev)
393 {
394 	unsigned char b;
395 	struct pci_dev *dummy = NULL;
396 	int retval = -ENODEV, i;
397 
398 	/* check for supported SiS devices */
399 	for (i=0; supported[i] > 0 ; i++) {
400 		if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy)))
401 			break; /* found */
402 	}
403 
404 	if (dummy) {
405 		pci_dev_put(dummy);
406 	}
407         else if (force) {
408 		dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
409 			"loading because of force option enabled\n");
410  	}
411 	else {
412 		return -ENODEV;
413 	}
414 
415 	/*
416 	   Enable ACPI first , so we can accsess reg 74-75
417 	   in acpi io space and read acpi base addr
418 	*/
419 	if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
420 		dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
421 		goto exit;
422 	}
423 	/* if ACPI already enabled , do nothing */
424 	if (!(b & 0x80) &&
425 	    pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
426 		dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
427 		goto exit;
428 	}
429 
430 	/* Determine the ACPI base address */
431 	if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
432 		dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
433 		goto exit;
434 	}
435 
436 	dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
437 
438 	retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
439 				   sis630_driver.name);
440 	if (retval)
441 		goto exit;
442 
443 	/* Everything is happy, let's grab the memory and set things up. */
444 	if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
445 			    sis630_driver.name)) {
446 		dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
447 			"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
448 		goto exit;
449 	}
450 
451 	retval = 0;
452 
453 exit:
454 	if (retval)
455 		acpi_base = 0;
456 	return retval;
457 }
458 
459 
460 static const struct i2c_algorithm smbus_algorithm = {
461 	.smbus_xfer	= sis630_access,
462 	.functionality	= sis630_func,
463 };
464 
465 static struct i2c_adapter sis630_adapter = {
466 	.owner		= THIS_MODULE,
467 	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD,
468 	.algo		= &smbus_algorithm,
469 };
470 
471 static const struct pci_device_id sis630_ids[] __devinitconst = {
472 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
473 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
474 	{ 0, }
475 };
476 
477 MODULE_DEVICE_TABLE (pci, sis630_ids);
478 
sis630_probe(struct pci_dev * dev,const struct pci_device_id * id)479 static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
480 {
481 	if (sis630_setup(dev)) {
482 		dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
483 		return -ENODEV;
484 	}
485 
486 	/* set up the sysfs linkage to our parent device */
487 	sis630_adapter.dev.parent = &dev->dev;
488 
489 	snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
490 		 "SMBus SIS630 adapter at %04x", acpi_base + SMB_STS);
491 
492 	return i2c_add_adapter(&sis630_adapter);
493 }
494 
sis630_remove(struct pci_dev * dev)495 static void __devexit sis630_remove(struct pci_dev *dev)
496 {
497 	if (acpi_base) {
498 		i2c_del_adapter(&sis630_adapter);
499 		release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
500 		acpi_base = 0;
501 	}
502 }
503 
504 
505 static struct pci_driver sis630_driver = {
506 	.name		= "sis630_smbus",
507 	.id_table	= sis630_ids,
508 	.probe		= sis630_probe,
509 	.remove		= __devexit_p(sis630_remove),
510 };
511 
i2c_sis630_init(void)512 static int __init i2c_sis630_init(void)
513 {
514 	return pci_register_driver(&sis630_driver);
515 }
516 
517 
i2c_sis630_exit(void)518 static void __exit i2c_sis630_exit(void)
519 {
520 	pci_unregister_driver(&sis630_driver);
521 }
522 
523 
524 MODULE_LICENSE("GPL");
525 MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
526 MODULE_DESCRIPTION("SIS630 SMBus driver");
527 
528 module_init(i2c_sis630_init);
529 module_exit(i2c_sis630_exit);
530