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