| From: Jon Hunter <jon-hunter@ti.com> |
| Date: Fri, 23 Aug 2013 04:40:23 -0600 |
| Subject: ARM: OMAP2+: Only write the sysconfig on idle when necessary |
| |
| commit 127500ccb766f0e963436e25ddd57be8f1695498 upstream. |
| |
| Currently, whenever we idle a device _idle_sysc() is called and writes to the |
| devices SYSCONFIG register to set the idle mode. A lot devices are using the |
| smart-idle mode and so the write to the SYSCONFIG register is programming the |
| same value that is already stored in the register. |
| |
| Writes to the devices SYSCONFIG register can be slow, for example, writing to |
| the DMTIMER SYSCONFIG register takes 3 interface clock cycles and 3 functional |
| clock cycles. If the DMTIMER is using the slow 32kHz functional clock this can |
| take ~100us. |
| |
| Furthermore, during boot on an OMAP4430 panda board, I see that there are 100 |
| calls to _idle_sysc(), however, only 3 out of the 100 calls actually write |
| the SYSCONFIG register with a new value. |
| |
| Therefore, to avoid unnecessary writes to device SYSCONFIG registers when |
| idling the device, only write the value if the value has changed. It should be |
| safe to do this on idle as the context of the register will never be lost while |
| the device is active. |
| |
| Verified that suspend, CORE off and retention states are working with this |
| change on OMAP3430 Beagle board. |
| |
| Signed-off-by: Jon Hunter <jon-hunter@ti.com> |
| [paul@pwsan.com: updated to apply] |
| Signed-off-by: Paul Walmsley <paul@pwsan.com> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| arch/arm/mach-omap2/omap_hwmod.c | 4 +++- |
| 1 file changed, 3 insertions(+), 1 deletion(-) |
| |
| --- a/arch/arm/mach-omap2/omap_hwmod.c |
| +++ b/arch/arm/mach-omap2/omap_hwmod.c |
| @@ -1946,7 +1946,9 @@ static int _ocp_softreset(struct omap_hw |
| if (ret) |
| goto dis_opt_clks; |
| |
| - _write_sysconfig(v, oh); |
| + /* If the cached value is the same as the new value, skip the write */ |
| + if (oh->_sysc_cache != v) |
| + _write_sysconfig(v, oh); |
| |
| if (oh->class->sysc->srst_udelay) |
| udelay(oh->class->sysc->srst_udelay); |