[BACK]Return to sa11x0_ost.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / sa11x0

Annotation of sys/arch/arm/sa11x0/sa11x0_ost.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: sa11x0_ost.c,v 1.7 2007/01/11 07:24:52 robert Exp $ */
        !             2: /*     $NetBSD: sa11x0_ost.c,v 1.11 2003/07/15 00:24:51 lukem Exp $    */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1997 Mark Brinicombe.
        !             6:  * Copyright (c) 1997 Causality Limited.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * This code is derived from software contributed to The NetBSD Foundation
        !            10:  * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: #include <sys/cdefs.h>
        !            42: /*
        !            43: __KERNEL_RCSID(0, "$NetBSD: sa11x0_ost.c,v 1.11 2003/07/15 00:24:51 lukem Exp $");
        !            44: */
        !            45:
        !            46: #include <sys/types.h>
        !            47: #include <sys/param.h>
        !            48: #include <sys/systm.h>
        !            49: #include <sys/kernel.h>
        !            50: #include <sys/time.h>
        !            51: #include <sys/device.h>
        !            52:
        !            53: #include <machine/bus.h>
        !            54: #include <machine/intr.h>
        !            55:
        !            56: #include <arm/cpufunc.h>
        !            57:
        !            58: #include <arm/sa11x0/sa11x0_reg.h>
        !            59: #include <arm/sa11x0/sa11x0_var.h>
        !            60: #include <arm/sa11x0/sa11x0_ostreg.h>
        !            61:
        !            62: int    saost_match(struct device *, void *, void *);
        !            63: void   saost_attach(struct device *, struct device *, void *);
        !            64:
        !            65: int            gettick(void);
        !            66: static int     clockintr(void *);
        !            67: static int     statintr(void *);
        !            68: void           rtcinit(void);
        !            69:
        !            70: struct saost_softc {
        !            71:        struct device           sc_dev;
        !            72:        bus_addr_t              sc_baseaddr;
        !            73:        bus_space_tag_t         sc_iot;
        !            74:        bus_space_handle_t      sc_ioh;
        !            75:
        !            76:        u_int32_t       sc_clock_count;
        !            77:        u_int32_t       sc_statclock_count;
        !            78:        u_int32_t       sc_statclock_step;
        !            79: };
        !            80:
        !            81: static struct saost_softc *saost_sc = NULL;
        !            82:
        !            83: #define DEF_TIMER_FREQUENCY         3686400         /* 3.6864MHz */
        !            84: int saost_timer_freq =DEF_TIMER_FREQUENCY;
        !            85: #define TIMER_FREQUENCY         saost_timer_freq
        !            86: #define TICKS_PER_MICROSECOND   (TIMER_FREQUENCY/1000000)
        !            87:
        !            88: #ifndef STATHZ
        !            89: #define STATHZ 64
        !            90: #endif
        !            91:
        !            92: extern volatile struct timeval time;
        !            93:
        !            94: struct cfattach saost_ca = {
        !            95:        sizeof (struct saost_softc), saost_match, saost_attach
        !            96: };
        !            97:
        !            98: struct cfdriver saost_cd = {
        !            99:        NULL, "saost", DV_DULL
        !           100: };
        !           101:
        !           102: int
        !           103: saost_match(parent, match, aux)
        !           104:        struct device *parent;
        !           105:        void *match;
        !           106:        void *aux;
        !           107: {
        !           108:        if (saost_sc == NULL)
        !           109:                return (1);
        !           110:
        !           111:        return (0);
        !           112: }
        !           113:
        !           114: void
        !           115: saost_attach(parent, self, aux)
        !           116:        struct device *parent;
        !           117:        struct device *self;
        !           118:        void *aux;
        !           119: {
        !           120:        struct saost_softc *sc = (struct saost_softc*)self;
        !           121:        struct saip_attach_args *sa = aux;
        !           122:
        !           123: //     printf("\n");
        !           124:
        !           125:        sc->sc_iot = sa->sai_iot;
        !           126:        sc->sc_baseaddr = sa->sai_addr;
        !           127:
        !           128:        saost_sc = sc;
        !           129:
        !           130:        /* XXX */
        !           131:        if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X)
        !           132:                TIMER_FREQUENCY = 3250000; /* XXX */
        !           133:
        !           134:
        !           135:        if(bus_space_map(sa->sai_iot, sa->sai_addr, sa->sai_size, 0,
        !           136:                        &sc->sc_ioh))
        !           137:                panic("%s: Cannot map registers", self->dv_xname);
        !           138:
        !           139:        /* disable all channel and clear interrupt status */
        !           140:        /* FIXME uvm_fault? */
        !           141:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 0);
        !           142:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf);
        !           143:
        !           144:        printf(": SA-11x0 OS Timer\n",  sc->sc_dev.dv_xname);
        !           145: }
        !           146:
        !           147: static int
        !           148: clockintr(arg)
        !           149:        void *arg;
        !           150: {
        !           151:        struct clockframe *frame = arg;
        !           152:        u_int32_t oscr, nextmatch, oldmatch;
        !           153:        int s;
        !           154:
        !           155:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           156:                        SAOST_SR, 1);
        !           157:
        !           158:        /* schedule next clock intr */
        !           159:        oldmatch = saost_sc->sc_clock_count;
        !           160:        nextmatch = oldmatch + TIMER_FREQUENCY / hz;
        !           161:
        !           162:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0,
        !           163:                          nextmatch);
        !           164:        oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           165:                                SAOST_CR);
        !           166:
        !           167:        if ((nextmatch > oldmatch &&
        !           168:             (oscr > nextmatch || oscr < oldmatch)) ||
        !           169:            (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) {
        !           170:                /*
        !           171:                 * we couldn't set the matching register in time.
        !           172:                 * just set it to some value so that next interrupt happens.
        !           173:                 * XXX is it possible to compansate lost interrupts?
        !           174:                 */
        !           175:
        !           176:                s = splhigh();
        !           177:                oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           178:                                        SAOST_CR);
        !           179:                nextmatch = oscr + 10;
        !           180:                bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           181:                                  SAOST_MR0, nextmatch);
        !           182:                splx(s);
        !           183:        }
        !           184:
        !           185:        saost_sc->sc_clock_count = nextmatch;
        !           186:        hardclock(frame);
        !           187:
        !           188:        return(1);
        !           189: }
        !           190:
        !           191: static int
        !           192: statintr(arg)
        !           193:        void *arg;
        !           194: {
        !           195:        struct clockframe *frame = arg;
        !           196:        u_int32_t oscr, nextmatch, oldmatch;
        !           197:        int s;
        !           198:
        !           199:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           200:                        SAOST_SR, 2);
        !           201:
        !           202:        /* schedule next clock intr */
        !           203:        oldmatch = saost_sc->sc_statclock_count;
        !           204:        nextmatch = oldmatch + saost_sc->sc_statclock_step;
        !           205:
        !           206:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1,
        !           207:                          nextmatch);
        !           208:        oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           209:                                SAOST_CR);
        !           210:
        !           211:        if ((nextmatch > oldmatch &&
        !           212:             (oscr > nextmatch || oscr < oldmatch)) ||
        !           213:            (nextmatch < oldmatch && oscr > nextmatch && oscr < oldmatch)) {
        !           214:                /*
        !           215:                 * we couldn't set the matching register in time.
        !           216:                 * just set it to some value so that next interrupt happens.
        !           217:                 * XXX is it possible to compansate lost interrupts?
        !           218:                 */
        !           219:
        !           220:                s = splhigh();
        !           221:                oscr = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           222:                                        SAOST_CR);
        !           223:                nextmatch = oscr + 10;
        !           224:                bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           225:                                  SAOST_MR1, nextmatch);
        !           226:                splx(s);
        !           227:        }
        !           228:
        !           229:        saost_sc->sc_statclock_count = nextmatch;
        !           230:        statclock(frame);
        !           231:
        !           232:        return(1);
        !           233: }
        !           234:
        !           235:
        !           236: void
        !           237: setstatclockrate(hz)
        !           238:        int hz;
        !           239: {
        !           240:        u_int32_t count;
        !           241:
        !           242:        saost_sc->sc_statclock_step = TIMER_FREQUENCY / hz;
        !           243:        count = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR);
        !           244:        count += saost_sc->sc_statclock_step;
        !           245:        saost_sc->sc_statclock_count = count;
        !           246:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           247:                        SAOST_MR1, count);
        !           248: }
        !           249:
        !           250: void
        !           251: cpu_initclocks()
        !           252: {
        !           253:        stathz = STATHZ;
        !           254:        profhz = stathz;
        !           255:        saost_sc->sc_statclock_step = TIMER_FREQUENCY / stathz;
        !           256:
        !           257:        /* Use the channels 0 and 1 for hardclock and statclock, respectively */
        !           258:        saost_sc->sc_clock_count = TIMER_FREQUENCY / hz;
        !           259:        saost_sc->sc_statclock_count = TIMER_FREQUENCY / stathz;
        !           260:
        !           261:        sa11x0_intr_establish(0, 26, 1, IPL_CLOCK, clockintr, 0, "clock");
        !           262:        sa11x0_intr_establish(0, 27, 1, IPL_CLOCK, statintr, 0, "stat");
        !           263:
        !           264:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_SR, 0xf);
        !           265:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_IR, 3);
        !           266:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR0,
        !           267:                          saost_sc->sc_clock_count);
        !           268:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_MR1,
        !           269:                          saost_sc->sc_statclock_count);
        !           270:
        !           271:        /* Zero the counter value */
        !           272:        bus_space_write_4(saost_sc->sc_iot, saost_sc->sc_ioh, SAOST_CR, 0);
        !           273: }
        !           274:
        !           275: int
        !           276: gettick()
        !           277: {
        !           278:        int counter;
        !           279:        u_int savedints;
        !           280:        savedints = disable_interrupts(I32_bit);
        !           281:
        !           282:        counter = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           283:                        SAOST_CR);
        !           284:
        !           285:        restore_interrupts(savedints);
        !           286:        return counter;
        !           287: }
        !           288:
        !           289: void
        !           290: microtime(tvp)
        !           291:        register struct timeval *tvp;
        !           292: {
        !           293:        int s, tm, deltatm;
        !           294:        static struct timeval lasttime;
        !           295:
        !           296:        if(saost_sc == NULL) {
        !           297:                tvp->tv_sec = 0;
        !           298:                tvp->tv_usec = 0;
        !           299:                return;
        !           300:        }
        !           301:
        !           302:        s = splhigh();
        !           303:        tm = bus_space_read_4(saost_sc->sc_iot, saost_sc->sc_ioh,
        !           304:                        SAOST_CR);
        !           305:
        !           306:        deltatm = saost_sc->sc_clock_count - tm;
        !           307:
        !           308: #ifdef OST_DEBUG
        !           309:        printf("deltatm = %d\n",deltatm);
        !           310: #endif
        !           311:
        !           312:        *tvp = time;
        !           313:        tvp->tv_usec++;         /* XXX */
        !           314:        while (tvp->tv_usec >= 1000000) {
        !           315:                tvp->tv_sec++;
        !           316:                tvp->tv_usec -= 1000000;
        !           317:        }
        !           318:
        !           319:        if (tvp->tv_sec == lasttime.tv_sec &&
        !           320:                tvp->tv_usec <= lasttime.tv_usec &&
        !           321:                (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000)
        !           322:        {
        !           323:                tvp->tv_sec++;
        !           324:                tvp->tv_usec -= 1000000;
        !           325:        }
        !           326:        lasttime = *tvp;
        !           327:        splx(s);
        !           328: }
        !           329:
        !           330: void
        !           331: delay(usecs)
        !           332:        u_int usecs;
        !           333: {
        !           334:        u_int32_t tick, otick, delta;
        !           335:        int j, csec, usec;
        !           336:
        !           337:        csec = usecs / 10000;
        !           338:        usec = usecs % 10000;
        !           339:
        !           340:        usecs = (TIMER_FREQUENCY / 100) * csec
        !           341:            + (TIMER_FREQUENCY / 100) * usec / 10000;
        !           342:
        !           343:        if (! saost_sc) {
        !           344:                /* clock isn't initialized yet */
        !           345:                for(; usecs > 0; usecs--)
        !           346:                        for(j = 100; j > 0; j--)
        !           347:                                ;
        !           348:                return;
        !           349:        }
        !           350:
        !           351:        otick = gettick();
        !           352:
        !           353:        while (1) {
        !           354:                for(j = 100; j > 0; j--)
        !           355:                        ;
        !           356:                tick = gettick();
        !           357:                delta = tick - otick;
        !           358:                if (delta > usecs)
        !           359:                        break;
        !           360:                usecs -= delta;
        !           361:                otick = tick;
        !           362:        }
        !           363: }

CVSweb