1 /* $OpenBSD: mcclock.c,v 1.4 2020/05/25 13:16:06 visa Exp $ */ 2 /* $NetBSD: mcclock.c,v 1.4 1996/10/13 02:59:41 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 6 * All rights reserved. 7 * 8 * Author: Chris G. Demetriou 9 * 10 * Permission to use, copy, modify and distribute this software and 11 * its documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/kernel.h> 33 #include <sys/systm.h> 34 #include <sys/device.h> 35 36 #include <dev/clock_subr.h> 37 #include <dev/ic/mc146818reg.h> 38 39 #include <loongson/dev/mcclockvar.h> 40 41 struct cfdriver mcclock_cd = { 42 NULL, "mcclock", DV_DULL, 43 }; 44 45 int mcclock_gettime(struct todr_chip_handle *, struct timeval *); 46 int mcclock_settime(struct todr_chip_handle *, struct timeval *); 47 48 #define mc146818_write(dev, reg, datum) \ 49 (*(dev)->sc_busfns->mc_bf_write)(dev, reg, datum) 50 #define mc146818_read(dev, reg) \ 51 (*(dev)->sc_busfns->mc_bf_read)(dev, reg) 52 53 void 54 mcclock_attach(sc, busfns) 55 struct mcclock_softc *sc; 56 const struct mcclock_busfns *busfns; 57 { 58 59 printf(": mc146818 or compatible\n"); 60 61 sc->sc_busfns = busfns; 62 63 /* Turn interrupts off, just in case. */ 64 mc146818_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR); 65 mc146818_write(sc, MC_REGA, MC_BASE_32_KHz | MC_RATE_NONE); 66 67 sc->sc_todr.cookie = sc; 68 sc->sc_todr.todr_gettime = mcclock_gettime; 69 sc->sc_todr.todr_settime = mcclock_settime; 70 todr_attach(&sc->sc_todr); 71 } 72 73 /* 74 * Get the time of day, based on the clock's value and/or the base value. 75 */ 76 int 77 mcclock_gettime(struct todr_chip_handle *handle, struct timeval *tv) 78 { 79 struct clock_ymdhms dt; 80 struct mcclock_softc *sc = handle->cookie; 81 mc_todregs regs; 82 int s; 83 84 s = splclock(); 85 MC146818_GETTOD(sc, ®s) 86 splx(s); 87 88 dt.dt_sec = regs[MC_SEC]; 89 dt.dt_min = regs[MC_MIN]; 90 dt.dt_hour = regs[MC_HOUR]; 91 dt.dt_day = regs[MC_DOM]; 92 dt.dt_mon = regs[MC_MONTH]; 93 dt.dt_year = regs[MC_YEAR] + 2000; 94 95 tv->tv_sec = clock_ymdhms_to_secs(&dt); 96 tv->tv_usec = 0; 97 return 0; 98 } 99 100 /* 101 * Reset the TODR based on the time value. 102 */ 103 int 104 mcclock_settime(struct todr_chip_handle *handle, struct timeval *tv) 105 { 106 struct clock_ymdhms dt; 107 struct mcclock_softc *sc = handle->cookie; 108 mc_todregs regs; 109 int s; 110 111 clock_secs_to_ymdhms(tv->tv_sec, &dt); 112 113 s = splclock(); 114 MC146818_GETTOD(sc, ®s); 115 splx(s); 116 117 regs[MC_SEC] = dt.dt_sec; 118 regs[MC_MIN] = dt.dt_min; 119 regs[MC_HOUR] = dt.dt_hour; 120 regs[MC_DOW] = dt.dt_wday + 1; 121 regs[MC_DOM] = dt.dt_day; 122 regs[MC_MONTH] = dt.dt_mon; 123 regs[MC_YEAR] = dt.dt_year % 100; 124 125 s = splclock(); 126 MC146818_PUTTOD(sc, ®s); 127 splx(s); 128 129 return 0; 130 } 131