PageRenderTime 37ms CodeModel.GetById 18ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/i2c/busses/i2c-sis5595.c

https://bitbucket.org/evzijst/gittest
C | 424 lines | 286 code | 53 blank | 85 comment | 56 complexity | 70d0083d24e9c77d6c8fd5ecff098ac5 MD5 | raw file
  1/*
  2    sis5595.c - Part of lm_sensors, Linux kernel modules for hardware
  3              monitoring
  4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
  5    Philip Edelbrock <phil@netroedge.com>
  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/* Note: we assume there can only be one SIS5595 with one SMBus interface */
 23
 24/*
 25   Note: all have mfr. ID 0x1039.
 26   SUPPORTED		PCI ID		
 27	5595		0008
 28
 29   Note: these chips contain a 0008 device which is incompatible with the
 30         5595. We recognize these by the presence of the listed
 31         "blacklist" PCI ID and refuse to load.
 32
 33   NOT SUPPORTED	PCI ID		BLACKLIST PCI ID	
 34	 540		0008		0540
 35	 550		0008		0550
 36	5513		0008		5511
 37	5581		0008		5597
 38	5582		0008		5597
 39	5597		0008		5597
 40	5598		0008		5597/5598
 41	 630		0008		0630
 42	 645		0008		0645
 43	 646		0008		0646
 44	 648		0008		0648
 45	 650		0008		0650
 46	 651		0008		0651
 47	 730		0008		0730
 48	 735		0008		0735
 49	 745		0008		0745
 50	 746		0008		0746
 51*/
 52
 53/* TO DO: 
 54 * Add Block Transfers (ugly, but supported by the adapter)
 55 * Add adapter resets
 56 */
 57
 58#include <linux/config.h>
 59#include <linux/kernel.h>
 60#include <linux/module.h>
 61#include <linux/delay.h>
 62#include <linux/pci.h>
 63#include <linux/ioport.h>
 64#include <linux/init.h>
 65#include <linux/i2c.h>
 66#include <asm/io.h>
 67
 68static int blacklist[] = {
 69	PCI_DEVICE_ID_SI_540,
 70	PCI_DEVICE_ID_SI_550,
 71	PCI_DEVICE_ID_SI_630,
 72	PCI_DEVICE_ID_SI_645,
 73	PCI_DEVICE_ID_SI_646,
 74	PCI_DEVICE_ID_SI_648,
 75	PCI_DEVICE_ID_SI_650,
 76	PCI_DEVICE_ID_SI_651,
 77	PCI_DEVICE_ID_SI_730,
 78	PCI_DEVICE_ID_SI_735,
 79	PCI_DEVICE_ID_SI_745,
 80	PCI_DEVICE_ID_SI_746,
 81	PCI_DEVICE_ID_SI_5511,	/* 5513 chip has the 0008 device but that ID
 82				   shows up in other chips so we use the 5511
 83				   ID for recognition */
 84	PCI_DEVICE_ID_SI_5597,
 85	PCI_DEVICE_ID_SI_5598,
 86	0,			/* terminates the list */
 87};
 88
 89/* Length of ISA address segment */
 90#define SIS5595_EXTENT		8
 91/* SIS5595 SMBus registers */
 92#define SMB_STS_LO		0x00
 93#define SMB_STS_HI		0x01
 94#define SMB_CTL_LO		0x02
 95#define SMB_CTL_HI		0x03
 96#define SMB_ADDR		0x04
 97#define SMB_CMD			0x05
 98#define SMB_PCNT		0x06
 99#define SMB_CNT			0x07
100#define SMB_BYTE		0x08
101#define SMB_DEV			0x10
102#define SMB_DB0			0x11
103#define SMB_DB1			0x12
104#define SMB_HAA			0x13
105
106/* PCI Address Constants */
107#define SMB_INDEX		0x38
108#define SMB_DAT			0x39
109#define SIS5595_ENABLE_REG	0x40
110#define ACPI_BASE		0x90
111
112/* Other settings */
113#define MAX_TIMEOUT		500
114
115/* SIS5595 constants */
116#define SIS5595_QUICK		0x00
117#define SIS5595_BYTE		0x02
118#define SIS5595_BYTE_DATA	0x04
119#define SIS5595_WORD_DATA	0x06
120#define SIS5595_PROC_CALL	0x08
121#define SIS5595_BLOCK_DATA	0x0A
122
123/* insmod parameters */
124
125/* If force_addr is set to anything different from 0, we forcibly enable
126   the device at the given address. */
127static u16 force_addr = 0;
128module_param(force_addr, ushort, 0);
129MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
130
131static unsigned short sis5595_base = 0;
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 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	if (!request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus")) {
177		dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
178			sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
179		return -ENODEV;
180	}
181
182	if (force_addr) {
183		dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base);
184		if (pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base)
185		    != PCIBIOS_SUCCESSFUL)
186			goto error;
187		if (pci_read_config_word(SIS5595_dev, ACPI_BASE, &a)
188		    != PCIBIOS_SUCCESSFUL)
189			goto error;
190		if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) {
191			/* doesn't work for some chips! */
192			dev_err(&SIS5595_dev->dev, "force address failed - not supported?\n");
193			goto error;
194		}
195	}
196
197	if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
198	    != PCIBIOS_SUCCESSFUL)
199		goto error;
200	if ((val & 0x80) == 0) {
201		dev_info(&SIS5595_dev->dev, "enabling ACPI\n");
202		if (pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80)
203		    != PCIBIOS_SUCCESSFUL)
204			goto error;
205		if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
206		    != PCIBIOS_SUCCESSFUL)
207			goto error;
208		if ((val & 0x80) == 0) {
209			/* doesn't work for some chips? */
210			dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n");
211			goto error;
212		}
213	}
214
215	/* Everything is happy */
216	return 0;
217
218error:
219	release_region(sis5595_base + SMB_INDEX, 2);
220	return retval;
221}
222
223static int sis5595_transaction(struct i2c_adapter *adap)
224{
225	int temp;
226	int result = 0;
227	int timeout = 0;
228
229	/* Make sure the SMBus host is ready to start transmitting */
230	temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
231	if (temp != 0x00) {
232		dev_dbg(&adap->dev, "SMBus busy (%04x). Resetting... \n", temp);
233		sis5595_write(SMB_STS_LO, temp & 0xff);
234		sis5595_write(SMB_STS_HI, temp >> 8);
235		if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
236			dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
237			return -1;
238		} else {
239			dev_dbg(&adap->dev, "Successfull!\n");
240		}
241	}
242
243	/* start the transaction by setting bit 4 */
244	sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
245
246	/* We will always wait for a fraction of a second! */
247	do {
248		msleep(1);
249		temp = sis5595_read(SMB_STS_LO);
250	} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
251
252	/* If the SMBus is still busy, we give up */
253	if (timeout >= MAX_TIMEOUT) {
254		dev_dbg(&adap->dev, "SMBus Timeout!\n");
255		result = -1;
256	}
257
258	if (temp & 0x10) {
259		dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
260		result = -1;
261	}
262
263	if (temp & 0x20) {
264		dev_err(&adap->dev, "Bus collision! SMBus may be locked until "
265			"next hard reset (or not...)\n");
266		/* Clock stops and slave is stuck in mid-transmission */
267		result = -1;
268	}
269
270	temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
271	if (temp != 0x00) {
272		sis5595_write(SMB_STS_LO, temp & 0xff);
273		sis5595_write(SMB_STS_HI, temp >> 8);
274	}
275
276	temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
277	if (temp != 0x00)
278		dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp);
279
280	return result;
281}
282
283/* Return -1 on error. */
284static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
285			  unsigned short flags, char read_write,
286			  u8 command, int size, union i2c_smbus_data *data)
287{
288	switch (size) {
289	case I2C_SMBUS_QUICK:
290		sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
291		size = SIS5595_QUICK;
292		break;
293	case I2C_SMBUS_BYTE:
294		sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
295		if (read_write == I2C_SMBUS_WRITE)
296			sis5595_write(SMB_CMD, command);
297		size = SIS5595_BYTE;
298		break;
299	case I2C_SMBUS_BYTE_DATA:
300		sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
301		sis5595_write(SMB_CMD, command);
302		if (read_write == I2C_SMBUS_WRITE)
303			sis5595_write(SMB_BYTE, data->byte);
304		size = SIS5595_BYTE_DATA;
305		break;
306	case I2C_SMBUS_PROC_CALL:
307	case I2C_SMBUS_WORD_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->word & 0xff);
312			sis5595_write(SMB_BYTE + 1,
313				      (data->word & 0xff00) >> 8);
314		}
315		size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA;
316		break;
317/*
318	case I2C_SMBUS_BLOCK_DATA:
319		printk(KERN_WARNING "sis5595.o: Block data not yet implemented!\n");
320		return -1;
321		break;
322*/
323	default:
324		printk(KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size);
325		return -1;
326	}
327
328	sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
329
330	if (sis5595_transaction(adap))
331		return -1;
332
333	if ((size != SIS5595_PROC_CALL) &&
334	    ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
335		return 0;
336
337
338	switch (size) {
339	case SIS5595_BYTE:	/* Where is the result put? I assume here it is in
340				   SMB_DATA but it might just as well be in the
341				   SMB_CMD. No clue in the docs */
342	case SIS5595_BYTE_DATA:
343		data->byte = sis5595_read(SMB_BYTE);
344		break;
345	case SIS5595_WORD_DATA:
346	case SIS5595_PROC_CALL:
347		data->word = sis5595_read(SMB_BYTE) + (sis5595_read(SMB_BYTE + 1) << 8);
348		break;
349	}
350	return 0;
351}
352
353static u32 sis5595_func(struct i2c_adapter *adapter)
354{
355	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
356	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
357	    I2C_FUNC_SMBUS_PROC_CALL;
358}
359
360static struct i2c_algorithm smbus_algorithm = {
361	.name		= "Non-I2C SMBus adapter",
362	.id		= I2C_ALGO_SMBUS,
363	.smbus_xfer	= sis5595_access,
364	.functionality	= sis5595_func,
365};
366
367static struct i2c_adapter sis5595_adapter = {
368	.owner		= THIS_MODULE,
369	.class          = I2C_CLASS_HWMON,
370	.name		= "unset",
371	.algo		= &smbus_algorithm,
372};
373
374static struct pci_device_id sis5595_ids[] __devinitdata = {
375	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, 
376	{ 0, }
377};
378
379MODULE_DEVICE_TABLE (pci, sis5595_ids);
380
381static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
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 driverfs linkage to our parent device */
389	sis5595_adapter.dev.parent = &dev->dev;
390
391	sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
392		sis5595_base + SMB_INDEX);
393	return i2c_add_adapter(&sis5595_adapter);
394}
395
396static void __devexit sis5595_remove(struct pci_dev *dev)
397{
398	i2c_del_adapter(&sis5595_adapter);
399	release_region(sis5595_base + SMB_INDEX, 2);
400}
401
402static struct pci_driver sis5595_driver = {
403	.name		= "sis5595_smbus",
404	.id_table	= sis5595_ids,
405	.probe		= sis5595_probe,
406	.remove		= __devexit_p(sis5595_remove),
407};
408
409static int __init i2c_sis5595_init(void)
410{
411	return pci_register_driver(&sis5595_driver);
412}
413
414static void __exit i2c_sis5595_exit(void)
415{
416	pci_unregister_driver(&sis5595_driver);
417}
418
419MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
420MODULE_DESCRIPTION("SIS5595 SMBus driver");
421MODULE_LICENSE("GPL");
422
423module_init(i2c_sis5595_init);
424module_exit(i2c_sis5595_exit);