aboutsummaryrefslogtreecommitdiff
path: root/drivers/i2c/algos/i2c-algo-pca.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/algos/i2c-algo-pca.c')
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c83
1 files changed, 42 insertions, 41 deletions
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;