1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2023 Arm Ltd 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * Driver for the Arm PL031 RTC device 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/clock.h> 36 #include <sys/kernel.h> 37 #include <sys/module.h> 38 #include <sys/rman.h> 39 40 #include <machine/bus.h> 41 #include <machine/resource.h> 42 43 #include <dev/ofw/openfirm.h> 44 #include <dev/ofw/ofw_bus.h> 45 #include <dev/ofw/ofw_bus_subr.h> 46 47 #include "clock_if.h" 48 49 #define RTCDR 0x00 50 #define RTCMR 0x04 51 #define RTCLR 0x08 52 #define RTCCR 0x0c 53 #define RTCIMSR 0x10 54 #define RTCRIS 0x14 55 #define RTCMIS 0x18 56 #define RTCICR 0x1c 57 58 struct pl031_softc { 59 struct resource *reg; 60 int reg_rid; 61 }; 62 63 static device_probe_t pl031_probe; 64 static device_attach_t pl031_attach; 65 static device_detach_t pl031_detach; 66 67 static clock_gettime_t pl031_gettime; 68 static clock_settime_t pl031_settime; 69 70 static int 71 pl031_probe(device_t dev) 72 { 73 if (!ofw_bus_status_okay(dev)) 74 return (ENXIO); 75 76 if (!ofw_bus_is_compatible(dev, "arm,pl031")) 77 return (ENXIO); 78 79 device_set_desc(dev, "PL031 RTC"); 80 return (BUS_PROBE_DEFAULT); 81 } 82 83 static int 84 pl031_attach(device_t dev) 85 { 86 struct pl031_softc *sc; 87 88 sc = device_get_softc(dev); 89 90 sc->reg_rid = 0; 91 sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->reg_rid, 92 RF_ACTIVE); 93 if (sc->reg == 0) 94 return (ENXIO); 95 96 clock_register(dev, 1000000); 97 98 return (0); 99 } 100 101 static int 102 pl031_detach(device_t dev) 103 { 104 struct pl031_softc *sc; 105 106 sc = device_get_softc(dev); 107 108 clock_unregister(dev); 109 bus_release_resource(dev, SYS_RES_MEMORY, sc->reg_rid, sc->reg); 110 111 return (0); 112 } 113 114 static int 115 pl031_gettime(device_t dev, struct timespec *ts) 116 { 117 struct pl031_softc *sc; 118 119 sc = device_get_softc(dev); 120 ts->tv_sec = bus_read_4(sc->reg, RTCDR); 121 ts->tv_nsec = 0; 122 123 return (0); 124 } 125 126 static int 127 pl031_settime(device_t dev, struct timespec *ts) 128 { 129 struct pl031_softc *sc; 130 131 sc = device_get_softc(dev); 132 bus_write_4(sc->reg, RTCLR, ts->tv_sec); 133 return (0); 134 } 135 136 static device_method_t pl031_methods[] = { 137 /* Device interface */ 138 DEVMETHOD(device_probe, pl031_probe), 139 DEVMETHOD(device_attach, pl031_attach), 140 DEVMETHOD(device_detach, pl031_detach), 141 142 /* Clock interface */ 143 DEVMETHOD(clock_gettime, pl031_gettime), 144 DEVMETHOD(clock_settime, pl031_settime), 145 146 /* End */ 147 DEVMETHOD_END 148 }; 149 150 DEFINE_CLASS_0(pl031, pl031_driver, pl031_methods, 151 sizeof(struct pl031_softc)); 152 153 DRIVER_MODULE(pl031, simplebus, pl031_driver, 0, 0); 154