2013-05-21 10:53:37 +02:00
/*
* MIPS idle loop and WAIT instruction support .
*
* Copyright ( C ) xxxx the Anonymous
* Copyright ( C ) 1994 - 2006 Ralf Baechle
* Copyright ( C ) 2003 , 2004 Maciej W . Rozycki
* Copyright ( C ) 2001 , 2004 , 2011 , 2012 MIPS Technologies , Inc .
*
* 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 .
*/
2017-08-23 11:17:47 -07:00
# include <linux/cpu.h>
2013-05-21 10:53:37 +02:00
# include <linux/export.h>
# include <linux/init.h>
# include <linux/irqflags.h>
# include <linux/printk.h>
# include <linux/sched.h>
# include <asm/cpu.h>
# include <asm/cpu-info.h>
2013-09-17 10:25:47 +02:00
# include <asm/cpu-type.h>
2013-05-21 16:59:19 +02:00
# include <asm/idle.h>
2013-05-21 10:53:37 +02:00
# include <asm/mipsregs.h>
/*
* Not all of the MIPS CPUs have the " wait " instruction available . Moreover ,
* the implementation of the " wait " feature differs between CPU families . This
* points to the function that implements CPU specific wait .
* The wait instruction stops the pipeline and reduces the power consumption of
* the CPU very much .
*/
void ( * cpu_wait ) ( void ) ;
EXPORT_SYMBOL ( cpu_wait ) ;
static void r3081_wait ( void )
{
unsigned long cfg = read_c0_conf ( ) ;
write_c0_conf ( cfg | R30XX_CONF_HALT ) ;
2013-05-21 14:05:27 +02:00
local_irq_enable ( ) ;
2013-05-21 10:53:37 +02:00
}
static void r39xx_wait ( void )
{
if ( ! need_resched ( ) )
write_c0_conf ( read_c0_conf ( ) | TX39_CONF_HALT ) ;
local_irq_enable ( ) ;
}
2013-05-21 17:33:32 +02:00
void r4k_wait ( void )
{
local_irq_enable ( ) ;
__r4k_wait ( ) ;
}
2013-05-21 10:53:37 +02:00
/*
* This variant is preferable as it allows testing need_resched and going to
* sleep depending on the outcome atomically . Unfortunately the " It is
* implementation - dependent whether the pipeline restarts when a non - enabled
* interrupt is requested " restriction in the MIPS32/MIPS64 architecture makes
* using this version a gamble .
*/
void r4k_wait_irqoff ( void )
{
if ( ! need_resched ( ) )
2013-05-21 12:58:08 +02:00
__asm__ (
" .set push \n "
2014-03-30 13:20:10 +02:00
" .set arch=r4000 \n "
2013-05-21 12:58:08 +02:00
" wait \n "
" .set pop \n " ) ;
2013-05-21 10:53:37 +02:00
local_irq_enable ( ) ;
}
/*
* The RM7000 variant has to handle erratum 38. The workaround is to not
* have any pending stores when the WAIT instruction is executed .
*/
static void rm7k_wait_irqoff ( void )
{
if ( ! need_resched ( ) )
__asm__ (
" .set push \n "
2014-03-30 13:20:10 +02:00
" .set arch=r4000 \n "
2013-05-21 10:53:37 +02:00
" .set noat \n "
" mfc0 $1, $12 \n "
" sync \n "
" mtc0 $1, $12 # stalls until W stage \n "
" wait \n "
" mtc0 $1, $12 # stalls until W stage \n "
" .set pop \n " ) ;
local_irq_enable ( ) ;
}
/*
2013-06-08 19:15:41 +00:00
* Au1 ' wait ' is only useful when the 32 kHz counter is used as timer ,
* since coreclock ( and the cp0 counter ) stops upon executing it . Only an
* interrupt can wake it , so they must be enabled before entering idle modes .
2013-05-21 10:53:37 +02:00
*/
static void au1k_wait ( void )
{
2013-06-08 19:15:41 +00:00
unsigned long c0status = read_c0_status ( ) | 1 ; /* irqs on */
2013-05-21 12:58:08 +02:00
__asm__ (
2014-03-30 13:20:10 +02:00
" .set arch=r4000 \n "
2013-05-21 12:58:08 +02:00
" cache 0x14, 0(%0) \n "
" cache 0x14, 32(%0) \n "
" sync \n "
2013-06-08 19:15:41 +00:00
" mtc0 %1, $12 \n " /* wr c0status */
2013-05-21 12:58:08 +02:00
" wait \n "
" nop \n "
" nop \n "
" nop \n "
" nop \n "
" .set mips0 \n "
2013-06-08 19:15:41 +00:00
: : " r " ( au1k_wait ) , " r " ( c0status ) ) ;
2013-05-21 10:53:37 +02:00
}
static int __initdata nowait ;
static int __init wait_disable ( char * s )
{
nowait = 1 ;
return 1 ;
}
__setup ( " nowait " , wait_disable ) ;
void __init check_wait ( void )
{
struct cpuinfo_mips * c = & current_cpu_data ;
if ( nowait ) {
printk ( " Wait instruction disabled. \n " ) ;
return ;
}
2015-09-22 11:24:20 -07:00
/*
* MIPSr6 specifies that masked interrupts should unblock an executing
* wait instruction , and thus that it is safe for us to use
* r4k_wait_irqoff . Yippee !
*/
if ( cpu_has_mips_r6 ) {
cpu_wait = r4k_wait_irqoff ;
return ;
}
2013-09-17 10:25:47 +02:00
switch ( current_cpu_type ( ) ) {
2013-05-21 10:53:37 +02:00
case CPU_R3081 :
case CPU_R3081E :
cpu_wait = r3081_wait ;
break ;
case CPU_TX3927 :
cpu_wait = r39xx_wait ;
break ;
case CPU_R4200 :
/* case CPU_R4300: */
case CPU_R4600 :
case CPU_R4640 :
case CPU_R4650 :
case CPU_R4700 :
case CPU_R5000 :
case CPU_R5500 :
case CPU_NEVADA :
case CPU_4KC :
case CPU_4KEC :
case CPU_4KSC :
case CPU_5KC :
2015-09-05 18:47:31 +02:00
case CPU_5KE :
2013-05-21 10:53:37 +02:00
case CPU_25KF :
case CPU_PR4450 :
case CPU_BMIPS3300 :
case CPU_BMIPS4350 :
case CPU_BMIPS4380 :
case CPU_CAVIUM_OCTEON :
case CPU_CAVIUM_OCTEON_PLUS :
case CPU_CAVIUM_OCTEON2 :
2013-07-29 15:07:02 -07:00
case CPU_CAVIUM_OCTEON3 :
2013-05-21 10:53:37 +02:00
case CPU_JZRISC :
case CPU_LOONGSON1 :
case CPU_XLR :
case CPU_XLP :
cpu_wait = r4k_wait ;
break ;
2016-03-03 09:45:09 +08:00
case CPU_LOONGSON3 :
if ( ( c - > processor_id & PRID_REV_MASK ) > = PRID_REV_LOONGSON3A_R2 )
cpu_wait = r4k_wait ;
break ;
2015-10-19 11:44:24 -07:00
case CPU_BMIPS5000 :
cpu_wait = r4k_wait_irqoff ;
break ;
2013-05-21 10:53:37 +02:00
case CPU_RM7000 :
cpu_wait = rm7k_wait_irqoff ;
break ;
2015-01-29 11:14:11 +00:00
case CPU_PROAPTIV :
case CPU_P5600 :
/*
* Incoming Fast Debug Channel ( FDC ) data during a wait
* instruction causes the wait never to resume , even if an
* interrupt is received . Avoid using wait at all if FDC data is
* likely to be received .
*/
if ( IS_ENABLED ( CONFIG_MIPS_EJTAG_FDC_TTY ) )
break ;
/* fall through */
2013-05-21 10:53:37 +02:00
case CPU_M14KC :
case CPU_M14KEC :
case CPU_24K :
case CPU_34K :
case CPU_1004K :
2014-01-17 15:03:50 -06:00
case CPU_1074K :
2013-11-27 10:07:53 +00:00
case CPU_INTERAPTIV :
2014-03-04 13:34:43 +00:00
case CPU_M5150 :
2014-11-24 12:59:01 +00:00
case CPU_QEMU_GENERIC :
2013-05-21 10:53:37 +02:00
cpu_wait = r4k_wait ;
if ( read_c0_config7 ( ) & MIPS_CONF7_WII )
cpu_wait = r4k_wait_irqoff ;
break ;
case CPU_74K :
cpu_wait = r4k_wait ;
if ( ( c - > processor_id & 0xff ) > = PRID_REV_ENCODE_332 ( 2 , 1 , 0 ) )
cpu_wait = r4k_wait_irqoff ;
break ;
case CPU_TX49XX :
cpu_wait = r4k_wait_irqoff ;
break ;
case CPU_ALCHEMY :
cpu_wait = au1k_wait ;
break ;
case CPU_20KC :
/*
* WAIT on Rev1 .0 has E1 , E2 , E3 and E16 .
* WAIT on Rev2 .0 and Rev3 .0 has E16 .
* Rev3 .1 WAIT is nop , why bother
*/
if ( ( c - > processor_id & 0xff ) < = 0x64 )
break ;
/*
* Another rev is incremeting c0_count at a reduced clock
* rate while in WAIT mode . So we basically have the choice
* between using the cp0 timer as clocksource or avoiding
* the WAIT instruction . Until more details are known ,
* disable the use of WAIT for 20 Kc entirely .
cpu_wait = r4k_wait ;
*/
break ;
default :
break ;
}
}
2013-05-21 12:47:26 +02:00
void arch_cpu_idle ( void )
{
2013-05-21 10:53:37 +02:00
if ( cpu_wait )
2013-05-21 13:02:12 +02:00
cpu_wait ( ) ;
2013-05-21 10:53:37 +02:00
else
local_irq_enable ( ) ;
}
2014-04-14 16:16:41 +01:00
# ifdef CONFIG_CPU_IDLE
int mips_cpuidle_wait_enter ( struct cpuidle_device * dev ,
struct cpuidle_driver * drv , int index )
{
arch_cpu_idle ( ) ;
return index ;
}
# endif