1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org> 5 * Copyright (c) 2012 Damjan Marion <dmarion@freebsd.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/bus.h> 36 #include <sys/kernel.h> 37 #include <sys/module.h> 38 #include <sys/malloc.h> 39 40 #include <sys/timeet.h> 41 #include <sys/timetc.h> 42 #include <sys/watchdog.h> 43 #include <machine/bus.h> 44 #include <machine/cpu.h> 45 #include <machine/intr.h> 46 47 #include <machine/machdep.h> /* For arm_set_delay */ 48 49 #include <dev/ofw/openfirm.h> 50 #include <dev/ofw/ofw_bus.h> 51 #include <dev/ofw/ofw_bus_subr.h> 52 53 #include <machine/bus.h> 54 55 #define SP804_TIMER1_LOAD 0x00 56 #define SP804_TIMER1_VALUE 0x04 57 #define SP804_TIMER1_CONTROL 0x08 58 #define TIMER_CONTROL_EN (1 << 7) 59 #define TIMER_CONTROL_FREERUN (0 << 6) 60 #define TIMER_CONTROL_PERIODIC (1 << 6) 61 #define TIMER_CONTROL_INTREN (1 << 5) 62 #define TIMER_CONTROL_DIV1 (0 << 2) 63 #define TIMER_CONTROL_DIV16 (1 << 2) 64 #define TIMER_CONTROL_DIV256 (2 << 2) 65 #define TIMER_CONTROL_32BIT (1 << 1) 66 #define TIMER_CONTROL_ONESHOT (1 << 0) 67 #define SP804_TIMER1_INTCLR 0x0C 68 #define SP804_TIMER1_RIS 0x10 69 #define SP804_TIMER1_MIS 0x14 70 #define SP804_TIMER1_BGLOAD 0x18 71 #define SP804_TIMER2_LOAD 0x20 72 #define SP804_TIMER2_VALUE 0x24 73 #define SP804_TIMER2_CONTROL 0x28 74 #define SP804_TIMER2_INTCLR 0x2C 75 #define SP804_TIMER2_RIS 0x30 76 #define SP804_TIMER2_MIS 0x34 77 #define SP804_TIMER2_BGLOAD 0x38 78 79 #define SP804_PERIPH_ID0 0xFE0 80 #define SP804_PERIPH_ID1 0xFE4 81 #define SP804_PERIPH_ID2 0xFE8 82 #define SP804_PERIPH_ID3 0xFEC 83 #define SP804_PRIMECELL_ID0 0xFF0 84 #define SP804_PRIMECELL_ID1 0xFF4 85 #define SP804_PRIMECELL_ID2 0xFF8 86 #define SP804_PRIMECELL_ID3 0xFFC 87 88 #define DEFAULT_FREQUENCY 1000000 89 /* 90 * QEMU seems to have problem with full frequency 91 */ 92 #define DEFAULT_DIVISOR 16 93 #define DEFAULT_CONTROL_DIV TIMER_CONTROL_DIV16 94 95 struct sp804_timer_softc { 96 struct resource* mem_res; 97 struct resource* irq_res; 98 void* intr_hl; 99 uint32_t sysclk_freq; 100 bus_space_tag_t bst; 101 bus_space_handle_t bsh; 102 struct timecounter tc; 103 bool et_enabled; 104 struct eventtimer et; 105 int timer_initialized; 106 }; 107 108 /* Read/Write macros for Timer used as timecounter */ 109 #define sp804_timer_tc_read_4(reg) \ 110 bus_space_read_4(sc->bst, sc->bsh, reg) 111 112 #define sp804_timer_tc_write_4(reg, val) \ 113 bus_space_write_4(sc->bst, sc->bsh, reg, val) 114 115 static unsigned sp804_timer_tc_get_timecount(struct timecounter *); 116 static void sp804_timer_delay(int, void *); 117 118 static unsigned 119 sp804_timer_tc_get_timecount(struct timecounter *tc) 120 { 121 struct sp804_timer_softc *sc = tc->tc_priv; 122 return 0xffffffff - sp804_timer_tc_read_4(SP804_TIMER1_VALUE); 123 } 124 125 static int 126 sp804_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) 127 { 128 struct sp804_timer_softc *sc = et->et_priv; 129 uint32_t count, reg; 130 131 if (first != 0) { 132 sc->et_enabled = 1; 133 134 count = ((uint32_t)et->et_frequency * first) >> 32; 135 136 sp804_timer_tc_write_4(SP804_TIMER2_LOAD, count); 137 reg = TIMER_CONTROL_32BIT | TIMER_CONTROL_INTREN | 138 TIMER_CONTROL_PERIODIC | DEFAULT_CONTROL_DIV | 139 TIMER_CONTROL_EN; 140 sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, reg); 141 142 return (0); 143 } 144 145 if (period != 0) { 146 panic("period"); 147 } 148 149 return (EINVAL); 150 } 151 152 static int 153 sp804_timer_stop(struct eventtimer *et) 154 { 155 struct sp804_timer_softc *sc = et->et_priv; 156 uint32_t reg; 157 158 sc->et_enabled = 0; 159 reg = sp804_timer_tc_read_4(SP804_TIMER2_CONTROL); 160 reg &= ~(TIMER_CONTROL_EN); 161 sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, reg); 162 163 return (0); 164 } 165 166 static int 167 sp804_timer_intr(void *arg) 168 { 169 struct sp804_timer_softc *sc = arg; 170 static uint32_t prev = 0; 171 uint32_t x = 0; 172 173 x = sp804_timer_tc_read_4(SP804_TIMER1_VALUE); 174 175 prev =x ; 176 sp804_timer_tc_write_4(SP804_TIMER2_INTCLR, 1); 177 if (sc->et_enabled) { 178 if (sc->et.et_active) { 179 sc->et.et_event_cb(&sc->et, sc->et.et_arg); 180 } 181 } 182 183 return (FILTER_HANDLED); 184 } 185 186 static int 187 sp804_timer_probe(device_t dev) 188 { 189 190 if (!ofw_bus_status_okay(dev)) 191 return (ENXIO); 192 193 if (ofw_bus_is_compatible(dev, "arm,sp804")) { 194 device_set_desc(dev, "SP804 System Timer"); 195 return (BUS_PROBE_DEFAULT); 196 } 197 198 return (ENXIO); 199 } 200 201 static int 202 sp804_timer_attach(device_t dev) 203 { 204 struct sp804_timer_softc *sc = device_get_softc(dev); 205 int rid = 0; 206 int i; 207 uint32_t id, reg; 208 phandle_t node; 209 pcell_t clock; 210 211 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 212 if (sc->mem_res == NULL) { 213 device_printf(dev, "could not allocate memory resource\n"); 214 return (ENXIO); 215 } 216 217 sc->bst = rman_get_bustag(sc->mem_res); 218 sc->bsh = rman_get_bushandle(sc->mem_res); 219 220 /* Request the IRQ resources */ 221 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 222 if (sc->irq_res == NULL) { 223 device_printf(dev, "Error: could not allocate irq resources\n"); 224 return (ENXIO); 225 } 226 227 sc->sysclk_freq = DEFAULT_FREQUENCY; 228 /* Get the base clock frequency */ 229 node = ofw_bus_get_node(dev); 230 if ((OF_getencprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) { 231 sc->sysclk_freq = clock; 232 } 233 234 /* Setup and enable the timer */ 235 if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK, 236 sp804_timer_intr, NULL, sc, 237 &sc->intr_hl) != 0) { 238 bus_release_resource(dev, SYS_RES_IRQ, rid, 239 sc->irq_res); 240 device_printf(dev, "Unable to setup the clock irq handler.\n"); 241 return (ENXIO); 242 } 243 244 sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, 0); 245 sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, 0); 246 247 /* 248 * Timer 1, timecounter 249 */ 250 sc->tc.tc_frequency = sc->sysclk_freq; 251 sc->tc.tc_name = "SP804-1"; 252 sc->tc.tc_get_timecount = sp804_timer_tc_get_timecount; 253 sc->tc.tc_poll_pps = NULL; 254 sc->tc.tc_counter_mask = ~0u; 255 sc->tc.tc_quality = 1000; 256 sc->tc.tc_priv = sc; 257 258 sp804_timer_tc_write_4(SP804_TIMER1_VALUE, 0xffffffff); 259 sp804_timer_tc_write_4(SP804_TIMER1_LOAD, 0xffffffff); 260 reg = TIMER_CONTROL_PERIODIC | TIMER_CONTROL_32BIT; 261 sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, reg); 262 reg |= TIMER_CONTROL_EN; 263 sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, reg); 264 tc_init(&sc->tc); 265 266 /* 267 * Timer 2, event timer 268 */ 269 sc->et_enabled = 0; 270 sc->et.et_name = "SP804-2"; 271 sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; 272 sc->et.et_quality = 1000; 273 sc->et.et_frequency = sc->sysclk_freq / DEFAULT_DIVISOR; 274 sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency; 275 sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; 276 sc->et.et_start = sp804_timer_start; 277 sc->et.et_stop = sp804_timer_stop; 278 sc->et.et_priv = sc; 279 et_register(&sc->et); 280 281 id = 0; 282 for (i = 3; i >= 0; i--) { 283 id = (id << 8) | 284 (sp804_timer_tc_read_4(SP804_PERIPH_ID0 + i*4) & 0xff); 285 } 286 287 device_printf(dev, "peripheral ID: %08x\n", id); 288 289 id = 0; 290 for (i = 3; i >= 0; i--) { 291 id = (id << 8) | 292 (sp804_timer_tc_read_4(SP804_PRIMECELL_ID0 + i*4) & 0xff); 293 } 294 295 arm_set_delay(sp804_timer_delay, sc); 296 297 device_printf(dev, "PrimeCell ID: %08x\n", id); 298 299 sc->timer_initialized = 1; 300 301 return (0); 302 } 303 304 static device_method_t sp804_timer_methods[] = { 305 DEVMETHOD(device_probe, sp804_timer_probe), 306 DEVMETHOD(device_attach, sp804_timer_attach), 307 { 0, 0 } 308 }; 309 310 static driver_t sp804_timer_driver = { 311 "timer", 312 sp804_timer_methods, 313 sizeof(struct sp804_timer_softc), 314 }; 315 316 static devclass_t sp804_timer_devclass; 317 318 DRIVER_MODULE(sp804_timer, simplebus, sp804_timer_driver, sp804_timer_devclass, 0, 0); 319 320 static void 321 sp804_timer_delay(int usec, void *arg) 322 { 323 struct sp804_timer_softc *sc = arg; 324 int32_t counts; 325 uint32_t first, last; 326 327 /* Get the number of times to count */ 328 counts = usec * ((sc->tc.tc_frequency / 1000000) + 1); 329 330 first = sp804_timer_tc_get_timecount(&sc->tc); 331 332 while (counts > 0) { 333 last = sp804_timer_tc_get_timecount(&sc->tc); 334 if (last == first) 335 continue; 336 if (last > first) { 337 counts -= (int32_t)(last - first); 338 } else { 339 counts -= (int32_t)((0xFFFFFFFF - first) + last); 340 } 341 first = last; 342 } 343 } 344