From a81c69da0edda9f50da4d5b218723d0cf315a15e Mon Sep 17 00:00:00 2001 From: kfx Date: Tue, 23 Apr 2013 14:33:09 +0800 Subject: [PATCH] rk30: i2c: support 'I2C_M_TEN flag' --- drivers/i2c/busses/i2c-rk30-adapter.c | 94 +++++++++++++++++---------- drivers/i2c/busses/i2c-rk30.h | 1 + 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk30-adapter.c b/drivers/i2c/busses/i2c-rk30-adapter.c index cae8bde0aaf7..21503f5c172f 100755 --- a/drivers/i2c/busses/i2c-rk30-adapter.c +++ b/drivers/i2c/busses/i2c-rk30-adapter.c @@ -322,9 +322,11 @@ static void rk30_irq_write_prepare(struct rk30_i2c *i2c) for(j = 0; j < 4; j++) { if(is_msgend(i2c)) break; - if(i2c->msg_ptr == 0 && cnt == 0) - byte = (i2c->addr & 0x7f) << 1; - else + if((i2c->msg_ptr == 0) && (cnt == 0)) + byte = (i2c->addr_1st & 0x7f) << 1; + else if((i2c->msg_ptr == 0) && (cnt == 1) && (i2c->msg->flags & I2C_M_TEN)) + byte = i2c->addr_2nd; + else byte = i2c->msg->buf[i2c->msg_ptr++]; cnt++; data |= (byte << (j * 8)); @@ -341,7 +343,7 @@ static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd) case STATE_START: if(!(ipd & I2C_STARTIPD)){ rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%02x] no start irq in STATE_START\n", i2c->addr); + dev_err(i2c->dev, "Addr[0x%04x] no start irq in STATE_START\n", i2c->addr); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; @@ -361,7 +363,7 @@ static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd) case STATE_WRITE: if(!(ipd & I2C_MBTFIPD)){ rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%02x] no mbtf irq in STATE_WRITE\n", i2c->addr); + dev_err(i2c->dev, "Addr[0x%04x] no mbtf irq in STATE_WRITE\n", i2c->addr); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; @@ -374,7 +376,7 @@ prepare_write: case STATE_READ: if(!(ipd & I2C_MBRFIPD)){ rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%02x] no mbrf irq in STATE_READ, ipd = 0x%x\n", i2c->addr, ipd); + dev_err(i2c->dev, "Addr[0x%04x] no mbrf irq in STATE_READ, ipd = 0x%x\n", i2c->addr, ipd); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; @@ -388,7 +390,7 @@ prepare_read: case STATE_STOP: if(!(ipd & I2C_STOPIPD)){ rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%02x] no stop irq in STATE_STOP\n", i2c->addr); + dev_err(i2c->dev, "Addr[0x%04x] no stop irq in STATE_STOP\n", i2c->addr); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; @@ -414,7 +416,7 @@ static irqreturn_t rk30_i2c_irq(int irq, void *dev_id) spin_lock(&i2c->lock); ipd = i2c_readl(i2c->regs + I2C_IPD); if(i2c->state == STATE_IDLE){ - dev_info(i2c->dev, "Addr[0x%02x] irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd); + dev_info(i2c->dev, "Addr[0x%04x] irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; } @@ -433,9 +435,9 @@ out: static int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int num) { - unsigned int addr = (msgs[0].addr & 0x7f) << 1; unsigned int reg_valid_bits = 0; unsigned int reg_addr = 0; + unsigned int addr = (i2c->addr_1st << 1) | 1; if(num == 1) { i2c->count = msgs[0].len; @@ -444,7 +446,6 @@ static int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int n i2c->mode = I2C_CON_MOD_TX; } else { - addr |= 1; i2c->msg = &msgs[0]; i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); i2c_writel(0, i2c->regs + I2C_MRXRADDR); @@ -454,24 +455,39 @@ static int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int n } else if(num == 2) { i2c->count = msgs[1].len; - switch(msgs[0].len){ - case 1: - reg_addr = msgs[0].buf[0]; - reg_valid_bits |= I2C_MRXADDR_LOW; + + if(msgs[0].flags & I2C_M_TEN){ + switch(msgs[0].len){ + case 1: + reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8); + reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; + break; + case 2: + reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8) | (msgs[0].buf[1] << 16); + reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; + break; + default: + return -EIO; + } + }else{ + switch(msgs[0].len){ + case 1: + reg_addr = msgs[0].buf[0]; + reg_valid_bits |= I2C_MRXADDR_LOW; break; - case 2: - reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; - break; - case 3: - reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8) | (msgs[0].buf[2] << 16); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; - break; - default: - return -EIO; - } + case 2: + reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8); + reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; + break; + case 3: + reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8) | (msgs[0].buf[2] << 16); + reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; + break; + default: + return -EIO; + } + } if((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { - addr |= 1; i2c->msg = &msgs[1]; i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); @@ -516,12 +532,22 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c, } spin_lock_irqsave(&i2c->lock, flags); + i2c->addr = msgs[0].addr; + if(msgs[0].flags & I2C_M_TEN){ + i2c->addr_1st = ((i2c->addr & 0x0300)>>8) | 0x78; + i2c->addr_2nd = i2c->addr & 0x00ff; + }else{ + i2c->addr_1st = i2c->addr & 0x007f; + i2c->addr_2nd = 0; + } + i2c_dbg(i2c->dev, "addr: 0x%04x, addr_1st: 0x%02x, addr_2nd: 0x%02x\n", + i2c->addr, i2c->addr_1st, i2c->addr_2nd); + if(rk30_i2c_set_master(i2c, msgs, num) < 0){ spin_unlock_irqrestore(&i2c->lock, flags); - dev_err(i2c->dev, "addr[0x%02x] set master error\n", msgs[0].addr); + dev_err(i2c->dev, "addr[0x%04x] set master error\n", msgs[0].addr); return -EIO; } - i2c->addr = msgs[0].addr; i2c->msg_ptr = 0; i2c->error = 0; i2c->is_busy = 1; @@ -549,7 +575,7 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c, if(error < 0) i2c_dbg(i2c->dev, "error = %d\n", error); else if((i2c->complete_what !=COMPLETE_READ && i2c->complete_what != COMPLETE_WRITE)){ - dev_err(i2c->dev, "Addr[0x%02x] wait event timeout, state: %d, is_busy: %d, error: %d, complete_what: 0x%x, ipd: 0x%x\n", + dev_err(i2c->dev, "Addr[0x%04x] wait event timeout, state: %d, is_busy: %d, error: %d, complete_what: 0x%x, ipd: 0x%x\n", msgs[0].addr, i2c->state, i2c->is_busy, error, i2c->complete_what, i2c_readl(i2c->regs + I2C_IPD)); //rk30_show_regs(i2c); error = -ETIMEDOUT; @@ -571,7 +597,7 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c, rk30_i2c_disable(i2c); if(error == -EAGAIN) - i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%02x) not exist or abnormal power-on\n", + i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%04x) not exist or abnormal power-on\n", i2c->complete_what, i2c->addr); return error; } @@ -606,12 +632,12 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap, if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000) scl_rate = msgs[0].scl_rate; else if(msgs[0].scl_rate > 400000){ - dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too high!", + dev_warn(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too high!", msgs[0].addr, msgs[0].scl_rate/1000); scl_rate = 400000; } else{ - dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too low!", + dev_warn(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too low!", msgs[0].addr, msgs[0].scl_rate/1000); scl_rate = 10000; } @@ -620,9 +646,9 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap, } rk30_i2c_set_clk(i2c, scl_rate); - i2c_dbg(i2c->dev, "i2c transfer start: addr: 0x%x, scl_reate: %ldKhz, len: %d\n", msgs[0].addr, scl_rate/1000, num); + i2c_dbg(i2c->dev, "i2c transfer start: addr: 0x%04x, scl_reate: %ldKhz, len: %d\n", msgs[0].addr, scl_rate/1000, num); ret = rk30_i2c_doxfer(i2c, msgs, num); - i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state); + i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%04x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state); if(i2c->is_div_from_arm[i2c->adap.nr]){ mutex_unlock(&i2c->m_lock); diff --git a/drivers/i2c/busses/i2c-rk30.h b/drivers/i2c/busses/i2c-rk30.h index 0cb6d9e35a2b..13b5c559569f 100755 --- a/drivers/i2c/busses/i2c-rk30.h +++ b/drivers/i2c/busses/i2c-rk30.h @@ -96,6 +96,7 @@ struct rk30_i2c { unsigned long scl_rate; unsigned long i2c_rate; unsigned int addr; + unsigned char addr_1st, addr_2nd; unsigned int mode; unsigned int count; -- 2.34.1