[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

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