[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

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