From 33fa2791543e4196156f39ab6378f5652564d544 Mon Sep 17 00:00:00 2001 From: kfx Date: Sat, 24 Mar 2012 18:06:46 +0800 Subject: [PATCH] rk30: i2c: update i2c drivers for touch screen --- drivers/i2c/busses/i2c-rk30-adapter.c | 598 ++++++++++++++------------ drivers/i2c/busses/i2c-rk30.h | 3 +- drivers/i2c/i2c-core.c | 2 +- 3 files changed, 321 insertions(+), 282 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk30-adapter.c b/drivers/i2c/busses/i2c-rk30-adapter.c index c0e773cb827e..ffb053e3067d 100755 --- a/drivers/i2c/busses/i2c-rk30-adapter.c +++ b/drivers/i2c/busses/i2c-rk30-adapter.c @@ -15,167 +15,178 @@ #include "i2c-rk30.h" /* Control register */ -#define I2C_CON 0X000 +#define I2C_CON 0x000 +#define I2C_CON_EN (1 << 0) +#define I2C_CON_MOD(mod) ((mod) << 1) +#define I2C_CON_MASK (3 << 1) enum{ - I2C_EN_BIT = 0, - I2C_MOD_BIT = 1, - I2C_START_BIT = 3, - I2C_STOP_BIT = 4, - I2C_LAST_ACK_BIT = 5, - I2C_ACT2ACK_BIT = 6, + I2C_CON_MOD_TX = 0, + I2C_CON_MOD_TRX, + I2C_CON_MOD_RX, + I2C_CON_MOD_RRX, }; -//send ACK to slave when the last byte received in RX only mode -#define LAST_SEND_ACK 0 -//send NAK to slave when the last byte received in RX only mode -#define LAST_SEND_NAK 1 -#define LAST_SEND_TYPE LAST_SEND_ACK //LAST_SEND_NAK +#define I2C_CON_START (1 << 3) +#define I2C_CON_STOP (1 << 4) +#define I2C_CON_LASTACK (1 << 5) +#define I2C_CON_ACTACK (1 << 6) -#define I2C_MOD_MASK (3 << I2C_MOD_BIT) -enum{ - I2C_MOD_TX = 0, - I2C_MOD_TRX, - I2C_MOD_RX, - I2C_MOD_RRX, -}; /* Clock dividor register */ -#define I2C_CLKDIV 0x004 +#define I2C_CLKDIV 0x004 #define I2C_CLKDIV_VAL(divl, divh) (((divl) & 0xffff) | (((divh) << 16) & 0xffff0000)) + /* the slave address accessed for master rx mode */ -#define I2C_MRXADDR 0x008 -#define I2C_MRXADDR_LOW (1 << 24) -#define I2C_MRXADDR_MID (1 << 25) -#define I2C_MRXADDR_HIGH (1 << 26) +#define I2C_MRXADDR 0x008 +#define I2C_MRXADDR_LOW (1 << 24) +#define I2C_MRXADDR_MID (1 << 25) +#define I2C_MRXADDR_HIGH (1 << 26) + /* the slave register address accessed for master rx mode */ -#define I2C_MRXRADDR 0x00c -#define I2C_MRXRADDR_LOW (1 << 24) -#define I2C_MRXRADDR_MID (1 << 25) -#define I2C_MRXRADDR_HIGH (1 << 26) +#define I2C_MRXRADDR 0x00c +#define I2C_MRXRADDR_LOW (1 << 24) +#define I2C_MRXRADDR_MID (1 << 25) +#define I2C_MRXRADDR_HIGH (1 << 26) + /* master tx count */ -#define I2C_MTXCNT 0x010 +#define I2C_MTXCNT 0x010 + /* master rx count */ -#define I2C_MRXCNT 0x014 +#define I2C_MRXCNT 0x014 + /* interrupt enable register */ -#define I2C_IEN 0x018 -#define I2C_BTFIEN (1 << 0) -#define I2C_BRFIEN (1 << 1) -#define I2C_MBTFIEN (1 << 2) -#define I2C_MBRFIEN (1 << 3) -#define I2C_STARTIEN (1 << 4) -#define I2C_STOPIEN (1 << 5) -#define I2C_NAKRCVIEN (1 << 6) -#define IRQ_MST_ENABLE (I2C_MBTFIEN | I2C_MBRFIEN | I2C_NAKRCVIEN | I2C_STARTIEN | I2C_STOPIEN) -#define IRQ_ALL_DISABLE 0 +#define I2C_IEN 0x018 +#define I2C_BTFIEN (1 << 0) +#define I2C_BRFIEN (1 << 1) +#define I2C_MBTFIEN (1 << 2) +#define I2C_MBRFIEN (1 << 3) +#define I2C_STARTIEN (1 << 4) +#define I2C_STOPIEN (1 << 5) +#define I2C_NAKRCVIEN (1 << 6) +#define IRQ_MST_ENABLE (I2C_MBTFIEN | I2C_MBRFIEN | I2C_NAKRCVIEN | I2C_STARTIEN | I2C_STOPIEN) +#define IRQ_ALL_DISABLE 0 + /* interrupt pending register */ -#define I2C_IPD 0x01c -#define I2C_BTFIPD (1 << 0) -#define I2C_BRFIPD (1 << 1) -#define I2C_MBTFIPD (1 << 2) -#define I2C_MBRFIPD (1 << 3) -#define I2C_STARTIPD (1 << 4) -#define I2C_STOPIPD (1 << 5) -#define I2C_NAKRCVIPD (1 << 6) +#define I2C_IPD 0x01c +#define I2C_BTFIPD (1 << 0) +#define I2C_BRFIPD (1 << 1) +#define I2C_MBTFIPD (1 << 2) +#define I2C_MBRFIPD (1 << 3) +#define I2C_STARTIPD (1 << 4) +#define I2C_STOPIPD (1 << 5) +#define I2C_NAKRCVIPD (1 << 6) +#define I2C_IPD_ALL_CLEAN 0x7f + /* finished count */ -#define I2C_FCNT 0x020 +#define I2C_FCNT 0x020 + /* I2C tx data register */ -#define I2C_TXDATA_BASE 0X100 +#define I2C_TXDATA_BASE 0X100 + /* I2C rx data register */ -#define I2C_RXDATA_BASE 0x200 +#define I2C_RXDATA_BASE 0x200 + + static void rk30_show_regs(struct rk30_i2c *i2c) { - i2c_dbg(i2c->dev, "I2C_CON: 0x%08x\n", readl(i2c->regs + I2C_CON)); - i2c_dbg(i2c->dev, "I2C_CLKDIV: 0x%08x\n", readl(i2c->regs + I2C_CLKDIV)); - i2c_dbg(i2c->dev, "I2C_MRXADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXADDR)); - i2c_dbg(i2c->dev, "I2C_MRXRADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXRADDR)); - i2c_dbg(i2c->dev, "I2C_MTXCNT: 0x%08x\n", readl(i2c->regs + I2C_MTXCNT)); - i2c_dbg(i2c->dev, "I2C_MRXCNT: 0x%08x\n", readl(i2c->regs + I2C_MRXCNT)); - i2c_dbg(i2c->dev, "I2C_IEN: 0x%08x\n", readl(i2c->regs + I2C_IEN)); - i2c_dbg(i2c->dev, "I2C_IPD: 0x%08x\n", readl(i2c->regs + I2C_IPD)); - i2c_dbg(i2c->dev, "I2C_FCNT: 0x%08x\n", readl(i2c->regs + I2C_FCNT)); - i2c_dbg(i2c->dev, "I2C_TXDATA0: 0x%08x\n", readl(i2c->regs + I2C_TXDATA_BASE + 0)); - i2c_dbg(i2c->dev, "I2C_RXDATA0: 0x%08x\n", readl(i2c->regs + I2C_RXDATA_BASE + 0)); + int i; + i2c_dbg(i2c->dev, "i2c->start = %d\n", i2c->state); + i2c_dbg(i2c->dev, "I2C_CON: 0x%08x\n", readl(i2c->regs + I2C_CON)); + i2c_dbg(i2c->dev, "I2C_CLKDIV: 0x%08x\n", readl(i2c->regs + I2C_CLKDIV)); + i2c_dbg(i2c->dev, "I2C_MRXADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXADDR)); + i2c_dbg(i2c->dev, "I2C_MRXRADDR: 0x%08x\n", readl(i2c->regs + I2C_MRXRADDR)); + i2c_dbg(i2c->dev, "I2C_MTXCNT: 0x%08x\n", readl(i2c->regs + I2C_MTXCNT)); + i2c_dbg(i2c->dev, "I2C_MRXCNT: 0x%08x\n", readl(i2c->regs + I2C_MRXCNT)); + i2c_dbg(i2c->dev, "I2C_IEN: 0x%08x\n", readl(i2c->regs + I2C_IEN)); + i2c_dbg(i2c->dev, "I2C_IPD: 0x%08x\n", readl(i2c->regs + I2C_IPD)); + i2c_dbg(i2c->dev, "I2C_FCNT: 0x%08x\n", readl(i2c->regs + I2C_FCNT)); + for( i = 0; i < 8; i ++) + i2c_dbg(i2c->dev, "I2C_TXDATA%d: 0x%08x\n", i, readl(i2c->regs + I2C_TXDATA_BASE + i * 4)); + for( i = 0; i < 8; i ++) + i2c_dbg(i2c->dev, "I2C_RXDATA%d: 0x%08x\n", i, readl(i2c->regs + I2C_RXDATA_BASE + i * 4)); } -static inline void rk30_i2c_last_ack(struct rk30_i2c *i2c, int enable) +static inline void rk30_i2c_enable(struct rk30_i2c *i2c, unsigned int lastnak) { - unsigned int p = readl(i2c->regs + I2C_CON); - - p = rk30_set_bit(p, 0, I2C_START_BIT); - p = rk30_set_bit(p, 0, I2C_STOP_BIT); - writel(rk30_set_bit(p, enable, I2C_LAST_ACK_BIT), i2c->regs + I2C_CON); + unsigned int con = 0; + + con |= I2C_CON_EN; + con |= I2C_CON_MOD(i2c->mode); + if(lastnak) + con |= I2C_CON_LASTACK; + con |= I2C_CON_START; + writel(con, i2c->regs + I2C_CON); } -static inline void rk30_i2c_act2ack(struct rk30_i2c *i2c, int enable) +static inline void rk30_i2c_disable(struct rk30_i2c *i2c) { - unsigned int p = readl(i2c->regs + I2C_CON); - - p = rk30_set_bit(p, 0, I2C_START_BIT); - p = rk30_set_bit(p, 0, I2C_STOP_BIT); - writel(rk30_set_bit(p, enable, I2C_ACT2ACK_BIT), i2c->regs + I2C_CON); + writel( 0, i2c->regs + I2C_CON); } -static inline void rk30_i2c_enable(struct rk30_i2c *i2c, int enable) + +static inline void rk30_i2c_clean_start(struct rk30_i2c *i2c) { - unsigned int p = readl(i2c->regs + I2C_CON); + unsigned int con = readl(i2c->regs + I2C_CON); - p = rk30_set_bit(p, 0, I2C_START_BIT); - p = rk30_set_bit(p, 0, I2C_STOP_BIT); + con &= ~I2C_CON_START; + writel(con, i2c->regs + I2C_CON); +} +static inline void rk30_i2c_send_start(struct rk30_i2c *i2c) +{ + unsigned int con = readl(i2c->regs + I2C_CON); - writel(rk30_set_bit(p, enable, I2C_EN_BIT), i2c->regs + I2C_CON); + con |= I2C_CON_START; + if(con & I2C_CON_STOP) + dev_warn(i2c->dev, "I2C_CON: stop bit is set\n"); + + writel(con, i2c->regs + I2C_CON); } -static inline void rk30_i2c_set_mode(struct rk30_i2c *i2c) +static inline void rk30_i2c_send_stop(struct rk30_i2c *i2c) { - unsigned int p = readl(i2c->regs + I2C_CON); - - p = rk30_set_bit(p, 0, I2C_START_BIT); - p = rk30_set_bit(p, 0, I2C_STOP_BIT); - writel(rk30_set_bits(p, i2c->mode, I2C_MOD_BIT, I2C_MOD_MASK), i2c->regs + I2C_CON); + unsigned int con = readl(i2c->regs + I2C_CON); + + con |= I2C_CON_STOP; + if(con & I2C_CON_START) + dev_warn(i2c->dev, "I2C_CON: start bit is set\n"); + + writel(con, i2c->regs + I2C_CON); } -static inline void rk30_i2c_disable_irq(struct rk30_i2c *i2c) +static inline void rk30_i2c_clean_stop(struct rk30_i2c *i2c) { - writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IEN); + unsigned int con = readl(i2c->regs + I2C_CON); + + con &= ~I2C_CON_STOP; + writel(con, i2c->regs + I2C_CON); } -static inline void rk30_i2c_enable_irq(struct rk30_i2c *i2c) +static inline void rk30_i2c_disable_irq(struct rk30_i2c *i2c) { - writel(IRQ_MST_ENABLE, i2c->regs + I2C_IEN); + writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IEN); } -static inline void rk30_i2c_send_start(struct rk30_i2c *i2c) +static inline void rk30_i2c_enable_irq(struct rk30_i2c *i2c) { - unsigned int p = readl(i2c->regs + I2C_CON); - - p = rk30_set_bit(p, 1, I2C_START_BIT); - p = rk30_set_bit(p, 0, I2C_STOP_BIT); - writel(p, i2c->regs + I2C_CON); + writel(IRQ_MST_ENABLE, i2c->regs + I2C_IEN); } -static inline void rk30_i2c_send_stop(struct rk30_i2c *i2c) -{ - unsigned int p = readl(i2c->regs + I2C_CON); - - p = rk30_set_bit(p, 0, I2C_START_BIT); - p = rk30_set_bit(p, 1, I2C_STOP_BIT); - writel(p, i2c->regs + I2C_CON); -} /* SCL Divisor = 8 * (CLKDIVL + CLKDIVH) * SCL = i2c_rate/ SCLK Divisor */ static void rk30_i2c_set_clk(struct rk30_i2c *i2c, unsigned long scl_rate) { - unsigned long i2c_rate = clk_get_rate(i2c->clk); - - unsigned int div, divl, divh; - - if((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate)) - return; - i2c->i2c_rate = i2c_rate; - i2c->scl_rate = scl_rate; - div = rk30_ceil(i2c_rate, scl_rate * 8); - divh = divl = rk30_ceil(div, 2); - i2c_dbg(i2c->dev, "div divh divl: %d %d %d\n", div, divh, divl); - writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV); - return; + unsigned long i2c_rate = clk_get_rate(i2c->clk); + + unsigned int div, divl, divh; + + if((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate)) + return; + i2c->i2c_rate = i2c_rate; + i2c->scl_rate = scl_rate; + div = rk30_ceil(i2c_rate, scl_rate * 8); + divh = divl = rk30_ceil(div, 2); + writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV); + i2c_dbg(i2c->dev, "set clk(I2C_CLKDIV: 0x%08x)\n", readl(i2c->regs + I2C_CLKDIV)); + return; } static void rk30_i2c_init_hw(struct rk30_i2c *i2c, unsigned long scl_rate) { - rk30_i2c_set_clk(i2c, scl_rate); + i2c->scl_rate = 0; + rk30_i2c_set_clk(i2c, scl_rate); return; } /* returns TRUE if we this is the last byte in the current message */ @@ -195,19 +206,32 @@ static void rk30_i2c_stop(struct rk30_i2c *i2c, int ret) i2c->msg_ptr = 0; i2c->msg = NULL; - i2c->msg_idx++; i2c->msg_num = 0; if (ret) i2c->msg_idx = ret; + writel(I2C_STOPIEN, i2c->regs + I2C_IEN); + i2c->state = STATE_STOP; + rk30_i2c_send_stop(i2c); +} +static inline void rk30_set_rx_mode(struct rk30_i2c *i2c, unsigned int lastnak) +{ + unsigned long con = readl(i2c->regs + I2C_CON); - mdelay(10); - i2c->state = STATE_STOP; - rk30_i2c_send_stop(i2c); + con &= (~I2C_CON_MASK); + con |= (I2C_CON_MOD_RX << 1); + if(lastnak) + con |= I2C_CON_LASTACK; + writel(con, i2c->regs + I2C_CON); } static void rk30_irq_read_prepare(struct rk30_i2c *i2c) { unsigned int cnt, len = i2c->msg->len - i2c->msg_ptr; + if(len <= 32 && i2c->msg_ptr != 0) + rk30_set_rx_mode(i2c, 1); + else if(i2c->msg_ptr != 0) + rk30_set_rx_mode(i2c, 0); + if(is_msgend(i2c)) { rk30_i2c_stop(i2c, 0); return; @@ -216,7 +240,6 @@ static void rk30_irq_read_prepare(struct rk30_i2c *i2c) cnt = 32; else cnt = len; - writel(cnt, i2c->regs + I2C_MRXCNT); } static void rk30_irq_read_get_data(struct rk30_i2c *i2c) @@ -263,147 +286,162 @@ static void rk30_irq_write_prepare(struct rk30_i2c *i2c) } static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd) { - switch (i2c->state) { - case STATE_IDLE: - dev_err(i2c->dev, "Addr[0x%02x] called in STATE_IDLE\n", i2c->addr); - goto out; - case STATE_START: - if(!(ipd & I2C_STARTIPD)){ - if(ipd & I2C_STOPIPD){ - writel(I2C_STOPIPD, i2c->regs + I2C_IPD); - } - else { - rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%02x] no start irq in STATE_START\n", i2c->addr); + switch (i2c->state) { + case STATE_IDLE: + dev_err(i2c->dev, "Addr[0x%02x] called in STATE_IDLE\n", i2c->addr); rk30_show_regs(i2c); - } - goto out; - } - writel(I2C_STARTIPD, i2c->regs + I2C_IPD); - if(i2c->mode == I2C_MOD_TX){ - i2c->state = STATE_WRITE; - goto prepare_write; - } - else { - i2c->state = STATE_READ; - goto prepare_read; - } - case STATE_WRITE: - if(!(ipd & I2C_MBTFIPD)){ - goto out; - } - writel(I2C_MBTFIPD, i2c->regs + I2C_IPD); + writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); + goto out; + 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); + rk30_show_regs(i2c); + writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); + goto out; + } + + rk30_show_regs(i2c); + writel(I2C_STARTIPD, i2c->regs + I2C_IPD); + rk30_i2c_clean_start(i2c); + if(i2c->mode == I2C_CON_MOD_TX){ + writel(I2C_MBTFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); + i2c->state = STATE_WRITE; + goto prepare_write; + } else { + writel(I2C_MBRFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); + i2c->state = STATE_READ; + goto prepare_read; + } + 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); + rk30_show_regs(i2c); + writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); + goto out; + } + rk30_show_regs(i2c); + writel(I2C_MBTFIPD, i2c->regs + I2C_IPD); prepare_write: - rk30_irq_write_prepare(i2c); - break; - case STATE_READ: - if(!(ipd & I2C_MBRFIPD)){ - goto out; - } - writel(I2C_MBRFIPD, i2c->regs + I2C_IPD); - rk30_irq_read_get_data(i2c); + rk30_irq_write_prepare(i2c); + break; + 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\n", i2c->addr); + rk30_show_regs(i2c); + writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); + goto out; + } + rk30_show_regs(i2c); + writel(I2C_MBRFIPD, i2c->regs + I2C_IPD); + rk30_irq_read_get_data(i2c); prepare_read: - rk30_irq_read_prepare(i2c); - break; - case STATE_STOP: - if(ipd & I2C_STOPIPD){ - writel(0xff, i2c->regs + I2C_IPD); - i2c->state = STATE_IDLE; - rk30_i2c_disable_irq(i2c); + rk30_irq_read_prepare(i2c); + break; + 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); + rk30_show_regs(i2c); + writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); + goto out; + } + rk30_show_regs(i2c); + rk30_i2c_clean_stop(i2c); + writel(I2C_STOPIPD, i2c->regs + I2C_IPD); + i2c->state = STATE_IDLE; wake_up(&i2c->wait); + break; + default: + break; } - break; - default: - break; - } out: - return; + return; } static irqreturn_t rk30_i2c_irq(int irq, void *dev_id) { - struct rk30_i2c *i2c = dev_id; - unsigned int ipd; - spin_lock(&i2c->lock); - ipd = readl(i2c->regs + I2C_IPD); - - if(ipd & I2C_NAKRCVIPD) { - writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD); - rk30_i2c_stop(i2c, -EAGAIN); - dev_dbg(i2c->dev, "Addr[0x%02x] ack was not received\n", i2c->addr); - rk30_show_regs(i2c); - goto out; - } - - rk30_i2c_irq_nextblock(i2c, ipd); + struct rk30_i2c *i2c = dev_id; + unsigned int ipd; + + spin_lock(&i2c->lock); + ipd = readl(i2c->regs + I2C_IPD); +#if 1 + if((ipd & I2C_NAKRCVIPD) && (i2c->state != STATE_STOP)){ + dev_err(i2c->dev, "Addr[0x%02x] ack was not received\n", i2c->addr); + rk30_show_regs(i2c); + writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD); + rk30_i2c_stop(i2c, -EAGAIN); + goto out; + } +#endif + rk30_i2c_irq_nextblock(i2c, ipd); out: - spin_unlock(&i2c->lock); - return IRQ_HANDLED; + spin_unlock(&i2c->lock); + return IRQ_HANDLED; } 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 = (msgs[0].addr & 0x7f) << 1; + unsigned int reg_valid_bits = 0; + unsigned int reg_addr = 0; - if(num == 1) { - if(!(msgs[0].flags & I2C_M_RD)){ - i2c->msg = &msgs[0]; - i2c->mode = I2C_MOD_TX; + if(num == 1) { + i2c->count = msgs[0].len; + if(!(msgs[0].flags & I2C_M_RD)){ + i2c->msg = &msgs[0]; + i2c->mode = I2C_CON_MOD_TX; + } + else { + addr |= 1; + i2c->msg = &msgs[0]; + writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); + i2c->mode = I2C_CON_MOD_RX; + } } - else { - addr |= 1; - i2c->msg = &msgs[0]; - writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - i2c->mode = I2C_MOD_RX; + 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; + 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; + } + if((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { + addr |= 1; + i2c->msg = &msgs[1]; + writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); + writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); + i2c->mode = I2C_CON_MOD_RRX; + } + else if(!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { + i2c->msg = &msgs[1]; + writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); + writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); + i2c->mode = I2C_CON_MOD_TRX; + } + else + return -EIO; } - } - else if(num == 2) { - 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: + else { + dev_err(i2c->dev, "This case(num > 2) has not been support now\n"); return -EIO; } - if((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { - addr |= 1; - i2c->msg = &msgs[1]; - writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_MOD_RRX; - } - else if(!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { - i2c->msg = &msgs[1]; - writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_MOD_TRX; - } - else - return -EIO; - } - else { - dev_err(i2c->dev, "This case(num > 2) has not been support now\n"); - return -EIO; - } - rk30_i2c_set_mode(i2c); - rk30_i2c_last_ack(i2c, LAST_SEND_TYPE); - if(msgs[0].flags & I2C_M_IGNORE_NAK) - rk30_i2c_act2ack(i2c, 0); - else - rk30_i2c_act2ack(i2c, 1); - return 0; + return 0; } /* rk30_i2c_doxfer * @@ -420,38 +458,41 @@ static int rk30_i2c_doxfer(struct rk30_i2c *i2c, ret = rk30_i2c_set_master(i2c, msgs, num); if (ret != 0) { - dev_err(i2c->dev, "addr[0x%02x] set master error\n", msgs[0].addr); - return ret; - } + dev_err(i2c->dev, "addr[0x%02x] set master error\n", msgs[0].addr); + return ret; + } spin_lock_irq(&i2c->lock); - i2c->addr = msgs[0].addr; + i2c->addr = msgs[0].addr; i2c->msg_num = num; - i2c->msg_ptr = 0; - i2c->msg_idx = 0; - i2c->state = STATE_START; + i2c->msg_ptr = 0; + i2c->msg_idx = num; + i2c->state = STATE_START; spin_unlock_irq(&i2c->lock); - rk30_i2c_enable_irq(i2c); - rk30_i2c_send_start(i2c); + writel(I2C_STARTIEN, i2c->regs + I2C_IEN); + rk30_i2c_enable(i2c, (i2c->count > 32)?0:1); //if count > 32, byte(32) send ack + rk30_show_regs(i2c); + //rk30_i2c_enable_irq(i2c); + //rk30_i2c_send_start(i2c); - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, msecs_to_jiffies(I2C_WAIT_TIMEOUT)); + timeout = wait_event_timeout(i2c->wait, (i2c->msg_num == 0), msecs_to_jiffies(I2C_WAIT_TIMEOUT)); ret = i2c->msg_idx; if (timeout == 0){ - dev_err(i2c->dev, "addr[0x%02x] wait event timeout, state = %d\n", msgs[0].addr, i2c->state); + dev_err(i2c->dev, "addr[0x%02x] wait event timeout, state = %d\n", msgs[0].addr, i2c->state); + rk30_show_regs(i2c); + if(i2c->state != STATE_STOP) + rk30_i2c_send_stop(i2c); + ret = -ETIMEDOUT; + } + writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); + rk30_i2c_disable_irq(i2c); + rk30_i2c_disable(i2c); + i2c_dbg(i2c->dev, "i2c transfer finished ret = %d\n", ret); rk30_show_regs(i2c); - writel(0xff, i2c->regs + I2C_IPD); - rk30_i2c_disable_irq(i2c); - rk30_i2c_send_stop(i2c); - if(ret >= 0) - ret = -ETIMEDOUT; - return ret; - } - if(ret > 0) - ret = num; return ret; } @@ -465,10 +506,10 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret = 0; - unsigned long scl_rate; + unsigned long scl_rate; struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; - if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000) + 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!", @@ -480,19 +521,16 @@ static int rk30_i2c_xfer(struct i2c_adapter *adap, msgs[0].addr, msgs[0].scl_rate/1000); scl_rate = 10000; } - if(i2c->is_div_from_arm[i2c->adap.nr]) + if(i2c->is_div_from_arm[i2c->adap.nr]) wake_lock(&i2c->idlelock[i2c->adap.nr]); - rk30_i2c_enable(i2c, 1); rk30_i2c_set_clk(i2c, scl_rate); - udelay(i2c->tx_setup); - - i2c_dbg(i2c->dev, "i2c transfer: addr[0x%x], scl_reate[%ldKhz]\n", msgs[0].addr, scl_rate/1000); + udelay(i2c->tx_setup); + i2c_dbg(i2c->dev, "i2c transfer: addr[0x%x], scl_reate[%ldKhz], len = %d\n", msgs[0].addr, scl_rate/1000, i2c->count); ret = rk30_i2c_doxfer(i2c, msgs, num); - rk30_i2c_enable(i2c, 0); - i2c->state = STATE_IDLE; - if(i2c->is_div_from_arm[i2c->adap.nr]) + i2c->state = STATE_IDLE; + if(i2c->is_div_from_arm[i2c->adap.nr]) wake_unlock(&i2c->idlelock[i2c->adap.nr]); return ret; } @@ -512,17 +550,17 @@ static const struct i2c_algorithm rk30_i2c_algorithm = { int i2c_add_rk30_adapter(struct i2c_adapter *adap) { - int ret = 0; - struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; + int ret = 0; + struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; - adap->algo = &rk30_i2c_algorithm; + adap->algo = &rk30_i2c_algorithm; - i2c->i2c_init_hw = &rk30_i2c_init_hw; - i2c->i2c_set_clk = &rk30_i2c_set_clk; - i2c->i2c_irq = &rk30_i2c_irq; + i2c->i2c_init_hw = &rk30_i2c_init_hw; + i2c->i2c_set_clk = &rk30_i2c_set_clk; + i2c->i2c_irq = &rk30_i2c_irq; - ret = i2c_add_numbered_adapter(adap); + ret = i2c_add_numbered_adapter(adap); - return ret; + return ret; } diff --git a/drivers/i2c/busses/i2c-rk30.h b/drivers/i2c/busses/i2c-rk30.h index 05db8a4c22a6..68daa5cb535c 100755 --- a/drivers/i2c/busses/i2c-rk30.h +++ b/drivers/i2c/busses/i2c-rk30.h @@ -28,7 +28,7 @@ #define i2c_dbg(dev, format, arg...) #endif -#define I2C_WAIT_TIMEOUT 100 //100ms +#define I2C_WAIT_TIMEOUT 200 //100ms #define rk30_set_bit(p, v, b) (((p) & ~(1 << (b))) | ((v) << (b))) #define rk30_get_bit(p, b) (((p) & (1 << (b))) >> (b)) @@ -75,6 +75,7 @@ struct rk30_i2c { unsigned long i2c_rate; unsigned int addr; unsigned int mode; + unsigned int count; struct wake_lock idlelock[5]; int is_div_from_arm[5]; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index b32f5654c6c1..d37266328952 100755 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1456,7 +1456,7 @@ int i2c_master_recv(const struct i2c_client *client, char *buf, int count) msg.flags = client->flags | I2C_M_RD; msg.len = count; msg.buf = (char *)buf; - msg.scl_rate = 400 * 1000; + msg.scl_rate = 100 * 1000; msg.udelay = client->udelay; ret = i2c_transfer(adap, &msg, 1); -- 2.34.1