static int __platform_pm_runtime_resume(struct platform_device *pdev) { struct device *d = &pdev->dev; struct pdev_archdata *ad = &pdev->archdata; int hwblk = ad->hwblk_id; int ret = -ENOSYS; dev_dbg(d, "__platform_pm_runtime_resume() [%d]\n", hwblk); if (d->driver) { hwblk_enable(hwblk_info, hwblk); ret = 0; if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) { if (d->driver->pm && d->driver->pm->runtime_resume) ret = d->driver->pm->runtime_resume(d); if (!ret) clear_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); else hwblk_disable(hwblk_info, hwblk); } } dev_dbg(d, "__platform_pm_runtime_resume() [%d] - returns %d\n", hwblk, ret); return ret; }
static int __platform_pm_runtime_suspend(struct platform_device *pdev) { struct device *d = &pdev->dev; struct pdev_archdata *ad = &pdev->archdata; int hwblk = ad->hwblk_id; int ret = -ENOSYS; dev_dbg(d, "__platform_pm_runtime_suspend() [%d]\n", hwblk); if (d->driver) { BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags)); ret = 0; if (d->driver->pm && d->driver->pm->runtime_suspend) { hwblk_enable(hwblk_info, hwblk); ret = d->driver->pm->runtime_suspend(d); hwblk_disable(hwblk_info, hwblk); } if (!ret) { set_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); platform_pm_runtime_not_idle(pdev); hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE); } } dev_dbg(d, "__platform_pm_runtime_suspend() [%d] - returns %d\n", hwblk, ret); return ret; }
/* allow clocks to enable and disable hardware blocks */ static int sh_hwblk_clk_enable(struct clk *clk) { if (!hwblk_info) return -ENOENT; hwblk_enable(hwblk_info, clk->arch_flags); return 0; }
static int platform_bus_notify(struct notifier_block *nb, unsigned long action, void *data) { struct device *dev = data; struct platform_device *pdev = to_platform_device(dev); int hwblk = pdev->archdata.hwblk_id; /* ignore off-chip platform devices */ if (!hwblk) return 0; switch (action) { case BUS_NOTIFY_ADD_DEVICE: INIT_LIST_HEAD(&pdev->archdata.entry); mutex_init(&pdev->archdata.mutex); /* platform devices without drivers should be disabled */ hwblk_enable(hwblk_info, hwblk); hwblk_disable(hwblk_info, hwblk); /* make sure driver re-inits itself once */ __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); break; /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */ case BUS_NOTIFY_BOUND_DRIVER: /* keep track of number of devices in use per hwblk */ hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_DEVICES); break; case BUS_NOTIFY_UNBOUND_DRIVER: /* keep track of number of devices in use per hwblk */ hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_DEVICES); /* make sure driver re-inits itself once */ __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); break; case BUS_NOTIFY_DEL_DEVICE: break; } return 0; }