The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/iicbus/ds1307.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2015 Luiz Otavio O Souza <loos@FreeBSD.org>
    3  * Copyright (c) 2022 Mathew McBride <matt@traverse.com.au>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 /*
   32  * Driver for Maxim DS1307 I2C real-time clock/calendar.
   33  */
   34 
   35 #include "opt_platform.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/bus.h>
   40 #include <sys/clock.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/sysctl.h>
   44 
   45 #include <dev/iicbus/iicbus.h>
   46 #include <dev/iicbus/iiconf.h>
   47 #ifdef FDT
   48 #include <dev/ofw/openfirm.h>
   49 #include <dev/ofw/ofw_bus.h>
   50 #include <dev/ofw/ofw_bus_subr.h>
   51 #endif
   52 
   53 #include <dev/iicbus/ds1307reg.h>
   54 
   55 #include "clock_if.h"
   56 #include "iicbus_if.h"
   57 
   58 enum {
   59         TYPE_DS1307,
   60         TYPE_MAXIM1307,
   61         TYPE_MICROCHIP_MCP7491X,
   62         TYPE_EPSON_RX8035,
   63         TYPE_COUNT
   64 };
   65 
   66 struct ds1307_softc {
   67         device_t                        sc_dev;
   68         struct intr_config_hook         enum_hook;
   69         uint32_t                        chiptype;
   70         uint8_t                         sc_ctrl;
   71         bool                            sc_use_ampm;
   72 };
   73 
   74 static void ds1307_start(void *);
   75 
   76 #ifdef FDT
   77 static const struct ofw_compat_data ds1307_compat_data[] = {
   78         {"dallas,ds1307",               TYPE_DS1307},
   79         {"maxim,ds1307",                TYPE_MAXIM1307},
   80         {"microchip,mcp7941x",          TYPE_MICROCHIP_MCP7491X},
   81         {"epson,rx8035",                TYPE_EPSON_RX8035},
   82         { NULL, 0 }
   83 };
   84 #endif
   85 
   86 static int
   87 ds1307_read1(device_t dev, uint8_t reg, uint8_t *data)
   88 {
   89 
   90         return (iicdev_readfrom(dev, reg, data, 1, IIC_INTRWAIT));
   91 }
   92 
   93 static int
   94 ds1307_write1(device_t dev, uint8_t reg, uint8_t data)
   95 {
   96 
   97         return (iicdev_writeto(dev, reg, &data, 1, IIC_INTRWAIT));
   98 }
   99 
  100 static int
  101 ds1307_ctrl_read(struct ds1307_softc *sc)
  102 {
  103         int error;
  104 
  105         sc->sc_ctrl = 0;
  106         error = ds1307_read1(sc->sc_dev, DS1307_CONTROL, &sc->sc_ctrl);
  107         if (error) {
  108                 device_printf(sc->sc_dev, "%s: cannot read from RTC: %d\n",
  109                     __func__, error);
  110                 return (error);
  111         }
  112 
  113         return (0);
  114 }
  115 
  116 static int
  117 ds1307_ctrl_write(struct ds1307_softc *sc)
  118 {
  119         int error;
  120         uint8_t ctrl;
  121 
  122         ctrl = sc->sc_ctrl & DS1307_CTRL_MASK;
  123         error = ds1307_write1(sc->sc_dev, DS1307_CONTROL, ctrl);
  124         if (error != 0)
  125                 device_printf(sc->sc_dev, "%s: cannot write to RTC: %d\n",
  126                     __func__, error);
  127 
  128         return (error);
  129 }
  130 
  131 static int
  132 ds1307_sqwe_sysctl(SYSCTL_HANDLER_ARGS)
  133 {
  134         int sqwe, error, newv, sqwe_bit;
  135         struct ds1307_softc *sc;
  136 
  137         sc = (struct ds1307_softc *)arg1;
  138         error = ds1307_ctrl_read(sc);
  139         if (error != 0)
  140                 return (error);
  141         if (sc->chiptype == TYPE_MICROCHIP_MCP7491X)
  142                 sqwe_bit = MCP7941X_CTRL_SQWE;
  143         else
  144                 sqwe_bit = DS1307_CTRL_SQWE;
  145         sqwe = newv = (sc->sc_ctrl & sqwe_bit) ? 1 : 0;
  146         error = sysctl_handle_int(oidp, &newv, 0, req);
  147         if (error != 0 || req->newptr == NULL)
  148                 return (error);
  149         if (sqwe != newv) {
  150                 sc->sc_ctrl &= ~sqwe_bit;
  151                 if (newv)
  152                         sc->sc_ctrl |= sqwe_bit;
  153                 error = ds1307_ctrl_write(sc);
  154                 if (error != 0)
  155                         return (error);
  156         }
  157 
  158         return (error);
  159 }
  160 
  161 static int
  162 ds1307_sqw_freq_sysctl(SYSCTL_HANDLER_ARGS)
  163 {
  164         int ds1307_sqw_freq[] = { 1, 4096, 8192, 32768 };
  165         int error, freq, i, newf, tmp;
  166         struct ds1307_softc *sc;
  167 
  168         sc = (struct ds1307_softc *)arg1;
  169         error = ds1307_ctrl_read(sc);
  170         if (error != 0)
  171                 return (error);
  172         tmp = (sc->sc_ctrl & DS1307_CTRL_RS_MASK);
  173         if (tmp >= nitems(ds1307_sqw_freq))
  174                 tmp = nitems(ds1307_sqw_freq) - 1;
  175         freq = ds1307_sqw_freq[tmp];
  176         error = sysctl_handle_int(oidp, &freq, 0, req);
  177         if (error != 0 || req->newptr == NULL)
  178                 return (error);
  179         if (freq != ds1307_sqw_freq[tmp]) {
  180                 newf = 0;
  181                 for (i = 0; i < nitems(ds1307_sqw_freq); i++)
  182                         if (freq >= ds1307_sqw_freq[i])
  183                                 newf = i;
  184                 sc->sc_ctrl &= ~DS1307_CTRL_RS_MASK;
  185                 sc->sc_ctrl |= newf;
  186                 error = ds1307_ctrl_write(sc);
  187                 if (error != 0)
  188                         return (error);
  189         }
  190 
  191         return (error);
  192 }
  193 
  194 static int
  195 ds1307_sqw_out_sysctl(SYSCTL_HANDLER_ARGS)
  196 {
  197         int sqwe, error, newv;
  198         struct ds1307_softc *sc;
  199 
  200         sc = (struct ds1307_softc *)arg1;
  201         error = ds1307_ctrl_read(sc);
  202         if (error != 0)
  203                 return (error);
  204         sqwe = newv = (sc->sc_ctrl & DS1307_CTRL_OUT) ? 1 : 0;
  205         error = sysctl_handle_int(oidp, &newv, 0, req);
  206         if (error != 0 || req->newptr == NULL)
  207                 return (error);
  208         if (sqwe != newv) {
  209                 sc->sc_ctrl &= ~DS1307_CTRL_OUT;
  210                 if (newv)
  211                         sc->sc_ctrl |= DS1307_CTRL_OUT;
  212                 error = ds1307_ctrl_write(sc);
  213                 if (error != 0)
  214                         return (error);
  215         }
  216 
  217         return (error);
  218 }
  219 
  220 static int
  221 ds1307_probe(device_t dev)
  222 {
  223 #ifdef FDT
  224         const struct ofw_compat_data *compat;
  225 
  226         if (!ofw_bus_status_okay(dev))
  227                 return (ENXIO);
  228 
  229         compat = ofw_bus_search_compatible(dev, ds1307_compat_data);
  230         if (compat->ocd_str == NULL)
  231                 return (ENXIO);
  232 
  233         switch(compat->ocd_data) {
  234                 case TYPE_DS1307:
  235                         device_set_desc(dev, "Dallas DS1307");
  236                         break;
  237                 case TYPE_MAXIM1307:
  238                         device_set_desc(dev, "Maxim DS1307");
  239                         break;
  240                 case TYPE_MICROCHIP_MCP7491X:
  241                         device_set_desc(dev, "Microchip MCP7491X");
  242                         break;
  243                 case TYPE_EPSON_RX8035:
  244                         device_set_desc(dev, "Epson RX-8035");
  245                         break;
  246                 default:
  247                         device_set_desc(dev, "Unknown DS1307-like device");
  248                         break;
  249         }
  250         return (BUS_PROBE_DEFAULT);
  251 #endif
  252 
  253         device_set_desc(dev, "Maxim DS1307 RTC");
  254         return (BUS_PROBE_NOWILDCARD);
  255 }
  256 
  257 static int
  258 ds1307_attach(device_t dev)
  259 {
  260 #ifdef FDT
  261         const struct ofw_compat_data *compat;
  262 #endif
  263         struct ds1307_softc *sc;
  264 
  265         sc = device_get_softc(dev);
  266         sc->sc_dev = dev;
  267         sc->enum_hook.ich_func = ds1307_start;
  268         sc->enum_hook.ich_arg = dev;
  269 #ifdef FDT
  270         compat = ofw_bus_search_compatible(dev, ds1307_compat_data);
  271         sc->chiptype = compat->ocd_data;
  272         /* Unify the chiptypes to DS1307 where possible. */
  273         if (sc->chiptype == TYPE_MAXIM1307)
  274                 sc->chiptype = TYPE_DS1307;
  275 #else
  276         sc->chiptype = TYPE_DS1307;
  277 #endif
  278 
  279         /*
  280          * We have to wait until interrupts are enabled.  Usually I2C read
  281          * and write only works when the interrupts are available.
  282          */
  283         if (config_intrhook_establish(&sc->enum_hook) != 0)
  284                 return (ENOMEM);
  285 
  286         return (0);
  287 }
  288 
  289 static int
  290 ds1307_detach(device_t dev)
  291 {
  292 
  293         clock_unregister(dev);
  294         return (0);
  295 }
  296 
  297 static bool
  298 is_epson_time_valid(struct ds1307_softc *sc)
  299 {
  300         device_t dev;
  301         int error;
  302         uint8_t ctrl2;
  303 
  304         dev = sc->sc_dev;
  305 
  306         /*
  307          * The RX-8035 single register read is non-standard
  308          * Refer to section 8.9.5 of the RX-8035 application manual:
  309          * "I2C bus basic transfer format", under "Standard Read Method".
  310          * Basically, register to read goes into the top 4 bits.
  311          */
  312         error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
  313         if (error) {
  314                 device_printf(dev, "%s cannot read Control 2 register: %d\n",
  315                     __func__, error);
  316                 return (false);
  317         }
  318 
  319         if (ctrl2 & RX8035_CTRL_2_XSTP) {
  320                 device_printf(dev, "Oscillation stop detected (ctrl2=%#02x)\n",
  321                     ctrl2);
  322                 return (false);
  323         }
  324 
  325         /*
  326          * Power on reset (PON) generally implies oscillation stop,
  327          * but catch it as well to be sure.
  328          */
  329         if (ctrl2 & RX8035_CTRL_2_PON) {
  330                 device_printf(dev, "Power-on reset detected (ctrl2=%#02x)\n",
  331                     ctrl2);
  332                 return (false);
  333         }
  334 
  335         return (true);
  336 }
  337 
  338 static int
  339 mark_epson_time_valid(struct ds1307_softc *sc)
  340 {
  341         device_t dev;
  342         int error;
  343         uint8_t ctrl2;
  344         uint8_t control_mask;
  345 
  346         dev = sc->sc_dev;
  347 
  348         error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
  349         if (error) {
  350                 device_printf(dev, "%s cannot read Control 2 register: %d\n",
  351                     __func__, error);
  352                 return (false);
  353         }
  354 
  355         control_mask = (RX8035_CTRL_2_PON | RX8035_CTRL_2_XSTP | RX8035_CTRL_2_VDET);
  356         ctrl2 = ctrl2 & ~(control_mask);
  357 
  358         error = ds1307_write1(dev, (RX8035_CTRL_2 << 4), ctrl2);
  359         if (error) {
  360                 device_printf(dev, "%s cannot write to Control 2 register: %d\n",
  361                     __func__, error);
  362                 return (false);
  363         }
  364         return (true);
  365 }
  366 
  367 static bool is_dev_time_valid(struct ds1307_softc *sc)
  368 {
  369         device_t dev;
  370         int error;
  371         uint8_t osc_en;
  372         uint8_t secs;
  373 
  374         /* Epson RTCs have different control/status registers. */
  375         if (sc->chiptype == TYPE_EPSON_RX8035)
  376                 return (is_epson_time_valid(sc));
  377 
  378         dev = sc->sc_dev;
  379         /* Check if the oscillator is disabled. */
  380         error = ds1307_read1(dev, DS1307_SECS, &secs);
  381         if (error) {
  382                 device_printf(dev, "%s: cannot read from RTC: %d\n",
  383                     __func__, error);
  384                 return (false);
  385         }
  386 
  387         switch (sc->chiptype) {
  388         case TYPE_MICROCHIP_MCP7491X:
  389                 osc_en = 0x80;
  390                 break;
  391         default:
  392                 osc_en = 0x00;
  393                 break;
  394         }
  395         if (((secs & DS1307_SECS_CH) ^ osc_en) != 0)
  396                 return (false);
  397 
  398         return (true);
  399 }
  400 
  401 static void
  402 ds1307_start(void *xdev)
  403 {
  404         device_t dev;
  405         struct ds1307_softc *sc;
  406         struct sysctl_ctx_list *ctx;
  407         struct sysctl_oid *tree_node;
  408         struct sysctl_oid_list *tree;
  409 
  410         dev = (device_t)xdev;
  411         sc = device_get_softc(dev);
  412 
  413         config_intrhook_disestablish(&sc->enum_hook);
  414 
  415         if (!is_dev_time_valid(sc))
  416                 device_printf(dev,
  417                     "WARNING: RTC clock stopped, check the battery.\n");
  418 
  419         /*
  420          * Configuration parameters:
  421          * square wave output cannot be changed or inhibited on the RX-8035,
  422          * so don't present the sysctls there.
  423          */
  424         if (sc->chiptype == TYPE_EPSON_RX8035)
  425                 goto skip_sysctl;
  426 
  427         ctx = device_get_sysctl_ctx(dev);
  428         tree_node = device_get_sysctl_tree(dev);
  429         tree = SYSCTL_CHILDREN(tree_node);
  430 
  431         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqwe",
  432             CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
  433             ds1307_sqwe_sysctl, "IU", "DS1307 square-wave enable");
  434         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_freq",
  435             CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
  436             ds1307_sqw_freq_sysctl, "IU",
  437             "DS1307 square-wave output frequency");
  438         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_out",
  439             CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
  440             ds1307_sqw_out_sysctl, "IU", "DS1307 square-wave output state");
  441 skip_sysctl:
  442 
  443         /*
  444          * Register as a clock with 1 second resolution.  Schedule the
  445          * clock_settime() method to be called just after top-of-second;
  446          * resetting the time resets top-of-second in the hardware.
  447          */
  448         clock_register_flags(dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
  449         clock_schedule(dev, 1);
  450 }
  451 
  452 static int
  453 ds1307_gettime(device_t dev, struct timespec *ts)
  454 {
  455         struct bcd_clocktime bct;
  456         struct ds1307_softc *sc;
  457         int error;
  458         uint8_t data[7], hourmask, ampm_mode;
  459 
  460         sc = device_get_softc(dev);
  461         error = iicdev_readfrom(sc->sc_dev, DS1307_SECS, data, sizeof(data),
  462             IIC_INTRWAIT);
  463         if (error != 0) {
  464                 device_printf(dev, "%s: cannot read from RTC: %d\n",
  465                     __func__, error);
  466                 return (error);
  467         }
  468 
  469         if (!is_dev_time_valid(sc)) {
  470                 device_printf(dev, "Device time not valid.\n");
  471                 return (EINVAL);
  472         }
  473 
  474         /*
  475          * If the chip is in AM/PM mode remember that.
  476          * The EPSON uses a 1 to signify 24 hour mode, while the DS uses a 0,
  477          * in slighly different positions.
  478          */
  479         if (sc->chiptype == TYPE_EPSON_RX8035)
  480                 ampm_mode = !(data[DS1307_HOUR] & RX8035_HOUR_USE_24);
  481         else
  482                 ampm_mode = data[DS1307_HOUR] & DS1307_HOUR_USE_AMPM;
  483 
  484         if (ampm_mode) {
  485                 sc->sc_use_ampm = true;
  486                 hourmask = DS1307_HOUR_MASK_12HR;
  487         } else
  488                 hourmask = DS1307_HOUR_MASK_24HR;
  489 
  490         bct.nsec = 0;
  491         bct.ispm = (data[DS1307_HOUR] & DS1307_HOUR_IS_PM) != 0;
  492         bct.sec  = data[DS1307_SECS]  & DS1307_SECS_MASK;
  493         bct.min  = data[DS1307_MINS]  & DS1307_MINS_MASK;
  494         bct.hour = data[DS1307_HOUR]  & hourmask;
  495         bct.day  = data[DS1307_DATE]  & DS1307_DATE_MASK;
  496         bct.mon  = data[DS1307_MONTH] & DS1307_MONTH_MASK;
  497         bct.year = data[DS1307_YEAR]  & DS1307_YEAR_MASK;
  498 
  499         clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct); 
  500         return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm));
  501 }
  502 
  503 static int
  504 ds1307_settime(device_t dev, struct timespec *ts)
  505 {
  506         struct bcd_clocktime bct;
  507         struct ds1307_softc *sc;
  508         int error, year;
  509         uint8_t data[7];
  510         uint8_t pmflags;
  511 
  512         sc = device_get_softc(dev);
  513 
  514         /*
  515          * We request a timespec with no resolution-adjustment.  That also
  516          * disables utc adjustment, so apply that ourselves.
  517          */
  518         ts->tv_sec -= utc_offset();
  519         clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm);
  520         clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct);
  521 
  522         /*
  523          * If the chip is in AM/PM mode, adjust hour and set flags as needed.
  524          * The AM/PM bit polarity and position is different on the EPSON.
  525          */
  526         if (sc->sc_use_ampm) {
  527                 pmflags = (sc->chiptype != TYPE_EPSON_RX8035) ?
  528                                 DS1307_HOUR_USE_AMPM : 0;
  529                 if (bct.ispm)
  530                         pmflags |= DS1307_HOUR_IS_PM;
  531 
  532         } else if (sc->chiptype == TYPE_EPSON_RX8035)
  533                 pmflags = RX8035_HOUR_USE_24;
  534         else
  535                 pmflags = 0;
  536 
  537         data[DS1307_SECS]    = bct.sec;
  538         data[DS1307_MINS]    = bct.min;
  539         data[DS1307_HOUR]    = bct.hour | pmflags;
  540         data[DS1307_DATE]    = bct.day;
  541         data[DS1307_WEEKDAY] = bct.dow;
  542         data[DS1307_MONTH]   = bct.mon;
  543         data[DS1307_YEAR]    = bct.year & 0xff;
  544         if (sc->chiptype == TYPE_MICROCHIP_MCP7491X) {
  545                 data[DS1307_SECS] |= MCP7941X_SECS_ST;
  546                 data[DS1307_WEEKDAY] |= MCP7941X_WEEKDAY_VBATEN;
  547                 year = bcd2bin(bct.year >> 8) * 100 + bcd2bin(bct.year & 0xff);
  548                 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
  549                         data[DS1307_MONTH] |= MCP7941X_MONTH_LPYR;
  550         }
  551 
  552         /* Write the time back to RTC. */
  553         error = iicdev_writeto(sc->sc_dev, DS1307_SECS, data, sizeof(data),
  554             IIC_INTRWAIT);
  555         if (error != 0)
  556                 device_printf(dev, "%s: cannot write to RTC: %d\n",
  557                     __func__, error);
  558 
  559         if (sc->chiptype == TYPE_EPSON_RX8035)
  560                 error = mark_epson_time_valid(sc);
  561 
  562         return (error);
  563 }
  564 
  565 static device_method_t ds1307_methods[] = {
  566         DEVMETHOD(device_probe,         ds1307_probe),
  567         DEVMETHOD(device_attach,        ds1307_attach),
  568         DEVMETHOD(device_detach,        ds1307_detach),
  569 
  570         DEVMETHOD(clock_gettime,        ds1307_gettime),
  571         DEVMETHOD(clock_settime,        ds1307_settime),
  572 
  573         DEVMETHOD_END
  574 };
  575 
  576 static driver_t ds1307_driver = {
  577         "ds1307",
  578         ds1307_methods,
  579         sizeof(struct ds1307_softc),
  580 };
  581 
  582 DRIVER_MODULE(ds1307, iicbus, ds1307_driver, NULL, NULL);
  583 MODULE_VERSION(ds1307, 1);
  584 MODULE_DEPEND(ds1307, iicbus, 1, 1, 1);
  585 IICBUS_FDT_PNP_INFO(ds1307_compat_data);

Cache object: c97b3134d8415aba1e8e6b06b0446f72


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.