root/dev/i2c/rs5c372.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ricohrtc_match
  2. ricohrtc_attach
  3. ricohrtc_gettime
  4. ricohrtc_settime
  5. ricohrtc_setcal
  6. ricohrtc_getcal
  7. ricohrtc_reg_write
  8. ricohrtc_clock_read
  9. ricohrtc_clock_write

    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 }

/* [<][>][^][v][top][bottom][index][help] */