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

Annotation of sys/arch/sparc64/dev/rtc.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: rtc.c,v 1.3 2007/04/24 18:30:45 kettenis Exp $        */
                      2:
                      3: /*
                      4:  * Copyright (c) 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  * Copyright (c) 1994 Gordon W. Ross
                      7:  * Copyright (c) 1993 Adam Glass
                      8:  * Copyright (c) 1996 Paul Kranenburg
                      9:  * Copyright (c) 1996
                     10:  *     The President and Fellows of Harvard College. All rights reserved.
                     11:  *
                     12:  * This software was developed by the Computer Systems Engineering group
                     13:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     14:  * contributed to Berkeley.
                     15:  *
                     16:  * All advertising materials mentioning features or use of this software
                     17:  * must display the following acknowledgement:
                     18:  *     This product includes software developed by Harvard University.
                     19:  *     This product includes software developed by the University of
                     20:  *     California, Lawrence Berkeley Laboratory.
                     21:  *
                     22:  * Redistribution and use in source and binary forms, with or without
                     23:  * modification, are permitted provided that the following conditions
                     24:  * are met:
                     25:  *
                     26:  * 1. Redistributions of source code must retain the above copyright
                     27:  *    notice, this list of conditions and the following disclaimer.
                     28:  * 2. Redistributions in binary form must reproduce the above copyright
                     29:  *    notice, this list of conditions and the following disclaimer in the
                     30:  *    documentation and/or other materials provided with the distribution.
                     31:  * 3. All advertising materials mentioning features or use of this software
                     32:  *    must display the following acknowledgement:
                     33:  *     This product includes software developed by the University of
                     34:  *     California, Berkeley and its contributors.
                     35:  *     This product includes software developed by Paul Kranenburg.
                     36:  *     This product includes software developed by Harvard University.
                     37:  * 4. Neither the name of the University nor the names of its contributors
                     38:  *    may be used to endorse or promote products derived from this software
                     39:  *    without specific prior written permission.
                     40:  *
                     41:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     42:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     43:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     44:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     45:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     46:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     47:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     48:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     49:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     50:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     51:  * SUCH DAMAGE.
                     52:  *
                     53:  */
                     54:
                     55: /*
                     56:  * Driver for rtc device on Blade 1000, Fire V210, etc.
                     57:  */
                     58:
                     59: #include <sys/param.h>
                     60: #include <sys/kernel.h>
                     61: #include <sys/device.h>
                     62: #include <sys/malloc.h>
                     63: #include <sys/proc.h>
                     64: #include <sys/signalvar.h>
                     65: #include <sys/systm.h>
                     66:
                     67: #include <machine/bus.h>
                     68: #include <machine/autoconf.h>
                     69:
                     70: #include <dev/clock_subr.h>
                     71: #include <dev/ic/mc146818reg.h>
                     72:
                     73: #include <sparc64/dev/ebusreg.h>
                     74: #include <sparc64/dev/ebusvar.h>
                     75:
                     76: extern todr_chip_handle_t todr_handle;
                     77:
                     78: struct rtc_softc {
                     79:        struct device           sc_dv;
                     80:        bus_space_tag_t         sc_iot;
                     81:        bus_space_handle_t      sc_ioh;
                     82:        struct intrhand         *sc_ih;
                     83: };
                     84:
                     85: int    rtc_match(struct device *, void *, void *);
                     86: void   rtc_attach(struct device *, struct device *, void *);
                     87:
                     88: struct cfattach rtc_ca = {
                     89:        sizeof(struct rtc_softc), rtc_match, rtc_attach
                     90: };
                     91:
                     92: struct cfdriver rtc_cd = {
                     93:        NULL, "rtc", DV_DULL
                     94: };
                     95:
                     96: int rtc_intr(void *arg);
                     97:
                     98: u_int8_t rtc_read_reg(struct rtc_softc *, bus_size_t);
                     99: void rtc_write_reg(struct rtc_softc *sc, bus_size_t, u_int8_t);
                    100:
                    101: int rtc_gettime(todr_chip_handle_t, struct timeval *);
                    102: int rtc_settime(todr_chip_handle_t, struct timeval *);
                    103: int rtc_getcal(todr_chip_handle_t, int *);
                    104: int rtc_setcal(todr_chip_handle_t, int);
                    105:
                    106: int
                    107: rtc_match(struct device *parent, void *cf, void *aux)
                    108: {
                    109:        struct ebus_attach_args *ea = aux;
                    110:
                    111:        if (strcmp("rtc", ea->ea_name) == 0)
                    112:                return (1);
                    113:        return (0);
                    114: }
                    115:
                    116: void
                    117: rtc_attach(struct device *parent, struct device *self, void *aux)
                    118: {
                    119:        struct rtc_softc *sc = (void *)self;
                    120:        struct ebus_attach_args *ea = aux;
                    121:        todr_chip_handle_t handle;
                    122:        char *model;
                    123:
                    124:        if (ebus_bus_map(ea->ea_iotag, 0,
                    125:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
                    126:            ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
                    127:                sc->sc_iot = ea->ea_iotag;
                    128:        } else if (ebus_bus_map(ea->ea_memtag, 0,
                    129:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
                    130:            ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
                    131:                sc->sc_iot = ea->ea_memtag;
                    132:        } else {
                    133:                printf("%s: can't map register\n", self->dv_xname);
                    134:                return;
                    135:        }
                    136:
                    137:        model = getpropstring(ea->ea_node, "model");
                    138: #ifdef DIAGNOSTIC
                    139:        if (model == NULL)
                    140:                panic("rtc_attach: no model property");
                    141: #endif
                    142:        printf(": %s\n", model);
                    143:
                    144:        /* Setup our todr_handle */
                    145:        handle = malloc(sizeof(struct todr_chip_handle), M_DEVBUF, M_NOWAIT);
                    146:        if (handle == NULL)
                    147:                panic("couldn't allocate todr_handle");
                    148:        handle->cookie = sc;
                    149:        handle->todr_gettime = rtc_gettime;
                    150:        handle->todr_settime = rtc_settime;
                    151:        handle->todr_getcal = rtc_getcal;
                    152:        handle->todr_setcal = rtc_setcal;
                    153:
                    154:        handle->bus_cookie = NULL;
                    155:        handle->todr_setwen = NULL;
                    156:        todr_handle = handle;
                    157:
                    158:        /*
                    159:         * Turn interrupts off, just in case. (Although they shouldn't
                    160:         * be wired to an interrupt controller on sparcs).
                    161:         */
                    162:        rtc_write_reg(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
                    163:
                    164:        /*
                    165:         * On ds1287 models (which really are ns87317 chips), the
                    166:         * interrupt is wired to the powerbutton.
                    167:         */
                    168:        if(strcmp(model, "ds1287") == 0 && ea->ea_nintrs > 0) {
                    169:                sc->sc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0],
                    170:                    IPL_BIO, 0, rtc_intr, sc, self->dv_xname);
                    171:                if (sc->sc_ih == NULL) {
                    172:                        printf("%s: can't establush interrupt\n",
                    173:                            self->dv_xname);
                    174:                }
                    175:        }
                    176: }
                    177:
                    178: int
                    179: rtc_intr(void *arg)
                    180: {
                    181:        extern int kbd_reset;
                    182:
                    183:        if (kbd_reset == 1) {
                    184:                kbd_reset = 0;
                    185:                psignal(initproc, SIGUSR2);
                    186:        }
                    187:        return (1);
                    188: }
                    189:
                    190: /*
                    191:  * Register access is indirect, through an address and data port.
                    192:  */
                    193:
                    194: #define        RTC_ADDR        0
                    195: #define        RTC_DATA        1
                    196:
                    197: u_int8_t
                    198: rtc_read_reg(struct rtc_softc *sc, bus_size_t reg)
                    199: {
                    200:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg);
                    201:        return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, RTC_DATA));
                    202: }
                    203:
                    204: void
                    205: rtc_write_reg(struct rtc_softc *sc, bus_size_t reg, u_int8_t val)
                    206: {
                    207:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_ADDR, reg);
                    208:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_DATA, val);
                    209: }
                    210:
                    211: /*
                    212:  * RTC todr routines.
                    213:  */
                    214:
                    215: /*
                    216:  * Get time-of-day and convert to a `struct timeval'
                    217:  * Return 0 on success; an error number otherwise.
                    218:  */
                    219: int
                    220: rtc_gettime(todr_chip_handle_t handle, struct timeval *tv)
                    221: {
                    222:        struct rtc_softc *sc = handle->cookie;
                    223:        struct clock_ymdhms dt;
                    224:        int year;
                    225:        u_int8_t csr;
                    226:
                    227:        /* Stop updates. */
                    228:        csr = rtc_read_reg(sc, MC_REGB);
                    229:        csr |= MC_REGB_SET;
                    230:        rtc_write_reg(sc, MC_REGB, csr);
                    231:
                    232:        /* Read time */
                    233:        dt.dt_sec = rtc_read_reg(sc, MC_SEC);
                    234:        dt.dt_min = rtc_read_reg(sc, MC_MIN);
                    235:        dt.dt_hour = rtc_read_reg(sc, MC_HOUR);
                    236:        dt.dt_day = rtc_read_reg(sc, MC_DOM);
                    237:        dt.dt_wday = rtc_read_reg(sc, MC_DOW);
                    238:        dt.dt_mon = rtc_read_reg(sc, MC_MONTH);
                    239:        year = rtc_read_reg(sc, MC_YEAR);
                    240:
                    241:        if ((year += 1900) < POSIX_BASE_YEAR)
                    242:                year += 100;
                    243:
                    244:        dt.dt_year = year;
                    245:
                    246:        /* time wears on */
                    247:        csr = rtc_read_reg(sc, MC_REGB);
                    248:        csr &= ~MC_REGB_SET;
                    249:        rtc_write_reg(sc, MC_REGB, csr);
                    250:
                    251:        /* simple sanity checks */
                    252:        if (dt.dt_mon > 12 || dt.dt_day > 31 ||
                    253:            dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60)
                    254:                return (1);
                    255:
                    256:        tv->tv_sec = clock_ymdhms_to_secs(&dt);
                    257:        tv->tv_usec = 0;
                    258:        return (0);
                    259: }
                    260:
                    261: /*
                    262:  * Set the time-of-day clock based on the value of the `struct timeval' arg.
                    263:  * Return 0 on success; an error number otherwise.
                    264:  */
                    265: int
                    266: rtc_settime(todr_chip_handle_t handle, struct timeval *tv)
                    267: {
                    268:        struct rtc_softc *sc = handle->cookie;
                    269:        struct clock_ymdhms dt;
                    270:        u_int8_t csr;
                    271:        int year;
                    272:
                    273:        /* Note: we ignore `tv_usec' */
                    274:        clock_secs_to_ymdhms(tv->tv_sec, &dt);
                    275:
                    276:        year = dt.dt_year % 100;
                    277:
                    278:        /* enable write */
                    279:        csr = rtc_read_reg(sc, MC_REGB);
                    280:        csr |= MC_REGB_SET;
                    281:        rtc_write_reg(sc, MC_REGB, csr);
                    282:
                    283:        rtc_write_reg(sc, MC_SEC, dt.dt_sec);
                    284:        rtc_write_reg(sc, MC_MIN, dt.dt_min);
                    285:        rtc_write_reg(sc, MC_HOUR, dt.dt_hour);
                    286:        rtc_write_reg(sc, MC_DOW, dt.dt_wday);
                    287:        rtc_write_reg(sc, MC_DOM, dt.dt_day);
                    288:        rtc_write_reg(sc, MC_MONTH, dt.dt_mon);
                    289:        rtc_write_reg(sc, MC_YEAR, year);
                    290:
                    291:        /* load them up */
                    292:        csr = rtc_read_reg(sc, MC_REGB);
                    293:        csr &= ~MC_REGB_SET;
                    294:        rtc_write_reg(sc, MC_REGB, csr);
                    295:        return (0);
                    296: }
                    297:
                    298: int
                    299: rtc_getcal(todr_chip_handle_t handle, int *vp)
                    300: {
                    301:        return (EOPNOTSUPP);
                    302: }
                    303:
                    304: int
                    305: rtc_setcal(todr_chip_handle_t handle, int v)
                    306: {
                    307:        return (EOPNOTSUPP);
                    308: }

CVSweb