xref: /netbsd-src/sys/arch/news68k/dev/timer_hb.c (revision 88c4775d9b21b8bca7c5f35a924b2f6958659492)
1*88c4775dSthorpej /*	$NetBSD: timer_hb.c,v 1.21 2024/01/15 20:21:50 thorpej Exp $	*/
2d49986b1Stsutsui 
3d49986b1Stsutsui /*-
4d49986b1Stsutsui  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5d49986b1Stsutsui  * All rights reserved.
6d49986b1Stsutsui  *
7d49986b1Stsutsui  * This code is derived from software contributed to The NetBSD Foundation
8d49986b1Stsutsui  * by Jason R. Thorpe.
9d49986b1Stsutsui  *
10d49986b1Stsutsui  * Redistribution and use in source and binary forms, with or without
11d49986b1Stsutsui  * modification, are permitted provided that the following conditions
12d49986b1Stsutsui  * are met:
13d49986b1Stsutsui  * 1. Redistributions of source code must retain the above copyright
14d49986b1Stsutsui  *    notice, this list of conditions and the following disclaimer.
15d49986b1Stsutsui  * 2. Redistributions in binary form must reproduce the above copyright
16d49986b1Stsutsui  *    notice, this list of conditions and the following disclaimer in the
17d49986b1Stsutsui  *    documentation and/or other materials provided with the distribution.
18d49986b1Stsutsui  *
19d49986b1Stsutsui  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20d49986b1Stsutsui  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21d49986b1Stsutsui  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22d49986b1Stsutsui  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23d49986b1Stsutsui  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24d49986b1Stsutsui  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25d49986b1Stsutsui  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26d49986b1Stsutsui  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27d49986b1Stsutsui  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28d49986b1Stsutsui  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29d49986b1Stsutsui  * POSSIBILITY OF SUCH DAMAGE.
30d49986b1Stsutsui  */
31d49986b1Stsutsui 
32ed517291Slukem #include <sys/cdefs.h>
33*88c4775dSthorpej __KERNEL_RCSID(0, "$NetBSD: timer_hb.c,v 1.21 2024/01/15 20:21:50 thorpej Exp $");
34ed517291Slukem 
35d49986b1Stsutsui #include <sys/param.h>
36d49986b1Stsutsui #include <sys/kernel.h>
37d49986b1Stsutsui #include <sys/systm.h>
38d49986b1Stsutsui #include <sys/device.h>
3903242949Stsutsui #include <sys/intr.h>
40d49986b1Stsutsui 
41d49986b1Stsutsui #include <uvm/uvm_extern.h>
42d49986b1Stsutsui 
43d49986b1Stsutsui #include <machine/cpu.h>
44d49986b1Stsutsui #include <machine/bus.h>
45e157db6cSthorpej #include <machine/vectors.h>
46d49986b1Stsutsui 
47d49986b1Stsutsui #include <dev/clock_subr.h>
48d49986b1Stsutsui 
49d49986b1Stsutsui #include <news68k/news68k/isr.h>
50d49986b1Stsutsui #include <news68k/news68k/clockvar.h>
51d49986b1Stsutsui 
52d49986b1Stsutsui #include <news68k/dev/hbvar.h>
53d49986b1Stsutsui 
54378871cdStsutsui #include "ioconf.h"
55378871cdStsutsui 
56d49986b1Stsutsui /*
57d49986b1Stsutsui  * interrupt level for clock
58d49986b1Stsutsui  */
59d49986b1Stsutsui 
60d49986b1Stsutsui #define TIMER_LEVEL 6
61d49986b1Stsutsui #define TIMER_SIZE 8	/* XXX */
62d49986b1Stsutsui 
63820a544dStsutsui static int timer_hb_match(device_t, cfdata_t, void *);
64820a544dStsutsui static void timer_hb_attach(device_t, device_t, void *);
6552b46dcfStsutsui static void timer_hb_initclocks(int, int);
66e157db6cSthorpej void clock_intr(struct clockframe);
67d49986b1Stsutsui 
685f1c88d7Sperry static inline void leds_intr(void);
69d49986b1Stsutsui 
700687b33bStsutsui extern void _isr_clock(void);	/* locore.s */
71d49986b1Stsutsui 
72820a544dStsutsui CFATTACH_DECL_NEW(timer_hb, 0,
73021b694dSthorpej     timer_hb_match, timer_hb_attach, NULL, NULL);
74d49986b1Stsutsui 
753725e983Stsutsui static volatile uint8_t *ctrl_timer; /* XXX */
76d49986b1Stsutsui 
77d49986b1Stsutsui extern volatile u_char *ctrl_led; /* XXX */
78d49986b1Stsutsui 
7952b46dcfStsutsui static int
timer_hb_match(device_t parent,cfdata_t cf,void * aux)80820a544dStsutsui timer_hb_match(device_t parent, cfdata_t cf, void *aux)
81d49986b1Stsutsui {
82d49986b1Stsutsui 	struct hb_attach_args *ha = aux;
83d49986b1Stsutsui 	static int timer_hb_matched;
84d49986b1Stsutsui 
85d49986b1Stsutsui 	/* Only one timer, please. */
86d49986b1Stsutsui 	if (timer_hb_matched)
8752b46dcfStsutsui 		return 0;
88d49986b1Stsutsui 
89d49986b1Stsutsui 	if (strcmp(ha->ha_name, timer_cd.cd_name))
9052b46dcfStsutsui 		return 0;
91d49986b1Stsutsui 
92d49986b1Stsutsui 	if (ha->ha_ipl == -1)
93d49986b1Stsutsui 		ha->ha_ipl = TIMER_LEVEL;
94d49986b1Stsutsui 
95d49986b1Stsutsui 	ha->ha_size = TIMER_SIZE;
96d49986b1Stsutsui 
97d49986b1Stsutsui 	timer_hb_matched = 1;
98d49986b1Stsutsui 
99d49986b1Stsutsui 	return 1;
100d49986b1Stsutsui }
101d49986b1Stsutsui 
10252b46dcfStsutsui static void
timer_hb_attach(device_t parent,device_t self,void * aux)103820a544dStsutsui timer_hb_attach(device_t parent, device_t self, void *aux)
104d49986b1Stsutsui {
105d49986b1Stsutsui 	struct hb_attach_args *ha = aux;
106d49986b1Stsutsui 
107d49986b1Stsutsui 	if (ha->ha_ipl != TIMER_LEVEL)
108d49986b1Stsutsui 		panic("clock_hb_attach: wrong interrupt level");
109d49986b1Stsutsui 
11043993578Stsutsui 	ctrl_timer = (uint8_t *)(ha->ha_address); /* XXX needs bus_space */
111d49986b1Stsutsui 
112d49986b1Stsutsui 	printf("\n");
113d49986b1Stsutsui 
114d49986b1Stsutsui 	timer_config(timer_hb_initclocks);
115d49986b1Stsutsui 
116d49986b1Stsutsui #if 0 /* XXX this will be done in timer_hb_initclocks() */
117e157db6cSthorpej 	vec_set_entry(VECI_INTRAV0 + ha->ha_ipl, _isr_clock);
118d49986b1Stsutsui #endif
119d49986b1Stsutsui }
120d49986b1Stsutsui 
121d49986b1Stsutsui /*
122d49986b1Stsutsui  * Set up the interval timer (enable clock interrupts).
123d49986b1Stsutsui  * Leave stathz 0 since there is no secondary clock available.
124d49986b1Stsutsui  * Note that clock interrupts MUST STAY DISABLED until here.
125d49986b1Stsutsui  */
12652b46dcfStsutsui static void
timer_hb_initclocks(int prof,int stat)12711d4655dStsutsui timer_hb_initclocks(int prof, int stat)
128d49986b1Stsutsui {
129d49986b1Stsutsui 	int s;
130d49986b1Stsutsui 
131d49986b1Stsutsui 	s = splhigh();
132d49986b1Stsutsui 
133d49986b1Stsutsui 	/* Install isr (in locore.s) that calls clock_intr(). */
134e157db6cSthorpej 	vec_set_entry(VECI_INTRAV0 + TIMER_LEVEL, _isr_clock);
135d49986b1Stsutsui 
136d49986b1Stsutsui 	/* enable the clock */
137d49986b1Stsutsui 	*ctrl_timer = 1;
138d49986b1Stsutsui 	splx(s);
139d49986b1Stsutsui }
140d49986b1Stsutsui 
141d49986b1Stsutsui /*
142d49986b1Stsutsui  * Clock interrupt handler.
14345aabfbeSmbalmer  * This is called by the "custom" interrupt handler.
144d49986b1Stsutsui  *
145d49986b1Stsutsui  * from sun3/sun3x/clock.c -tsutsui
146d49986b1Stsutsui  */
147d49986b1Stsutsui void
clock_intr(struct clockframe cf)148e157db6cSthorpej clock_intr(struct clockframe cf)
149d49986b1Stsutsui {
150d49986b1Stsutsui #ifdef	LED_IDLE_CHECK
151d49986b1Stsutsui 	extern char _Idle[];	/* locore.s */
152d49986b1Stsutsui #endif
153d49986b1Stsutsui 
154d49986b1Stsutsui 	/* Pulse the clock intr. enable low. */
155d49986b1Stsutsui 	*ctrl_timer = 0;
156d49986b1Stsutsui 	*ctrl_timer = 1;
157*88c4775dSthorpej 
158*88c4775dSthorpej 	m68k_count_intr(TIMER_LEVEL);
159d49986b1Stsutsui 
160d49986b1Stsutsui 	/* Entertainment! */
161d49986b1Stsutsui #ifdef	LED_IDLE_CHECK
162d49986b1Stsutsui 	if (cf.cf_pc == (long)_Idle)
163d49986b1Stsutsui #endif
164d49986b1Stsutsui 		leds_intr();
165d49986b1Stsutsui 
166d49986b1Stsutsui 	/* Call common clock interrupt handler. */
167e157db6cSthorpej 	hardclock(&cf);
168d49986b1Stsutsui }
169d49986b1Stsutsui 
170d49986b1Stsutsui /* heartbeat LED */
171d49986b1Stsutsui #define LED0	0x01
172d49986b1Stsutsui #define LED1	0x02
173d49986b1Stsutsui 
1745f1c88d7Sperry static inline void
leds_intr(void)17552b46dcfStsutsui leds_intr(void)
176d49986b1Stsutsui {
177d49986b1Stsutsui 	static u_char led_countdown, led_stat;
178d49986b1Stsutsui 	u_char i;
179d49986b1Stsutsui 
180d49986b1Stsutsui 	if (led_countdown) {
181d49986b1Stsutsui 		led_countdown--;
182d49986b1Stsutsui 		return;
183d49986b1Stsutsui 	}
184d49986b1Stsutsui 
185d49986b1Stsutsui 	i = led_stat ^ LED0;
186d49986b1Stsutsui 	*ctrl_led = i;
187d49986b1Stsutsui 	led_stat = i;
188d49986b1Stsutsui 	led_countdown = hz;
189d49986b1Stsutsui }
190d49986b1Stsutsui 
191