• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/i2c/busses/
1/*
2    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
3    Philip Edelbrock <phil@netroedge.com>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20/* Note: we assume there can only be one SIS5595 with one SMBus interface */
21
22/*
23   Note: all have mfr. ID 0x1039.
24   SUPPORTED		PCI ID
25	5595		0008
26
27   Note: these chips contain a 0008 device which is incompatible with the
28         5595. We recognize these by the presence of the listed
29         "blacklist" PCI ID and refuse to load.
30
31   NOT SUPPORTED	PCI ID		BLACKLIST PCI ID
32	 540		0008		0540
33	 550		0008		0550
34	5513		0008		5511
35	5581		0008		5597
36	5582		0008		5597
37	5597		0008		5597
38	5598		0008		5597/5598
39	 630		0008		0630
40	 645		0008		0645
41	 646		0008		0646
42	 648		0008		0648
43	 650		0008		0650
44	 651		0008		0651
45	 730		0008		0730
46	 735		0008		0735
47	 745		0008		0745
48	 746		0008		0746
49*/
50
51/* TO DO:
52 * Add Block Transfers (ugly, but supported by the adapter)
53 * Add adapter resets
54 */
55
56#include <linux/kernel.h>
57#include <linux/module.h>
58#include <linux/delay.h>
59#include <linux/pci.h>
60#include <linux/ioport.h>
61#include <linux/init.h>
62#include <linux/i2c.h>
63#include <linux/acpi.h>
64#include <linux/io.h>
65
66static int blacklist[] = {
67	PCI_DEVICE_ID_SI_540,
68	PCI_DEVICE_ID_SI_550,
69	PCI_DEVICE_ID_SI_630,
70	PCI_DEVICE_ID_SI_645,
71	PCI_DEVICE_ID_SI_646,
72	PCI_DEVICE_ID_SI_648,
73	PCI_DEVICE_ID_SI_650,
74	PCI_DEVICE_ID_SI_651,
75	PCI_DEVICE_ID_SI_730,
76	PCI_DEVICE_ID_SI_735,
77	PCI_DEVICE_ID_SI_745,
78	PCI_DEVICE_ID_SI_746,
79	PCI_DEVICE_ID_SI_5511,	/* 5513 chip has the 0008 device but that ID
80				   shows up in other chips so we use the 5511
81				   ID for recognition */
82	PCI_DEVICE_ID_SI_5597,
83	PCI_DEVICE_ID_SI_5598,
84	0,			/* terminates the list */
85};
86
87/* Length of ISA address segment */
88#define SIS5595_EXTENT		8
89/* SIS5595 SMBus registers */
90#define SMB_STS_LO		0x00
91#define SMB_STS_HI		0x01
92#define SMB_CTL_LO		0x02
93#define SMB_CTL_HI		0x03
94#define SMB_ADDR		0x04
95#define SMB_CMD			0x05
96#define SMB_PCNT		0x06
97#define SMB_CNT			0x07
98#define SMB_BYTE		0x08
99#define SMB_DEV			0x10
100#define SMB_DB0			0x11
101#define SMB_DB1			0x12
102#define SMB_HAA			0x13
103
104/* PCI Address Constants */
105#define SMB_INDEX		0x38
106#define SMB_DAT			0x39
107#define SIS5595_ENABLE_REG	0x40
108#define ACPI_BASE		0x90
109
110/* Other settings */
111#define MAX_TIMEOUT		500
112
113/* SIS5595 constants */
114#define SIS5595_QUICK		0x00
115#define SIS5595_BYTE		0x02
116#define SIS5595_BYTE_DATA	0x04
117#define SIS5595_WORD_DATA	0x06
118#define SIS5595_PROC_CALL	0x08
119#define SIS5595_BLOCK_DATA	0x0A
120
121/* insmod parameters */
122
123/* If force_addr is set to anything different from 0, we forcibly enable
124   the device at the given address. */
125static u16 force_addr;
126module_param(force_addr, ushort, 0);
127MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
128
129static struct pci_driver sis5595_driver;
130static unsigned short sis5595_base;
131static struct pci_dev *sis5595_pdev;
132
133static u8 sis5595_read(u8 reg)
134{
135	outb(reg, sis5595_base + SMB_INDEX);
136	return inb(sis5595_base + SMB_DAT);
137}
138
139static void sis5595_write(u8 reg, u8 data)
140{
141	outb(reg, sis5595_base + SMB_INDEX);
142	outb(data, sis5595_base + SMB_DAT);
143}
144
145static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
146{
147	u16 a;
148	u8 val;
149	int *i;
150	int retval = -ENODEV;
151
152	/* Look for imposters */
153	for (i = blacklist; *i != 0; i++) {
154		struct pci_dev *dev;
155		dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
156		if (dev) {
157			dev_err(&SIS5595_dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
158			pci_dev_put(dev);
159			return -ENODEV;
160		}
161	}
162
163	/* Determine the address of the SMBus areas */
164	pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base);
165	if (sis5595_base == 0 && force_addr == 0) {
166		dev_err(&SIS5595_dev->dev, "ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
167		return -ENODEV;
168	}
169
170	if (force_addr)
171		sis5595_base = force_addr & ~(SIS5595_EXTENT - 1);
172	dev_dbg(&SIS5595_dev->dev, "ACPI Base address: %04x\n", sis5595_base);
173
174	/* NB: We grab just the two SMBus registers here, but this may still
175	 * interfere with ACPI :-(  */
176	retval = acpi_check_region(sis5595_base + SMB_INDEX, 2,
177				   sis5595_driver.name);
178	if (retval)
179		return retval;
180
181	if (!request_region(sis5595_base + SMB_INDEX, 2,
182			    sis5595_driver.name)) {
183		dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
184			sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
185		return -ENODEV;
186	}
187
188	if (force_addr) {
189		dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base);
190		if (pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base)
191		    != PCIBIOS_SUCCESSFUL)
192			goto error;
193		if (pci_read_config_word(SIS5595_dev, ACPI_BASE, &a)
194		    != PCIBIOS_SUCCESSFUL)
195			goto error;
196		if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) {
197			/* doesn't work for some chips! */
198			dev_err(&SIS5595_dev->dev, "force address failed - not supported?\n");
199			goto error;
200		}
201	}
202
203	if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
204	    != PCIBIOS_SUCCESSFUL)
205		goto error;
206	if ((val & 0x80) == 0) {
207		dev_info(&SIS5595_dev->dev, "enabling ACPI\n");
208		if (pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80)
209		    != PCIBIOS_SUCCESSFUL)
210			goto error;
211		if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
212		    != PCIBIOS_SUCCESSFUL)
213			goto error;
214		if ((val & 0x80) == 0) {
215			/* doesn't work for some chips? */
216			dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n");
217			goto error;
218		}
219	}
220
221	/* Everything is happy */
222	return 0;
223
224error:
225	release_region(sis5595_base + SMB_INDEX, 2);
226	return retval;
227}
228
229static int sis5595_transaction(struct i2c_adapter *adap)
230{
231	int temp;
232	int result = 0;
233	int timeout = 0;
234
235	/* Make sure the SMBus host is ready to start transmitting */
236	temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
237	if (temp != 0x00) {
238		dev_dbg(&adap->dev, "SMBus busy (%04x). Resetting...\n", temp);
239		sis5595_write(SMB_STS_LO, temp & 0xff);
240		sis5595_write(SMB_STS_HI, temp >> 8);
241		if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
242			dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
243			return -EBUSY;
244		} else {
245			dev_dbg(&adap->dev, "Successful!\n");
246		}
247	}
248
249	/* start the transaction by setting bit 4 */
250	sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
251
252	/* We will always wait for a fraction of a second! */
253	do {
254		msleep(1);
255		temp = sis5595_read(SMB_STS_LO);
256	} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
257
258	/* If the SMBus is still busy, we give up */
259	if (timeout > MAX_TIMEOUT) {
260		dev_dbg(&adap->dev, "SMBus Timeout!\n");
261		result = -ETIMEDOUT;
262	}
263
264	if (temp & 0x10) {
265		dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
266		result = -ENXIO;
267	}
268
269	if (temp & 0x20) {
270		dev_err(&adap->dev, "Bus collision! SMBus may be locked until "
271			"next hard reset (or not...)\n");
272		/* Clock stops and slave is stuck in mid-transmission */
273		result = -EIO;
274	}
275
276	temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
277	if (temp != 0x00) {
278		sis5595_write(SMB_STS_LO, temp & 0xff);
279		sis5595_write(SMB_STS_HI, temp >> 8);
280	}
281
282	temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
283	if (temp != 0x00)
284		dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp);
285
286	return result;
287}
288
289/* Return negative errno on error. */
290static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
291			  unsigned short flags, char read_write,
292			  u8 command, int size, union i2c_smbus_data *data)
293{
294	int status;
295
296	switch (size) {
297	case I2C_SMBUS_QUICK:
298		sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
299		size = SIS5595_QUICK;
300		break;
301	case I2C_SMBUS_BYTE:
302		sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
303		if (read_write == I2C_SMBUS_WRITE)
304			sis5595_write(SMB_CMD, command);
305		size = SIS5595_BYTE;
306		break;
307	case I2C_SMBUS_BYTE_DATA:
308		sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
309		sis5595_write(SMB_CMD, command);
310		if (read_write == I2C_SMBUS_WRITE)
311			sis5595_write(SMB_BYTE, data->byte);
312		size = SIS5595_BYTE_DATA;
313		break;
314	case I2C_SMBUS_PROC_CALL:
315	case I2C_SMBUS_WORD_DATA:
316		sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
317		sis5595_write(SMB_CMD, command);
318		if (read_write == I2C_SMBUS_WRITE) {
319			sis5595_write(SMB_BYTE, data->word & 0xff);
320			sis5595_write(SMB_BYTE + 1,
321				      (data->word & 0xff00) >> 8);
322		}
323		size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA;
324		break;
325	default:
326		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
327		return -EOPNOTSUPP;
328	}
329
330	sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
331
332	status = sis5595_transaction(adap);
333	if (status)
334		return status;
335
336	if ((size != SIS5595_PROC_CALL) &&
337	    ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
338		return 0;
339
340
341	switch (size) {
342	case SIS5595_BYTE:
343	case SIS5595_BYTE_DATA:
344		data->byte = sis5595_read(SMB_BYTE);
345		break;
346	case SIS5595_WORD_DATA:
347	case SIS5595_PROC_CALL:
348		data->word = sis5595_read(SMB_BYTE) + (sis5595_read(SMB_BYTE + 1) << 8);
349		break;
350	}
351	return 0;
352}
353
354static u32 sis5595_func(struct i2c_adapter *adapter)
355{
356	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
357	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
358	    I2C_FUNC_SMBUS_PROC_CALL;
359}
360
361static const struct i2c_algorithm smbus_algorithm = {
362	.smbus_xfer	= sis5595_access,
363	.functionality	= sis5595_func,
364};
365
366static struct i2c_adapter sis5595_adapter = {
367	.owner		= THIS_MODULE,
368	.class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
369	.algo		= &smbus_algorithm,
370};
371
372static const struct pci_device_id sis5595_ids[] __devinitconst = {
373	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
374	{ 0, }
375};
376
377MODULE_DEVICE_TABLE (pci, sis5595_ids);
378
379static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
380{
381	int err;
382
383	if (sis5595_setup(dev)) {
384		dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n");
385		return -ENODEV;
386	}
387
388	/* set up the sysfs linkage to our parent device */
389	sis5595_adapter.dev.parent = &dev->dev;
390
391	snprintf(sis5595_adapter.name, sizeof(sis5595_adapter.name),
392		 "SMBus SIS5595 adapter at %04x", sis5595_base + SMB_INDEX);
393	err = i2c_add_adapter(&sis5595_adapter);
394	if (err) {
395		release_region(sis5595_base + SMB_INDEX, 2);
396		return err;
397	}
398
399	/* Always return failure here.  This is to allow other drivers to bind
400	 * to this pci device.  We don't really want to have control over the
401	 * pci device, we only wanted to read as few register values from it.
402	 */
403	sis5595_pdev =  pci_dev_get(dev);
404	return -ENODEV;
405}
406
407static struct pci_driver sis5595_driver = {
408	.name		= "sis5595_smbus",
409	.id_table	= sis5595_ids,
410	.probe		= sis5595_probe,
411};
412
413static int __init i2c_sis5595_init(void)
414{
415	return pci_register_driver(&sis5595_driver);
416}
417
418static void __exit i2c_sis5595_exit(void)
419{
420	pci_unregister_driver(&sis5595_driver);
421	if (sis5595_pdev) {
422		i2c_del_adapter(&sis5595_adapter);
423		release_region(sis5595_base + SMB_INDEX, 2);
424		pci_dev_put(sis5595_pdev);
425		sis5595_pdev = NULL;
426	}
427}
428
429MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
430MODULE_DESCRIPTION("SIS5595 SMBus driver");
431MODULE_LICENSE("GPL");
432
433module_init(i2c_sis5595_init);
434module_exit(i2c_sis5595_exit);
435