2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
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 .
*/
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 ) ;
2018-06-22 10:55:47 -07:00
static void __cpuidle r3081_wait ( void )
2013-05-21 10:53:37 +02:00
{
unsigned long cfg = read_c0_conf ( ) ;
write_c0_conf ( cfg | R30XX_CONF_HALT ) ;
}
2018-06-22 10:55:47 -07:00
void __cpuidle r4k_wait ( void )
2013-05-21 17:33:32 +02:00
{
2020-11-20 11:50:35 +01:00
raw_local_irq_enable ( ) ;
2013-05-21 17:33:32 +02:00
__r4k_wait ( ) ;
2023-01-12 20:43:35 +01:00
raw_local_irq_disable ( ) ;
2013-05-21 17:33:32 +02:00
}
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 .
*/
2018-06-22 10:55:47 -07:00
void __cpuidle r4k_wait_irqoff ( void )
2013-05-21 10:53:37 +02:00
{
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
}
/*
* The RM7000 variant has to handle erratum 38. The workaround is to not
* have any pending stores when the WAIT instruction is executed .
*/
2018-06-22 10:55:47 -07:00
static void __cpuidle rm7k_wait_irqoff ( void )
2013-05-21 10:53:37 +02:00
{
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 " ) ;
}
/*
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
*/
2018-06-22 10:55:47 -07:00
static void __cpuidle au1k_wait ( void )
2013-05-21 10:53:37 +02:00
{
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__ (
2018-11-08 20:14:38 +00:00
" .set push \n "
" .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 "
2018-11-08 20:14:38 +00:00
" .set pop \n "
2013-06-08 19:15:41 +00:00
: : " r " ( au1k_wait ) , " r " ( c0status ) ) ;
2023-01-12 20:43:35 +01:00
raw_local_irq_disable ( ) ;
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_R4200 :
2021-01-13 17:10:07 +02:00
/* case CPU_R4300: */
2013-05-21 10:53:37 +02:00
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 :
2019-05-08 00:43:56 +02:00
case CPU_XBURST :
2019-11-04 14:11:20 +08:00
case CPU_LOONGSON32 :
2013-05-21 10:53:37 +02:00
cpu_wait = r4k_wait ;
break ;
2019-10-20 22:43:13 +08:00
case CPU_LOONGSON64 :
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 21:50:27 +08:00
if ( ( c - > processor_id & ( PRID_IMP_MASK | PRID_REV_MASK ) ) > =
2020-04-22 22:43:44 +08:00
( PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0 ) | |
( c - > processor_id & PRID_IMP_MASK ) = = PRID_IMP_LOONGSON_64R )
2016-03-03 09:45:09 +08:00
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 ;
2020-05-04 16:51:29 +08:00
fallthrough ;
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 ;
/*
2022-04-30 21:03:10 +02:00
* Another rev is incrementing c0_count at a reduced clock
2013-05-21 10:53:37 +02:00
* 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 ;
}
}
2023-01-12 20:44:03 +01:00
__cpuidle void arch_cpu_idle ( void )
2013-05-21 12:47:26 +02:00
{
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
}
2014-04-14 16:16:41 +01:00
# ifdef CONFIG_CPU_IDLE
2023-01-12 20:44:03 +01:00
__cpuidle int mips_cpuidle_wait_enter ( struct cpuidle_device * dev ,
struct cpuidle_driver * drv , int index )
2014-04-14 16:16:41 +01:00
{
arch_cpu_idle ( ) ;
return index ;
}
# endif