From patchwork Fri Nov 19 07:21:52 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: manjugk manjugk X-Patchwork-Id: 338611 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oAJ7LThO014204 for ; Fri, 19 Nov 2010 07:21:30 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751173Ab0KSHV2 (ORCPT ); Fri, 19 Nov 2010 02:21:28 -0500 Received: from devils.ext.ti.com ([198.47.26.153]:42944 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750754Ab0KSHV2 (ORCPT ); Fri, 19 Nov 2010 02:21:28 -0500 Received: from dlep36.itg.ti.com ([157.170.170.91]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id oAJ7LP4b027225 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 19 Nov 2010 01:21:25 -0600 Received: from legion.dal.design.ti.com (localhost [127.0.0.1]) by dlep36.itg.ti.com (8.13.8/8.13.8) with ESMTP id oAJ7LO2W021137; Fri, 19 Nov 2010 01:21:24 -0600 (CST) Received: from localhost (glpp-machine.apr.dhcp.ti.com [172.24.137.105]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id oAJ7LMf03125; Fri, 19 Nov 2010 01:21:22 -0600 (CST) From: "G, Manjunath Kondaiah" To: linux-omap@vger.kernel.org Cc: "G, Manjunath Kondaiah" , Kevin Hilman , Paul Walmsley , linux-arm-kernel@lists.infradead.org Subject: [PATCH v4] OMAP2+: PM: omap device: API's for handling mstandby mode Date: Fri, 19 Nov 2010 12:51:52 +0530 Message-Id: <1290151312-347-1-git-send-email-manjugk@ti.com> X-Mailer: git-send-email 1.7.1 MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 19 Nov 2010 07:21:30 +0000 (UTC) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 5a30658..43c90ba 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1427,6 +1427,54 @@ int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode) } /** + * omap_hwmod_set_master_standbymode - set the hwmod's OCP mstandby mode + * @oh: struct omap_hwmod * + * @midlemode: flag to set mstandby to either "no standby" or "smart standby" + * + * Sets the IP block's OCP mstandby mode in hardware, and updates our + * local copy. Intended to be used by drivers that have some erratum + * that requires direct manipulation of the MIDLEMODE bits. Returns + * -EINVAL if @oh is null, or passes along the return value from + * _set_master_standbymode(). + * + * Any users of this function should be scrutinized carefully. + */ +int omap_hwmod_set_master_standbymode(struct omap_hwmod *oh, u8 idlemode) +{ + u32 v; + u8 sf; + int retval = 0; + + if (!oh) + return -EINVAL; + + v = oh->_sysc_cache; + + if (!oh->class->sysc) + return -EINVAL; + + mutex_lock(&omap_hwmod_mutex); + + v = oh->_sysc_cache; + sf = oh->class->sysc->sysc_flags; + + if (sf & SYSC_HAS_MIDLEMODE) { + if (idlemode) + idlemode = HWMOD_IDLEMODE_NO; + else + idlemode = (oh->flags & HWMOD_SWSUP_MSTANDBY) ? + HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART; + } + retval = _set_master_standbymode(oh, idlemode, &v); + if (!retval) + _write_sysconfig(v, oh); + + mutex_unlock(&omap_hwmod_mutex); + + return retval; +} + +/** * omap_hwmod_register - register a struct omap_hwmod * @oh: struct omap_hwmod * * @@ -2116,4 +2164,3 @@ int omap_hwmod_for_each_by_class(const char *classname, return ret; } - diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index 28e2d1a..14a6c46 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -109,13 +109,14 @@ int omap_device_align_pm_lat(struct platform_device *pdev, struct powerdomain *omap_device_get_pwrdm(struct omap_device *od); /* Other */ - int omap_device_idle_hwmods(struct omap_device *od); int omap_device_enable_hwmods(struct omap_device *od); int omap_device_disable_clocks(struct omap_device *od); int omap_device_enable_clocks(struct omap_device *od); +int omap_device_require_no_mstandby(struct platform_device *pdev); +int omap_device_release_no_mstandby(struct platform_device *pdev); /* * Entries should be kept in latency order ascending diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 7eaa8ed..c7ff65a 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -354,7 +354,7 @@ struct omap_hwmod_omap4_prcm { * * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out * of idle, rather than relying on module smart-idle - * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out + * HWMOD_SWSUP_MSTANDBY: omap_hwmod code should manually bring module in and out * of standby, rather than relying on module smart-standby * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for * SDRAM controller, etc. @@ -526,6 +526,8 @@ int omap_hwmod_disable_clocks(struct omap_hwmod *oh); int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode); +int omap_hwmod_set_master_standbymode(struct omap_hwmod *oh, u8 idlemode); + int omap_hwmod_reset(struct omap_hwmod *oh); void omap_hwmod_ocp_barrier(struct omap_hwmod *oh); diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index abe933c..372021b 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -584,6 +584,79 @@ int omap_device_idle(struct platform_device *pdev) } /** + * omap_device_require_no_mstandby - set no mstandby mode of an omap_device + * @od: struct omap_device * to idle + * + * Sets the IP block's OCP master standby to no mstandby mode in hardware. + * Intended to be used by drivers that have some erratum that requires direct + * manipulation of the MSTANDBYMODE bits. Returns -EINVAL if the + * omap_device is not currently enabled or passes along the return value + * of omap_hwmod_set_master_standbymode(). + * + * Intended to be used by drivers that have some erratum that requires direct + * manipulation of the MSTANDBYMODE bits. Returns -EINVAL if the + * omap_device is not currently enabled or passes along the return value + * of omap_hwmod_set_master_standbymode(). + * + * Intended to be used by drivers that have some erratum that requires direct + * manipulation of the MSTANDBYMODE bits. Returns -EINVAL if the + * omap_device is not currently enabled or passes along the return value + * of omap_hwmod_set_master_standbymode(). + */ +int omap_device_require_no_mstandby(struct platform_device *pdev) +{ + int ret = 0, i; + struct omap_device *od; + struct omap_hwmod *oh; + + od = _find_by_pdev(pdev); + if (od->_state != OMAP_DEVICE_STATE_ENABLED) { + WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n", + od->pdev.name, od->pdev.id, __func__, od->_state); + return -EINVAL; + } + + oh = *od->hwmods; + for (i = 0; i < od->hwmods_cnt; i++) + ret = omap_hwmod_set_master_standbymode(oh, true); + + return ret; +} + +/** + * omap_device_release_no_mstandby - releases no mstandby mode of an omap_device + * @od: struct omap_device * to idle + * + * Release no mstandby mode and sets the master standby to either no standby or + * smart standby in IP block's OCP in hardware depending on status of the flag + * HWMOD_SWSUP_MSTANDBY. + * + * Intended to be used by drivers that have some erratum that requires direct + * manipulation of the MSTANDBYMODE bits. Returns -EINVAL if the + * omap_device is not currently enabled or passes along the return value + * of omap_hwmod_set_master_standbymode(). + */ +int omap_device_release_no_mstandby(struct platform_device *pdev) +{ + int ret = 0, i; + struct omap_device *od; + struct omap_hwmod *oh; + + od = _find_by_pdev(pdev); + if (od->_state != OMAP_DEVICE_STATE_ENABLED) { + WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n", + od->pdev.name, od->pdev.id, __func__, od->_state); + return -EINVAL; + } + + oh = *od->hwmods; + for (i = 0; i < od->hwmods_cnt; i++) + ret = omap_hwmod_set_master_standbymode(oh, false); + + return ret; +} + +/** * omap_device_shutdown - shut down an omap_device * @od: struct omap_device * to shut down *