1 /* $NetBSD: mk48txx.c,v 1.22 2007/10/19 11:59:56 ad Exp $ */ 2 /*- 3 * Copyright (c) 2000 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Paul Kranenburg. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Mostek MK48T02, MK48T08, MK48T59 time-of-day chip subroutines. 40 */ 41 42 #include <sys/cdefs.h> 43 __KERNEL_RCSID(0, "$NetBSD: mk48txx.c,v 1.22 2007/10/19 11:59:56 ad Exp $"); 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/device.h> 48 #include <sys/errno.h> 49 50 #include <sys/bus.h> 51 #include <dev/clock_subr.h> 52 #include <dev/ic/mk48txxreg.h> 53 #include <dev/ic/mk48txxvar.h> 54 55 int mk48txx_gettime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *); 56 int mk48txx_settime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *); 57 uint8_t mk48txx_def_nvrd(struct mk48txx_softc *, int); 58 void mk48txx_def_nvwr(struct mk48txx_softc *, int, uint8_t); 59 60 struct { 61 const char *name; 62 bus_size_t nvramsz; 63 bus_size_t clkoff; 64 int flags; 65 #define MK48TXX_EXT_REGISTERS 1 /* Has extended register set */ 66 } mk48txx_models[] = { 67 { "mk48t02", MK48T02_CLKSZ, MK48T02_CLKOFF, 0 }, 68 { "mk48t08", MK48T08_CLKSZ, MK48T08_CLKOFF, 0 }, 69 { "mk48t18", MK48T18_CLKSZ, MK48T18_CLKOFF, 0 }, 70 { "mk48t59", MK48T59_CLKSZ, MK48T59_CLKOFF, MK48TXX_EXT_REGISTERS }, 71 }; 72 73 void 74 mk48txx_attach(struct mk48txx_softc *sc) 75 { 76 todr_chip_handle_t handle; 77 int i; 78 79 printf(": %s", sc->sc_model); 80 81 i = sizeof(mk48txx_models) / sizeof(mk48txx_models[0]); 82 while (--i >= 0) { 83 if (strcmp(sc->sc_model, mk48txx_models[i].name) == 0) 84 break; 85 } 86 if (i < 0) 87 panic("mk48txx_attach: unsupported model"); 88 89 sc->sc_nvramsz = mk48txx_models[i].nvramsz; 90 sc->sc_clkoffset = mk48txx_models[i].clkoff; 91 92 handle = &sc->sc_handle; 93 handle->cookie = sc; 94 handle->todr_gettime = NULL; 95 handle->todr_settime = NULL; 96 handle->todr_gettime_ymdhms = mk48txx_gettime_ymdhms; 97 handle->todr_settime_ymdhms = mk48txx_settime_ymdhms; 98 handle->todr_setwen = NULL; 99 100 if (sc->sc_nvrd == NULL) 101 sc->sc_nvrd = mk48txx_def_nvrd; 102 if (sc->sc_nvwr == NULL) 103 sc->sc_nvwr = mk48txx_def_nvwr; 104 } 105 106 /* 107 * Get time-of-day and convert to a `struct timeval' 108 * Return 0 on success; an error number otherwise. 109 */ 110 int 111 mk48txx_gettime_ymdhms(todr_chip_handle_t handle, struct clock_ymdhms *dt) 112 { 113 struct mk48txx_softc *sc; 114 bus_size_t clkoff; 115 int year; 116 uint8_t csr; 117 118 sc = handle->cookie; 119 clkoff = sc->sc_clkoffset; 120 121 todr_wenable(handle, 1); 122 123 /* enable read (stop time) */ 124 csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); 125 csr |= MK48TXX_CSR_READ; 126 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); 127 128 dt->dt_sec = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_ISEC)); 129 dt->dt_min = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IMIN)); 130 dt->dt_hour = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IHOUR)); 131 dt->dt_day = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IDAY)); 132 dt->dt_wday = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IWDAY)); 133 dt->dt_mon = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IMON)); 134 year = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IYEAR)); 135 136 year += sc->sc_year0; 137 if (year < POSIX_BASE_YEAR && 138 (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) == 0) 139 year += 100; 140 141 dt->dt_year = year; 142 143 /* time wears on */ 144 csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); 145 csr &= ~MK48TXX_CSR_READ; 146 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); 147 todr_wenable(handle, 0); 148 149 return 0; 150 } 151 152 /* 153 * Set the time-of-day clock based on the value of the `struct timeval' arg. 154 * Return 0 on success; an error number otherwise. 155 */ 156 int 157 mk48txx_settime_ymdhms(todr_chip_handle_t handle, struct clock_ymdhms *dt) 158 { 159 struct mk48txx_softc *sc; 160 bus_size_t clkoff; 161 uint8_t csr; 162 int year; 163 164 sc = handle->cookie; 165 clkoff = sc->sc_clkoffset; 166 167 year = dt->dt_year - sc->sc_year0; 168 if (year > 99 && 169 (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) == 0) 170 year -= 100; 171 172 todr_wenable(handle, 1); 173 /* enable write */ 174 csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); 175 csr |= MK48TXX_CSR_WRITE; 176 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); 177 178 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ISEC, TOBCD(dt->dt_sec)); 179 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IMIN, TOBCD(dt->dt_min)); 180 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IHOUR, TOBCD(dt->dt_hour)); 181 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IWDAY, TOBCD(dt->dt_wday)); 182 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IDAY, TOBCD(dt->dt_day)); 183 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IMON, TOBCD(dt->dt_mon)); 184 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IYEAR, TOBCD(year)); 185 186 /* load them up */ 187 csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); 188 csr &= ~MK48TXX_CSR_WRITE; 189 (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); 190 todr_wenable(handle, 0); 191 return 0; 192 } 193 194 int 195 mk48txx_get_nvram_size(todr_chip_handle_t handle, bus_size_t *vp) 196 { 197 struct mk48txx_softc *sc; 198 199 sc = handle->cookie; 200 *vp = sc->sc_nvramsz; 201 return 0; 202 } 203 204 uint8_t 205 mk48txx_def_nvrd(struct mk48txx_softc *sc, int off) 206 { 207 208 return bus_space_read_1(sc->sc_bst, sc->sc_bsh, off); 209 } 210 211 void 212 mk48txx_def_nvwr(struct mk48txx_softc *sc, int off, uint8_t v) 213 { 214 215 bus_space_write_1(sc->sc_bst, sc->sc_bsh, off, v); 216 } 217