2018-12-28 00:32:21 -08:00
// SPDX-License-Identifier: GPL-2.0
2005-04-16 15:20:36 -07:00
/*
* arch / sh / kernel / cpu / init . c
*
* CPU init code
*
2009-08-15 07:43:21 +09:00
* Copyright ( C ) 2002 - 2009 Paul Mundt
2006-09-27 14:09:26 +09:00
* Copyright ( C ) 2003 Richard Curnow
2005-04-16 15:20:36 -07:00
*/
# include <linux/init.h>
# include <linux/kernel.h>
2006-12-25 09:51:47 +09:00
# include <linux/mm.h>
2007-12-10 15:50:28 +09:00
# include <linux/log2.h>
2006-12-25 09:51:47 +09:00
# include <asm/mmu_context.h>
2005-04-16 15:20:36 -07:00
# include <asm/processor.h>
2016-12-24 11:46:01 -08:00
# include <linux/uaccess.h>
2006-09-27 18:36:17 +09:00
# include <asm/page.h>
2005-04-16 15:20:36 -07:00
# include <asm/cacheflush.h>
# include <asm/cache.h>
2007-12-10 15:50:28 +09:00
# include <asm/elf.h>
2005-04-16 15:20:36 -07:00
# include <asm/io.h>
2007-09-21 18:32:32 +09:00
# include <asm/smp.h>
2010-02-17 12:33:22 +09:00
# include <asm/sh_bios.h>
2012-03-28 18:30:03 +01:00
# include <asm/setup.h>
2005-04-16 15:20:36 -07:00
2010-01-13 12:51:40 +09:00
# ifdef CONFIG_SH_FPU
# define cpu_has_fpu 1
# else
# define cpu_has_fpu 0
# endif
# ifdef CONFIG_SH_DSP
# define cpu_has_dsp 1
# else
# define cpu_has_dsp 0
2007-11-10 20:18:18 +09:00
# endif
2005-04-16 15:20:36 -07:00
/*
* Generic wrapper for command line arguments to disable on - chip
* peripherals ( nofpu , nodsp , and so forth ) .
*/
2010-01-13 12:51:40 +09:00
# define onchip_setup(x) \
2013-06-18 17:10:12 -04:00
static int x # # _disabled = ! cpu_has_ # # x ; \
2010-01-13 12:51:40 +09:00
\
2013-06-18 17:10:12 -04:00
static int x # # _setup ( char * opts ) \
2010-01-13 12:51:40 +09:00
{ \
x # # _disabled = 1 ; \
return 1 ; \
} \
2005-04-16 15:20:36 -07:00
__setup ( " no " __stringify ( x ) , x # # _setup ) ;
onchip_setup ( fpu ) ;
onchip_setup ( dsp ) ;
2007-03-08 18:12:17 +09:00
# ifdef CONFIG_SPECULATIVE_EXECUTION
# define CPUOPM 0xff2f0000
# define CPUOPM_RABD (1 << 5)
2013-06-18 17:10:12 -04:00
static void speculative_execution_init ( void )
2007-03-08 18:12:17 +09:00
{
/* Clear RABD */
2010-01-26 12:58:40 +09:00
__raw_writel ( __raw_readl ( CPUOPM ) & ~ CPUOPM_RABD , CPUOPM ) ;
2007-03-08 18:12:17 +09:00
/* Flush the update */
2010-01-26 12:58:40 +09:00
( void ) __raw_readl ( CPUOPM ) ;
2007-03-08 18:12:17 +09:00
ctrl_barrier ( ) ;
}
# else
# define speculative_execution_init() do { } while (0)
# endif
2009-08-15 07:43:21 +09:00
# ifdef CONFIG_CPU_SH4A
# define EXPMASK 0xff2f0004
# define EXPMASK_RTEDS (1 << 0)
# define EXPMASK_BRDSSLP (1 << 1)
# define EXPMASK_MMCAW (1 << 4)
2013-06-18 17:10:12 -04:00
static void expmask_init ( void )
2009-08-15 07:43:21 +09:00
{
unsigned long expmask = __raw_readl ( EXPMASK ) ;
/*
* Future proofing .
*
2009-12-04 16:22:11 +09:00
* Disable support for slottable sleep instruction , non - nop
* instructions in the rte delay slot , and associative writes to
* the memory - mapped cache array .
2009-08-15 07:43:21 +09:00
*/
2009-12-04 16:22:11 +09:00
expmask & = ~ ( EXPMASK_RTEDS | EXPMASK_BRDSSLP | EXPMASK_MMCAW ) ;
2009-08-15 07:43:21 +09:00
__raw_writel ( expmask , EXPMASK ) ;
ctrl_barrier ( ) ;
}
# else
# define expmask_init() do { } while (0)
# endif
2009-06-02 02:49:20 +00:00
/* 2nd-level cache init */
2010-01-21 16:05:25 +09:00
void __attribute__ ( ( weak ) ) l2_cache_init ( void )
2009-06-02 02:49:20 +00:00
{
}
2005-04-16 15:20:36 -07:00
/*
* Generic first - level cache init
*/
2020-04-20 11:37:12 +02:00
# if !defined(CONFIG_CPU_J2)
2010-01-21 16:05:25 +09:00
static void cache_init ( void )
2005-04-16 15:20:36 -07:00
{
unsigned long ccr , flags ;
2007-11-30 17:06:36 +09:00
jump_to_uncached ( ) ;
2014-03-03 15:38:33 -08:00
ccr = __raw_readl ( SH_CCR ) ;
2005-04-16 15:20:36 -07:00
/*
2006-09-27 14:09:26 +09:00
* At this point we don ' t know whether the cache is enabled or not - a
* bootloader may have enabled it . There are at least 2 things that
* could be dirty in the cache at this point :
* 1. kernel command line set up by boot loader
* 2. spilled registers from the prolog of this function
* = > before re - initialising the cache , we must do a purge of the whole
* cache out to memory for safety . As long as nothing is spilled
* during the loop to lines that have already been done , this is safe .
* - RPC
2005-04-16 15:20:36 -07:00
*/
if ( ccr & CCR_CACHE_ENABLE ) {
unsigned long ways , waysize , addrstart ;
2006-12-25 10:19:56 +09:00
waysize = current_cpu_data . dcache . sets ;
2005-04-16 15:20:36 -07:00
2006-11-05 15:40:13 +09:00
# ifdef CCR_CACHE_ORA
2005-04-16 15:20:36 -07:00
/*
* If the OC is already in RAM mode , we only have
* half of the entries to flush . .
*/
if ( ccr & CCR_CACHE_ORA )
waysize > > = 1 ;
2006-11-05 15:40:13 +09:00
# endif
2005-04-16 15:20:36 -07:00
2006-12-25 10:19:56 +09:00
waysize < < = current_cpu_data . dcache . entry_shift ;
2005-04-16 15:20:36 -07:00
# ifdef CCR_CACHE_EMODE
/* If EMODE is not set, we only have 1 way to flush. */
if ( ! ( ccr & CCR_CACHE_EMODE ) )
ways = 1 ;
else
# endif
2006-12-25 10:19:56 +09:00
ways = current_cpu_data . dcache . ways ;
2005-04-16 15:20:36 -07:00
addrstart = CACHE_OC_ADDRESS_ARRAY ;
do {
unsigned long addr ;
for ( addr = addrstart ;
addr < addrstart + waysize ;
2006-12-25 10:19:56 +09:00
addr + = current_cpu_data . dcache . linesz )
2010-01-26 12:58:40 +09:00
__raw_writel ( 0 , addr ) ;
2005-04-16 15:20:36 -07:00
2006-12-25 10:19:56 +09:00
addrstart + = current_cpu_data . dcache . way_incr ;
2005-04-16 15:20:36 -07:00
} while ( - - ways ) ;
}
/*
* Default CCR values . . enable the caches
* and invalidate them immediately . .
*/
flags = CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE ;
# ifdef CCR_CACHE_EMODE
/* Force EMODE if possible */
2006-12-25 10:19:56 +09:00
if ( current_cpu_data . dcache . ways > 1 )
2005-04-16 15:20:36 -07:00
flags | = CCR_CACHE_EMODE ;
2006-09-27 14:09:26 +09:00
else
flags & = ~ CCR_CACHE_EMODE ;
2005-04-16 15:20:36 -07:00
# endif
2007-07-31 17:07:28 +09:00
# if defined(CONFIG_CACHE_WRITETHROUGH)
/* Write-through */
2005-04-16 15:20:36 -07:00
flags | = CCR_CACHE_WT ;
2007-07-31 17:07:28 +09:00
# elif defined(CONFIG_CACHE_WRITEBACK)
/* Write-back */
2005-04-16 15:20:36 -07:00
flags | = CCR_CACHE_CB ;
2007-07-31 17:07:28 +09:00
# else
/* Off */
flags & = ~ CCR_CACHE_ENABLE ;
2005-04-16 15:20:36 -07:00
# endif
2009-06-02 02:49:20 +00:00
l2_cache_init ( ) ;
2014-03-03 15:38:33 -08:00
__raw_writel ( flags , SH_CCR ) ;
2007-11-30 17:06:36 +09:00
back_to_cached ( ) ;
2005-04-16 15:20:36 -07:00
}
2007-11-10 20:25:28 +09:00
# else
# define cache_init() do { } while (0)
# endif
2005-04-16 15:20:36 -07:00
2007-12-10 15:50:28 +09:00
# define CSHAPE(totalsize, linesize, assoc) \
( ( totalsize & ~ 0xff ) | ( linesize < < 4 ) | assoc )
# define CACHE_DESC_SHAPE(desc) \
CSHAPE ( ( desc ) . way_size * ( desc ) . ways , ilog2 ( ( desc ) . linesz ) , ( desc ) . ways )
static void detect_cache_shape ( void )
{
l1d_cache_shape = CACHE_DESC_SHAPE ( current_cpu_data . dcache ) ;
if ( current_cpu_data . dcache . flags & SH_CACHE_COMBINED )
l1i_cache_shape = l1d_cache_shape ;
else
l1i_cache_shape = CACHE_DESC_SHAPE ( current_cpu_data . icache ) ;
if ( current_cpu_data . flags & CPU_HAS_L2_CACHE )
l2_cache_shape = CACHE_DESC_SHAPE ( current_cpu_data . scache ) ;
else
l2_cache_shape = - 1 ; /* No S-cache */
}
2013-06-18 17:10:12 -04:00
static void fpu_init ( void )
2010-01-13 12:51:40 +09:00
{
/* Disable the FPU */
if ( fpu_disabled & & ( current_cpu_data . flags & CPU_HAS_FPU ) ) {
printk ( " FPU Disabled \n " ) ;
current_cpu_data . flags & = ~ CPU_HAS_FPU ;
}
disable_fpu ( ) ;
clear_used_math ( ) ;
}
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_SH_DSP
2013-06-18 17:10:12 -04:00
static void release_dsp ( void )
2005-04-16 15:20:36 -07:00
{
unsigned long sr ;
/* Clear SR.DSP bit */
__asm__ __volatile__ (
" stc \t sr, %0 \n \t "
" and \t %1, %0 \n \t "
" ldc \t %0, sr \n \t "
: " =&r " ( sr )
: " r " ( ~ SR_DSP )
) ;
}
2013-06-18 17:10:12 -04:00
static void dsp_init ( void )
2005-04-16 15:20:36 -07:00
{
unsigned long sr ;
/*
* Set the SR . DSP bit , wait for one instruction , and then read
* back the SR value .
*/
__asm__ __volatile__ (
" stc \t sr, %0 \n \t "
" or \t %1, %0 \n \t "
" ldc \t %0, sr \n \t "
" nop \n \t "
" stc \t sr, %0 \n \t "
: " =&r " ( sr )
: " r " ( SR_DSP )
) ;
/* If the DSP bit is still set, this CPU has a DSP */
if ( sr & SR_DSP )
2006-12-25 10:19:56 +09:00
current_cpu_data . flags | = CPU_HAS_DSP ;
2005-04-16 15:20:36 -07:00
2010-01-13 12:51:40 +09:00
/* Disable the DSP */
if ( dsp_disabled & & ( current_cpu_data . flags & CPU_HAS_DSP ) ) {
printk ( " DSP Disabled \n " ) ;
current_cpu_data . flags & = ~ CPU_HAS_DSP ;
}
2005-04-16 15:20:36 -07:00
/* Now that we've determined the DSP status, clear the DSP bit. */
release_dsp ( ) ;
}
2010-01-13 12:51:40 +09:00
# else
2013-06-18 17:10:12 -04:00
static inline void dsp_init ( void ) { }
2005-04-16 15:20:36 -07:00
# endif /* CONFIG_SH_DSP */
/**
2010-04-21 12:20:42 +09:00
* cpu_init
2005-04-16 15:20:36 -07:00
*
2010-01-05 19:16:35 +09:00
* This is our initial entry point for each CPU , and is invoked on the
* boot CPU prior to calling start_kernel ( ) . For SMP , a combination of
* this and start_secondary ( ) will bring up each processor to a ready
* state prior to hand forking the idle loop .
2005-04-16 15:20:36 -07:00
*
2010-01-05 19:16:35 +09:00
* We do all of the basic processor init here , including setting up
* the caches , FPU , DSP , etc . By the time start_kernel ( ) is hit ( and
* subsequently platform_setup ( ) ) things like determining the CPU
* subtype and initial configuration will all be done .
2005-04-16 15:20:36 -07:00
*
* Each processor family is still responsible for doing its own probing
2010-04-21 12:01:06 +09:00
* and cache configuration in cpu_probe ( ) .
2005-04-16 15:20:36 -07:00
*/
2013-06-18 17:10:12 -04:00
asmlinkage void cpu_init ( void )
2005-04-16 15:20:36 -07:00
{
2007-09-21 18:32:32 +09:00
current_thread_info ( ) - > cpu = hard_smp_processor_id ( ) ;
2005-04-16 15:20:36 -07:00
/* First, probe the CPU */
2010-04-21 12:01:06 +09:00
cpu_probe ( ) ;
2005-04-16 15:20:36 -07:00
2007-03-12 16:15:22 +09:00
if ( current_cpu_data . type = = CPU_SH_NONE )
panic ( " Unknown CPU " ) ;
2007-11-10 20:25:28 +09:00
/* First setup the rest of the I-cache info */
current_cpu_data . icache . entry_mask = current_cpu_data . icache . way_incr -
current_cpu_data . icache . linesz ;
current_cpu_data . icache . way_size = current_cpu_data . icache . sets *
current_cpu_data . icache . linesz ;
/* And the D-cache too */
current_cpu_data . dcache . entry_mask = current_cpu_data . dcache . way_incr -
current_cpu_data . dcache . linesz ;
current_cpu_data . dcache . way_size = current_cpu_data . dcache . sets *
current_cpu_data . dcache . linesz ;
2005-04-16 15:20:36 -07:00
/* Init the cache */
cache_init ( ) ;
2007-12-10 15:50:28 +09:00
if ( raw_smp_processor_id ( ) = = 0 ) {
2016-03-22 22:02:23 +00:00
# ifdef CONFIG_MMU
2007-09-21 18:32:32 +09:00
shm_align_mask = max_t ( unsigned long ,
current_cpu_data . dcache . way_size - 1 ,
PAGE_SIZE - 1 ) ;
2016-03-22 22:02:23 +00:00
# else
shm_align_mask = PAGE_SIZE - 1 ;
# endif
2006-09-27 18:36:17 +09:00
2007-12-10 15:50:28 +09:00
/* Boot CPU sets the cache shape */
detect_cache_shape ( ) ;
}
2010-01-13 12:51:40 +09:00
fpu_init ( ) ;
dsp_init ( ) ;
2005-04-16 15:20:36 -07:00
2006-12-25 09:51:47 +09:00
/*
* Initialize the per - CPU ASID cache very early , since the
* TLB flushing routines depend on this being setup .
*/
current_cpu_data . asid_cache = NO_CONTEXT ;
2010-10-26 14:44:58 +09:00
current_cpu_data . phys_bits = __in_29bit_mode ( ) ? 29 : 32 ;
2007-03-08 18:12:17 +09:00
speculative_execution_init ( ) ;
2009-08-15 07:43:21 +09:00
expmask_init ( ) ;
2010-01-13 12:51:40 +09:00
2010-02-17 12:33:22 +09:00
/* Do the rest of the boot processor setup */
if ( raw_smp_processor_id ( ) = = 0 ) {
/* Save off the BIOS VBR, if there is one */
sh_bios_vbr_init ( ) ;
/*
* Setup VBR for boot CPU . Secondary CPUs do this through
* start_secondary ( ) .
*/
per_cpu_trap_init ( ) ;
/*
* Boot processor to setup the FP and extended state
* context info .
*/
2010-01-13 12:51:40 +09:00
init_thread_xstate ( ) ;
2010-02-17 12:33:22 +09:00
}
2005-04-16 15:20:36 -07:00
}