[BACK]Return to clock.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvme68k / dev

Annotation of sys/arch/mvme68k/dev/clock.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: clock.c,v 1.13 2004/07/30 22:29:44 miod Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1995 Theo de Raadt
        !             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:  *
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
        !            16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
        !            19:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            25:  * SUCH DAMAGE.
        !            26:  *
        !            27:  * Copyright (c) 1992, 1993
        !            28:  *      The Regents of the University of California.  All rights reserved.
        !            29:  *
        !            30:  * This software was developed by the Computer Systems Engineering group
        !            31:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
        !            32:  * contributed to Berkeley.
        !            33:  *
        !            34:  * All advertising materials mentioning features or use of this software
        !            35:  * must display the following acknowledgement:
        !            36:  *      This product includes software developed by the University of
        !            37:  *      California, Lawrence Berkeley Laboratory.
        !            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:  * 3. Neither the name of the University nor the names of its contributors
        !            48:  *    may be used to endorse or promote products derived from this software
        !            49:  *    without specific prior written permission.
        !            50:  *
        !            51:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            52:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            53:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            54:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            55:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            56:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            57:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            58:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            59:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            60:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            61:  * SUCH DAMAGE.
        !            62:  *
        !            63:  *      @(#)clock.c     8.1 (Berkeley) 6/11/93
        !            64:  */
        !            65:
        !            66: #include <sys/param.h>
        !            67: #include <sys/device.h>
        !            68: #include <sys/kernel.h>
        !            69: #include <sys/systm.h>
        !            70:
        !            71: #include <machine/psl.h>
        !            72: #include <machine/autoconf.h>
        !            73: #include <machine/cpu.h>
        !            74:
        !            75: #include "pcc.h"
        !            76: #include "mc.h"
        !            77: #include "pcctwo.h"
        !            78:
        !            79: #if NPCC > 0
        !            80: #include <mvme68k/dev/pccreg.h>
        !            81: #endif
        !            82: #if NPCCTWO > 0
        !            83: #include <mvme68k/dev/pcctworeg.h>
        !            84: #include <mvme68k/dev/vme.h>
        !            85: extern struct vme2reg *sys_vme2;
        !            86: #endif
        !            87: #if NMC > 0
        !            88: #include <mvme68k/dev/mcreg.h>
        !            89: #endif
        !            90:
        !            91: /*
        !            92:  * Statistics clock interval and variance, in usec.  Variance must be a
        !            93:  * power of two.  Since this gives us an even number, not an odd number,
        !            94:  * we discard one case and compensate.  That is, a variance of 8192 would
        !            95:  * give us offsets in [0..8191].  Instead, we take offsets in [1..8191].
        !            96:  * This is symmetric about the point 2048, or statvar/2, and thus averages
        !            97:  * to that value (assuming uniform random numbers).
        !            98:  */
        !            99: int statvar = 8192;
        !           100: int statmin;           /* statclock interval - 1/2*variance */
        !           101:
        !           102: struct clocksoftc {
        !           103:        struct device   sc_dev;
        !           104:        struct intrhand sc_profih;
        !           105:        struct intrhand sc_statih;
        !           106: };
        !           107:
        !           108: void   clockattach(struct device *, struct device *, void *);
        !           109: int    clockmatch(struct device *, void *, void *);
        !           110:
        !           111: struct cfattach clock_ca = {
        !           112:        sizeof(struct clocksoftc), clockmatch, clockattach
        !           113: };
        !           114:
        !           115: struct cfdriver clock_cd = {
        !           116:        NULL, "clock", DV_DULL
        !           117: };
        !           118:
        !           119: int    clockintr(void *);
        !           120: int    statintr(void *);
        !           121:
        !           122: int    clockbus;
        !           123: u_char stat_reset, prof_reset;
        !           124:
        !           125: /*
        !           126:  * Every machine must have a clock tick device of some sort; for this
        !           127:  * platform this file manages it, no matter what form it takes.
        !           128:  */
        !           129: int
        !           130: clockmatch(parent, vcf, args)
        !           131:        struct device *parent;
        !           132:        void *vcf, *args;
        !           133: {
        !           134:        return (1);
        !           135: }
        !           136:
        !           137: void
        !           138: clockattach(parent, self, args)
        !           139:        struct device *parent, *self;
        !           140:        void *args;
        !           141: {
        !           142:        struct confargs *ca = args;
        !           143:        struct clocksoftc *sc = (struct clocksoftc *)self;
        !           144:
        !           145:        sc->sc_profih.ih_fn = clockintr;
        !           146:        sc->sc_profih.ih_arg = 0;
        !           147:        sc->sc_profih.ih_wantframe = 1;
        !           148:        sc->sc_profih.ih_ipl = ca->ca_ipl;
        !           149:
        !           150:        sc->sc_statih.ih_fn = statintr;
        !           151:        sc->sc_statih.ih_arg = 0;
        !           152:        sc->sc_statih.ih_wantframe = 1;
        !           153:        sc->sc_statih.ih_ipl = ca->ca_ipl;
        !           154:
        !           155:        clockbus = ca->ca_bustype;
        !           156:        switch (ca->ca_bustype) {
        !           157: #if NPCC > 0
        !           158:        case BUS_PCC:
        !           159:                prof_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
        !           160:                stat_reset = ca->ca_ipl | PCC_IRQ_IEN | PCC_TIMERACK;
        !           161:                pccintr_establish(PCCV_TIMER1, &sc->sc_profih, "clock");
        !           162:                pccintr_establish(PCCV_TIMER2, &sc->sc_statih, "stat");
        !           163:                break;
        !           164: #endif
        !           165: #if NMC > 0
        !           166:        case BUS_MC:
        !           167:                prof_reset = ca->ca_ipl | MC_IRQ_IEN | MC_IRQ_ICLR;
        !           168:                stat_reset = ca->ca_ipl | MC_IRQ_IEN | MC_IRQ_ICLR;
        !           169:                mcintr_establish(MCV_TIMER1, &sc->sc_profih, "clock");
        !           170:                mcintr_establish(MCV_TIMER2, &sc->sc_statih, "stat");
        !           171:                break;
        !           172: #endif
        !           173: #if NPCCTWO > 0
        !           174:        case BUS_PCCTWO:
        !           175:                prof_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
        !           176:                stat_reset = ca->ca_ipl | PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
        !           177:                pcctwointr_establish(PCC2V_TIMER1, &sc->sc_profih, "clock");
        !           178:                pcctwointr_establish(PCC2V_TIMER2, &sc->sc_statih, "stat");
        !           179:                break;
        !           180: #endif
        !           181:        }
        !           182:
        !           183:        printf("\n");
        !           184: }
        !           185:
        !           186: /*
        !           187:  * clockintr: ack intr and call hardclock
        !           188:  */
        !           189: int
        !           190: clockintr(arg)
        !           191:        void *arg;
        !           192: {
        !           193:        switch (clockbus) {
        !           194: #if NPCC > 0
        !           195:        case BUS_PCC:
        !           196:                sys_pcc->pcc_t1irq = prof_reset;
        !           197:                break;
        !           198: #endif
        !           199: #if NMC > 0
        !           200:        case BUS_MC:
        !           201:                sys_mc->mc_t1irq = prof_reset;
        !           202:                break;
        !           203: #endif
        !           204: #if NPCCTWO > 0
        !           205:        case BUS_PCCTWO:
        !           206:                sys_pcc2->pcc2_t1irq = prof_reset;
        !           207:                break;
        !           208: #endif
        !           209:        }
        !           210:
        !           211:        hardclock(arg);
        !           212:        return (1);
        !           213: }
        !           214:
        !           215: /*
        !           216:  * Set up real-time clock; we don't have a statistics clock at
        !           217:  * present.
        !           218:  */
        !           219: void
        !           220: cpu_initclocks()
        !           221: {
        !           222:        register int statint, minint;
        !           223:
        !           224:        if (1000000 % hz) {
        !           225:                printf("cannot get %d Hz clock; using 100 Hz\n", hz);
        !           226:                hz = 100;
        !           227:                tick = 1000000 / hz;
        !           228:        }
        !           229:        if (stathz == 0)
        !           230:                stathz = hz;
        !           231:        if (1000000 % stathz) {
        !           232:                printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
        !           233:                stathz = 100;
        !           234:        }
        !           235:        profhz = stathz;                /* always */
        !           236:
        !           237:        statint = 1000000 / stathz;
        !           238:        minint = statint / 2 + 100;
        !           239:        while (statvar > minint)
        !           240:                statvar >>= 1;
        !           241:        switch (clockbus) {
        !           242: #if NPCC > 0
        !           243:        case BUS_PCC:
        !           244:                sys_pcc->pcc_t1pload = pcc_timer_us2lim(tick);
        !           245:                sys_pcc->pcc_t1ctl = PCC_TIMERCLEAR;
        !           246:                sys_pcc->pcc_t1ctl = PCC_TIMERSTART;
        !           247:                sys_pcc->pcc_t1irq = prof_reset;
        !           248:
        !           249:                sys_pcc->pcc_t2pload = pcc_timer_us2lim(statint);
        !           250:                sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
        !           251:                sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
        !           252:                sys_pcc->pcc_t2irq = stat_reset;
        !           253:                break;
        !           254: #endif
        !           255: #if NMC > 0
        !           256:        case BUS_MC:
        !           257:                /* profclock */
        !           258:                sys_mc->mc_t1ctl = 0;
        !           259:                sys_mc->mc_t1cmp = mc_timer_us2lim(tick);
        !           260:                sys_mc->mc_t1count = 0;
        !           261:                sys_mc->mc_t1ctl = MC_TCTL_CEN | MC_TCTL_COC | MC_TCTL_COVF;
        !           262:                sys_mc->mc_t1irq = prof_reset;
        !           263:
        !           264:                /* statclock */
        !           265:                sys_mc->mc_t2ctl = 0;
        !           266:                sys_mc->mc_t2cmp = mc_timer_us2lim(statint);
        !           267:                sys_mc->mc_t2count = 0;
        !           268:                sys_mc->mc_t2ctl = MC_TCTL_CEN | MC_TCTL_COC | MC_TCTL_COVF;
        !           269:                sys_mc->mc_t2irq = stat_reset;
        !           270:                break;
        !           271: #endif
        !           272: #if NPCCTWO > 0
        !           273:        case BUS_PCCTWO:
        !           274:                /* profclock */
        !           275:                sys_pcc2->pcc2_t1ctl = 0;
        !           276:                sys_pcc2->pcc2_t1cmp = pcc2_timer_us2lim(tick);
        !           277:                sys_pcc2->pcc2_t1count = 0;
        !           278:                sys_pcc2->pcc2_t1ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
        !           279:                    PCC2_TCTL_COVF;
        !           280:                sys_pcc2->pcc2_t1irq = prof_reset;
        !           281:
        !           282:                /* statclock */
        !           283:                sys_pcc2->pcc2_t2ctl = 0;
        !           284:                sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(statint);
        !           285:                sys_pcc2->pcc2_t2count = 0;
        !           286:                sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC |
        !           287:                    PCC2_TCTL_COVF;
        !           288:                sys_pcc2->pcc2_t2irq = stat_reset;
        !           289:                break;
        !           290: #endif
        !           291:        }
        !           292:        statmin = statint - (statvar >> 1);
        !           293: }
        !           294:
        !           295: void
        !           296: setstatclockrate(newhz)
        !           297:        int newhz;
        !           298: {
        !           299: }
        !           300:
        !           301: int
        !           302: statintr(cap)
        !           303:        void *cap;
        !           304: {
        !           305:        register u_long newint, r, var;
        !           306:
        !           307:        switch (clockbus) {
        !           308: #if NPCC > 0
        !           309:        case BUS_PCC:
        !           310:                sys_pcc->pcc_t2irq = stat_reset;
        !           311:                break;
        !           312: #endif
        !           313: #if NMC > 0
        !           314:        case BUS_MC:
        !           315:                sys_mc->mc_t2irq = stat_reset;
        !           316:                break;
        !           317: #endif
        !           318: #if NPCCTWO > 0
        !           319:        case BUS_PCCTWO:
        !           320:                sys_pcc2->pcc2_t2irq = stat_reset;
        !           321:                break;
        !           322: #endif
        !           323:        }
        !           324:
        !           325:        statclock((struct clockframe *)cap);
        !           326:
        !           327:        /*
        !           328:         * Compute new randomized interval.  The intervals are uniformly
        !           329:         * distributed on [statint - statvar / 2, statint + statvar / 2],
        !           330:         * and therefore have mean statint, giving a stathz frequency clock.
        !           331:         */
        !           332:        var = statvar;
        !           333:        do {
        !           334:                r = random() & (var - 1);
        !           335:        } while (r == 0);
        !           336:        newint = statmin + r;
        !           337:
        !           338:        switch (clockbus) {
        !           339: #if NPCC > 0
        !           340:        case BUS_PCC:
        !           341:                sys_pcc->pcc_t2pload = pcc_timer_us2lim(newint);
        !           342:                sys_pcc->pcc_t2ctl = PCC_TIMERCLEAR;
        !           343:                sys_pcc->pcc_t2ctl = PCC_TIMERSTART;
        !           344:                sys_pcc->pcc_t2irq = stat_reset;
        !           345:                break;
        !           346: #endif
        !           347: #if NMC > 0
        !           348:        case BUS_MC:
        !           349:                sys_mc->mc_t2ctl = 0;
        !           350:                sys_mc->mc_t2cmp = mc_timer_us2lim(newint);
        !           351:                sys_mc->mc_t2count = 0;         /* should I? */
        !           352:                sys_mc->mc_t2irq = stat_reset;
        !           353:                sys_mc->mc_t2ctl = MC_TCTL_CEN | MC_TCTL_COC;
        !           354:                break;
        !           355: #endif
        !           356: #if NPCCTWO > 0
        !           357:        case BUS_PCCTWO:
        !           358:                sys_pcc2->pcc2_t2ctl = 0;
        !           359:                sys_pcc2->pcc2_t2cmp = pcc2_timer_us2lim(newint);
        !           360:                sys_pcc2->pcc2_t2count = 0;             /* should I? */
        !           361:                sys_pcc2->pcc2_t2irq = stat_reset;
        !           362:                sys_pcc2->pcc2_t2ctl = PCC2_TCTL_CEN | PCC2_TCTL_COC;
        !           363:                break;
        !           364: #endif
        !           365:        }
        !           366:        return (1);
        !           367: }
        !           368:
        !           369: void
        !           370: delay(us)
        !           371:        int us;
        !           372: {
        !           373: #if (NPCC > 0) || (NPCCTWO > 0)
        !           374:        volatile register int c;
        !           375: #endif
        !           376:
        !           377:        switch (clockbus) {
        !           378: #if NPCC > 0
        !           379:        case BUS_PCC:
        !           380:                /*
        !           381:                 * XXX MVME147 doesn't have a 3rd free-running timer,
        !           382:                 * so we use a stupid loop. Fix the code to watch t1:
        !           383:                 * the profiling timer.
        !           384:                 */
        !           385:                c = 2 * us;
        !           386:                while (--c > 0)
        !           387:                        ;
        !           388:                break;
        !           389: #endif
        !           390: #if NMC > 0
        !           391:        case BUS_MC:
        !           392:                /*
        !           393:                 * Reset and restart a free-running timer 1MHz, watch
        !           394:                 * for it to reach the required count.
        !           395:                 */
        !           396:                sys_mc->mc_t3irq = 0;
        !           397:                sys_mc->mc_t3ctl = 0;
        !           398:                sys_mc->mc_t3count = 0;
        !           399:                sys_mc->mc_t3ctl = MC_TCTL_CEN | MC_TCTL_COVF;
        !           400:
        !           401:                while (sys_mc->mc_t3count < us)
        !           402:                        ;
        !           403:                break;
        !           404: #endif
        !           405: #if NPCCTWO > 0
        !           406:        case BUS_PCCTWO:
        !           407:                /*
        !           408:                 * Use the first VMEChip2 timer in polling mode whenever
        !           409:                 * possible. However, since clock attaches before vme,
        !           410:                 * use a tight loop if necessary.
        !           411:                 */
        !           412:        {
        !           413:                struct vme2reg *vme2;
        !           414:
        !           415:                if (sys_vme2 != NULL)
        !           416:                        vme2 = sys_vme2;
        !           417:                else
        !           418:                        vme2 = (struct vme2reg *)IIOV(0xfff40000);
        !           419:
        !           420:                vme2->vme2_t1cmp = 0xffffffff;
        !           421:                vme2->vme2_t1count = 0;
        !           422:                vme2->vme2_tctl |= VME2_TCTL_CEN;
        !           423:
        !           424:                while (vme2->vme2_t1count < us)
        !           425:                        ;
        !           426:
        !           427:                vme2->vme2_tctl &= ~VME2_TCTL_CEN;
        !           428:        }
        !           429:                break;
        !           430: #endif
        !           431:        }
        !           432: }

CVSweb