void dsp_wdt_dpc(unsigned long data) { struct deh_mgr *deh_mgr; dev_get_deh_mgr(dev_get_first(), &deh_mgr); if (deh_mgr) bridge_deh_notify(deh_mgr, DSP_WDTOVERFLOW, 0); }
void io_dpc(unsigned long ref_data) { struct io_mgr *pio_mgr = (struct io_mgr *)ref_data; struct chnl_mgr *chnl_mgr_obj; struct msg_mgr *msg_mgr_obj; struct deh_mgr *hdeh_mgr; u32 requested; u32 serviced; if (!pio_mgr) goto func_end; chnl_mgr_obj = pio_mgr->chnl_mgr; dev_get_msg_mgr(pio_mgr->dev_obj, &msg_mgr_obj); dev_get_deh_mgr(pio_mgr->dev_obj, &hdeh_mgr); if (!chnl_mgr_obj) goto func_end; requested = pio_mgr->dpc_req; serviced = pio_mgr->dpc_sched; if (serviced == requested) goto func_end; do { if ((pio_mgr->intr_val > DEH_BASE) && (pio_mgr->intr_val < DEH_LIMIT)) { if (hdeh_mgr) { #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE print_dsp_debug_trace(pio_mgr); #endif bridge_deh_notify(hdeh_mgr, DSP_SYSERROR, pio_mgr->intr_val); } } input_chnl(pio_mgr, NULL, IO_SERVICE); output_chnl(pio_mgr, NULL, IO_SERVICE); #ifdef CHNL_MESSAGES if (msg_mgr_obj) { input_msg(pio_mgr, msg_mgr_obj); output_msg(pio_mgr, msg_mgr_obj); } #endif #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE if (pio_mgr->intr_val & MBX_DBG_SYSPRINTF) { print_dsp_debug_trace(pio_mgr); } #endif serviced++; } while (serviced != requested); pio_mgr->dpc_sched = requested; func_end: return; }
/* * ======== 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->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->dev_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->brd_state = BRD_HIBERNATION; else dev_context->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; }