unsigned long scl_rate;
struct clk *clk;
+ unsigned int mode;
+
unsigned int irq;
spinlock_t cmd_lock;
}
/* scl = pclk/(5 *(rem+1) * 2^(exp+1)) */
-static unsigned long rk2818_i2c_calcdivisor(unsigned long pclk,
+static void rk2818_i2c_calcdivisor(unsigned long pclk,
unsigned long scl_rate,
unsigned long *real_rate,
unsigned int *rem, unsigned int *exp)
{
- unsigned int calc_rem = pclk / (5 * scl_rate);
- unsigned int calc_exp;
+ unsigned int calc_rem = 0;
+ unsigned int calc_exp = 0;
for(calc_exp = 0; calc_exp < I2CCDVR_EXP_MAX; calc_exp++)
{
+ calc_rem = pclk / (5 * scl_rate * (1 <<(calc_exp +1)));
if(calc_rem < I2CCDVR_REM_MAX)
- {
- calc_exp--;
break;
- }
- calc_rem = calc_rem >> 1;
}
- if(calc_rem >= I2CCDVR_REM_MAX)
- return -1;
+ if(calc_rem >= I2CCDVR_REM_MAX || calc_exp >= I2CCDVR_EXP_MAX)
+ {
+ calc_rem = I2CCDVR_REM_MAX - 1;
+ calc_exp = I2CCDVR_EXP_MAX - 1;
+ }
*rem = calc_rem;
*exp = calc_exp;
-
*real_rate = pclk/(5 * (calc_rem + 1) * (1 <<(calc_exp +1)));
- return 0;
+ return;
}
/* set i2c bus scl rate */
static unsigned long rk2818_i2c_clockrate(struct rk2818_i2c_data *i2c)
struct rk2818_i2c_platform_data *pdata = i2c->dev->platform_data;
unsigned int rem = 0, exp = 0;
unsigned long scl_rate, real_rate = 0, tmp, pclk;
- int ret = 0;
struct clk *arm_pclk;
arm_pclk = clk_get_parent(i2c->clk);
if(IS_ERR(arm_pclk))
{
dev_err(i2c->dev, "cannot get pclk\n");
- ret = -ENOENT;
+ return -ENOENT;
}
pclk = clk_get_rate(arm_pclk);
- dev_dbg(i2c->dev, "pdata desired clkrate %lu\n", pdata->scl_rate);
+ scl_rate = (i2c->scl_rate) ? i2c->scl_rate : ((pdata->scl_rate)? pdata->scl_rate:100000);
- scl_rate = pdata->scl_rate ? pdata->scl_rate : 100000;
-
- ret = rk2818_i2c_calcdivisor(pclk, scl_rate, &real_rate, &rem, &exp);
-
- if (ret < 0)
- {
- dev_err(i2c->dev,
- "Unable to achieve desired clkrate %luHz.", scl_rate);
- return -EINVAL;
- }
-
+ rk2818_i2c_calcdivisor(pclk, scl_rate, &real_rate, &rem, &exp);
tmp = readl(i2c->regs + I2C_OPR);
tmp |= exp;
tmp |= rem<<I2CCDVR_EXP_BITS;
writel(tmp, i2c->regs + I2C_OPR);
- dev_dbg(i2c->dev, " Scl real rate is %lu\n", real_rate);
-
- return ret;
+ if(real_rate > 400000)
+ dev_info(i2c->dev, "WARN: PCLK %luKhz, I2C set rate %luKhz, and real rate is %luKhz > 400Khz\n",
+ pclk/1000, scl_rate/1000, real_rate/1000);
+ else
+ dev_dbg(i2c->dev, " OK: PCLK %luKhz, I2C set rate %luKhz, real rate is %luKhz\n",
+ pclk/1000, scl_rate/1000, real_rate/1000);
+ return 0;
}
static int rk2818_event_occurred(struct rk2818_i2c_data *i2c)
{
- unsigned long isr, lsr;
+ unsigned long isr;
isr = readl(i2c->regs + I2C_ISR);
- lsr = readl(i2c->regs + I2C_LSR);
if(isr & I2C_ISR_ARBITR_LOSE)
{
isr &= ~I2C_ISR_ARBITR_LOSE;
break;
}
i2c->cmd_err = RK2818_ERROR_UNKNOWN;
- dev_err(i2c->dev,"Unhandled interrupt!\n");
return 0;
}
{
struct rk2818_i2c_data *i2c = (struct rk2818_i2c_data *)data;
int res;
+
rk2818_i2c_disable_irqs(i2c);
spin_lock(&i2c->cmd_lock);
res = rk2818_event_occurred(i2c);
if(res || i2c->cmd_err != RK2818_ERROR_NONE)
complete(&i2c->cmd_complete);
spin_unlock(&i2c->cmd_lock);
-
return IRQ_HANDLED;
}
+static int wait_for_completion_poll_timeout(struct rk2818_i2c_data *i2c)
+{
+ unsigned long timeout = jiffies + RK2818_I2C_TIMEOUT;
+ unsigned int time = 10;
+ int res;
+ while(!time_after(jiffies, timeout))
+ {
+ dev_dbg(i2c->dev, "%s: time = %d\n", __func__, time);
+ res = rk2818_event_occurred(i2c);
+ if(res || i2c->cmd_err != RK2818_ERROR_NONE)
+ return 1;
+ udelay(time);
+ time *= 2;
+ }
+ return 0;
+
+}
static int rk2818_wait_event(struct rk2818_i2c_data *i2c,
enum rk2818_event mr_event)
{
int ret = 0;
+
if(unlikely(irqs_disabled()))
{
dev_err(i2c->dev, "irqs are disabled on this system!\n");
spin_unlock_irq(&i2c->cmd_lock);
rk2818_i2c_enable_irqs(i2c);
- ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete,
+ if(i2c->mode == I2C_MODE_IRQ)
+ {
+ ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete,
RK2818_I2C_TIMEOUT);
-
+ }
+ else
+ {
+ ret = wait_for_completion_poll_timeout(i2c);
+ dev_dbg(i2c->dev, "%s: ret = %d\n", __func__, ret);
+ }
if(ret < 0)
{
dev_err(i2c->dev, "wait_for_completion_interruptible_timeout(): "
}
clk_enable(i2c->clk);
- if(msg->scl_rate)
- i2c->scl_rate = msg->scl_rate;
- rk2818_i2c_clockrate(i2c);
ret = rk2818_send_address(i2c, msg);
if(ret != 0)
if(i2c->suspended ==1)
return -EIO;
- i2c->scl_rate = msgs[0].scl_rate;
+ if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate > 0)
+ {
+ i2c->scl_rate = msgs[0].scl_rate;
+ }
+ else
+ {
+ dev_info(i2c->dev, "Scl_rate(%uKhz) is failed to change[0 -- 400Khz], current rate(%luKhz)\n",
+ msgs[0].scl_rate/1000, i2c->scl_rate/1000);
+ }
+
ret = rk2818_i2c_init_hw(i2c);
if(ret < 0)
return ret;
dev_err(&pdev->dev, "no memory for state\n");
return -ENOMEM;
}
+ i2c->mode = pdata->mode;
+ i2c->scl_rate = (pdata->scl_rate) ? pdata->scl_rate : 100000;
strlcpy(i2c->adap.name, DRV_NAME, sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;
dev_err(&pdev->dev, "cannot find IRQ\n");
goto err_iomap;
}
+ if(i2c->mode == I2C_MODE_IRQ)
+ {
+ ret = request_irq(i2c->irq, rk2818_i2c_irq, IRQF_DISABLED,
+ dev_name(&pdev->dev), i2c);
- ret = request_irq(i2c->irq, rk2818_i2c_irq, IRQF_DISABLED,
- dev_name(&pdev->dev), i2c);
-
- if (ret != 0) {
- dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
- goto err_iomap;
+ if (ret != 0) {
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
+ goto err_iomap;
+ }
}
-
ret = rk2818_i2c_register_cpufreq(i2c);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
platform_set_drvdata(pdev, i2c);
- dev_dbg(&pdev->dev, "%s: RK2818 I2C adapter\n", dev_name(&i2c->adap.dev));
+ dev_info(&pdev->dev, "%s: RK2818 I2C adapter\n", dev_name(&i2c->adap.dev));
return 0;
err_cpufreq:
rk2818_i2c_unregister_cpufreq(i2c);
err_irq:
- free_irq(i2c->irq, i2c);
+ if(i2c->mode == I2C_MODE_IRQ)
+ free_irq(i2c->irq, i2c);
err_iomap:
iounmap(i2c->regs);
rk2818_i2c_unregister_cpufreq(i2c);
i2c_del_adapter(&i2c->adap);
- free_irq(i2c->irq, i2c);
+ if(i2c->mode == I2C_MODE_IRQ)
+ free_irq(i2c->irq, i2c);
clk_disable(i2c->clk);
clk_put(i2c->clk);