xref: /openbsd/sys/arch/sparc64/dev/prtc.c (revision 0701a158)
1*0701a158Skettenis /*	$OpenBSD: prtc.c,v 1.7 2022/10/12 13:39:50 kettenis Exp $	*/
24e0ed43dSkettenis 
34e0ed43dSkettenis /*
44e0ed43dSkettenis  * Copyright (c) 2008 Mark Kettenis
54e0ed43dSkettenis  *
64e0ed43dSkettenis  * Permission to use, copy, modify, and distribute this software for any
74e0ed43dSkettenis  * purpose with or without fee is hereby granted, provided that the above
84e0ed43dSkettenis  * copyright notice and this permission notice appear in all copies.
94e0ed43dSkettenis  *
104e0ed43dSkettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
114e0ed43dSkettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
124e0ed43dSkettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
134e0ed43dSkettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
144e0ed43dSkettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
154e0ed43dSkettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
164e0ed43dSkettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
174e0ed43dSkettenis  */
184e0ed43dSkettenis 
194e0ed43dSkettenis /*
204e0ed43dSkettenis  * Driver to get the time-of-day from the PROM for machines that don't
214e0ed43dSkettenis  * have a hardware real-time clock, like the Enterprise 10000,
224e0ed43dSkettenis  * Fire 12K and Fire 15K.
234e0ed43dSkettenis  */
244e0ed43dSkettenis 
254e0ed43dSkettenis #include <sys/param.h>
264e0ed43dSkettenis #include <sys/device.h>
274e0ed43dSkettenis #include <sys/malloc.h>
284e0ed43dSkettenis #include <sys/systm.h>
294e0ed43dSkettenis 
304e0ed43dSkettenis #include <machine/autoconf.h>
314e0ed43dSkettenis #include <machine/openfirm.h>
32805f8e64Skettenis #include <machine/sparc64.h>
334e0ed43dSkettenis 
344e0ed43dSkettenis #include <dev/clock_subr.h>
354e0ed43dSkettenis 
364e0ed43dSkettenis extern todr_chip_handle_t todr_handle;
374e0ed43dSkettenis 
38fe27195aSdlg struct prtc_softc {
39fe27195aSdlg 	struct device	sc_dev;
40fe27195aSdlg 	struct todr_chip_handle
41fe27195aSdlg 			sc_todr_chip;
42fe27195aSdlg };
43fe27195aSdlg 
444e0ed43dSkettenis int	prtc_match(struct device *, void *, void *);
454e0ed43dSkettenis void	prtc_attach(struct device *, struct device *, void *);
464e0ed43dSkettenis 
47eb7eaf8dSmpi const struct cfattach prtc_ca = {
48fe27195aSdlg 	sizeof(struct prtc_softc), prtc_match, prtc_attach
494e0ed43dSkettenis };
504e0ed43dSkettenis 
514e0ed43dSkettenis struct cfdriver prtc_cd = {
524e0ed43dSkettenis 	NULL, "prtc", DV_DULL
534e0ed43dSkettenis };
544e0ed43dSkettenis 
554e0ed43dSkettenis int	prtc_gettime(todr_chip_handle_t, struct timeval *);
564e0ed43dSkettenis int	prtc_settime(todr_chip_handle_t, struct timeval *);
574e0ed43dSkettenis 
58c45efb56Sdlg int	prtc_opl_gettime(todr_chip_handle_t, struct timeval *);
59c45efb56Sdlg int	prtc_opl_settime(todr_chip_handle_t, struct timeval *);
60c45efb56Sdlg 
614e0ed43dSkettenis int
prtc_match(struct device * parent,void * match,void * aux)624e0ed43dSkettenis prtc_match(struct device *parent, void *match, void *aux)
634e0ed43dSkettenis {
644e0ed43dSkettenis 	struct mainbus_attach_args *ma = aux;
654e0ed43dSkettenis 
664e0ed43dSkettenis 	if (strcmp(ma->ma_name, "prtc") == 0)
674e0ed43dSkettenis 		return (1);
684e0ed43dSkettenis 
694e0ed43dSkettenis 	return (0);
704e0ed43dSkettenis }
714e0ed43dSkettenis 
724e0ed43dSkettenis void
prtc_attach(struct device * parent,struct device * self,void * aux)734e0ed43dSkettenis prtc_attach(struct device *parent, struct device *self, void *aux)
744e0ed43dSkettenis {
75fe27195aSdlg 	struct prtc_softc *sc = (struct prtc_softc *)self;
76fe27195aSdlg 	todr_chip_handle_t handle = &sc->sc_todr_chip;
77c45efb56Sdlg 	char buf[32];
78c45efb56Sdlg 	int opl;
79c45efb56Sdlg 
80c45efb56Sdlg 	opl = OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0 &&
81c45efb56Sdlg 	    strcmp(buf, "SUNW,SPARC-Enterprise") == 0;
82c45efb56Sdlg 
83c45efb56Sdlg 	if (opl)
84c45efb56Sdlg 		printf(": OPL");
854e0ed43dSkettenis 
864e0ed43dSkettenis 	printf("\n");
874e0ed43dSkettenis 
88fe27195aSdlg 	handle->cookie = sc;
89c45efb56Sdlg 	if (opl) {
90c45efb56Sdlg 		handle->todr_gettime = prtc_opl_gettime;
91c45efb56Sdlg 		handle->todr_settime = prtc_opl_settime;
92c45efb56Sdlg 	} else {
934e0ed43dSkettenis 		handle->todr_gettime = prtc_gettime;
944e0ed43dSkettenis 		handle->todr_settime = prtc_settime;
95c45efb56Sdlg 	}
964e0ed43dSkettenis 
974e0ed43dSkettenis 	handle->bus_cookie = NULL;
984e0ed43dSkettenis 	handle->todr_setwen = NULL;
99*0701a158Skettenis 	handle->todr_quality = 0;
1004e0ed43dSkettenis 	todr_handle = handle;
1014e0ed43dSkettenis }
1024e0ed43dSkettenis 
1034e0ed43dSkettenis int
prtc_gettime(todr_chip_handle_t handle,struct timeval * tv)1044e0ed43dSkettenis prtc_gettime(todr_chip_handle_t handle, struct timeval *tv)
1054e0ed43dSkettenis {
106805f8e64Skettenis 	char buf[32];
107c45efb56Sdlg 	u_int32_t tod = 0;
108805f8e64Skettenis 
109afa5fc7eSkettenis 	snprintf(buf, sizeof(buf), "h# %08lx unix-gettod", (long)&tod);
110805f8e64Skettenis 	OF_interpret(buf, 0);
1114e0ed43dSkettenis 
1124e0ed43dSkettenis 	tv->tv_sec = tod;
1134e0ed43dSkettenis 	tv->tv_usec = 0;
1144e0ed43dSkettenis 	return (0);
1154e0ed43dSkettenis }
1164e0ed43dSkettenis 
1174e0ed43dSkettenis int
prtc_settime(todr_chip_handle_t handle,struct timeval * tv)1184e0ed43dSkettenis prtc_settime(todr_chip_handle_t handle, struct timeval *tv)
1194e0ed43dSkettenis {
1204e0ed43dSkettenis 	return (0);
1214e0ed43dSkettenis }
122c45efb56Sdlg 
123c45efb56Sdlg int
prtc_opl_gettime(todr_chip_handle_t handle,struct timeval * tv)124c45efb56Sdlg prtc_opl_gettime(todr_chip_handle_t handle, struct timeval *tv)
125c45efb56Sdlg {
126c45efb56Sdlg 	struct {
127c45efb56Sdlg 		cell_t	name;
128c45efb56Sdlg 		cell_t	nargs;
129c45efb56Sdlg 		cell_t	nrets;
130c45efb56Sdlg 		cell_t	stick;
131c45efb56Sdlg 		cell_t	time;
132c45efb56Sdlg 	} args = {
133c45efb56Sdlg 		.name	= ADR2CELL("FJSV,get-tod"),
134c45efb56Sdlg 		.nargs	= 0,
135c45efb56Sdlg 		.nrets	= 2,
136c45efb56Sdlg 	};
137c45efb56Sdlg 
138c45efb56Sdlg 	if (openfirmware(&args) == -1)
139c45efb56Sdlg 		return (-1);
140c45efb56Sdlg 
141c45efb56Sdlg 	tv->tv_sec = args.time;
142c45efb56Sdlg 	tv->tv_usec = 0;
143c45efb56Sdlg 
144c45efb56Sdlg 	return (0);
145c45efb56Sdlg }
146c45efb56Sdlg 
147c45efb56Sdlg int
prtc_opl_settime(todr_chip_handle_t handle,struct timeval * tv)148c45efb56Sdlg prtc_opl_settime(todr_chip_handle_t handle, struct timeval *tv)
149c45efb56Sdlg {
150c45efb56Sdlg 	struct timeval otv;
151c45efb56Sdlg 	struct {
152c45efb56Sdlg 		cell_t	name;
153c45efb56Sdlg 		cell_t	nargs;
154c45efb56Sdlg 		cell_t	nrets;
155c45efb56Sdlg 		cell_t	diff;
156c45efb56Sdlg 	} args = {
157c45efb56Sdlg 		.name	= ADR2CELL("FJSV,set-domain-time"),
158c45efb56Sdlg 		.nargs	= 1,
159c45efb56Sdlg 		.nrets	= 0,
160c45efb56Sdlg 	};
161c45efb56Sdlg 
162c45efb56Sdlg 	if (prtc_opl_gettime(handle, &otv) == -1)
163c45efb56Sdlg 		return (-1);
164c45efb56Sdlg 
165c45efb56Sdlg 	args.diff = tv->tv_sec - otv.tv_sec;
166c45efb56Sdlg 	if (args.diff == 0)
167c45efb56Sdlg 		return (0);
168c45efb56Sdlg 
169c45efb56Sdlg 	if (openfirmware(&args) == -1)
170c45efb56Sdlg 		return (-1);
171c45efb56Sdlg 
172c45efb56Sdlg 	return (0);
173c45efb56Sdlg }
174