xref: /openbmc/linux/drivers/i2c/busses/i2c-sis630.c (revision 8fdff1dc)
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 bool high_clock;
97 static bool 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 
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 -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 
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 
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 				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. */
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 
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 
392 static int sis630_setup(struct pci_dev *sis630_dev)
393 {
394 	unsigned char b;
395 	struct pci_dev *dummy = NULL;
396 	int retval, 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 		retval = -ENODEV;
422 		goto exit;
423 	}
424 	/* if ACPI already enabled , do nothing */
425 	if (!(b & 0x80) &&
426 	    pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
427 		dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
428 		retval = -ENODEV;
429 		goto exit;
430 	}
431 
432 	/* Determine the ACPI base address */
433 	if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
434 		dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
435 		retval = -ENODEV;
436 		goto exit;
437 	}
438 
439 	dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
440 
441 	retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
442 				   sis630_driver.name);
443 	if (retval)
444 		goto exit;
445 
446 	/* Everything is happy, let's grab the memory and set things up. */
447 	if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
448 			    sis630_driver.name)) {
449 		dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
450 			"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
451 		retval = -EBUSY;
452 		goto exit;
453 	}
454 
455 	retval = 0;
456 
457 exit:
458 	if (retval)
459 		acpi_base = 0;
460 	return retval;
461 }
462 
463 
464 static const struct i2c_algorithm smbus_algorithm = {
465 	.smbus_xfer	= sis630_access,
466 	.functionality	= sis630_func,
467 };
468 
469 static struct i2c_adapter sis630_adapter = {
470 	.owner		= THIS_MODULE,
471 	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD,
472 	.algo		= &smbus_algorithm,
473 };
474 
475 static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = {
476 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
477 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
478 	{ 0, }
479 };
480 
481 MODULE_DEVICE_TABLE (pci, sis630_ids);
482 
483 static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
484 {
485 	if (sis630_setup(dev)) {
486 		dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
487 		return -ENODEV;
488 	}
489 
490 	/* set up the sysfs linkage to our parent device */
491 	sis630_adapter.dev.parent = &dev->dev;
492 
493 	snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
494 		 "SMBus SIS630 adapter at %04x", acpi_base + SMB_STS);
495 
496 	return i2c_add_adapter(&sis630_adapter);
497 }
498 
499 static void sis630_remove(struct pci_dev *dev)
500 {
501 	if (acpi_base) {
502 		i2c_del_adapter(&sis630_adapter);
503 		release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
504 		acpi_base = 0;
505 	}
506 }
507 
508 
509 static struct pci_driver sis630_driver = {
510 	.name		= "sis630_smbus",
511 	.id_table	= sis630_ids,
512 	.probe		= sis630_probe,
513 	.remove		= sis630_remove,
514 };
515 
516 module_pci_driver(sis630_driver);
517 
518 MODULE_LICENSE("GPL");
519 MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
520 MODULE_DESCRIPTION("SIS630 SMBus driver");
521