update i2c drivers

This commit is contained in:
kfx
2011-01-06 10:47:49 +08:00
parent af9b5b9cff
commit 094ccd6c4f
2 changed files with 149 additions and 216 deletions

View File

@@ -379,16 +379,6 @@ struct mma8452_platform_data mma8452_info = {
*****************************************************************************************/
static int rk29_i2c0_io_init(void)
{
rk29_mux_api_set(GPIO2B7_I2C0SCL_NAME, 0);
rk29_mux_api_set(GPIO2B6_I2C0SDA_NAME, 0);
gpio_request(RK29_PIN2_PB6, "i2c0_sda");
gpio_set_value(RK29_PIN2_PB6, GPIO_HIGH);
gpio_pull_updown(RK29_PIN2_PB6, PullDisable);
gpio_request(RK29_PIN2_PB7, "i2c0_scl");
gpio_set_value(RK29_PIN2_PB7, GPIO_HIGH);
gpio_pull_updown(RK29_PIN2_PB7, PullDisable);
rk29_mux_api_set(GPIO2B7_I2C0SCL_NAME, GPIO2L_I2C0_SCL);
rk29_mux_api_set(GPIO2B6_I2C0SDA_NAME, GPIO2L_I2C0_SDA);
return 0;
@@ -396,28 +386,12 @@ static int rk29_i2c0_io_init(void)
static int rk29_i2c1_io_init(void)
{
gpio_request(RK29_PIN1_PA6, "i2c1_sda");
gpio_set_value(RK29_PIN1_PA6, GPIO_HIGH);
gpio_pull_updown(RK29_PIN1_PA6, PullDisable);
gpio_request(RK29_PIN1_PA7, "i2c1_scl");
gpio_set_value(RK29_PIN1_PA7, GPIO_HIGH);
gpio_pull_updown(RK29_PIN1_PA7, PullDisable);
rk29_mux_api_set(GPIO1A7_I2C1SCL_NAME, GPIO1L_I2C1_SCL);
rk29_mux_api_set(GPIO1A6_I2C1SDA_NAME, GPIO1L_I2C1_SDA);
return 0;
}
static int rk29_i2c2_io_init(void)
{
gpio_request(RK29_PIN5_PD3, "i2c2_sda");
gpio_set_value(RK29_PIN5_PD3, GPIO_HIGH);
gpio_pull_updown(RK29_PIN5_PD3, PullDisable);
gpio_request(RK29_PIN5_PD4, "i2c2_scl");
gpio_set_value(RK29_PIN5_PD4, GPIO_HIGH);
gpio_pull_updown(RK29_PIN5_PD4, PullDisable);
rk29_mux_api_set(GPIO5D4_I2C2SCL_NAME, GPIO5H_I2C2_SCL);
rk29_mux_api_set(GPIO5D3_I2C2SDA_NAME, GPIO5H_I2C2_SDA);
return 0;
@@ -425,14 +399,6 @@ static int rk29_i2c2_io_init(void)
static int rk29_i2c3_io_init(void)
{
gpio_request(RK29_PIN2_PB4, "i2c3_sda");
gpio_set_value(RK29_PIN2_PB4, GPIO_HIGH);
gpio_pull_updown(RK29_PIN2_PB4, PullDisable);
gpio_request(RK29_PIN2_PB5, "i2c3_scl");
gpio_set_value(RK29_PIN2_PB5, GPIO_HIGH);
gpio_pull_updown(RK29_PIN2_PB5, PullDisable);
rk29_mux_api_set(GPIO2B5_UART3RTSN_I2C3SCL_NAME, GPIO2L_I2C3_SCL);
rk29_mux_api_set(GPIO2B4_UART3CTSN_I2C3SDA_NAME, GPIO2L_I2C3_SDA);
return 0;

View File

@@ -31,10 +31,9 @@
#include "i2c-rk29.h"
#define DRV_NAME "rk29_i2c"
#define RETRY_NUM 3
#define RETRY_NUM 1
#define RK2818_I2C_TIMEOUT (msecs_to_jiffies(100))
#define RK2818_DELAY_TIME 2
#define RK29_I2C_TIMEOUT(x) (msecs_to_jiffies(x))
#if 0
#define i2c_dbg(dev, format, arg...) \
@@ -44,27 +43,27 @@
#else
#define i2c_dbg(dev, format, arg...)
#define i2c_err(dev, format, arg...)
#define i2c_err(dev, format, arg...)
#endif
enum rk29_error {
RK2818_ERROR_NONE = 0,
RK2818_ERROR_ARBITR_LOSE,
RK2818_ERROR_UNKNOWN
RK29_ERROR_NONE = 0,
RK29_ERROR_ARBITR_LOSE,
RK29_ERROR_UNKNOWN
};
enum rk29_event {
RK2818_EVENT_NONE = 0,
RK29_EVENT_NONE = 0,
/* master has received ack(MTX mode)
means that data has been sent to slave.
*/
RK2818_EVENT_MTX_RCVD_ACK,
RK29_EVENT_MTX_RCVD_ACK,
/* master needs to send ack to slave(MRX mode)
means that data has been received from slave.
*/
RK2818_EVENT_MRX_NEED_ACK,
RK2818_EVENT_MAX
RK29_EVENT_MRX_NEED_ACK,
RK29_EVENT_MAX
};
struct rk29_i2c_data {
@@ -81,6 +80,8 @@ struct rk29_i2c_data {
unsigned int mode;
int retry;
int poll_status;
unsigned int irq;
spinlock_t cmd_lock;
@@ -96,8 +97,6 @@ struct rk29_i2c_data {
#endif
};
static void rk29_i2c_init_hw(struct rk29_i2c_data *i2c);
static void rk29_set_ack(struct rk29_i2c_data *i2c)
{
unsigned long conr = readl(i2c->regs + I2C_CONR);
@@ -159,11 +158,8 @@ static void rk29_i2c_calcdivisor(unsigned long pclk,
/* set i2c bus scl rate */
static void rk29_i2c_clockrate(struct rk29_i2c_data *i2c)
{
#ifdef CONFIG_ARCH_RK2818
struct rk2818_i2c_platform_data *pdata = i2c->dev->platform_data;
#else
struct rk29_i2c_platform_data *pdata = i2c->dev->platform_data;
#endif
unsigned int rem = 0, exp = 0;
unsigned long scl_rate, real_rate = 0, tmp;
@@ -187,22 +183,22 @@ static void rk29_i2c_clockrate(struct rk29_i2c_data *i2c)
}
static int rk29_event_occurred(struct rk29_i2c_data *i2c)
{
unsigned long isr;
unsigned long isr, lsr;
isr = readl(i2c->regs + I2C_ISR);
i2c_dbg(i2c->dev,"event occurred, isr = %lx\n", isr);
lsr = readl(i2c->regs + I2C_LSR);
i2c_dbg(i2c->dev,"event occurred, isr = %lx, lsr = %lx\n", isr, lsr);
if(isr & I2C_ISR_ARBITR_LOSE)
{
isr &= ~I2C_ISR_ARBITR_LOSE;
writel(isr, i2c->regs + I2C_ISR);
i2c->cmd_err = RK2818_ERROR_ARBITR_LOSE;
writel(0, i2c->regs + I2C_ISR);
i2c->cmd_err = RK29_ERROR_ARBITR_LOSE;
i2c_err(i2c->dev, "<error>arbitration loss\n");
return 1;
return 0;
}
switch(i2c->cmd_event)
{
case RK2818_EVENT_MTX_RCVD_ACK:
case RK29_EVENT_MTX_RCVD_ACK:
if(isr & I2C_ISR_MTX_RCVD_ACK)
{
isr &= ~I2C_ISR_MTX_RCVD_ACK;
@@ -210,7 +206,7 @@ static int rk29_event_occurred(struct rk29_i2c_data *i2c)
return 1;
}
break;
case RK2818_EVENT_MRX_NEED_ACK:
case RK29_EVENT_MRX_NEED_ACK:
if(isr & I2C_ISR_MRX_NEED_ACK)
{
isr &= ~I2C_ISR_MRX_NEED_ACK;
@@ -221,7 +217,8 @@ static int rk29_event_occurred(struct rk29_i2c_data *i2c)
default:
break;
}
i2c->cmd_err = RK2818_ERROR_UNKNOWN;
writel(0, i2c->regs + I2C_ISR);
i2c->cmd_err = RK29_ERROR_UNKNOWN;
return 0;
}
@@ -234,56 +231,51 @@ static irqreturn_t rk29_i2c_irq(int irq, void *data)
spin_lock(&i2c->cmd_lock);
res = rk29_event_occurred(i2c);
if(res)
//if(res || i2c->cmd_err != RK2818_ERROR_NONE)
complete(&i2c->cmd_complete);
{
if(i2c->mode == I2C_MODE_IRQ)
complete(&i2c->cmd_complete);
else
i2c->poll_status = 1;
}
spin_unlock(&i2c->cmd_lock);
return IRQ_HANDLED;
}
static int wait_for_completion_poll_timeout(struct rk29_i2c_data *i2c, unsigned long timeout)
static int wait_for_completion_poll_timeout(struct rk29_i2c_data *i2c)
{
unsigned int time = RK2818_DELAY_TIME;
int res;
while(!time_after(jiffies, jiffies + timeout))
int tmo = 10000;
while(--tmo)
{
res = rk29_event_occurred(i2c);
if(res)
//if(res || (i2c->cmd_err != RK2818_ERROR_NONE && i2c->cmd_err != RK2818_ERROR_UNKNOWN))
if(i2c->poll_status == 1)
return 1;
udelay(time);
time *= 2;
udelay(400*1000/i2c->scl_rate);
}
return 0;
}
static int rk29_wait_event(struct rk29_i2c_data *i2c,
enum rk29_event mr_event)
{
int ret = 0;
unsigned long flags;
if(i2c->mode == I2C_MODE_IRQ)
if(unlikely(irqs_disabled()))
{
if(unlikely(irqs_disabled()))
{
i2c_err(i2c->dev, "irqs are disabled on this system!\n");
return -EIO;
}
i2c_err(i2c->dev, "irqs are disabled on this system!\n");
return -EIO;
}
spin_lock_irqsave(&i2c->cmd_lock,flags);
i2c->cmd_err = RK2818_ERROR_NONE;
i2c->cmd_err = RK29_ERROR_NONE;
i2c->cmd_event = mr_event;
init_completion(&i2c->cmd_complete);
spin_unlock_irqrestore(&i2c->cmd_lock,flags);
rk29_i2c_enable_irqs(i2c);
if(i2c->mode == I2C_MODE_IRQ)
{
init_completion(&i2c->cmd_complete);
ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete,
RK2818_I2C_TIMEOUT);
RK29_I2C_TIMEOUT(40000 * 1000/i2c->scl_rate));
}
else
ret = wait_for_completion_poll_timeout(i2c, RK2818_I2C_TIMEOUT);
{
i2c->poll_status = 0;
ret = wait_for_completion_poll_timeout(i2c);
}
if(ret < 0)
{
i2c_err(i2c->dev, "i2c wait for event %04x, retrun %d \n", mr_event, ret);
@@ -296,66 +288,59 @@ static int rk29_wait_event(struct rk29_i2c_data *i2c,
return 0;
}
static int rk29_wait_while_busy(struct rk29_i2c_data *i2c)
static void rk29_i2c_stop(struct rk29_i2c_data *i2c)
{
unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT/1000;
unsigned long lsr;
unsigned int time = RK2818_DELAY_TIME;
while(!time_after(jiffies, timeout))
{
lsr = readl(i2c->regs + I2C_LSR);
if(!(lsr & I2C_LSR_BUSY))
return 0;
udelay(time);
time *= 2;
}
return 0;
}
static int rk29_i2c_stop(struct rk29_i2c_data *i2c)
{
unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT/1000;
unsigned int time = RK2818_DELAY_TIME;
int tmo = 10000 * 1000/i2c->scl_rate;
writel(I2C_LCMR_STOP|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
while(!time_after(jiffies, timeout))
while(--tmo && !(readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP))
{
if(!(readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP))
{
udelay(100);
return 0;
}
udelay(time);
time *= 2;
udelay(400*1000/i2c->scl_rate);
}
return 0;
writel(0, i2c->regs + I2C_ISR);
rk29_i2c_disable_irqs(i2c);
udelay(tmo);
return;
}
static void rk29_wait_while_busy(struct rk29_i2c_data *i2c)
{
int tmo = 10000 * 1000/i2c->scl_rate;
while(--tmo && (readl(i2c->regs + I2C_LSR) & I2C_LSR_BUSY))
{
udelay(400*1000/i2c->scl_rate);
}
return;
}
static int rk29_send_2nd_addr(struct rk29_i2c_data *i2c,
struct i2c_msg *msg, int start)
{
int ret = 0;
unsigned long lsr;
unsigned long addr_2nd = msg->addr & 0xff;
unsigned long conr = readl(i2c->regs + I2C_CONR);
conr |= I2C_CONR_MTX_MODE;
//conr &= I2C_CONR_ACK;
writel(conr, i2c->regs + I2C_CONR);
i2c_dbg(i2c->dev, "i2c send addr_2nd: %lx\n", addr_2nd);
writel(addr_2nd, i2c->regs + I2C_MTXR);
writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
rk29_set_ack(i2c);
if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0)
{
i2c_err(i2c->dev, "after sent addr_2nd, i2c wait for ACK timeout\n");
return ret;
}
lsr = readl(i2c->regs + I2C_LSR);
if(lsr & I2C_LSR_RCV_NAK)
return -EINVAL;
return ret;
}
static int rk29_send_address(struct rk29_i2c_data *i2c,
struct i2c_msg *msg, int start)
{
unsigned long addr_1st;
unsigned long conr = readl(i2c->regs + I2C_CONR);
unsigned long conr,lsr;
int ret = 0;
if(msg->flags & I2C_M_TEN)
@@ -367,29 +352,29 @@ static int rk29_send_address(struct rk29_i2c_data *i2c,
addr_1st |= 0x01;
else
addr_1st &= (~0x01);
rk29_set_ack(i2c);
if(start)
rk29_wait_while_busy(i2c);
writel(0, i2c->regs + I2C_ISR);
conr = readl(i2c->regs + I2C_CONR);
conr |= I2C_CONR_MTX_MODE;
conr |= I2C_CONR_MPORT_ENABLE;
writel(conr, i2c->regs + I2C_CONR);
i2c_dbg(i2c->dev, "i2c send addr_1st: %lx\n", addr_1st);
writel(addr_1st, i2c->regs + I2C_MTXR);
if (start)
{
if((ret = rk29_wait_while_busy(i2c)) != 0)
{
i2c_err(i2c->dev, "i2c is busy, when send address\n");
return ret;
}
}
rk29_set_ack(i2c);
writel(I2C_LCMR_START|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0)
{
i2c_err(i2c->dev, "after sent addr_1st, i2c wait for ACK timeout\n");
return ret;
}
lsr = readl(i2c->regs + I2C_LSR);
if(lsr & I2C_LSR_RCV_NAK)
return -EINVAL;
if(start && (msg->flags & I2C_M_TEN))
ret = rk29_send_2nd_addr(i2c, msg, start);
return ret;
@@ -398,23 +383,26 @@ static int rk29_send_address(struct rk29_i2c_data *i2c,
static int rk29_i2c_send_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg)
{
int i, ret = 0;
unsigned long conr = readl(i2c->regs + I2C_CONR);
unsigned long conr, lsr;
conr = readl(i2c->regs + I2C_CONR);
conr |= I2C_CONR_MTX_MODE;
//conr |= I2C_CONR_MPORT_ENABLE;
writel(conr, i2c->regs + I2C_CONR);
rk29_set_ack(i2c);
for(i = 0; i < msg->len; i++)
{
i2c_dbg(i2c->dev, "i2c send buf[%d]: %x\n", i, msg->buf[i]);
i2c_dbg(i2c->dev, "i2c send buf[%d]: %x\n", i, msg->buf[i]);
writel(msg->buf[i], i2c->regs + I2C_MTXR);
rk29_set_ack(i2c);
writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
if((ret = rk29_wait_event(i2c, RK2818_EVENT_MTX_RCVD_ACK)) != 0)
if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0)
return ret;
if(readl(i2c->regs + I2C_LSR) & I2C_LSR_RCV_NAK)
rk29_set_nak(i2c);
lsr = readl(i2c->regs + I2C_LSR);
if((lsr & I2C_LSR_RCV_NAK) && (i != msg->len -1))
return -EINVAL;
}
return ret;
}
@@ -423,19 +411,22 @@ static int rk29_i2c_recv_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg)
int i, ret = 0;
unsigned long conr;
rk29_set_ack(i2c);
conr = readl(i2c->regs + I2C_CONR);
conr &= I2C_CONR_MRX_MODE;
//conr |= I2C_CONR_MPORT_ENABLE;
writel(conr, i2c->regs + I2C_CONR);
for(i = 0; i < msg->len; i++)
{
writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
if((ret = rk29_wait_event(i2c, RK2818_EVENT_MRX_NEED_ACK)) != 0)
if((ret = rk29_wait_event(i2c, RK29_EVENT_MRX_NEED_ACK)) != 0)
return ret;
msg->buf[i] = (uint8_t)readl(i2c->regs + I2C_MRXR);
if( i == msg->len - 1)
if( i == msg->len -1)
rk29_set_nak(i2c);
else
rk29_set_ack(i2c);
i2c_dbg(i2c->dev, "i2c recv >>>>>>>>>>>> buf[%d]: %x\n", i, msg->buf[i]);
}
return ret;
@@ -446,10 +437,6 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data;
int ret = 0;
#if defined (CONFIG_IOEXTEND_TCA6424)
struct tca6424_platform_data *pdata = adap->dev.platform_data;
#endif
if(msg->len == 0)
{
ret = -EINVAL;
@@ -459,6 +446,7 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
if((ret = rk29_send_address(i2c, msg, start))!= 0)
{
rk29_set_nak(i2c);
i2c_err(i2c->dev, "<error>rk29_send_address timeout\n");
goto exit;
}
@@ -474,32 +462,17 @@ static int rk29_xfer_msg(struct i2c_adapter *adap,
{
if((ret = rk29_i2c_send_msg(i2c, msg)) != 0)
{
rk29_set_nak(i2c);
i2c_err(i2c->dev, "<error>rk29_i2c_send_msg timeout\n");
goto exit;
}
}
exit:
if(stop || ret < 0)
{
if(ret < 0)
rk29_set_nak(i2c);
if((ret = rk29_i2c_stop(i2c)) != 0)
{
i2c_err(i2c->dev, "<error>rk29_i2c_stop timeout\n");
}
#if 0
//not I2C code,add by sxj,used for extend gpio intrrupt,set SCL and SDA pin.
if(msg->flags & I2C_M_RD)
{
#if defined (CONFIG_IOEXTEND_TCA6424)
if (pdata && pdata->reseti2cpin) {
pdata->reseti2cpin();
}
#endif
}
#endif
}
//if(stop || ret < 0)
//{
rk29_i2c_stop(i2c);
//}
return ret;
}
@@ -510,26 +483,16 @@ static int rk29_i2c_xfer(struct i2c_adapter *adap,
int ret = -1;
int i;
struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data;
int retry = i2c->retry;
unsigned long conr = readl(i2c->regs + I2C_CONR);
//int retry = i2c->retry;
/*
if(i2c->suspended ==1)
return -EIO;
*/
retry:
if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate > 0)
i2c->scl_rate = msgs[0].scl_rate;
else
i2c->scl_rate = 400000;
conr |= I2C_CONR_MPORT_ENABLE;
writel(conr, i2c->regs + I2C_CONR);
rk29_i2c_init_hw(i2c);
conr = readl(i2c->regs + I2C_CONR);
conr &= I2C_CONR_ACK;
writel(conr, i2c->regs + I2C_CONR);
i2c->scl_rate = 400000;
rk29_i2c_clockrate(i2c);
for (i = 0; i < num; i++)
{
@@ -541,16 +504,15 @@ retry:
break;
}
}
conr = readl(i2c->regs + I2C_CONR);
conr &= I2C_CONR_MPORT_DISABLE;
writel(conr, i2c->regs + I2C_CONR);
/*
if( --retry && num < 0)
{
mdelay(1);
udelay(10000 * 1000/i2c->scl_rate);
goto retry;
}
*/
if(num < 0)
dev_err(i2c->dev, "i2c transfer err, client address is 0x%x", msgs[0].addr);
dev_err(i2c->dev, "i2c transfer err, client address is 0x%x [20110106]\n", msgs[0].addr);
return num;
}
@@ -574,21 +536,33 @@ int i2c_suspended(struct i2c_adapter *adap)
return i2c->suspended;
}
EXPORT_SYMBOL(i2c_suspended);
static void rk29_i2c_deinit_hw(struct rk29_i2c_data *i2c)
{
unsigned long opr = readl(i2c->regs + I2C_OPR);
opr &= ~I2C_OPR_RESET_STATUS;
writel(opr, i2c->regs);
return;
}
static void rk29_i2c_init_hw(struct rk29_i2c_data *i2c)
{
unsigned long lcmr = 0x00000000;
unsigned long opr = readl(i2c->regs + I2C_OPR);
opr |= I2C_OPR_RESET_STATUS;
writel(opr, i2c->regs + I2C_OPR);
udelay(10);
opr = readl(i2c->regs + I2C_OPR);
opr &= ~I2C_OPR_RESET_STATUS;
writel(opr, i2c->regs + I2C_OPR);
writel(lcmr, i2c->regs + I2C_LCMR);
rk29_i2c_clockrate(i2c);
rk29_i2c_disable_irqs(i2c);
rk29_i2c_clockrate(i2c);
i2c->io_init();
writel(0, i2c->regs + I2C_LCMR);
writel(0, i2c->regs + I2C_LCMR);
opr = readl(i2c->regs + I2C_OPR);
opr |= I2C_OPR_CORE_ENABLE;
writel(opr, i2c->regs + I2C_OPR);
@@ -647,11 +621,7 @@ static inline void rk29_i2c_unregister_cpufreq(struct rk29_i2c_data *i2c)
static int rk29_i2c_probe(struct platform_device *pdev)
{
struct rk29_i2c_data *i2c;
#ifdef CONFIG_ARCH_RK2818
struct rk2818_i2c_platform_data *pdata = NULL;
#else
struct rk29_i2c_platform_data *pdata = NULL;
#endif
struct resource *res;
int ret;
@@ -719,22 +689,18 @@ static int rk29_i2c_probe(struct platform_device *pdev)
i2c->io_init = pdata->io_init;
pdata->io_init();
}
rk29_i2c_init_hw(i2c);
i2c->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
i2c_err(&pdev->dev, "cannot find IRQ\n");
goto err_iomap;
}
if(i2c->mode == I2C_MODE_IRQ)
{
ret = request_irq(i2c->irq, rk29_i2c_irq, IRQF_DISABLED,
ret = request_irq(i2c->irq, rk29_i2c_irq, IRQF_DISABLED,
dev_name(&pdev->dev), i2c);
if (ret != 0) {
i2c_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
goto err_iomap;
}
if (ret != 0) {
i2c_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
goto err_iomap;
}
ret = rk29_i2c_register_cpufreq(i2c);
if (ret < 0) {
@@ -750,16 +716,16 @@ static int rk29_i2c_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, i2c);
dev_info(&pdev->dev, "%s: RK2818 I2C adapter\n", dev_name(&i2c->adap.dev));
rk29_i2c_init_hw(i2c);
dev_info(&pdev->dev, "%s: RK29 I2C adapter\n", dev_name(&i2c->adap.dev));
return 0;
err_cpufreq:
rk29_i2c_unregister_cpufreq(i2c);
err_irq:
if(i2c->mode == I2C_MODE_IRQ)
free_irq(i2c->irq, i2c);
free_irq(i2c->irq, i2c);
err_iomap:
iounmap(i2c->regs);
@@ -782,11 +748,12 @@ static int rk29_i2c_remove(struct platform_device *pdev)
{
struct rk29_i2c_data *i2c = platform_get_drvdata(pdev);
rk29_i2c_deinit_hw(i2c);
rk29_i2c_unregister_cpufreq(i2c);
i2c_del_adapter(&i2c->adap);
if(i2c->mode == I2C_MODE_IRQ)
free_irq(i2c->irq, i2c);
free_irq(i2c->irq, i2c);
clk_disable(i2c->clk);
clk_put(i2c->clk);
@@ -848,6 +815,6 @@ static void __exit rk29_i2c_adap_exit(void)
subsys_initcall(rk29_i2c_adap_init);
module_exit(rk29_i2c_adap_exit);
MODULE_DESCRIPTION("Driver for RK2818 I2C Bus");
MODULE_DESCRIPTION("Driver for RK29 I2C Bus");
MODULE_AUTHOR("kfx, kfx@rock-chips.com");
MODULE_LICENSE("GPL");