xref: /openbsd/sys/arch/sparc64/dev/prtc.c (revision 0701a158)
1 /*	$OpenBSD: prtc.c,v 1.7 2022/10/12 13:39:50 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Mark Kettenis
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 /*
20  * Driver to get the time-of-day from the PROM for machines that don't
21  * have a hardware real-time clock, like the Enterprise 10000,
22  * Fire 12K and Fire 15K.
23  */
24 
25 #include <sys/param.h>
26 #include <sys/device.h>
27 #include <sys/malloc.h>
28 #include <sys/systm.h>
29 
30 #include <machine/autoconf.h>
31 #include <machine/openfirm.h>
32 #include <machine/sparc64.h>
33 
34 #include <dev/clock_subr.h>
35 
36 extern todr_chip_handle_t todr_handle;
37 
38 struct prtc_softc {
39 	struct device	sc_dev;
40 	struct todr_chip_handle
41 			sc_todr_chip;
42 };
43 
44 int	prtc_match(struct device *, void *, void *);
45 void	prtc_attach(struct device *, struct device *, void *);
46 
47 const struct cfattach prtc_ca = {
48 	sizeof(struct prtc_softc), prtc_match, prtc_attach
49 };
50 
51 struct cfdriver prtc_cd = {
52 	NULL, "prtc", DV_DULL
53 };
54 
55 int	prtc_gettime(todr_chip_handle_t, struct timeval *);
56 int	prtc_settime(todr_chip_handle_t, struct timeval *);
57 
58 int	prtc_opl_gettime(todr_chip_handle_t, struct timeval *);
59 int	prtc_opl_settime(todr_chip_handle_t, struct timeval *);
60 
61 int
prtc_match(struct device * parent,void * match,void * aux)62 prtc_match(struct device *parent, void *match, void *aux)
63 {
64 	struct mainbus_attach_args *ma = aux;
65 
66 	if (strcmp(ma->ma_name, "prtc") == 0)
67 		return (1);
68 
69 	return (0);
70 }
71 
72 void
prtc_attach(struct device * parent,struct device * self,void * aux)73 prtc_attach(struct device *parent, struct device *self, void *aux)
74 {
75 	struct prtc_softc *sc = (struct prtc_softc *)self;
76 	todr_chip_handle_t handle = &sc->sc_todr_chip;
77 	char buf[32];
78 	int opl;
79 
80 	opl = OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0 &&
81 	    strcmp(buf, "SUNW,SPARC-Enterprise") == 0;
82 
83 	if (opl)
84 		printf(": OPL");
85 
86 	printf("\n");
87 
88 	handle->cookie = sc;
89 	if (opl) {
90 		handle->todr_gettime = prtc_opl_gettime;
91 		handle->todr_settime = prtc_opl_settime;
92 	} else {
93 		handle->todr_gettime = prtc_gettime;
94 		handle->todr_settime = prtc_settime;
95 	}
96 
97 	handle->bus_cookie = NULL;
98 	handle->todr_setwen = NULL;
99 	handle->todr_quality = 0;
100 	todr_handle = handle;
101 }
102 
103 int
prtc_gettime(todr_chip_handle_t handle,struct timeval * tv)104 prtc_gettime(todr_chip_handle_t handle, struct timeval *tv)
105 {
106 	char buf[32];
107 	u_int32_t tod = 0;
108 
109 	snprintf(buf, sizeof(buf), "h# %08lx unix-gettod", (long)&tod);
110 	OF_interpret(buf, 0);
111 
112 	tv->tv_sec = tod;
113 	tv->tv_usec = 0;
114 	return (0);
115 }
116 
117 int
prtc_settime(todr_chip_handle_t handle,struct timeval * tv)118 prtc_settime(todr_chip_handle_t handle, struct timeval *tv)
119 {
120 	return (0);
121 }
122 
123 int
prtc_opl_gettime(todr_chip_handle_t handle,struct timeval * tv)124 prtc_opl_gettime(todr_chip_handle_t handle, struct timeval *tv)
125 {
126 	struct {
127 		cell_t	name;
128 		cell_t	nargs;
129 		cell_t	nrets;
130 		cell_t	stick;
131 		cell_t	time;
132 	} args = {
133 		.name	= ADR2CELL("FJSV,get-tod"),
134 		.nargs	= 0,
135 		.nrets	= 2,
136 	};
137 
138 	if (openfirmware(&args) == -1)
139 		return (-1);
140 
141 	tv->tv_sec = args.time;
142 	tv->tv_usec = 0;
143 
144 	return (0);
145 }
146 
147 int
prtc_opl_settime(todr_chip_handle_t handle,struct timeval * tv)148 prtc_opl_settime(todr_chip_handle_t handle, struct timeval *tv)
149 {
150 	struct timeval otv;
151 	struct {
152 		cell_t	name;
153 		cell_t	nargs;
154 		cell_t	nrets;
155 		cell_t	diff;
156 	} args = {
157 		.name	= ADR2CELL("FJSV,set-domain-time"),
158 		.nargs	= 1,
159 		.nrets	= 0,
160 	};
161 
162 	if (prtc_opl_gettime(handle, &otv) == -1)
163 		return (-1);
164 
165 	args.diff = tv->tv_sec - otv.tv_sec;
166 	if (args.diff == 0)
167 		return (0);
168 
169 	if (openfirmware(&args) == -1)
170 		return (-1);
171 
172 	return (0);
173 }
174