Source
/*
* Copyright (C) 2014 Imagination Technologies
* Author: Paul Burton <paul.burton@mips.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.
*/
/* 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 (cpus_are_siblings(0, dev->cpu) && (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 */