1/*	$OpenBSD: clock.c,v 1.87 2024/04/08 20:05:51 miod Exp $	*/
2/*	$NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */
3
4/*
5 * Copyright (c) 1992, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 * Copyright (c) 1994 Gordon W. Ross
8 * Copyright (c) 1993 Adam Glass
9 * Copyright (c) 1996 Paul Kranenburg
10 * Copyright (c) 1996
11 * 	The President and Fellows of Harvard College. All rights reserved.
12 *
13 * This software was developed by the Computer Systems Engineering group
14 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
15 * contributed to Berkeley.
16 *
17 * All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 *	This product includes software developed by Harvard University.
20 *	This product includes software developed by the University of
21 *	California, Lawrence Berkeley Laboratory.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright
28 *    notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 *    notice, this list of conditions and the following disclaimer in the
31 *    documentation and/or other materials provided with the distribution.
32 * 3. All advertising materials mentioning features or use of this software
33 *    must display the following acknowledgement:
34 *	This product includes software developed by the University of
35 *	California, Berkeley and its contributors.
36 *	This product includes software developed by Paul Kranenburg.
37 *	This product includes software developed by Harvard University.
38 * 4. Neither the name of the University nor the names of its contributors
39 *    may be used to endorse or promote products derived from this software
40 *    without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 *
54 *	@(#)clock.c	8.1 (Berkeley) 6/11/93
55 *
56 */
57
58/*
59 * Clock driver.  This is the id prom and eeprom driver as well
60 * and includes the timer register functions too.
61 */
62
63/* Define this for a 1/4s clock to ease debugging */
64/* #define INTR_DEBUG */
65
66#include <sys/param.h>
67#include <sys/kernel.h>
68#include <sys/device.h>
69#include <sys/malloc.h>
70#include <sys/systm.h>
71#include <sys/clockintr.h>
72#include <sys/sched.h>
73#include <sys/stdint.h>
74#include <sys/timetc.h>
75#include <sys/atomic.h>
76
77#include <machine/bus.h>
78#include <machine/autoconf.h>
79#include <machine/cpu.h>
80#include <machine/idprom.h>
81
82#include <dev/clock_subr.h>
83#include <dev/ic/mk48txxreg.h>
84
85#include <sparc64/dev/iommureg.h>
86#include <sparc64/dev/sbusreg.h>
87#include <dev/sbus/sbusvar.h>
88#include <sparc64/dev/ebusreg.h>
89#include <sparc64/dev/ebusvar.h>
90#include <sparc64/dev/fhcvar.h>
91
92extern u_int64_t cpu_clockrate;
93
94struct clock_wenable_info {
95	bus_space_tag_t		cwi_bt;
96	bus_space_handle_t	cwi_bh;
97	bus_size_t		cwi_size;
98};
99
100struct cfdriver clock_cd = {
101	NULL, "clock", DV_DULL
102};
103
104u_int tick_get_timecount(struct timecounter *);
105
106struct timecounter tick_timecounter = {
107	.tc_get_timecount = tick_get_timecount,
108	.tc_counter_mask = ~0u,
109	.tc_frequency = 0,
110	.tc_name = "tick",
111	.tc_quality = 0,
112	.tc_priv = NULL,
113	.tc_user = TC_TICK,
114};
115
116u_int sys_tick_get_timecount(struct timecounter *);
117
118struct timecounter sys_tick_timecounter = {
119	.tc_get_timecount = sys_tick_get_timecount,
120	.tc_counter_mask = ~0u,
121	.tc_frequency = 0,
122	.tc_name = "sys_tick",
123	.tc_quality = 1000,
124	.tc_priv = NULL,
125	.tc_user = TC_SYS_TICK,
126};
127
128void	tick_start(void);
129void	sys_tick_start(void);
130void	stick_start(void);
131
132int	tickintr(void *);
133int	sys_tickintr(void *);
134int	stickintr(void *);
135
136/* %TICK is at most a 63-bit counter. */
137#define TICK_COUNT_MASK 0x7fffffffffffffff
138
139uint64_t tick_nsec_cycle_ratio;
140uint64_t tick_nsec_max;
141
142void tick_rearm(void *, uint64_t);
143void tick_trigger(void *);
144
145const struct intrclock tick_intrclock = {
146	.ic_rearm = tick_rearm,
147	.ic_trigger = tick_trigger
148};
149
150/* %STICK is at most a 63-bit counter. */
151#define STICK_COUNT_MASK 0x7fffffffffffffff
152
153uint64_t sys_tick_nsec_cycle_ratio;
154uint64_t sys_tick_nsec_max;
155
156void sys_tick_rearm(void *, uint64_t);
157void sys_tick_trigger(void *);
158
159const struct intrclock sys_tick_intrclock = {
160	.ic_rearm = sys_tick_rearm,
161	.ic_trigger = sys_tick_trigger
162};
163
164void stick_rearm(void *, uint64_t);
165void stick_trigger(void *);
166
167const struct intrclock stick_intrclock = {
168	.ic_rearm = stick_rearm,
169	.ic_trigger = stick_trigger
170};
171
172void sparc64_raise_clockintr(void);
173
174static struct intrhand level10 = {
175	.ih_fun = tickintr,
176	.ih_number = 1,
177	.ih_pil = 10,
178	.ih_name = "clock"
179};
180
181/*
182 * clock (eeprom) attaches at the sbus or the ebus (PCI)
183 */
184static int	clockmatch_sbus(struct device *, void *, void *);
185static void	clockattach_sbus(struct device *, struct device *, void *);
186static int	clockmatch_ebus(struct device *, void *, void *);
187static void	clockattach_ebus(struct device *, struct device *, void *);
188static int	clockmatch_fhc(struct device *, void *, void *);
189static void	clockattach_fhc(struct device *, struct device *, void *);
190static void	clockattach(int, bus_space_tag_t, bus_space_handle_t);
191
192const struct cfattach clock_sbus_ca = {
193	sizeof(struct device), clockmatch_sbus, clockattach_sbus
194};
195
196const struct cfattach clock_ebus_ca = {
197	sizeof(struct device), clockmatch_ebus, clockattach_ebus
198};
199
200const struct cfattach clock_fhc_ca = {
201	sizeof(struct device), clockmatch_fhc, clockattach_fhc
202};
203
204/* Global TOD clock handle & idprom pointer */
205extern todr_chip_handle_t todr_handle;
206static struct idprom *idprom;
207
208int clock_bus_wenable(struct todr_chip_handle *, int);
209void myetheraddr(u_char *);
210struct idprom *getidprom(void);
211
212/*
213 * The OPENPROM calls the clock the "eeprom", so we have to have our
214 * own special match function to call it the "clock".
215 */
216static int
217clockmatch_sbus(struct device *parent, void *cf, void *aux)
218{
219	struct sbus_attach_args *sa = aux;
220
221	return (strcmp("eeprom", sa->sa_name) == 0);
222}
223
224static int
225clockmatch_ebus(struct device *parent, void *cf, void *aux)
226{
227	struct ebus_attach_args *ea = aux;
228
229	return (strcmp("eeprom", ea->ea_name) == 0);
230}
231
232static int
233clockmatch_fhc(struct device *parent, void *cf, void *aux)
234{
235	struct fhc_attach_args *fa = aux;
236
237	return (strcmp("eeprom", fa->fa_name) == 0);
238}
239
240/*
241 * Attach a clock (really `eeprom') to the sbus or ebus.
242 *
243 * We ignore any existing virtual address as we need to map
244 * this read-only and make it read-write only temporarily,
245 * whenever we read or write the clock chip.  The clock also
246 * contains the ID ``PROM'', and I have already had the pleasure
247 * of reloading the cpu type, Ethernet address, etc, by hand from
248 * the console FORTH interpreter.  I intend not to enjoy it again.
249 *
250 * the MK48T02 is 2K.  the MK48T08 is 8K, and the MK48T59 is
251 * supposed to be identical to it.
252 *
253 * This is *UGLY*!  We probably have multiple mappings.  But I do
254 * know that this all fits inside an 8K page, so I'll just map in
255 * once.
256 *
257 * What we really need is some way to record the bus attach args
258 * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY
259 * or not to write enable/disable the device registers.  This is
260 * a non-trivial operation.
261 */
262
263static void
264clockattach_sbus(struct device *parent, struct device *self, void *aux)
265{
266	struct sbus_attach_args *sa = aux;
267	bus_space_tag_t bt = sa->sa_bustag;
268	int sz;
269	static struct clock_wenable_info cwi;
270
271	/* use sa->sa_regs[0].size? */
272	sz = 8192;
273
274	if (sbus_bus_map(bt,
275			 sa->sa_slot,
276			 (sa->sa_offset & ~NBPG),
277			 sz,
278			 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY,
279			 0, &cwi.cwi_bh) != 0) {
280		printf("%s: can't map register\n", self->dv_xname);
281		return;
282	}
283	clockattach(sa->sa_node, bt, cwi.cwi_bh);
284
285	/* Save info for the clock wenable call. */
286	cwi.cwi_bt = bt;
287	cwi.cwi_size = sz;
288	todr_handle->bus_cookie = &cwi;
289	todr_handle->todr_setwen = clock_bus_wenable;
290}
291
292/*
293 * Write en/dis-able clock registers.  We coordinate so that several
294 * writers can run simultaneously.
295 * XXX There is still a race here.  The page change and the "writers"
296 * change are not atomic.
297 */
298int
299clock_bus_wenable(struct todr_chip_handle *handle, int onoff)
300{
301	int s, err = 0;
302	int prot; /* nonzero => change prot */
303	volatile static int writers;
304	struct clock_wenable_info *cwi = handle->bus_cookie;
305
306	s = splhigh();
307	if (onoff)
308		prot = writers++ == 0 ? 1 : 0;
309	else
310		prot = --writers == 0 ? 1 : 0;
311	splx(s);
312
313	if (prot) {
314		err = bus_space_protect(cwi->cwi_bt, cwi->cwi_bh, cwi->cwi_size,
315		    onoff ? 0 : BUS_SPACE_MAP_READONLY);
316		if (err)
317			printf("clock_wenable_info: WARNING -- cannot %s "
318			    "page protection\n", onoff ? "disable" : "enable");
319	}
320	return (err);
321}
322
323static void
324clockattach_ebus(struct device *parent, struct device *self, void *aux)
325{
326	struct ebus_attach_args *ea = aux;
327	bus_space_tag_t bt;
328	int sz;
329	static struct clock_wenable_info cwi;
330
331	/* hard code to 8K? */
332	sz = ea->ea_regs[0].size;
333
334	if (ebus_bus_map(ea->ea_iotag, 0,
335	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz, 0, 0, &cwi.cwi_bh) == 0) {
336		bt = ea->ea_iotag;
337	} else if (ebus_bus_map(ea->ea_memtag, 0,
338	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz,
339	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY,
340	    0, &cwi.cwi_bh) == 0) {
341		bt = ea->ea_memtag;
342	} else {
343		printf("%s: can't map register\n", self->dv_xname);
344		return;
345	}
346
347	clockattach(ea->ea_node, bt, cwi.cwi_bh);
348
349	/* Save info for the clock wenable call. */
350	cwi.cwi_bt = bt;
351	cwi.cwi_size = sz;
352	todr_handle->bus_cookie = &cwi;
353	todr_handle->todr_setwen = (ea->ea_memtag == bt) ?
354	    clock_bus_wenable : NULL;
355}
356
357static void
358clockattach_fhc(struct device *parent, struct device *self, void *aux)
359{
360	struct fhc_attach_args *fa = aux;
361	bus_space_tag_t bt = fa->fa_bustag;
362	int sz;
363	static struct clock_wenable_info cwi;
364
365	/* use sa->sa_regs[0].size? */
366	sz = 8192;
367
368	if (fhc_bus_map(bt, fa->fa_reg[0].fbr_slot,
369	    (fa->fa_reg[0].fbr_offset & ~NBPG), fa->fa_reg[0].fbr_size,
370	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, &cwi.cwi_bh) != 0) {
371		printf("%s: can't map register\n", self->dv_xname);
372		return;
373	}
374
375	clockattach(fa->fa_node, bt, cwi.cwi_bh);
376
377	/* Save info for the clock wenable call. */
378	cwi.cwi_bt = bt;
379	cwi.cwi_size = sz;
380	todr_handle->bus_cookie = &cwi;
381	todr_handle->todr_setwen = clock_bus_wenable;
382}
383
384static void
385clockattach(int node, bus_space_tag_t bt, bus_space_handle_t bh)
386{
387	char *model;
388	struct idprom *idp;
389	int h;
390
391	model = getpropstring(node, "model");
392
393#ifdef DIAGNOSTIC
394	if (model == NULL)
395		panic("clockattach: no model property");
396#endif
397
398	/* Our TOD clock year 0 is 1968 */
399	if ((todr_handle = mk48txx_attach(bt, bh, model, 1968)) == NULL)
400		panic("Can't attach %s tod clock", model);
401
402#define IDPROM_OFFSET (8*1024 - 40)	/* XXX - get nvram sz from driver */
403	if (idprom == NULL) {
404		idp = getidprom();
405		if (idp == NULL)
406			idp = (struct idprom *)(bus_space_vaddr(bt, bh) +
407			    IDPROM_OFFSET);
408		idprom = idp;
409	} else
410		idp = idprom;
411	h = idp->id_machine << 24;
412	h |= idp->id_hostid[0] << 16;
413	h |= idp->id_hostid[1] << 8;
414	h |= idp->id_hostid[2];
415	hostid = h;
416	printf("\n");
417}
418
419struct idprom *
420getidprom(void)
421{
422	struct idprom *idp = NULL;
423	int node, n;
424
425	node = findroot();
426	if (getprop(node, "idprom", sizeof(*idp), &n, (void **)&idp) != 0)
427		return (NULL);
428	if (n != 1) {
429		free(idp, M_DEVBUF, 0);
430		return (NULL);
431	}
432	return (idp);
433}
434
435/*
436 * XXX this belongs elsewhere
437 */
438void
439myetheraddr(u_char *cp)
440{
441	struct idprom *idp;
442
443	if ((idp = idprom) == NULL) {
444		int node, n;
445
446		node = findroot();
447		if (getprop(node, "idprom", sizeof *idp, &n, (void **)&idp) ||
448		    n != 1) {
449			printf("\nmyetheraddr: clock not setup yet, "
450			       "and no idprom property in /\n");
451			return;
452		}
453	}
454
455	cp[0] = idp->id_ether[0];
456	cp[1] = idp->id_ether[1];
457	cp[2] = idp->id_ether[2];
458	cp[3] = idp->id_ether[3];
459	cp[4] = idp->id_ether[4];
460	cp[5] = idp->id_ether[5];
461	if (idprom == NULL)
462		free(idp, M_DEVBUF, 0);
463}
464
465/*
466 * Set up the real-time and statistics clocks.
467 *
468 * The frequencies of these clocks must be an even number of microseconds.
469 */
470void
471cpu_initclocks(void)
472{
473	u_int sys_tick_rate;
474	int impl = 0;
475
476	if (1000000 % hz) {
477		printf("cannot get %d Hz clock; using 100 Hz\n", hz);
478		hz = 100;
479		tick = 1000000 / hz;
480		tick_nsec = 1000000000 / hz;
481	}
482
483	stathz = hz;
484	profhz = stathz * 10;
485	statclock_is_randomized = 1;
486
487	/* Make sure we have a sane cpu_clockrate -- we'll need it */
488	if (!cpu_clockrate)
489		/* Default to 200MHz clock XXXXX */
490		cpu_clockrate = 200000000;
491
492	tick_timecounter.tc_frequency = cpu_clockrate;
493	tc_init(&tick_timecounter);
494
495	/*
496	 * UltraSPARC IIe processors do have a STICK register, but it
497	 * lives on the PCI host bridge and isn't accessible through
498	 * ASR24.
499	 */
500	if (CPU_ISSUN4U || CPU_ISSUN4US)
501		impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT;
502
503	sys_tick_rate = getpropint(findroot(), "stick-frequency", 0);
504	if (sys_tick_rate > 0 && impl != IMPL_HUMMINGBIRD) {
505		sys_tick_timecounter.tc_frequency = sys_tick_rate;
506		tc_init(&sys_tick_timecounter);
507	}
508
509	struct cpu_info *ci;
510
511	/*
512	 * Establish a level 10 interrupt handler
513	 *
514	 * We will have a conflict with the softint handler,
515	 * so we set the ih_number to 1.
516	 */
517	intr_establish(&level10);
518	evcount_percpu(&level10.ih_count);
519
520	if (sys_tick_rate > 0) {
521		sys_tick_nsec_cycle_ratio =
522		    sys_tick_rate * (1ULL << 32) / 1000000000;
523		sys_tick_nsec_max = UINT64_MAX / sys_tick_nsec_cycle_ratio;
524		if (impl == IMPL_HUMMINGBIRD) {
525			level10.ih_fun = stickintr;
526			cpu_start_clock = stick_start;
527		} else {
528			level10.ih_fun = sys_tickintr;
529			cpu_start_clock = sys_tick_start;
530		}
531	} else {
532		tick_nsec_cycle_ratio =
533		    cpu_clockrate * (1ULL << 32) / 1000000000;
534		tick_nsec_max = UINT64_MAX / tick_nsec_cycle_ratio;
535		level10.ih_fun = tickintr;
536		cpu_start_clock = tick_start;
537	}
538
539	for (ci = cpus; ci != NULL; ci = ci->ci_next)
540		memcpy(&ci->ci_tickintr, &level10, sizeof(level10));
541}
542
543void
544cpu_startclock(void)
545{
546	cpu_start_clock();
547}
548
549void
550setstatclockrate(int newhz)
551{
552}
553
554/*
555 * Level 10 (clock) interrupts.  If we are using the FORTH PROM for
556 * console input, we need to check for that here as well, and generate
557 * a software interrupt to read it.
558 *
559 * %tick is really a level-14 interrupt.  We need to remap this in
560 * locore.s to a level 10.
561 */
562int
563tickintr(void *cap)
564{
565	clockintr_dispatch(cap);
566	evcount_inc(&level10.ih_count);
567	return (1);
568}
569
570int
571sys_tickintr(void *cap)
572{
573	clockintr_dispatch(cap);
574	evcount_inc(&level10.ih_count);
575	return (1);
576}
577
578int
579stickintr(void *cap)
580{
581	clockintr_dispatch(cap);
582	evcount_inc(&level10.ih_count);
583	return (1);
584}
585
586void
587tick_start(void)
588{
589	tick_enable();
590
591	clockintr_cpu_init(&tick_intrclock);
592	clockintr_trigger();
593}
594
595void
596tick_rearm(void *unused, uint64_t nsecs)
597{
598	uint64_t s, t0;
599	uint32_t cycles;
600
601	if (nsecs > tick_nsec_max)
602		nsecs = tick_nsec_max;
603	cycles = (nsecs * tick_nsec_cycle_ratio) >> 32;
604
605	s = intr_disable();
606	t0 = tick();
607	tickcmpr_set((t0 + cycles) & TICK_COUNT_MASK);
608	if (cycles <= ((tick() - t0) & TICK_COUNT_MASK))
609		sparc64_raise_clockintr();
610	intr_restore(s);
611}
612
613void
614tick_trigger(void *unused)
615{
616	sparc64_raise_clockintr();
617}
618
619void
620sys_tick_start(void)
621{
622	if (CPU_ISSUN4U || CPU_ISSUN4US) {
623		tick_enable();
624		sys_tick_enable();
625	}
626
627	clockintr_cpu_init(&sys_tick_intrclock);
628	clockintr_trigger();
629}
630
631void
632sys_tick_rearm(void *unused, uint64_t nsecs)
633{
634	uint64_t s, t0;
635	uint32_t cycles;
636
637	if (nsecs > sys_tick_nsec_max)
638		nsecs = sys_tick_nsec_max;
639	cycles = (nsecs * sys_tick_nsec_cycle_ratio) >> 32;
640
641	s = intr_disable();
642	t0 = sys_tick();
643	sys_tickcmpr_set((t0 + cycles) & STICK_COUNT_MASK);
644	if (cycles <= ((sys_tick() - t0) & STICK_COUNT_MASK))
645		sparc64_raise_clockintr();
646	intr_restore(s);
647}
648
649void
650sys_tick_trigger(void *unused)
651{
652	sparc64_raise_clockintr();
653}
654
655void
656stick_start(void)
657{
658	tick_enable();
659
660	clockintr_cpu_init(&stick_intrclock);
661	clockintr_trigger();
662}
663
664void
665stick_rearm(void *unused, uint64_t nsecs)
666{
667	uint64_t s, t0;
668	uint32_t cycles;
669
670	if (nsecs > sys_tick_nsec_max)
671		nsecs = sys_tick_nsec_max;
672	cycles = (nsecs * sys_tick_nsec_cycle_ratio) >> 32;
673
674	s = intr_disable();
675	t0 = stick();
676	stickcmpr_set((t0 + cycles) & STICK_COUNT_MASK);
677	if (cycles <= ((stick() - t0) & STICK_COUNT_MASK))
678		sparc64_raise_clockintr();
679	intr_restore(s);
680}
681
682void
683stick_trigger(void *unused)
684{
685	sparc64_raise_clockintr();
686}
687
688u_int
689tick_get_timecount(struct timecounter *tc)
690{
691	u_int64_t tick;
692
693	__asm volatile("rd %%tick, %0" : "=r" (tick));
694
695	return (tick & ~0u);
696}
697
698u_int
699sys_tick_get_timecount(struct timecounter *tc)
700{
701	u_int64_t tick;
702
703	__asm volatile("rd %%sys_tick, %0" : "=r" (tick));
704
705	return (tick & ~0u);
706}
707
708void
709sparc64_raise_clockintr(void)
710{
711	send_softint(PIL_CLOCK, &curcpu()->ci_tickintr);
712}
713