From patchwork Fri Mar 11 14:20:12 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: manjugk manjugk X-Patchwork-Id: 628321 X-Patchwork-Delegate: khilman@deeprootsystems.com 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 p2BEMK7F030099 for ; Fri, 11 Mar 2011 14:22:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755278Ab1CKOWV (ORCPT ); Fri, 11 Mar 2011 09:22:21 -0500 Received: from devils.ext.ti.com ([198.47.26.153]:43964 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752096Ab1CKOWS (ORCPT ); Fri, 11 Mar 2011 09:22:18 -0500 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id p2BELwFM018972 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 11 Mar 2011 08:22:00 -0600 Received: from ucmsshproxy.india.ext.ti.com (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with SMTP id p2BELshf012682; Fri, 11 Mar 2011 19:51:54 +0530 (IST) Received: from localhost (unknown [10.24.244.236]) by ucmsshproxy.india.ext.ti.com (Postfix) with ESMTP id 06C42158003; Fri, 11 Mar 2011 19:51:53 +0530 (IST) From: "G, Manjunath Kondaiah" To: linux-omap@vger.kernel.org, linux-arm-kernel@lists.arm.linux.org.uk Cc: khilman@deeprootsystems.com, paul@pwsan.com, tony@atomide.com Subject: [PATCH v2 1/4] OMAP2+: PM: omap device: API's for handling mstandby mode Date: Fri, 11 Mar 2011 19:50:12 +0530 Message-Id: <1299853215-8507-2-git-send-email-manjugk@ti.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1299853215-8507-1-git-send-email-manjugk@ti.com> References: <1299853215-8507-1-git-send-email-manjugk@ti.com> 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.6 (demeter1.kernel.org [140.211.167.41]); Fri, 11 Mar 2011 14:22:22 +0000 (UTC) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e282e35..27eb845 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1537,6 +1537,48 @@ 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; + + if (!oh->class->sysc) + return -EINVAL; + + 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); + + return retval; +} + +/** * omap_hwmod_lookup - look up a registered omap_hwmod by name * @name: name of the omap_hwmod to look up * diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index e4c349f..42e0186 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -117,6 +117,8 @@ 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 1eee85a..8a37c6e 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -366,7 +366,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. XXX probably belongs outside the main hwmod file @@ -556,6 +556,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 57adb27..125cbef 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -612,6 +612,70 @@ 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(). + */ +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 *