The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/powerpc/clock.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-4-Clause AND BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
    5  * Copyright (C) 1995, 1996 TooLs GmbH.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by TooLs GmbH.
   19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  *
   33  *      $NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $
   34  */
   35 /*
   36  * Copyright (C) 2001 Benno Rice.
   37  * All rights reserved.
   38  *
   39  * Redistribution and use in source and binary forms, with or without
   40  * modification, are permitted provided that the following conditions
   41  * are met:
   42  * 1. Redistributions of source code must retain the above copyright
   43  *    notice, this list of conditions and the following disclaimer.
   44  * 2. Redistributions in binary form must reproduce the above copyright
   45  *    notice, this list of conditions and the following disclaimer in the
   46  *    documentation and/or other materials provided with the distribution.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   50  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   51  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   52  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   53  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   54  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   55  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   56  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   57  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   58  */
   59 
   60 #include <sys/cdefs.h>
   61 __FBSDID("$FreeBSD$");
   62 
   63 #include <sys/param.h>
   64 #include <sys/systm.h>
   65 #include <sys/kernel.h>
   66 #include <sys/bus.h>
   67 #include <sys/interrupt.h>
   68 #include <sys/pcpu.h>
   69 #include <sys/sysctl.h>
   70 #include <sys/timeet.h>
   71 #include <sys/timetc.h>
   72 
   73 #include <dev/ofw/openfirm.h>
   74 
   75 #include <machine/clock.h>
   76 #include <machine/cpu.h>
   77 #include <machine/intr_machdep.h>
   78 #include <machine/md_var.h>
   79 #include <machine/smp.h>
   80 
   81 /*
   82  * Initially we assume a processor with a bus frequency of 12.5 MHz.
   83  */
   84 static int              initialized = 0;
   85 static uint64_t         ps_per_tick = 80000;
   86 static u_long           ticks_per_sec = 12500000;
   87 static u_long           *decr_counts[MAXCPU];
   88 
   89 static int              decr_et_start(struct eventtimer *et,
   90     sbintime_t first, sbintime_t period);
   91 static int              decr_et_stop(struct eventtimer *et);
   92 static timecounter_get_t        decr_get_timecount;
   93 
   94 struct decr_state {
   95         int     mode;   /* 0 - off, 1 - periodic, 2 - one-shot. */
   96         int32_t div;    /* Periodic divisor. */
   97 };
   98 DPCPU_DEFINE_STATIC(struct decr_state, decr_state);
   99 
  100 static struct eventtimer        decr_et;
  101 static struct timecounter       decr_tc = {
  102         decr_get_timecount,     /* get_timecount */
  103         0,                      /* no poll_pps */
  104         ~0u,                    /* counter_mask */
  105         0,                      /* frequency */
  106         "timebase"              /* name */
  107 };
  108 
  109 /*
  110  * Decrementer interrupt handler.
  111  */
  112 void
  113 decr_intr(struct trapframe *frame)
  114 {
  115         struct decr_state *s = DPCPU_PTR(decr_state);
  116         int             nticks = 0;
  117         int32_t         val;
  118 
  119         if (!initialized)
  120                 return;
  121 
  122         (*decr_counts[curcpu])++;
  123 
  124 #ifdef BOOKE
  125         /*
  126          * Interrupt handler must reset DIS to avoid getting another
  127          * interrupt once EE is enabled.
  128          */
  129         mtspr(SPR_TSR, TSR_DIS);
  130 #endif
  131 
  132         if (s->mode == 1) {
  133                 /*
  134                  * Based on the actual time delay since the last decrementer
  135                  * reload, we arrange for earlier interrupt next time.
  136                  */
  137                 __asm ("mfdec %0" : "=r"(val));
  138                 while (val < 0) {
  139                         val += s->div;
  140                         nticks++;
  141                 }
  142                 mtdec(val);
  143         } else if (s->mode == 2) {
  144                 nticks = 1;
  145                 decr_et_stop(NULL);
  146         } else if (s->mode == 0) {
  147                 /* Potemkin timer ran out without an event. Just reset it. */
  148                 decr_et_stop(NULL);
  149         }
  150 
  151         while (nticks-- > 0) {
  152                 if (decr_et.et_active)
  153                         decr_et.et_event_cb(&decr_et, decr_et.et_arg);
  154         }
  155 }
  156 
  157 void
  158 cpu_initclocks(void)
  159 {
  160 
  161         decr_tc_init();
  162         cpu_initclocks_bsp();
  163 }
  164 
  165 /*
  166  * BSP early initialization.
  167  */
  168 void
  169 decr_init(void)
  170 {
  171         struct cpuref cpu;
  172         char buf[32];
  173 
  174         /*
  175          * Check the BSP's timebase frequency. Sometimes we can't find the BSP,
  176          * so fall back to the first CPU in this case.
  177          */
  178         if (platform_smp_get_bsp(&cpu) != 0)
  179                 platform_smp_first_cpu(&cpu);
  180         ticks_per_sec = platform_timebase_freq(&cpu);
  181         ps_per_tick = 1000000000000 / ticks_per_sec;
  182 
  183         set_cputicker(mftb, ticks_per_sec, 0);
  184         snprintf(buf, sizeof(buf), "cpu%d:decrementer", curcpu);
  185         intrcnt_add(buf, &decr_counts[curcpu]);
  186         decr_et_stop(NULL);
  187         initialized = 1;
  188 }
  189 
  190 #ifdef SMP
  191 /*
  192  * AP early initialization.
  193  */
  194 void
  195 decr_ap_init(void)
  196 {
  197         char buf[32];
  198 
  199         snprintf(buf, sizeof(buf), "cpu%d:decrementer", curcpu);
  200         intrcnt_add(buf, &decr_counts[curcpu]);
  201         decr_et_stop(NULL);
  202 }
  203 #endif
  204 
  205 /*
  206  * Final initialization.
  207  */
  208 void
  209 decr_tc_init(void)
  210 {
  211 
  212         decr_tc.tc_frequency = ticks_per_sec;
  213         tc_init(&decr_tc);
  214         decr_et.et_name = "decrementer";
  215         decr_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT |
  216             ET_FLAGS_PERCPU;
  217         decr_et.et_quality = 1000;
  218         decr_et.et_frequency = ticks_per_sec;
  219         decr_et.et_min_period = (0x00000002LLU << 32) / ticks_per_sec;
  220         decr_et.et_max_period = (0x7fffffffLLU << 32) / ticks_per_sec;
  221         decr_et.et_start = decr_et_start;
  222         decr_et.et_stop = decr_et_stop;
  223         decr_et.et_priv = NULL;
  224         et_register(&decr_et);
  225 }
  226 
  227 /*
  228  * Event timer start method.
  229  */
  230 static int
  231 decr_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
  232 {
  233         struct decr_state *s = DPCPU_PTR(decr_state);
  234         uint32_t fdiv;
  235 #ifdef BOOKE
  236         uint32_t tcr;
  237 #endif
  238 
  239         if (period != 0) {
  240                 s->mode = 1;
  241                 s->div = (decr_et.et_frequency * period) >> 32;
  242         } else {
  243                 s->mode = 2;
  244                 s->div = 0;
  245         }
  246         if (first != 0)
  247                 fdiv = (decr_et.et_frequency * first) >> 32;
  248         else
  249                 fdiv = s->div;
  250 
  251 #ifdef BOOKE
  252         tcr = mfspr(SPR_TCR);
  253         tcr |= TCR_DIE;
  254         if (s->mode == 1) {
  255                 mtspr(SPR_DECAR, s->div);
  256                 tcr |= TCR_ARE;
  257         } else
  258                 tcr &= ~TCR_ARE;
  259         mtdec(fdiv);
  260         mtspr(SPR_TCR, tcr);
  261 #else
  262         mtdec(fdiv);
  263 #endif
  264 
  265         return (0);
  266 }
  267 
  268 /*
  269  * Event timer stop method.
  270  */
  271 static int
  272 decr_et_stop(struct eventtimer *et)
  273 {
  274         struct decr_state *s = DPCPU_PTR(decr_state);
  275 #ifdef BOOKE
  276         uint32_t tcr;
  277 #endif
  278 
  279         s->mode = 0;
  280         s->div = 0x7fffffff;
  281 #ifdef BOOKE
  282         tcr = mfspr(SPR_TCR);
  283         tcr &= ~(TCR_DIE | TCR_ARE);
  284         mtspr(SPR_TCR, tcr);
  285 #else
  286         mtdec(s->div);
  287 #endif
  288         return (0);
  289 }
  290 
  291 /*
  292  * Timecounter get method.
  293  */
  294 static unsigned
  295 decr_get_timecount(struct timecounter *tc)
  296 {
  297         return (mftb());
  298 }
  299 
  300 /*
  301  * Wait for about n microseconds (at least!).
  302  */
  303 void
  304 DELAY(int n)
  305 {
  306         u_quad_t        tb, ttb;
  307 
  308         TSENTER();
  309         tb = mftb();
  310         ttb = tb + howmany((uint64_t)n * 1000000, ps_per_tick);
  311         while (tb < ttb)
  312                 tb = mftb();
  313         TSEXIT();
  314 }
  315 

Cache object: 4139d8eba991ba7e78b0e186aca774bd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.