aboutsummaryrefslogblamecommitdiff
path: root/sys/arm/arm/cpufunc.c
blob: 3f773a3ece72368336e6c15fcfb850fd6a065dbb (plain) (tree)
1
2
3
4
5

                                                                  
   

                                        










































                                                                             



                      

                        




                             
                   
 
                            
 
                             



                              









                                              

                                        
                              




                                                            

                             
                                           

                            
                                
  

                        

                                         
                              




                                                            
 
                             
                                   
 
                            
                                 
  
                       
 
                                              
                                         
                              

          
                                                                           

                                                   




                                                            
 
                             
                                    
 
                            
                                 
  
                                     
 





                                         
 
                                     
 
           
                        
 
                                  
                                    
                         
                    
 

                                






                                                                     
                           

                         


                                                            








                                                                              
                                                       








                                                                              




                                     


                                                                                
 

                                                              
                                                                       

                                                     
                                                                       
                 
 


                                                             
 





                                                         
                  
 
                                  

                                   

                                           
                                            
                                     

                         
                        
                                              






                                              


                              
                             
                                            
                                     
                         

                      
         
                                     
 
                        
                                              
                                              
                                                
                                           
                                     

                         
                        
 




                                                                        


                                             


  


                 
 
                          
                          
                                              









                                                              
                              
      
                        
                                                             
                         

                                                         


                                                           


                                     
      


      
                        
           
                   
 

                                      

                       
                                
 

                         








                                                                                





                                    
 
                             
 
                         
 
                  
           
                  
 

                      
                             


                        
                                              
           
                   
 

                             
 
                                      
/*	$NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $	*/

/*-
 * SPDX-License-Identifier: BSD-4-Clause
 *
 * arm9 support code Copyright (C) 2001 ARM Ltd
 * Copyright (c) 1997 Mark Brinicombe.
 * Copyright (c) 1997 Causality Limited
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Causality Limited.
 * 4. The name of Causality Limited may not be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * RiscBSD kernel project
 *
 * cpufuncs.c
 *
 * C functions for supporting CPU / MMU / TLB specific operations.
 *
 * Created      : 30/01/97
 */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/disassem.h>

#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/uma.h>

#include <machine/cpufunc.h>

/* PRIMARY CACHE VARIABLES */

int	arm_dcache_align;
int	arm_dcache_align_mask;

#ifdef CPU_MV_PJ4B
static void pj4bv7_setup(void);
#endif
#if defined(CPU_ARM1176)
static void arm11x6_setup(void);
#endif
#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
static void cortexa_setup(void);
#endif

#ifdef CPU_MV_PJ4B
struct cpu_functions pj4bv7_cpufuncs = {
	/* Cache operations */
	.cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,

	/* Other functions */
	.cf_sleep = (void *)cpufunc_nullop,

	/* Soft functions */
	.cf_setup = pj4bv7_setup
};
#endif /* CPU_MV_PJ4B */

#if defined(CPU_ARM1176)
struct cpu_functions arm1176_cpufuncs = {
	/* Cache operations */
	.cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,

	/* Other functions */
	.cf_sleep = arm11x6_sleep, 

	/* Soft functions */
	.cf_setup = arm11x6_setup
};
#endif /*CPU_ARM1176 */

#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
struct cpu_functions cortexa_cpufuncs = {
	/* Cache operations */

	/*
	 * Note: For CPUs using the PL310 the L2 ops are filled in when the
	 * L2 cache controller is actually enabled.
	 */
	.cf_l2cache_wbinv_all = cpufunc_nullop,
	.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
	.cf_l2cache_inv_range = (void *)cpufunc_nullop,
	.cf_l2cache_wb_range = (void *)cpufunc_nullop,
	.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,

	/* Other functions */
	.cf_sleep = armv7_cpu_sleep,

	/* Soft functions */
	.cf_setup = cortexa_setup
};
#endif /* CPU_CORTEXA || CPU_KRAIT */

/*
 * Global constants also used by locore.s
 */

struct cpu_functions cpufuncs;
u_int cputype;

static void get_cachetype_cp15(void);

static void
get_cachetype_cp15(void)
{
	u_int ctype, dsize, cpuid;
	u_int clevel, csize, i, sel;
	u_int multiplier;
	u_char type;

	ctype = cp15_ctr_get();
	cpuid = cp15_midr_get();
	/*
	 * ...and thus spake the ARM ARM:
	 *
	 * If an <opcode2> value corresponding to an unimplemented or
	 * reserved ID register is encountered, the System Control
	 * processor returns the value of the main ID register.
	 */
	if (ctype == cpuid)
		goto out;

	if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
		__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
		    : "=r" (clevel));
		i = 0;
		while ((type = (clevel & 0x7)) && i < 7) {
			if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
			    type == CACHE_SEP_CACHE) {
				sel = i << 1;
				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
				    : : "r" (sel));
				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
				    : "=r" (csize));
				arm_dcache_align = 1 <<
				    (CPUV7_CT_xSIZE_LEN(csize) + 4);
				arm_dcache_align_mask = arm_dcache_align - 1;
			}
			if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
				sel = (i << 1) | 1;
				__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
				    : : "r" (sel));
				__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
				    : "=r" (csize));
			}
			i++;
			clevel >>= 3;
		}
	} else {
		/*
		 * If you want to know how this code works, go read the ARM ARM.
		 */

		dsize = CPU_CT_DSIZE(ctype);
		multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
		arm_dcache_align = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
		if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
			if (dsize & CPU_CT_xSIZE_M)
				arm_dcache_align = 0; /* not present */
		}

	out:
		arm_dcache_align_mask = arm_dcache_align - 1;
	}
}

/*
 * Cannot panic here as we may not have a console yet ...
 */

int
set_cpufuncs(void)
{
	cputype = cp15_midr_get();
	cputype &= CPU_ID_CPU_MASK;

#if defined(CPU_ARM1176)
	if (cputype == CPU_ID_ARM1176JZS) {
		cpufuncs = arm1176_cpufuncs;
		get_cachetype_cp15();
		goto out;
	}
#endif /* CPU_ARM1176 */
#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
	switch(cputype & CPU_ID_SCHEME_MASK) {
	case CPU_ID_CORTEXA5:
	case CPU_ID_CORTEXA7:
	case CPU_ID_CORTEXA8:
	case CPU_ID_CORTEXA9:
	case CPU_ID_CORTEXA12:
	case CPU_ID_CORTEXA15:
	case CPU_ID_CORTEXA53:
	case CPU_ID_CORTEXA57:
	case CPU_ID_CORTEXA72:
	case CPU_ID_KRAIT300:
		cpufuncs = cortexa_cpufuncs;
		get_cachetype_cp15();
		goto out;
	default:
		break;
	}
#endif /* CPU_CORTEXA || CPU_KRAIT */

#if defined(CPU_MV_PJ4B)
	if (cputype == CPU_ID_MV88SV581X_V7 ||
	    cputype == CPU_ID_MV88SV584X_V7 ||
	    cputype == CPU_ID_ARM_88SV581X_V7) {
		cpufuncs = pj4bv7_cpufuncs;
		get_cachetype_cp15();
		goto out;
	}
#endif /* CPU_MV_PJ4B */

	/*
	 * Bzzzz. And the answer was ...
	 */
	panic("No support for this CPU type (%08x) in kernel", cputype);
	return(ARCHITECTURE_NOT_PRESENT);
out:
	uma_set_align(arm_dcache_align_mask);
	return (0);
}

/*
 * CPU Setup code
 */


#if defined(CPU_ARM1176) \
 || defined(CPU_MV_PJ4B) \
 || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
static __inline void
cpu_scc_setup_ccnt(void)
{
/* This is how you give userland access to the CCNT and PMCn
 * registers.
 * BEWARE! This gives write access also, which may not be what
 * you want!
 */
#ifdef _PMC_USER_READ_WRITE_
	/* Set PMUSERENR[0] to allow userland access */
	cp15_pmuserenr_set(1);
#endif
#if defined(CPU_ARM1176)
	/* Set PMCR[2,0] to enable counters and reset CCNT */
	cp15_pmcr_set(5);
#else
	/* Set up the PMCCNTR register as a cyclecounter:
	 * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
	 * Set PMCR[2,0] to enable counters and reset CCNT
	 * Set PMCNTENSET to 0x80000000 to enable CCNT */
	cp15_pminten_clr(0xFFFFFFFF);
	cp15_pmcr_set(5);
	cp15_pmcnten_set(0x80000000);
#endif
}
#endif

#if defined(CPU_ARM1176)
static void
arm11x6_setup(void)
{
	uint32_t auxctrl, auxctrl_wax;
	uint32_t tmp, tmp2;
	uint32_t cpuid;

	cpuid = cp15_midr_get();

	auxctrl = 0;
	auxctrl_wax = ~0;

	/*
	 * Enable an errata workaround
	 */
	if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
		auxctrl = ARM1176_AUXCTL_PHD;
		auxctrl_wax = ~ARM1176_AUXCTL_PHD;
	}

	tmp = cp15_actlr_get();
	tmp2 = tmp;
	tmp &= auxctrl_wax;
	tmp |= auxctrl;
	if (tmp != tmp2)
		cp15_actlr_set(tmp);

	cpu_scc_setup_ccnt();
}
#endif  /* CPU_ARM1176 */

#ifdef CPU_MV_PJ4B
static void
pj4bv7_setup(void)
{

	pj4b_config();
	cpu_scc_setup_ccnt();
}
#endif /* CPU_MV_PJ4B */

#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
static void
cortexa_setup(void)
{

	cpu_scc_setup_ccnt();
}
#endif  /* CPU_CORTEXA || CPU_KRAIT */