clock.c revision 198428
1285612Sdelphij/*- 2181834Sroberto * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3285612Sdelphij * Copyright (C) 1995, 1996 TooLs GmbH. 4285612Sdelphij * All rights reserved. 5285612Sdelphij * 6285612Sdelphij * Redistribution and use in source and binary forms, with or without 7285612Sdelphij * modification, are permitted provided that the following conditions 8285612Sdelphij * are met: 9285612Sdelphij * 1. Redistributions of source code must retain the above copyright 10285612Sdelphij * notice, this list of conditions and the following disclaimer. 11285612Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 12285612Sdelphij * notice, this list of conditions and the following disclaimer in the 13285612Sdelphij * documentation and/or other materials provided with the distribution. 14285612Sdelphij * 3. All advertising materials mentioning features or use of this software 15285612Sdelphij * must display the following acknowledgement: 16285612Sdelphij * This product includes software developed by TooLs GmbH. 17285612Sdelphij * 4. The name of TooLs GmbH may not be used to endorse or promote products 18285612Sdelphij * derived from this software without specific prior written permission. 19285612Sdelphij * 20285612Sdelphij * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21285612Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22285612Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23285612Sdelphij * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24285612Sdelphij * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25285612Sdelphij * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26285612Sdelphij * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27285612Sdelphij * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28285612Sdelphij * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29285612Sdelphij * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30285612Sdelphij * 31181834Sroberto * $NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $ 32285612Sdelphij */ 33181834Sroberto/* 34181834Sroberto * Copyright (C) 2001 Benno Rice. 35181834Sroberto * All rights reserved. 36181834Sroberto * 37181834Sroberto * Redistribution and use in source and binary forms, with or without 38181834Sroberto * modification, are permitted provided that the following conditions 39285612Sdelphij * are met: 40181834Sroberto * 1. Redistributions of source code must retain the above copyright 41181834Sroberto * notice, this list of conditions and the following disclaimer. 42285612Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 43181834Sroberto * notice, this list of conditions and the following disclaimer in the 44181834Sroberto * documentation and/or other materials provided with the distribution. 45285612Sdelphij * 46285612Sdelphij * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47285612Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48285612Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49285612Sdelphij * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50285612Sdelphij * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51181834Sroberto * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52181834Sroberto * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53181834Sroberto * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54285612Sdelphij * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55285612Sdelphij * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56181834Sroberto */ 57285612Sdelphij 58285612Sdelphij#include <sys/cdefs.h> 59181834Sroberto__FBSDID("$FreeBSD: head/sys/powerpc/aim/clock.c 198428 2009-10-23 21:44:46Z nwhitehorn $"); 60285612Sdelphij 61181834Sroberto#include <sys/param.h> 62285612Sdelphij#include <sys/systm.h> 63285612Sdelphij#include <sys/kernel.h> 64285612Sdelphij#include <sys/bus.h> 65181834Sroberto#include <sys/interrupt.h> 66285612Sdelphij#include <sys/pcpu.h> 67285612Sdelphij#include <sys/sysctl.h> 68285612Sdelphij#include <sys/timetc.h> 69285612Sdelphij 70285612Sdelphij#include <dev/ofw/openfirm.h> 71285612Sdelphij 72285612Sdelphij#include <machine/clock.h> 73285612Sdelphij#include <machine/cpu.h> 74285612Sdelphij#include <machine/intr.h> 75285612Sdelphij#include <machine/md_var.h> 76285612Sdelphij#include <machine/smp.h> 77285612Sdelphij 78285612Sdelphij/* 79285612Sdelphij * Initially we assume a processor with a bus frequency of 12.5 MHz. 80285612Sdelphij */ 81285612Sdelphiju_long ns_per_tick = 80; 82285612Sdelphijstatic u_long ticks_per_sec = 12500000; 83285612Sdelphijstatic long ticks_per_intr; 84285612Sdelphij 85285612Sdelphijstatic timecounter_get_t decr_get_timecount; 86285612Sdelphij 87285612Sdelphijstatic struct timecounter decr_timecounter = { 88285612Sdelphij decr_get_timecount, /* get_timecount */ 89285612Sdelphij 0, /* no poll_pps */ 90285612Sdelphij ~0u, /* counter_mask */ 91285612Sdelphij 0, /* frequency */ 92285612Sdelphij "decrementer" /* name */ 93285612Sdelphij}; 94285612Sdelphij 95285612Sdelphijvoid 96285612Sdelphijdecr_intr(struct trapframe *frame) 97285612Sdelphij{ 98285612Sdelphij int32_t tick, nticks; 99285612Sdelphij 100285612Sdelphij /* 101285612Sdelphij * Check whether we are initialized. 102285612Sdelphij */ 103285612Sdelphij if (!ticks_per_intr) 104285612Sdelphij return; 105285612Sdelphij 106285612Sdelphij /* 107285612Sdelphij * Based on the actual time delay since the last decrementer reload, 108285612Sdelphij * we arrange for earlier interrupt next time. 109285612Sdelphij */ 110285612Sdelphij __asm ("mfdec %0" : "=r"(tick)); 111285612Sdelphij for (nticks = 0; tick < 0; nticks++) 112285612Sdelphij tick += ticks_per_intr; 113285612Sdelphij mtdec(tick); 114285612Sdelphij 115285612Sdelphij while (nticks-- > 0) { 116285612Sdelphij if (PCPU_GET(cpuid) == 0) 117285612Sdelphij hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); 118285612Sdelphij else 119285612Sdelphij hardclock_cpu(TRAPF_USERMODE(frame)); 120285612Sdelphij 121285612Sdelphij statclock(TRAPF_USERMODE(frame)); 122285612Sdelphij if (profprocs != 0) 123285612Sdelphij profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); 124285612Sdelphij } 125285612Sdelphij} 126285612Sdelphij 127285612Sdelphijvoid 128285612Sdelphijdecr_init(void) 129285612Sdelphij{ 130285612Sdelphij struct cpuref cpu; 131285612Sdelphij register_t msr; 132285612Sdelphij 133285612Sdelphij /* 134285612Sdelphij * Check the BSP's timebase frequency. Sometimes we can't find the BSP, so fall 135285612Sdelphij * back to the first CPU in this case. 136285612Sdelphij */ 137285612Sdelphij 138285612Sdelphij if (platform_smp_get_bsp(&cpu) != 0) 139285612Sdelphij platform_smp_first_cpu(&cpu); 140285612Sdelphij 141285612Sdelphij ticks_per_sec = platform_timebase_freq(&cpu); 142285612Sdelphij 143285612Sdelphij msr = mfmsr(); 144285612Sdelphij mtmsr(msr & ~PSL_EE); 145285612Sdelphij 146285612Sdelphij ns_per_tick = 1000000000 / ticks_per_sec; 147285612Sdelphij ticks_per_intr = ticks_per_sec / hz; 148285612Sdelphij mtdec(ticks_per_intr); 149285612Sdelphij 150285612Sdelphij set_cputicker(mftb, ticks_per_sec, 0); 151285612Sdelphij 152285612Sdelphij mtmsr(msr); 153285612Sdelphij} 154285612Sdelphij 155285612Sdelphij#ifdef SMP 156285612Sdelphijvoid 157285612Sdelphijdecr_ap_init(void) 158285612Sdelphij{ 159285612Sdelphij 160285612Sdelphij} 161285612Sdelphij#endif 162285612Sdelphij 163285612Sdelphijvoid 164285612Sdelphijdecr_tc_init(void) 165285612Sdelphij{ 166285612Sdelphij decr_timecounter.tc_frequency = ticks_per_sec; 167285612Sdelphij tc_init(&decr_timecounter); 168285612Sdelphij} 169285612Sdelphij 170285612Sdelphijstatic unsigned 171285612Sdelphijdecr_get_timecount(struct timecounter *tc) 172285612Sdelphij{ 173285612Sdelphij register_t tb; 174181834Sroberto 175181834Sroberto __asm __volatile("mftb %0" : "=r"(tb)); 176181834Sroberto return (tb); 177181834Sroberto} 178181834Sroberto 179181834Sroberto/* 180285612Sdelphij * Wait for about n microseconds (at least!). 181285612Sdelphij */ 182285612Sdelphijvoid 183285612SdelphijDELAY(int n) 184285612Sdelphij{ 185285612Sdelphij u_quad_t tb, ttb; 186285612Sdelphij 187285612Sdelphij tb = mftb(); 188285612Sdelphij ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick; 189285612Sdelphij while (tb < ttb) 190285612Sdelphij tb = mftb(); 191285612Sdelphij} 192285612Sdelphij 193285612Sdelphij/* 194285612Sdelphij * Nothing to do. 195285612Sdelphij */ 196285612Sdelphijvoid 197285612Sdelphijcpu_startprofclock(void) 198285612Sdelphij{ 199285612Sdelphij 200285612Sdelphij /* Do nothing */ 201285612Sdelphij} 202285612Sdelphij 203285612Sdelphijvoid 204285612Sdelphijcpu_stopprofclock(void) 205285612Sdelphij{ 206285612Sdelphij} 207285612Sdelphij