From 0ba70878ffac79edbae612ba7c1d8a3271a8b633 Mon Sep 17 00:00:00 2001 From: kfx Date: Sat, 25 Sep 2010 17:31:03 +0800 Subject: [PATCH] i2c don NOT suspend when system enter sleep --- drivers/i2c/busses/i2c-rk2818.c | 46 ++++++++++++++++++++++++++------- drivers/i2c/i2c-core.c | 6 ++++- include/linux/i2c.h | 1 + 3 files changed, 42 insertions(+), 11 deletions(-) mode change 100644 => 100755 drivers/i2c/i2c-core.c mode change 100644 => 100755 include/linux/i2c.h diff --git a/drivers/i2c/busses/i2c-rk2818.c b/drivers/i2c/busses/i2c-rk2818.c index 9652b945c90d..545ebbfebfe1 100755 --- a/drivers/i2c/busses/i2c-rk2818.c +++ b/drivers/i2c/busses/i2c-rk2818.c @@ -85,7 +85,7 @@ struct rk2818_i2c_data { unsigned int msg_num; #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; -#endif +#endif }; static void rk2818_i2c_init_hw(struct rk2818_i2c_data *i2c); @@ -230,19 +230,22 @@ static int rk2818_wait_event(struct rk2818_i2c_data *i2c, enum rk2818_event mr_event) { int ret = 0; - - if(unlikely(irqs_disabled())) + unsigned long flags; + if(i2c->mode == I2C_MODE_IRQ) { - dev_err(i2c->dev, "irqs are disabled on this system!\n"); - return -EIO; - } - spin_lock_irq(&i2c->cmd_lock); + if(unlikely(irqs_disabled())) + { + dev_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_event = mr_event; init_completion(&i2c->cmd_complete); - spin_unlock_irq(&i2c->cmd_lock); + spin_unlock_irqrestore(&i2c->cmd_lock,flags); rk2818_i2c_enable_irqs(i2c); if(i2c->mode == I2C_MODE_IRQ) @@ -461,6 +464,17 @@ exit: { dev_err(i2c->dev, "rk2818_i2c_stop timeout\n"); } + + //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 + } + } return ret; @@ -473,9 +487,10 @@ static int rk2818_i2c_xfer(struct i2c_adapter *adap, int i; struct rk2818_i2c_data *i2c = (struct rk2818_i2c_data *)adap->algo_data; unsigned long conr = readl(i2c->regs + I2C_CONR); - + /* if(i2c->suspended ==1) return -EIO; + */ if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate > 0) i2c->scl_rate = msgs[0].scl_rate; else @@ -516,7 +531,17 @@ static const struct i2c_algorithm rk2818_i2c_algorithm = { .functionality = rk2818_i2c_func, }; - +int i2c_suspended(struct i2c_adapter *adap) +{ + struct rk2818_i2c_data *i2c = (struct rk2818_i2c_data *)adap->algo_data; + if(adap->nr > 1) + return 1; + if(i2c == NULL) + return 1; + return i2c->suspended; +} +EXPORT_SYMBOL(i2c_suspended); + static void rk2818_i2c_init_hw(struct rk2818_i2c_data *i2c) { unsigned long lcmr = 0x00000000; @@ -735,6 +760,7 @@ static int rk2818_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM + static int rk2818_i2c_suspend(struct platform_device *pdev, pm_message_t state) { struct rk2818_i2c_data *i2c = platform_get_drvdata(pdev); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c old mode 100644 new mode 100755 index d36ea1d6f6ec..5a3264f4abff --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1091,8 +1091,12 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); } #endif - +#ifdef CONFIG_I2C_RK2818 + if (!(i2c_suspended(adap)) && (in_atomic() || irqs_disabled())) { +#else if (in_atomic() || irqs_disabled()) { +#endif + ret = mutex_trylock(&adap->bus_lock); if (!ret) /* I2C activity is ongoing. */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h old mode 100644 new mode 100755 index d1cb39dd68a1..63276d3f88f0 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -62,6 +62,7 @@ extern int i2c_master_reg8_send(struct i2c_client *client, const char reg, const extern int i2c_master_reg8_recv(struct i2c_client *client, const char reg, char *buf, int count, int scl_rate); extern int i2c_master_reg16_send(struct i2c_client *client, const short regs, const short *buf, int count, int scl_rate); extern int i2c_master_reg16_recv(struct i2c_client *client, const short regs, short *buf, int count, int scl_rate); +extern int i2c_suspended(struct i2c_adapter *adap); #endif extern int i2c_master_send(struct i2c_client *client, const char *buf, -- 2.34.1