1*62d244edSkettenis /* $OpenBSD: plrtc.c,v 1.4 2022/10/17 19:09:46 kettenis Exp $ */
24406bb04Sjsg
34406bb04Sjsg /*
44406bb04Sjsg * Copyright (c) 2015 Jonathan Gray <jsg@openbsd.org>
54406bb04Sjsg *
64406bb04Sjsg * Permission to use, copy, modify, and distribute this software for any
74406bb04Sjsg * purpose with or without fee is hereby granted, provided that the above
84406bb04Sjsg * copyright notice and this permission notice appear in all copies.
94406bb04Sjsg *
104406bb04Sjsg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
114406bb04Sjsg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
124406bb04Sjsg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
134406bb04Sjsg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
144406bb04Sjsg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
154406bb04Sjsg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
164406bb04Sjsg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
174406bb04Sjsg */
184406bb04Sjsg
194406bb04Sjsg #include <sys/param.h>
204406bb04Sjsg #include <sys/device.h>
214406bb04Sjsg #include <sys/malloc.h>
224406bb04Sjsg #include <sys/systm.h>
234406bb04Sjsg
244406bb04Sjsg #include <machine/bus.h>
254406bb04Sjsg #include <machine/fdt.h>
264406bb04Sjsg #include <dev/clock_subr.h>
274406bb04Sjsg
284406bb04Sjsg #include <dev/ofw/openfirm.h>
294406bb04Sjsg #include <dev/ofw/fdt.h>
304406bb04Sjsg
314406bb04Sjsg #define RTCDR 0x00
324406bb04Sjsg #define RTCMR 0x04
334406bb04Sjsg #define RTCLR 0x08
344406bb04Sjsg #define RTCCR 0x0c
354406bb04Sjsg #define RTCIMSC 0x10
364406bb04Sjsg #define RTCRIS 0x14
374406bb04Sjsg #define RTCMIS 0x18
384406bb04Sjsg #define RTCICR 0x1c
394406bb04Sjsg
404406bb04Sjsg #define RTCCR_START (1 << 0)
414406bb04Sjsg
424406bb04Sjsg struct plrtc_softc {
434406bb04Sjsg struct device sc_dev;
444406bb04Sjsg bus_space_tag_t sc_iot;
454406bb04Sjsg bus_space_handle_t sc_ioh;
464406bb04Sjsg };
474406bb04Sjsg
484406bb04Sjsg int plrtc_match(struct device *, void *, void *);
494406bb04Sjsg void plrtc_attach(struct device *, struct device *, void *);
504406bb04Sjsg int plrtc_gettime(struct todr_chip_handle *, struct timeval *);
514406bb04Sjsg int plrtc_settime(struct todr_chip_handle *, struct timeval *);
524406bb04Sjsg
534406bb04Sjsg
549fdf0c62Smpi const struct cfattach plrtc_ca = {
554406bb04Sjsg sizeof(struct plrtc_softc), plrtc_match, plrtc_attach
564406bb04Sjsg };
574406bb04Sjsg
584406bb04Sjsg struct cfdriver plrtc_cd = {
594406bb04Sjsg NULL, "plrtc", DV_DULL
604406bb04Sjsg };
614406bb04Sjsg
624406bb04Sjsg int
plrtc_gettime(todr_chip_handle_t handle,struct timeval * tv)634406bb04Sjsg plrtc_gettime(todr_chip_handle_t handle, struct timeval *tv)
644406bb04Sjsg {
654406bb04Sjsg struct plrtc_softc *sc = handle->cookie;
664406bb04Sjsg uint32_t tod;
674406bb04Sjsg
684406bb04Sjsg tod = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RTCDR);
694406bb04Sjsg
704406bb04Sjsg tv->tv_sec = tod;
714406bb04Sjsg tv->tv_usec = 0;
724406bb04Sjsg
734406bb04Sjsg return (0);
744406bb04Sjsg }
754406bb04Sjsg
764406bb04Sjsg int
plrtc_settime(todr_chip_handle_t handle,struct timeval * tv)774406bb04Sjsg plrtc_settime(todr_chip_handle_t handle, struct timeval *tv)
784406bb04Sjsg {
794406bb04Sjsg struct plrtc_softc *sc = handle->cookie;
804406bb04Sjsg
814406bb04Sjsg bus_space_write_4(sc->sc_iot, sc->sc_ioh, RTCLR, tv->tv_sec);
824406bb04Sjsg
834406bb04Sjsg return (0);
844406bb04Sjsg }
854406bb04Sjsg
864406bb04Sjsg int
plrtc_match(struct device * parent,void * match,void * aux)874406bb04Sjsg plrtc_match(struct device *parent, void *match, void *aux)
884406bb04Sjsg {
894406bb04Sjsg struct fdt_attach_args *faa = aux;
904406bb04Sjsg
914406bb04Sjsg return (OF_is_compatible(faa->fa_node, "arm,pl031"));
924406bb04Sjsg }
934406bb04Sjsg
944406bb04Sjsg void
plrtc_attach(struct device * parent,struct device * self,void * aux)954406bb04Sjsg plrtc_attach(struct device *parent, struct device *self, void *aux)
964406bb04Sjsg {
974406bb04Sjsg struct fdt_attach_args *faa = aux;
984406bb04Sjsg struct plrtc_softc *sc = (struct plrtc_softc *) self;
994406bb04Sjsg todr_chip_handle_t handle;
1004406bb04Sjsg
1014406bb04Sjsg if (faa->fa_nreg < 1) {
1024406bb04Sjsg printf(": no register data\n");
1034406bb04Sjsg return;
1044406bb04Sjsg }
1054406bb04Sjsg
1064406bb04Sjsg sc->sc_iot = faa->fa_iot;
1074406bb04Sjsg if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
1084406bb04Sjsg faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
1094406bb04Sjsg printf(": failed to map mem space\n");
1104406bb04Sjsg return;
1114406bb04Sjsg }
1124406bb04Sjsg
1134406bb04Sjsg handle = malloc(sizeof(struct todr_chip_handle), M_DEVBUF,
1144406bb04Sjsg M_NOWAIT | M_ZERO);
1154406bb04Sjsg if (handle == NULL)
1164406bb04Sjsg panic("couldn't allocate todr_handle");
1174406bb04Sjsg
1184406bb04Sjsg handle->cookie = sc;
1194406bb04Sjsg handle->todr_gettime = plrtc_gettime;
1204406bb04Sjsg handle->todr_settime = plrtc_settime;
1210701a158Skettenis handle->todr_quality = 0;
122*62d244edSkettenis todr_attach(handle);
1234406bb04Sjsg
1244406bb04Sjsg /* enable the rtc */
1254406bb04Sjsg bus_space_write_4(sc->sc_iot, sc->sc_ioh, RTCCR, RTCCR_START);
1264406bb04Sjsg
1274406bb04Sjsg printf("\n");
1284406bb04Sjsg }
129