xref: /openbsd-src/sys/dev/fdt/plrtc.c (revision 62d244ed99f17c1263ee095bc7d8fa1f61df02fd)
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