1 1.11 dyoung /* $NetBSD: au_timer.c,v 1.11 2011/07/01 18:39:29 dyoung Exp $ */ 2 1.1 simonb 3 1.1 simonb /* 4 1.1 simonb * Copyright 2002 Wasabi Systems, Inc. 5 1.1 simonb * All rights reserved. 6 1.1 simonb * 7 1.1 simonb * Written by Simon Burge for Wasabi Systems, Inc. 8 1.1 simonb * 9 1.1 simonb * Redistribution and use in source and binary forms, with or without 10 1.1 simonb * modification, are permitted provided that the following conditions 11 1.1 simonb * are met: 12 1.1 simonb * 1. Redistributions of source code must retain the above copyright 13 1.1 simonb * notice, this list of conditions and the following disclaimer. 14 1.1 simonb * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 simonb * notice, this list of conditions and the following disclaimer in the 16 1.1 simonb * documentation and/or other materials provided with the distribution. 17 1.1 simonb * 3. All advertising materials mentioning features or use of this software 18 1.1 simonb * must display the following acknowledgement: 19 1.1 simonb * This product includes software developed for the NetBSD Project by 20 1.1 simonb * Wasabi Systems, Inc. 21 1.1 simonb * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 simonb * or promote products derived from this software without specific prior 23 1.1 simonb * written permission. 24 1.1 simonb * 25 1.1 simonb * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 simonb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 simonb * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 simonb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 simonb * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 simonb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 simonb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 simonb * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 simonb * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 simonb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 simonb * POSSIBILITY OF SUCH DAMAGE. 36 1.1 simonb */ 37 1.2 lukem 38 1.2 lukem #include <sys/cdefs.h> 39 1.11 dyoung __KERNEL_RCSID(0, "$NetBSD: au_timer.c,v 1.11 2011/07/01 18:39:29 dyoung Exp $"); 40 1.1 simonb 41 1.1 simonb #include <sys/param.h> 42 1.1 simonb #include <sys/kernel.h> 43 1.6 he #include <sys/lwp.h> 44 1.4 simonb #include <sys/systm.h> 45 1.1 simonb 46 1.11 dyoung #include <sys/bus.h> 47 1.1 simonb #include <mips/locore.h> 48 1.1 simonb 49 1.1 simonb #include <mips/alchemy/include/aureg.h> 50 1.1 simonb #include <mips/alchemy/include/auvar.h> 51 1.1 simonb 52 1.1 simonb /* 53 1.1 simonb * Set a programmable clock register. 54 1.1 simonb * If "wait" is non-zero, wait for that bit to become 0 in the 55 1.1 simonb * counter control register before and after writing to the 56 1.1 simonb * specified clock register. 57 1.1 simonb */ 58 1.1 simonb #define SET_PC_REG(reg, wait, val) \ 59 1.1 simonb do { \ 60 1.1 simonb if (wait) \ 61 1.1 simonb while (bus_space_read_4(st, sh, PC_COUNTER_CONTROL) \ 62 1.1 simonb & (wait)) \ 63 1.1 simonb /* nothing */; \ 64 1.1 simonb bus_space_write_4(st, sh, (reg), (val)); \ 65 1.1 simonb if (wait) \ 66 1.1 simonb while (bus_space_read_4(st, sh, (reg)) & (wait)) \ 67 1.1 simonb /* nothing */; \ 68 1.1 simonb } while (0) 69 1.1 simonb 70 1.1 simonb void 71 1.1 simonb au_cal_timers(bus_space_tag_t st, bus_space_handle_t sh) 72 1.1 simonb { 73 1.10 matt struct cpu_info * const ci = curcpu(); 74 1.1 simonb uint32_t ctrdiff[4], startctr, endctr; 75 1.1 simonb uint32_t ctl, ctr, octr; 76 1.1 simonb int i; 77 1.1 simonb 78 1.1 simonb /* Enable the programmable counter 1. */ 79 1.1 simonb ctl = bus_space_read_4(st, sh, PC_COUNTER_CONTROL); 80 1.3 simonb if ((ctl & (CC_EO | CC_EN1)) != (CC_EO | CC_EN1)) 81 1.1 simonb SET_PC_REG(PC_COUNTER_CONTROL, 0, ctl | CC_EO | CC_EN1); 82 1.1 simonb 83 1.1 simonb /* Initialize for 16Hz. */ 84 1.1 simonb SET_PC_REG(PC_TRIM1, CC_T1S, PC_RATE / 16 - 1); 85 1.1 simonb 86 1.1 simonb /* Run the loop an extra time to prime the cache. */ 87 1.1 simonb for (i = 0; i < 4; i++) { 88 1.1 simonb /* Reset the counter. */ 89 1.1 simonb SET_PC_REG(PC_COUNTER_WRITE1, CC_C1S, 0); 90 1.1 simonb 91 1.1 simonb /* Wait for 1/16th of a second. */ 92 1.1 simonb //startctr = mips3_cp0_count_read(); 93 1.1 simonb 94 1.1 simonb /* Wait for the PC to tick over. */ 95 1.1 simonb ctr = bus_space_read_4(st, sh, PC_COUNTER_READ_1); 96 1.1 simonb do { 97 1.1 simonb octr = bus_space_read_4(st, sh, PC_COUNTER_READ_1); 98 1.1 simonb } while (ctr == octr); 99 1.1 simonb 100 1.1 simonb startctr = mips3_cp0_count_read(); 101 1.1 simonb do { 102 1.1 simonb ctr = bus_space_read_4(st, sh, PC_COUNTER_READ_1); 103 1.1 simonb } while (ctr == octr); // while (ctr <= octr + 1); 104 1.1 simonb endctr = mips3_cp0_count_read(); 105 1.1 simonb ctrdiff[i] = endctr - startctr; 106 1.1 simonb } 107 1.1 simonb 108 1.1 simonb /* Disable the counter (if it wasn't enabled already). */ 109 1.3 simonb if ((ctl & (CC_EO | CC_EN1)) != (CC_EO | CC_EN1)) 110 1.1 simonb SET_PC_REG(PC_COUNTER_CONTROL, 0, ctl); 111 1.1 simonb 112 1.1 simonb /* Compute the number of cycles per second. */ 113 1.10 matt ci->ci_cpu_freq = ((ctrdiff[2] + ctrdiff[3]) / 2) * 16; 114 1.10 matt ci->ci_cctr_freq = ci->ci_cpu_freq; 115 1.1 simonb 116 1.1 simonb /* Compute the number of ticks for hz. */ 117 1.10 matt ci->ci_cycles_per_hz = (ci->ci_cpu_freq + hz / 2) / hz; 118 1.1 simonb 119 1.1 simonb /* Compute the delay divisor. */ 120 1.10 matt ci->ci_divisor_delay = (ci->ci_cpu_freq + 500000) / 1000000; 121 1.1 simonb 122 1.1 simonb /* 123 1.1 simonb * Get correct cpu frequency if the CPU runs at twice the 124 1.1 simonb * external/cp0-count frequency. 125 1.1 simonb */ 126 1.10 matt if (mips_options.mips_cpu_flags & CPU_MIPS_DOUBLE_COUNT) 127 1.10 matt ci->ci_cpu_freq *= 2; 128 1.1 simonb 129 1.1 simonb #ifdef DEBUG 130 1.1 simonb printf("Timer calibration: %lu cycles/sec [(%u, %u) * 16]\n", 131 1.10 matt ci->ci_cpu_freq, ctrdiff[2], ctrdiff[3]); 132 1.1 simonb #endif 133 1.1 simonb } 134