/*
 * arch/sh/kernel/cpu/shmobile/pm_runtime.c
 *
 * Runtime PM support code for SuperH Mobile
 *
 *  Copyright (C) 2009 Magnus Damm
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <asm/hwblk.h>

static DEFINE_SPINLOCK(hwblk_lock);
static LIST_HEAD(hwblk_idle_list);
static struct work_struct hwblk_work;

extern struct hwblk_info *hwblk_info;

static void platform_pm_runtime_not_idle(struct platform_device *pdev)
{
	unsigned long flags;

	/* remove device from idle list */
	spin_lock_irqsave(&hwblk_lock, flags);
	if (test_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags)) {
		list_del(&pdev->archdata.entry);
		__clear_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags);
	}
	spin_unlock_irqrestore(&hwblk_lock, flags);
}

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 && d->driver->pm && d->driver->pm->runtime_resume) {
		hwblk_enable(hwblk_info, hwblk);
		ret = 0;

		if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) {
			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 && d->driver->pm && d->driver->pm->runtime_suspend) {
		BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags));

		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;
}

static void platform_pm_runtime_work(struct work_struct *work)
{
	struct platform_device *pdev;
	unsigned long flags;
	int ret;

	/* go through the idle list and suspend one device at a time */
	do {
		spin_lock_irqsave(&hwblk_lock, flags);
		if (list_empty(&hwblk_idle_list))
			pdev = NULL;
		else
			pdev = list_first_entry(&hwblk_idle_list,
						struct platform_device,
						archdata.entry);
		spin_unlock_irqrestore(&hwblk_lock, flags);

		if (pdev) {
			mutex_lock(&pdev->archdata.mutex);
			ret = __platform_pm_runtime_suspend(pdev);

			/* at this point the platform device may be:
			 * suspended: ret = 0, FLAG_SUSP set, clock stopped
			 * failed: ret < 0, FLAG_IDLE set, clock stopped
			 */
			mutex_unlock(&pdev->archdata.mutex);
		} else {
			ret = -ENODEV;
		}
	} while (!ret);
}

/* this function gets called from cpuidle context when all devices in the
 * main power domain are unused but some are counted as idle, ie the hwblk
 * counter values are (HWBLK_CNT_USAGE == 0) && (HWBLK_CNT_IDLE != 0)
 */
void platform_pm_runtime_suspend_idle(void)
{
	queue_work(pm_wq, &hwblk_work);
}

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;
}

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;
}

int platform_pm_runtime_idle(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	int hwblk = pdev->archdata.hwblk_id;
	int ret = 0;

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

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

	/* interrupt context not allowed, use pm_runtime_put()! */
	might_sleep();

	/* suspend synchronously to disable clocks immediately */
	ret = pm_runtime_suspend(dev);
out:
	dev_dbg(dev, "platform_pm_runtime_idle() [%d] done!\n", hwblk);
	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;
}

static struct notifier_block platform_bus_notifier = {
	.notifier_call = platform_bus_notify
};

static int __init sh_pm_runtime_init(void)
{
	INIT_WORK(&hwblk_work, platform_pm_runtime_work);

	bus_register_notifier(&platform_bus_type, &platform_bus_notifier);
	return 0;
}
core_initcall(sh_pm_runtime_init);
