1 /* $NetBSD: obio_timer.c,v 1.6 2025/12/19 13:03:51 nia 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 * 91 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 92 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 93 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 94 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT, 95 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 96 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 97 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 98 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 99 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 100 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 101 * SUCH DAMAGE. 102 */ 103 104 #include <sys/cdefs.h> 105 __KERNEL_RCSID(0, "$NetBSD: obio_timer.c,v 1.6 2025/12/19 13:03:51 nia Exp $"); 106 107 #include "opt_cpuoptions.h" 108 #include "opt_gemini.h" 109 #include "locators.h" 110 111 #include <sys/types.h> 112 #include <sys/param.h> 113 #include <sys/systm.h> 114 #include <sys/kernel.h> 115 #include <sys/time.h> 116 #include <sys/device.h> 117 118 #include <dev/clock_subr.h> 119 120 #include <sys/bus.h> 121 #include <machine/intr.h> 122 123 #include <arm/gemini/gemini_reg.h> 124 #include <arm/gemini/gemini_obiovar.h> 125 #include <arm/gemini/gemini_timervar.h> 126 127 #if STATHZ != HZ 128 # error system clock HZ and stat clock STATHZ must be same 129 #endif 130 131 132 #ifndef GEMINI_TIMER_CLOCK_FREQ 133 # error Specify the timer frequency in Hz with option GEMINI_TIMER_CLOCK_FREQ 134 #endif 135 136 static int obiotimer_match(device_t, struct cfdata *, void *); 137 static void obiotimer_attach(device_t, device_t, void *); 138 139 struct geminitmr_softc xsc; 140 141 142 143 typedef struct { 144 uint timerno; 145 bus_addr_t addr; 146 uint intr; 147 } obiotimer_instance_t; 148 149 /* XXX 150 * this table can be used to match the GP Timers 151 * until we use config(8) locators to distinguish between 152 * gemini "sub-timers". 153 */ 154 #define GPT_ENTRY(n, i) { \ 155 .timerno = (n), \ 156 .addr = GEMINI_TIMER_BASE, \ 157 .intr = i, \ 158 } 159 static const obiotimer_instance_t obiotimer_instance_tab[] = { 160 GPT_ENTRY(1, 14), 161 GPT_ENTRY(2, 15), 162 GPT_ENTRY(3, 16), 163 }; 164 #undef GPT_ENTRY 165 #define GPTIMER_INSTANCE_CNT __arraycount(obiotimer_instance_tab) 166 167 static const obiotimer_instance_t * 168 obiotimer_lookup(struct obio_attach_args *); 169 static void obiotimer_enable(struct geminitmr_softc *, 170 struct obio_attach_args *, 171 const obiotimer_instance_t *); 172 173 static int obiotimer_match(device_t, struct cfdata *, void *); 174 static void obiotimer_attach(device_t, device_t, void *); 175 176 177 CFATTACH_DECL_NEW(obiotimer, sizeof(struct geminitmr_softc), 178 obiotimer_match, obiotimer_attach, NULL, NULL); 179 180 181 static int 182 obiotimer_match(device_t parent, struct cfdata *match, void *aux) 183 { 184 struct obio_attach_args *obio = aux; 185 186 if ((obio->obio_addr == OBIOCF_ADDR_DEFAULT) 187 || (obio->obio_intr == OBIOCF_INTR_DEFAULT)) 188 panic("geminitmr must have addr and intr specified in config."); 189 190 if (obiotimer_lookup(obio) == NULL) 191 return 0; 192 193 return 1; 194 } 195 196 void 197 obiotimer_attach(device_t parent, device_t self, void *aux) 198 { 199 struct geminitmr_softc *sc = device_private(self); 200 struct obio_attach_args *obio = aux; 201 const obiotimer_instance_t *ip; 202 #ifndef GEMINI_SLAVE 203 static int once=1; 204 #endif 205 206 ip = obiotimer_lookup(obio); 207 if (ip == NULL) 208 panic("%s: bad lookup", device_xname(self)); 209 /* should not fail since we already matched */ 210 211 sc->sc_timerno = ip->timerno; 212 sc->sc_iot = obio->obio_iot; 213 sc->sc_intr = obio->obio_intr; 214 sc->sc_addr = obio->obio_addr; 215 sc->sc_size = (obio->obio_size == OBIOCF_SIZE_DEFAULT) 216 ? (GEMINI_TIMER_INTRMASK + 4) 217 : obio->obio_size; 218 219 if (bus_space_map(sc->sc_iot, sc->sc_addr, sc->sc_size, 0, &sc->sc_ioh)) 220 panic("%s: Cannot map registers", device_xname(self)); 221 222 obiotimer_enable(sc, obio, obiotimer_lookup(obio)); 223 aprint_normal("\n"); 224 aprint_naive("\n"); 225 226 #ifndef GEMINI_SLAVE 227 if (once) { 228 once = 0; 229 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 230 GEMINI_TIMER_TMCR, 0); 231 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 232 GEMINI_TIMER_INTRMASK, (uint32_t)~TIMER_INTRMASK_Resv); 233 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 234 GEMINI_TIMER_INTRSTATE, 0); 235 } 236 #endif 237 238 switch (sc->sc_timerno) { 239 case 1: 240 #ifndef GEMINI_SLAVE 241 /* 242 * timer #1 is the combined system clock and stat clock 243 * for the Master or Single Gemini CPU 244 * it gets started later 245 */ 246 profhz = stathz = hz; 247 stat_sc = clock_sc = sc; 248 #endif 249 break; 250 case 2: 251 #ifdef GEMINI_SLAVE 252 /* 253 * timer #2 is the combined system clock and stat clock 254 * for the Slave Gemini CPU 255 * it gets started later 256 */ 257 profhz = stathz = hz; 258 stat_sc = clock_sc = sc; 259 #endif 260 break; 261 case 3: 262 /* 263 * Timer #3 is used for microtime reference clock and delay() 264 * autoloading, non-interrupting, just wraps around 265 * we start it now to make delay() available 266 */ 267 ref_sc = sc; 268 #ifndef GEMINI_SLAVE 269 gemini_microtime_init(); 270 #endif 271 break; 272 default: 273 panic("bad gemini timer number %d\n", sc->sc_timerno); 274 break; 275 } 276 } 277 278 static const obiotimer_instance_t * 279 obiotimer_lookup(struct obio_attach_args *obio) 280 { 281 const obiotimer_instance_t *ip; 282 uint i; 283 284 for (i = 0, ip = obiotimer_instance_tab; 285 i < GPTIMER_INSTANCE_CNT; i++, ip++) { 286 if (ip->addr == obio->obio_addr && ip->intr == obio->obio_intr) 287 return ip; 288 } 289 290 return NULL; 291 } 292 293 void 294 obiotimer_enable( 295 struct geminitmr_softc *sc, 296 struct obio_attach_args *obio, 297 const obiotimer_instance_t *ip) 298 { 299 /* nothing to do */ 300 } 301