[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     ! 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