/*
 * Copyright (C) 2014 Imagination Technologies
 * Author: Paul Burton <paul.burton@imgtec.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/cpu_pm.h>
#include <linux/cpuidle.h>
#include <linux/init.h>

#include <asm/idle.h>
#include <asm/pm-cps.h>

/* Enumeration of the various idle states this driver may enter */
enum cps_idle_state {
	STATE_WAIT = 0,		/* MIPS wait instruction, coherent */
	STATE_NC_WAIT,		/* MIPS wait instruction, non-coherent */
	STATE_CLOCK_GATED,	/* Core clock gated */
	STATE_POWER_GATED,	/* Core power gated */
	STATE_COUNT
};

static int cps_nc_enter(struct cpuidle_device *dev,
			struct cpuidle_driver *drv, int index)
{
	enum cps_pm_state pm_state;
	int err;

	/*
	 * At least one core must remain powered up & clocked in order for the
	 * system to have any hope of functioning.
	 *
	 * TODO: don't treat core 0 specially, just prevent the final core
	 * TODO: remap interrupt affinity temporarily
	 */
	if (!cpu_data[dev->cpu].core && (index > STATE_NC_WAIT))
		index = STATE_NC_WAIT;

	/* Select the appropriate cps_pm_state */
	switch (index) {
	case STATE_NC_WAIT:
		pm_state = CPS_PM_NC_WAIT;
		break;
	case STATE_CLOCK_GATED:
		pm_state = CPS_PM_CLOCK_GATED;
		break;
	case STATE_POWER_GATED:
		pm_state = CPS_PM_POWER_GATED;
		break;
	default:
		BUG();
		return -EINVAL;
	}

	/* Notify listeners the CPU is about to power down */
	if ((pm_state == CPS_PM_POWER_GATED) && cpu_pm_enter())
		return -EINTR;

	/* Enter that state */
	err = cps_pm_enter_state(pm_state);

	/* Notify listeners the CPU is back up */
	if (pm_state == CPS_PM_POWER_GATED)
		cpu_pm_exit();

	return err ?: index;
}

static struct cpuidle_driver cps_driver = {
	.name			= "cpc_cpuidle",
	.owner			= THIS_MODULE,
	.states = {
		[STATE_WAIT] = MIPS_CPUIDLE_WAIT_STATE,
		[STATE_NC_WAIT] = {
			.enter	= cps_nc_enter,
			.exit_latency		= 200,
			.target_residency	= 450,
			.flags	= CPUIDLE_FLAG_TIME_VALID,
			.name	= "nc-wait",
			.desc	= "non-coherent MIPS wait",
		},
		[STATE_CLOCK_GATED] = {
			.enter	= cps_nc_enter,
			.exit_latency		= 300,
			.target_residency	= 700,
			.flags	= CPUIDLE_FLAG_TIME_VALID |
				  CPUIDLE_FLAG_TIMER_STOP,
			.name	= "clock-gated",
			.desc	= "core clock gated",
		},
		[STATE_POWER_GATED] = {
			.enter	= cps_nc_enter,
			.exit_latency		= 600,
			.target_residency	= 1000,
			.flags	= CPUIDLE_FLAG_TIME_VALID |
				  CPUIDLE_FLAG_TIMER_STOP,
			.name	= "power-gated",
			.desc	= "core power gated",
		},
	},
	.state_count		= STATE_COUNT,
	.safe_state_index	= 0,
};

static void __init cps_cpuidle_unregister(void)
{
	int cpu;
	struct cpuidle_device *device;

	for_each_possible_cpu(cpu) {
		device = &per_cpu(cpuidle_dev, cpu);
		cpuidle_unregister_device(device);
	}

	cpuidle_unregister_driver(&cps_driver);
}

static int __init cps_cpuidle_init(void)
{
	int err, cpu, core, i;
	struct cpuidle_device *device;

	/* Detect supported states */
	if (!cps_pm_support_state(CPS_PM_POWER_GATED))
		cps_driver.state_count = STATE_CLOCK_GATED + 1;
	if (!cps_pm_support_state(CPS_PM_CLOCK_GATED))
		cps_driver.state_count = STATE_NC_WAIT + 1;
	if (!cps_pm_support_state(CPS_PM_NC_WAIT))
		cps_driver.state_count = STATE_WAIT + 1;

	/* Inform the user if some states are unavailable */
	if (cps_driver.state_count < STATE_COUNT) {
		pr_info("cpuidle-cps: limited to ");
		switch (cps_driver.state_count - 1) {
		case STATE_WAIT:
			pr_cont("coherent wait\n");
			break;
		case STATE_NC_WAIT:
			pr_cont("non-coherent wait\n");
			break;
		case STATE_CLOCK_GATED:
			pr_cont("clock gating\n");
			break;
		}
	}

	/*
	 * Set the coupled flag on the appropriate states if this system
	 * requires it.
	 */
	if (coupled_coherence)
		for (i = STATE_NC_WAIT; i < cps_driver.state_count; i++)
			cps_driver.states[i].flags |= CPUIDLE_FLAG_COUPLED;

	err = cpuidle_register_driver(&cps_driver);
	if (err) {
		pr_err("Failed to register CPS cpuidle driver\n");
		return err;
	}

	for_each_possible_cpu(cpu) {
		core = cpu_data[cpu].core;
		device = &per_cpu(cpuidle_dev, cpu);
		device->cpu = cpu;
#ifdef CONFIG_MIPS_MT
		cpumask_copy(&device->coupled_cpus, &cpu_sibling_map[cpu]);
#endif

		err = cpuidle_register_device(device);
		if (err) {
			pr_err("Failed to register CPU%d cpuidle device\n",
			       cpu);
			goto err_out;
		}
	}

	return 0;
err_out:
	cps_cpuidle_unregister();
	return err;
}
device_initcall(cps_cpuidle_init);
