1/*- 2 * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h>
|
28__FBSDID("$FreeBSD: head/sys/arm/allwinner/timer.c 247463 2013-02-28 13:46:03Z mav $");
| 28__FBSDID("$FreeBSD: head/sys/arm/allwinner/timer.c 254056 2013-08-07 11:07:56Z ganbold $");
|
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#include <sys/rman.h> 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/frame.h> 43#include <machine/intr.h> 44 45#include <dev/fdt/fdt_common.h> 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#include <machine/fdt.h> 52 53#include <sys/kdb.h> 54
| 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#include <sys/rman.h> 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/frame.h> 43#include <machine/intr.h> 44 45#include <dev/fdt/fdt_common.h> 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#include <machine/fdt.h> 52 53#include <sys/kdb.h> 54
|
| 55#include "a20/a20_cpu_cfg.h" 56
|
55/** 56 * Timer registers addr 57 * 58 */ 59#define SW_TIMER_IRQ_EN_REG 0x00 60#define SW_TIMER_IRQ_STA_REG 0x04 61#define SW_TIMER0_CTRL_REG 0x10 62#define SW_TIMER0_INT_VALUE_REG 0x14 63#define SW_TIMER0_CUR_VALUE_REG 0x18 64 65#define SW_COUNTER64LO_REG 0xa4 66#define SW_COUNTER64HI_REG 0xa8 67#define CNT64_CTRL_REG 0xa0 68 69#define CNT64_RL_EN 0x02 /* read latch enable */ 70 71#define TIMER_ENABLE (1<<0) 72#define TIMER_AUTORELOAD (1<<1) 73#define TIMER_OSC24M (1<<2) /* oscillator = 24mhz */ 74#define TIMER_PRESCALAR (4<<4) /* prescalar = 16 */ 75 76#define SYS_TIMER_CLKSRC 24000000 /* clock source */ 77 78struct a10_timer_softc { 79 device_t sc_dev; 80 struct resource *res[2]; 81 bus_space_tag_t sc_bst; 82 bus_space_handle_t sc_bsh; 83 void *sc_ih; /* interrupt handler */ 84 uint32_t sc_period; 85 uint32_t timer0_freq; 86 struct eventtimer et;
| 57/** 58 * Timer registers addr 59 * 60 */ 61#define SW_TIMER_IRQ_EN_REG 0x00 62#define SW_TIMER_IRQ_STA_REG 0x04 63#define SW_TIMER0_CTRL_REG 0x10 64#define SW_TIMER0_INT_VALUE_REG 0x14 65#define SW_TIMER0_CUR_VALUE_REG 0x18 66 67#define SW_COUNTER64LO_REG 0xa4 68#define SW_COUNTER64HI_REG 0xa8 69#define CNT64_CTRL_REG 0xa0 70 71#define CNT64_RL_EN 0x02 /* read latch enable */ 72 73#define TIMER_ENABLE (1<<0) 74#define TIMER_AUTORELOAD (1<<1) 75#define TIMER_OSC24M (1<<2) /* oscillator = 24mhz */ 76#define TIMER_PRESCALAR (4<<4) /* prescalar = 16 */ 77 78#define SYS_TIMER_CLKSRC 24000000 /* clock source */ 79 80struct a10_timer_softc { 81 device_t sc_dev; 82 struct resource *res[2]; 83 bus_space_tag_t sc_bst; 84 bus_space_handle_t sc_bsh; 85 void *sc_ih; /* interrupt handler */ 86 uint32_t sc_period; 87 uint32_t timer0_freq; 88 struct eventtimer et;
|
| 89 uint8_t sc_timer_type; /* 0 for A10, 1 for A20 */
|
87}; 88 89int a10_timer_get_timerfreq(struct a10_timer_softc *); 90 91#define timer_read_4(sc, reg) \ 92 bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg) 93#define timer_write_4(sc, reg, val) \ 94 bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val) 95 96static u_int a10_timer_get_timecount(struct timecounter *); 97static int a10_timer_timer_start(struct eventtimer *, 98 sbintime_t first, sbintime_t period); 99static int a10_timer_timer_stop(struct eventtimer *); 100 101static uint64_t timer_read_counter64(void); 102 103static int a10_timer_initialized = 0; 104static int a10_timer_hardclock(void *); 105static int a10_timer_probe(device_t); 106static int a10_timer_attach(device_t); 107 108static struct timecounter a10_timer_timecounter = { 109 .tc_name = "a10_timer timer0", 110 .tc_get_timecount = a10_timer_get_timecount, 111 .tc_counter_mask = ~0u, 112 .tc_frequency = 0, 113 .tc_quality = 1000, 114}; 115 116struct a10_timer_softc *a10_timer_sc = NULL; 117 118static struct resource_spec a10_timer_spec[] = { 119 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 120 { SYS_RES_IRQ, 0, RF_ACTIVE }, 121 { -1, 0 } 122}; 123 124static uint64_t 125timer_read_counter64(void) 126{ 127 uint32_t lo, hi; 128
| 90}; 91 92int a10_timer_get_timerfreq(struct a10_timer_softc *); 93 94#define timer_read_4(sc, reg) \ 95 bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg) 96#define timer_write_4(sc, reg, val) \ 97 bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val) 98 99static u_int a10_timer_get_timecount(struct timecounter *); 100static int a10_timer_timer_start(struct eventtimer *, 101 sbintime_t first, sbintime_t period); 102static int a10_timer_timer_stop(struct eventtimer *); 103 104static uint64_t timer_read_counter64(void); 105 106static int a10_timer_initialized = 0; 107static int a10_timer_hardclock(void *); 108static int a10_timer_probe(device_t); 109static int a10_timer_attach(device_t); 110 111static struct timecounter a10_timer_timecounter = { 112 .tc_name = "a10_timer timer0", 113 .tc_get_timecount = a10_timer_get_timecount, 114 .tc_counter_mask = ~0u, 115 .tc_frequency = 0, 116 .tc_quality = 1000, 117}; 118 119struct a10_timer_softc *a10_timer_sc = NULL; 120 121static struct resource_spec a10_timer_spec[] = { 122 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 123 { SYS_RES_IRQ, 0, RF_ACTIVE }, 124 { -1, 0 } 125}; 126 127static uint64_t 128timer_read_counter64(void) 129{ 130 uint32_t lo, hi; 131
|
| 132 /* In case of A20 get appropriate counter info */ 133 if (a10_timer_sc->sc_timer_type) 134 return (a20_read_counter64()); 135
|
129 /* Latch counter, wait for it to be ready to read. */ 130 timer_write_4(a10_timer_sc, CNT64_CTRL_REG, CNT64_RL_EN); 131 while (timer_read_4(a10_timer_sc, CNT64_CTRL_REG) & CNT64_RL_EN) 132 continue; 133 134 hi = timer_read_4(a10_timer_sc, SW_COUNTER64HI_REG); 135 lo = timer_read_4(a10_timer_sc, SW_COUNTER64LO_REG); 136 137 return (((uint64_t)hi << 32) | lo); 138} 139 140static int 141a10_timer_probe(device_t dev) 142{
| 136 /* Latch counter, wait for it to be ready to read. */ 137 timer_write_4(a10_timer_sc, CNT64_CTRL_REG, CNT64_RL_EN); 138 while (timer_read_4(a10_timer_sc, CNT64_CTRL_REG) & CNT64_RL_EN) 139 continue; 140 141 hi = timer_read_4(a10_timer_sc, SW_COUNTER64HI_REG); 142 lo = timer_read_4(a10_timer_sc, SW_COUNTER64LO_REG); 143 144 return (((uint64_t)hi << 32) | lo); 145} 146 147static int 148a10_timer_probe(device_t dev) 149{
|
| 150 struct a10_timer_softc *sc;
|
143
| 151
|
144 if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-timer"))
| 152 sc = device_get_softc(dev); 153 154 if (ofw_bus_is_compatible(dev, "allwinner,sun4i-timer")) 155 sc->sc_timer_type = 0; 156 else if (ofw_bus_is_compatible(dev, "allwinner,sun7i-timer")) 157 sc->sc_timer_type = 1; 158 else
|
145 return (ENXIO); 146
| 159 return (ENXIO); 160
|
147 device_set_desc(dev, "Allwinner A10 timer");
| 161 device_set_desc(dev, "Allwinner A10/A20 timer");
|
148 return (BUS_PROBE_DEFAULT); 149} 150 151static int 152a10_timer_attach(device_t dev) 153{ 154 struct a10_timer_softc *sc; 155 int err; 156 uint32_t val; 157 158 sc = device_get_softc(dev); 159 160 if (bus_alloc_resources(dev, a10_timer_spec, sc->res)) { 161 device_printf(dev, "could not allocate resources\n"); 162 return (ENXIO); 163 } 164 165 sc->sc_dev = dev; 166 sc->sc_bst = rman_get_bustag(sc->res[0]); 167 sc->sc_bsh = rman_get_bushandle(sc->res[0]); 168 169 /* Setup and enable the timer interrupt */ 170 err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, a10_timer_hardclock, 171 NULL, sc, &sc->sc_ih); 172 if (err != 0) { 173 bus_release_resources(dev, a10_timer_spec, sc->res); 174 device_printf(dev, "Unable to setup the clock irq handler, " 175 "err = %d\n", err); 176 return (ENXIO); 177 } 178 179 /* Set clock source to OSC24M, 16 pre-division */ 180 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 181 val |= TIMER_PRESCALAR | TIMER_OSC24M; 182 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 183 184 /* Enable timer0 */ 185 val = timer_read_4(sc, SW_TIMER_IRQ_EN_REG); 186 val |= TIMER_ENABLE; 187 timer_write_4(sc, SW_TIMER_IRQ_EN_REG, val); 188 189 sc->timer0_freq = SYS_TIMER_CLKSRC; 190 191 /* Set desired frequency in event timer and timecounter */ 192 sc->et.et_frequency = sc->timer0_freq; 193 sc->et.et_name = "a10_timer Eventtimer"; 194 sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC; 195 sc->et.et_quality = 1000; 196 sc->et.et_min_period = (0x00000005LLU << 32) / sc->et.et_frequency; 197 sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; 198 sc->et.et_start = a10_timer_timer_start; 199 sc->et.et_stop = a10_timer_timer_stop; 200 sc->et.et_priv = sc; 201 et_register(&sc->et); 202 203 if (device_get_unit(dev) == 0) 204 a10_timer_sc = sc; 205 206 a10_timer_timecounter.tc_frequency = sc->timer0_freq; 207 tc_init(&a10_timer_timecounter); 208 209 if (bootverbose) { 210 device_printf(sc->sc_dev, "clock: hz=%d stathz = %d\n", hz, stathz); 211 212 device_printf(sc->sc_dev, "event timer clock frequency %u\n", 213 sc->timer0_freq); 214 device_printf(sc->sc_dev, "timecounter clock frequency %lld\n", 215 a10_timer_timecounter.tc_frequency); 216 } 217 218 a10_timer_initialized = 1; 219 220 return (0); 221} 222 223static int 224a10_timer_timer_start(struct eventtimer *et, sbintime_t first, 225 sbintime_t period) 226{ 227 struct a10_timer_softc *sc; 228 uint32_t count; 229 uint32_t val; 230 231 sc = (struct a10_timer_softc *)et->et_priv; 232 233 if (period != 0) 234 sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32; 235 else 236 sc->sc_period = 0; 237 if (first != 0) 238 count = ((uint32_t)et->et_frequency * first) >> 32; 239 else 240 count = sc->sc_period; 241 242 /* Update timer values */ 243 timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period); 244 timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count); 245 246 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 247 if (period != 0) { 248 /* periodic */ 249 val |= TIMER_AUTORELOAD; 250 } else { 251 /* oneshot */ 252 val &= ~TIMER_AUTORELOAD; 253 } 254 /* Enable timer0 */ 255 val |= TIMER_ENABLE; 256 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 257 258 return (0); 259} 260 261static int 262a10_timer_timer_stop(struct eventtimer *et) 263{ 264 struct a10_timer_softc *sc; 265 uint32_t val; 266 267 sc = (struct a10_timer_softc *)et->et_priv; 268 269 /* Disable timer0 */ 270 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 271 val &= ~TIMER_ENABLE; 272 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 273 274 sc->sc_period = 0; 275 276 return (0); 277} 278 279int 280a10_timer_get_timerfreq(struct a10_timer_softc *sc) 281{ 282 return (sc->timer0_freq); 283} 284 285void 286cpu_initclocks(void) 287{ 288 cpu_initclocks_bsp(); 289} 290 291static int 292a10_timer_hardclock(void *arg) 293{ 294 struct a10_timer_softc *sc; 295 uint32_t val; 296 297 sc = (struct a10_timer_softc *)arg; 298 299 /* Clear interrupt pending bit. */ 300 timer_write_4(sc, SW_TIMER_IRQ_STA_REG, 0x1); 301 302 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 303 /* 304 * Disabled autoreload and sc_period > 0 means 305 * timer_start was called with non NULL first value. 306 * Now we will set periodic timer with the given period 307 * value. 308 */ 309 if ((val & (1<<1)) == 0 && sc->sc_period > 0) { 310 /* Update timer */ 311 timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, sc->sc_period); 312 313 /* Make periodic and enable */ 314 val |= TIMER_AUTORELOAD | TIMER_ENABLE; 315 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 316 } 317 318 if (sc->et.et_active) 319 sc->et.et_event_cb(&sc->et, sc->et.et_arg); 320 321 return (FILTER_HANDLED); 322} 323 324u_int 325a10_timer_get_timecount(struct timecounter *tc) 326{ 327 328 if (a10_timer_sc == NULL) 329 return (0); 330 331 return ((u_int)timer_read_counter64()); 332} 333 334static device_method_t a10_timer_methods[] = { 335 DEVMETHOD(device_probe, a10_timer_probe), 336 DEVMETHOD(device_attach, a10_timer_attach), 337 338 DEVMETHOD_END 339}; 340 341static driver_t a10_timer_driver = { 342 "a10_timer", 343 a10_timer_methods, 344 sizeof(struct a10_timer_softc), 345}; 346 347static devclass_t a10_timer_devclass; 348 349DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0); 350 351void 352DELAY(int usec) 353{ 354 uint32_t counter; 355 uint64_t end, now; 356 357 if (!a10_timer_initialized) { 358 for (; usec > 0; usec--) 359 for (counter = 50; counter > 0; counter--) 360 cpufunc_nullop(); 361 return; 362 } 363 364 now = timer_read_counter64(); 365 end = now + (a10_timer_sc->timer0_freq / 1000000) * (usec + 1); 366 367 while (now < end) 368 now = timer_read_counter64(); 369} 370
| 162 return (BUS_PROBE_DEFAULT); 163} 164 165static int 166a10_timer_attach(device_t dev) 167{ 168 struct a10_timer_softc *sc; 169 int err; 170 uint32_t val; 171 172 sc = device_get_softc(dev); 173 174 if (bus_alloc_resources(dev, a10_timer_spec, sc->res)) { 175 device_printf(dev, "could not allocate resources\n"); 176 return (ENXIO); 177 } 178 179 sc->sc_dev = dev; 180 sc->sc_bst = rman_get_bustag(sc->res[0]); 181 sc->sc_bsh = rman_get_bushandle(sc->res[0]); 182 183 /* Setup and enable the timer interrupt */ 184 err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, a10_timer_hardclock, 185 NULL, sc, &sc->sc_ih); 186 if (err != 0) { 187 bus_release_resources(dev, a10_timer_spec, sc->res); 188 device_printf(dev, "Unable to setup the clock irq handler, " 189 "err = %d\n", err); 190 return (ENXIO); 191 } 192 193 /* Set clock source to OSC24M, 16 pre-division */ 194 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 195 val |= TIMER_PRESCALAR | TIMER_OSC24M; 196 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 197 198 /* Enable timer0 */ 199 val = timer_read_4(sc, SW_TIMER_IRQ_EN_REG); 200 val |= TIMER_ENABLE; 201 timer_write_4(sc, SW_TIMER_IRQ_EN_REG, val); 202 203 sc->timer0_freq = SYS_TIMER_CLKSRC; 204 205 /* Set desired frequency in event timer and timecounter */ 206 sc->et.et_frequency = sc->timer0_freq; 207 sc->et.et_name = "a10_timer Eventtimer"; 208 sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC; 209 sc->et.et_quality = 1000; 210 sc->et.et_min_period = (0x00000005LLU << 32) / sc->et.et_frequency; 211 sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; 212 sc->et.et_start = a10_timer_timer_start; 213 sc->et.et_stop = a10_timer_timer_stop; 214 sc->et.et_priv = sc; 215 et_register(&sc->et); 216 217 if (device_get_unit(dev) == 0) 218 a10_timer_sc = sc; 219 220 a10_timer_timecounter.tc_frequency = sc->timer0_freq; 221 tc_init(&a10_timer_timecounter); 222 223 if (bootverbose) { 224 device_printf(sc->sc_dev, "clock: hz=%d stathz = %d\n", hz, stathz); 225 226 device_printf(sc->sc_dev, "event timer clock frequency %u\n", 227 sc->timer0_freq); 228 device_printf(sc->sc_dev, "timecounter clock frequency %lld\n", 229 a10_timer_timecounter.tc_frequency); 230 } 231 232 a10_timer_initialized = 1; 233 234 return (0); 235} 236 237static int 238a10_timer_timer_start(struct eventtimer *et, sbintime_t first, 239 sbintime_t period) 240{ 241 struct a10_timer_softc *sc; 242 uint32_t count; 243 uint32_t val; 244 245 sc = (struct a10_timer_softc *)et->et_priv; 246 247 if (period != 0) 248 sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32; 249 else 250 sc->sc_period = 0; 251 if (first != 0) 252 count = ((uint32_t)et->et_frequency * first) >> 32; 253 else 254 count = sc->sc_period; 255 256 /* Update timer values */ 257 timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period); 258 timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count); 259 260 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 261 if (period != 0) { 262 /* periodic */ 263 val |= TIMER_AUTORELOAD; 264 } else { 265 /* oneshot */ 266 val &= ~TIMER_AUTORELOAD; 267 } 268 /* Enable timer0 */ 269 val |= TIMER_ENABLE; 270 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 271 272 return (0); 273} 274 275static int 276a10_timer_timer_stop(struct eventtimer *et) 277{ 278 struct a10_timer_softc *sc; 279 uint32_t val; 280 281 sc = (struct a10_timer_softc *)et->et_priv; 282 283 /* Disable timer0 */ 284 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 285 val &= ~TIMER_ENABLE; 286 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 287 288 sc->sc_period = 0; 289 290 return (0); 291} 292 293int 294a10_timer_get_timerfreq(struct a10_timer_softc *sc) 295{ 296 return (sc->timer0_freq); 297} 298 299void 300cpu_initclocks(void) 301{ 302 cpu_initclocks_bsp(); 303} 304 305static int 306a10_timer_hardclock(void *arg) 307{ 308 struct a10_timer_softc *sc; 309 uint32_t val; 310 311 sc = (struct a10_timer_softc *)arg; 312 313 /* Clear interrupt pending bit. */ 314 timer_write_4(sc, SW_TIMER_IRQ_STA_REG, 0x1); 315 316 val = timer_read_4(sc, SW_TIMER0_CTRL_REG); 317 /* 318 * Disabled autoreload and sc_period > 0 means 319 * timer_start was called with non NULL first value. 320 * Now we will set periodic timer with the given period 321 * value. 322 */ 323 if ((val & (1<<1)) == 0 && sc->sc_period > 0) { 324 /* Update timer */ 325 timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, sc->sc_period); 326 327 /* Make periodic and enable */ 328 val |= TIMER_AUTORELOAD | TIMER_ENABLE; 329 timer_write_4(sc, SW_TIMER0_CTRL_REG, val); 330 } 331 332 if (sc->et.et_active) 333 sc->et.et_event_cb(&sc->et, sc->et.et_arg); 334 335 return (FILTER_HANDLED); 336} 337 338u_int 339a10_timer_get_timecount(struct timecounter *tc) 340{ 341 342 if (a10_timer_sc == NULL) 343 return (0); 344 345 return ((u_int)timer_read_counter64()); 346} 347 348static device_method_t a10_timer_methods[] = { 349 DEVMETHOD(device_probe, a10_timer_probe), 350 DEVMETHOD(device_attach, a10_timer_attach), 351 352 DEVMETHOD_END 353}; 354 355static driver_t a10_timer_driver = { 356 "a10_timer", 357 a10_timer_methods, 358 sizeof(struct a10_timer_softc), 359}; 360 361static devclass_t a10_timer_devclass; 362 363DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0); 364 365void 366DELAY(int usec) 367{ 368 uint32_t counter; 369 uint64_t end, now; 370 371 if (!a10_timer_initialized) { 372 for (; usec > 0; usec--) 373 for (counter = 50; counter > 0; counter--) 374 cpufunc_nullop(); 375 return; 376 } 377 378 now = timer_read_counter64(); 379 end = now + (a10_timer_sc->timer0_freq / 1000000) * (usec + 1); 380 381 while (now < end) 382 now = timer_read_counter64(); 383} 384
|