1 /* $NetBSD: ti_omaptimer.c,v 1.1 2017/10/26 01:16:32 jakllsch Exp $ */ 2 3 #include <sys/cdefs.h> 4 __KERNEL_RCSID(0, "$NetBSD: ti_omaptimer.c,v 1.1 2017/10/26 01:16:32 jakllsch Exp $"); 5 6 #include <sys/types.h> 7 #include <sys/param.h> 8 #include <sys/bus.h> 9 #include <sys/device.h> 10 #include <sys/timetc.h> 11 #include <sys/kernel.h> 12 13 #include <arm/locore.h> 14 #include <arm/fdt/arm_fdtvar.h> 15 16 #include <dev/fdt/fdtvar.h> 17 18 static const char * const compatible[] = { 19 "ti,am335x-timer-1ms", 20 "ti,am335x-timer", 21 NULL 22 }; 23 24 struct omaptimer_softc { 25 device_t sc_dev; 26 bus_space_tag_t sc_bst; 27 bus_space_handle_t sc_bsh; 28 int sc_phandle; 29 struct clk *sc_clk; 30 struct timecounter sc_tc; 31 }; 32 33 static struct omaptimer_softc *timer_softc; 34 35 static int 36 omaptimer_intr(void *arg) 37 { 38 struct omaptimer_softc * const sc = timer_softc; 39 struct clockframe * const frame = arg; 40 41 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 0x28, 2); 42 hardclock(frame); 43 44 return 1; 45 } 46 47 static void 48 omaptimer_cpu_initclocks(void) 49 { 50 struct omaptimer_softc * const sc = timer_softc; 51 char intrstr[128]; 52 void *ih; 53 54 KASSERT(sc != NULL); 55 if (!fdtbus_intr_str(sc->sc_phandle, 0, intrstr, sizeof(intrstr))) 56 panic("%s: failed to decode interrupt", __func__); 57 ih = fdtbus_intr_establish(sc->sc_phandle, 0, IPL_CLOCK, 58 FDT_INTR_MPSAFE, omaptimer_intr, NULL); 59 if (ih == NULL) 60 panic("%s: failed to establish timer interrupt", __func__); 61 62 aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr); 63 64 uint32_t value; 65 value = (0xffffffff - ((24000000UL / hz) - 1)); 66 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 0x40, value); 67 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 0x3c, value); 68 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 0x2c, 2); 69 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 0x38, 3); 70 } 71 72 static int 73 omaptimer_match(device_t parent, cfdata_t match, void *aux) 74 { 75 struct fdt_attach_args * const faa = aux; 76 77 return of_match_compatible(faa->faa_phandle, compatible); 78 } 79 80 static void 81 omaptimer_attach(device_t parent, device_t self, void *aux) 82 { 83 struct omaptimer_softc * const sc = device_private(self); 84 struct fdt_attach_args * const faa = aux; 85 const int phandle = faa->faa_phandle; 86 bus_addr_t addr; 87 bus_size_t size; 88 89 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 90 aprint_error(": couldn't get registers\n"); 91 return; 92 } 93 94 #if 0 95 if ((sc->sc_clk = fdtbus_clock_get_index(phandle, 0)) == NULL) { 96 aprint_error(": couldn't get clock\n"); 97 return; 98 } 99 #endif 100 101 sc->sc_dev = self; 102 sc->sc_phandle = phandle; 103 sc->sc_bst = faa->faa_bst; 104 105 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 106 device_printf(self, "unable to map bus space"); 107 return; 108 } 109 110 aprint_naive("\n"); 111 aprint_normal(": Timer\n"); 112 113 /* Use this as the OS timer in UP configurations */ 114 if (!arm_has_mpext_p && addr == 0x48042000) { /* TIMER3 */ 115 timer_softc = sc; 116 arm_fdt_timer_register(omaptimer_cpu_initclocks); 117 } 118 } 119 120 CFATTACH_DECL_NEW(omaptimer, sizeof(struct omaptimer_softc), 121 omaptimer_match, omaptimer_attach, NULL, NULL); 122 123