summaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/tidspbridge/core/tiomap3430_pwr.c')
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430_pwr.c550
1 files changed, 550 insertions, 0 deletions
diff --git a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
new file mode 100644
index 000000000000..b57a9fd5e757
--- /dev/null
+++ b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
@@ -0,0 +1,550 @@
+/*
+ * tiomap_pwr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Implementation of DSP wake/sleep routines.
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
+
+#include <plat/dsp.h>
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/io_sm.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/brddefs.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/iodefs.h>
+
+#include <dspbridge/pwr_sh.h>
+
+/* ----------------------------------- Bridge Driver */
+#include <dspbridge/dspdeh.h>
+#include <dspbridge/wdt.h>
+
+/* ----------------------------------- specific to this file */
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include <mach-omap2/prm-regbits-34xx.h>
+#include <mach-omap2/cm-regbits-34xx.h>
+
+#define PWRSTST_TIMEOUT 200
+
+/*
+ * ======== handle_constraints_set ========
+ * Sets new DSP constraint
+ */
+int handle_constraints_set(struct bridge_dev_context *dev_context,
+ void *pargs)
+{
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
+ u32 *constraint_val;
+ struct omap_dsp_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+
+ constraint_val = (u32 *) (pargs);
+ /* Read the target value requested by DSP */
+ dev_dbg(bridge, "OPP: %s opp requested = 0x%x\n", __func__,
+ (u32) *(constraint_val + 1));
+
+ /* Set the new opp value */
+ if (pdata->dsp_set_min_opp)
+ (*pdata->dsp_set_min_opp) ((u32) *(constraint_val + 1));
+#endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
+ return 0;
+}
+
+/*
+ * ======== handle_hibernation_from_dsp ========
+ * Handle Hibernation requested from DSP
+ */
+int handle_hibernation_from_dsp(struct bridge_dev_context *dev_context)
+{
+ int status = 0;
+#ifdef CONFIG_PM
+ u16 timeout = PWRSTST_TIMEOUT / 10;
+ u32 pwr_state;
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
+ u32 opplevel;
+ struct io_mgr *hio_mgr;
+#endif
+ struct omap_dsp_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+
+ pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD, OMAP2_PM_PWSTST) &
+ OMAP_POWERSTATEST_MASK;
+ /* Wait for DSP to move into OFF state */
+ while ((pwr_state != PWRDM_POWER_OFF) && --timeout) {
+ if (msleep_interruptible(10)) {
+ pr_err("Waiting for DSP OFF mode interrupted\n");
+ return -EPERM;
+ }
+ pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
+ OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
+ }
+ if (timeout == 0) {
+ pr_err("%s: Timed out waiting for DSP off mode\n", __func__);
+ status = -ETIMEDOUT;
+ return status;
+ } else {
+
+ /* Save mailbox settings */
+ omap_mbox_save_ctx(dev_context->mbox);
+
+ /* Turn off DSP Peripheral clocks and DSP Load monitor timer */
+ status = dsp_clock_disable_all(dev_context->dsp_per_clks);
+
+ /* Disable wdt on hibernation. */
+ dsp_wdt_enable(false);
+
+ if (!status) {
+ /* Update the Bridger Driver state */
+ dev_context->dw_brd_state = BRD_DSP_HIBERNATION;
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
+ status =
+ dev_get_io_mgr(dev_context->hdev_obj, &hio_mgr);
+ if (!hio_mgr) {
+ status = DSP_EHANDLE;
+ return status;
+ }
+ io_sh_msetting(hio_mgr, SHM_GETOPP, &opplevel);
+
+ /*
+ * Set the OPP to low level before moving to OFF
+ * mode
+ */
+ if (pdata->dsp_set_min_opp)
+ (*pdata->dsp_set_min_opp) (VDD1_OPP1);
+ status = 0;
+#endif /* CONFIG_TIDSPBRIDGE_DVFS */
+ }
+ }
+#endif
+ return status;
+}
+
+/*
+ * ======== sleep_dsp ========
+ * Put DSP in low power consuming state.
+ */
+int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd,
+ void *pargs)
+{
+ int status = 0;
+#ifdef CONFIG_PM
+#ifdef CONFIG_TIDSPBRIDGE_NTFY_PWRERR
+ struct deh_mgr *hdeh_mgr;
+#endif /* CONFIG_TIDSPBRIDGE_NTFY_PWRERR */
+ u16 timeout = PWRSTST_TIMEOUT / 10;
+ u32 pwr_state, target_pwr_state;
+ struct omap_dsp_platform_data *pdata =
+ omap_dspbridge_dev->dev.platform_data;
+
+ /* Check if sleep code is valid */
+ if ((dw_cmd != PWR_DEEPSLEEP) && (dw_cmd != PWR_EMERGENCYDEEPSLEEP))
+ return -EINVAL;
+
+ switch (dev_context->dw_brd_state) {
+ case BRD_RUNNING:
+ omap_mbox_save_ctx(dev_context->mbox);
+ if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
+ sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
+ dev_dbg(bridge, "PM: %s - sent hibernate cmd to DSP\n",
+ __func__);
+ target_pwr_state = PWRDM_POWER_OFF;
+ } else {
+ sm_interrupt_dsp(dev_context, MBX_PM_DSPRETENTION);
+ target_pwr_state = PWRDM_POWER_RET;
+ }
+ break;
+ case BRD_RETENTION:
+ omap_mbox_save_ctx(dev_context->mbox);
+ if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
+ sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
+ target_pwr_state = PWRDM_POWER_OFF;
+ } else
+ return 0;
+ break;
+ case BRD_HIBERNATION:
+ case BRD_DSP_HIBERNATION:
+ /* Already in Hibernation, so just return */
+ dev_dbg(bridge, "PM: %s - DSP already in hibernation\n",
+ __func__);
+ return 0;
+ case BRD_STOPPED:
+ dev_dbg(bridge, "PM: %s - Board in STOP state\n", __func__);
+ return 0;
+ default:
+ dev_dbg(bridge, "PM: %s - Bridge in Illegal state\n", __func__);
+ return -EPERM;
+ }
+
+ /* Get the PRCM DSP power domain status */
+ pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD, OMAP2_PM_PWSTST) &
+ OMAP_POWERSTATEST_MASK;
+
+ /* Wait for DSP to move into target power state */
+ while ((pwr_state != target_pwr_state) && --timeout) {
+ if (msleep_interruptible(10)) {
+ pr_err("Waiting for DSP to Suspend interrupted\n");
+ return -EPERM;
+ }
+ pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
+ OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
+ }
+
+ if (!timeout) {
+ pr_err("%s: Timed out waiting for DSP off mode, state %x\n",
+ __func__, pwr_state);
+#ifdef CONFIG_TIDSPBRIDGE_NTFY_PWRERR
+ dev_get_deh_mgr(dev_context->hdev_obj, &hdeh_mgr);
+ bridge_deh_notify(hdeh_mgr, DSP_PWRERROR, 0);
+#endif /* CONFIG_TIDSPBRIDGE_NTFY_PWRERR */
+ return -ETIMEDOUT;
+ } else {
+ /* Update the Bridger Driver state */
+ if (dsp_test_sleepstate == PWRDM_POWER_OFF)
+ dev_context->dw_brd_state = BRD_HIBERNATION;
+ else
+ dev_context->dw_brd_state = BRD_RETENTION;
+
+ /* Disable wdt on hibernation. */
+ dsp_wdt_enable(false);
+
+ /* Turn off DSP Peripheral clocks */
+ status = dsp_clock_disable_all(dev_context->dsp_per_clks);
+ if (status)
+ return status;
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
+ else if (target_pwr_state == PWRDM_POWER_OFF) {
+ /*
+ * Set the OPP to low level before moving to OFF mode
+ */
+ if (pdata->dsp_set_min_opp)
+ (*pdata->dsp_set_min_opp) (VDD1_OPP1);
+ }
+#endif /* CONFIG_TIDSPBRIDGE_DVFS */
+ }
+#endif /* CONFIG_PM */
+ return status;
+}
+
+/*
+ * ======== wake_dsp ========
+ * Wake up DSP from sleep.
+ */
+int wake_dsp(struct bridge_dev_context *dev_context, void *pargs)
+{
+ int status = 0;
+#ifdef CONFIG_PM
+
+ /* Check the board state, if it is not 'SLEEP' then return */
+ if (dev_context->dw_brd_state == BRD_RUNNING ||
+ dev_context->dw_brd_state == BRD_STOPPED) {
+ /* The Device is in 'RET' or 'OFF' state and Bridge state is not
+ * 'SLEEP', this means state inconsistency, so return */
+ return 0;
+ }
+
+ /* Send a wakeup message to DSP */
+ sm_interrupt_dsp(dev_context, MBX_PM_DSPWAKEUP);
+
+ /* Set the device state to RUNNIG */
+ dev_context->dw_brd_state = BRD_RUNNING;
+#endif /* CONFIG_PM */
+ return status;
+}
+
+/*
+ * ======== dsp_peripheral_clk_ctrl ========
+ * Enable/Disable the DSP peripheral clocks as needed..
+ */
+int dsp_peripheral_clk_ctrl(struct bridge_dev_context *dev_context,
+ void *pargs)
+{
+ u32 ext_clk = 0;
+ u32 ext_clk_id = 0;
+ u32 ext_clk_cmd = 0;
+ u32 clk_id_index = MBX_PM_MAX_RESOURCES;
+ u32 tmp_index;
+ u32 dsp_per_clks_before;
+ int status = 0;
+
+ dsp_per_clks_before = dev_context->dsp_per_clks;
+
+ ext_clk = (u32) *((u32 *) pargs);
+ ext_clk_id = ext_clk & MBX_PM_CLK_IDMASK;
+
+ /* process the power message -- TODO, keep it in a separate function */
+ for (tmp_index = 0; tmp_index < MBX_PM_MAX_RESOURCES; tmp_index++) {
+ if (ext_clk_id == bpwr_clkid[tmp_index]) {
+ clk_id_index = tmp_index;
+ break;
+ }
+ }
+ /* TODO -- Assert may be a too hard restriction here.. May be we should
+ * just return with failure when the CLK ID does not match */
+ /* DBC_ASSERT(clk_id_index < MBX_PM_MAX_RESOURCES); */
+ if (clk_id_index == MBX_PM_MAX_RESOURCES) {
+ /* return with a more meaningfull error code */
+ return -EPERM;
+ }
+ ext_clk_cmd = (ext_clk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
+ switch (ext_clk_cmd) {
+ case BPWR_DISABLE_CLOCK:
+ status = dsp_clk_disable(bpwr_clks[clk_id_index].clk);
+ dsp_clk_wakeup_event_ctrl(bpwr_clks[clk_id_index].clk_id,
+ false);
+ if (!status) {
+ (dev_context->dsp_per_clks) &=
+ (~((u32) (1 << bpwr_clks[clk_id_index].clk)));
+ }
+ break;
+ case BPWR_ENABLE_CLOCK:
+ status = dsp_clk_enable(bpwr_clks[clk_id_index].clk);
+ dsp_clk_wakeup_event_ctrl(bpwr_clks[clk_id_index].clk_id, true);
+ if (!status)
+ (dev_context->dsp_per_clks) |=
+ (1 << bpwr_clks[clk_id_index].clk);
+ break;
+ default:
+ dev_dbg(bridge, "%s: Unsupported CMD\n", __func__);
+ /* unsupported cmd */
+ /* TODO -- provide support for AUTOIDLE Enable/Disable
+ * commands */
+ }
+ return status;
+}
+
+/*
+ * ========pre_scale_dsp========
+ * Sends prescale notification to DSP
+ *
+ */
+int pre_scale_dsp(struct bridge_dev_context *dev_context, void *pargs)
+{
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
+ u32 level;
+ u32 voltage_domain;
+
+ voltage_domain = *((u32 *) pargs);
+ level = *((u32 *) pargs + 1);
+
+ dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
+ __func__, voltage_domain, level);
+ if ((dev_context->dw_brd_state == BRD_HIBERNATION) ||
+ (dev_context->dw_brd_state == BRD_RETENTION) ||
+ (dev_context->dw_brd_state == BRD_DSP_HIBERNATION)) {
+ dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n");
+ return 0;
+ } else if ((dev_context->dw_brd_state == BRD_RUNNING)) {
+ /* Send a prenotificatio to DSP */
+ dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__);
+ sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY);
+ return 0;
+ } else {
+ return -EPERM;
+ }
+#endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
+ return 0;
+}
+
+/*
+ * ========post_scale_dsp========
+ * Sends postscale notification to DSP
+ *
+ */
+int post_scale_dsp(struct bridge_dev_context *dev_context,
+ void *pargs)
+{
+ int status = 0;
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
+ u32 level;
+ u32 voltage_domain;
+ struct io_mgr *hio_mgr;
+
+ status = dev_get_io_mgr(dev_context->hdev_obj, &hio_mgr);
+ if (!hio_mgr)
+ return -EFAULT;
+
+ voltage_domain = *((u32 *) pargs);
+ level = *((u32 *) pargs + 1);
+ dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
+ __func__, voltage_domain, level);
+ if ((dev_context->dw_brd_state == BRD_HIBERNATION) ||
+ (dev_context->dw_brd_state == BRD_RETENTION) ||
+ (dev_context->dw_brd_state == BRD_DSP_HIBERNATION)) {
+ /* Update the OPP value in shared memory */
+ io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
+ dev_dbg(bridge, "OPP: %s IVA in sleep. Wrote to shm\n",
+ __func__);
+ } else if ((dev_context->dw_brd_state == BRD_RUNNING)) {
+ /* Update the OPP value in shared memory */
+ io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
+ /* Send a post notification to DSP */
+ sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_POSTNOTIFY);
+ dev_dbg(bridge, "OPP: %s wrote to shm. Sent post notification "
+ "to DSP\n", __func__);
+ } else {
+ status = -EPERM;
+ }
+#endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
+ return status;
+}
+
+void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
+{
+ struct cfg_hostres *resources;
+ int status = 0;
+ u32 iva2_grpsel;
+ u32 mpu_grpsel;
+ struct dev_object *hdev_object = NULL;
+ struct bridge_dev_context *bridge_context = NULL;
+
+ hdev_object = (struct dev_object *)drv_get_first_dev_object();
+ if (!hdev_object)
+ return;
+
+ status = dev_get_bridge_context(hdev_object, &bridge_context);
+ if (!bridge_context)
+ return;
+
+ resources = bridge_context->resources;
+ if (!resources)
+ return;
+
+ switch (clock_id) {
+ case BPWR_GP_TIMER5:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ case BPWR_GP_TIMER6:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ case BPWR_GP_TIMER7:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ case BPWR_GP_TIMER8:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ case BPWR_MCBSP1:
+ iva2_grpsel = readl(resources->dw_core_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_core_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_core_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_core_pm_base + 0xA4);
+ break;
+ case BPWR_MCBSP2:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ case BPWR_MCBSP3:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ case BPWR_MCBSP4:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ case BPWR_MCBSP5:
+ iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
+ mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+ if (enable) {
+ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
+ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
+ } else {
+ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
+ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
+ }
+ writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
+ writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+ break;
+ }
+}