2019-05-29 16:57:47 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2007-02-04 16:36:51 -06:00
/*
* Copyright ( C ) 2006 - 2007 PA Semi , Inc
*
* Maintained by : Olof Johansson < olof @ lixom . net >
*/
# undef DEBUG
# include <linux/kernel.h>
# include <linux/string.h>
2007-05-11 15:40:36 +10:00
# include <linux/irq.h>
2007-02-04 16:36:51 -06:00
# include <asm/machdep.h>
# include <asm/reg.h>
2007-05-28 10:20:45 +10:00
# include <asm/smp.h>
2007-02-04 16:36:51 -06:00
# include "pasemi.h"
struct sleep_mode {
char * name ;
void ( * entry ) ( void ) ;
} ;
static struct sleep_mode modes [ ] = {
{ . name = " spin " , . entry = & idle_spin } ,
{ . name = " doze " , . entry = & idle_doze } ,
} ;
static int current_mode = 0 ;
static int pasemi_system_reset_exception ( struct pt_regs * regs )
{
/* If we were woken up from power savings, we need to return
* to the calling function , since nip is not saved across
* all modes .
*/
if ( regs - > msr & SRR1_WAKEMASK )
regs - > nip = regs - > link ;
switch ( regs - > msr & SRR1_WAKEMASK ) {
case SRR1_WAKEDEC :
2017-03-20 16:31:48 +10:00
set_dec ( 1 ) ;
case SRR1_WAKEEE :
/*
* Handle these when interrupts get re - enabled and we take
* them as regular exceptions . We are in an NMI context
* and can ' t handle these here .
*/
2007-02-04 16:36:51 -06:00
break ;
default :
/* do system reset */
return 0 ;
}
2007-04-27 15:46:01 +10:00
/* Set higher astate since we come out of power savings at 0 */
restore_astate ( hard_smp_processor_id ( ) ) ;
2007-02-04 16:36:51 -06:00
/* everything handled */
regs - > msr | = MSR_RI ;
return 1 ;
}
2007-09-05 12:09:45 +10:00
static int __init pasemi_idle_init ( void )
2007-02-04 16:36:51 -06:00
{
2007-04-27 15:46:01 +10:00
# ifndef CONFIG_PPC_PASEMI_CPUFREQ
2018-08-03 21:15:10 +10:00
pr_warn ( " No cpufreq driver, powersavings modes disabled \n " ) ;
2007-04-27 15:46:01 +10:00
current_mode = 0 ;
# endif
2007-02-04 16:36:51 -06:00
ppc_md . system_reset_exception = pasemi_system_reset_exception ;
ppc_md . power_save = modes [ current_mode ] . entry ;
2018-08-03 21:15:10 +10:00
pr_info ( " Using PA6T idle loop (%s) \n " , modes [ current_mode ] . name ) ;
2007-09-05 12:09:45 +10:00
return 0 ;
2007-02-04 16:36:51 -06:00
}
2008-01-02 12:32:28 -07:00
machine_late_initcall ( pasemi , pasemi_idle_init ) ;
2007-02-04 16:36:51 -06:00
static int __init idle_param ( char * p )
{
int i ;
2009-07-21 17:02:31 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( modes ) ; i + + ) {
2007-02-04 16:36:51 -06:00
if ( ! strcmp ( modes [ i ] . name , p ) ) {
current_mode = i ;
break ;
}
}
return 0 ;
}
early_param ( " idle " , idle_param ) ;