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/arm/xscale/ixp425/ixp425_timer.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 /*      $NetBSD: ixp425_timer.c,v 1.11 2006/04/10 03:36:03 simonb Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2003
    5  *      Ichiro FUKUHARA <ichiro@ichiro.org>.
    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 Ichiro FUKUHARA.
   19  * 4. The name of the company nor the name of the author may be used to
   20  *    endorse or promote products derived from this software without specific
   21  *    prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
   24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   26  * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
   27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD: releng/8.3/sys/arm/xscale/ixp425/ixp425_timer.c 186352 2008-12-20 03:26:09Z sam $");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/time.h>
   44 #include <sys/bus.h>
   45 #include <sys/resource.h>
   46 #include <sys/rman.h>
   47 #include <sys/timetc.h>
   48 
   49 #include <machine/bus.h>
   50 #include <machine/cpu.h>
   51 #include <machine/cpufunc.h>
   52 #include <machine/frame.h>
   53 #include <machine/resource.h>
   54 #include <machine/intr.h>
   55 #include <arm/xscale/ixp425/ixp425reg.h>
   56 #include <arm/xscale/ixp425/ixp425var.h>
   57 
   58 static uint32_t counts_per_hz;
   59 
   60 /* callback functions for intr_functions */
   61 int     ixpclk_intr(void *);
   62 
   63 struct ixpclk_softc {
   64         device_t                sc_dev;
   65         bus_addr_t              sc_baseaddr;
   66         bus_space_tag_t         sc_iot;
   67         bus_space_handle_t      sc_ioh;
   68 };
   69 
   70 static unsigned ixp425_timer_get_timecount(struct timecounter *tc);
   71 
   72 #ifndef IXP425_CLOCK_FREQ
   73 #define COUNTS_PER_SEC          66666600        /* 66MHz */
   74 #else
   75 #define COUNTS_PER_SEC          IXP425_CLOCK_FREQ
   76 #endif
   77 #define COUNTS_PER_USEC         ((COUNTS_PER_SEC / 1000000) + 1)
   78 
   79 static struct ixpclk_softc *ixpclk_sc = NULL;
   80 
   81 #define GET_TS_VALUE(sc)        (*(volatile u_int32_t *) \
   82                                   (IXP425_TIMER_VBASE + IXP425_OST_TS))
   83 
   84 static struct timecounter ixp425_timer_timecounter = {
   85         ixp425_timer_get_timecount,     /* get_timecount */
   86         NULL,                           /* no poll_pps */
   87         ~0u,                            /* counter_mask */
   88         COUNTS_PER_SEC,                 /* frequency */
   89         "IXP4XX Timer",                 /* name */
   90         1000,                           /* quality */
   91 };
   92 
   93 static int
   94 ixpclk_probe(device_t dev)
   95 {
   96         device_set_desc(dev, "IXP4XX Timer");
   97         return (0);
   98 }
   99 
  100 static int
  101 ixpclk_attach(device_t dev)
  102 {
  103         struct ixpclk_softc *sc = device_get_softc(dev);
  104         struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
  105 
  106         ixpclk_sc = sc;
  107 
  108         sc->sc_dev = dev;
  109         sc->sc_iot = sa->sc_iot;
  110         sc->sc_baseaddr = IXP425_TIMER_HWBASE;
  111 
  112         if (bus_space_map(sc->sc_iot, sc->sc_baseaddr, 8, 0,
  113                           &sc->sc_ioh))
  114                 panic("%s: Cannot map registers", device_get_name(dev));
  115 
  116         return (0);
  117 }
  118 
  119 static device_method_t ixpclk_methods[] = {
  120         DEVMETHOD(device_probe, ixpclk_probe),
  121         DEVMETHOD(device_attach, ixpclk_attach),
  122         {0, 0},
  123 };
  124 
  125 static driver_t ixpclk_driver = {
  126         "ixpclk",
  127         ixpclk_methods,
  128         sizeof(struct ixpclk_softc),
  129 };
  130 static devclass_t ixpclk_devclass;
  131 
  132 DRIVER_MODULE(ixpclk, ixp, ixpclk_driver, ixpclk_devclass, 0, 0);
  133 static unsigned
  134 ixp425_timer_get_timecount(struct timecounter *tc)
  135 {
  136         uint32_t ret;
  137 
  138         ret = GET_TS_VALUE(sc);
  139         return (ret);
  140 }
  141 
  142 /*
  143  * cpu_initclocks:
  144  *
  145  *      Initialize the clock and get them going.
  146  */
  147 void
  148 cpu_initclocks(void)
  149 {
  150         struct ixpclk_softc* sc = ixpclk_sc;
  151         struct resource *irq;
  152         device_t dev = sc->sc_dev;
  153         u_int oldirqstate;
  154         int rid = 0;
  155         void *ihl;
  156 
  157         if (hz < 50 || COUNTS_PER_SEC % hz) {
  158                 printf("Cannot get %d Hz clock; using 100 Hz\n", hz);
  159                 hz = 100;
  160         }
  161         tick = 1000000 / hz;    /* number of microseconds between interrupts */
  162 
  163         /*
  164          * We only have one timer available; stathz and profhz are
  165          * always left as 0 (the upper-layer clock code deals with
  166          * this situation).
  167          */
  168         if (stathz != 0)
  169                 printf("Cannot get %d Hz statclock\n", stathz);
  170         stathz = 0;
  171 
  172         if (profhz != 0)
  173                 printf("Cannot get %d Hz profclock\n", profhz);
  174         profhz = 0;
  175 
  176         /* Report the clock frequency. */
  177 
  178         oldirqstate = disable_interrupts(I32_bit);
  179 
  180         irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, IXP425_INT_TMR0,
  181             IXP425_INT_TMR0, 1, RF_ACTIVE);
  182         if (!irq)
  183                 panic("Unable to setup the clock irq handler.\n");
  184         else
  185                 bus_setup_intr(dev, irq, INTR_TYPE_CLK, ixpclk_intr, NULL,
  186                     NULL, &ihl);
  187 
  188         /* Set up the new clock parameters. */
  189 
  190         /* clear interrupt */
  191         bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS,
  192                           OST_WARM_RESET | OST_WDOG_INT | OST_TS_INT |
  193                           OST_TIM1_INT | OST_TIM0_INT);
  194 
  195         counts_per_hz = COUNTS_PER_SEC / hz;
  196 
  197         /* reload value & Timer enable */
  198         bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_TIM0_RELOAD,
  199                           (counts_per_hz & TIMERRELOAD_MASK) | OST_TIMER_EN);
  200 
  201         tc_init(&ixp425_timer_timecounter);
  202         restore_interrupts(oldirqstate);
  203         rid = 0;
  204 }
  205 
  206 
  207 /*
  208  * DELAY:
  209  *
  210  *      Delay for at least N microseconds.
  211  */
  212 void
  213 DELAY(int n)
  214 {
  215         u_int32_t first, last;
  216         int usecs;
  217 
  218         if (n == 0)
  219                 return;
  220 
  221         /*
  222          * Clamp the timeout at a maximum value (about 32 seconds with
  223          * a 66MHz clock). *Nobody* should be delay()ing for anywhere
  224          * near that length of time and if they are, they should be hung
  225          * out to dry.
  226          */
  227         if (n >= (0x80000000U / COUNTS_PER_USEC))
  228                 usecs = (0x80000000U / COUNTS_PER_USEC) - 1;
  229         else
  230                 usecs = n * COUNTS_PER_USEC;
  231 
  232         /* Note: Timestamp timer counts *up*, unlike the other timers */
  233         first = GET_TS_VALUE();
  234 
  235         while (usecs > 0) {
  236                 last = GET_TS_VALUE();
  237                 usecs -= (int)(last - first);
  238                 first = last;
  239         }
  240 }
  241 
  242 /*
  243  * ixpclk_intr:
  244  *
  245  *      Handle the hardclock interrupt.
  246  */
  247 int
  248 ixpclk_intr(void *arg)
  249 {
  250         struct ixpclk_softc* sc = ixpclk_sc;
  251         struct trapframe *frame = arg;
  252 
  253         bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS,
  254                           OST_TIM0_INT);
  255 
  256         hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
  257         return (FILTER_HANDLED);
  258 }
  259 
  260 void
  261 cpu_startprofclock(void)
  262 {
  263 }
  264 
  265 void
  266 cpu_stopprofclock(void)
  267 {
  268 }

Cache object: 16610288e877e9168af1d5f941372230


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