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 #include <sys/cdefs.h>
   59 __FBSDID("$FreeBSD: releng/5.2/sys/powerpc/powerpc/clock.c 120460 2003-09-26 09:02:24Z grehan $");
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/kernel.h>
   64 #include <sys/sysctl.h>
   65 #include <sys/bus.h>
   66 #include <sys/timetc.h>
   67 #include <sys/interrupt.h>
   68 
   69 #include <dev/ofw/openfirm.h>
   70 
   71 #include <machine/clock.h>
   72 #include <machine/cpu.h>
   73 #include <machine/intr.h>
   74 
   75 #if 0 /* XXX */
   76 #include "adb.h"
   77 #else
   78 #define NADB    0
   79 #endif
   80 
   81 /*
   82  * Initially we assume a processor with a bus frequency of 12.5 MHz.
   83  */
   84 u_int                   tickspending;
   85 u_long                  ns_per_tick = 80;
   86 static u_long           ticks_per_sec = 12500000;
   87 static long             ticks_per_intr;
   88 static volatile u_long  lasttb;
   89 
   90 #define SECDAY          86400
   91 #define DIFF19041970    2082844800
   92 
   93 #if NADB > 0
   94 extern int adb_read_date_time(int *);
   95 extern int adb_set_date_time(int);
   96 #endif
   97 
   98 static int              clockinitted = 0;
   99 
  100 static timecounter_get_t        decr_get_timecount;
  101 
  102 static struct timecounter       decr_timecounter = {
  103         decr_get_timecount,     /* get_timecount */
  104         0,                      /* no poll_pps */
  105         ~0u,                    /* counter_mask */
  106         0,                      /* frequency */
  107         "decrementer"           /* name */
  108 };
  109 
  110 void
  111 inittodr(time_t base)
  112 {
  113         time_t          deltat;
  114         u_int           rtc_time;
  115         struct timespec ts;
  116         phandle_t       phandle;
  117         ihandle_t       ihandle;
  118         char            rtcpath[128];
  119         u_int           rtcsecs;
  120 
  121         /*
  122          * If we can't read from RTC, use the fs time.
  123          */
  124         phandle = OF_finddevice("rtc");
  125         if (phandle != -1) {
  126                 OF_package_to_path(phandle, rtcpath, sizeof(rtcpath));
  127                 ihandle = OF_open(rtcpath);
  128                 if (ihandle != -1) {
  129                         if (OF_call_method("read-rtc", ihandle,
  130                             0, 1, &rtcsecs))
  131                                 printf("RTC call method error\n");
  132                         else {
  133                                 ts.tv_sec = rtcsecs - DIFF19041970;
  134                                 ts.tv_nsec = 0;
  135                                 tc_setclock(&ts);
  136                                 return;
  137                         }
  138                 }
  139         }
  140 
  141 #if NADB > 0
  142         if (adb_read_date_time(&rtc_time) < 0)
  143 #endif
  144         {
  145                 ts.tv_sec = base;
  146                 ts.tv_nsec = 0;
  147                 tc_setclock(&ts);
  148                 return;
  149         }
  150         clockinitted = 1;
  151         ts.tv_sec = rtc_time - DIFF19041970;
  152 
  153         deltat = ts.tv_sec - base;
  154         if (deltat < 0) {
  155                 deltat = -deltat;
  156         }
  157         if (deltat < 2 * SECDAY) {
  158                 tc_setclock(&ts);
  159                 return;
  160         }
  161 
  162         printf("WARNING: clock %s %d days",
  163             ts.tv_sec < base ? "lost" : "gained", (int)(deltat / SECDAY));
  164 
  165         printf(" -- CHECK AND RESET THE DATE!\n");
  166 }
  167 
  168 /*
  169  * Similar to the above
  170  */
  171 void
  172 resettodr()
  173 {
  174 #if NADB > 0
  175         u_int   rtc_time;
  176 
  177         if (clockinitted) {
  178                 rtc_time = time.tv_sec + DIFF19041970;
  179                 adb_set_date_time(rtc_time);
  180         }
  181 #endif
  182 }
  183 
  184 void
  185 decr_intr(struct clockframe *frame)
  186 {
  187         u_long          tb;
  188         long            tick;
  189         int             nticks;
  190         register_t      msr;
  191 
  192         /*
  193          * Check whether we are initialized.
  194          */
  195         if (!ticks_per_intr)
  196                 return;
  197 
  198         /*
  199          * Based on the actual time delay since the last decrementer reload,
  200          * we arrange for earlier interrupt next time.
  201          */
  202         __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick));
  203         for (nticks = 0; tick < 0; nticks++)
  204                 tick += ticks_per_intr;
  205         mtdec(tick);
  206         /*
  207          * lasttb is used during microtime. Set it to the virtual
  208          * start of this tick interval.
  209          */
  210         lasttb = tb + tick - ticks_per_intr;
  211 
  212         nticks += tickspending;
  213         tickspending = 0;
  214 
  215         /*
  216          * Reenable interrupts
  217          */
  218 #if 0
  219         msr = mfmsr();
  220         mtmsr(msr | PSL_EE | PSL_RI);
  221 #endif  
  222         /*
  223          * Do standard timer interrupt stuff.
  224          * Do softclock stuff only on the last iteration.
  225          */
  226 #if 0
  227         while (--nticks > 0) {
  228                 hardclock(frame);
  229         }
  230 #endif
  231         hardclock(frame);
  232 }
  233 
  234 void
  235 cpu_initclocks(void)
  236 {
  237 
  238         return;
  239 }
  240 
  241 void
  242 decr_init(void)
  243 {
  244         int qhandle, phandle;
  245         char name[32];
  246         unsigned int msr;
  247         
  248         phandle = 0;
  249 
  250         /*
  251          * Get this info during autoconf?                               XXX
  252          */
  253         for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
  254                 if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0
  255                     && !strcmp(name, "cpu")
  256                     && OF_getprop(qhandle, "timebase-frequency",
  257                                   &ticks_per_sec, sizeof ticks_per_sec) >= 0) {
  258                         /*
  259                          * Should check for correct CPU here?           XXX
  260                          */
  261                         msr = mfmsr();
  262                         mtmsr(msr & ~(PSL_EE|PSL_RI));
  263 
  264                         decr_timecounter.tc_frequency = ticks_per_sec;
  265                         tc_init(&decr_timecounter);
  266 
  267                         ns_per_tick = 1000000000 / ticks_per_sec;
  268                         ticks_per_intr = ticks_per_sec / hz;
  269                         __asm __volatile ("mftb %0" : "=r"(lasttb));
  270                         mtdec(ticks_per_intr);
  271 
  272                         mtmsr(msr);
  273 
  274                         break;
  275                 }
  276                 if ((phandle = OF_child(qhandle)))
  277                         continue;
  278                 while (qhandle) {
  279                         if ((phandle = OF_peer(qhandle)))
  280                                 break;
  281                         qhandle = OF_parent(qhandle);
  282                 }
  283         }
  284         if (!phandle)
  285                 panic("no cpu node");
  286 }
  287 
  288 static __inline u_quad_t
  289 mftb(void)
  290 {
  291         u_long          scratch;
  292         u_quad_t        tb;
  293         
  294         __asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b"
  295               : "=r"(tb), "=r"(scratch));
  296         return tb;
  297 }
  298 
  299 static unsigned
  300 decr_get_timecount(struct timecounter *tc)
  301 {
  302         return mftb();
  303 }
  304 
  305 /*
  306  * Wait for about n microseconds (at least!).
  307  */
  308 void
  309 DELAY(int n)
  310 {
  311         u_quad_t        tb, ttb;
  312         
  313         tb = mftb();
  314         ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick;
  315         while (tb < ttb)
  316                 tb = mftb();
  317 }
  318 
  319 /*
  320  * Nothing to do.
  321  */
  322 void
  323 cpu_startprofclock(void)
  324 {
  325 
  326         /* Do nothing */
  327 }
  328 
  329 void
  330 cpu_stopprofclock(void)
  331 {
  332 }

Cache object: dfafa010307bb4bf09466413708867a8


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