diff options
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 7144ae651d3..bb7ed98ab9a 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -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 * @@ -1378,6 +1378,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 * * @@ -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) @@ -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; } |