rtc.c revision 139825
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 139825 2005-01-07 02:29:27Z imp $"); 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/module.h> 43#include <sys/resource.h> 44 45#include <dev/ofw/ofw_bus.h> 46 47#include <machine/bus.h> 48#include <machine/resource.h> 49 50#include <sys/rman.h> 51 52#include <isa/isavar.h> 53 54#include <dev/mc146818/mc146818var.h> 55 56#include "clock_if.h" 57 58static devclass_t rtc_devclass; 59 60static int rtc_attach(device_t dev); 61static int rtc_ebus_probe(device_t dev); 62#ifdef DEV_ISA 63static int rtc_isa_probe(device_t dev); 64#endif 65 66static device_method_t rtc_ebus_methods[] = { 67 /* Device interface */ 68 DEVMETHOD(device_probe, rtc_ebus_probe), 69 DEVMETHOD(device_attach, rtc_attach), 70 71 /* clock interface */ 72 DEVMETHOD(clock_gettime, mc146818_gettime), 73 DEVMETHOD(clock_settime, mc146818_settime), 74#ifdef notyet 75 DEVMETHOD(clock_getsecs, mc146818_getsecs), 76#endif 77 78 { 0, 0 } 79}; 80 81static driver_t rtc_ebus_driver = { 82 "rtc", 83 rtc_ebus_methods, 84 sizeof(struct mc146818_softc), 85}; 86 87DRIVER_MODULE(rtc, ebus, rtc_ebus_driver, rtc_devclass, 0, 0); 88 89#ifdef DEV_ISA 90static device_method_t rtc_isa_methods[] = { 91 /* Device interface */ 92 DEVMETHOD(device_probe, rtc_isa_probe), 93 DEVMETHOD(device_attach, rtc_attach), 94 95 /* clock interface */ 96 DEVMETHOD(clock_gettime, mc146818_gettime), 97 DEVMETHOD(clock_settime, mc146818_settime), 98#ifdef notyet 99 DEVMETHOD(clock_getsecs, mc146818_getsecs), 100#endif 101 102 { 0, 0 } 103}; 104 105static driver_t rtc_isa_driver = { 106 "rtc", 107 rtc_isa_methods, 108 sizeof(struct mc146818_softc), 109}; 110 111DRIVER_MODULE(rtc, isa, rtc_isa_driver, rtc_devclass, 0, 0); 112#endif 113 114static int 115rtc_ebus_probe(device_t dev) 116{ 117 118 if (strcmp(ofw_bus_get_name(dev), "rtc") == 0) { 119 device_set_desc(dev, "Real Time Clock"); 120 return (0); 121 } 122 123 return (ENXIO); 124} 125 126#ifdef DEV_ISA 127static struct isa_pnp_id rtc_isa_ids[] = { 128 { 0x000bd041, "AT realtime clock" }, /* PNP0B00 */ 129 { 0 } 130}; 131 132static int 133rtc_isa_probe(device_t dev) 134{ 135 136 if (ISA_PNP_PROBE(device_get_parent(dev), dev, rtc_isa_ids) == 0) { 137 device_set_desc(dev, "Real Time Clock"); 138 return (0); 139 } 140 141 return (ENXIO); 142} 143#endif 144 145static int 146rtc_attach(device_t dev) 147{ 148 struct timespec ts; 149 struct mc146818_softc *sc; 150 struct resource *res; 151 int error, rid; 152 153 sc = device_get_softc(dev); 154 bzero(sc, sizeof(struct mc146818_softc)); 155 156 rid = 0; 157 res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 158 if (res == NULL) { 159 device_printf(dev, "could not allocate resources\n"); 160 return (ENXIO); 161 } 162 sc->sc_bst = rman_get_bustag(res); 163 sc->sc_bsh = rman_get_bushandle(res); 164 165 /* The TOD clock year 0 is 0. */ 166 sc->sc_year0 = 0; 167 /* Use default register read/write and century get/set functions. */ 168 sc->sc_flag = MC146818_NO_CENT_ADJUST; 169 if ((error = mc146818_attach(dev)) != 0) { 170 device_printf(dev, "cannot attach time of day clock\n"); 171 return (error); 172 } 173 174 if (bootverbose) { 175 mc146818_gettime(dev, &ts); 176 device_printf(dev, "current time: %ld.%09ld\n", (long)ts.tv_sec, 177 ts.tv_nsec); 178 } 179 180 return (0); 181} 182