1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 #include <sys/kernel.h> 34 #include <sys/module.h> 35 #include <sys/malloc.h> 36 37 #include <sys/timeet.h> 38 #include <sys/timetc.h> 39 #include <sys/watchdog.h> 40 #include <machine/bus.h> 41 #include <machine/cpu.h> 42 #include <machine/intr.h> 43 44 #include <machine/machdep.h> /* For arm_set_delay */ 45 46 #include <dev/ofw/openfirm.h> 47 #include <dev/ofw/ofw_bus.h> 48 #include <dev/ofw/ofw_bus_subr.h> 49 50 #include <machine/bus.h> 51 52 #define SP804_TIMER1_LOAD 0x00 53 #define SP804_TIMER1_VALUE 0x04 54 #define SP804_TIMER1_CONTROL 0x08 55 #define TIMER_CONTROL_EN (1 << 7) 56 #define TIMER_CONTROL_FREERUN (0 << 6) 57 #define TIMER_CONTROL_PERIODIC (1 << 6) 58 #define TIMER_CONTROL_INTREN (1 << 5) 59 #define TIMER_CONTROL_DIV1 (0 << 2) 60 #define TIMER_CONTROL_DIV16 (1 << 2) 61 #define TIMER_CONTROL_DIV256 (2 << 2) 62 #define TIMER_CONTROL_32BIT (1 << 1) 63 #define TIMER_CONTROL_ONESHOT (1 << 0) 64 #define SP804_TIMER1_INTCLR 0x0C 65 #define SP804_TIMER1_RIS 0x10 66 #define SP804_TIMER1_MIS 0x14 67 #define SP804_TIMER1_BGLOAD 0x18 68 #define SP804_TIMER2_LOAD 0x20 69 #define SP804_TIMER2_VALUE 0x24 70 #define SP804_TIMER2_CONTROL 0x28 71 #define SP804_TIMER2_INTCLR 0x2C 72 #define SP804_TIMER2_RIS 0x30 73 #define SP804_TIMER2_MIS 0x34 74 #define SP804_TIMER2_BGLOAD 0x38 75 76 #define SP804_PERIPH_ID0 0xFE0 77 #define SP804_PERIPH_ID1 0xFE4 78 #define SP804_PERIPH_ID2 0xFE8 79 #define SP804_PERIPH_ID3 0xFEC 80 #define SP804_PRIMECELL_ID0 0xFF0 81 #define SP804_PRIMECELL_ID1 0xFF4 82 #define SP804_PRIMECELL_ID2 0xFF8 83 #define SP804_PRIMECELL_ID3 0xFFC 84 85 #define DEFAULT_FREQUENCY 1000000 86 /* 87 * QEMU seems to have problem with full frequency 88 */ 89 #define DEFAULT_DIVISOR 16 90 #define DEFAULT_CONTROL_DIV TIMER_CONTROL_DIV16 91 92 struct sp804_timer_softc { 93 struct resource* mem_res; 94 struct resource* irq_res; 95 void* intr_hl; 96 uint32_t sysclk_freq; 97 bus_space_tag_t bst; 98 bus_space_handle_t bsh; 99 struct timecounter tc; 100 bool et_enabled; 101 struct eventtimer et; 102 int timer_initialized; 103 }; 104 105 /* Read/Write macros for Timer used as timecounter */ 106 #define sp804_timer_tc_read_4(reg) \ 107 bus_space_read_4(sc->bst, sc->bsh, reg) 108 109 #define sp804_timer_tc_write_4(reg, val) \ 110 bus_space_write_4(sc->bst, sc->bsh, reg, val) 111 112 static unsigned sp804_timer_tc_get_timecount(struct timecounter *); 113 static void sp804_timer_delay(int, void *); 114 115 static unsigned 116 sp804_timer_tc_get_timecount(struct timecounter *tc) 117 { 118 struct sp804_timer_softc *sc = tc->tc_priv; 119 return 0xffffffff - sp804_timer_tc_read_4(SP804_TIMER1_VALUE); 120 } 121 122 static int 123 sp804_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) 124 { 125 struct sp804_timer_softc *sc = et->et_priv; 126 uint32_t count, reg; 127 128 if (first != 0) { 129 sc->et_enabled = 1; 130 131 count = ((uint32_t)et->et_frequency * first) >> 32; 132 133 sp804_timer_tc_write_4(SP804_TIMER2_LOAD, count); 134 reg = TIMER_CONTROL_32BIT | TIMER_CONTROL_INTREN | 135 TIMER_CONTROL_PERIODIC | DEFAULT_CONTROL_DIV | 136 TIMER_CONTROL_EN; 137 sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, reg); 138 139 return (0); 140 } 141 142 if (period != 0) { 143 panic("period"); 144 } 145 146 return (EINVAL); 147 } 148 149 static int 150 sp804_timer_stop(struct eventtimer *et) 151 { 152 struct sp804_timer_softc *sc = et->et_priv; 153 uint32_t reg; 154 155 sc->et_enabled = 0; 156 reg = sp804_timer_tc_read_4(SP804_TIMER2_CONTROL); 157 reg &= ~(TIMER_CONTROL_EN); 158 sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, reg); 159 160 return (0); 161 } 162 163 static int 164 sp804_timer_intr(void *arg) 165 { 166 struct sp804_timer_softc *sc = arg; 167 168 (void)sp804_timer_tc_read_4(SP804_TIMER1_VALUE); 169 170 sp804_timer_tc_write_4(SP804_TIMER2_INTCLR, 1); 171 if (sc->et_enabled) { 172 if (sc->et.et_active) { 173 sc->et.et_event_cb(&sc->et, sc->et.et_arg); 174 } 175 } 176 177 return (FILTER_HANDLED); 178 } 179 180 static int 181 sp804_timer_probe(device_t dev) 182 { 183 184 if (!ofw_bus_status_okay(dev)) 185 return (ENXIO); 186 187 if (ofw_bus_is_compatible(dev, "arm,sp804")) { 188 device_set_desc(dev, "SP804 System Timer"); 189 return (BUS_PROBE_DEFAULT); 190 } 191 192 return (ENXIO); 193 } 194 195 static int 196 sp804_timer_attach(device_t dev) 197 { 198 struct sp804_timer_softc *sc = device_get_softc(dev); 199 int rid = 0; 200 int i; 201 uint32_t id, reg; 202 phandle_t node; 203 pcell_t clock; 204 205 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 206 if (sc->mem_res == NULL) { 207 device_printf(dev, "could not allocate memory resource\n"); 208 return (ENXIO); 209 } 210 211 sc->bst = rman_get_bustag(sc->mem_res); 212 sc->bsh = rman_get_bushandle(sc->mem_res); 213 214 /* Request the IRQ resources */ 215 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 216 if (sc->irq_res == NULL) { 217 device_printf(dev, "Error: could not allocate irq resources\n"); 218 return (ENXIO); 219 } 220 221 sc->sysclk_freq = DEFAULT_FREQUENCY; 222 /* Get the base clock frequency */ 223 node = ofw_bus_get_node(dev); 224 if ((OF_getencprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) { 225 sc->sysclk_freq = clock; 226 } 227 228 /* Setup and enable the timer */ 229 if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK, 230 sp804_timer_intr, NULL, sc, 231 &sc->intr_hl) != 0) { 232 bus_release_resource(dev, SYS_RES_IRQ, rid, 233 sc->irq_res); 234 device_printf(dev, "Unable to setup the clock irq handler.\n"); 235 return (ENXIO); 236 } 237 238 sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, 0); 239 sp804_timer_tc_write_4(SP804_TIMER2_CONTROL, 0); 240 241 /* 242 * Timer 1, timecounter 243 */ 244 sc->tc.tc_frequency = sc->sysclk_freq; 245 sc->tc.tc_name = "SP804-1"; 246 sc->tc.tc_get_timecount = sp804_timer_tc_get_timecount; 247 sc->tc.tc_poll_pps = NULL; 248 sc->tc.tc_counter_mask = ~0u; 249 sc->tc.tc_quality = 1000; 250 sc->tc.tc_priv = sc; 251 252 sp804_timer_tc_write_4(SP804_TIMER1_VALUE, 0xffffffff); 253 sp804_timer_tc_write_4(SP804_TIMER1_LOAD, 0xffffffff); 254 reg = TIMER_CONTROL_PERIODIC | TIMER_CONTROL_32BIT; 255 sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, reg); 256 reg |= TIMER_CONTROL_EN; 257 sp804_timer_tc_write_4(SP804_TIMER1_CONTROL, reg); 258 tc_init(&sc->tc); 259 260 /* 261 * Timer 2, event timer 262 */ 263 sc->et_enabled = 0; 264 sc->et.et_name = "SP804-2"; 265 sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT; 266 sc->et.et_quality = 1000; 267 sc->et.et_frequency = sc->sysclk_freq / DEFAULT_DIVISOR; 268 sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency; 269 sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; 270 sc->et.et_start = sp804_timer_start; 271 sc->et.et_stop = sp804_timer_stop; 272 sc->et.et_priv = sc; 273 et_register(&sc->et); 274 275 id = 0; 276 for (i = 3; i >= 0; i--) { 277 id = (id << 8) | 278 (sp804_timer_tc_read_4(SP804_PERIPH_ID0 + i*4) & 0xff); 279 } 280 281 device_printf(dev, "peripheral ID: %08x\n", id); 282 283 id = 0; 284 for (i = 3; i >= 0; i--) { 285 id = (id << 8) | 286 (sp804_timer_tc_read_4(SP804_PRIMECELL_ID0 + i*4) & 0xff); 287 } 288 289 arm_set_delay(sp804_timer_delay, sc); 290 291 device_printf(dev, "PrimeCell ID: %08x\n", id); 292 293 sc->timer_initialized = 1; 294 295 return (0); 296 } 297 298 static device_method_t sp804_timer_methods[] = { 299 DEVMETHOD(device_probe, sp804_timer_probe), 300 DEVMETHOD(device_attach, sp804_timer_attach), 301 { 0, 0 } 302 }; 303 304 static driver_t sp804_timer_driver = { 305 "timer", 306 sp804_timer_methods, 307 sizeof(struct sp804_timer_softc), 308 }; 309 310 DRIVER_MODULE(sp804_timer, simplebus, sp804_timer_driver, 0, 0); 311 312 static void 313 sp804_timer_delay(int usec, void *arg) 314 { 315 struct sp804_timer_softc *sc = arg; 316 int32_t counts; 317 uint32_t first, last; 318 319 /* Get the number of times to count */ 320 counts = usec * ((sc->tc.tc_frequency / 1000000) + 1); 321 322 first = sp804_timer_tc_get_timecount(&sc->tc); 323 324 while (counts > 0) { 325 last = sp804_timer_tc_get_timecount(&sc->tc); 326 if (last == first) 327 continue; 328 if (last > first) { 329 counts -= (int32_t)(last - first); 330 } else { 331 counts -= (int32_t)((0xFFFFFFFF - first) + last); 332 } 333 first = last; 334 } 335 } 336