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/10.4/sys/arm/xscale/ixp425/ixp425_timer.c 278613 2015-02-12 03:50:33Z ian $");
   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/armreg.h>
   50 #include <machine/bus.h>
   51 #include <machine/cpu.h>
   52 #include <machine/cpufunc.h>
   53 #include <machine/frame.h>
   54 #include <machine/resource.h>
   55 #include <machine/intr.h>
   56 #include <arm/xscale/ixp425/ixp425reg.h>
   57 #include <arm/xscale/ixp425/ixp425var.h>
   58 
   59 static uint32_t counts_per_hz;
   60 
   61 /* callback functions for intr_functions */
   62 int     ixpclk_intr(void *);
   63 
   64 struct ixpclk_softc {
   65         device_t                sc_dev;
   66         bus_addr_t              sc_baseaddr;
   67         bus_space_tag_t         sc_iot;
   68         bus_space_handle_t      sc_ioh;
   69 };
   70 
   71 static unsigned ixp425_timer_get_timecount(struct timecounter *tc);
   72 
   73 #ifndef IXP425_CLOCK_FREQ
   74 #define COUNTS_PER_SEC          66666600        /* 66MHz */
   75 #else
   76 #define COUNTS_PER_SEC          IXP425_CLOCK_FREQ
   77 #endif
   78 #define COUNTS_PER_USEC         ((COUNTS_PER_SEC / 1000000) + 1)
   79 
   80 static struct ixpclk_softc *ixpclk_sc = NULL;
   81 
   82 #define GET_TS_VALUE(sc)        (*(volatile u_int32_t *) \
   83                                   (IXP425_TIMER_VBASE + IXP425_OST_TS))
   84 
   85 static struct timecounter ixp425_timer_timecounter = {
   86         ixp425_timer_get_timecount,     /* get_timecount */
   87         NULL,                           /* no poll_pps */
   88         ~0u,                            /* counter_mask */
   89         COUNTS_PER_SEC,                 /* frequency */
   90         "IXP4XX Timer",                 /* name */
   91         1000,                           /* quality */
   92 };
   93 
   94 static int
   95 ixpclk_probe(device_t dev)
   96 {
   97         device_set_desc(dev, "IXP4XX Timer");
   98         return (0);
   99 }
  100 
  101 static int
  102 ixpclk_attach(device_t dev)
  103 {
  104         struct ixpclk_softc *sc = device_get_softc(dev);
  105         struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
  106 
  107         ixpclk_sc = sc;
  108 
  109         sc->sc_dev = dev;
  110         sc->sc_iot = sa->sc_iot;
  111         sc->sc_baseaddr = IXP425_TIMER_HWBASE;
  112 
  113         if (bus_space_map(sc->sc_iot, sc->sc_baseaddr, 8, 0,
  114                           &sc->sc_ioh))
  115                 panic("%s: Cannot map registers", device_get_name(dev));
  116 
  117         return (0);
  118 }
  119 
  120 static device_method_t ixpclk_methods[] = {
  121         DEVMETHOD(device_probe, ixpclk_probe),
  122         DEVMETHOD(device_attach, ixpclk_attach),
  123         {0, 0},
  124 };
  125 
  126 static driver_t ixpclk_driver = {
  127         "ixpclk",
  128         ixpclk_methods,
  129         sizeof(struct ixpclk_softc),
  130 };
  131 static devclass_t ixpclk_devclass;
  132 
  133 DRIVER_MODULE(ixpclk, ixp, ixpclk_driver, ixpclk_devclass, 0, 0);
  134 static unsigned
  135 ixp425_timer_get_timecount(struct timecounter *tc)
  136 {
  137         uint32_t ret;
  138 
  139         ret = GET_TS_VALUE(sc);
  140         return (ret);
  141 }
  142 
  143 /*
  144  * cpu_initclocks:
  145  *
  146  *      Initialize the clock and get them going.
  147  */
  148 void
  149 cpu_initclocks(void)
  150 {
  151         struct ixpclk_softc* sc = ixpclk_sc;
  152         struct resource *irq;
  153         device_t dev = sc->sc_dev;
  154         u_int oldirqstate;
  155         int rid = 0;
  156         void *ihl;
  157 
  158         if (hz < 50 || COUNTS_PER_SEC % hz) {
  159                 printf("Cannot get %d Hz clock; using 100 Hz\n", hz);
  160                 hz = 100;
  161         }
  162         tick = 1000000 / hz;    /* number of microseconds between interrupts */
  163 
  164         /*
  165          * We only have one timer available; stathz and profhz are
  166          * always left as 0 (the upper-layer clock code deals with
  167          * this situation).
  168          */
  169         if (stathz != 0)
  170                 printf("Cannot get %d Hz statclock\n", stathz);
  171         stathz = 0;
  172 
  173         if (profhz != 0)
  174                 printf("Cannot get %d Hz profclock\n", profhz);
  175         profhz = 0;
  176 
  177         /* Report the clock frequency. */
  178 
  179         oldirqstate = disable_interrupts(PSR_I);
  180 
  181         irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, IXP425_INT_TMR0,
  182             IXP425_INT_TMR0, 1, RF_ACTIVE);
  183         if (!irq)
  184                 panic("Unable to setup the clock irq handler.\n");
  185         else
  186                 bus_setup_intr(dev, irq, INTR_TYPE_CLK, ixpclk_intr, NULL,
  187                     NULL, &ihl);
  188 
  189         /* Set up the new clock parameters. */
  190 
  191         /* clear interrupt */
  192         bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS,
  193                           OST_WARM_RESET | OST_WDOG_INT | OST_TS_INT |
  194                           OST_TIM1_INT | OST_TIM0_INT);
  195 
  196         counts_per_hz = COUNTS_PER_SEC / hz;
  197 
  198         /* reload value & Timer enable */
  199         bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_TIM0_RELOAD,
  200                           (counts_per_hz & TIMERRELOAD_MASK) | OST_TIMER_EN);
  201 
  202         tc_init(&ixp425_timer_timecounter);
  203         restore_interrupts(oldirqstate);
  204         rid = 0;
  205 }
  206 
  207 
  208 /*
  209  * DELAY:
  210  *
  211  *      Delay for at least N microseconds.
  212  */
  213 void
  214 DELAY(int n)
  215 {
  216         u_int32_t first, last;
  217         int usecs;
  218 
  219         if (n == 0)
  220                 return;
  221 
  222         /*
  223          * Clamp the timeout at a maximum value (about 32 seconds with
  224          * a 66MHz clock). *Nobody* should be delay()ing for anywhere
  225          * near that length of time and if they are, they should be hung
  226          * out to dry.
  227          */
  228         if (n >= (0x80000000U / COUNTS_PER_USEC))
  229                 usecs = (0x80000000U / COUNTS_PER_USEC) - 1;
  230         else
  231                 usecs = n * COUNTS_PER_USEC;
  232 
  233         /* Note: Timestamp timer counts *up*, unlike the other timers */
  234         first = GET_TS_VALUE();
  235 
  236         while (usecs > 0) {
  237                 last = GET_TS_VALUE();
  238                 usecs -= (int)(last - first);
  239                 first = last;
  240         }
  241 }
  242 
  243 /*
  244  * ixpclk_intr:
  245  *
  246  *      Handle the hardclock interrupt.
  247  */
  248 int
  249 ixpclk_intr(void *arg)
  250 {
  251         struct ixpclk_softc* sc = ixpclk_sc;
  252         struct trapframe *frame = arg;
  253 
  254         bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS,
  255                           OST_TIM0_INT);
  256 
  257         hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
  258         return (FILTER_HANDLED);
  259 }
  260 
  261 void
  262 cpu_startprofclock(void)
  263 {
  264 }
  265 
  266 void
  267 cpu_stopprofclock(void)
  268 {
  269 }

Cache object: f4d241abbac2efec797ff188f19cbd05


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