Home | History | Annotate | Line # | Download | only in arm32
      1 /*	$NetBSD: arm11_pmc.c,v 1.8 2020/06/20 07:10:36 skrll Exp $	*/
      2 
      3 /* Copyright (c) 2007 Microsoft
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed by Microsoft
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 
     32 /*
     33  * support for ARM 11 Performance Monitor Counters
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: arm11_pmc.c,v 1.8 2020/06/20 07:10:36 skrll Exp $");
     38 
     39 #include <sys/param.h>
     40 #include <sys/types.h>
     41 
     42 #include <sys/kernel.h>
     43 #include <sys/systm.h>
     44 #include <sys/time.h>
     45 #include <sys/timetc.h>
     46 
     47 #include <dev/clock_subr.h>
     48 
     49 #include <arm/armreg.h>
     50 #include <arm/cpufunc.h>
     51 
     52 #ifndef ARM11_PMC_CCNT_HZ
     53 # define ARM11_PMC_CCNT_HZ	400000000	/* 400MHz */
     54 #endif
     55 
     56 void arm11_pmc_ccnt_init(void);
     57 
     58 #define COUNTS_PER_USEC	(ARM11_PMC_CCNT_HZ / 1000000)
     59 
     60 static uint32_t counts_per_wrap = ~0UL;		/* XXX off by 1 */
     61 
     62 static inline uint32_t
     63 arm11_pmc_ctrl_read(void)
     64 {
     65 	uint32_t val;
     66 
     67 	__asm volatile ("mrc p15, 0, %0, c15, c12, 0" : "=r" (val));
     68 
     69 	return val;
     70 }
     71 
     72 static inline void
     73 arm11_pmc_ctrl_write(uint32_t val)
     74 {
     75 	__asm volatile ("mcr p15, 0, %0, c15, c12, 0" :: "r" (val));
     76 }
     77 
     78 static inline uint32_t
     79 arm11_pmc_ccnt_read(void)
     80 {
     81 	uint32_t val;
     82 
     83 	__asm volatile ("mrc p15, 0, %0, c15, c12, 1" : "=r" (val));
     84 
     85 	return val;
     86 }
     87 
     88 __unused static inline void
     89 arm11_pmc_ccnt_write(uint32_t val)
     90 {
     91 	__asm volatile ("mcr p15, 0, %0, c15, c12, 1;" :: "r" (val));
     92 }
     93 
     94 /*
     95  * enable the PMC CCNT for delay()
     96  */
     97 void
     98 arm11_pmc_ccnt_init(void)
     99 {
    100 	uint32_t val;
    101 
    102 	val = ARM11_PMCCTL_E | ARM11_PMCCTL_P | ARM11_PMCCTL_C;
    103 
    104 	arm11_pmc_ctrl_write(val);
    105 }
    106 
    107 /*
    108  * delay - for "at least" arg usec
    109  *
    110  *	NOTE: at 400MHz we are restricted to (uint32_t)~0 "counts"
    111  *	if this is a problem, accumulate counts in LL vars
    112  */
    113 #define DELAY_ARG_LIMIT (((uint32_t)~0) / COUNTS_PER_USEC)	/* about 10 sec */
    114 void
    115 delay(u_int arg)
    116 {
    117 	uint32_t ctrl;
    118 	uint32_t cur;
    119 	uint32_t last;
    120 	uint32_t delta = 0;
    121 	uint32_t usecs = 0;
    122 
    123 	if (arg > DELAY_ARG_LIMIT)
    124 		panic("delay: arg %u overflow, limit is %d usec\n", arg, DELAY_ARG_LIMIT);
    125 
    126 	last = arm11_pmc_ccnt_read();
    127 	delta = usecs = 0;
    128 
    129 	while (arg > usecs) {
    130 		cur  = arm11_pmc_ccnt_read();
    131 		ctrl = arm11_pmc_ctrl_read();
    132 		if (ctrl & ARM11_PMCCTL_CCR) {
    133 			/*
    134 			 * reset CCR, do not reset other write-to-clear flags;
    135 			 * keep the rest of the PMC Control Reg configuration
    136 			 */
    137 			ctrl &= ~(ARM11_PMCCTL_CR0|ARM11_PMCCTL_CR1);
    138 			arm11_pmc_ctrl_write(ctrl);
    139 			delta += (last + (counts_per_wrap - cur));
    140 		} else {
    141 			delta += (cur - last);
    142 		}
    143 		last = cur;
    144 		if (delta >= COUNTS_PER_USEC) {
    145 			usecs += delta / COUNTS_PER_USEC;
    146 			delta %= COUNTS_PER_USEC;
    147 		}
    148 	}
    149 }
    150