mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
update i2c drivers
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user