Skip to content

Commit

Permalink
ARM: OMAP2+: hwmod: Fix SOFTRESET logic
Browse files Browse the repository at this point in the history
commit 313a76e upstream.

In _ocp_softreset(), after _set_softreset() + write_sysconfig(),
the hwmod's sysc_cache will always contain SOFTRESET bit set
so all further writes to sysconfig using this cache will initiate
a repeated SOFTRESET e.g. enable_sysc(). This is true for OMAP3 like
platforms that have RESET_DONE status in the SYSSTATUS register and
so the the SOFTRESET bit in SYSCONFIG is not automatically cleared.
It is not a problem for OMAP4 like platforms that indicate RESET
completion by clearing the SOFTRESET bit in the SYSCONFIG register.

This repeated SOFTRESET is undesired and was the root cause of
USB host issues on OMAP3 platforms when hwmod was allowed to do the
SOFTRESET for the USB Host module.

To fix this we clear the SOFTRESET bit and update the sysconfig
register + sysc_cache using write_sysconfig().

Signed-off-by: Roger Quadros <rogerq@ti.com>
Tested-by: Tomi Valkeinen <tomi.valkeinen@ti.com> # Panda, BeagleXM
[paul@pwsan.com: renamed _clr_softreset() to _clear_softreset()]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Roger Quadros authored and Greg Kroah-Hartman committed Dec 20, 2013
1 parent 8670ef4 commit 2c64388
Showing 1 changed file with 42 additions and 1 deletion.
43 changes: 42 additions & 1 deletion arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
}

/**
* _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
* _set_softreset: set OCP_SYSCONFIG.SOFTRESET bit in @v
* @oh: struct omap_hwmod *
* @v: pointer to register contents to modify
*
Expand Down Expand Up @@ -1377,6 +1377,36 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
}
}

/**
* _clear_softreset: clear OCP_SYSCONFIG.SOFTRESET bit in @v
* @oh: struct omap_hwmod *
* @v: pointer to register contents to modify
*
* Clear the SOFTRESET bit in @v for hwmod @oh. Returns -EINVAL upon
* error or 0 upon success.
*/
static int _clear_softreset(struct omap_hwmod *oh, u32 *v)
{
u32 softrst_mask;

if (!oh->class->sysc ||
!(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
return -EINVAL;

if (!oh->class->sysc->sysc_fields) {
WARN(1,
"omap_hwmod: %s: sysc_fields absent for sysconfig class\n",
oh->name);
return -EINVAL;
}

softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);

*v &= ~softrst_mask;

return 0;
}

/**
* _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
* @oh: struct omap_hwmod *
Expand Down Expand Up @@ -1420,6 +1450,12 @@ static int _ocp_softreset(struct omap_hwmod *oh)
ret = _set_softreset(oh, &v);
if (ret)
goto dis_opt_clks;

_write_sysconfig(v, oh);
ret = _clear_softreset(oh, &v);
if (ret)
goto dis_opt_clks;

_write_sysconfig(v, oh);

if (oh->class->sysc->srst_udelay)
Expand Down Expand Up @@ -1918,6 +1954,11 @@ int omap_hwmod_softreset(struct omap_hwmod *oh)
goto error;
_write_sysconfig(v, oh);

ret = _clear_softreset(oh, &v);
if (ret)
goto error;
_write_sysconfig(v, oh);

error:
return ret;
}
Expand Down

0 comments on commit 2c64388

Please sign in to comment.