| 384 | #endif |
| 385 | |
| 386 | static int |
| 387 | arm_tmr_attach(device_t dev) |
| 388 | { |
| 389 | struct arm_tmr_softc *sc; |
| 390 | #ifdef FDT |
| 391 | phandle_t node; |
| 392 | pcell_t clock; |
| 393 | #endif |
| 394 | int error; |
| 395 | int i, first_timer, last_timer; |
| 396 | |
| 397 | sc = device_get_softc(dev); |
| 398 | if (arm_tmr_sc) |
| 399 | return (ENXIO); |
| 400 | |
| 401 | sc->get_cntxct = &get_cntxct; |
| 402 | #ifdef FDT |
| 403 | /* Get the base clock frequency */ |
| 404 | node = ofw_bus_get_node(dev); |
| 405 | if (node > 0) { |
| 406 | error = OF_getencprop(node, "clock-frequency", &clock, |
| 407 | sizeof(clock)); |
| 408 | if (error > 0) |
| 409 | sc->clkfreq = clock; |
| 410 | |
| 411 | if (OF_hasprop(node, "allwinner,sun50i-a64-unstable-timer")) { |
| 412 | sc->get_cntxct = &get_cntxct_a64_unstable; |
| 413 | if (bootverbose) |
| 414 | device_printf(dev, |
| 415 | "Enabling allwinner unstable timer workaround\n"); |
| 416 | } |
| 417 | } |
| 418 | #endif |
| 419 | |
| 420 | if (sc->clkfreq == 0) { |
| 421 | /* Try to get clock frequency from timer */ |
| 422 | sc->clkfreq = get_freq(); |
| 423 | } |
| 424 | |
| 425 | if (sc->clkfreq == 0) { |
| 426 | device_printf(dev, "No clock frequency specified\n"); |
| 427 | return (ENXIO); |
| 428 | } |
| 429 | |
| 430 | if (bus_alloc_resources(dev, timer_spec, sc->res)) { |
| 431 | device_printf(dev, "could not allocate resources\n"); |
| 432 | return (ENXIO); |
| 433 | } |
| 434 | |
| 435 | #ifdef __aarch64__ |
| 436 | /* Use the virtual timer if we have one. */ |
| 437 | if (sc->res[2] != NULL) { |
| 438 | sc->physical = false; |
| 439 | first_timer = 2; |
| 440 | last_timer = 2; |
| 441 | } else |
| 442 | #endif |
| 443 | /* Otherwise set up the secure and non-secure physical timers. */ |
nothing calls this directly
no test coverage detected