static void _destroy_pm_flags(struct rproc *rproc) { struct omap_rproc_priv *rpp = rproc->priv; if (rpp->mbox) { omap_mbox_put(rpp->mbox, NULL); rpp->mbox = NULL; } if (rpp->idle) { iounmap(rpp->idle); rpp->idle = NULL; } if (rpp->suspend) { iounmap(rpp->suspend); rpp->suspend = NULL; } }
int omap_rproc_deactivate(struct omap_device *od) { int i, ret = 0; struct rproc *rproc = platform_get_drvdata(&od->pdev); struct device *dev = rproc->dev; struct omap_rproc_pdata *pdata = dev->platform_data; struct omap_rproc_timers_info *timers = pdata->timers; #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND struct omap_rproc_priv *rpp = rproc->priv; #endif if (pdata->clkdm) clkdm_wakeup(pdata->clkdm); for (i = 0; i < od->hwmods_cnt; i++) { ret = omap_hwmod_shutdown(od->hwmods[i]); if (ret) goto err; } for (i = 0; i < pdata->timers_cnt; i++) omap_dm_timer_stop(timers[i].odt); #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND if (rpp->iommu) { iommu_put(rpp->iommu); rpp->iommu = NULL; } if (rpp->mbox) { omap_mbox_put(rpp->mbox, NULL); rpp->mbox = NULL; } #endif err: if (pdata->clkdm) clkdm_allow_idle(pdata->clkdm); return ret; }
static int _init_pm_flags(struct rproc *rproc) { struct omap_rproc_pdata *pdata = rproc->dev->platform_data; struct omap_rproc_priv *rpp = rproc->priv; struct omap_mbox *mbox; if (!rpp->mbox) { mbox = omap_mbox_get(pdata->sus_mbox_name, NULL); if (IS_ERR(mbox)) return PTR_ERR(mbox); rpp->mbox = mbox; } if (!pdata->idle_addr) goto err_idle; rpp->idle = ioremap(pdata->idle_addr, sizeof(u32)); if (!rpp->idle) goto err_idle; if (!pdata->suspend_addr) goto err_suspend; rpp->suspend = ioremap(pdata->suspend_addr, sizeof(u32)); if (!rpp->suspend) goto err_suspend; rpp->idle_mask = pdata->idle_mask; rpp->suspend_mask = pdata->suspend_mask; return 0; err_suspend: iounmap(rpp->idle); rpp->idle = NULL; err_idle: omap_mbox_put(rpp->mbox, NULL); rpp->mbox = NULL; return -EIO; }
/* Initiliaze WKUP_M3, load the binary blob and let it run */ static int wkup_m3_init(void) { struct clk *m3_clk; struct omap_hwmod *wkup_m3_oh; const struct firmware *firmware; int ret = 0; wkup_m3_oh = omap_hwmod_lookup("wkup_m3"); if (!wkup_m3_oh) { pr_err("%s: could not find omap_hwmod\n", __func__); ret = -ENODEV; goto exit; } ipc_regs = ioremap(A8_M3_IPC_REGS, 0x4*8); if (!ipc_regs) { pr_err("Could not ioremap the IPC area\b"); ret = -ENOMEM; goto exit; } m3_eoi = ioremap(M3_TXEV_EOI, 0x4); if (!m3_eoi) { pr_err("Could not ioremap the EOI register\n"); ret = -ENOMEM; goto err1; } /* Reserve the MBOX for sending messages to M3 */ m3_mbox = omap_mbox_get("wkup_m3", &wkup_m3_mbox_notifier); if (IS_ERR(m3_mbox)) { pr_err("Could not reserve mailbox for A8->M3 IPC\n"); ret = -ENODEV; goto err2; } /* Enable access to the M3 code and data area from A8 */ m3_clk = clk_get(NULL, "wkup_m3_fck"); if (IS_ERR(m3_clk)) { pr_err("%s failed to enable WKUP_M3 clock\n", __func__); goto err3; } if (clk_enable(m3_clk)) { pr_err("%s WKUP_M3: clock enable Failed\n", __func__); goto err4; } m3_code = ioremap(M3_UMEM, SZ_16K); if (!m3_code) { pr_err("%s Could not ioremap M3 code space\n", __func__); ret = -ENOMEM; goto err5; } pr_info("Trying to load am335x-pm-firmware.bin (60 secs timeout)\n"); ret = request_firmware(&firmware, "am335x-pm-firmware.bin", mpu_dev); if (ret < 0) { dev_err(mpu_dev, "request_firmware failed\n"); goto err6; } else { memcpy(m3_code, firmware->data, firmware->size); pr_info("Copied the M3 firmware to UMEM\n"); } ret = request_irq(AM33XX_IRQ_M3_M3SP_TXEV, wkup_m3_txev_handler, IRQF_DISABLED, "wkup_m3_txev", NULL); if (ret) { pr_err("%s request_irq failed for 0x%x\n", __func__, AM33XX_IRQ_M3_M3SP_TXEV); goto err6; } m3_state = M3_STATE_RESET; ret = omap_hwmod_deassert_hardreset(wkup_m3_oh, "wkup_m3"); if (ret) { pr_err("Could not deassert the reset for WKUP_M3\n"); goto err6; } else { return 0; } err6: release_firmware(firmware); iounmap(m3_code); err5: clk_disable(m3_clk); err4: clk_put(m3_clk); err3: omap_mbox_put(m3_mbox, &wkup_m3_mbox_notifier); err2: iounmap(m3_eoi); err1: iounmap(ipc_regs); exit: return ret; }
/* * ======== bridge_brd_stop ======== * purpose: * Puts DSP in self loop. * * Preconditions : * a) None */ static int bridge_brd_stop(struct bridge_dev_context *dev_ctxt) { int status = 0; struct bridge_dev_context *dev_context = dev_ctxt; u32 dsp_pwr_state; int i; struct bridge_ioctl_extproc *tlb = dev_context->atlb_entry; struct omap_dsp_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; if (dev_context->dw_brd_state == BRD_STOPPED) return status; /* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode, * before turning off the clocks.. This is to ensure that there are no * pending L3 or other transactons from IVA2 */ dsp_pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD, OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK; if (dsp_pwr_state != PWRDM_POWER_OFF) { (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST2_IVA2_MASK, 0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); sm_interrupt_dsp(dev_context, MBX_PM_DSPIDLE); mdelay(10); /* IVA2 is not in OFF state */ /* Set PM_PWSTCTRL_IVA2 to OFF */ (*pdata->dsp_prm_rmw_bits)(OMAP_POWERSTATEST_MASK, PWRDM_POWER_OFF, OMAP3430_IVA2_MOD, OMAP2_PM_PWSTCTRL); /* Set the SW supervised state transition for Sleep */ (*pdata->dsp_cm_write)(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL); } udelay(10); /* Release the Ext Base virtual Address as the next DSP Program * may have a different load address */ if (dev_context->dw_dsp_ext_base_addr) dev_context->dw_dsp_ext_base_addr = 0; dev_context->dw_brd_state = BRD_STOPPED; /* update board state */ dsp_wdt_enable(false); /* Reset DSP */ (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); /* Disable the mailbox interrupts */ if (dev_context->mbox) { omap_mbox_disable_irq(dev_context->mbox, IRQ_RX); omap_mbox_put(dev_context->mbox); dev_context->mbox = NULL; } if (dev_context->dsp_mmu) { pr_err("Proc stop mmu if statement\n"); for (i = 0; i < BRDIOCTL_NUMOFMMUTLB; i++) { if (!tlb[i].ul_gpp_pa) continue; iommu_kunmap(dev_context->dsp_mmu, tlb[i].ul_gpp_va); } i = 0; while (l4_peripheral_table[i].phys_addr) { iommu_kunmap(dev_context->dsp_mmu, l4_peripheral_table[i].dsp_virt_addr); i++; } iommu_kunmap(dev_context->dsp_mmu, dev_context->sh_s.seg0_da); iommu_kunmap(dev_context->dsp_mmu, dev_context->sh_s.seg1_da); dsp_mmu_exit(dev_context->dsp_mmu); dev_context->dsp_mmu = NULL; } /* Reset IVA IOMMU*/ (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST2_IVA2_MASK, OMAP3430_RST2_IVA2_MASK, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); dsp_clock_disable_all(dev_context->dsp_per_clks); dsp_clk_disable(DSP_CLK_IVA2); return status; }