diff mbox

[v3] OMAP2/3: hwmod: fix the i2c-reset timeout during bootup

Message ID 1304328111-15999-1-git-send-email-avinashhm@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Avinash H.M. May 2, 2011, 9:21 a.m. UTC
The sequence of _ocp_softreset doesn't work for i2c. The i2c module has a
special sequence to reset the module. The sequence is
 - Disable the I2C.
 - Write to SOFTRESET bit.
 - Enable the I2C.
 - Poll on the RESETDONE bit.
The sequence is implemented as a function and the i2c_class is updated with
the correct 'reset' pointer.  omap_hwmod_softreset function is implemented
which triggers the softreset by writing into sysconfig register. On following
this sequence, i2c module resets properly and timeouts are not seen.

Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
Signed-off-by: Avinash.H.M <avinashhm@ti.com>
---

The patch is based on
 * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
 * master branch.
 * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )

Changes from previous versions:
from v1:
	- moved i2c specific things from hwmod files to i2c files.
	- fixed comments from Paul.
	- http://www.spinics.net/lists/linux-omap/msg49483.html

from v2: 
	- Avoided direct SYSCONFIG access in i2c.c
	- http://www.spinics.net/lists/linux-omap/msg49632.html

Testing:
* build tested omap2plus_defconfig for warnings and errors. none introduced.
* boot tested on 2430. 
* tested for 'core off' in suspend resume on 3430 sdp. core off counters
  increment after suspend resume. 

 arch/arm/mach-omap2/i2c.c                    |   54 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/omap_hwmod.c             |   12 ++++++
 arch/arm/mach-omap2/omap_hwmod_2420_data.c   |    1 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c   |    1 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c   |    1 +
 arch/arm/plat-omap/include/plat/i2c.h        |    4 ++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
 7 files changed, 74 insertions(+), 0 deletions(-)

Comments

Paul Walmsley May 5, 2011, 9:58 p.m. UTC | #1
Hello Avinash

On Mon, 2 May 2011, Avinash.H.M wrote:

> The sequence of _ocp_softreset doesn't work for i2c. The i2c module has a
> special sequence to reset the module. The sequence is
>  - Disable the I2C.
>  - Write to SOFTRESET bit.
>  - Enable the I2C.
>  - Poll on the RESETDONE bit.
> The sequence is implemented as a function and the i2c_class is updated with
> the correct 'reset' pointer.  omap_hwmod_softreset function is implemented
> which triggers the softreset by writing into sysconfig register. On following
> this sequence, i2c module resets properly and timeouts are not seen.
> 
> Cc: Rajendra Nayak <rnayak@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@ti.com>
> Signed-off-by: Avinash.H.M <avinashhm@ti.com>
> ---
> 
> The patch is based on
>  * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
>  * master branch.
>  * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )

Please base all your patches against mainline commits.  I suggest using 
v2.6.39-rc6.

Also some comments:

> Changes from previous versions:
> from v1:
> 	- moved i2c specific things from hwmod files to i2c files.
> 	- fixed comments from Paul.
> 	- http://www.spinics.net/lists/linux-omap/msg49483.html
> 
> from v2: 
> 	- Avoided direct SYSCONFIG access in i2c.c
> 	- http://www.spinics.net/lists/linux-omap/msg49632.html
> 
> Testing:
> * build tested omap2plus_defconfig for warnings and errors. none introduced.
> * boot tested on 2430. 
> * tested for 'core off' in suspend resume on 3430 sdp. core off counters
>   increment after suspend resume. 
> 
>  arch/arm/mach-omap2/i2c.c                    |   54 ++++++++++++++++++++++++++
>  arch/arm/mach-omap2/omap_hwmod.c             |   12 ++++++
>  arch/arm/mach-omap2/omap_hwmod_2420_data.c   |    1 +
>  arch/arm/mach-omap2/omap_hwmod_2430_data.c   |    1 +
>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c   |    1 +
>  arch/arm/plat-omap/include/plat/i2c.h        |    4 ++
>  arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
>  7 files changed, 74 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
> index 79c478c..bd50e26 100644
> --- a/arch/arm/mach-omap2/i2c.c
> +++ b/arch/arm/mach-omap2/i2c.c
> @@ -21,9 +21,16 @@
>  
>  #include <plat/cpu.h>
>  #include <plat/i2c.h>
> +#include <plat/common.h>
>  
>  #include "mux.h"
>  
> +/* In register I2C_CON, Bit 15 is the I2C enable bit */
> +#define I2C_EN				BIT(15)
> +#define I2C_CON_OFFSET			0x24
> +/* Maximum microseconds to wait for OMAP module to softreset */
> +#define MAX_MODULE_SOFTRESET_WAIT	10000
> +
>  void __init omap2_i2c_mux_pins(int bus_id)
>  {
>  	char mux_name[sizeof("i2c2_scl.i2c2_scl")];
> @@ -37,3 +44,50 @@ void __init omap2_i2c_mux_pins(int bus_id)
>  	sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id);
>  	omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
>  }
> +
> +/**
> + * omap_i2c_reset- reset the omap i2c module.

Please put a space before the dash.

> + * @oh: struct omap_hwmod *
> + *
> + * The i2c moudle in omap2, omap3 had a special sequence to reset. The
> + * sequence is:
> + * - Disable the I2C.
> + * - Write to SOFTRESET bit.
> + * - Enable the I2C.
> + * - Poll on the RESETDONE bit.
> + * The sequence is implemented in below function. This is called for 2420,
> + * 2430 and omap3.
> + */
> +int omap_i2c_reset(struct omap_hwmod *oh)
> +{
> +	u32 v;
> +	int c = 0;
> +
> +	/* Disable I2C */
> +	v = omap_hwmod_read(oh, I2C_CON_OFFSET);
> +	v = v & ~I2C_EN;
> +	omap_hwmod_write(v, oh, I2C_CON_OFFSET);
> +
> +	/* Write to the SOFTRESET bit */
> +	omap_hwmod_softreset(oh);
> +
> +	/* Enable I2C */
> +	v = omap_hwmod_read(oh, I2C_CON_OFFSET);
> +	v |= I2C_EN;
> +	omap_hwmod_write(v, oh, I2C_CON_OFFSET);
> +
> +	/* Poll on RESETDONE bit */
> +	omap_test_timeout((omap_hwmod_read(oh,
> +				oh->class->sysc->syss_offs)
> +				& SYSS_RESETDONE_MASK),
> +				MAX_MODULE_SOFTRESET_WAIT, c);
> +
> +	if (c == MAX_MODULE_SOFTRESET_WAIT)
> +		pr_warning("%s: %s: softreset failed (waited %d usec)\n",
> +			__func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
> +	else
> +		pr_debug("%s: %s: softreset in %d usec\n", __func__,
> +			oh->name, c);
> +
> +	return 0;
> +}
> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
> index e034294..771fc15 100644
> --- a/arch/arm/mach-omap2/omap_hwmod.c
> +++ b/arch/arm/mach-omap2/omap_hwmod.c
> @@ -1561,6 +1561,18 @@ void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
>  		__raw_writel(v, oh->_mpu_rt_va + reg_offs);
>  }
>  

You're missing kerneldoc here.  Please add it.

> +void omap_hwmod_softreset(struct omap_hwmod *oh)
> +{
> +	u32 v;
> +
> +	/* Write to the SOFTRESET bit in SYSCONFIG */
> +	v = oh->_sysc_cache;
> +	v |= (0x1 << oh->class->sysc->sysc_fields->srst_shift);
> +
> +	oh->_sysc_cache = v;
> +	omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
> +}

This is a public function, so you need to validate your oh argument and 
return an error if something isn't right.  Similarly, you should use the 
existing function _set_softreset() to set the bit, because it also does 
some errorchecking.

> +
>  /**
>   * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
>   * @oh: struct omap_hwmod *
> diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
> index e9a416c..fd386af 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
> @@ -1447,6 +1447,7 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
>  static struct omap_hwmod_class i2c_class = {
>  	.name		= "i2c",
>  	.sysc		= &i2c_sysc,
> +	.reset		= &omap_i2c_reset,
>  	.rev		= OMAP_I2C_IP_VERSION_1,
>  };
>  
> diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
> index beedda6..4ad4188 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
> @@ -1524,6 +1524,7 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
>  static struct omap_hwmod_class i2c_class = {
>  	.name		= "i2c",
>  	.sysc		= &i2c_sysc,
> +	.reset		= &omap_i2c_reset,
>  	.rev		= OMAP_I2C_IP_VERSION_1,
>  };
>  
> diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> index dec1a38..e938810 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> @@ -1460,6 +1460,7 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = {
>  static struct omap_hwmod_class i2c_class = {
>  	.name = "i2c",
>  	.sysc = &i2c_sysc,
> +	.reset = &omap_i2c_reset,
>  	.rev  = OMAP_I2C_IP_VERSION_1,
>  };
>  
> diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
> index fd75dad..20237c1 100644
> --- a/arch/arm/plat-omap/include/plat/i2c.h
> +++ b/arch/arm/plat-omap/include/plat/i2c.h
> @@ -24,6 +24,8 @@
>  #include <linux/i2c.h>
>  #include <linux/i2c-omap.h>
>  
> +#include <plat/omap_hwmod.h>
> +
>  #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
>  extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
>  				 struct i2c_board_info const *info,
> @@ -53,4 +55,6 @@ struct omap_i2c_dev_attr {
>  void __init omap1_i2c_mux_pins(int bus_id);
>  void __init omap2_i2c_mux_pins(int bus_id);
>  
> +int omap_i2c_reset(struct omap_hwmod *oh);
> +
>  #endif /* __ASM__ARCH_OMAP_I2C_H */
> diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
> index 1adea9c..9637130 100644
> --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
> +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
> @@ -572,6 +572,7 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
>  
>  void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
>  u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
> +void omap_hwmod_softreset(struct omap_hwmod *oh);
>  
>  int omap_hwmod_count_resources(struct omap_hwmod *oh);
>  int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
> -- 
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


- Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avinash H.M. May 9, 2011, 12:48 p.m. UTC | #2
On Thu, May 05, 2011 at 03:58:56PM -0600, Paul Walmsley wrote:

Hi Paul ,

> > 
> > The patch is based on
> >  * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> >  * master branch.
> >  * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )
> 
> Please base all your patches against mainline commits.  I suggest using 
> v2.6.39-rc6.

OK Paul. I will rebase against mainline, -rc6.

> 
> Also some comments:
> 
> > Changes from previous versions:
> > from v1:
> > 	- moved i2c specific things from hwmod files to i2c files.
> > 	- fixed comments from Paul.
> > 	- http://www.spinics.net/lists/linux-omap/msg49483.html
> > 
> > +
> > +/**
> > + * omap_i2c_reset- reset the omap i2c module.
> 
> Please put a space before the dash.

OK. I ll correct.

> 
> > + * @oh: struct omap_hwmod *
> > + *
> > + * The i2c moudle in omap2, omap3 had a special sequence to reset. The
> > + * sequence is:
> > + * - Disable the I2C.
> > + * - Write to SOFTRESET bit.
> > + * - Enable the I2C.
> > + * - Poll on the RESETDONE bit.
> > + * The sequence is implemented in below function. This is called for 2420,
> > + * 2430 and omap3.
> > + */
> > +int omap_i2c_reset(struct omap_hwmod *oh)
> > +{
> You're missing kerneldoc here.  Please add it.

OK. I ll add the kerneldoc.

> 
> > +void omap_hwmod_softreset(struct omap_hwmod *oh)
> > +{
> > +	u32 v;
> > +
> > +	/* Write to the SOFTRESET bit in SYSCONFIG */
> > +	v = oh->_sysc_cache;
> > +	v |= (0x1 << oh->class->sysc->sysc_fields->srst_shift);
> > +
> > +	oh->_sysc_cache = v;
> > +	omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
> > +}
> 
> This is a public function, so you need to validate your oh argument and 
> return an error if something isn't right.  Similarly, you should use the 
> existing function _set_softreset() to set the bit, because it also does 
> some errorchecking.
> 


I agree. I ll use _set_softreset to set the bit and check for the
argument sanity.

> > +
> >  /**
> >   * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
> >   * @oh: struct omap_hwmod *
> > diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c

thanks for reviewing.

- Avinash
> 
> 
> - Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Walmsley May 18, 2011, 4:22 p.m. UTC | #3
On Mon, 9 May 2011, Avinash.H.M. wrote:

> On Thu, May 05, 2011 at 03:58:56PM -0600, Paul Walmsley wrote:
> 
> > > 
> > > The patch is based on
> > >  * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> > >  * master branch.
> > >  * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )
> > 
> > Please base all your patches against mainline commits.  I suggest using 
> > v2.6.39-rc6.
> 
> OK Paul. I will rebase against mainline, -rc6.

Ping.  Any progress?


- Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avinash H.M. May 18, 2011, 4:25 p.m. UTC | #4
On Wed, May 18, 2011 at 10:22:28AM -0600, Paul Walmsley wrote:
> On Mon, 9 May 2011, Avinash.H.M. wrote:
> 
> > On Thu, May 05, 2011 at 03:58:56PM -0600, Paul Walmsley wrote:
> > 
> > > > 
> > > > The patch is based on
> > > >  * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> > > >  * master branch.
> > > >  * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )
> > > 
> > > Please base all your patches against mainline commits.  I suggest using 
> > > v2.6.39-rc6.
> > 
> > OK Paul. I will rebase against mainline, -rc6.
> 
> Ping.  Any progress?

Hi Paul ,

I am having the patch ready. Haven't had a chance to test. I will test
and send by tomorrow.

thanks ,

- Avinash

> 
> 
> - Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Koyamangalath, Abhilash May 19, 2011, 12:35 p.m. UTC | #5
> On Wed, May 18, 2011 at 10:22:28AM -0600, Paul Walmsley wrote:
> > On Mon, 9 May 2011, Avinash.H.M. wrote:
> >
> > > On Thu, May 05, 2011 at 03:58:56PM -0600, Paul Walmsley wrote:
> > >
> > > > >
> > > > > The patch is based on
> > > > >  * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> > > > >  * master branch.
> > > > >  * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )
> > > >
> > > > Please base all your patches against mainline commits.  I suggest using
> > > > v2.6.39-rc6.
> > >
> > > OK Paul. I will rebase against mainline, -rc6.
> >
> > Ping.  Any progress?
>
> Hi Paul ,
>
> I am having the patch ready. Haven't had a chance to test. I will test
> and send by tomorrow.

> thanks ,

> - Avinash
I have tried the patch on am37x evm and the i2c soft-reset time-out issue doesn't
seem to go off for me. Previously I used to get a log  : 

[    0.000000] omap_hwmod: i2c1: softreset failed (waited 10000 usec)                                                                                                            
[    0.000000] omap_hwmod: i2c2: softreset failed (waited 10000 usec)                                                                                                            
[    0.000000] omap_hwmod: i2c3: softreset failed (waited 10000 usec) 

And now I get :
[    0.000000] omap_i2c_reset: i2c1: softreset failed (waited 10000 usec)
[    0.000000] omap_i2c_reset: i2c2: softreset failed (waited 10000 usec)
[    0.000000] omap_i2c_reset: i2c3: softreset failed (waited 10000 usec)

So the function where this failure happens seems to be the only thing that has changed.
I've tried this patch on top of the recent PSP 04.02.00.07 release. 
What am I missing?

thanks,
Abhilash



> >
> >
> > - Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avinash H.M. May 20, 2011, 3:02 p.m. UTC | #6
On Wed, May 18, 2011 at 09:55:42PM +0530, Avinash.H.M. wrote:
> On Wed, May 18, 2011 at 10:22:28AM -0600, Paul Walmsley wrote:
> > On Mon, 9 May 2011, Avinash.H.M. wrote:
> > 
> > > On Thu, May 05, 2011 at 03:58:56PM -0600, Paul Walmsley wrote:
> > > 
> > > > > 
> > > > > The patch is based on
> > > > >  * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> > > > >  * master branch.
> > > > >  * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )
> > > > 
> > > > Please base all your patches against mainline commits.  I suggest using 
> > > > v2.6.39-rc6.
> > > 
> > > OK Paul. I will rebase against mainline, -rc6.
> > 
> > Ping.  Any progress?
> 
> Hi Paul ,
> 
> I am having the patch ready. Haven't had a chance to test. I will test
> and send by tomorrow.

Hi Paul ,

I tested the patch on 3430 sdp today with the patch against 2.6.39-rc7.

I am seeing that the timeout is there during bootup event with this
patch. Tried with the previous version (v3 , which was tested against
the older commit and was confirmed to be working). With this also, i am
seeing that the reset timeouts are still present. 

So, looks like there is something broken. First glance, i suspect that
the register access may not be proper. Need to debug more. I ll debug
this and send the fix together.

Incase, if you want me to send this patch now and then send a seperate
patch for the recent problem, do let me know.

thanks ,

- Avinash

> thanks ,
> 
> - Avinash
> 
> > 
> > 
> > - Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avinash H.M. May 20, 2011, 3:38 p.m. UTC | #7
On Fri, May 20, 2011 at 08:32:17PM +0530, Avinash.H.M. wrote:
> On Wed, May 18, 2011 at 09:55:42PM +0530, Avinash.H.M. wrote:
> > On Wed, May 18, 2011 at 10:22:28AM -0600, Paul Walmsley wrote:
> > > On Mon, 9 May 2011, Avinash.H.M. wrote:
> > > 
> > > > On Thu, May 05, 2011 at 03:58:56PM -0600, Paul Walmsley wrote:
> > > > 
> > > > > > 
> > > > > > The patch is based on
> > > > > >  * git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
> > > > > >  * master branch.
> > > > > >  * 9be20f0 commit. ( Linux-omap rebuilt: Updated to -rc5 )
> > > > > 
> > > > > Please base all your patches against mainline commits.  I suggest using 
> > > > > v2.6.39-rc6.
> > > > 
> > > > OK Paul. I will rebase against mainline, -rc6.
> > > 
> > > Ping.  Any progress?
> > 
> > Hi Paul ,
> > 
> > I am having the patch ready. Haven't had a chance to test. I will test
> > and send by tomorrow.
> 
> Hi Paul ,
> 
> I tested the patch on 3430 sdp today with the patch against 2.6.39-rc7.
> 
> I am seeing that the timeout is there during bootup event with this
> patch. Tried with the previous version (v3 , which was tested against
> the older commit and was confirmed to be working). With this also, i am
> seeing that the reset timeouts are still present. 
> 
> So, looks like there is something broken. First glance, i suspect that
> the register access may not be proper. Need to debug more. I ll debug

Hi Paul ,

This turned out to be the issue. The register access weren't proper. I2C
needs 16bit access. We need a flag 'HWMOD_16BIT_REG' added to i2c1,2,3
hwmods.

Andy Green has already submitted a patch for this and looks like it is
not merged. After adding this patch, now no more timeouts are seen. I ll
mention this dependency and submit v4.

thanks ,

- Avinash


> this and send the fix together.
> 
> Incase, if you want me to send this patch now and then send a seperate
> patch for the recent problem, do let me know.
> 
> thanks ,
> 
> - Avinash
> 
> > thanks ,
> > 
> > - Avinash
> > 
> > > 
> > > 
> > > - Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avinash H.M. May 24, 2011, 7:07 p.m. UTC | #8
On Thu, May 19, 2011 at 06:05:21PM +0530, Koyamangalath, Abhilash wrote:

> I have tried the patch on am37x evm and the i2c soft-reset time-out issue doesn't
> seem to go off for me. Previously I used to get a log  : 
> 
> [    0.000000] omap_hwmod: i2c1: softreset failed (waited 10000 usec)                                                                                                            
> [    0.000000] omap_hwmod: i2c2: softreset failed (waited 10000 usec)                                                                                                            
> [    0.000000] omap_hwmod: i2c3: softreset failed (waited 10000 usec) 
> 
> And now I get :
> [    0.000000] omap_i2c_reset: i2c1: softreset failed (waited 10000 usec)
> [    0.000000] omap_i2c_reset: i2c2: softreset failed (waited 10000 usec)
> [    0.000000] omap_i2c_reset: i2c3: softreset failed (waited 10000 usec)
> 
> So the function where this failure happens seems to be the only thing that has changed.
> I've tried this patch on top of the recent PSP 04.02.00.07 release. 
> What am I missing?

Abhilash ,

I am not sure what is PSP 04.02.00.07 release. But you should make sure
that the hwmod structures in omap_hwmod_3xxx_data.c should have the
16_bit flags. 

Below is just a snippet in P.S.. There is already a patch submitted by
andy green for this. Not sure, if it is merged.  

With this and the posted v3 patch, you should not see timeouts. Or else
you have some other problem.

thanks ,

- Avinash

PS:

 static struct omap_hwmod omap3xxx_i2c1_hwmod = {
        .name           = "i2c1",
+       .flags          = HWMOD_16BIT_REG,
 

> 
> thanks,
> Abhilash
> 
> 
> 
> > >
> > >
> > > - Paul
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Koyamangalath, Abhilash May 25, 2011, 1:15 p.m. UTC | #9
>On Thu, May 19, 2011 at 06:05:21PM +0530, Koyamangalath, Abhilash wrote:
>
> > I have tried the patch on am37x evm and the i2c soft-reset time-out issue doesn't
> > seem to go off for me. Previously I used to get a log  :
> >
> > [    0.000000] omap_hwmod: i2c1: softreset failed (waited 10000 usec)
> > [    0.000000] omap_hwmod: i2c2: softreset failed (waited 10000 usec)
> > [    0.000000] omap_hwmod: i2c3: softreset failed (waited 10000 usec)
> >
> > And now I get :
> > [    0.000000] omap_i2c_reset: i2c1: softreset failed (waited 10000 usec)
> > [    0.000000] omap_i2c_reset: i2c2: softreset failed (waited 10000 usec)
> > [    0.000000] omap_i2c_reset: i2c3: softreset failed (waited 10000 usec)
> >
> > So the function where this failure happens seems to be the only thing that has changed.
> > I've tried this patch on top of the recent PSP 04.02.00.07 release.
> > What am I missing?
>
>Abhilash ,
>
>I am not sure what is PSP 04.02.00.07 release. But you should make sure
>that the hwmod structures in omap_hwmod_3xxx_data.c should have the
>16_bit flags.
>
>Below is just a snippet in P.S.. There is already a patch submitted by
>andy green for this. Not sure, if it is merged.
>
>With this and the posted v3 patch, you should not see timeouts. Or else
>you have some other problem.
>
>thanks ,
>
>- Avinash
>
>PS:
>
> static struct omap_hwmod omap3xxx_i2c1_hwmod = {
>        .name           = "i2c1",
>+       .flags          = HWMOD_16BIT_REG,

Yes Avinash, that works , 
thanks.
>
>
> >
> > thanks,
> > Abhilash
> >
> >
> >
> > > >
> > > >
> > > > - Paul
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index 79c478c..bd50e26 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -21,9 +21,16 @@ 
 
 #include <plat/cpu.h>
 #include <plat/i2c.h>
+#include <plat/common.h>
 
 #include "mux.h"
 
+/* In register I2C_CON, Bit 15 is the I2C enable bit */
+#define I2C_EN				BIT(15)
+#define I2C_CON_OFFSET			0x24
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT	10000
+
 void __init omap2_i2c_mux_pins(int bus_id)
 {
 	char mux_name[sizeof("i2c2_scl.i2c2_scl")];
@@ -37,3 +44,50 @@  void __init omap2_i2c_mux_pins(int bus_id)
 	sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id);
 	omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
 }
+
+/**
+ * omap_i2c_reset- reset the omap i2c module.
+ * @oh: struct omap_hwmod *
+ *
+ * The i2c moudle in omap2, omap3 had a special sequence to reset. The
+ * sequence is:
+ * - Disable the I2C.
+ * - Write to SOFTRESET bit.
+ * - Enable the I2C.
+ * - Poll on the RESETDONE bit.
+ * The sequence is implemented in below function. This is called for 2420,
+ * 2430 and omap3.
+ */
+int omap_i2c_reset(struct omap_hwmod *oh)
+{
+	u32 v;
+	int c = 0;
+
+	/* Disable I2C */
+	v = omap_hwmod_read(oh, I2C_CON_OFFSET);
+	v = v & ~I2C_EN;
+	omap_hwmod_write(v, oh, I2C_CON_OFFSET);
+
+	/* Write to the SOFTRESET bit */
+	omap_hwmod_softreset(oh);
+
+	/* Enable I2C */
+	v = omap_hwmod_read(oh, I2C_CON_OFFSET);
+	v |= I2C_EN;
+	omap_hwmod_write(v, oh, I2C_CON_OFFSET);
+
+	/* Poll on RESETDONE bit */
+	omap_test_timeout((omap_hwmod_read(oh,
+				oh->class->sysc->syss_offs)
+				& SYSS_RESETDONE_MASK),
+				MAX_MODULE_SOFTRESET_WAIT, c);
+
+	if (c == MAX_MODULE_SOFTRESET_WAIT)
+		pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+			__func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+	else
+		pr_debug("%s: %s: softreset in %d usec\n", __func__,
+			oh->name, c);
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e034294..771fc15 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1561,6 +1561,18 @@  void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
 		__raw_writel(v, oh->_mpu_rt_va + reg_offs);
 }
 
+void omap_hwmod_softreset(struct omap_hwmod *oh)
+{
+	u32 v;
+
+	/* Write to the SOFTRESET bit in SYSCONFIG */
+	v = oh->_sysc_cache;
+	v |= (0x1 << oh->class->sysc->sysc_fields->srst_shift);
+
+	oh->_sysc_cache = v;
+	omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
+}
+
 /**
  * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
  * @oh: struct omap_hwmod *
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index e9a416c..fd386af 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1447,6 +1447,7 @@  static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
 	.name		= "i2c",
 	.sysc		= &i2c_sysc,
+	.reset		= &omap_i2c_reset,
 	.rev		= OMAP_I2C_IP_VERSION_1,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index beedda6..4ad4188 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1524,6 +1524,7 @@  static struct omap_hwmod_class_sysconfig i2c_sysc = {
 static struct omap_hwmod_class i2c_class = {
 	.name		= "i2c",
 	.sysc		= &i2c_sysc,
+	.reset		= &omap_i2c_reset,
 	.rev		= OMAP_I2C_IP_VERSION_1,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index dec1a38..e938810 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1460,6 +1460,7 @@  static struct omap_hwmod omap3xxx_uart4_hwmod = {
 static struct omap_hwmod_class i2c_class = {
 	.name = "i2c",
 	.sysc = &i2c_sysc,
+	.reset = &omap_i2c_reset,
 	.rev  = OMAP_I2C_IP_VERSION_1,
 };
 
diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
index fd75dad..20237c1 100644
--- a/arch/arm/plat-omap/include/plat/i2c.h
+++ b/arch/arm/plat-omap/include/plat/i2c.h
@@ -24,6 +24,8 @@ 
 #include <linux/i2c.h>
 #include <linux/i2c-omap.h>
 
+#include <plat/omap_hwmod.h>
+
 #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
 				 struct i2c_board_info const *info,
@@ -53,4 +55,6 @@  struct omap_i2c_dev_attr {
 void __init omap1_i2c_mux_pins(int bus_id);
 void __init omap2_i2c_mux_pins(int bus_id);
 
+int omap_i2c_reset(struct omap_hwmod *oh);
+
 #endif /* __ASM__ARCH_OMAP_I2C_H */
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1adea9c..9637130 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -572,6 +572,7 @@  void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
 
 void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
 u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
+void omap_hwmod_softreset(struct omap_hwmod *oh);
 
 int omap_hwmod_count_resources(struct omap_hwmod *oh);
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);