/** * hsi_clocks_disable_channel - virtual wrapper for disabling HSI clocks for * a given channel * @dev - reference to the hsi device. * @channel_number - channel number which requests clock to be disabled * 0xFF means no particular channel * * Note : there is no real HW clock management per HSI channel, this is only * virtual to keep track of active channels and ease debug * * Function to be called with lock */ void hsi_clocks_disable_channel(struct device *dev, u8 channel_number, const char *s) { struct platform_device *pd = to_platform_device(dev); struct hsi_dev *hsi_ctrl = platform_get_drvdata(pd); if (channel_number != HSI_CH_NUMBER_NONE) dev_dbg(dev, "CLK: hsi_clocks_disable for " "channel %d: %s\n", channel_number, s); else dev_dbg(dev, "CLK: hsi_clocks_disable: %s\n", s); if (!hsi_ctrl->clock_enabled) { dev_dbg(dev, "Clocks already disabled, skipping...\n"); return; } if (hsi_is_hsi_controller_busy(hsi_ctrl)) { dev_dbg(dev, "Cannot disable clocks, HSI port busy\n"); return; } if (hsi_is_hst_controller_busy(hsi_ctrl)) dev_warn(dev, "Disabling clocks with HST FSM not IDLE !\n"); #ifndef USE_PM_RUNTIME_FOR_HSI hsi_runtime_suspend(dev); omap_device_idle(pd); #else /* HSI_TODO : this can probably be changed * to return pm_runtime_put(dev); */ pm_runtime_put_sync(dev); #endif }
static int _od_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); int ret; /* Don't attempt late suspend on a driver that is not bound */ if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) return 0; ret = pm_generic_suspend_noirq(dev); if (!ret && !pm_runtime_status_suspended(dev)) { if (pm_generic_runtime_suspend(dev) == 0) { if (!pm_runtime_suspended(dev)) { /* NOTE: *might* indicate driver race */ dev_dbg(dev, "%s: Force suspending\n", __func__); pm_runtime_set_suspended(dev); od->flags |= OMAP_DEVICE_SUSPEND_FORCED; } omap_device_idle(pdev); od->flags |= OMAP_DEVICE_SUSPENDED; } } return ret; }
/** * omap_device_late_idle - idle devices without drivers * @dev: struct device * associated with omap_device * @data: unused * * Check the driver bound status of this device, and idle it * if there is no driver attached. */ static int __init omap_device_late_idle(struct device *dev, void *data) { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); int i; if (!od) return 0; /* * If omap_device state is enabled, but has no driver bound, * idle it. */ /* * Some devices (like memory controllers) are always kept * enabled, and should not be idled even with no drivers. */ for (i = 0; i < od->hwmods_cnt; i++) if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE) return 0; if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { if (od->_state == OMAP_DEVICE_STATE_ENABLED) { dev_warn(dev, "%s: enabled but no driver. Idling\n", __func__); omap_device_idle(pdev); } } return 0; }
static int rpres_fdif_shutdown(struct platform_device *pdev) { struct rpres_platform_data *pdata = pdev->dev.platform_data; omap_hwmod_reset(pdata->oh); return omap_device_idle(pdev); }
static int _od_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); int ret; ret = pm_generic_runtime_suspend(dev); if (ret) return ret; return omap_device_idle(pdev); }
static int rpres_iss_shutdown(struct platform_device *pdev) { int ret; struct rpres_platform_data *pdata = pdev->dev.platform_data; omap_hwmod_reset(pdata->oh); ret = omap_device_idle(pdev); if (!ret) _disable_optional_clocks(pdata->oh); return ret; }
static int sr_put(struct omap_sr *sr) { int r; if (sr->suspended) r = omap_device_idle(sr->pdev); else r = pm_runtime_put_sync_suspend(&sr->pdev->dev); if (r < 0) dev_err(&sr->pdev->dev, "%s: failed:%d susp=%d\n", __func__, r, sr->suspended); return r; }
int omap_pm_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); int r, ret = 0; dev_dbg(dev, "%s\n", __func__); ret = pm_generic_runtime_suspend(dev); if (!ret && dev->parent == &omap_device_parent) { r = omap_device_idle(pdev); WARN_ON(r); } return ret; };
int omap2430_async_suspend(struct musb *musb) { struct platform_device *pdev = to_platform_device(musb->controller->parent); unsigned long flags = 0; int ret = 0; if (!pdev) { pr_err("%s pdev is null error\n", __func__); return -ENODEV; } dev_info(&pdev->dev, "%s async_resume %d +\n", __func__, musb->async_resume); mutex_lock(&musb->async_musb_lock); do { musb->async_resume--; } while (musb->reserve_async_suspend-- > 0); musb->reserve_async_suspend = 0; if (musb->async_resume > 0) ; else if (musb->async_resume < 0) { musb->async_resume++; dev_err(&pdev->dev, "%s async_resume is fault\n", __func__); } else { spin_lock_irqsave(&musb->lock, flags); musb_async_suspend(musb); omap2430_low_level_exit(musb); otg_set_suspend(musb->xceiv, 1); spin_unlock_irqrestore(&musb->lock, flags); ret = omap_device_idle(pdev); if (ret < 0) { dev_err(&pdev->dev, "%s omap_device_idle error ret=%d\n", __func__, ret); mutex_unlock(&musb->async_musb_lock); return ret; } } mutex_unlock(&musb->async_musb_lock); dev_info(&pdev->dev, "%s async_resume %d -\n", __func__, musb->async_resume); return 0; }
static int _od_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); int ret; ret = pm_generic_suspend_noirq(dev); if (!ret && !pm_runtime_status_suspended(dev)) { if (pm_generic_runtime_suspend(dev) == 0) { if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND)) omap_device_idle(pdev); od->flags |= OMAP_DEVICE_SUSPENDED; } } return ret; }
/** * omap_hsi_prepare_idle - Prepare HSI for idle to low power * * Return value : -ENODEV if HSI controller has not been found, else 0. * */ int omap_hsi_prepare_idle(void) { struct platform_device *pdev; struct hsi_dev *hsi_ctrl; pdev = hsi_get_hsi_platform_device(); hsi_ctrl = hsi_get_hsi_controller_data(pdev); if (!hsi_ctrl) return -ENODEV; /* If hsi_clocks_disable_channel() is used, it prevents board to */ /* enter sleep, due to the checks of HSI controller status. */ /* This is why we call directly the omap_device_xxx() function here */ hsi_runtime_suspend(hsi_ctrl->dev); omap_device_idle(pdev); return 0; }
/** * hsi_clocks_disable_channel - virtual wrapper for disabling HSI clocks for * a given channel * @dev - reference to the hsi device. * @channel_number - channel number which requests clock to be disabled * 0xFF means no particular channel * * Note : there is no real HW clock management per HSI channel, this is only * virtual to keep track of active channels and ease debug * * Function to be called with lock */ void hsi_clocks_disable_channel(struct device *dev, u8 channel_number, const char *s) { struct platform_device *pd = to_platform_device(dev); struct hsi_dev *hsi_ctrl = platform_get_drvdata(pd); if (channel_number != HSI_CH_NUMBER_NONE) dev_dbg(dev, "CLK: hsi_clocks_disable for " "channel %d: %s\n", channel_number, s); else dev_dbg(dev, "CLK: hsi_clocks_disable: %s\n", s); if (!hsi_ctrl->clock_enabled) { dev_dbg(dev, "Clocks already disabled, skipping...\n"); return; } if (hsi_is_hsi_controller_busy(hsi_ctrl)) { dev_dbg(dev, "Cannot disable clocks, HSI port busy\n"); return; } if (hsi_is_hst_controller_busy(hsi_ctrl)) /* MIPI Unstable Downlink Throughput : Disable log ( dev_warn = > dev_dbg) */ #if 1 dev_dbg(dev, "Disabling clocks with HST FSM not IDLE !\n"); #endif #ifdef CONFIG_PM /* Allow Fclk to change */ if (dpll_cascading_blocker_release(dev) < 0) dev_warn(dev, "Error releasing DPLL cascading constraint\n"); #endif /* CONFIG_PM */ #ifndef USE_PM_RUNTIME_FOR_HSI hsi_runtime_suspend(dev); omap_device_idle(pd); #else /* HSI_TODO : this can probably be changed * to return pm_runtime_put(dev); */ pm_runtime_put_sync(dev); #endif }
static int _omap_device_notifier_call(struct notifier_block *nb, unsigned long event, void *dev) { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od; int err; switch (event) { case BUS_NOTIFY_REMOVED_DEVICE: if (pdev->archdata.od) omap_device_delete(pdev->archdata.od); break; case BUS_NOTIFY_UNBOUND_DRIVER: od = to_omap_device(pdev); if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) { dev_info(dev, "enabled after unload, idling\n"); err = omap_device_idle(pdev); if (err) dev_err(dev, "failed to idle\n"); } break; case BUS_NOTIFY_BIND_DRIVER: od = to_omap_device(pdev); if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && pm_runtime_status_suspended(dev)) { od->_driver_status = BUS_NOTIFY_BIND_DRIVER; pm_runtime_set_active(dev); } break; case BUS_NOTIFY_ADD_DEVICE: if (pdev->dev.of_node) omap_device_build_from_dt(pdev); omap_auxdata_legacy_init(dev); /* fall through */ default: od = to_omap_device(pdev); if (od) od->_driver_status = event; } return NOTIFY_DONE; }
static int _od_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); int ret; /* Don't attempt late suspend on a driver that is not bound */ if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) return 0; ret = pm_generic_suspend_noirq(dev); if (!ret && !pm_runtime_status_suspended(dev)) { if (pm_generic_runtime_suspend(dev) == 0) { omap_device_idle(pdev); od->flags |= OMAP_DEVICE_SUSPENDED; } } return ret; }
/** * omap_device_late_idle - idle devices without drivers * @dev: struct device * associated with omap_device * @data: unused * * Check the driver bound status of this device, and idle it * if there is no driver attached. */ static int __init omap_device_late_idle(struct device *dev, void *data) { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); if (!od) return 0; /* * If omap_device state is enabled, but has no driver bound, * idle it. */ if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { if (od->_state == OMAP_DEVICE_STATE_ENABLED) { dev_warn(dev, "%s: enabled but no driver. Idling\n", __func__); omap_device_idle(pdev); } } return 0; }
static inline int omap_rproc_stop(struct rproc *rproc) { struct device *dev = rproc->dev; struct platform_device *pdev = to_platform_device(dev); struct omap_rproc_pdata *pdata = dev->platform_data; struct omap_rproc_timers_info *timers = pdata->timers; int ret, i; #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND _destroy_pm_flags(rproc); #endif if (rproc->secure_reset) { ret = rproc_drm_invoke_service(false); if (ret) dev_err(rproc->dev, "rproc_drm_invoke_service failed " "for secure disable ret = 0x%x\n", ret); rproc->secure_reset = false; } ret = omap_device_idle(pdev); if (ret) goto err; for (i = 0; i < pdata->timers_cnt; i++) { #ifdef CONFIG_REMOTEPROC_WATCHDOG /* GPT 9 & 11 (ipu); GPT 6 (dsp) are used as watchdog timers */ if ((!strcmp(rproc->name, "dsp") && timers[i].id == 6) || (!strcmp(rproc->name, "ipu") && (timers[i].id == DUCATI_WDT_TIMER_1 || timers[i].id == DUCATI_WDT_TIMER_2))) free_irq(omap_dm_timer_get_irq(timers[i].odt), rproc); #endif omap_dm_timer_free(timers[i].odt); timers[i].odt = NULL; } err: return ret; }
static int _od_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); return omap_device_idle(pdev); }