2019-05-30 02:57:47 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2008-04-19 01:43:06 +04:00
/*
* arch / arm / kernel / thumbee . c
*
* Copyright ( C ) 2008 ARM Limited
*/
# include <linux/kernel.h>
# include <linux/init.h>
2012-04-12 20:52:10 +04:00
# include <asm/cputype.h>
2012-03-28 21:30:01 +04:00
# include <asm/system_info.h>
2008-04-19 01:43:06 +04:00
# include <asm/thread_notify.h>
/*
* Access to the ThumbEE Handler Base register
*/
2008-11-10 17:14:11 +03:00
static inline unsigned long teehbr_read ( void )
2008-04-19 01:43:06 +04:00
{
unsigned long v ;
asm ( " mrc p14, 6, %0, c1, c0, 0 \n " : " =r " ( v ) ) ;
return v ;
}
static inline void teehbr_write ( unsigned long v )
{
asm ( " mcr p14, 6, %0, c1, c0, 0 \n " : : " r " ( v ) ) ;
}
static int thumbee_notifier ( struct notifier_block * self , unsigned long cmd , void * t )
{
struct thread_info * thread = t ;
switch ( cmd ) {
case THREAD_NOTIFY_FLUSH :
2014-09-11 05:49:08 +04:00
teehbr_write ( 0 ) ;
2008-04-19 01:43:06 +04:00
break ;
case THREAD_NOTIFY_SWITCH :
current_thread_info ( ) - > thumbee_state = teehbr_read ( ) ;
teehbr_write ( thread - > thumbee_state ) ;
break ;
}
return NOTIFY_DONE ;
}
static struct notifier_block thumbee_notifier_block = {
. notifier_call = thumbee_notifier ,
} ;
static int __init thumbee_init ( void )
{
unsigned long pfr0 ;
unsigned int cpu_arch = cpu_architecture ( ) ;
if ( cpu_arch < CPU_ARCH_ARMv7 )
return 0 ;
2012-04-12 20:52:10 +04:00
pfr0 = read_cpuid_ext ( CPUID_EXT_PFR0 ) ;
2008-04-19 01:43:06 +04:00
if ( ( pfr0 & 0x0000f000 ) ! = 0x00001000 )
return 0 ;
2014-10-28 14:26:42 +03:00
pr_info ( " ThumbEE CPU extension supported. \n " ) ;
2008-04-19 01:43:06 +04:00
elf_hwcap | = HWCAP_THUMBEE ;
thread_register_notifier ( & thumbee_notifier_block ) ;
return 0 ;
}
late_initcall ( thumbee_init ) ;