int platform_pm_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct pdev_archdata *ad = &pdev->archdata; int hwblk = ad->hwblk_id; int ret = 0; dev_dbg(dev, "platform_pm_runtime_resume() [%d]\n", hwblk); /* ignore off-chip platform devices */ if (!hwblk) goto out; /* interrupt context not allowed */ might_sleep(); /* serialize */ mutex_lock(&ad->mutex); /* make sure device is removed from idle list */ platform_pm_runtime_not_idle(pdev); /* decrease idle count */ if (!test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags) && !test_bit(PDEV_ARCHDATA_FLAG_SUSP, &pdev->archdata.flags)) hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE); /* resume the device if needed */ ret = __platform_pm_runtime_resume(pdev); /* the driver has been initialized now, so clear the init flag */ clear_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); /* at this point the platform device may be: * resumed: ret = 0, flags = 0, clock started * failed: ret < 0, FLAG_SUSP set, clock stopped */ mutex_unlock(&ad->mutex); out: dev_dbg(dev, "platform_pm_runtime_resume() [%d] returns %d\n", hwblk, ret); return ret; }
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; }