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/mk48txx/mk48txx.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) 2000 The NetBSD Foundation, Inc.
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to The NetBSD Foundation
    6  * by Paul Kranenburg.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *        This product includes software developed by the NetBSD
   19  *        Foundation, Inc. and its contributors.
   20  * 4. Neither the name of The NetBSD Foundation nor the names of its
   21  *    contributors may be used to endorse or promote products derived
   22  *    from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   27  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34  * POSSIBILITY OF SUCH DAMAGE.
   35  *
   36  *      $NetBSD: mk48txx.c,v 1.7 2001/04/08 17:05:10 tsutsui Exp $
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD: releng/5.4/sys/dev/mk48txx/mk48txx.c 135796 2004-09-25 20:53:44Z marius $");
   41 
   42 /*
   43  * Mostek MK48T02, MK48T08, MK48T59 time-of-day chip subroutines.
   44  */
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/bus.h>
   49 #include <sys/clock.h>
   50 #include <sys/malloc.h>
   51 
   52 #include <machine/bus.h>
   53 
   54 #include <dev/mk48txx/mk48txxreg.h>
   55 
   56 #include "clock_if.h"
   57 
   58 struct mk48txx_softc {
   59         bus_space_tag_t mk_bt;          /* bus tag & handle */
   60         bus_space_handle_t mk_bh;       /* */
   61         bus_size_t      mk_nvramsz;     /* Size of NVRAM on the chip */
   62         bus_size_t      mk_clkoffset;   /* Offset in NVRAM to clock bits */
   63         u_int           mk_year0;       /* What year is represented on the system
   64                                            by the chip's year counter at 0 */
   65 };
   66 
   67 int mk48txx_auto_century_adjust = 1;
   68 
   69 struct {
   70         const char *name;
   71         bus_size_t nvramsz;
   72         bus_size_t clkoff;
   73         int flags;
   74 #define MK48TXX_EXT_REGISTERS   1       /* Has extended register set */
   75 } mk48txx_models[] = {
   76         { "mk48t02", MK48T02_CLKSZ, MK48T02_CLKOFF, 0 },
   77         { "mk48t08", MK48T08_CLKSZ, MK48T08_CLKOFF, 0 },
   78         { "mk48t59", MK48T59_CLKSZ, MK48T59_CLKOFF, MK48TXX_EXT_REGISTERS },
   79 };
   80 
   81 int
   82 mk48txx_attach(device_t dev, bus_space_tag_t bt, bus_space_handle_t bh,
   83     const char *model, int year0)
   84 {
   85         struct mk48txx_softc *sc;
   86         bus_size_t clkoff = 0, nvramsz = 0;
   87         int i;
   88 
   89         device_printf(dev, "model %s", model);
   90         i = sizeof(mk48txx_models) / sizeof(mk48txx_models[0]);
   91         while (--i >= 0) {
   92                 if (strcmp(model, mk48txx_models[i].name) == 0) {
   93                         nvramsz = mk48txx_models[i].nvramsz;
   94                         clkoff = mk48txx_models[i].clkoff;
   95                         break;
   96                 }
   97         }
   98         if (i < 0) {
   99                 device_printf(dev, " (unsupported)\n");
  100                 return (ENXIO);
  101         }
  102         printf("\n");
  103 
  104         if ((mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS) &&
  105             (bus_space_read_1(bt, bh, clkoff + MK48TXX_FLAGS) &
  106             MK48TXX_FLAGS_BL)) {
  107                 device_printf(dev, "mk48txx_attach: battery low\n");
  108                 return (ENXIO);
  109         }
  110 
  111         sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
  112         sc->mk_bt = bt;
  113         sc->mk_bh = bh;
  114         sc->mk_nvramsz = nvramsz;
  115         sc->mk_clkoffset = clkoff;
  116         sc->mk_year0 = year0;
  117         device_set_softc(dev, sc);
  118         clock_register(dev, 1000000);   /* 1 second resolution. */
  119 
  120         return (0);
  121 }
  122 
  123 /*
  124  * Get time-of-day and convert to a `struct timespec'
  125  * Return 0 on success; an error number otherwise.
  126  */
  127 int
  128 mk48txx_gettime(device_t dev, struct timespec *ts)
  129 {
  130         struct mk48txx_softc *mk = device_get_softc(dev);
  131         bus_space_tag_t bt = mk->mk_bt;
  132         bus_space_handle_t bh = mk->mk_bh;
  133         bus_size_t clkoff = mk->mk_clkoffset;
  134         struct clocktime ct;
  135         int year;
  136         u_int8_t csr;
  137 
  138         /* enable read (stop time) */
  139         csr = bus_space_read_1(bt, bh, clkoff + MK48TXX_ICSR);
  140         csr |= MK48TXX_CSR_READ;
  141         bus_space_write_1(bt, bh, clkoff + MK48TXX_ICSR, csr);
  142 
  143 #define FROMREG(reg, mask)                                              \
  144         (bus_space_read_1(bt, bh, clkoff + (reg)) & (mask))
  145 
  146         ct.nsec = 0;
  147         ct.sec = FROMBCD(FROMREG(MK48TXX_ISEC, MK48TXX_SEC_MASK));
  148         ct.min = FROMBCD(FROMREG(MK48TXX_IMIN, MK48TXX_MIN_MASK));
  149         ct.hour = FROMBCD(FROMREG(MK48TXX_IHOUR, MK48TXX_HOUR_MASK));
  150         ct.day = FROMBCD(FROMREG(MK48TXX_IDAY, MK48TXX_DAY_MASK));
  151         /* Map dow from 1 - 7 to 0 - 6; FROMBCD() isn't necessary here. */
  152         ct.dow = FROMREG(MK48TXX_IWDAY, MK48TXX_WDAY_MASK) - 1;
  153         ct.mon = FROMBCD(FROMREG(MK48TXX_IMON, MK48TXX_MON_MASK));
  154         year = FROMBCD(FROMREG(MK48TXX_IYEAR, MK48TXX_YEAR_MASK));
  155 
  156         /*
  157          * XXX: At least the MK48T59 (probably all MK48Txx models with
  158          *      extended registers) has a century bit in the MK48TXX_IWDAY
  159          *      register which should be used here to make up the century
  160          *      when mk48txx_auto_century_adjust (which actually means
  161          *      manually adjust the century in the driver) is set to 0.
  162          *      Sun/Solaris doesn't use this bit (probably for backwards
  163          *      compatibility with Sun hardware equipped with older MK48Txx
  164          *      models) and at present this driver is only used on sparc64
  165          *      so not respecting the century bit doesn't really matter at
  166          *      the moment but generally this should be implemented.
  167          */
  168 
  169 #undef FROMREG
  170 
  171         year += mk->mk_year0;
  172         if (year < POSIX_BASE_YEAR && mk48txx_auto_century_adjust != 0)
  173                 year += 100;
  174 
  175         ct.year = year;
  176 
  177         /* time wears on */
  178         csr = bus_space_read_1(bt, bh, clkoff + MK48TXX_ICSR);
  179         csr &= ~MK48TXX_CSR_READ;
  180         bus_space_write_1(bt, bh, clkoff + MK48TXX_ICSR, csr);
  181 
  182         return (clock_ct_to_ts(&ct, ts));
  183 }
  184 
  185 /*
  186  * Set the time-of-day clock based on the value of the `struct timespec' arg.
  187  * Return 0 on success; an error number otherwise.
  188  */
  189 int
  190 mk48txx_settime(device_t dev, struct timespec *ts)
  191 {
  192         struct mk48txx_softc *mk = device_get_softc(dev);
  193         bus_space_tag_t bt = mk->mk_bt;
  194         bus_space_handle_t bh = mk->mk_bh;
  195         bus_size_t clkoff = mk->mk_clkoffset;
  196         struct clocktime ct;
  197         u_int8_t csr;
  198         int year;
  199 
  200         /* Accuracy is only one second. */
  201         if (ts->tv_nsec >= 500000000)
  202                 ts->tv_sec++;
  203         ts->tv_nsec = 0;
  204         clock_ts_to_ct(ts, &ct);
  205 
  206         year = ct.year - mk->mk_year0;
  207         if (year > 99 && mk48txx_auto_century_adjust != 0)
  208                 year -= 100;
  209 
  210         /* enable write */
  211         csr = bus_space_read_1(bt, bh, clkoff + MK48TXX_ICSR);
  212         csr |= MK48TXX_CSR_WRITE;
  213         bus_space_write_1(bt, bh, clkoff + MK48TXX_ICSR, csr);
  214 
  215 #define TOREG(reg, mask, val)                                           \
  216         (bus_space_write_1(bt, bh, clkoff + (reg),                      \
  217         (bus_space_read_1(bt, bh, clkoff + (reg)) & ~(mask)) |          \
  218         ((val) & (mask))))
  219 
  220         TOREG(MK48TXX_ISEC, MK48TXX_SEC_MASK, TOBCD(ct.sec));
  221         TOREG(MK48TXX_IMIN, MK48TXX_MIN_MASK, TOBCD(ct.min));
  222         TOREG(MK48TXX_IHOUR, MK48TXX_HOUR_MASK, TOBCD(ct.hour));
  223         /* Map dow from 0 - 6 to 1 - 7; TOBCD() isn't necessary here. */
  224         TOREG(MK48TXX_IWDAY, MK48TXX_WDAY_MASK, ct.dow + 1);
  225         TOREG(MK48TXX_IDAY, MK48TXX_DAY_MASK, TOBCD(ct.day));
  226         TOREG(MK48TXX_IMON, MK48TXX_MON_MASK, TOBCD(ct.mon));
  227         TOREG(MK48TXX_IYEAR, MK48TXX_YEAR_MASK, TOBCD(year));
  228 
  229         /*
  230          * XXX: Use the century bit for storing the century when
  231          *      mk48txx_auto_century_adjust is set to 0.
  232          */
  233 
  234 #undef TOREG
  235 
  236         /* load them up */
  237         csr = bus_space_read_1(bt, bh, clkoff + MK48TXX_ICSR);
  238         csr &= ~MK48TXX_CSR_WRITE;
  239         bus_space_write_1(bt, bh, clkoff + MK48TXX_ICSR, csr);
  240         return (0);
  241 }
  242 
  243 int
  244 mk48txx_get_nvram_size(device_t dev, bus_size_t *vp)
  245 {
  246         struct mk48txx_softc *mk;
  247 
  248         mk = device_get_softc(dev);
  249         *vp = mk->mk_nvramsz;
  250         return (0);
  251 }

Cache object: 17ea937b872fe0a92774a254446e0e37


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