diff options
Diffstat (limited to 'drivers/i2c/algos')
| -rw-r--r-- | drivers/i2c/algos/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/i2c/algos/Makefile | 4 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-bit.c | 110 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pca.c | 83 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pcf.c | 7 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pcf.h | 3 |
6 files changed, 120 insertions, 89 deletions
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index 7b2ce4a0852..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" diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile index 18b3e962ec0..215303f60d6 100644 --- a/drivers/i2c/algos/Makefile +++ b/drivers/i2c/algos/Makefile @@ -6,6 +6,4 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o -ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_ALGO) := -DDEBUG diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index e25e13980af..65ef9664d5d 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -15,17 +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/slab.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/i2c.h> @@ -48,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; @@ -104,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) @@ -233,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); @@ -243,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; } @@ -298,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; } @@ -426,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, @@ -455,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) @@ -471,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 " @@ -497,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 */ @@ -522,6 +545,12 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, int i, ret; unsigned short nak_ok; + if (adap->pre_xfer) { + ret = adap->pre_xfer(i2c_adap); + if (ret < 0) + return ret; + } + bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); i2c_start(adap); for (i = 0; i < num; i++) { @@ -549,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 { @@ -560,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; } } @@ -570,12 +599,15 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, bailout: bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); i2c_stop(adap); + + if (adap->post_xfer) + adap->post_xfer(i2c_adap); return ret; } 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; @@ -584,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; } @@ -606,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 78d42aae008..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); + } } /* @@ -109,13 +114,13 @@ static void pca_stop(struct i2c_algo_pca_data *adap) * returns after the address has been sent */ static int pca_address(struct i2c_algo_pca_data *adap, - struct i2c_msg *msg) + struct i2c_msg *msg) { int sta = pca_get_con(adap); int addr; - addr = ( (0x7f & msg->addr) << 1 ); - if (msg->flags & I2C_M_RD ) + addr = ((0x7f & msg->addr) << 1); + if (msg->flags & I2C_M_RD) addr |= 1; DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n", msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr); @@ -134,7 +139,7 @@ static int pca_address(struct i2c_algo_pca_data *adap, * Returns after the byte has been transmitted */ static int pca_tx_byte(struct i2c_algo_pca_data *adap, - __u8 b) + __u8 b) { int sta = pca_get_con(adap); DEB2("=== WRITE %#04x\n", b); @@ -164,13 +169,13 @@ static void pca_rx_byte(struct i2c_algo_pca_data *adap, * Returns after next byte has arrived. */ static int pca_rx_ack(struct i2c_algo_pca_data *adap, - int ack) + int ack) { int sta = pca_get_con(adap); sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI|I2C_PCA_CON_AA); - if ( ack ) + if (ack) sta |= I2C_PCA_CON_AA; pca_set_con(adap, sta); @@ -178,12 +183,12 @@ static int pca_rx_ack(struct i2c_algo_pca_data *adap, } static int pca_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, - int num) + struct i2c_msg *msgs, + int num) { - struct i2c_algo_pca_data *adap = i2c_adap->algo_data; - struct i2c_msg *msg = NULL; - int curmsg; + struct i2c_algo_pca_data *adap = i2c_adap->algo_data; + struct i2c_msg *msg = NULL; + int curmsg; int numbytes = 0; int state; int ret; @@ -196,27 +201,27 @@ 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; } } DEB1("{{{ XFER %d messages\n", num); - if (i2c_debug>=2) { + if (i2c_debug >= 2) { for (curmsg = 0; curmsg < num; curmsg++) { int addr, i; msg = &msgs[curmsg]; addr = (0x7f & msg->addr) ; - if (msg->flags & I2C_M_RD ) + if (msg->flags & I2C_M_RD) printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n", - curmsg, msg->len, addr, (addr<<1) | 1); + curmsg, msg->len, addr, (addr << 1) | 1); else { printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s", - curmsg, msg->len, addr, addr<<1, + curmsg, msg->len, addr, addr << 1, msg->len == 0 ? "" : ", "); - for(i=0; i < msg->len; i++) + for (i = 0; i < msg->len; i++) printk("%#04x%s", msg->buf[i], i == msg->len - 1 ? "" : ", "); printk("]\n"); } @@ -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 */ @@ -305,7 +312,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, goto out; case 0x58: /* Data byte has been received; NOT ACK has been returned */ - if ( numbytes == msg->len - 1 ) { + if (numbytes == msg->len - 1) { pca_rx_byte(adap, &msg->buf[numbytes], 0); curmsg++; numbytes = 0; if (curmsg == num) @@ -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)); @@ -352,7 +359,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, static u32 pca_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } static const struct i2c_algorithm pca_algo = { @@ -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,13 +461,6 @@ static int pca_init(struct i2c_adapter *adap) */ int raise_fall_time; - struct i2c_algo_pca_data *pca_data = adap->algo_data; - - /* 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); @@ -475,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 7ce75775ec7..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,8 +30,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/slab.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/i2c.h> #include <linux/i2c-algo-pcf.h> @@ -176,7 +175,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) */ if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) { DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp)); - return -ENXIO; /* definetly not PCF8584 */ + return -ENXIO; /* definitely not PCF8584 */ } /* load own address in S0, effective address is (own << 1) */ 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> */ |
