[BACK]Return to rs5c372.c CVS log [TXT][DIR] Up to [local] / sys / dev / i2c

Annotation of sys/dev/i2c/rs5c372.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $NetBSD: rs5c372.c,v 1.5 2006/03/29 06:41:24 thorpej Exp $      */
                      2:
                      3: /*
                      4:  * Copyright (c) 2005 Kimihiro Nonaka
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     18:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     20:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     22:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     23:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     24:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     25:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/param.h>
                     30: #include <sys/systm.h>
                     31: #include <sys/device.h>
                     32: #include <sys/kernel.h>
                     33: #include <sys/fcntl.h>
                     34: #include <sys/uio.h>
                     35: #include <sys/conf.h>
                     36: #include <sys/event.h>
                     37:
                     38: #include <dev/clock_subr.h>
                     39:
                     40: #include <dev/i2c/i2cvar.h>
                     41:
                     42: /*
                     43:  * RS5C372[AB] Real-Time Clock
                     44:  */
                     45:
                     46: #define        RICOHRTC_ADDR           0x32    /* Fixed I2C Slave Address */
                     47:
                     48: #define RICOHRTC_SECONDS       0
                     49: #define RICOHRTC_MINUTES       1
                     50: #define RICOHRTC_HOURS         2
                     51: #define RICOHRTC_DAY           3
                     52: #define RICOHRTC_DATE          4
                     53: #define RICOHRTC_MONTH         5
                     54: #define RICOHRTC_YEAR          6
                     55: #define RICOHRTC_CLOCK_CORRECT 7
                     56: #define RICOHRTC_ALARMA_MIN    8
                     57: #define RICOHRTC_ALARMA_HOUR   9
                     58: #define RICOHRTC_ALARMA_DATE   10
                     59: #define RICOHRTC_ALARMB_MIN    11
                     60: #define RICOHRTC_ALARMB_HOUR   12
                     61: #define RICOHRTC_ALARMB_DATE   13
                     62: #define RICOHRTC_CONTROL1      14
                     63: #define RICOHRTC_CONTROL2      15
                     64: #define        RICOHRTC_NREGS          16
                     65: #define        RICOHRTC_NRTC_REGS      7
                     66:
                     67: /*
                     68:  * Bit definitions.
                     69:  */
                     70: #define        RICOHRTC_SECONDS_MASK   0x7f
                     71: #define        RICOHRTC_MINUTES_MASK   0x7f
                     72: #define        RICOHRTC_HOURS_12HRS_PM (1u << 5)       /* If 12 hr mode, set = PM */
                     73: #define        RICOHRTC_HOURS_12MASK   0x1f
                     74: #define        RICOHRTC_HOURS_24MASK   0x3f
                     75: #define        RICOHRTC_DAY_MASK       0x07
                     76: #define        RICOHRTC_DATE_MASK      0x3f
                     77: #define        RICOHRTC_MONTH_MASK     0x1f
                     78: #define        RICOHRTC_CONTROL2_24HRS (1u << 5)
                     79: #define        RICOHRTC_CONTROL2_XSTP  (1u << 4)       /* read */
                     80: #define        RICOHRTC_CONTROL2_ADJ   (1u << 4)       /* write */
                     81: #define        RICOHRTC_CONTROL2_NCLEN (1u << 3)
                     82: #define        RICOHRTC_CONTROL2_CTFG  (1u << 2)
                     83: #define        RICOHRTC_CONTROL2_AAFG  (1u << 1)
                     84: #define        RICOHRTC_CONTROL2_BAFG  (1u << 0)
                     85:
                     86: struct ricohrtc_softc {
                     87:        struct device sc_dev;
                     88:        i2c_tag_t sc_tag;
                     89:        int sc_address;
                     90:        struct todr_chip_handle sc_todr;
                     91: };
                     92:
                     93: int ricohrtc_match(struct device *, void *, void *);
                     94: void ricohrtc_attach(struct device *, struct device *, void *);
                     95:
                     96: struct cfattach ricohrtc_ca = {
                     97:        sizeof(struct ricohrtc_softc), ricohrtc_match, ricohrtc_attach
                     98: };
                     99:
                    100: struct cfdriver ricohrtc_cd = {
                    101:        NULL, "ricohrtc", DV_DULL
                    102: };
                    103:
                    104: void ricohrtc_reg_write(struct ricohrtc_softc *, int, uint8_t);
                    105: int ricohrtc_clock_read(struct ricohrtc_softc *, struct clock_ymdhms *);
                    106: int ricohrtc_clock_write(struct ricohrtc_softc *, struct clock_ymdhms *);
                    107: int ricohrtc_gettime(struct todr_chip_handle *, struct timeval *);
                    108: int ricohrtc_settime(struct todr_chip_handle *, struct timeval *);
                    109: int ricohrtc_getcal(struct todr_chip_handle *, int *);
                    110: int ricohrtc_setcal(struct todr_chip_handle *, int);
                    111:
                    112: int
                    113: ricohrtc_match(struct device *parent, void *v, void *arg)
                    114: {
                    115:        struct i2c_attach_args *ia = arg;
                    116: #ifdef PARANOID_CHECKS
                    117:        u_int8_t data, cmd;
                    118: #endif
                    119:
                    120:        if (ia->ia_addr != RICOHRTC_ADDR)
                    121:                return (0);
                    122:
                    123: #ifdef PARANOID_CHECKS
                    124:        /* Verify that the 'reserved bits in a few registers read 0 */
                    125:        if (iic_acquire_bus(ia->ia_tag, I2C_F_POLL)) {
                    126:                printf("ricohrtc acquire fail\n");
                    127:                return (0);
                    128:        }
                    129:
                    130:        cmd = RICOHRTC_SECONDS;
                    131:        if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
                    132:            &cmd, 1, &data, 1, I2C_F_POLL)) {
                    133:                iic_release_bus(ia->ia_tag, I2C_F_POLL);
                    134:                printf("ricohrtc read %d fail\n", cmd);
                    135:                return (0);
                    136:        }
                    137:        if ((data & ~RICOHRTC_SECONDS_MASK) != 0) {
                    138:                printf("ricohrtc second %d\n",data);
                    139:                return (0);
                    140:        }
                    141:
                    142:        cmd = RICOHRTC_MINUTES;
                    143:        if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
                    144:            &cmd, 1, &data, 1, I2C_F_POLL)) {
                    145:                iic_release_bus(ia->ia_tag, I2C_F_POLL);
                    146:                printf("ricohrtc read %d fail\n", cmd);
                    147:                return (0);
                    148:        }
                    149:
                    150:        if ((data & ~RICOHRTC_MINUTES_MASK) != 0) {
                    151:                printf("ricohrtc minute %d\n",data);
                    152:                return (0);
                    153:        }
                    154:
                    155:        cmd = RICOHRTC_HOURS;
                    156:        if (iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
                    157:            &cmd, 1, &data, 1, I2C_F_POLL)) {
                    158:                iic_release_bus(ia->ia_tag, I2C_F_POLL);
                    159:                printf("ricohrtc read %d fail\n", cmd);
                    160:                return (0);
                    161:        }
                    162:        if ((data & ~RICOHRTC_HOURS_24MASK) != 0) {
                    163:                printf("ricohrtc hour %d\n",data);
                    164:                return (0);
                    165:        }
                    166: #endif
                    167:
                    168:        iic_release_bus(ia->ia_tag, I2C_F_POLL);
                    169:        return (1);
                    170: }
                    171:
                    172: void
                    173: ricohrtc_attach(struct device *parent, struct device *self, void *arg)
                    174: {
                    175:        struct ricohrtc_softc *sc = (struct ricohrtc_softc *)self;
                    176:        struct i2c_attach_args *ia = arg;
                    177:
                    178:        printf(": RICOH RS5C372[AB] Real-time Clock\n");
                    179:
                    180:        sc->sc_tag = ia->ia_tag;
                    181:        sc->sc_address = ia->ia_addr;
                    182:        sc->sc_todr.cookie = sc;
                    183:        sc->sc_todr.todr_gettime = ricohrtc_gettime;
                    184:        sc->sc_todr.todr_settime = ricohrtc_settime;
                    185:        sc->sc_todr.todr_getcal = ricohrtc_getcal;
                    186:        sc->sc_todr.todr_setcal = ricohrtc_setcal;
                    187:        sc->sc_todr.todr_setwen = NULL;
                    188:
                    189: #if 0
                    190:        todr_attach(&sc->sc_todr);
                    191: #else
                    192:        /* XXX */
                    193:        {
                    194:        extern todr_chip_handle_t todr_handle;
                    195:        todr_handle = &sc->sc_todr;
                    196:        }
                    197: #endif
                    198:
                    199:        /* Initialize RTC */
                    200:        ricohrtc_reg_write(sc, RICOHRTC_CONTROL2, RICOHRTC_CONTROL2_24HRS);
                    201:        ricohrtc_reg_write(sc, RICOHRTC_CONTROL1, 0);
                    202: }
                    203:
                    204: int
                    205: ricohrtc_gettime(struct todr_chip_handle *ch, struct timeval *tv)
                    206: {
                    207:        struct ricohrtc_softc *sc = ch->cookie;
                    208:        struct clock_ymdhms dt;
                    209:
                    210:        memset(&dt, 0, sizeof(dt));
                    211:        if (ricohrtc_clock_read(sc, &dt) == 0)
                    212:                return (-1);
                    213:
                    214:        tv->tv_sec = clock_ymdhms_to_secs(&dt);
                    215:        tv->tv_usec = 0;
                    216:        return (0);
                    217: }
                    218:
                    219: int
                    220: ricohrtc_settime(struct todr_chip_handle *ch, struct timeval *tv)
                    221: {
                    222:        struct ricohrtc_softc *sc = ch->cookie;
                    223:        struct clock_ymdhms dt;
                    224:
                    225:        clock_secs_to_ymdhms(tv->tv_sec, &dt);
                    226:
                    227:        if (ricohrtc_clock_write(sc, &dt) == 0)
                    228:                return (-1);
                    229:        return (0);
                    230: }
                    231:
                    232: int
                    233: ricohrtc_setcal(struct todr_chip_handle *ch, int cal)
                    234: {
                    235:
                    236:        return (EOPNOTSUPP);
                    237: }
                    238:
                    239: int
                    240: ricohrtc_getcal(struct todr_chip_handle *ch, int *cal)
                    241: {
                    242:
                    243:        return (EOPNOTSUPP);
                    244: }
                    245:
                    246: void
                    247: ricohrtc_reg_write(struct ricohrtc_softc *sc, int reg, uint8_t val)
                    248: {
                    249:        uint8_t cmd;
                    250:
                    251:        iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
                    252:        reg &= 0xf;
                    253:        cmd = (reg << 4);
                    254:        if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
                    255:            &cmd, 1, &val, 1, I2C_F_POLL)) {
                    256:                iic_release_bus(sc->sc_tag, I2C_F_POLL);
                    257:                printf("%s: ricohrtc_reg_write: failed to write reg%d\n",
                    258:                    sc->sc_dev.dv_xname, reg);
                    259:                return;
                    260:        }
                    261:        iic_release_bus(sc->sc_tag, I2C_F_POLL);
                    262: }
                    263:
                    264: int
                    265: ricohrtc_clock_read(struct ricohrtc_softc *sc, struct clock_ymdhms *dt)
                    266: {
                    267:        uint8_t bcd[RICOHRTC_NRTC_REGS];
                    268:        uint8_t cmd;
                    269:
                    270:        iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
                    271:        cmd = (RICOHRTC_SECONDS << 4);
                    272:        if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address,
                    273:            &cmd, 1, bcd, RICOHRTC_NRTC_REGS, I2C_F_POLL)) {
                    274:                iic_release_bus(sc->sc_tag, I2C_F_POLL);
                    275:                printf("%s: ricohrtc_clock_read: failed to read rtc\n",
                    276:                    sc->sc_dev.dv_xname);
                    277:                return (0);
                    278:        }
                    279:        iic_release_bus(sc->sc_tag, I2C_F_POLL);
                    280:
                    281:        /*
                    282:         * Convert the RICOHRTC's register values into something useable
                    283:         */
                    284:        dt->dt_sec = FROMBCD(bcd[RICOHRTC_SECONDS] & RICOHRTC_SECONDS_MASK);
                    285:        dt->dt_min = FROMBCD(bcd[RICOHRTC_MINUTES] & RICOHRTC_MINUTES_MASK);
                    286:        dt->dt_hour = FROMBCD(bcd[RICOHRTC_HOURS] & RICOHRTC_HOURS_24MASK);
                    287:        dt->dt_day = FROMBCD(bcd[RICOHRTC_DATE] & RICOHRTC_DATE_MASK);
                    288:        dt->dt_mon = FROMBCD(bcd[RICOHRTC_MONTH] & RICOHRTC_MONTH_MASK);
                    289:        dt->dt_year = FROMBCD(bcd[RICOHRTC_YEAR]) + POSIX_BASE_YEAR;
                    290:        return (1);
                    291: }
                    292:
                    293: int
                    294: ricohrtc_clock_write(struct ricohrtc_softc *sc, struct clock_ymdhms *dt)
                    295: {
                    296:        uint8_t bcd[RICOHRTC_NRTC_REGS];
                    297:        uint8_t cmd;
                    298:
                    299:        /*
                    300:         * Convert our time representation into something the RICOHRTC
                    301:         * can understand.
                    302:         */
                    303:        bcd[RICOHRTC_SECONDS] = TOBCD(dt->dt_sec);
                    304:        bcd[RICOHRTC_MINUTES] = TOBCD(dt->dt_min);
                    305:        bcd[RICOHRTC_HOURS] = TOBCD(dt->dt_hour);
                    306:        bcd[RICOHRTC_DATE] = TOBCD(dt->dt_day);
                    307:        bcd[RICOHRTC_DAY] = TOBCD(dt->dt_wday);
                    308:        bcd[RICOHRTC_MONTH] = TOBCD(dt->dt_mon);
                    309:        bcd[RICOHRTC_YEAR] = TOBCD(dt->dt_year - POSIX_BASE_YEAR);
                    310:
                    311:        iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
                    312:        cmd = (RICOHRTC_SECONDS << 4);
                    313:        if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
                    314:            &cmd, 1, bcd, RICOHRTC_NRTC_REGS, I2C_F_POLL)) {
                    315:                iic_release_bus(sc->sc_tag, I2C_F_POLL);
                    316:                printf("%s: ricohrtc_clock_write: failed to write rtc\n",
                    317:                    sc->sc_dev.dv_xname);
                    318:                return (0);
                    319:        }
                    320:        iic_release_bus(sc->sc_tag, I2C_F_POLL);
                    321:        return (1);
                    322: }

CVSweb