/* kick the remote processor, and let it know which virtqueue to poke at */ static void omap_rpmsg_notify(struct virtqueue *vq) { struct omap_rpmsg_vq_info *rpvq = vq->priv; int ret; int count = 15; pr_debug("sending mailbox msg: %d\n", rpvq->vq_id); do { rproc_last_busy(rpvq->rpdev->rproc); mutex_lock(&rpvq->rpdev->lock); if (rpvq->rpdev->mbox) break; mutex_unlock(&rpvq->rpdev->lock); msleep(30); pr_err("Recovering from NULL mbox handle situation...\n"); } while (--count); if (!count) { pr_err("mbox handle is NULL\n"); return; } /* send the index of the triggered virtqueue as the mailbox payload */ ret = omap_mbox_msg_send(rpvq->rpdev->mbox, rpvq->vq_id); if (ret) pr_err("ugh, omap_mbox_msg_send() failed: %d\n", ret); mutex_unlock(&rpvq->rpdev->lock); }
static int _suspend(struct omap_rproc_priv *rpp, bool force) { unsigned long timeout = msecs_to_jiffies(PM_SUSPEND_TIMEOUT) + jiffies; if (force) omap_mbox_msg_send(rpp->mbox, PM_SUSPEND_MBOX_FORCE); else omap_mbox_msg_send(rpp->mbox, PM_SUSPEND_MBOX); while (time_after(timeout, jiffies)) { if ((readl(rpp->suspend) & rpp->suspend_mask) && (readl(rpp->idle) & rpp->idle_mask)) return 0; schedule(); } return -EAGAIN; }
static int am33xx_pm_begin(suspend_state_t state) { int ret = 0; int state_id = 0; disable_hlt(); switch (state) { case PM_SUSPEND_STANDBY: state_id = 0xb; break; case PM_SUSPEND_MEM: state_id = 0x3; break; } /* * Populate the resume address as part of IPC data * The offset to be added comes from sleep33xx.S * Add 4 bytes to ensure that resume happens from * the word *after* the word which holds the resume offset */ am33xx_lp_ipc.resume_addr = (DS_RESUME_BASE + am33xx_resume_offset + 4); am33xx_lp_ipc.sleep_mode = state_id; am33xx_lp_ipc.ipc_data1 = DS_IPC_DEFAULT; am33xx_lp_ipc.ipc_data2 = DS_IPC_DEFAULT; am33xx_ipc_cmd(&am33xx_lp_ipc); m3_state = M3_STATE_MSG_FOR_LP; omap_mbox_enable_irq(m3_mbox, IRQ_RX); ret = omap_mbox_msg_send(m3_mbox, 0xABCDABCD); if (ret) { pr_err("A8<->CM3 MSG for LP failed\n"); am33xx_m3_state_machine_reset(); ret = -1; } if (!wait_for_completion_timeout(&a8_m3_sync, msecs_to_jiffies(5000))) { pr_err("A8<->CM3 sync failure\n"); am33xx_m3_state_machine_reset(); ret = -1; } else { pr_debug("Message sent for entering %s\n", (DS_MODE == DS0_ID ? "DS0" : "DS1")); omap_mbox_disable_irq(m3_mbox, IRQ_RX); } suspend_state = state; return ret; }
/* * sysfs files */ static ssize_t omap_mbox_write(struct device *dev, struct device_attribute *attr, const char * buf, size_t count) { int ret; mbox_msg_t *p = (mbox_msg_t *)buf; struct omap_mbox *mbox = dev_get_drvdata(dev); for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) { ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL); if (ret) return -EAGAIN; p++; } return (size_t)((char *)p - buf); }
int sm_interrupt_dsp(struct wmd_dev_context *dev_context, u16 mb_val) { int status = 0; if (!dev_context->mbox) return status; status = omap_mbox_msg_send(dev_context->mbox, mb_val); if (status) { pr_err("omap_mbox_msg_send Fail and status = %d\n", status); status = -EPERM; } dev_dbg(bridge, "MBX: writing %x to Mailbox\n", mb_val); return status; }
DSP_STATUS sm_interrupt_dsp(struct WMD_DEV_CONTEXT *pDevContext, u16 wMbVal) { DSP_STATUS status = DSP_SOK; if (!pDevContext->mbox) return DSP_SOK; status = omap_mbox_msg_send(pDevContext->mbox, wMbVal, (void *)pDevContext); if (status) { pr_err("omap_mbox_msg_send Fail and status = %d\n", status); status = DSP_EFAIL; } DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n", wMbVal); return status; }
static void am33xx_m3_state_machine_reset(void) { int ret = 0; am33xx_lp_ipc.resume_addr = 0x0; am33xx_lp_ipc.sleep_mode = 0xe; am33xx_lp_ipc.ipc_data1 = DS_IPC_DEFAULT; am33xx_lp_ipc.ipc_data2 = DS_IPC_DEFAULT; am33xx_ipc_cmd(&am33xx_lp_ipc); m3_state = M3_STATE_MSG_FOR_RESET; ret = omap_mbox_msg_send(m3_mbox, 0xABCDABCD); if (!ret) { pr_debug("Message sent for resetting M3 state machine\n"); if (!wait_for_completion_timeout(&a8_m3_sync, msecs_to_jiffies(5000))) pr_err("A8<->CM3 sync failure\n"); } else { pr_err("Could not reset M3 state machine!!!\n"); m3_state = M3_STATE_UNKNOWN; } }
static int am33xx_pm_begin(suspend_state_t state) { int ret = 0; disable_hlt(); am33xx_lp_ipc.resume_addr = DS_RESUME_ADDR; am33xx_lp_ipc.sleep_mode = DS_MODE; am33xx_lp_ipc.ipc_data1 = DS_IPC_DEFAULT; am33xx_lp_ipc.ipc_data2 = DS_IPC_DEFAULT; am33xx_ipc_cmd(&am33xx_lp_ipc); m3_state = M3_STATE_MSG_FOR_LP; omap_mbox_enable_irq(m3_mbox, IRQ_RX); ret = omap_mbox_msg_send(m3_mbox, 0xABCDABCD); if (ret) { pr_err("A8<->CM3 MSG for LP failed\n"); am33xx_m3_state_machine_reset(); ret = -1; } if (!wait_for_completion_timeout(&a8_m3_sync, msecs_to_jiffies(5000))) { pr_err("A8<->CM3 sync failure\n"); am33xx_m3_state_machine_reset(); ret = -1; } else { pr_debug("Message sent for entering %s\n", (DS_MODE == DS0_ID ? "DS0" : "DS1")); omap_mbox_disable_irq(m3_mbox, IRQ_RX); } suspend_state = state; return ret; }
int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val) { #ifdef CONFIG_TIDSPBRIDGE_DVFS u32 opplevel = 0; #endif struct omap_dsp_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; struct cfg_hostres *resources = dev_context->resources; int status = 0; u32 temp; if (!dev_context->mbox) return 0; if (!resources) return -EPERM; if (dev_context->brd_state == BRD_DSP_HIBERNATION || dev_context->brd_state == BRD_HIBERNATION) { #ifdef CONFIG_TIDSPBRIDGE_DVFS if (pdata->dsp_get_opp) opplevel = (*pdata->dsp_get_opp) (); if (opplevel == VDD1_OPP1) { if (pdata->dsp_set_min_opp) (*pdata->dsp_set_min_opp) (VDD1_OPP2); } #endif /* Restart the peripheral clocks */ dsp_clock_enable_all(dev_context->dsp_per_clks); dsp_wdt_enable(true); /* * 2:0 AUTO_IVA2_DPLL - Enabling IVA2 DPLL auto control * in CM_AUTOIDLE_PLL_IVA2 register */ (*pdata->dsp_cm_write)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT, OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL); /* * 7:4 IVA2_DPLL_FREQSEL - IVA2 internal frq set to * 0.75 MHz - 1.0 MHz * 2:0 EN_IVA2_DPLL - Enable IVA2 DPLL in lock mode */ (*pdata->dsp_cm_rmw_bits)(OMAP3430_IVA2_DPLL_FREQSEL_MASK | OMAP3430_EN_IVA2_DPLL_MASK, 0x3 << OMAP3430_IVA2_DPLL_FREQSEL_SHIFT | 0x7 << OMAP3430_EN_IVA2_DPLL_SHIFT, OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL); /* Restore mailbox settings */ omap_mbox_restore_ctx(dev_context->mbox); /* Access MMU SYS CONFIG register to generate a short wakeup */ temp = readl(resources->dmmu_base + 0x10); dev_context->brd_state = BRD_RUNNING; } else if (dev_context->brd_state == BRD_RETENTION) { /* Restart the peripheral clocks */ dsp_clock_enable_all(dev_context->dsp_per_clks); } status = omap_mbox_msg_send(dev_context->mbox, mb_val); if (status) { pr_err("omap_mbox_msg_send Fail and status = %d\n", status); status = -EPERM; } return 0; }
int sm_interrupt_dsp(struct wmd_dev_context *dev_context, u16 mb_val) { int status = 0; struct cfg_hostres *resources; u32 temp; struct dspbridge_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; if (!dev_context || !dev_context->resources) return -EFAULT; if (!dev_context->mbox) return status; resources = dev_context->resources; if (dev_context->dw_brd_state == BRD_DSP_HIBERNATION || dev_context->dw_brd_state == BRD_HIBERNATION) { /* Restart the peripheral clocks */ dsp_peripheral_clocks_enable(dev_context, NULL); #ifdef CONFIG_BRIDGE_WDT3 dsp_wdt_enable(true); #endif /* * 2:0 AUTO_IVA2_DPLL - Enabling IVA2 DPLL auto control * in CM_AUTOIDLE_PLL_IVA2 register */ (*pdata->dsp_cm_write)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT, OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL); /* * 7:4 IVA2_DPLL_FREQSEL - IVA2 internal frq set to * 0.75 MHz - 1.0 MHz * 2:0 EN_IVA2_DPLL - Enable IVA2 DPLL in lock mode */ (*pdata->dsp_cm_rmw_bits)(OMAP3430_IVA2_DPLL_FREQSEL_MASK | OMAP3430_EN_IVA2_DPLL_MASK, 0x3 << OMAP3430_IVA2_DPLL_FREQSEL_SHIFT | 0x7 << OMAP3430_EN_IVA2_DPLL_SHIFT, OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL); /* Restore mailbox settings */ omap_mbox_restore_ctx(dev_context->mbox); /* Access MMU SYS CONFIG register to generate a short wakeup */ temp = *(reg_uword32 *) (resources->dw_dmmu_base + 0x10); dev_context->dw_brd_state = BRD_RUNNING; } else if (dev_context->dw_brd_state == BRD_RETENTION) { /* Restart the peripheral clocks */ dsp_peripheral_clocks_enable(dev_context, NULL); dev_context->dw_brd_state = BRD_RUNNING; } status = omap_mbox_msg_send(dev_context->mbox, mb_val); if (status) { pr_err("omap_mbox_msg_send Fail and status = %d\n", status); status = -EPERM; } dev_dbg(bridge, "MBX: writing %x to Mailbox\n", mb_val); return status; }
int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val) { #ifdef CONFIG_TIDSPBRIDGE_DVFS u32 opplevel = 0; #endif struct omap_dsp_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; struct cfg_hostres *resources = dev_context->resources; int status = 0; u32 temp; if (!dev_context->mbox) return 0; if (!resources) return -EPERM; if (dev_context->brd_state == BRD_DSP_HIBERNATION || dev_context->brd_state == BRD_HIBERNATION) { #ifdef CONFIG_TIDSPBRIDGE_DVFS if (pdata->dsp_get_opp) opplevel = (*pdata->dsp_get_opp) (); if (opplevel == VDD1_OPP1) { if (pdata->dsp_set_min_opp) (*pdata->dsp_set_min_opp) (VDD1_OPP2); } #endif dsp_clock_enable_all(dev_context->dsp_per_clks); dsp_wdt_enable(true); (*pdata->dsp_cm_write)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT, OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL); (*pdata->dsp_cm_rmw_bits)(OMAP3430_IVA2_DPLL_FREQSEL_MASK | OMAP3430_EN_IVA2_DPLL_MASK, 0x3 << OMAP3430_IVA2_DPLL_FREQSEL_SHIFT | 0x7 << OMAP3430_EN_IVA2_DPLL_SHIFT, OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL); omap_mbox_restore_ctx(dev_context->mbox); temp = readl(resources->dmmu_base + 0x10); dev_context->brd_state = BRD_RUNNING; } else if (dev_context->brd_state == BRD_RETENTION) { dsp_clock_enable_all(dev_context->dsp_per_clks); } status = omap_mbox_msg_send(dev_context->mbox, mb_val); if (status) { pr_err("omap_mbox_msg_send Fail and status = %d\n", status); status = -EPERM; } return 0; }