예제 #1
0
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;
}
예제 #2
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;
}