I2C patches for v3.8 merge window
Subsystems (8)
cover I2C patches for v3.8 merge window
Hi guys,
here's another series for OMAP I2C driver. There are a few cleanups and one very nice new feature: we can now report how many bytes we transferred until NACK.
Note that the implemementation for OMAP-I2C turned out to be a little more complex then I expected, mainly because of the way I2C_CNT register behaves and because of the very buggy register usage on that driver.
I have boot tested all patches on beagle xM (3630) and pandaboard rev A3 (4430), will send boot-logs if anyone wants to see.
All patches are available at [1] if anyone wants an easy way to test the patches.
[1] git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git i2c-transferred-bytes-on-NACK
Felipe Balbi (7):
i2c: omap: no need to access platform_device
i2c: omap: reorder exit path of omap_i2c_xfer_msg()
i2c: omap: fix error checking
i2c: omap: also complete() when stat becomes zero
i2c: omap: introduce and use OMAP_I2C_IP_VERSION_3
i2c: omap: wait for transfer completion before sending STP bit
i2c: omap: implement handling for 'transferred' bytes
Shubhrajyoti D (1):
i2c: add 'transferred' field to struct i2c_msg
arch/arm/mach-omap2/i2c.c | 3 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- drivers/i2c/busses/i2c-omap.c | 156 ++++++++++++++++------------- include/linux/i2c-omap.h | 1 + include/uapi/linux/i2c.h | 1 + 5 files changed, 89 insertions(+), 74 deletions(-)
Signature · 1 line
1.8.0.rc0
PATCH 1/8 i2c: omap: no need to access platform_device
PM callbacks pass our device pointer as argument
and we don't need to access the platform_device
just to dereference that down to dev->drvdata.
instead, just use dev_get_drvdata() directly.
--- drivers/i2c/busses/i2c-omap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/i2c/busses/i2c-omap.c +2 -4
@@ -1239,8 +1239,7 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev)#ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend (struct device *dev) { -struct platform_device *pdev =to_platform_device (dev); -struct omap_i2c_dev *_dev =platform_get_drvdata (pdev); +struct omap_i2c_dev *_dev =dev_get_drvdata (dev);u16 iv; _dev->iestate =omap_i2c_read_reg (_dev,OMAP_I2C_IE_REG );
@@ -1261,8 +1260,7 @@ static int omap_i2c_runtime_suspend(struct device *dev)static int omap_i2c_runtime_resume (struct device *dev) { -struct platform_device *pdev =to_platform_device (dev); -struct omap_i2c_dev *_dev =platform_get_drvdata (pdev); +struct omap_i2c_dev *_dev =dev_get_drvdata (dev);if (_dev->flags &OMAP_I2C_FLAG_RESET_REGS_POSTIDLE ) {omap_i2c_write_reg (_dev,OMAP_I2C_CON_REG ,0 );
Signature · 1 line
1.8.0.rc0
PATCH 2/8 i2c: omap: reorder exit path of omap_i2c_xfer_msg()
In reply to Felipe Balbijust a cleanup patch trying to make exit path
more straightforward. No changes otherwise.
--- drivers/i2c/busses/i2c-omap.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
drivers/i2c/busses/i2c-omap.c +17 -9
@@ -505,6 +505,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; +int ret;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
@@ -582,31 +583,38 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf_len =0 ;if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); -omap_i2c_init (dev); -return -ETIMEDOUT ; + ret = -ETIMEDOUT ; + goto err_i2c_init; } -if (likely (!dev->cmd_err)) -return 0 ; -/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { -omap_i2c_init (dev); -return -EIO ; + ret = -EIO ; + goto err_i2c_init; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; +if (stop) { w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); w |=OMAP_I2C_CON_STP ;omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); } -return -EREMOTEIO ; + + ret = -EREMOTEIO ; + goto err; } -return -EIO ; + +return 0 ; + +err_i2c_init: +omap_i2c_init (dev); + +err: +return ret; }
Signature · 1 line
1.8.0.rc0
PATCH 2/8 i2c: omap: reorder exit path of omap_i2c_xfer_msg()
Quoted 45 lines · Felipe Balbi
just a cleanup patch trying to make exit path
more straightforward. No changes otherwise.Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)drivers/i2c/busses/i2c-omap.c +5
-7@@ -505,6 +505,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; +int ret;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",@@ -582,31 +583,38 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf_len =0 ;if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); -omap_i2c_init (dev); -return -ETIMEDOUT ; + ret = -ETIMEDOUT ; + goto err_i2c_init; } -if (likely (!dev->cmd_err)) -return 0 ; -/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { -omap_i2c_init (dev); -return -EIO ; + ret = -EIO ; + goto err_i2c_init; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ;
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 608
Quoted 10 lines
drivers/i2c/busses/i2c-omap.c +4
-1+if (stop) { w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); w |=OMAP_I2C_CON_STP ;omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); } -return -EREMOTEIO ; + + ret = -EREMOTEIO ; + goto err;
This adds reset to nack may be that can be removed.
Quoted 20 lines
drivers/i2c/busses/i2c-omap.c +8
-2} -return -EIO ; + +return 0 ; + +err_i2c_init: +omap_i2c_init (dev); + +err: +return ret; } --1.8.0.rc0
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/8 i2c: omap: reorder exit path of omap_i2c_xfer_msg()
Hi,
Quoted 43 lines · Shubhrajyoti Datta
Quoted 42 lines · Felipe Balbi
just a cleanup patch trying to make exit path
more straightforward. No changes otherwise.Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)drivers/i2c/busses/i2c-omap.c +5
-7@@ -505,6 +505,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; +int ret;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",@@ -582,31 +583,38 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf_len =0 ;if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); -omap_i2c_init (dev); -return -ETIMEDOUT ; + ret = -ETIMEDOUT ; + goto err_i2c_init; } -if (likely (!dev->cmd_err)) -return 0 ; -/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { -omap_i2c_init (dev); -return -EIO ; + ret = -EIO ; + goto err_i2c_init; }
Quoted 15 lines
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 608
Quoted 13 lines
drivers/i2c/busses/i2c-omap.c +4
-1if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; +if (stop) { w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); w |=OMAP_I2C_CON_STP ;omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); } -return -EREMOTEIO ; + + ret = -EREMOTEIO ; + goto err;This adds reset to nack may be that can be removed.
great catch. I will respin this series.
thanks
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/ee1f2e15/attachment-0001.sig>
PATCH 3/8 i2c: omap: fix error checking
In reply to Felipe BalbiIt's impossible to have Arbitration Lost, Read Overflow, and Tranmist Underflow all asserted at the same time.
Those error conditions are mutually exclusive so what the code should be doing, instead, is check each error flag separataly.
--- drivers/i2c/busses/i2c-omap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/i2c/busses/i2c-omap.c +3 -3
@@ -587,9 +587,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto err_i2c_init; } -/* We have an error */ -if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR | -OMAP_I2C_STAT_XUDF )) { +if ((dev->cmd_err &OMAP_I2C_STAT_AL ) + || (dev->cmd_err &OMAP_I2C_STAT_ROVR ) + || (dev->cmd_err &OMAP_I2C_STAT_XUDF )) { ret = -EIO ; goto err_i2c_init; }
Signature · 1 line
1.8.0.rc0
PATCH 3/8 i2c: omap: fix error checking
Hi
Quoted 18 lines · Felipe Balbi
It's impossible to have Arbitration Lost, Read Overflow, and Tranmist Underflow all asserted at the same time.
Those error conditions are mutually exclusive so what the code should be doing, instead, is check each error flag separataly.
Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/i2c/busses/i2c-omap.c +0
-0
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 592
Quoted 9 lines
drivers/i2c/busses/i2c-omap.c +3
-3@@ -587,9 +587,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto err_i2c_init; } -/* We have an error */ -if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR | -OMAP_I2C_STAT_XUDF )) { +if ((dev->cmd_err &OMAP_I2C_STAT_AL ) + || (dev->cmd_err &OMAP_I2C_STAT_ROVR ) + || (dev->cmd_err &OMAP_I2C_STAT_XUDF )) {
Sorry, what is the difference? I didn't understand the optimisation and why now is more clear. Can you just add a comment?
Michael
Quoted 4 lines
drivers/i2c/busses/i2c-omap.c +0
-0ret = -EIO ; goto err_i2c_init; }
PATCH 3/8 i2c: omap: fix error checking
Hi,
Quoted 24 lines · Michael Trimarchi
Hi
Quoted 21 lines · Felipe Balbi
It's impossible to have Arbitration Lost, Read Overflow, and Tranmist Underflow all asserted at the same time.
Those error conditions are mutually exclusive so what the code should be doing, instead, is check each error flag separataly.
Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/i2c/busses/i2c-omap.c +0
-0@@ -587,9 +587,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto err_i2c_init; }
Quoted 9 lines
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 592
Quoted 6 lines
drivers/i2c/busses/i2c-omap.c +3
-3-/* We have an error */ -if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR | -OMAP_I2C_STAT_XUDF )) { +if ((dev->cmd_err &OMAP_I2C_STAT_AL ) + || (dev->cmd_err &OMAP_I2C_STAT_ROVR ) + || (dev->cmd_err &OMAP_I2C_STAT_XUDF )) {Sorry, what is the difference? I didn't understand the optimisation and why now is more clear. Can you just add a comment?
semantically they're not the same, right ? We want to check if each of those bits are set, not if all of them are set together.
my 2 cents.
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/f3659a9c/attachment.sig>
PATCH 3/8 i2c: omap: fix error checking
Hi
Quoted 37 lines · Felipe Balbi
Hi,
Quoted 24 lines · Michael Trimarchi
Hi
Quoted 21 lines · Felipe Balbi
It's impossible to have Arbitration Lost, Read Overflow, and Tranmist Underflow all asserted at the same time.
Those error conditions are mutually exclusive so what the code should be doing, instead, is check each error flag separataly.
Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)drivers/i2c/busses/i2c-omap.c +0
-0@@ -587,9 +587,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto err_i2c_init; }Quoted 9 lines
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 592
Quoted 6 lines
drivers/i2c/busses/i2c-omap.c +3
-3-/* We have an error */ -if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR | -OMAP_I2C_STAT_XUDF )) { +if ((dev->cmd_err &OMAP_I2C_STAT_AL ) + || (dev->cmd_err &OMAP_I2C_STAT_ROVR ) + || (dev->cmd_err &OMAP_I2C_STAT_XUDF )) {Sorry, what is the difference? I didn't understand the optimisation and why now is more clear. Can you just add a comment?
Quoted 4 lines
semantically they're not the same, right ? We want to check if each of those bits are set, not if all of them are set together.
my 2 cents.
You are doing the same thing, but of course is better with just one *if* as before . A general rule is: when you have logic expression you can use undefined states to simplify the logic.
Michael
PATCH 3/8 i2c: omap: fix error checking
Hi,
Quoted 14 lines · Michael Trimarchi
Quoted 14 lines
Quoted 13 lines
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 592
Quoted 10 lines
drivers/i2c/busses/i2c-omap.c +3
-3@@ -587,9 +587,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto err_i2c_init; } -/* We have an error */ -if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR | -OMAP_I2C_STAT_XUDF )) { +if ((dev->cmd_err &OMAP_I2C_STAT_AL ) + || (dev->cmd_err &OMAP_I2C_STAT_ROVR ) + || (dev->cmd_err &OMAP_I2C_STAT_XUDF )) {Sorry, what is the difference? I didn't understand the optimisation and why now is more clear. Can you just add a comment?
Quoted 6 lines
Quoted 4 lines
semantically they're not the same, right ? We want to check if each of those bits are set, not if all of them are set together.
my 2 cents.
You are doing the same thing, but of course is better with just one
I never claimed the contrary. I said *semantically* they're not the same.
Quoted 1 line
*if* as before . A general rule is: when you have logic expression you
We still have a single *if* and I'm sure compiler will optimize that expression as much as it likes.
Quoted 1 line
can use undefined states to simplify the logic.
don't-care is not the same as undefined states.
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/cbb6ab32/attachment.sig>
PATCH 4/8 i2c: omap: also complete() when stat becomes zero
In reply to Felipe BalbiIn case we loop on IRQ handler until stat is finally zero, we would end up in a situation where all I2C transfers would misteriously timeout because we were not calling complete() in that situation.
Fix the issue by moving omap_i2c_complete_cmd() call inside the 'out' label.
--- drivers/i2c/busses/i2c-omap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +1 -2
@@ -1021,9 +1021,8 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) } }while (stat); -omap_i2c_complete_cmd (dev, err); - out: +omap_i2c_complete_cmd (dev, err);spin_unlock_irqrestore (&dev->lock, flags);return IRQ_HANDLED ;
Signature · 1 line
1.8.0.rc0
PATCH 5/8 i2c: omap: introduce and use OMAP_I2C_IP_VERSION_3
In reply to Felipe Balbion OMAP4+ we want to read IRQSTATUS_RAW register, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled on IRQENABLE_SET and that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.
One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Note, however, that omap-i2c.c needs a big rework on register definition and register access. Such work will be done in a separate series of patches.
--- arch/arm/mach-omap2/i2c.c | 3 ++- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- drivers/i2c/busses/i2c-omap.c | 26 ++++++++++++++++++++++---- include/linux/i2c-omap.h | 1 + 4 files changed, 26 insertions(+), 6 deletions(-)
arch/arm/mach-omap2/i2c.c +2 -1
@@ -66,7 +66,8 @@ int omap_i2c_reset(struct omap_hwmod *oh)u16 i2c_con;int c =0 ; -if (oh->class->rev ==OMAP_I2C_IP_VERSION_2 ) { +if ((oh->class->rev ==OMAP_I2C_IP_VERSION_2 ) || + (oh->class->rev ==OMAP_I2C_IP_VERSION_3 )) { i2c_con =OMAP4_I2C_CON_OFFSET ; }else if (oh->class->rev ==OMAP_I2C_IP_VERSION_1 ) { i2c_con =OMAP2_I2C_CON_OFFSET ;
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +1 -1
@@ -1521,7 +1521,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {static struct omap_hwmod_class omap44xx_i2c_hwmod_class = { .name ="i2c" , .sysc = &omap44xx_i2c_sysc, - .rev =OMAP_I2C_IP_VERSION_2 , + .rev =OMAP_I2C_IP_VERSION_3 , .reset = &omap_i2c_reset, };
drivers/i2c/busses/i2c-omap.c +22 -4
@@ -271,8 +271,18 @@ static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,static inline u16 omap_i2c_read_reg (struct omap_i2c_dev *i2c_dev,int reg) { -return __raw_readw (i2c_dev->base + +/* if we are OMAP_I2C_IP_VERSION_3, we need to read from +* IRQSTATUS_RAW, but write to IRQSTATUS +*/ +if ((i2c_dev->dtrev ==OMAP_I2C_IP_VERSION_3 ) && + (reg ==OMAP_I2C_STAT_REG )) { +return __raw_readw (i2c_dev->base + + ((i2c_dev->regs[reg] -0x04 ) + << i2c_dev->reg_shift)); + }else { +return __raw_readw (i2c_dev->base + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); + } }static int omap_i2c_init (struct omap_i2c_dev *dev)
@@ -1124,10 +1134,18 @@ omap_i2c_probe(struct platform_device *pdev) dev->reg_shift = (dev->flags >>OMAP_I2C_FLAG_BUS_SHIFT__SHIFT ) &3 ; -if (dev->dtrev ==OMAP_I2C_IP_VERSION_2 ) - dev->regs = (u8 *)reg_map_ip_v2; -else +switch (dev->dtrev) { +case OMAP_I2C_IP_VERSION_1 : dev->regs = (u8 *)reg_map_ip_v1; +break ; +case OMAP_I2C_IP_VERSION_2 : +/* FALLTHROUGH */ +case OMAP_I2C_IP_VERSION_3 : +/* FALLTHROUGH */ +default : + dev->regs = (u8 *)reg_map_ip_v2; +break ; + }pm_runtime_enable (dev->dev);pm_runtime_set_autosuspend_delay (dev->dev,OMAP_I2C_PM_TIMEOUT );
include/linux/i2c-omap.h +1 -0
@@ -14,6 +14,7 @@#define OMAP_I2C_IP_VERSION_1 1#define OMAP_I2C_IP_VERSION_2 2 +#define OMAP_I2C_IP_VERSION_3 3/* struct omap_i2c_bus_platform_data .flags meanings */
Signature · 1 line
1.8.0.rc0
PATCH 5/8 i2c: omap: introduce and use OMAP_I2C_IP_VERSION_3
Hi Felipe,
Quoted 13 lines · Felipe Balbi
on OMAP4+ we want to read
IRQSTATUS_RAWregister, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled onIRQENABLE_SETand that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Quoted 3 lines
Note, however, that
omap-i2c.cneeds a big rework on register definition and register access. Such work will be done in a separate series of patches.
Do you need OMAP_I2C_IP_VERSION_3 for OMAP4?
OMAP_I2C_IP_VERSION_2 was already introduced to detect OMAP3630 vs omap4430 because they were sharing the same IP version..
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_3430_3530 0x3C #define OMAP_I2C_REV_ON_3630_4430 0x40
So in theory you should not need an extra version.
Regards,
Benoit
PATCH 5/8 i2c: omap: introduce and use OMAP_I2C_IP_VERSION_3
Hi,
Quoted 25 lines · Benoit Cousson
Hi Felipe,
Quoted 13 lines · Felipe Balbi
on OMAP4+ we want to read
IRQSTATUS_RAWregister, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled onIRQENABLE_SETand that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Quoted 3 lines
Note, however, that
omap-i2c.cneeds a big rework on register definition and register access. Such work will be done in a separate series of patches.Do you need
OMAP_I2C_IP_VERSION_3for OMAP4?
OMAP_I2C_IP_VERSION_2was already introduced to detect OMAP3630 vs omap4430 because they were sharing the same IP version..
Quoted 6 lines
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_3430_3530 0x3C #define OMAP_I2C_REV_ON_3630_4430 0x40So in theory you should not need an extra version.
are you sure that's how they're used ? Looking at the code where we choose reg_map_ip_v1 and reg_map_ip_v2:
1120 if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
1121 dev->regs = (u8 *)reg_map_ip_v2;
1122 else
1123 dev->regs = (u8 *)reg_map_ip_v1;
And looking at reg_map_ip_v1:
218 static const u8 reg_map_ip_v1[] = {
219 [OMAP_I2C_REV_REG] = 0x00, 220 [OMAP_I2C_IE_REG] = 0x01, 221 [OMAP_I2C_STAT_REG] = 0x02, 222 [OMAP_I2C_IV_REG] = 0x03, 223 [OMAP_I2C_WE_REG] = 0x03, 224 [OMAP_I2C_SYSS_REG] = 0x04, 225 [OMAP_I2C_BUF_REG] = 0x05, 226 [OMAP_I2C_CNT_REG] = 0x06, 227 [OMAP_I2C_DATA_REG] = 0x07, 228 [OMAP_I2C_SYSC_REG] = 0x08, 229 [OMAP_I2C_CON_REG] = 0x09, 230 [OMAP_I2C_OA_REG] = 0x0a, 231 [OMAP_I2C_SA_REG] = 0x0b, 232 [OMAP_I2C_PSC_REG] = 0x0c, 233 [OMAP_I2C_SCLL_REG] = 0x0d, 234 [OMAP_I2C_SCLH_REG] = 0x0e, 235 [OMAP_I2C_SYSTEST_REG] = 0x0f, 236 [OMAP_I2C_BUFSTAT_REG] = 0x10,
237 };
that's really not the register map on OMAP3. That only looks valid for OMAP1.
-ECONFUSED
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121022/d5deb0e8/attachment.sig>
PATCH 5/8 i2c: omap: introduce and use OMAP_I2C_IP_VERSION_3
Quoted 64 lines · Felipe Balbi
Hi,
Quoted 25 lines · Benoit Cousson
Hi Felipe,
Quoted 13 lines · Felipe Balbi
on OMAP4+ we want to read
IRQSTATUS_RAWregister, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled onIRQENABLE_SETand that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Quoted 3 lines
Note, however, that
omap-i2c.cneeds a big rework on register definition and register access. Such work will be done in a separate series of patches.Do you need
OMAP_I2C_IP_VERSION_3for OMAP4?
OMAP_I2C_IP_VERSION_2was already introduced to detect OMAP3630 vs omap4430 because they were sharing the same IP version..Quoted 6 lines
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_3430_3530 0x3C #define OMAP_I2C_REV_ON_3630_4430 0x40So in theory you should not need an extra version.
are you sure that's how they're used ? Looking at the code where we choose
reg_map_ip_v1andreg_map_ip_v2:1120 if (
dev->dtrev==OMAP_I2C_IP_VERSION_2)
1121dev->regs= (u8 *)reg_map_ip_v2;
1122 else
1123dev->regs= (u8 *)reg_map_ip_v1;And looking at
reg_map_ip_v1:218 static const u8 reg_map_ip_v1[] = {
219 [OMAP_I2C_REV_REG] = 0x00, 220 [OMAP_I2C_IE_REG] = 0x01, 221 [OMAP_I2C_STAT_REG] = 0x02, 222 [OMAP_I2C_IV_REG] = 0x03, 223 [OMAP_I2C_WE_REG] = 0x03, 224 [OMAP_I2C_SYSS_REG] = 0x04, 225 [OMAP_I2C_BUF_REG] = 0x05, 226 [OMAP_I2C_CNT_REG] = 0x06, 227 [OMAP_I2C_DATA_REG] = 0x07, 228 [OMAP_I2C_SYSC_REG] = 0x08, 229 [OMAP_I2C_CON_REG] = 0x09, 230 [OMAP_I2C_OA_REG] = 0x0a, 231 [OMAP_I2C_SA_REG] = 0x0b, 232 [OMAP_I2C_PSC_REG] = 0x0c, 233 [OMAP_I2C_SCLL_REG] = 0x0d, 234 [OMAP_I2C_SCLH_REG] = 0x0e, 235 [OMAP_I2C_SYSTEST_REG] = 0x0f, 236 [OMAP_I2C_BUFSTAT_REG] = 0x10,
Quoted 4 lines
237 };
that's really not the register map on OMAP3. That only looks valid for OMAP1.
No that should be valid as well for OMAP2&3 thanks to the OMAP_I2C_FLAG_BUS_SHIFT_2.
It was introduced during DT adaptation:
#ifdef CONFIG_OF
static struct omap_i2c_bus_platform_data omap3_pdata = {
.rev = OMAP_I2C_IP_VERSION_1,
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
};static struct omap_i2c_bus_platform_data omap4_pdata = {
.rev = OMAP_I2C_IP_VERSION_2,
};static const struct of_device_id omap_i2c_of_match[] = {
{
.compatible = "ti,omap4-i2c",
.data = &omap4_pdata,
},
{
.compatible = "ti,omap3-i2c",
.data = &omap3_pdata,
},
{ },
};MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
#endif
Quoted 1 line
-ECONFUSED
Well, it is confusing...
Benoit
PATCH 5/8 i2c: omap: introduce and use OMAP_I2C_IP_VERSION_3
Hi,
Quoted 67 lines · Benoit Cousson
Quoted 66 lines · Felipe Balbi
Hi,
Quoted 25 lines · Benoit Cousson
Hi Felipe,
Quoted 13 lines · Felipe Balbi
on OMAP4+ we want to read
IRQSTATUS_RAWregister, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled onIRQENABLE_SETand that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Quoted 3 lines
Note, however, that
omap-i2c.cneeds a big rework on register definition and register access. Such work will be done in a separate series of patches.Do you need
OMAP_I2C_IP_VERSION_3for OMAP4?
OMAP_I2C_IP_VERSION_2was already introduced to detect OMAP3630 vs omap4430 because they were sharing the same IP version..Quoted 6 lines
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_3430_3530 0x3C #define OMAP_I2C_REV_ON_3630_4430 0x40So in theory you should not need an extra version.
are you sure that's how they're used ? Looking at the code where we choose
reg_map_ip_v1andreg_map_ip_v2:1120 if (
dev->dtrev==OMAP_I2C_IP_VERSION_2)
1121dev->regs= (u8 *)reg_map_ip_v2;
1122 else
1123dev->regs= (u8 *)reg_map_ip_v1;And looking at
reg_map_ip_v1:218 static const u8 reg_map_ip_v1[] = {
219 [OMAP_I2C_REV_REG] = 0x00, 220 [OMAP_I2C_IE_REG] = 0x01, 221 [OMAP_I2C_STAT_REG] = 0x02, 222 [OMAP_I2C_IV_REG] = 0x03, 223 [OMAP_I2C_WE_REG] = 0x03, 224 [OMAP_I2C_SYSS_REG] = 0x04, 225 [OMAP_I2C_BUF_REG] = 0x05, 226 [OMAP_I2C_CNT_REG] = 0x06, 227 [OMAP_I2C_DATA_REG] = 0x07, 228 [OMAP_I2C_SYSC_REG] = 0x08, 229 [OMAP_I2C_CON_REG] = 0x09, 230 [OMAP_I2C_OA_REG] = 0x0a, 231 [OMAP_I2C_SA_REG] = 0x0b, 232 [OMAP_I2C_PSC_REG] = 0x0c, 233 [OMAP_I2C_SCLL_REG] = 0x0d, 234 [OMAP_I2C_SCLH_REG] = 0x0e, 235 [OMAP_I2C_SYSTEST_REG] = 0x0f, 236 [OMAP_I2C_BUFSTAT_REG] = 0x10,237 };
Quoted 5 lines
Quoted 2 lines
that's really not the register map on OMAP3. That only looks valid for OMAP1.
No that should be valid as well for OMAP2&3 thanks to the
OMAP_I2C_FLAG_BUS_SHIFT_2.
aha.. I see. What a hack!
Quoted 25 lines
It was introduced during DT adaptation:
#ifdef
CONFIG_OFstatic struct omap_i2c_bus_platform_data omap3_pdata = { .rev = OMAP_I2C_IP_VERSION_1, .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | OMAP_I2C_FLAG_RESET_REGS_POSTIDLE | OMAP_I2C_FLAG_BUS_SHIFT_2, };static struct omap_i2c_bus_platform_data omap4_pdata = { .rev = OMAP_I2C_IP_VERSION_2, };static const struct of_device_id omap_i2c_of_match[] = { { .compatible = "ti,omap4-i2c", .data = &omap4_pdata, }, { .compatible = "ti,omap3-i2c", .data = &omap3_pdata, }, { }, };
Quoted 7 lines
MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
#endifQuoted 1 line
-ECONFUSEDWell, it is confusing...
Tell me about it... in that case, $SUBJECT can be dropped silently, I will respin next patch so that it checks for VERSION_2 instead of VERSION_3.
cheers.
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121022/fb9efdd5/attachment.sig>
PATCH v2 5/8 i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to IRQSTATUS
In reply to Felipe Balbion OMAP4+ we want to read IRQSTATUS_RAW register, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled on IRQENABLE_SET and that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.
One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Note, however, that omap-i2c.c needs a big rework on register definition and register access. Such work will be done in a separate series of patches.
--- drivers/i2c/busses/i2c-omap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-omap.c +11 -1
@@ -271,8 +271,18 @@ static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,static inline u16 omap_i2c_read_reg (struct omap_i2c_dev *i2c_dev,int reg) { -return __raw_readw (i2c_dev->base + +/* if we are OMAP_I2C_IP_VERSION_2, we need to read from +* IRQSTATUS_RAW, but write to IRQSTATUS +*/ +if ((i2c_dev->dtrev ==OMAP_I2C_IP_VERSION_2 ) && + (reg ==OMAP_I2C_STAT_REG )) { +return __raw_readw (i2c_dev->base + + ((i2c_dev->regs[reg] -0x04 ) + << i2c_dev->reg_shift)); + }else { +return __raw_readw (i2c_dev->base + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); + } }static int omap_i2c_init (struct omap_i2c_dev *dev)
Signature · 1 line
1.8.0.rc0
PATCH 6/8 i2c: omap: wait for transfer completion before sending STP bit
In reply to Felipe BalbiLater patches will come adding support for reporting amount of bytes transferred so that client drivers can count how many bytes are left to transfer.
This is useful mostly in case of NACKs when client driver wants to know exactly which byte got NACKed so it doesn't have to resend all bytes again.
In order to make that work with OMAP's I2C controller, we need to prevent sending STP bit until message is transferred. The reason behind that is because OMAP_I2C_CNT_REG gets reset to original value after STP bit is shifted through I2C_SDA line and that would prevent us from reading the correct number of bytes left to transfer.
The full programming model suggested by IP owner was the following:
- start I2C transfer (without STP bit)
- upon completion or NACK, read I2C_CNT register
- write STP bit to I2C_CON register
- wait for ARDY bit
With this patch we're implementing all steps except step #2 which will come in a later patch adding such support.
--- drivers/i2c/busses/i2c-omap.c | 101 ++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 62 deletions(-)
drivers/i2c/busses/i2c-omap.c +33 -56
@@ -438,9 +438,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)/* Enable interrupts */ dev->iestate = (OMAP_I2C_IE_XRDY |OMAP_I2C_IE_RRDY | -OMAP_I2C_IE_ARDY |OMAP_I2C_IE_NACK | -OMAP_I2C_IE_AL ) | ((dev->fifo_size) ? - (OMAP_I2C_IE_RDR |OMAP_I2C_IE_XDR ) :0 ); +OMAP_I2C_IE_NACK |OMAP_I2C_IE_AL ) | + ((dev->fifo_size) ? (OMAP_I2C_IE_RDR | +OMAP_I2C_IE_XDR ) :0 );omap_i2c_write_reg (dev,OMAP_I2C_IE_REG , dev->iestate);if (dev->flags &OMAP_I2C_FLAG_RESET_REGS_POSTIDLE ) { dev->pscstate = psc;
@@ -470,6 +476,22 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)return 0 ; } +static int omap_i2c_wait_for_ardy (struct omap_i2c_dev *dev) +{ +unsigned long timeout; + + timeout = jiffies +OMAP_I2C_TIMEOUT ; +while (!(omap_i2c_read_reg (dev,OMAP_I2C_STAT_REG ) &OMAP_I2C_STAT_ARDY )) { +if (time_after (jiffies, timeout)) { +dev_warn (dev->dev,"timeout waiting for access ready\n" ); +return -ETIMEDOUT ; + } +usleep_range (800 ,1200 ); + } + +return 0 ; +} +static void omap_i2c_resize_fifo (struct omap_i2c_dev *dev,u8 size,bool is_rx) {u16 buf;
@@ -515,7 +537,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; -int ret; +int ret =0 ;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
@@ -556,35 +578,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (!(msg->flags &I2C_M_RD )) w |=OMAP_I2C_CON_TRX ; -if (!dev->b_hw && stop) - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w);/* -* Don't write stt and stp together on some hardware. -*/ -if (dev->b_hw && stop) { -unsigned long delay = jiffies +OMAP_I2C_TIMEOUT ; -u16 con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); -while (con &OMAP_I2C_CON_STT ) { - con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - -/* Let the user know if i2c is in a bad state */ -if (time_after (jiffies, delay)) { -dev_err (dev->dev,"controller timed out " -"waiting for start condition to finish\n" ); -return -ETIMEDOUT ; - } -cpu_relax (); - } - - w |=OMAP_I2C_CON_STP ; - w &= ~OMAP_I2C_CON_STT ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - -/* * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */
@@ -594,36 +590,36 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); ret = -ETIMEDOUT ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }if ((dev->cmd_err &OMAP_I2C_STAT_AL ) || (dev->cmd_err &OMAP_I2C_STAT_ROVR ) || (dev->cmd_err &OMAP_I2C_STAT_XUDF )) { ret = -EIO ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; -if (stop) { - w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - ret = -EREMOTEIO ; - goto err; +omap_i2c_init (dev); } -return 0 ; +out: -err_i2c_init: -omap_i2c_init (dev); +if (stop) { + w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); + w |=OMAP_I2C_CON_STP ; +omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); + + ret =omap_i2c_wait_for_ardy (dev); + } -err:return ret; }
@@ -947,19 +937,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)break ; } -/* -* ProDB0017052: Clear ARDY bit twice -*/ -if (stat & (OMAP_I2C_STAT_ARDY |OMAP_I2C_STAT_NACK | -OMAP_I2C_STAT_AL )) { -omap_i2c_ack_stat (dev, (OMAP_I2C_STAT_RRDY | -OMAP_I2C_STAT_RDR | -OMAP_I2C_STAT_XRDY | -OMAP_I2C_STAT_XDR | -OMAP_I2C_STAT_ARDY )); -break ; - } -if (stat &OMAP_I2C_STAT_RDR ) {u8 num_bytes =1 ;
Signature · 1 line
1.8.0.rc0
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
In reply to Felipe BalbiFrom: Shubhrajyoti D <[email protected]>
In case of a NACK, it's wise to tell our clients drivers about how many bytes were actually transferred.
Support this by adding an extra field to the struct i2c_msg which gets incremented the amount of bytes actually transferred.
--- include/uapi/linux/i2c.h | 1 + 1 file changed, 1 insertion(+)
include/uapi/linux/i2c.h +1 -0
@@ -77,6 +77,7 @@ struct i2c_msg {#define I2C_M_NO_RD_ACK 0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400/* length will be first received byte */ __u16 len;/* msg length */ +__u16 transferred;/* actual bytes transferred */ __u8 *buf;/* pointer to msg data */ };
Signature · 1 line
1.8.0.rc0
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Hi Felipe, Shubhrajyoti,
Quoted 20 lines · Felipe Balbi
From: Shubhrajyoti D <[email protected]>
In case of a NACK, it's wise to tell our clients drivers about how many bytes were actually transferred.
Support this by adding an extra field to the struct
i2c_msgwhich gets incremented the amount of bytes actually transferred.Signed-off-by Shubhrajyoti D <[email protected]>Signed-off-by Felipe Balbi <[email protected]>--- include/uapi/linux/i2c.h | 1 + 1 file changed, 1 insertion(+)include/uapi/linux/i2c.h +0
-0
include/uapi/linux/i2c.h struct i2c_msg { · line 82
Quoted 6 lines
include/uapi/linux/i2c.h +1
-0@@ -77,6 +77,7 @@ struct i2c_msg {#define I2C_M_NO_RD_ACK 0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400/* length will be first received byte */ __u16 len;/* msg length */ +__u16 transferred;/* actual bytes transferred */ __u8 *buf;/* pointer to msg data */ };
On the principle I am fine with this, however you also need to define who should initialize this field, and to what value.
Not all i2c bus drivers will implement this functionality at first. Some may even be unable to ever implement it. As soon as i2c chip drivers start checking this value, you will hit combinations of chip driver checking the value and bus driver not setting it. And it has to work.
We have to decide whether it is enough to initialize "transferred" to 0, or if we need a more reliable way to distinguish between "0 bytes transferred" and "the bus driver can't tell". What's your take on this? If we need to distinguish, this could be done using a new I2C_FUNC_* flag, or by initializing "transferred" to (__u16)(-1) instead of 0 for example.
Then we have to decide whether initialization is done by the individual drivers, or by i2c-core. By the drivers might be faster, but this may also mean more code (and bugs more likely) than letting i2c-core handle it. The exact balance probably depends on the answer to the previous question (initializing a field to 0 is free in many cases.)
Signature · 1 line
Jean Delvare
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 18 lines · Jean Delvare
Hi Felipe, Shubhrajyoti,
Quoted 15 lines · Felipe Balbi
From: Shubhrajyoti D <[email protected]>
In case of a NACK, it's wise to tell our clients drivers about how many bytes were actually transferred.
Support this by adding an extra field to the struct
i2c_msgwhich gets incremented the amount of bytes actually transferred.Signed-off-by Shubhrajyoti D <[email protected]>Signed-off-by Felipe Balbi <[email protected]>--- include/uapi/linux/i2c.h | 1 + 1 file changed, 1 insertion(+)
Quoted 14 lines
include/uapi/linux/i2c.h struct i2c_msg { · line 82
Quoted 11 lines
include/uapi/linux/i2c.h +1
-0@@ -77,6 +77,7 @@ struct i2c_msg {#define I2C_M_NO_RD_ACK 0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400/* length will be first received byte */ __u16 len;/* msg length */ +__u16 transferred;/* actual bytes transferred */ __u8 *buf;/* pointer to msg data */ };On the principle I am fine with this, however you also need to define who should initialize this field, and to what value.
You also miss one very very very big point. This will break every I2C using userspace program out there unless it is rebuilt - this change will require the exact right version of those userspace programs for the kernel that they're being used on.
Now that we have the userspace API headers separated, this is now much easier to detect: a patch which touches a uapi header needs much more careful consideration than one which doesn't.
So no, strong NAK. This is not how we treat userspace.
If we want to change userspace API then we do it in a sane manner, where we provide the new functionality in a way that it doesn't break existing users. There's two ways to do this:
1. Leave the existing struct alone, introduce a new one with new ioctls. Schedule the removal of the old interfaces for maybe 10 years time.
2. Rename the existing struct (eg struct old_i2c_msg), and create a new struct called i2c_msg. Rename the existing ioctls to have OLD_ in their names. Provide the existing ioctls under those names, and make them print a warning once that userspace programs need updating. Schedule the removal of the old interfaces for a shorter number of years than (1);
Remember all those "old" syscalls we have... this is no different from those.
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 34 lines · Russell King - ARM Linux
Quoted 18 lines · Jean Delvare
Hi Felipe, Shubhrajyoti,
Quoted 15 lines · Felipe Balbi
From: Shubhrajyoti D <[email protected]>
In case of a NACK, it's wise to tell our clients drivers about how many bytes were actually transferred.
Support this by adding an extra field to the struct
i2c_msgwhich gets incremented the amount of bytes actually transferred.Signed-off-by Shubhrajyoti D <[email protected]>Signed-off-by Felipe Balbi <[email protected]>--- include/uapi/linux/i2c.h | 1 + 1 file changed, 1 insertion(+)Quoted 14 lines
include/uapi/linux/i2c.h struct i2c_msg { · line 82
Quoted 11 lines
include/uapi/linux/i2c.h +1
-0@@ -77,6 +77,7 @@ struct i2c_msg {#define I2C_M_NO_RD_ACK 0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400/* length will be first received byte */ __u16 len;/* msg length */ +__u16 transferred;/* actual bytes transferred */ __u8 *buf;/* pointer to msg data */ };On the principle I am fine with this, however you also need to define who should initialize this field, and to what value.
Quoted 4 lines
You also miss one very very very big point. This will break every I2C using userspace program out there unless it is rebuilt - this change will require the exact right version of those userspace programs for the kernel that they're being used on.
How that? The extra field is added in a hole, so we don't change the struct size nor the relative positions of existing fields. Why would user-space care?
Signature · 1 line
Jean Delvare
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 35 lines · Jean Delvare
Quoted 34 lines · Russell King - ARM Linux
Quoted 32 lines · Jean Delvare
Hi Felipe, Shubhrajyoti,
Quoted 20 lines · Felipe Balbi
From: Shubhrajyoti D <[email protected]>
In case of a NACK, it's wise to tell our clients drivers about how many bytes were actually transferred.
Support this by adding an extra field to the struct
i2c_msgwhich gets incremented the amount of bytes actually transferred.Signed-off-by Shubhrajyoti D <[email protected]>Signed-off-by Felipe Balbi <[email protected]>--- include/uapi/linux/i2c.h | 1 + 1 file changed, 1 insertion(+)include/uapi/linux/i2c.h +0
-0include/uapi/linux/i2c.h struct i2c_msg { · line 82
Quoted 6 lines
include/uapi/linux/i2c.h +1
-0@@ -77,6 +77,7 @@ struct i2c_msg {#define I2C_M_NO_RD_ACK 0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400/* length will be first received byte */ __u16 len;/* msg length */ +__u16 transferred;/* actual bytes transferred */ __u8 *buf;/* pointer to msg data */ };On the principle I am fine with this, however you also need to define who should initialize this field, and to what value.
Quoted 8 lines
Quoted 4 lines
You also miss one very very very big point. This will break every I2C using userspace program out there unless it is rebuilt - this change will require the exact right version of those userspace programs for the kernel that they're being used on.
How that? The extra field is added in a hole, so we don't change the struct size nor the relative positions of existing fields. Why would user-space care?
You know the layout of that struct for certain across all Linux supported architectures, including some of the more obscure ones which may not require pointers to be aligned?
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Jean Delvare
Quoted 4 lines · Russell King - ARM Linux
You also miss one very very very big point. This will break every I2C using userspace program out there unless it is rebuilt - this change will require the exact right version of those userspace programs for the kernel that they're being used on.
Quoted 7 lines
Quoted 3 lines
How that? The extra field is added in a hole, so we don't change the struct size nor the relative positions of existing fields. Why would user-space care?
You know the layout of that struct for certain across all Linux supported architectures, including some of the more obscure ones which may not require pointers to be aligned?
No I don't, I naively supposed it would be fine. I would expect gcc to always align pointers even when the architecture doesn't need them to be, for performance reasons, even when it doesn't have to, as long as attribute packed isn't used. After all, integers don't _have_ to be aligned on x86, but gcc aligns them.
The original idea of using the hole in the i2c_msg structure is from David Brownell, who was apparently familiar with such practice, so I assumed it was OK. Actually I still assume it is, until someone comes with an supported architecture where it is not.
Signature · 1 line
Jean Delvare
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 22 lines · Jean Delvare
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Jean Delvare
Quoted 4 lines · Russell King - ARM Linux
You also miss one very very very big point. This will break every I2C using userspace program out there unless it is rebuilt - this change will require the exact right version of those userspace programs for the kernel that they're being used on.
Quoted 7 lines
Quoted 3 lines
How that? The extra field is added in a hole, so we don't change the struct size nor the relative positions of existing fields. Why would user-space care?
You know the layout of that struct for certain across all Linux supported architectures, including some of the more obscure ones which may not require pointers to be aligned?
No I don't, I naively supposed it would be fine. I would expect gcc to always align pointers even when the architecture doesn't need them to be, for performance reasons, even when it doesn't have to, as long as attribute packed isn't used. After all, integers don't _have_ to be aligned on x86, but gcc aligns them.
Quoted 4 lines
The original idea of using the hole in the
i2c_msgstructure is from David Brownell, who was apparently familiar with such practice, so I assumed it was OK. Actually I still assume it is, until someone comes with an supported architecture where it is not.
According to Al Viro, that would be m68k.
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 7 lines · Russell King - ARM Linux
Quoted 4 lines · Jean Delvare
The original idea of using the hole in the
i2c_msgstructure is from David Brownell, who was apparently familiar with such practice, so I assumed it was OK. Actually I still assume it is, until someone comes with an supported architecture where it is not.According to Al Viro, that would be m68k.
OK... So to make things clear, let me ask Al directly about it. Al, can you please tell us if:
--- a/include/uapi/linux/i2c.h
+++ b/include/uapi/linux/i2c.h
struct i2c_msg {
__u16 addr; /* slave address */
__u16 flags;
__u16 len; /* msg length */
+ __u16 transferred; /* actual bytes transferred */
__u8 *buf; /* pointer to msg data */
};
would break binary compatibility on m68k or any other architecture you are familiar with? Note that struct i2c_msg isn't declared with attribute packed, so my assumption was that pointer "buf" was align on at least 4 bytes, leaving a hole between len and buf. Am I wrong?
Thanks,
Signature · 1 line
Jean Delvare
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 11 lines · Jean Delvare
Quoted 7 lines · Russell King - ARM Linux
Quoted 4 lines · Jean Delvare
The original idea of using the hole in the
i2c_msgstructure is from David Brownell, who was apparently familiar with such practice, so I assumed it was OK. Actually I still assume it is, until someone comes with an supported architecture where it is not.According to Al Viro, that would be m68k.
OK... So to make things clear, let me ask Al directly about it. Al, can you please tell us if:
[snip]
Quoted 4 lines
would break binary compatibility on m68k or any other architecture you are familiar with? Note that struct
i2c_msgisn't declared with attribute packed, so my assumption was that pointer "buf" was align on at least 4 bytes, leaving a hole between len and buf. Am I wrong?
You are wrong. Assumption that pointers are aligned to 32bit boundary is simply not true. In particular, on m68k alignment is 16bit, i.e. there
struct foo {
char x;
void *p;
}; will have 1 byte occupied by x, followed by 1-byte gap, followed by 4 bytesoccupied by p.
Note, BTW, that m68k includes things like coldfire, etc. and I wouldn't be surprised by e.g. coldfire-based SoC with i2c on it.
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 10 lines · Al Viro
You are wrong. Assumption that pointers are aligned to 32bit boundary is simply not true. In particular, on m68k alignment is 16bit, i.e. there
struct foo { char x; void *p; }; will have 1 byte occupied by x, followed by 1-byte gap, followed by 4 bytesoccupied by p.
Note, BTW, that m68k includes things like coldfire, etc. and I wouldn't be surprised by e.g. coldfire-based SoC with i2c on it.
BTW, that's easily verified - take a cross-compiler and do this:
; cat >a.c <<'EOF'
struct { char x; void *y; } v;
int z = (char *)&v.y - (char *)&v;
EOF
; m68k-linux-gnu-gcc -S a.c
; grep -A1 'z:' a.s
z:
.long 2
;
and watch what it puts into z. gcc is very liberal about what it considers a constant expression, so it allows that sort of expressions as initializers for global variables. Not a portable C, but convenient for experiments like that; just grab a cross-toolchain and feed it testcases of that kind...
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Quoted 13 lines · Al Viro
Quoted 10 lines · Al Viro
You are wrong. Assumption that pointers are aligned to 32bit boundary is simply not true. In particular, on m68k alignment is 16bit, i.e. there
struct foo { char x; void *p; }; will have 1 byte occupied by x, followed by 1-byte gap, followed by 4 bytesoccupied by p.
Note, BTW, that m68k includes things like coldfire, etc. and I wouldn't be surprised by e.g. coldfire-based SoC with i2c on it.
Quoted 14 lines
BTW, that's easily verified - take a cross-compiler and do this:
; cat >a.c <<'EOF'
struct { char x; void *y; } v;
int z = (char *)&v.y - (char *)&v;
EOF
; m68k-linux-gnu-gcc -Sa.c
; grep -A1 'z:' a.s
z:
.long 2
;
and watch what it puts into z. gcc is very liberal about what it considers a constant expression, so it allows that sort of expressions as initializers for global variables. Not a portable C, but convenient for experiments like that; just grab a cross-toolchain and feed it testcases of that kind...
... and google for i2c coldfire immediately turns up this:
http://mailman.uclinux.org/pipermail/uclinux-dev/2012-May/051874.html
with
+config I2C_COLDFIRE
+ tristate "Freescale Coldfire I2C driver" + depends on !M5272 + help
+ This driver supports the I2C interface availible on most Freescale
+ Coldfire processors.
+
+ This driver can be built as a module. If so, the module
+ will be called i2c-coldfire.
in it, along with addition of drivers/i2c/busses/i2c-coldfire.c... IOW, i2c on m68k is quite real. Sorry, no go - you don't even have an excuse of i2c never existing on the architecture in question.
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
Hi Al,
Quoted 14 lines · Al Viro
Quoted 13 lines · Al Viro
Quoted 10 lines · Al Viro
You are wrong. Assumption that pointers are aligned to 32bit boundary is simply not true. In particular, on m68k alignment is 16bit, i.e. there
struct foo { char x; void *p; }; will have 1 byte occupied by x, followed by 1-byte gap, followed by 4 bytesoccupied by p.
Note, BTW, that m68k includes things like coldfire, etc. and I wouldn't be surprised by e.g. coldfire-based SoC with i2c on it.
Quoted 14 lines
Quoted 6 lines
BTW, that's easily verified - take a cross-compiler and do this:
; cat >a.c <<'EOF'
struct { char x; void *y; } v;
int z = (char *)&v.y - (char *)&v;
EOF
; m68k-linux-gnu-gcc -Sa.cQuoted 8 lines
; grep -A1 'z:' a.s
z:
.long 2
;
and watch what it puts into z. gcc is very liberal about what it considers a constant expression, so it allows that sort of expressions as initializers for global variables. Not a portable C, but convenient for experiments like that; just grab a cross-toolchain and feed it testcases of that kind...
Thanks for the fast and complete answer.
Quoted 13 lines
... and google for i2c coldfire immediately turns up this:
http://mailman.uclinux.org/pipermail/uclinux-dev/2012-May/051874.html
with(quoted diff) +9
-0+config I2C_COLDFIRE + tristate "Freescale Coldfire I2C driver" + depends on !M5272 + help + This driver supports the I2C interface availible on most Freescale + Coldfire processors. + + This driver can be built as a module. If so, the module + will be called i2c-coldfire.
Quoted 3 lines
in it, along with addition of
drivers/i2c/busses/i2c-coldfire.c... IOW, i2c on m68k is quite real. Sorry, no go - you don't even have an excuse of i2c never existing on the architecture in question.
You are completely right, we will have to find another way to let bus drivers report how much of each message they managed to transmit or receive.
Thanks again,
Signature · 1 line
Jean Delvare
PATCH 7/8 i2c: add 'transferred' field to struct i2c_msg
In reply to Jean DelvareQuoted 22 lines · Jean Delvare
Quoted 7 lines · Russell King - ARM Linux
Quoted 4 lines · Jean Delvare
The original idea of using the hole in the
i2c_msgstructure is from David Brownell, who was apparently familiar with such practice, so I assumed it was OK. Actually I still assume it is, until someone comes with an supported architecture where it is not.According to Al Viro, that would be m68k.
OK... So to make things clear, let me ask Al directly about it. Al, can you please tell us if:
include/uapi/linux/i2c.h +1
-0struct i2c_msg {__u16 addr;/* slave address */ __u16 flags;__u16 len;/* msg length */ +__u16 transferred;/* actual bytes transferred */ __u8 *buf;/* pointer to msg data */ };
Quoted 4 lines
would break binary compatibility on m68k or any other architecture you are familiar with? Note that struct
i2c_msgisn't declared with attribute packed, so my assumption was that pointer "buf" was align on at least 4 bytes, leaving a hole between len and buf. Am I wrong?
So, you're attitude here is "I don't believe you, you are lying". Well, if you have that level of distrust of your fellow developers, then you don't deserve to be a Linux developer at all - and given that why should I take any notice of you in the future over I2C stuff.
Especially as you've just proven that you don't know how to deal properly with APIs...
Quite frankly I find your attitude towards me here totally disgusting and insulting.
Not surprisingly, I didn't lie (I don't lie) and so I didn't "make up" that M68k is one such architecture, and you've now had the confirmation from Al.
So, I look forward to your apology for _implying_ that I'm a liar over this issue, or if not, your resignation as I2C maintainer.
Thanks.
PATCH 8/8 i2c: omap: implement handling for 'transferred' bytes
In reply to Felipe Balbithis is important in cases where client driver wants to know how many bytes were actually transferred.
There is one trick here: if transfer is completed, meaning I2C_CNT reaches zero, then ARDY will be asserted to let SW know that it can program a new transfer.
When ARDY is asserted, I2C_CNT is reset to the original value (msg->len), which means that for a successful message, msg->transferred = msg->len and we don't need to spend time with a register read.
In case of NACK condition, however, I2C_CNT will remain with the end value which is the amount of data transferred until NACK condition found on the bus inclusive. In this situation, msg->transferred needs to be initialized with:
msg->len - read(I2C_CNT) - 1;
This patch implements exactly that handling.
--- drivers/i2c/busses/i2c-omap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/i2c/busses/i2c-omap.c +12 -0
@@ -594,6 +594,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto out; } + msg->transferred = msg->len; +wmb (); +if ((dev->cmd_err &OMAP_I2C_STAT_AL ) || (dev->cmd_err &OMAP_I2C_STAT_ROVR ) || (dev->cmd_err &OMAP_I2C_STAT_XUDF )) {
@@ -603,6 +606,15 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) { +/* In case of a NACK, we need to check how many bytes we +* actually transferred, so we can tell our client driver about +* it. +* +* Let's check it here and overwrite msg->transferred. +*/ + w =omap_i2c_read_reg (dev,OMAP_I2C_CNT_REG ); + msg->transferred = msg->len - w -1 ; +if (msg->flags &I2C_M_IGNORE_NAK )return 0 ;
Signature · 1 line
1.8.0.rc0
cover I2C patches for v3.8 merge window
In reply to Felipe BalbiHi,
Quoted 11 lines · Felipe Balbi
Hi guys,
here's another series for OMAP I2C driver. There are a few cleanups and one very nice new feature: we can now report how many bytes we transferred until NACK.
Note that the implemementation for OMAP-I2C turned out to be a little more complex then I expected, mainly because of the way
I2C_CNTregister behaves and because of the very buggy register usage on that driver.
Quoted 7 lines
I have boot tested all patches on beagle xM (3630) and pandaboard rev A3 (4430), will send boot-logs if anyone wants to see.
All patches are available at [1] if anyone wants an easy way to test the patches.
[1]
git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.giti2c-transferred-bytes-on-NACK
forgot to mention, with [1] I could veridy suspend to ram with boards mentioned above.
[1] http://marc.info/?l=linux-arm-kernel&m=135090724817604&w=2
Quoted 22 lines
Felipe Balbi (7):
i2c: omap: no need to accessplatform_device
i2c: omap: reorder exit path ofomap_i2c_xfer_msg()
i2c: omap: fix error checking
i2c: omap: alsocomplete()when stat becomes zero
i2c: omap: introduce and useOMAP_I2C_IP_VERSION_3
i2c: omap: wait for transfer completion before sending STP bit
i2c: omap: implement handling for 'transferred' bytesShubhrajyoti D (1):
i2c: add 'transferred' field to structi2c_msgarch/arm/mach-omap2/i2c.c | 3 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- drivers/i2c/busses/i2c-omap.c | 156 ++++++++++++++++------------- include/linux/i2c-omap.h | 1 + include/uapi/linux/i2c.h | 1 + 5 files changed, 89 insertions(+), 74 deletions(-)Signature · 1 line
1.8.0.rc0
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121022/c344c2db/attachment.sig>
cover I2C patches for v3.8 merge window
Quoted 16 lines · Felipe Balbi
Hi,
Quoted 13 lines · Felipe Balbi
Hi guys,
here's another series for OMAP I2C driver. There are a few cleanups and one very nice new feature: we can now report how many bytes we transferred until NACK.
Note that the implemementation for OMAP-I2C turned out to be a little more complex then I expected, mainly because of the way
I2C_CNTregister behaves and because of the very buggy register usage on that driver.I have boot tested all patches on beagle xM (3630) and pandaboard rev A3 (4430), will send boot-logs if anyone wants to see.
tested the below branch on omap4430sdp , panda , omap3430sdp.
Doing simple i2ctools
.
Quoted 36 lines
Quoted 5 lines
All patches are available at [1] if anyone wants an easy way to test the patches.
[1]
git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.giti2c-transferred-bytes-on-NACKforgot to mention, with [1] I could veridy suspend to ram with boards mentioned above.
[1] http://marc.info/?l=linux-arm-kernel&m=135090724817604&w=2
Quoted 19 lines
Felipe Balbi (7):
i2c: omap: no need to accessplatform_device
i2c: omap: reorder exit path ofomap_i2c_xfer_msg()
i2c: omap: fix error checking
i2c: omap: alsocomplete()when stat becomes zero
i2c: omap: introduce and useOMAP_I2C_IP_VERSION_3
i2c: omap: wait for transfer completion before sending STP bit
i2c: omap: implement handling for 'transferred' bytesShubhrajyoti D (1):
i2c: add 'transferred' field to structi2c_msgarch/arm/mach-omap2/i2c.c | 3 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- drivers/i2c/busses/i2c-omap.c | 156 ++++++++++++++++------------- include/linux/i2c-omap.h | 1 + include/uapi/linux/i2c.h | 1 + 5 files changed, 89 insertions(+), 74 deletions(-)Quoted 3 lines
--
1.8.0.rc0--
balbi
cover I2C patches for v3.8 merge window
Hi,
Quoted 18 lines · Shubhrajyoti Datta
Quoted 16 lines · Felipe Balbi
Hi,
Quoted 13 lines · Felipe Balbi
Hi guys,
here's another series for OMAP I2C driver. There are a few cleanups and one very nice new feature: we can now report how many bytes we transferred until NACK.
Note that the implemementation for OMAP-I2C turned out to be a little more complex then I expected, mainly because of the way
I2C_CNTregister behaves and because of the very buggy register usage on that driver.I have boot tested all patches on beagle xM (3630) and pandaboard rev A3 (4430), will send boot-logs if anyone wants to see.
Quoted 7 lines
tested the below branch on omap4430sdp , panda , omap3430sdp.
Doing simple i2ctools
.Tested-by Shubhrajyoti D <[email protected]>
can you also check if echo mem > /sys/power/state works ? Don't forget to enable UART wakeups with:
echo enabled > /sys/devices/platform/omap_uart.2/power/wakeup echo enabled > /sys/devices/platform/omap_uart.2/tty/ttyO2/power/wakeup
before trying to suspend. Another cool test is rtctest (since our RTC is part of TWL). It worked fine on my two platforms. Attached you will find the sourcecode for rtctest.
Quoted 35 lines
Quoted 35 lines
Quoted 4 lines
All patches are available at [1] if anyone wants an easy way to test the patches.
[1]
git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.giti2c-transferred-bytes-on-NACKforgot to mention, with [1] I could veridy suspend to ram with boards mentioned above.
[1] http://marc.info/?l=linux-arm-kernel&m=135090724817604&w=2
Quoted 19 lines
Felipe Balbi (7):
i2c: omap: no need to accessplatform_device
i2c: omap: reorder exit path ofomap_i2c_xfer_msg()
i2c: omap: fix error checking
i2c: omap: alsocomplete()when stat becomes zero
i2c: omap: introduce and useOMAP_I2C_IP_VERSION_3
i2c: omap: wait for transfer completion before sending STP bit
i2c: omap: implement handling for 'transferred' bytesShubhrajyoti D (1):
i2c: add 'transferred' field to structi2c_msgarch/arm/mach-omap2/i2c.c | 3 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- drivers/i2c/busses/i2c-omap.c | 156 ++++++++++++++++------------- include/linux/i2c-omap.h | 1 + include/uapi/linux/i2c.h | 1 + 5 files changed, 89 insertions(+), 74 deletions(-)Quoted 3 lines
--
1.8.0.rc0--
balbi
Signature · 15 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: rtctest.c Type: text/x-csrc Size: 5768 bytes Desc: not available URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121022/d3212336/attachment-0001.bin> -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121022/d3212336/attachment-0001.sig>
cover I2C patches for v3.8 merge window
Quoted 9 lines · Felipe Balbi
can you also check if echo mem >
/sys/power/stateworks ? Don't forget to enable UART wakeups with:echo enabled >
/sys/devices/platform/omap_uart.2/power/wakeupecho enabled >/sys/devices/platform/omap_uart.2/tty/ttyO2/power/wakeupbefore trying to suspend. Another cool test is rtctest (since our RTC is part of TWL). It worked fine on my two platforms. Attached you will find the sourcecode for rtctest.
On omap3 tested . with off hitting both in suspend and idle path.
Also with rtcwake.
Thanks
cover I2C patches for v3.8 merge window
In reply to Shubhrajyoti DattaQuoted 5 lines
Quoted 5 lines
Quoted 5 lines
here's another series for OMAP I2C driver. There are a few cleanups and one very nice new feature: we can now report how many bytes we transferred until NACK.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Note that the implemementation for OMAP-I2C turned out to be a little more complex then I expected, mainly because of the way
I2C_CNTregister behaves and because of the very buggy register usage on that driver.I have boot tested all patches on beagle xM (3630) and pandaboard rev A3 (4430), will send boot-logs if anyone wants to see.
The series is a bit confusing mixing V1, V2 and V3 patches. Also, there are a few comments unaddressed it seems to me (reading in hot path, barriers). Please make sure these are properly handled and resend as a seperate series (all patches V4). Bonus point if you rebase it to my for-next, which I will push out soon.
Signature · 9 lines
Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 198 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121114/abbaf878/attachment.sig>
v2 cover I2C patches for v3.8 merge window
In reply to Felipe BalbiHi,
here's another series for OMAP I2C driver. There are a few cleanups and one very nice new feature: we can now report how many bytes we transferred until NACK.
Note that the implemementation for OMAP-I2C turned out to be a little more complex then I expected, mainly because of the way I2C_CNT register behaves and because of the very buggy register usage on that driver.
I have boot tested all patches on beagle xM (3630) and pandaboard rev A3 (4430), will send boot-logs if anyone wants to see.
All patches are available at [1] if anyone wants an easy way to test the patches.
Changes since v1:
- remove unnecessary omap_i2c_init() in case of NACK
- drop "i2c: omap: fix error checking"
Felipe Balbi (6):
i2c: omap: no need to access platform_device
i2c: omap: reorder exit path of omap_i2c_xfer_msg()
i2c: omap: also complete() when stat becomes zero
i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to
IRQSTATUS
i2c: omap: wait for transfer completion before sending STP bit
i2c: omap: implement handling for 'transferred' bytes
Shubhrajyoti D (1):
i2c: add 'transferred' field to struct i2c_msg
drivers/i2c/busses/i2c-omap.c | 124 ++++++++++++++++++++++-------------------- include/uapi/linux/i2c.h | 1 + 2 files changed, 65 insertions(+), 60 deletions(-)
Signature · 1 line
1.8.0
PATCH v2 1/7 i2c: omap: no need to access platform_device
PM callbacks pass our device pointer as argument
and we don't need to access the platform_device
just to dereference that down to dev->drvdata.
instead, just use dev_get_drvdata() directly.
--- drivers/i2c/busses/i2c-omap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/i2c/busses/i2c-omap.c +2 -4
@@ -1239,8 +1239,7 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev)#ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend (struct device *dev) { -struct platform_device *pdev =to_platform_device (dev); -struct omap_i2c_dev *_dev =platform_get_drvdata (pdev); +struct omap_i2c_dev *_dev =dev_get_drvdata (dev);u16 iv; _dev->iestate =omap_i2c_read_reg (_dev,OMAP_I2C_IE_REG );
@@ -1261,8 +1260,7 @@ static int omap_i2c_runtime_suspend(struct device *dev)static int omap_i2c_runtime_resume (struct device *dev) { -struct platform_device *pdev =to_platform_device (dev); -struct omap_i2c_dev *_dev =platform_get_drvdata (pdev); +struct omap_i2c_dev *_dev =dev_get_drvdata (dev);if (_dev->flags &OMAP_I2C_FLAG_RESET_REGS_POSTIDLE ) {omap_i2c_write_reg (_dev,OMAP_I2C_CON_REG ,0 );
Signature · 1 line
1.8.0
PATCH v2 1/7 i2c: omap: no need to access platform_device
Quoted 8 lines · Felipe Balbi
PM callbacks pass our device pointer as argument
and we don't need to access theplatform_device
just to dereference that down todev->drvdata.instead, just use
dev_get_drvdata()directly.Signed-off-by Felipe Balbi <[email protected]>---
PATCH v2 2/7 i2c: omap: reorder exit path of omap_i2c_xfer_msg()
In reply to Felipe Balbijust a cleanup patch trying to make exit path
more straightforward. No changes otherwise.
--- drivers/i2c/busses/i2c-omap.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
drivers/i2c/busses/i2c-omap.c +17 -9
@@ -505,6 +505,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; +int ret;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
@@ -582,31 +583,38 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf_len =0 ;if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); -omap_i2c_init (dev); -return -ETIMEDOUT ; + ret = -ETIMEDOUT ; + goto err_i2c_init; } -if (likely (!dev->cmd_err)) -return 0 ; -/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { -omap_i2c_init (dev); -return -EIO ; + ret = -EIO ; + goto err_i2c_init; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; +if (stop) { w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); w |=OMAP_I2C_CON_STP ;omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); } -return -EREMOTEIO ; + + ret = -EREMOTEIO ; + goto err; } -return -EIO ; + +return 0 ; + +err_i2c_init: +omap_i2c_init (dev); + +err: +return ret; }
Signature · 1 line
1.8.0
PATCH v2 2/7 i2c: omap: reorder exit path of omap_i2c_xfer_msg()
Quoted 13 lines · Felipe Balbi
just a cleanup patch trying to make exit path
more straightforward. No changes otherwise.Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)drivers/i2c/busses/i2c-omap.c +0
-0
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 508
Quoted 4 lines
drivers/i2c/busses/i2c-omap.c +1
-0@@ -505,6 +505,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; +int ret;
You might want to initialize the error value to avoid return 0. Compiler might be already cribbing for it
Quoted 6 lines
drivers/i2c/busses/i2c-omap.c +0
-0u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",@@ -582,31 +583,38 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf_len =0 ;if (timeout ==0 ) {
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 591
Quoted 10 lines
drivers/i2c/busses/i2c-omap.c +2
-5dev_err (dev->dev,"controller timed out\n" ); -omap_i2c_init (dev); -return -ETIMEDOUT ; + ret = -ETIMEDOUT ; + goto err_i2c_init; } -if (likely (!dev->cmd_err)) -return 0 ; -
Have you have drooped this check completely ?
Quoted 16 lines
drivers/i2c/busses/i2c-omap.c +3
-2/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { -omap_i2c_init (dev); -return -EIO ; + ret = -EIO ; + goto err_i2c_init; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; +if (stop) { w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); w |=OMAP_I2C_CON_STP ;
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 611
Quoted 10 lines
drivers/i2c/busses/i2c-omap.c +5
-2omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); } -return -EREMOTEIO ; + + ret = -EREMOTEIO ; + goto err; } -return -EIO ; + +return 0 ;
With initialized value you can use
return ret;
Regards
Santosh
PATCH v2 2/7 i2c: omap: reorder exit path of omap_i2c_xfer_msg()
Hi,
Quoted 34 lines · Santosh Shilimkar
Quoted 13 lines · Felipe Balbi
just a cleanup patch trying to make exit path
more straightforward. No changes otherwise.Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)drivers/i2c/busses/i2c-omap.c +0
-0drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 508
Quoted 4 lines
drivers/i2c/busses/i2c-omap.c +1
-0@@ -505,6 +505,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; +int ret;You might want to initialize the error value to avoid return 0. Compiler might be already cribbing for it
Quoted 13 lines
drivers/i2c/busses/i2c-omap.c +2
-2u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",@@ -582,31 +583,38 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf_len =0 ;if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); -omap_i2c_init (dev); -return -ETIMEDOUT ; + ret = -ETIMEDOUT ; + goto err_i2c_init; }
Quoted 4 lines
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 591
Quoted 3 lines
drivers/i2c/busses/i2c-omap.c +0
-3-if (likely (!dev->cmd_err)) -return 0 ; -Have you have drooped this check completely ?
yes, the idea is to have a single exit point, so all checks below would be executed.
Quoted 20 lines
Quoted 20 lines
drivers/i2c/busses/i2c-omap.c +4
-3/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { -omap_i2c_init (dev); -return -EIO ; + ret = -EIO ; + goto err_i2c_init; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; +if (stop) { w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); w |=OMAP_I2C_CON_STP ;omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); } -return -EREMOTEIO ; +
Quoted 8 lines
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 611
Quoted 6 lines
drivers/i2c/busses/i2c-omap.c +4
-1+ ret = -EREMOTEIO ; + goto err; } -return -EIO ; + +return 0 ;With initialized value you can use
return ret;
hmm, I guess I did that on a follow up patch where I grouped the stop handling.
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/ee35f97f/attachment-0001.sig>
PATCH v2 2/7 i2c: omap: reorder exit path of omap_i2c_xfer_msg()
In reply to Santosh ShilimkarHi,
Quoted 18 lines · Santosh Shilimkar
Quoted 17 lines · Felipe Balbi
just a cleanup patch trying to make exit path
more straightforward. No changes otherwise.Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)drivers/i2c/busses/i2c-omap.c +1
-0@@ -505,6 +505,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; +int ret;
[...]
Quoted 9 lines
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 611
Quoted 6 lines
drivers/i2c/busses/i2c-omap.c +4
-1+ ret = -EREMOTEIO ; + goto err; } -return -EIO ; + +return 0 ;With initialized value you can use
return ret;
Doing it this way has the advantage, that if an additional error exit is added it will generate an 'uninitialized variable' warning, if it fails to set the return value.
Lothar Wa?mann
Signature · 9 lines
___________________________________________________________ Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Gesch?ftsf?hrer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________
PATCH v2 3/7 i2c: omap: also complete() when stat becomes zero
In reply to Felipe BalbiIn case we loop on IRQ handler until stat is finally zero, we would end up in a situation where all I2C transfers would misteriously timeout because we were not calling complete() in that situation.
Fix the issue by moving omap_i2c_complete_cmd() call inside the 'out' label.
--- drivers/i2c/busses/i2c-omap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +1 -2
@@ -1021,9 +1021,8 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) } }while (stat); -omap_i2c_complete_cmd (dev, err); - out: +omap_i2c_complete_cmd (dev, err);spin_unlock_irqrestore (&dev->lock, flags);return IRQ_HANDLED ;
Signature · 1 line
1.8.0
PATCH v2 3/7 i2c: omap: also complete() when stat becomes zero
Quoted 11 lines · Felipe Balbi
In case we loop on IRQ handler until stat is finally zero, we would end up in a situation where all I2C transfers would misteriously timeout because we were not calling
complete()in that situation.Fix the issue by moving
omap_i2c_complete_cmd()call inside the 'out' label.Signed-off-by Felipe Balbi <[email protected]>---
Looks fine. Have you hit this issue in any corner case ?
Regards
santosh
PATCH v2 3/7 i2c: omap: also complete() when stat becomes zero
Hi,
Quoted 7 lines · Santosh Shilimkar
Quoted 6 lines · Felipe Balbi
In case we loop on IRQ handler until stat is finally zero, we would end up in a situation where all I2C transfers would misteriously timeout because we were not calling
complete()in that situation.
Quoted 6 lines
Quoted 5 lines
Fix the issue by moving
omap_i2c_complete_cmd()call inside the 'out' label.Signed-off-by Felipe Balbi <[email protected]>---
Looks fine. Have you hit this issue in any corner case ?
in fact, yes. With a difficult to reproduce situation with drv2665 (one of TI's piezo drivers) I saw that I was missing the ack and all transfers were timing out ;-)
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/53259a9f/attachment.sig>
PATCH v2 4/7 i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to IRQSTATUS
In reply to Felipe Balbion OMAP4+ we want to read IRQSTATUS_RAW register, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled on IRQENABLE_SET and that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.
One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Note, however, that omap-i2c.c needs a big rework on register definition and register access. Such work will be done in a separate series of patches.
--- drivers/i2c/busses/i2c-omap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-omap.c +11 -1
@@ -271,8 +271,18 @@ static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,static inline u16 omap_i2c_read_reg (struct omap_i2c_dev *i2c_dev,int reg) { -return __raw_readw (i2c_dev->base + +/* if we are OMAP_I2C_IP_VERSION_2, we need to read from +* IRQSTATUS_RAW, but write to IRQSTATUS +*/ +if ((i2c_dev->dtrev ==OMAP_I2C_IP_VERSION_2 ) && + (reg ==OMAP_I2C_STAT_REG )) { +return __raw_readw (i2c_dev->base + + ((i2c_dev->regs[reg] -0x04 ) + << i2c_dev->reg_shift)); + }else { +return __raw_readw (i2c_dev->base + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); + } }static int omap_i2c_init (struct omap_i2c_dev *dev)
Signature · 1 line
1.8.0
PATCH v2 4/7 i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to IRQSTATUS
Quoted 28 lines · Felipe Balbi
on OMAP4+ we want to read
IRQSTATUS_RAWregister, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled onIRQENABLE_SETand that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Note, however, that
omap-i2c.cneeds a big rework on register definition and register access. Such work will be done in a separate series of patches.Cc Benoit Cousson <[email protected]>Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)drivers/i2c/busses/i2c-omap.c +0
-0
drivers/i2c/busses/i2c-omap.c static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, · line 278
Quoted 9 lines
drivers/i2c/busses/i2c-omap.c +5
-1@@ -271,8 +271,18 @@ static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,static inline u16 omap_i2c_read_reg (struct omap_i2c_dev *i2c_dev,int reg) { - return __raw_readw(i2c_dev->base + +/* if we are OMAP_I2C_IP_VERSION_2, we need to read from +* IRQSTATUS_RAW, but write to IRQSTATUS +*/ +if ((i2c_dev->dtrev ==OMAP_I2C_IP_VERSION_2 ) && + (reg ==OMAP_I2C_STAT_REG )) {
Doing this check on every I2C register read seems to expensive to me. Can you not sort this in init with some offset which can be 0 or non zero ? Sorry in case this is already dicussed.
regards
santosh
PATCH v2 4/7 i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to IRQSTATUS
Hi,
Quoted 30 lines · Santosh Shilimkar
Quoted 29 lines · Felipe Balbi
on OMAP4+ we want to read
IRQSTATUS_RAWregister, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled onIRQENABLE_SETand that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Note, however, that
omap-i2c.cneeds a big rework on register definition and register access. Such work will be done in a separate series of patches.Cc Benoit Cousson <[email protected]>Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)drivers/i2c/busses/i2c-omap.c +0
-0@@ -271,8 +271,18 @@ static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
Quoted 11 lines
drivers/i2c/busses/i2c-omap.c static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, · line 278
Quoted 8 lines
drivers/i2c/busses/i2c-omap.c +5
-1static inline u16 omap_i2c_read_reg (struct omap_i2c_dev *i2c_dev,int reg) { - return __raw_readw(i2c_dev->base + +/* if we are OMAP_I2C_IP_VERSION_2, we need to read from +* IRQSTATUS_RAW, but write to IRQSTATUS +*/ +if ((i2c_dev->dtrev ==OMAP_I2C_IP_VERSION_2 ) && + (reg ==OMAP_I2C_STAT_REG )) {Doing this check on every I2C register read seems to expensive to me. Can you not sort this in init with some offset which can be 0 or non zero ? Sorry in case this is already dicussed.
could be. I didn't go that route because I'm planning a complete rewrite of all register accesses. The way it's done today is completely broken and already expensive (with reg_shift and different map tables and so on).
If it's really a big of a deal, I can try to find another way, maybe just adding omap_i2c_read_stat() and limit the version check just to I2C_STAT reads would do it for now...
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/d7a764f7/attachment.sig>
PATCH v2 4/7 i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to IRQSTATUS
Quoted 45 lines · Felipe Balbi
Hi,
Quoted 30 lines · Santosh Shilimkar
Quoted 29 lines · Felipe Balbi
on OMAP4+ we want to read
IRQSTATUS_RAWregister, instead of IRQSTATUS. The reason being that IRQSTATUS will only contain the bits which were enabled onIRQENABLE_SETand that will break when we need to poll for a certain bit which wasn't enabled as an IRQ source.One such case is after we finish converting to deferred stop bit, we will have to poll for ARDY bit before returning control for the client driver in order to prevent us from trying to start a transfer on a bus which is already busy.
Note, however, that
omap-i2c.cneeds a big rework on register definition and register access. Such work will be done in a separate series of patches.Cc Benoit Cousson <[email protected]>Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)drivers/i2c/busses/i2c-omap.c +0
-0@@ -271,8 +271,18 @@ static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,Quoted 11 lines
drivers/i2c/busses/i2c-omap.c static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, · line 278
Quoted 8 lines
drivers/i2c/busses/i2c-omap.c +5
-1static inline u16 omap_i2c_read_reg (struct omap_i2c_dev *i2c_dev,int reg) { - return __raw_readw(i2c_dev->base + +/* if we are OMAP_I2C_IP_VERSION_2, we need to read from +* IRQSTATUS_RAW, but write to IRQSTATUS +*/ +if ((i2c_dev->dtrev ==OMAP_I2C_IP_VERSION_2 ) && + (reg ==OMAP_I2C_STAT_REG )) {Doing this check on every I2C register read seems to expensive to me. Can you not sort this in init with some offset which can be 0 or non zero ? Sorry in case this is already dicussed.
Quoted 9 lines
could be. I didn't go that route because I'm planning a complete rewrite of all register accesses. The way it's done today is completely broken and already expensive (with
reg_shiftand different map tables and so on).If it's really a big of a deal, I can try to find another way, maybe just adding
omap_i2c_read_stat()and limit the version check just toI2C_STATreads would do it for now...
Its a hot path since you read many I2C register reads, so getting rid of that additional check will be good.
PATCH v2 5/7 i2c: omap: wait for transfer completion before sending STP bit
In reply to Felipe BalbiLater patches will come adding support for reporting amount of bytes transferred so that client drivers can count how many bytes are left to transfer.
This is useful mostly in case of NACKs when client driver wants to know exactly which byte got NACKed so it doesn't have to resend all bytes again.
In order to make that work with OMAP's I2C controller, we need to prevent sending STP bit until message is transferred. The reason behind that is because OMAP_I2C_CNT_REG gets reset to original value after STP bit is shifted through I2C_SDA line and that would prevent us from reading the correct number of bytes left to transfer.
The full programming model suggested by IP owner was the following:
- start I2C transfer (without STP bit)
- upon completion or NACK, read I2C_CNT register
- write STP bit to I2C_CON register
- wait for ARDY bit
With this patch we're implementing all steps except step #2 which will come in a later patch adding such support.
--- drivers/i2c/busses/i2c-omap.c | 89 ++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 56 deletions(-)
drivers/i2c/busses/i2c-omap.c +33 -56
@@ -438,9 +438,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)/* Enable interrupts */ dev->iestate = (OMAP_I2C_IE_XRDY |OMAP_I2C_IE_RRDY | -OMAP_I2C_IE_ARDY |OMAP_I2C_IE_NACK | -OMAP_I2C_IE_AL ) | ((dev->fifo_size) ? - (OMAP_I2C_IE_RDR |OMAP_I2C_IE_XDR ) :0 ); +OMAP_I2C_IE_NACK |OMAP_I2C_IE_AL ) | + ((dev->fifo_size) ? (OMAP_I2C_IE_RDR | +OMAP_I2C_IE_XDR ) :0 );omap_i2c_write_reg (dev,OMAP_I2C_IE_REG , dev->iestate);if (dev->flags &OMAP_I2C_FLAG_RESET_REGS_POSTIDLE ) { dev->pscstate = psc;
@@ -470,6 +470,22 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)return 0 ; } +static int omap_i2c_wait_for_ardy (struct omap_i2c_dev *dev) +{ +unsigned long timeout; + + timeout = jiffies +OMAP_I2C_TIMEOUT ; +while (!(omap_i2c_read_reg (dev,OMAP_I2C_STAT_REG ) &OMAP_I2C_STAT_ARDY )) { +if (time_after (jiffies, timeout)) { +dev_warn (dev->dev,"timeout waiting for access ready\n" ); +return -ETIMEDOUT ; + } +usleep_range (800 ,1200 ); + } + +return 0 ; +} +static void omap_i2c_resize_fifo (struct omap_i2c_dev *dev,u8 size,bool is_rx) {u16 buf;
@@ -515,7 +531,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; -int ret; +int ret =0 ;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
@@ -556,35 +572,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (!(msg->flags &I2C_M_RD )) w |=OMAP_I2C_CON_TRX ; -if (!dev->b_hw && stop) - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w);/* -* Don't write stt and stp together on some hardware. -*/ -if (dev->b_hw && stop) { -unsigned long delay = jiffies +OMAP_I2C_TIMEOUT ; -u16 con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); -while (con &OMAP_I2C_CON_STT ) { - con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - -/* Let the user know if i2c is in a bad state */ -if (time_after (jiffies, delay)) { -dev_err (dev->dev,"controller timed out " -"waiting for start condition to finish\n" ); -return -ETIMEDOUT ; - } -cpu_relax (); - } - - w |=OMAP_I2C_CON_STP ; - w &= ~OMAP_I2C_CON_STT ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - -/* * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */
@@ -594,36 +584,36 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); ret = -ETIMEDOUT ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { ret = -EIO ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; -if (stop) { - w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - ret = -EREMOTEIO ; - goto err; +omap_i2c_init (dev); } -return 0 ; +out: -err_i2c_init: -omap_i2c_init (dev); +if (stop) { + w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); + w |=OMAP_I2C_CON_STP ; +omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); + + ret =omap_i2c_wait_for_ardy (dev); + } -err:return ret; }
@@ -947,19 +937,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)break ; } -/* -* ProDB0017052: Clear ARDY bit twice -*/ -if (stat & (OMAP_I2C_STAT_ARDY |OMAP_I2C_STAT_NACK | -OMAP_I2C_STAT_AL )) { -omap_i2c_ack_stat (dev, (OMAP_I2C_STAT_RRDY | -OMAP_I2C_STAT_RDR | -OMAP_I2C_STAT_XRDY | -OMAP_I2C_STAT_XDR | -OMAP_I2C_STAT_ARDY )); -break ; - } -if (stat &OMAP_I2C_STAT_RDR ) {u8 num_bytes =1 ;
Signature · 1 line
1.8.0
PATCH v2 5/7 i2c: omap: wait for transfer completion before sending STP bit
Hi,
Quoted 142 lines · Felipe Balbi
Later patches will come adding support for reporting amount of bytes transferred so that client drivers can count how many bytes are left to transfer.
This is useful mostly in case of NACKs when client driver wants to know exactly which byte got NACKed so it doesn't have to resend all bytes again.
In order to make that work with OMAP's I2C controller, we need to prevent sending STP bit until message is transferred. The reason behind that is because
OMAP_I2C_CNT_REGgets reset to original value after STP bit is shifted throughI2C_SDAline and that would prevent us from reading the correct number of bytes left to transfer.The full programming model suggested by IP owner was the following:
- start I2C transfer (without STP bit)
- upon completion or NACK, readI2C_CNTregister
- write STP bit toI2C_CONregister
- wait for ARDY bitWith this patch we're implementing all steps except step #2 which will come in a later patch adding such support.
Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 89 ++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 56 deletions(-)drivers/i2c/busses/i2c-omap.c +24
-32@@ -438,9 +438,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)/* Enable interrupts */ dev->iestate = (OMAP_I2C_IE_XRDY |OMAP_I2C_IE_RRDY | -OMAP_I2C_IE_ARDY |OMAP_I2C_IE_NACK | -OMAP_I2C_IE_AL ) | ((dev->fifo_size) ? - (OMAP_I2C_IE_RDR |OMAP_I2C_IE_XDR ) :0 ); +OMAP_I2C_IE_NACK |OMAP_I2C_IE_AL ) | + ((dev->fifo_size) ? (OMAP_I2C_IE_RDR | +OMAP_I2C_IE_XDR ) :0 );omap_i2c_write_reg (dev,OMAP_I2C_IE_REG , dev->iestate);if (dev->flags &OMAP_I2C_FLAG_RESET_REGS_POSTIDLE ) { dev->pscstate = psc;@@ -470,6 +470,22 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)return 0 ; } +static int omap_i2c_wait_for_ardy (struct omap_i2c_dev *dev) +{ +unsigned long timeout; + + timeout = jiffies +OMAP_I2C_TIMEOUT ; +while (!(omap_i2c_read_reg (dev,OMAP_I2C_STAT_REG ) &OMAP_I2C_STAT_ARDY )) { +if (time_after (jiffies, timeout)) { +dev_warn (dev->dev,"timeout waiting for access ready\n" ); +return -ETIMEDOUT ; + } +usleep_range (800 ,1200 ); + } + +return 0 ; +} +static void omap_i2c_resize_fifo (struct omap_i2c_dev *dev,u8 size,bool is_rx) {u16 buf;@@ -515,7 +531,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; -int ret; +int ret =0 ;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",@@ -556,35 +572,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (!(msg->flags &I2C_M_RD )) w |=OMAP_I2C_CON_TRX ; -if (!dev->b_hw && stop) - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w);/* -* Don't write stt and stp together on some hardware. -*/ -if (dev->b_hw && stop) { -unsigned long delay = jiffies +OMAP_I2C_TIMEOUT ; -u16 con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); -while (con &OMAP_I2C_CON_STT ) { - con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - -/* Let the user know if i2c is in a bad state */ -if (time_after (jiffies, delay)) { -dev_err (dev->dev,"controller timed out " -"waiting for start condition to finish\n" ); -return -ETIMEDOUT ; - } -cpu_relax (); - } - - w |=OMAP_I2C_CON_STP ; - w &= ~OMAP_I2C_CON_STT ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - -/* * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */ @@ -594,36 +584,36 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); ret = -ETIMEDOUT ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { ret = -EIO ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ;
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 604
Quoted 10 lines
drivers/i2c/busses/i2c-omap.c +1
-7-if (stop) { - w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - ret = -EREMOTEIO ; - goto err; +omap_i2c_init (dev);
this is wrong. I will resend this patch alone. My bad.
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/d51dc1cc/attachment.sig>
PATCH v3 5/7 i2c: omap: wait for transfer completion before sending STP bit
In reply to Felipe BalbiLater patches will come adding support for reporting amount of bytes transferred so that client drivers can count how many bytes are left to transfer.
This is useful mostly in case of NACKs when client driver wants to know exactly which byte got NACKed so it doesn't have to resend all bytes again.
In order to make that work with OMAP's I2C controller, we need to prevent sending STP bit until message is transferred. The reason behind that is because OMAP_I2C_CNT_REG gets reset to original value after STP bit is shifted through I2C_SDA line and that would prevent us from reading the correct number of bytes left to transfer.
The full programming model suggested by IP owner was the following:
- start I2C transfer (without STP bit)
- upon completion or NACK, read I2C_CNT register
- write STP bit to I2C_CON register
- wait for ARDY bit
With this patch we're implementing all steps except step #2 which will come in a later patch adding such support.
---
Changes since v2:
- remove unnecessary omap_i2c_init() which was added during a rebase.
drivers/i2c/busses/i2c-omap.c | 88 ++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 56 deletions(-)
drivers/i2c/busses/i2c-omap.c +32 -56
@@ -438,9 +438,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)/* Enable interrupts */ dev->iestate = (OMAP_I2C_IE_XRDY |OMAP_I2C_IE_RRDY | -OMAP_I2C_IE_ARDY |OMAP_I2C_IE_NACK | -OMAP_I2C_IE_AL ) | ((dev->fifo_size) ? - (OMAP_I2C_IE_RDR |OMAP_I2C_IE_XDR ) :0 ); +OMAP_I2C_IE_NACK |OMAP_I2C_IE_AL ) | + ((dev->fifo_size) ? (OMAP_I2C_IE_RDR | +OMAP_I2C_IE_XDR ) :0 );omap_i2c_write_reg (dev,OMAP_I2C_IE_REG , dev->iestate);if (dev->flags &OMAP_I2C_FLAG_RESET_REGS_POSTIDLE ) { dev->pscstate = psc;
@@ -470,6 +470,22 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)return 0 ; } +static int omap_i2c_wait_for_ardy (struct omap_i2c_dev *dev) +{ +unsigned long timeout; + + timeout = jiffies +OMAP_I2C_TIMEOUT ; +while (!(omap_i2c_read_reg (dev,OMAP_I2C_STAT_REG ) &OMAP_I2C_STAT_ARDY )) { +if (time_after (jiffies, timeout)) { +dev_warn (dev->dev,"timeout waiting for access ready\n" ); +return -ETIMEDOUT ; + } +usleep_range (800 ,1200 ); + } + +return 0 ; +} +static void omap_i2c_resize_fifo (struct omap_i2c_dev *dev,u8 size,bool is_rx) {u16 buf;
@@ -515,7 +531,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, {struct omap_i2c_dev *dev =i2c_get_adapdata (adap);unsigned long timeout; -int ret; +int ret =0 ;u16 w; dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
@@ -556,35 +572,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (!(msg->flags &I2C_M_RD )) w |=OMAP_I2C_CON_TRX ; -if (!dev->b_hw && stop) - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w);/* -* Don't write stt and stp together on some hardware. -*/ -if (dev->b_hw && stop) { -unsigned long delay = jiffies +OMAP_I2C_TIMEOUT ; -u16 con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); -while (con &OMAP_I2C_CON_STT ) { - con =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - -/* Let the user know if i2c is in a bad state */ -if (time_after (jiffies, delay)) { -dev_err (dev->dev,"controller timed out " -"waiting for start condition to finish\n" ); -return -ETIMEDOUT ; - } -cpu_relax (); - } - - w |=OMAP_I2C_CON_STP ; - w &= ~OMAP_I2C_CON_STT ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - -/* * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */
@@ -594,36 +584,35 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,if (timeout ==0 ) {dev_err (dev->dev,"controller timed out\n" ); ret = -ETIMEDOUT ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) { ret = -EIO ; - goto err_i2c_init; +omap_i2c_init (dev); + goto out; }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) {if (msg->flags &I2C_M_IGNORE_NAK )return 0 ; -if (stop) { - w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); - w |=OMAP_I2C_CON_STP ; -omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); - } - ret = -EREMOTEIO ; - goto err; } -return 0 ; +out: -err_i2c_init: -omap_i2c_init (dev); +if (stop) { + w =omap_i2c_read_reg (dev,OMAP_I2C_CON_REG ); + w |=OMAP_I2C_CON_STP ; +omap_i2c_write_reg (dev,OMAP_I2C_CON_REG , w); + + ret =omap_i2c_wait_for_ardy (dev); + } -err:return ret; }
@@ -947,19 +936,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)break ; } -/* -* ProDB0017052: Clear ARDY bit twice -*/ -if (stat & (OMAP_I2C_STAT_ARDY |OMAP_I2C_STAT_NACK | -OMAP_I2C_STAT_AL )) { -omap_i2c_ack_stat (dev, (OMAP_I2C_STAT_RRDY | -OMAP_I2C_STAT_RDR | -OMAP_I2C_STAT_XRDY | -OMAP_I2C_STAT_XDR | -OMAP_I2C_STAT_ARDY )); -break ; - } -if (stat &OMAP_I2C_STAT_RDR ) {u8 num_bytes =1 ;
Signature · 1 line
1.8.0
PATCH v2 5/7 i2c: omap: wait for transfer completion before sending STP bit
In reply to Felipe BalbiQuoted 22 lines · Felipe Balbi
Later patches will come adding support for reporting amount of bytes transferred so that client drivers can count how many bytes are left to transfer.
This is useful mostly in case of NACKs when client driver wants to know exactly which byte got NACKed so it doesn't have to resend all bytes again.
In order to make that work with OMAP's I2C controller, we need to prevent sending STP bit until message is transferred. The reason behind that is because
OMAP_I2C_CNT_REGgets reset to original value after STP bit is shifted throughI2C_SDAline and that would prevent us from reading the correct number of bytes left to transfer.The full programming model suggested by IP owner was the following:
Quoted 9 lines
- start I2C transfer (without STP bit)
- upon completion or NACK, readI2C_CNTregister
- write STP bit toI2C_CONregister
- wait for ARDY bitWith this patch we're implementing all steps except step #2 which will come in a later patch adding such support.
Will this not break the bisect since CNT and NACK, completion is added in later patch
Quoted 2 lines
Signed-off-by Felipe Balbi <[email protected]>---
Apart from above, rest of the change follow the change log and looks fine tome. The change is quite drastic so hopefully it has gone through wider testing.
Regards
santosh
PATCH v2 5/7 i2c: omap: wait for transfer completion before sending STP bit
HI,
Quoted 28 lines · Santosh Shilimkar
Quoted 27 lines · Felipe Balbi
Later patches will come adding support for reporting amount of bytes transferred so that client drivers can count how many bytes are left to transfer.
This is useful mostly in case of NACKs when client driver wants to know exactly which byte got NACKed so it doesn't have to resend all bytes again.
In order to make that work with OMAP's I2C controller, we need to prevent sending STP bit until message is transferred. The reason behind that is because
OMAP_I2C_CNT_REGgets reset to original value after STP bit is shifted throughI2C_SDAline and that would prevent us from reading the correct number of bytes left to transfer.The full programming model suggested by IP owner was the following:
- start I2C transfer (without STP bit)
- upon completion or NACK, readI2C_CNTregister
- write STP bit toI2C_CONregister
- wait for ARDY bit
Quoted 6 lines
Quoted 4 lines
With this patch we're implementing all steps except step #2 which will come in a later patch adding such support.
Will this not break the bisect since CNT and
NACK, completion is added in later patch
not really. It keeps current behavior.
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121025/21c17265/attachment.sig>
PATCH v2 6/7 i2c: add 'transferred' field to struct i2c_msg
In reply to Felipe BalbiFrom: Shubhrajyoti D <[email protected]>
In case of a NACK, it's wise to tell our clients drivers about how many bytes were actually transferred.
Support this by adding an extra field to the struct i2c_msg which gets incremented the amount of bytes actually transferred.
--- include/uapi/linux/i2c.h | 1 + 1 file changed, 1 insertion(+)
include/uapi/linux/i2c.h +1 -0
@@ -77,6 +77,7 @@ struct i2c_msg {#define I2C_M_NO_RD_ACK 0x0800/* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400/* length will be first received byte */ __u16 len;/* msg length */ +__u16 transferred;/* actual bytes transferred */ __u8 *buf;/* pointer to msg data */ };
Signature · 1 line
1.8.0
PATCH v2 7/7 i2c: omap: implement handling for 'transferred' bytes
In reply to Felipe Balbithis is important in cases where client driver wants to know how many bytes were actually transferred.
There is one trick here: if transfer is completed, meaning I2C_CNT reaches zero, then ARDY will be asserted to let SW know that it can program a new transfer.
When ARDY is asserted, I2C_CNT is reset to the original value (msg->len), which means that for a successful message, msg->transferred = msg->len and we don't need to spend time with a register read.
In case of NACK condition, however, I2C_CNT will remain with the end value which is the amount of data transferred until NACK condition found on the bus inclusive. In this situation, msg->transferred needs to be initialized with:
msg->len - read(I2C_CNT) - 1;
This patch implements exactly that handling.
--- drivers/i2c/busses/i2c-omap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/i2c/busses/i2c-omap.c +12 -0
@@ -588,6 +588,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto out; } + msg->transferred = msg->len; +wmb (); +/* We have an error */ if (dev->cmd_err & (OMAP_I2C_STAT_AL |OMAP_I2C_STAT_ROVR |OMAP_I2C_STAT_XUDF )) {
@@ -597,6 +600,15 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, }if (dev->cmd_err &OMAP_I2C_STAT_NACK ) { +/* In case of a NACK, we need to check how many bytes we +* actually transferred, so we can tell our client driver about +* it. +* +* Let's check it here and overwrite msg->transferred. +*/ + w =omap_i2c_read_reg (dev,OMAP_I2C_CNT_REG ); + msg->transferred = msg->len - w -1 ; +if (msg->flags &I2C_M_IGNORE_NAK )return 0 ;
Signature · 1 line
1.8.0
Paul Walmsley
maintainerPATCH v2 7/7 i2c: omap: implement handling for 'transferred' bytes
Hi
Quoted 35 lines · Felipe Balbi
this is important in cases where client driver wants to know how many bytes were actually transferred.
There is one trick here: if transfer is completed, meaning
I2C_CNTreaches zero, then ARDY will be asserted to let SW know that it can program a new transfer.When ARDY is asserted,
I2C_CNTis reset to the original value (msg->len), which means that for a successful message,msg->transferred=msg->lenand we don't need to spend time with a register read.In case of NACK condition, however,
I2C_CNTwill remain with the end value which is the amount of data transferred until NACK condition found on the bus inclusive. In this situation,msg->transferredneeds to be initialized with:
msg->len-read(I2C_CNT)- 1;This patch implements exactly that handling.
Signed-off-by Felipe Balbi <[email protected]>--- drivers/i2c/busses/i2c-omap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)drivers/i2c/busses/i2c-omap.c +0
-0
drivers/i2c/busses/i2c-omap.c static int omap_i2c_xfer_msg(struct i2c_adapter *adap, · line 592
Quoted 5 lines
drivers/i2c/busses/i2c-omap.c +2
-0@@ -588,6 +588,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, goto out; } + msg->transferred = msg->len; +wmb ();
If this barrier is being used to ensure that the compiler doesn't move this store past the point at which the I2C interrupt handler can be entered, then please consider the same comments as on the other patch that adds a barrier:
http://marc.info/?l=linux-omap&m=135129247524136&w=2
http://marc.info/?l=linux-omap&m=135135357305794&w=2
- Paul
v2 cover I2C patches for v3.8 merge window
In reply to Felipe BalbiHi,
Quoted 11 lines · Felipe Balbi
Hi,
here's another series for OMAP I2C driver. There are a few cleanups and one very nice new feature: we can now report how many bytes we transferred until NACK.
Note that the implemementation for OMAP-I2C turned out to be a little more complex then I expected, mainly because of the way
I2C_CNTregister behaves and because of the very buggy register usage on that driver.
Quoted 5 lines
I have boot tested all patches on beagle xM (3630) and pandaboard rev A3 (4430), will send boot-logs if anyone wants to see.
All patches are available at [1] if anyone wants an easy way to test the patches.
Wolfram, patches 1-5 are ok to apply, we just need to rework patches 6 and 7 so drivers can report how many bytes managed to be transferred. None of these patches cause any known regressions.
let me know if you want me to resend only the 5 patches which should be applied.
cheers
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121105/49c4a6f5/attachment.sig>