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

Annotation of sys/arch/luna88k/dev/timekeeper.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: timekeeper.c,v 1.3 2004/08/18 13:29:46 aoyama Exp $ */
                      2: /* $NetBSD: timekeeper.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Tohru Nishimura.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/device.h>
                     43: #include <sys/kernel.h>
                     44: #include <sys/evcount.h>
                     45:
                     46: #include <machine/autoconf.h>
                     47: #include <machine/board.h>     /* machtype value */
                     48: #include <machine/cpu.h>
                     49:
                     50: #include <dev/clock_subr.h>
                     51:
                     52: #include <luna88k/luna88k/clockvar.h>
                     53: #include <luna88k/dev/timekeeper.h>
                     54:
                     55: #define        MK_YEAR0        1970    /* year offset of MK */
                     56: #define        DS_YEAR0        1990    /* year offset of DS */
                     57:
                     58: struct timekeeper_softc {
                     59:        struct device sc_dev;
                     60:        void *sc_clock, *sc_nvram;
                     61:        int sc_nvramsize;
                     62:        struct evcount sc_count;
                     63: };
                     64:
                     65: /*
                     66:  * BCD to decimal and decimal to BCD.
                     67:  */
                     68: #define FROMBCD(x)      (((x) >> 4) * 10 + ((x) & 0xf))
                     69: #define TOBCD(x)        (((x) / 10 * 16) + ((x) % 10))
                     70:
                     71: int  clock_match(struct device *, void *, void *);
                     72: void clock_attach(struct device *, struct device *, void *);
                     73:
                     74: struct cfattach clock_ca = {
                     75:        sizeof (struct timekeeper_softc), clock_match, clock_attach
                     76: };
                     77:
                     78: struct cfdriver clock_cd = {
                     79:         NULL, "clock", DV_DULL
                     80: };
                     81:
                     82: void mkclock_get(struct device *, time_t, struct clock_ymdhms *);
                     83: void mkclock_set(struct device *, struct clock_ymdhms *);
                     84: void dsclock_get(struct device *, time_t, struct clock_ymdhms *);
                     85: void dsclock_set(struct device *, struct clock_ymdhms *);
                     86:
                     87: const struct clockfns mkclock_clockfns = {
                     88:        NULL /* never used */, mkclock_get, mkclock_set,
                     89: };
                     90:
                     91: const struct clockfns dsclock_clockfns = {
                     92:        NULL /* never used */, dsclock_get, dsclock_set,
                     93: };
                     94:
                     95: int
                     96: clock_match(parent, match, aux)
                     97:         struct device *parent;
                     98:         void *match, *aux;
                     99: {
                    100:        struct mainbus_attach_args *ma = aux;
                    101:
                    102:        if (strcmp(ma->ma_name, clock_cd.cd_name))
                    103:                return 0;
                    104:        return 1;
                    105: }
                    106:
                    107: extern int machtype; /* in machdep.c */
                    108:
                    109: void
                    110: clock_attach(parent, self, aux)
                    111:         struct device *parent, *self;
                    112:         void *aux;
                    113: {
                    114:        struct timekeeper_softc *sc = (void *)self;
                    115:        struct mainbus_attach_args *ma = aux;
                    116:        const struct clockfns *clockwork;
                    117:
                    118:        switch (machtype) {
                    119:        default:
                    120:        case LUNA_88K:  /* Mostek MK48T02 */
                    121:                sc->sc_clock = (void *)(ma->ma_addr + 2040);
                    122:                sc->sc_nvram = (void *)ma->ma_addr;
                    123:                sc->sc_nvramsize = 2040;
                    124:                clockwork = &mkclock_clockfns;
                    125:                printf(": MK48T02\n");
                    126:                break;
                    127:        case LUNA_88K2: /* Dallas DS1397 */
                    128:                sc->sc_clock = (void *)ma->ma_addr;
                    129:                sc->sc_nvram = (void *)(ma->ma_addr + 50);
                    130:                sc->sc_nvramsize = 50;
                    131:                clockwork = &dsclock_clockfns;
                    132:                printf(": DS1397\n");
                    133:                break;
                    134:        }
                    135:
                    136:        evcount_attach(&sc->sc_count, self->dv_xname, (void *)&ma->ma_ilvl, &evcount_intr);
                    137:
                    138:        clockattach(&sc->sc_dev, clockwork, &sc->sc_count);
                    139: }
                    140:
                    141: /*
                    142:  * Get the time of day, based on the clock's value and/or the base value.
                    143:  */
                    144: void
                    145: mkclock_get(dev, base, dt)
                    146:        struct device *dev;
                    147:        time_t base;
                    148:        struct clock_ymdhms *dt;
                    149: {
                    150:        struct timekeeper_softc *sc = (void *)dev;
                    151:        volatile u_int8_t *chiptime = (void *)sc->sc_clock;
                    152:        int s;
                    153:
                    154:        s = splclock();
                    155:        chiptime[MK_CSR] |= MK_CSR_READ;        /* enable read (stop time) */
                    156:        dt->dt_sec = FROMBCD(chiptime[MK_SEC]);
                    157:        dt->dt_min = FROMBCD(chiptime[MK_MIN]);
                    158:        dt->dt_hour = FROMBCD(chiptime[MK_HOUR]);
                    159:        dt->dt_wday = FROMBCD(chiptime[MK_DOW]);
                    160:        dt->dt_day = FROMBCD(chiptime[MK_DOM]);
                    161:        dt->dt_mon = FROMBCD(chiptime[MK_MONTH]);
                    162:        dt->dt_year = FROMBCD(chiptime[MK_YEAR]) + MK_YEAR0;
                    163:        chiptime[MK_CSR] &= ~MK_CSR_READ;       /* time wears on */
                    164:        splx(s);
                    165: #ifdef TIMEKEEPER_DEBUG
                    166:        printf("get %d/%d/%d %d:%d:%d\n",
                    167:            dt->dt_year, dt->dt_mon, dt->dt_day,
                    168:            dt->dt_hour, dt->dt_min, dt->dt_sec);
                    169: #endif
                    170: }
                    171:
                    172: /*
                    173:  * Reset the TODR based on the time value.
                    174:  */
                    175: void
                    176: mkclock_set(dev, dt)
                    177:        struct device *dev;
                    178:        struct clock_ymdhms *dt;
                    179: {
                    180:        struct timekeeper_softc *sc = (void *)dev;
                    181:        volatile u_int8_t *chiptime = (void *)sc->sc_clock;
                    182:        volatile u_int8_t *stamp = (u_int8_t *)sc->sc_nvram + 0x10;
                    183:        int s;
                    184:
                    185:        s = splclock();
                    186:        chiptime[MK_CSR] |= MK_CSR_WRITE;       /* enable write */
                    187:        chiptime[MK_SEC] = TOBCD(dt->dt_sec);
                    188:        chiptime[MK_MIN] = TOBCD(dt->dt_min);
                    189:        chiptime[MK_HOUR] = TOBCD(dt->dt_hour);
                    190:        chiptime[MK_DOW] = TOBCD(dt->dt_wday);
                    191:        chiptime[MK_DOM] = TOBCD(dt->dt_day);
                    192:        chiptime[MK_MONTH] = TOBCD(dt->dt_mon);
                    193:        chiptime[MK_YEAR] = TOBCD(dt->dt_year - MK_YEAR0);
                    194:        chiptime[MK_CSR] &= ~MK_CSR_WRITE;      /* load them up */
                    195:        splx(s);
                    196: #ifdef TIMEKEEPER_DEBUG
                    197:        printf("set %d/%d/%d %d:%d:%d\n",
                    198:            dt->dt_year, dt->dt_mon, dt->dt_day,
                    199:            dt->dt_hour, dt->dt_min, dt->dt_sec);
                    200: #endif
                    201:
                    202:        stamp[0] = 'R'; stamp[1] = 'T'; stamp[2] = 'C'; stamp[3] = '\0';
                    203: }
                    204:
                    205: #define _DS_GET(off, data) \
                    206:        do { *chiptime = (off); (u_int8_t)(data) = (*chipdata); } while (0)
                    207: #define _DS_SET(off, data) \
                    208:        do { *chiptime = (off); *chipdata = (u_int8_t)(data); } while (0)
                    209: #define _DS_GET_BCD(off, data) \
                    210:        do { \
                    211:                u_int8_t c; \
                    212:                *chiptime = (off); \
                    213:                c = *chipdata; (u_int8_t)(data) = FROMBCD(c); \
                    214:        } while (0)
                    215: #define _DS_SET_BCD(off, data) \
                    216:        do { \
                    217:                *chiptime = (off); \
                    218:                *chipdata = TOBCD((u_int8_t)(data)); \
                    219:        } while (0)
                    220:
                    221: /*
                    222:  * Get the time of day, based on the clock's value and/or the base value.
                    223:  */
                    224: void
                    225: dsclock_get(dev, base, dt)
                    226:        struct device *dev;
                    227:        time_t base;
                    228:        struct clock_ymdhms *dt;
                    229: {
                    230:        struct timekeeper_softc *sc = (void *)dev;
                    231:        volatile u_int8_t *chiptime = (void *)sc->sc_clock;
                    232:        volatile u_int8_t *chipdata = (void *)(sc->sc_clock + 1);
                    233:        int s;
                    234:        u_int8_t c;
                    235:
                    236:        s = splclock();
                    237:
                    238:        /* specify 24hr and BCD mode */
                    239:        _DS_GET(DS_REGB, c);
                    240:        c |= DS_REGB_24HR;
                    241:        c &= ~DS_REGB_BINARY;
                    242:        _DS_SET(DS_REGB, c);
                    243:
                    244:        /* update in progress; spin loop */
                    245:        *chiptime = DS_REGA;
                    246:        while (*chipdata & DS_REGA_UIP)
                    247:                ;
                    248:
                    249:        _DS_GET_BCD(DS_SEC, dt->dt_sec);
                    250:        _DS_GET_BCD(DS_MIN, dt->dt_min);
                    251:        _DS_GET_BCD(DS_HOUR, dt->dt_hour);
                    252:        _DS_GET_BCD(DS_DOW, dt->dt_wday);
                    253:        _DS_GET_BCD(DS_DOM, dt->dt_day);
                    254:        _DS_GET_BCD(DS_MONTH, dt->dt_mon);
                    255:        _DS_GET_BCD(DS_YEAR, dt->dt_year);
                    256:        dt->dt_year += DS_YEAR0;
                    257:
                    258:        splx(s);
                    259:
                    260: #ifdef TIMEKEEPER_DEBUG
                    261:        printf("get %d/%d/%d %d:%d:%d\n",
                    262:            dt->dt_year, dt->dt_mon, dt->dt_day,
                    263:            dt->dt_hour, dt->dt_min, dt->dt_sec);
                    264: #endif
                    265: }
                    266:
                    267: /*
                    268:  * Reset the TODR based on the time value.
                    269:  */
                    270: void
                    271: dsclock_set(dev, dt)
                    272:        struct device *dev;
                    273:        struct clock_ymdhms *dt;
                    274: {
                    275:        struct timekeeper_softc *sc = (void *)dev;
                    276:        volatile u_int8_t *chiptime = (void *)sc->sc_clock;
                    277:        volatile u_int8_t *chipdata = (void *)(sc->sc_clock + 1);
                    278:        int s;
                    279:        u_int8_t c;
                    280:
                    281:        s = splclock();
                    282:
                    283:        /* enable write */
                    284:        _DS_GET(DS_REGB, c);
                    285:        c |= DS_REGB_SET;
                    286:        _DS_SET(DS_REGB, c);
                    287:
                    288:        _DS_SET_BCD(DS_SEC, dt->dt_sec);
                    289:        _DS_SET_BCD(DS_MIN, dt->dt_min);
                    290:        _DS_SET_BCD(DS_HOUR, dt->dt_hour);
                    291:        _DS_SET_BCD(DS_DOW, dt->dt_wday);
                    292:        _DS_SET_BCD(DS_DOM, dt->dt_day);
                    293:        _DS_SET_BCD(DS_MONTH, dt->dt_mon);
                    294:        _DS_SET_BCD(DS_YEAR, dt->dt_year - DS_YEAR0);
                    295:
                    296:        _DS_GET(DS_REGB, c);
                    297:        c &= ~DS_REGB_SET;
                    298:        _DS_SET(DS_REGB, c);
                    299:
                    300:        splx(s);
                    301:
                    302: #ifdef TIMEKEEPER_DEBUG
                    303:        printf("set %d/%d/%d %d:%d:%d\n",
                    304:            dt->dt_year, dt->dt_mon, dt->dt_day,
                    305:            dt->dt_hour, dt->dt_min, dt->dt_sec);
                    306: #endif
                    307: }

CVSweb