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  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
    3  * Copyright (C) 1995, 1996 TooLs GmbH.
    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 TooLs GmbH.
   17  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  *      $NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $
   32  */
   33 /*
   34  * Copyright (C) 2001 Benno Rice.
   35  * All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  *
   46  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   47  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   48  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   49  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   52  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   53  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   54  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   55  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   56  */
   57 
   58 #ifndef lint
   59 static const char rcsid[] =
   60   "$FreeBSD: releng/5.0/sys/powerpc/powerpc/clock.c 99032 2002-06-29 09:28:21Z benno $";
   61 #endif /* not lint */
   62 
   63 #include <sys/param.h>
   64 #include <sys/systm.h>
   65 #include <sys/kernel.h>
   66 #include <sys/sysctl.h>
   67 #include <sys/bus.h>
   68 #include <sys/timetc.h>
   69 #include <sys/interrupt.h>
   70 
   71 #include <dev/ofw/openfirm.h>
   72 
   73 #include <machine/clock.h>
   74 #include <machine/cpu.h>
   75 #include <machine/intr.h>
   76 
   77 #if 0 /* XXX */
   78 #include "adb.h"
   79 #else
   80 #define NADB    0
   81 #endif
   82 
   83 /*
   84  * Initially we assume a processor with a bus frequency of 12.5 MHz.
   85  */
   86 u_int                   tickspending;
   87 static u_long           ticks_per_sec = 12500000;
   88 static u_long           ns_per_tick = 80;
   89 static long             ticks_per_intr;
   90 static volatile u_long  lasttb;
   91 
   92 #define SECDAY          86400
   93 #define DIFF19041970    2082844800
   94 
   95 #if NADB > 0
   96 extern int adb_read_date_time(int *);
   97 extern int adb_set_date_time(int);
   98 #endif
   99 
  100 static int              clockinitted = 0;
  101 
  102 static timecounter_get_t        powerpc_get_timecount;
  103 
  104 static struct timecounter       powerpc_timecounter = {
  105         powerpc_get_timecount,  /* get_timecount */
  106         0,                      /* no poll_pps */
  107         ~0u,                    /* counter_mask */
  108         0,                      /* frequency */
  109         "powerpc"               /* name */
  110 };
  111 
  112 void
  113 inittodr(time_t base)
  114 {
  115         time_t          deltat;
  116         u_int           rtc_time;
  117         struct timespec ts;
  118 
  119         /*
  120          * If we can't read from RTC, use the fs time.
  121          */
  122 #if NADB > 0
  123         if (adb_read_date_time(&rtc_time) < 0)
  124 #endif
  125         {
  126                 ts.tv_sec = base;
  127                 ts.tv_nsec = 0;
  128                 tc_setclock(&ts);
  129                 return;
  130         }
  131         clockinitted = 1;
  132         ts.tv_sec = rtc_time - DIFF19041970;
  133 
  134         deltat = ts.tv_sec - base;
  135         if (deltat < 0) {
  136                 deltat = -deltat;
  137         }
  138         if (deltat < 2 * SECDAY) {
  139                 tc_setclock(&ts);
  140                 return;
  141         }
  142 
  143         printf("WARNING: clock %s %d days",
  144             ts.tv_sec < base ? "lost" : "gained", (int)(deltat / SECDAY));
  145 
  146         printf(" -- CHECK AND RESET THE DATE!\n");
  147 }
  148 
  149 /*
  150  * Similar to the above
  151  */
  152 void
  153 resettodr()
  154 {
  155 #if NADB > 0
  156         u_int   rtc_time;
  157 
  158         if (clockinitted) {
  159                 rtc_time = time.tv_sec + DIFF19041970;
  160                 adb_set_date_time(rtc_time);
  161         }
  162 #endif
  163 }
  164 
  165 void
  166 decr_intr(struct clockframe *frame)
  167 {
  168         u_long          tb;
  169         long            tick;
  170         int             nticks;
  171         register_t      msr;
  172 
  173         /*
  174          * Check whether we are initialized.
  175          */
  176         if (!ticks_per_intr)
  177                 return;
  178 
  179         /*
  180          * Based on the actual time delay since the last decrementer reload,
  181          * we arrange for earlier interrupt next time.
  182          */
  183         __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick));
  184         for (nticks = 0; tick < 0; nticks++)
  185                 tick += ticks_per_intr;
  186         mtdec(tick);
  187         /*
  188          * lasttb is used during microtime. Set it to the virtual
  189          * start of this tick interval.
  190          */
  191         lasttb = tb + tick - ticks_per_intr;
  192 
  193         nticks += tickspending;
  194         tickspending = 0;
  195 
  196         /*
  197          * Reenable interrupts
  198          */
  199 #if 0
  200         msr = mfmsr();
  201         mtmsr(msr | PSL_EE | PSL_RI);
  202 #endif  
  203         /*
  204          * Do standard timer interrupt stuff.
  205          * Do softclock stuff only on the last iteration.
  206          */
  207 #if 0
  208         while (--nticks > 0) {
  209                 hardclock(frame);
  210         }
  211 #endif
  212         hardclock(frame);
  213 }
  214 
  215 void
  216 cpu_initclocks(void)
  217 {
  218         int qhandle, phandle;
  219         char name[32];
  220         unsigned int msr;
  221         
  222         phandle = 0;
  223 
  224         /*
  225          * Get this info during autoconf?                               XXX
  226          */
  227         for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
  228                 if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0
  229                     && !strcmp(name, "cpu")
  230                     && OF_getprop(qhandle, "timebase-frequency",
  231                                   &ticks_per_sec, sizeof ticks_per_sec) >= 0) {
  232                         /*
  233                          * Should check for correct CPU here?           XXX
  234                          */
  235                         msr = mfmsr();
  236                         mtmsr(msr & ~(PSL_EE|PSL_RI));
  237 
  238                         powerpc_timecounter.tc_frequency = ticks_per_sec;
  239                         tc_init(&powerpc_timecounter);
  240 
  241                         ns_per_tick = 1000000000 / ticks_per_sec;
  242                         ticks_per_intr = ticks_per_sec / hz;
  243                         __asm __volatile ("mftb %0" : "=r"(lasttb));
  244                         mtdec(ticks_per_intr);
  245 
  246                         mtmsr(msr);
  247 
  248                         break;
  249                 }
  250                 if ((phandle = OF_child(qhandle)))
  251                         continue;
  252                 while (qhandle) {
  253                         if ((phandle = OF_peer(qhandle)))
  254                                 break;
  255                         qhandle = OF_parent(qhandle);
  256                 }
  257         }
  258         if (!phandle)
  259                 panic("no cpu node");
  260 }
  261 
  262 static __inline u_quad_t
  263 mftb(void)
  264 {
  265         u_long          scratch;
  266         u_quad_t        tb;
  267         
  268         __asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b"
  269               : "=r"(tb), "=r"(scratch));
  270         return tb;
  271 }
  272 
  273 static unsigned
  274 powerpc_get_timecount(struct timecounter *tc)
  275 {
  276         return mftb();
  277 }
  278 
  279 /*
  280  * Wait for about n microseconds (at least!).
  281  */
  282 void
  283 delay(int n)
  284 {
  285         u_quad_t        tb;
  286         u_long          tbh, tbl, scratch;
  287         
  288         tb = mftb();
  289         tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
  290         tbh = tb >> 32;
  291         tbl = tb;
  292         __asm ("1: mftbu %0; cmplw %0,%1; blt 1b; bgt 2f;"
  293                "mftb %0; cmplw %0,%2; blt 1b; 2:"
  294                : "=r"(scratch) : "r"(tbh), "r"(tbl));
  295 }
  296 
  297 /*
  298  * Nothing to do.
  299  */
  300 void
  301 setstatclockrate(int arg)
  302 {
  303 
  304         /* Do nothing */
  305 }

Cache object: 6d46b16f4aa92fede10d19a299508b0c


[ 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.