rtc.c revision 146982
1/*- 2 * Copyright (c) 2004 Marius Strobl <marius@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/rtc.c 146982 2005-06-04 23:24:50Z marius $"); 29 30/* 31 * The `rtc' device is a MC146818 compatible clock found on the ISA bus 32 * and EBus. The EBus version also has an interrupt property so it could 33 * be used to drive the statclock etc. 34 */ 35 36#include "opt_isa.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/bus.h> 41#include <sys/kernel.h> 42#include <sys/lock.h> 43#include <sys/module.h> 44#include <sys/mutex.h> 45#include <sys/resource.h> 46 47#include <dev/ofw/ofw_bus.h> 48 49#include <machine/bus.h> 50#include <machine/resource.h> 51 52#include <sys/rman.h> 53 54#include <isa/isavar.h> 55 56#include <dev/mc146818/mc146818var.h> 57 58#include "clock_if.h" 59 60static devclass_t rtc_devclass; 61 62static int rtc_attach(device_t dev); 63static int rtc_ebus_probe(device_t dev); 64#ifdef DEV_ISA 65static int rtc_isa_probe(device_t dev); 66#endif 67 68static device_method_t rtc_ebus_methods[] = { 69 /* Device interface */ 70 DEVMETHOD(device_probe, rtc_ebus_probe), 71 DEVMETHOD(device_attach, rtc_attach), 72 73 /* clock interface */ 74 DEVMETHOD(clock_gettime, mc146818_gettime), 75 DEVMETHOD(clock_settime, mc146818_settime), 76 77 { 0, 0 } 78}; 79 80static driver_t rtc_ebus_driver = { 81 "rtc", 82 rtc_ebus_methods, 83 sizeof(struct mc146818_softc), 84}; 85 86DRIVER_MODULE(rtc, ebus, rtc_ebus_driver, rtc_devclass, 0, 0); 87 88#ifdef DEV_ISA 89static device_method_t rtc_isa_methods[] = { 90 /* Device interface */ 91 DEVMETHOD(device_probe, rtc_isa_probe), 92 DEVMETHOD(device_attach, rtc_attach), 93 94 /* clock interface */ 95 DEVMETHOD(clock_gettime, mc146818_gettime), 96 DEVMETHOD(clock_settime, mc146818_settime), 97 98 { 0, 0 } 99}; 100 101static driver_t rtc_isa_driver = { 102 "rtc", 103 rtc_isa_methods, 104 sizeof(struct mc146818_softc), 105}; 106 107DRIVER_MODULE(rtc, isa, rtc_isa_driver, rtc_devclass, 0, 0); 108#endif 109 110static int 111rtc_ebus_probe(device_t dev) 112{ 113 114 if (strcmp(ofw_bus_get_name(dev), "rtc") == 0) { 115 device_set_desc(dev, "Real Time Clock"); 116 return (0); 117 } 118 119 return (ENXIO); 120} 121 122#ifdef DEV_ISA 123static struct isa_pnp_id rtc_isa_ids[] = { 124 { 0x000bd041, "AT realtime clock" }, /* PNP0B00 */ 125 { 0 } 126}; 127 128static int 129rtc_isa_probe(device_t dev) 130{ 131 132 if (ISA_PNP_PROBE(device_get_parent(dev), dev, rtc_isa_ids) == 0) { 133 device_set_desc(dev, "Real Time Clock"); 134 return (0); 135 } 136 137 return (ENXIO); 138} 139#endif 140 141static int 142rtc_attach(device_t dev) 143{ 144 struct timespec ts; 145 struct mc146818_softc *sc; 146 struct resource *res; 147 int error, rid, rtype; 148 149 sc = device_get_softc(dev); 150 bzero(sc, sizeof(struct mc146818_softc)); 151 152 mtx_init(&sc->sc_mtx, "rtc_mtx", NULL, MTX_SPIN); 153 154 if (strcmp(device_get_name(device_get_parent(dev)), "isa") == 0) 155 rtype = SYS_RES_IOPORT; 156 else 157 rtype = SYS_RES_MEMORY; 158 159 rid = 0; 160 res = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); 161 if (res == NULL) { 162 device_printf(dev, "cannot allocate resources\n"); 163 error = ENXIO; 164 goto fail_mtx; 165 } 166 sc->sc_bst = rman_get_bustag(res); 167 sc->sc_bsh = rman_get_bushandle(res); 168 169 /* The TOD clock year 0 is 0. */ 170 sc->sc_year0 = 0; 171 /* Use default register read/write and century get/set functions. */ 172 sc->sc_flag = MC146818_NO_CENT_ADJUST; 173 if ((error = mc146818_attach(dev)) != 0) { 174 device_printf(dev, "cannot attach time of day clock\n"); 175 goto fail_res; 176 } 177 178 if (bootverbose) { 179 mc146818_gettime(dev, &ts); 180 device_printf(dev, "current time: %ld.%09ld\n", (long)ts.tv_sec, 181 ts.tv_nsec); 182 } 183 184 return (0); 185 186 fail_res: 187 bus_release_resource(dev, rtype, rid, res); 188 fail_mtx: 189 mtx_destroy(&sc->sc_mtx); 190 191 return (error); 192} 193