Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
int platform_pm_runtime_suspend(struct device *dev)
{
    struct platform_device *pdev = to_platform_device(dev);
    struct pdev_archdata *ad = &pdev->archdata;
    unsigned long flags;
    int hwblk = ad->hwblk_id;
    int ret = 0;

    dev_dbg(dev, "platform_pm_runtime_suspend() [%d]\n", hwblk);

    /* ignore off-chip platform devices */
    if (!hwblk)
        goto out;

    /* interrupt context not allowed */
    might_sleep();

    /* catch misconfigured drivers not starting with resume */
    if (test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags)) {
        ret = -EINVAL;
        goto out;
    }

    /* serialize */
    mutex_lock(&ad->mutex);

    /* disable clock */
    hwblk_disable(hwblk_info, hwblk);

    /* put device on idle list */
    spin_lock_irqsave(&hwblk_lock, flags);
    list_add_tail(&pdev->archdata.entry, &hwblk_idle_list);
    __set_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags);
    spin_unlock_irqrestore(&hwblk_lock, flags);

    /* increase idle count */
    hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_IDLE);

    /* at this point the platform device is:
     * idle: ret = 0, FLAG_IDLE set, clock stopped
     */
    mutex_unlock(&ad->mutex);

out:
    dev_dbg(dev, "platform_pm_runtime_suspend() [%d] returns %d\n",
            hwblk, ret);

    return ret;
}
Exemple #4
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;
}
Exemple #5
0
static void sh_hwblk_clk_disable(struct clk *clk)
{
	if (hwblk_info)
		hwblk_disable(hwblk_info, clk->arch_flags);
}