From patchwork Tue Oct 26 12:11:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: manjugk manjugk X-Patchwork-Id: 282212 X-Patchwork-Delegate: paul@pwsan.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 o9QCBEpL014170 for ; Tue, 26 Oct 2010 12:11:15 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932907Ab0JZMLN (ORCPT ); Tue, 26 Oct 2010 08:11:13 -0400 Received: from arroyo.ext.ti.com ([192.94.94.40]:54144 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932618Ab0JZMLM (ORCPT ); Tue, 26 Oct 2010 08:11:12 -0400 Received: from dlep33.itg.ti.com ([157.170.170.112]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id o9QCBAaa013034 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 26 Oct 2010 07:11:10 -0500 Received: from legion.dal.design.ti.com (localhost [127.0.0.1]) by dlep33.itg.ti.com (8.13.7/8.13.7) with ESMTP id o9QCB8lZ013349; Tue, 26 Oct 2010 07:11:09 -0500 (CDT) 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 o9QCB6f05751; Tue, 26 Oct 2010 07:11:06 -0500 (CDT) From: "G, Manjunath Kondaiah" To: linux-omap@vger.kernel.org Cc: Kevin Hilman , Paul Walmsley , Anand Gadiyar , Benoit Cousson Subject: [PATCH v2] OMAP2+: PM: omap_device: API for set/get MSTANDBY mode Date: Tue, 26 Oct 2010 17:41:41 +0530 Message-Id: <1288095101-1294-1-git-send-email-manjugk@ti.com> X-Mailer: git-send-email 1.7.1 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]); Tue, 26 Oct 2010 12:11:15 +0000 (UTC) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 5a30658..e3f7490 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -250,6 +250,35 @@ static int _set_master_standbymode(struct omap_hwmod *oh, u8 standbymode, } /** + * _get_master_standbymode: get the OCP_SYSCONFIG MIDLEMODE field in @midlemode + * @oh: struct omap_hwmod * + * @standbymode: pointer to get mstandby mode bits(shifted to bit 0) + * + * Get the master standby mode bits in @midlemode for the @oh hwmod. + * Does not fetch the data from the hardware instead returns value + * from sysc_cache. Returns -EINVAL upon error or 0 upon success. + */ +static int _get_master_standbymode(struct omap_hwmod *oh, u32 *midlemode) +{ + u32 mstandby_mask; + u8 mstandby_shift; + + if (!oh->class->sysc || + !(oh->class->sysc->sysc_flags & SYSC_HAS_MIDLEMODE)) + return -EINVAL; + + if (!oh->class->sysc->sysc_fields) { + WARN(1, "omap_hwmod: %s: offset struct for sysconfig not" + " provided in class\n", oh->name); + return -EINVAL; + } + + *midlemode = ((oh->_sysc_cache) & mstandby_mask) >> mstandby_shift; + + return 0; +} + +/** * _set_slave_idlemode: set the OCP_SYSCONFIG SIDLEMODE field in @v * @oh: struct omap_hwmod * * @idlemode: SIDLEMODE field bits @@ -1427,6 +1456,60 @@ int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode) } /** + * omap_hwmod_set_master_standbymode - set the hwmod's OCP master idlemode + * @oh: struct omap_hwmod * + * @midlemode: MIDLEMODE field bits (shifted to bit 0) + * + * Sets the IP block's OCP master idlemode 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, u32 midlemode) +{ + u32 v; + int retval = 0; + + if (!oh) + return -EINVAL; + + v = oh->_sysc_cache; + + retval = _set_master_standbymode(oh, midlemode, &v); + if (!retval) + _write_sysconfig(v, oh); + + return retval; +} + +/** + * omap_hwmod_get_master_idlemode - set the hwmod's OCP master idlemode + * @oh: struct omap_hwmod * + * @midlemode: pointer to get MIDLEMODE field bits (shifted to bit 0) + * + * Gets the IP block's OCP master idlemode from 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 _get_master_standbymode(). + * + * Any users of this function should be scrutinized carefully. + */ +int omap_hwmod_get_master_standbymode(struct omap_hwmod *oh, u32 *midlemode) +{ + int retval = 0; + + if (!oh) + return -EINVAL; + + retval = _get_master_standbymode(oh, midlemode); + + return retval; +} + +/** * omap_hwmod_register - register a struct omap_hwmod * @oh: struct omap_hwmod * * diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index 28e2d1a..1a4e1ee 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_mstandby(struct platform_device *pdev, u32 *midlemode, + bool set_mstandby); /* * 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..ae0ca6b 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -526,6 +526,9 @@ 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, u32 midlemode); +int omap_hwmod_get_master_standbymode(struct omap_hwmod *oh, u32 *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..cd1c92a 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -584,6 +584,42 @@ int omap_device_idle(struct platform_device *pdev) } /** + * omap_device_mstandby - set/get mstandby mode an omap_device + * @od: struct omap_device * to idle + * @midlemode: MIDLEMODE field bits (shifted to bit 0) + * @set_mstandby: flag for mstandby get/set + * + * Sets/Gets the IP block's OCP master standby 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()/omap_hwmod_get_master_standbymode(). + */ +int omap_device_mstandby(struct platform_device *pdev, u32 *midlemode, + bool set_mstandby) +{ + 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++) { + if (set_mstandby) + ret = omap_hwmod_set_master_standbymode(oh, *midlemode); + else + ret = omap_hwmod_get_master_standbymode(oh, midlemode); + } + return ret; +} + +/** * omap_device_shutdown - shut down an omap_device * @od: struct omap_device * to shut down *