diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-ali1535.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-ali1535.c | 121 | 
1 files changed, 62 insertions, 59 deletions
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 906a3ca50db..451e305f797 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -1,23 +1,23 @@  /* -    Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>,  -                        Philip Edelbrock <phil@netroedge.com>,  -                        Mark D. Studebaker <mdsxyz123@yahoo.com>, -                        Dan Eaton <dan.eaton@rocketlogix.com> and  -                        Stephen Rousset<stephen.rousset@rocketlogix.com>  - -    This program is free software; you can redistribute it and/or modify -    it under the terms of the GNU General Public License as published by -    the Free Software Foundation; either version 2 of the License, or -    (at your option) any later version. - -    This program is distributed in the hope that it will be useful, -    but WITHOUT ANY WARRANTY; without even the implied warranty of -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -    GNU General Public License for more details. - -    You should have received a copy of the GNU General Public License -    along with this program; if not, write to the Free Software -    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>, + *                      Philip Edelbrock <phil@netroedge.com>, + *                      Mark D. Studebaker <mdsxyz123@yahoo.com>, + *                      Dan Eaton <dan.eaton@rocketlogix.com> and + *                      Stephen Rousset <stephen.rousset@rocketlogix.com> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */  /* @@ -58,7 +58,6 @@  #include <linux/delay.h>  #include <linux/ioport.h>  #include <linux/i2c.h> -#include <linux/init.h>  #include <linux/acpi.h>  #include <linux/io.h> @@ -132,15 +131,16 @@  #define	ALI1535_SMBIO_EN	0x04	/* SMB I/O Space enable		*/  static struct pci_driver ali1535_driver; -static unsigned short ali1535_smba; +static unsigned long ali1535_smba; +static unsigned short ali1535_offset;  /* Detect whether a ALI1535 can be found, and initialize it, where necessary.     Note the differences between kernels with the old PCI BIOS interface and     newer kernels with the real PCI interface. In compat.h some things are     defined to make the transition easier. */ -static int __devinit ali1535_setup(struct pci_dev *dev) +static int ali1535_setup(struct pci_dev *dev)  { -	int retval = -ENODEV; +	int retval;  	unsigned char temp;  	/* Check the following things: @@ -149,15 +149,28 @@ static int __devinit ali1535_setup(struct pci_dev *dev)  		- We can use the addresses  	*/ +	retval = pci_enable_device(dev); +	if (retval) { +		dev_err(&dev->dev, "ALI1535_smb can't enable device\n"); +		goto exit; +	} +  	/* Determine the address of the SMBus area */ -	pci_read_config_word(dev, SMBBA, &ali1535_smba); -	ali1535_smba &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1)); -	if (ali1535_smba == 0) { +	pci_read_config_word(dev, SMBBA, &ali1535_offset); +	dev_dbg(&dev->dev, "ALI1535_smb is at offset 0x%04x\n", ali1535_offset); +	ali1535_offset &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1)); +	if (ali1535_offset == 0) {  		dev_warn(&dev->dev,  			"ALI1535_smb region uninitialized - upgrade BIOS?\n"); +		retval = -ENODEV;  		goto exit;  	} +	if (pci_resource_flags(dev, 0) & IORESOURCE_IO) +		ali1535_smba = pci_resource_start(dev, 0) + ali1535_offset; +	else +		ali1535_smba = ali1535_offset; +  	retval = acpi_check_region(ali1535_smba, ALI1535_SMB_IOSIZE,  				   ali1535_driver.name);  	if (retval) @@ -165,8 +178,9 @@ static int __devinit ali1535_setup(struct pci_dev *dev)  	if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,  			    ali1535_driver.name)) { -		dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n", +		dev_err(&dev->dev, "ALI1535_smb region 0x%lx already in use!\n",  			ali1535_smba); +		retval = -EBUSY;  		goto exit;  	} @@ -174,6 +188,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)  	pci_read_config_byte(dev, SMBCFG, &temp);  	if ((temp & ALI1535_SMBIO_EN) == 0) {  		dev_err(&dev->dev, "SMB device not enabled - upgrade BIOS?\n"); +		retval = -ENODEV;  		goto exit_free;  	} @@ -181,6 +196,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)  	pci_read_config_byte(dev, SMBHSTCFG, &temp);  	if ((temp & 1) == 0) {  		dev_err(&dev->dev, "SMBus controller not enabled - upgrade BIOS?\n"); +		retval = -ENODEV;  		goto exit_free;  	} @@ -196,14 +212,13 @@ static int __devinit ali1535_setup(struct pci_dev *dev)  	*/  	pci_read_config_byte(dev, SMBREV, &temp);  	dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); -	dev_dbg(&dev->dev, "ALI1535_smba = 0x%X\n", ali1535_smba); +	dev_dbg(&dev->dev, "ALI1535_smba = 0x%lx\n", ali1535_smba); -	retval = 0; -exit: -	return retval; +	return 0;  exit_free:  	release_region(ali1535_smba, ALI1535_SMB_IOSIZE); +exit:  	return retval;  } @@ -254,8 +269,8 @@ static int ali1535_transaction(struct i2c_adapter *adap)  	if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {  		/* do a clear-on-write */  		outb_p(0xFF, SMBHSTSTS); -		if ((temp = inb_p(SMBHSTSTS)) & -		    (ALI1535_STS_ERR | ALI1535_STS_BUSY)) { +		temp = inb_p(SMBHSTSTS); +		if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) {  			/* This is probably going to be correctable only by a  			 * power reset as one of the bits now appears to be  			 * stuck */ @@ -267,9 +282,8 @@ static int ali1535_transaction(struct i2c_adapter *adap)  		}  	} else {  		/* check and clear done bit */ -		if (temp & ALI1535_STS_DONE) { +		if (temp & ALI1535_STS_DONE)  			outb_p(temp, SMBHSTSTS); -		}  	}  	/* start the transaction by writing anything to the start register */ @@ -278,7 +292,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)  	/* We will always wait for a fraction of a second! */  	timeout = 0;  	do { -		msleep(1); +		usleep_range(1000, 2000);  		temp = inb_p(SMBHSTSTS);  	} while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE))  		 && (timeout++ < MAX_TIMEOUT)); @@ -295,7 +309,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)  	}  	/* Unfortunately the ALI SMB controller maps "no response" and "bus -	 * collision" into a single bit. No reponse is the usual case so don't +	 * collision" into a single bit. No response is the usual case so don't  	 * do a printk.  This means that bus collisions go unreported.  	 */  	if (temp & ALI1535_STS_BUSERR) { @@ -325,12 +339,12 @@ static int ali1535_transaction(struct i2c_adapter *adap)  	/* take consequent actions for error conditions */  	if (!(temp & ALI1535_STS_DONE)) {  		/* issue "kill" to reset host controller */ -		outb_p(ALI1535_KILL,SMBHSTTYP); -		outb_p(0xFF,SMBHSTSTS); +		outb_p(ALI1535_KILL, SMBHSTTYP); +		outb_p(0xFF, SMBHSTSTS);  	} else if (temp & ALI1535_STS_ERR) {  		/* issue "timeout" to reset all devices on bus */ -		outb_p(ALI1535_T_OUT,SMBHSTTYP); -		outb_p(0xFF,SMBHSTSTS); +		outb_p(ALI1535_T_OUT, SMBHSTTYP); +		outb_p(0xFF, SMBHSTSTS);  	}  	return result; @@ -351,7 +365,7 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,  	for (timeout = 0;  	     (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE);  	     timeout++) { -		msleep(1); +		usleep_range(1000, 2000);  		temp = inb_p(SMBHSTSTS);  	}  	if (timeout >= MAX_TIMEOUT) @@ -485,9 +499,9 @@ static const struct pci_device_id ali1535_ids[] = {  	{ },  }; -MODULE_DEVICE_TABLE (pci, ali1535_ids); +MODULE_DEVICE_TABLE(pci, ali1535_ids); -static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)  {  	if (ali1535_setup(dev)) {  		dev_warn(&dev->dev, @@ -499,11 +513,11 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_  	ali1535_adapter.dev.parent = &dev->dev;  	snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name), -		"SMBus ALI1535 adapter at %04x", ali1535_smba); +		"SMBus ALI1535 adapter at %04x", ali1535_offset);  	return i2c_add_adapter(&ali1535_adapter);  } -static void __devexit ali1535_remove(struct pci_dev *dev) +static void ali1535_remove(struct pci_dev *dev)  {  	i2c_del_adapter(&ali1535_adapter);  	release_region(ali1535_smba, ALI1535_SMB_IOSIZE); @@ -513,18 +527,10 @@ static struct pci_driver ali1535_driver = {  	.name		= "ali1535_smbus",  	.id_table	= ali1535_ids,  	.probe		= ali1535_probe, -	.remove		= __devexit_p(ali1535_remove), +	.remove		= ali1535_remove,  }; -static int __init i2c_ali1535_init(void) -{ -	return pci_register_driver(&ali1535_driver); -} - -static void __exit i2c_ali1535_exit(void) -{ -	pci_unregister_driver(&ali1535_driver); -} +module_pci_driver(ali1535_driver);  MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "  	      "Philip Edelbrock <phil@netroedge.com>, " @@ -532,6 +538,3 @@ MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "  	      "and Dan Eaton <dan.eaton@rocketlogix.com>");  MODULE_DESCRIPTION("ALI1535 SMBus driver");  MODULE_LICENSE("GPL"); - -module_init(i2c_ali1535_init); -module_exit(i2c_ali1535_exit);  | 
