• Kevin Hilman's avatar
    OMAP2+: omap_hwmod: fix wakeup enable/disable for consistency · 5a7ddcbd
    Kevin Hilman authored
    In the omap_hwmod core, most of the SYSCONFIG register helper
    functions do not directly write the register, but instead just modify
    a value passed in.
    
    This patch converts the _enable_wakeup() and _disable_wakeup() helper
    functions to take a value argument and only modify it instead of
    actually writing the register.  This makes the wakeup helpers
    consistent with the other helper functions and avoids unintentional
    problems like the following.
    
    This problem was found after discovering that GPIO wakeups were no
    longer functional.  The root cause was that the ENAWAKEUP bit of the
    SYSCONFIG register was being unintentionaly overwritten, leaving
    wakeups disabled after the following two commits were combined:
    
    commit: 9980ce53
            OMAP: hwmod: Enable module wakeup if in smartidle
    
    commit: 78f26e87
            OMAP: hwmod: Set autoidle after smartidle during _sysc_enable
    
    There resulting in code in _enable_sysc() was this:
    
    	/*
    	 * XXX The clock framework should handle this, by
    	 * calling into this code.  But this must wait until the
    	 * clock structures are tagged with omap_hwmod entries
    	 */
    	if ((oh->flags & HWMOD_SET_DEFAULT_CLOCKACT) &&
    	    (sf & SYSC_HAS_CLOCKACTIVITY))
    		_set_clockactivity(oh, oh->class->sysc->clockact, &v);
    
    	_write_sysconfig(v, oh);
    
    so here, 'v' has wakeups disabled.
    
    	/* If slave is in SMARTIDLE, also enable wakeup */
    	if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
    		_enable_wakeup(oh);
    
    Here wakeup is enabled in the SYSCONFIG register (but 'v' is not updated)
    
    	/*
    	 * Set the autoidle bit only after setting the smartidle bit
    	 * Setting this will not have any impact on the other modules.
    	 */
    	if (sf & SYSC_HAS_AUTOIDLE) {
    		idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
    			0 : 1;
    		_set_module_autoidle(oh, idlemode, &v);
    		_write_sysconfig(v, oh);
    	}
    
    And here, SYSCONFIG is updated again using 'v', which does not have
    wakeups enabled, resulting in ENAWAKEUP being cleared.
    
    Special thanks to Benoit Cousson for pointing out that wakeups were
    supposed to be automatically enabled when a hwmod is enabled, and thus
    helping target the root cause of this problem.
    Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
    Cc: Benoit Cousson <b-cousson@ti.com>
    Signed-off-by: default avatarBenoit Cousson <b-cousson@ti.com>
    Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
    5a7ddcbd
omap_hwmod.c 59.2 KB