xref: /netbsd-src/sys/arch/arm/ti/ti_omaptimer.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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