diff options
Diffstat (limited to 'drivers/i2c/algos')
| -rw-r--r-- | drivers/i2c/algos/Kconfig | 14 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-bit.c | 100 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pca.c | 45 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pcf.c | 4 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pcf.h | 3 | 
5 files changed, 91 insertions, 75 deletions
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index 3998dd620a0..f1cfe7e5508 100644 --- a/drivers/i2c/algos/Kconfig +++ b/drivers/i2c/algos/Kconfig @@ -3,7 +3,7 @@  #  menu "I2C Algorithms" -	depends on !I2C_HELPER_AUTO +	visible if !I2C_HELPER_AUTO  config I2C_ALGOBIT  	tristate "I2C bit-banging interfaces" @@ -15,15 +15,3 @@ config I2C_ALGOPCA  	tristate "I2C PCA 9564 interfaces"  endmenu - -# In automatic configuration mode, we still have to define the -# symbols to avoid unmet dependencies. - -if I2C_HELPER_AUTO -config I2C_ALGOBIT -	tristate -config I2C_ALGOPCF -	tristate -config I2C_ALGOPCA -	tristate -endif diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index a39e6cff86e..65ef9664d5d 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -15,16 +15,16 @@      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. +    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +    MA 02110-1301 USA.   * ------------------------------------------------------------------------- */  /* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki -   <kmalkki@cc.hut.fi> and Jean Delvare <khali@linux-fr.org> */ +   <kmalkki@cc.hut.fi> and Jean Delvare <jdelvare@suse.de> */  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/delay.h> -#include <linux/init.h>  #include <linux/errno.h>  #include <linux/sched.h>  #include <linux/i2c.h> @@ -47,8 +47,8 @@  /* ----- global variables ---------------------------------------------	*/  static int bit_test;	/* see if the line-setting functions work	*/ -module_param(bit_test, bool, 0); -MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck"); +module_param(bit_test, int, S_IRUGO); +MODULE_PARM_DESC(bit_test, "lines testing - 0 off; 1 report; 2 fail if stuck");  #ifdef DEBUG  static int i2c_debug = 1; @@ -103,9 +103,15 @@ static int sclhi(struct i2c_algo_bit_data *adap)  		 * chips may hold it low ("clock stretching") while they  		 * are processing data internally.  		 */ -		if (time_after(jiffies, start + adap->timeout)) +		if (time_after(jiffies, start + adap->timeout)) { +			/* Test one last time, as we may have been preempted +			 * between last check and timeout test. +			 */ +			if (getscl(adap)) +				break;  			return -ETIMEDOUT; -		cond_resched(); +		} +		cpu_relax();  	}  #ifdef DEBUG  	if (jiffies != start && i2c_debug >= 3) @@ -232,9 +238,17 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)   * Sanity check for the adapter hardware - check the reaction of   * the bus lines only if it seems to be idle.   */ -static int test_bus(struct i2c_algo_bit_data *adap, char *name) +static int test_bus(struct i2c_adapter *i2c_adap)  { -	int scl, sda; +	struct i2c_algo_bit_data *adap = i2c_adap->algo_data; +	const char *name = i2c_adap->name; +	int scl, sda, ret; + +	if (adap->pre_xfer) { +		ret = adap->pre_xfer(i2c_adap); +		if (ret < 0) +			return -ENODEV; +	}  	if (adap->getscl == NULL)  		pr_info("%s: Testing SDA only, SCL is not readable\n", name); @@ -242,7 +256,9 @@ static int test_bus(struct i2c_algo_bit_data *adap, char *name)  	sda = getsda(adap);  	scl = (adap->getscl == NULL) ? 1 : getscl(adap);  	if (!scl || !sda) { -		printk(KERN_WARNING "%s: bus seems to be busy\n", name); +		printk(KERN_WARNING +		       "%s: bus seems to be busy (scl=%d, sda=%d)\n", +		       name, scl, sda);  		goto bailout;  	} @@ -297,11 +313,19 @@ static int test_bus(struct i2c_algo_bit_data *adap, char *name)  		       "while pulling SCL high!\n", name);  		goto bailout;  	} + +	if (adap->post_xfer) +		adap->post_xfer(i2c_adap); +  	pr_info("%s: Test OK\n", name);  	return 0;  bailout:  	sdahi(adap);  	sclhi(adap); + +	if (adap->post_xfer) +		adap->post_xfer(i2c_adap); +  	return -ENODEV;  } @@ -425,7 +449,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)  					acknak(i2c_adap, 0);  				dev_err(&i2c_adap->dev, "readbytes: invalid "  					"block length (%d)\n", inval); -				return -EREMOTEIO; +				return -EPROTO;  			}  			/* The original count value accounts for the extra  			   bytes, that is, either 1 for a regular transaction, @@ -454,7 +478,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)   * reads, writes as well as 10bit-addresses.   * returns:   *  0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set - * -x an error occurred (like: -EREMOTEIO if the device did not answer, or + * -x an error occurred (like: -ENXIO if the device did not answer, or   *	-ETIMEDOUT, for example if the lines are stuck...)   */  static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) @@ -470,21 +494,21 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)  	if (flags & I2C_M_TEN) {  		/* a ten bit address */ -		addr = 0xf0 | ((msg->addr >> 7) & 0x03); +		addr = 0xf0 | ((msg->addr >> 7) & 0x06);  		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);  		/* try extended address code...*/  		ret = try_address(i2c_adap, addr, retries);  		if ((ret != 1) && !nak_ok)  {  			dev_err(&i2c_adap->dev,  				"died at extended address code\n"); -			return -EREMOTEIO; +			return -ENXIO;  		}  		/* the remaining 8 bit address */ -		ret = i2c_outb(i2c_adap, msg->addr & 0x7f); +		ret = i2c_outb(i2c_adap, msg->addr & 0xff);  		if ((ret != 1) && !nak_ok) {  			/* the chip did not ack / xmission error occurred */  			dev_err(&i2c_adap->dev, "died at 2nd address code\n"); -			return -EREMOTEIO; +			return -ENXIO;  		}  		if (flags & I2C_M_RD) {  			bit_dbg(3, &i2c_adap->dev, "emitting repeated " @@ -496,7 +520,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)  			if ((ret != 1) && !nak_ok) {  				dev_err(&i2c_adap->dev,  					"died at repeated address code\n"); -				return -EREMOTEIO; +				return -EIO;  			}  		}  	} else {		/* normal 7bit address	*/ @@ -554,7 +578,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,  					ret, ret == 1 ? "" : "s");  			if (ret < pmsg->len) {  				if (ret >= 0) -					ret = -EREMOTEIO; +					ret = -EIO;  				goto bailout;  			}  		} else { @@ -565,7 +589,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,  					ret, ret == 1 ? "" : "s");  			if (ret < pmsg->len) {  				if (ret >= 0) -					ret = -EREMOTEIO; +					ret = -EIO;  				goto bailout;  			}  		} @@ -583,7 +607,7 @@ bailout:  static u32 bit_func(struct i2c_adapter *adap)  { -	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | +	return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |  	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |  	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |  	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; @@ -592,21 +616,24 @@ static u32 bit_func(struct i2c_adapter *adap)  /* -----exported algorithm data: -------------------------------------	*/ -static const struct i2c_algorithm i2c_bit_algo = { +const struct i2c_algorithm i2c_bit_algo = {  	.master_xfer	= bit_xfer,  	.functionality	= bit_func,  }; +EXPORT_SYMBOL(i2c_bit_algo);  /*   * registering functions to load algorithms at runtime   */ -static int i2c_bit_prepare_bus(struct i2c_adapter *adap) +static int __i2c_bit_add_bus(struct i2c_adapter *adap, +			     int (*add_adapter)(struct i2c_adapter *))  {  	struct i2c_algo_bit_data *bit_adap = adap->algo_data; +	int ret;  	if (bit_test) { -		int ret = test_bus(bit_adap, adap->name); -		if (ret < 0) +		ret = test_bus(adap); +		if (bit_test >= 2 && ret < 0)  			return -ENODEV;  	} @@ -614,30 +641,27 @@ static int i2c_bit_prepare_bus(struct i2c_adapter *adap)  	adap->algo = &i2c_bit_algo;  	adap->retries = 3; +	ret = add_adapter(adap); +	if (ret < 0) +		return ret; + +	/* Complain if SCL can't be read */ +	if (bit_adap->getscl == NULL) { +		dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n"); +		dev_warn(&adap->dev, "Bus may be unreliable\n"); +	}  	return 0;  }  int i2c_bit_add_bus(struct i2c_adapter *adap)  { -	int err; - -	err = i2c_bit_prepare_bus(adap); -	if (err) -		return err; - -	return i2c_add_adapter(adap); +	return __i2c_bit_add_bus(adap, i2c_add_adapter);  }  EXPORT_SYMBOL(i2c_bit_add_bus);  int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)  { -	int err; - -	err = i2c_bit_prepare_bus(adap); -	if (err) -		return err; - -	return i2c_add_numbered_adapter(adap); +	return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter);  }  EXPORT_SYMBOL(i2c_bit_add_numbered_bus); diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 2b9a8f54bb2..8b10f88b13d 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -15,7 +15,8 @@   *   *  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. + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + *  MA 02110-1301 USA.   */  #include <linux/kernel.h> @@ -23,7 +24,6 @@  #include <linux/moduleparam.h>  #include <linux/delay.h>  #include <linux/jiffies.h> -#include <linux/init.h>  #include <linux/errno.h>  #include <linux/i2c.h>  #include <linux/i2c-algo-pca.h> @@ -45,14 +45,19 @@ static int i2c_debug;  #define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)  #define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)  #define pca_wait(adap) adap->wait_for_completion(adap->data) -#define pca_reset(adap) adap->reset_chip(adap->data) -static void pca9665_reset(void *pd) +static void pca_reset(struct i2c_algo_pca_data *adap)  { -	struct i2c_algo_pca_data *adap = pd; -	pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET); -	pca_outw(adap, I2C_PCA_IND, 0xA5); -	pca_outw(adap, I2C_PCA_IND, 0x5A); +	if (adap->chip == I2C_PCA_CHIP_9665) { +		/* Ignore the reset function from the module, +		 * we can use the parallel bus reset. +		 */ +		pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET); +		pca_outw(adap, I2C_PCA_IND, 0xA5); +		pca_outw(adap, I2C_PCA_IND, 0x5A); +	} else { +		adap->reset_chip(adap->data); +	}  }  /* @@ -196,7 +201,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,  		} else {  			dev_dbg(&i2c_adap->dev, "bus is not idle. status is "  				"%#04x\n", state); -			return -EAGAIN; +			return -EBUSY;  		}  	} @@ -224,7 +229,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,  	}  	curmsg = 0; -	ret = -EREMOTEIO; +	ret = -EIO;  	while (curmsg < num) {  		state = pca_status(adap); @@ -259,6 +264,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,  		case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */  			DEB2("NOT ACK received after SLA+W\n");  			pca_stop(adap); +			ret = -ENXIO;  			goto out;  		case 0x40: /* SLA+R has been transmitted; ACK has been received */ @@ -283,6 +289,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,  		case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */  			DEB2("NOT ACK received after SLA+R\n");  			pca_stop(adap); +			ret = -ENXIO;  			goto out;  		case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */ @@ -343,7 +350,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,  	ret = curmsg;   out: -	DEB1("}}} transfered %d/%d messages. " +	DEB1("}}} transferred %d/%d messages. "  	     "status is %#04x. control is %#04x\n",  	     curmsg, num, pca_status(adap),  	     pca_get_con(adap)); @@ -375,11 +382,12 @@ static unsigned int pca_probe_chip(struct i2c_adapter *adap)  	pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR);  	if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) {  		printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name); -		return I2C_PCA_CHIP_9665; +		pca_data->chip = I2C_PCA_CHIP_9665;  	} else {  		printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name); -		return I2C_PCA_CHIP_9564; +		pca_data->chip = I2C_PCA_CHIP_9564;  	} +	return pca_data->chip;  }  static int pca_init(struct i2c_adapter *adap) @@ -453,11 +461,6 @@ static int pca_init(struct i2c_adapter *adap)  		 */  		int raise_fall_time; -		/* Ignore the reset function from the module, -		 * we can use the parallel bus reset -		 */ -		pca_data->reset_chip = pca9665_reset; -  		if (pca_data->i2c_clock > 1265800) {  			printk(KERN_WARNING "%s: I2C clock speed too high."  				" Using 1265.8kHz.\n", adap->name); @@ -473,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap)  		/* To avoid integer overflow, use clock/100 for calculations */  		clock = pca_clock(pca_data) / 100; -		if (pca_data->i2c_clock > 10000) { +		if (pca_data->i2c_clock > 1000000) {  			mode = I2C_PCA_MODE_TURBO;  			min_tlow = 14;  			min_thi  = 5;  			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ -		} else if (pca_data->i2c_clock > 4000) { +		} else if (pca_data->i2c_clock > 400000) {  			mode = I2C_PCA_MODE_FASTP;  			min_tlow = 17;  			min_thi  = 9;  			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ -		} else if (pca_data->i2c_clock > 1000) { +		} else if (pca_data->i2c_clock > 100000) {  			mode = I2C_PCA_MODE_FAST;  			min_tlow = 44;  			min_thi  = 20; diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 5eebf562ff3..34370090b75 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -16,7 +16,8 @@   *   *  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. + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + *  MA 02110-1301 USA.   *   * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and   * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey @@ -29,7 +30,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/delay.h> -#include <linux/init.h>  #include <linux/errno.h>  #include <linux/i2c.h>  #include <linux/i2c-algo-pcf.h> diff --git a/drivers/i2c/algos/i2c-algo-pcf.h b/drivers/i2c/algos/i2c-algo-pcf.h index 5263a9eeb8d..1ec703ee788 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.h +++ b/drivers/i2c/algos/i2c-algo-pcf.h @@ -16,7 +16,8 @@      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.		*/ +    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +    MA 02110-1301 USA.							*/  /* --------------------------------------------------------------------	*/  /* With some changes from Frodo Looijaard <frodol@dds.nl> */  | 
