1/*	$NetBSD: obio_timer.c,v 1.4 2008/12/04 00:38:07 cliff Exp $	*/
2
3/* adapted from:
4 *	NetBSD: obio_mputmr.c,v 1.3 2008/08/27 11:03:10 matt Exp
5 */
6
7/*
8 * Based on omap_mputmr.c
9 * Based on i80321_timer.c and arch/arm/sa11x0/sa11x0_ost.c
10 *
11 * Copyright (c) 1997 Mark Brinicombe.
12 * Copyright (c) 1997 Causality Limited.
13 * All rights reserved.
14 *
15 * This code is derived from software contributed to The NetBSD Foundation
16 * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 * 3. All advertising materials mentioning features or use of this software
27 *    must display the following acknowledgement:
28 *	This product includes software developed by the NetBSD
29 *	Foundation, Inc. and its contributors.
30 * 4. Neither the name of The NetBSD Foundation nor the names of its
31 *    contributors may be used to endorse or promote products derived
32 *    from this software without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
35 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44 * POSSIBILITY OF SUCH DAMAGE.
45 *
46 * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
47 * All rights reserved.
48 *
49 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 *    notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 *    notice, this list of conditions and the following disclaimer in the
58 *    documentation and/or other materials provided with the distribution.
59 * 3. All advertising materials mentioning features or use of this software
60 *    must display the following acknowledgement:
61 *	This product includes software developed for the NetBSD Project by
62 *	Wasabi Systems, Inc.
63 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
64 *    or promote products derived from this software without specific prior
65 *    written permission.
66 *
67 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
68 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
69 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
70 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
71 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
72 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
73 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
74 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
75 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
76 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
77 * POSSIBILITY OF SUCH DAMAGE.
78 *
79 * Copyright (c) 2007 Microsoft
80 * All rights reserved.
81 *
82 * Redistribution and use in source and binary forms, with or without
83 * modification, are permitted provided that the following conditions
84 * are met:
85 * 1. Redistributions of source code must retain the above copyright
86 *    notice, this list of conditions and the following disclaimer.
87 * 2. Redistributions in binary form must reproduce the above copyright
88 *    notice, this list of conditions and the following disclaimer in the
89 *    documentation and/or other materials provided with the distribution.
90 * 3. All advertising materials mentioning features or use of this software
91 *    must display the following acknowledgement:
92 *	This product includes software developed by Microsoft
93 *
94 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
95 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
96 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
97 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
98 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
99 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
100 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
101 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
102 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
103 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
104 * SUCH DAMAGE.
105 */
106
107#include <sys/cdefs.h>
108__KERNEL_RCSID(0, "$NetBSD: obio_timer.c,v 1.4 2008/12/04 00:38:07 cliff Exp $");
109
110#include "opt_cpuoptions.h"
111#include "opt_gemini.h"
112#include "locators.h"
113
114#include <sys/types.h>
115#include <sys/param.h>
116#include <sys/systm.h>
117#include <sys/kernel.h>
118#include <sys/time.h>
119#include <sys/device.h>
120
121#include <dev/clock_subr.h>
122
123#include <sys/bus.h>
124#include <machine/intr.h>
125
126#include <arm/gemini/gemini_reg.h>
127#include <arm/gemini/gemini_obiovar.h>
128#include <arm/gemini/gemini_timervar.h>
129
130#if STATHZ != HZ
131# error system clock HZ and stat clock STATHZ must be same
132#endif
133
134
135#ifndef GEMINI_TIMER_CLOCK_FREQ
136# error Specify the timer frequency in Hz with option GEMINI_TIMER_CLOCK_FREQ
137#endif
138
139static int	obiotimer_match(device_t, struct cfdata *, void *);
140static void	obiotimer_attach(device_t, device_t, void *);
141
142struct geminitmr_softc xsc;
143
144
145
146typedef struct {
147	uint       timerno;
148	bus_addr_t addr;
149	uint       intr;
150} obiotimer_instance_t;
151
152/* XXX
153 * this table can be used to match the GP Timers
154 * until we use config(8) locators to distinguish between
155 * gemini "sub-timers".
156 */
157#define GPT_ENTRY(n, i) { \
158		.timerno = (n), \
159		.addr = GEMINI_TIMER_BASE, \
160		.intr = i, \
161	}
162static const obiotimer_instance_t obiotimer_instance_tab[] = {
163	GPT_ENTRY(1, 14),
164	GPT_ENTRY(2, 15),
165	GPT_ENTRY(3, 16),
166};
167#undef	GPT_ENTRY
168#define GPTIMER_INSTANCE_CNT	__arraycount(obiotimer_instance_tab)
169
170static const obiotimer_instance_t *
171		obiotimer_lookup(struct obio_attach_args *);
172static void	obiotimer_enable(struct geminitmr_softc *,
173			struct obio_attach_args *,
174			const obiotimer_instance_t *);
175
176static int	obiotimer_match(device_t, struct cfdata *, void *);
177static void	obiotimer_attach(device_t, device_t, void *);
178
179
180CFATTACH_DECL_NEW(obiotimer, sizeof(struct geminitmr_softc),
181    obiotimer_match, obiotimer_attach, NULL, NULL);
182
183
184static int
185obiotimer_match(device_t parent, struct cfdata *match, void *aux)
186{
187	struct obio_attach_args *obio = aux;
188
189	if ((obio->obio_addr == OBIOCF_ADDR_DEFAULT)
190	||  (obio->obio_intr == OBIOCF_INTR_DEFAULT))
191		panic("geminitmr must have addr and intr specified in config.");
192
193	if (obiotimer_lookup(obio) == NULL)
194		return 0;
195
196	return 1;
197}
198
199void
200obiotimer_attach(device_t parent, device_t self, void *aux)
201{
202	struct geminitmr_softc *sc = device_private(self);
203	struct obio_attach_args *obio = aux;
204	const obiotimer_instance_t *ip;
205#ifndef GEMINI_SLAVE
206	static int once=1;
207#endif
208
209	ip = obiotimer_lookup(obio);
210	if (ip == NULL)
211		panic("%s: bad lookup", device_xname(self));
212			/* should not fail since we already matched */
213
214	sc->sc_timerno = ip->timerno;
215	sc->sc_iot = obio->obio_iot;
216	sc->sc_intr = obio->obio_intr;
217	sc->sc_addr = obio->obio_addr;
218	sc->sc_size = (obio->obio_size == OBIOCF_SIZE_DEFAULT)
219		? (GEMINI_TIMER_INTRMASK + 4)
220		: obio->obio_size;
221
222	if (bus_space_map(sc->sc_iot, sc->sc_addr, sc->sc_size, 0, &sc->sc_ioh))
223		panic("%s: Cannot map registers", device_xname(self));
224
225	obiotimer_enable(sc, obio, obiotimer_lookup(obio));
226	aprint_normal("\n");
227	aprint_naive("\n");
228
229#ifndef GEMINI_SLAVE
230	if (once) {
231		once = 0;
232		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
233			GEMINI_TIMER_TMCR, 0);
234		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
235			GEMINI_TIMER_INTRMASK, (uint32_t)~TIMER_INTRMASK_Resv);
236		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
237			GEMINI_TIMER_INTRSTATE, 0);
238	}
239#endif
240
241	switch (sc->sc_timerno) {
242	case 1:
243#ifndef GEMINI_SLAVE
244		/*
245		 * timer #1 is the combined system clock and stat clock
246		 * for the Master or Single Gemini CPU
247		 * it gets started later
248		 */
249		profhz = stathz = hz;
250		stat_sc = clock_sc = sc;
251#endif
252		break;
253	case 2:
254#ifdef GEMINI_SLAVE
255		/*
256		 * timer #2 is the combined system clock and stat clock
257		 * for the Slave Gemini CPU
258		 * it gets started later
259		 */
260		profhz = stathz = hz;
261		stat_sc = clock_sc = sc;
262#endif
263		break;
264	case 3:
265		/*
266		 * Timer #3 is used for microtime reference clock and delay()
267		 * autoloading, non-interrupting, just wraps around
268		 * we start it now to make delay() available
269		 */
270		ref_sc = sc;
271#ifndef GEMINI_SLAVE
272		gemini_microtime_init();
273#endif
274		break;
275	default:
276		panic("bad gemini timer number %d\n", sc->sc_timerno);
277		break;
278	}
279}
280
281static const obiotimer_instance_t *
282obiotimer_lookup(struct obio_attach_args *obio)
283{
284	const obiotimer_instance_t *ip;
285	uint i;
286
287	for (i = 0, ip = obiotimer_instance_tab;
288	     i < GPTIMER_INSTANCE_CNT; i++, ip++) {
289		if (ip->addr == obio->obio_addr && ip->intr == obio->obio_intr)
290			return ip;
291	}
292
293	return NULL;
294}
295
296void
297obiotimer_enable(
298	struct geminitmr_softc *sc,
299	struct obio_attach_args *obio,
300	const obiotimer_instance_t *ip)
301{
302	/* nothing to do */
303}
304