1 /* $OpenBSD: plrtc.c,v 1.4 2022/10/17 19:09:46 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2015 Jonathan Gray <jsg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/device.h> 21 #include <sys/malloc.h> 22 #include <sys/systm.h> 23 24 #include <machine/bus.h> 25 #include <machine/fdt.h> 26 #include <dev/clock_subr.h> 27 28 #include <dev/ofw/openfirm.h> 29 #include <dev/ofw/fdt.h> 30 31 #define RTCDR 0x00 32 #define RTCMR 0x04 33 #define RTCLR 0x08 34 #define RTCCR 0x0c 35 #define RTCIMSC 0x10 36 #define RTCRIS 0x14 37 #define RTCMIS 0x18 38 #define RTCICR 0x1c 39 40 #define RTCCR_START (1 << 0) 41 42 struct plrtc_softc { 43 struct device sc_dev; 44 bus_space_tag_t sc_iot; 45 bus_space_handle_t sc_ioh; 46 }; 47 48 int plrtc_match(struct device *, void *, void *); 49 void plrtc_attach(struct device *, struct device *, void *); 50 int plrtc_gettime(struct todr_chip_handle *, struct timeval *); 51 int plrtc_settime(struct todr_chip_handle *, struct timeval *); 52 53 54 const struct cfattach plrtc_ca = { 55 sizeof(struct plrtc_softc), plrtc_match, plrtc_attach 56 }; 57 58 struct cfdriver plrtc_cd = { 59 NULL, "plrtc", DV_DULL 60 }; 61 62 int 63 plrtc_gettime(todr_chip_handle_t handle, struct timeval *tv) 64 { 65 struct plrtc_softc *sc = handle->cookie; 66 uint32_t tod; 67 68 tod = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RTCDR); 69 70 tv->tv_sec = tod; 71 tv->tv_usec = 0; 72 73 return (0); 74 } 75 76 int 77 plrtc_settime(todr_chip_handle_t handle, struct timeval *tv) 78 { 79 struct plrtc_softc *sc = handle->cookie; 80 81 bus_space_write_4(sc->sc_iot, sc->sc_ioh, RTCLR, tv->tv_sec); 82 83 return (0); 84 } 85 86 int 87 plrtc_match(struct device *parent, void *match, void *aux) 88 { 89 struct fdt_attach_args *faa = aux; 90 91 return (OF_is_compatible(faa->fa_node, "arm,pl031")); 92 } 93 94 void 95 plrtc_attach(struct device *parent, struct device *self, void *aux) 96 { 97 struct fdt_attach_args *faa = aux; 98 struct plrtc_softc *sc = (struct plrtc_softc *) self; 99 todr_chip_handle_t handle; 100 101 if (faa->fa_nreg < 1) { 102 printf(": no register data\n"); 103 return; 104 } 105 106 sc->sc_iot = faa->fa_iot; 107 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 108 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 109 printf(": failed to map mem space\n"); 110 return; 111 } 112 113 handle = malloc(sizeof(struct todr_chip_handle), M_DEVBUF, 114 M_NOWAIT | M_ZERO); 115 if (handle == NULL) 116 panic("couldn't allocate todr_handle"); 117 118 handle->cookie = sc; 119 handle->todr_gettime = plrtc_gettime; 120 handle->todr_settime = plrtc_settime; 121 handle->todr_quality = 0; 122 todr_attach(handle); 123 124 /* enable the rtc */ 125 bus_space_write_4(sc->sc_iot, sc->sc_ioh, RTCCR, RTCCR_START); 126 127 printf("\n"); 128 } 129