Deleted Added
full compact
generic_timer.c (269605) generic_timer.c (271189)
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
4 * All rights reserved.
5 *
6 * Based on mpcore_timer.c developed by Ben Gray <ben.r.gray@gmail.com>
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 21 unchanged lines hidden (view full) ---

30 * SUCH DAMAGE.
31 */
32
33/**
34 * Cortex-A15 (and probably A7) Generic Timer
35 */
36
37#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2011 The FreeBSD Foundation
3 * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
4 * All rights reserved.
5 *
6 * Based on mpcore_timer.c developed by Ben Gray <ben.r.gray@gmail.com>
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 21 unchanged lines hidden (view full) ---

30 * SUCH DAMAGE.
31 */
32
33/**
34 * Cortex-A15 (and probably A7) Generic Timer
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/arm/arm/generic_timer.c 269605 2014-08-05 18:51:51Z ian $");
38__FBSDID("$FreeBSD: head/sys/arm/arm/generic_timer.c 271189 2014-09-06 13:21:07Z andrew $");
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/bus.h>
43#include <sys/kernel.h>
44#include <sys/module.h>
45#include <sys/malloc.h>
46#include <sys/rman.h>

--- 15 unchanged lines hidden (view full) ---

62#define GT_CTRL_ENABLE (1 << 0)
63#define GT_CTRL_INT_MASK (1 << 1)
64#define GT_CTRL_INT_STAT (1 << 2)
65#define GT_REG_CTRL 0
66#define GT_REG_TVAL 1
67
68#define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */
69#define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/bus.h>
43#include <sys/kernel.h>
44#include <sys/module.h>
45#include <sys/malloc.h>
46#include <sys/rman.h>

--- 15 unchanged lines hidden (view full) ---

62#define GT_CTRL_ENABLE (1 << 0)
63#define GT_CTRL_INT_MASK (1 << 1)
64#define GT_CTRL_INT_STAT (1 << 2)
65#define GT_REG_CTRL 0
66#define GT_REG_TVAL 1
67
68#define GT_CNTKCTL_PL0PTEN (1 << 9) /* PL0 Physical timer reg access */
69#define GT_CNTKCTL_PL0VTEN (1 << 8) /* PL0 Virtual timer reg access */
70#define GT_CNTKCTL_EVNTI (1 << 4) /* Virtual counter event bits */
70#define GT_CNTKCTL_EVNTI (0xf << 4) /* Virtual counter event bits */
71#define GT_CNTKCTL_EVNTDIR (1 << 3) /* Virtual counter event transition */
72#define GT_CNTKCTL_EVNTEN (1 << 2) /* Enables virtual counter events */
73#define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */
74#define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */
75
76struct arm_tmr_softc {
77 struct resource *res[4];
78 void *ihl[4];
79 uint32_t clkfreq;
80 struct eventtimer et;
71#define GT_CNTKCTL_EVNTDIR (1 << 3) /* Virtual counter event transition */
72#define GT_CNTKCTL_EVNTEN (1 << 2) /* Enables virtual counter events */
73#define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */
74#define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */
75
76struct arm_tmr_softc {
77 struct resource *res[4];
78 void *ihl[4];
79 uint32_t clkfreq;
80 struct eventtimer et;
81 bool physical;
81};
82
83static struct arm_tmr_softc *arm_tmr_sc = NULL;
84
85static struct resource_spec timer_spec[] = {
86 { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Secure */
87 { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Non-secure */
88 { SYS_RES_IRQ, 2, RF_ACTIVE }, /* Virt */

--- 7 unchanged lines hidden (view full) ---

96 .tc_name = "ARM MPCore Timecounter",
97 .tc_get_timecount = arm_tmr_get_timecount,
98 .tc_poll_pps = NULL,
99 .tc_counter_mask = ~0u,
100 .tc_frequency = 0,
101 .tc_quality = 1000,
102};
103
82};
83
84static struct arm_tmr_softc *arm_tmr_sc = NULL;
85
86static struct resource_spec timer_spec[] = {
87 { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Secure */
88 { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Non-secure */
89 { SYS_RES_IRQ, 2, RF_ACTIVE }, /* Virt */

--- 7 unchanged lines hidden (view full) ---

97 .tc_name = "ARM MPCore Timecounter",
98 .tc_get_timecount = arm_tmr_get_timecount,
99 .tc_poll_pps = NULL,
100 .tc_counter_mask = ~0u,
101 .tc_frequency = 0,
102 .tc_quality = 1000,
103};
104
104static inline int
105static int
105get_freq(void)
106{
107 uint32_t val;
108
106get_freq(void)
107{
108 uint32_t val;
109
110 /* cntfrq */
109 __asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
110
111 return (val);
112}
113
111 __asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
112
113 return (val);
114}
115
114static inline int
115set_freq(uint32_t val)
116static long
117get_cntxct(bool physical)
116{
118{
119 uint64_t val;
117
120
118 __asm volatile("mcr p15, 0, %[val], c14, c0, 0" : :
119 [val] "r" (val));
120 isb();
121 isb();
122 if (physical)
123 /* cntpct */
124 __asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val));
125 else
126 /* cntvct */
127 __asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (val));
121
122 return (val);
123}
124
128
129 return (val);
130}
131
125
126static inline long
127get_cntpct(void)
132static int
133set_ctrl(uint32_t val, bool physical)
128{
134{
129 uint64_t val;
130
135
131 __asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val));
132
133 return (val);
134}
135
136static inline int
137set_ctrl(uint32_t val)
138{
139
140 __asm volatile("mcr p15, 0, %[val], c14, c2, 1" : :
141 [val] "r" (val));
136 if (physical)
137 /* cntp_ctl */
138 __asm volatile("mcr p15, 0, %[val], c14, c2, 1" : :
139 [val] "r" (val));
140 else
141 /* cntv_ctl */
142 __asm volatile("mcr p15, 0, %[val], c14, c3, 1" : :
143 [val] "r" (val));
142 isb();
143
144 return (0);
145}
146
144 isb();
145
146 return (0);
147}
148
147static inline int
148set_tval(uint32_t val)
149static int
150set_tval(uint32_t val, bool physical)
149{
150
151{
152
151 __asm volatile("mcr p15, 0, %[val], c14, c2, 0" : :
152 [val] "r" (val));
153 if (physical)
154 /* cntp_tval */
155 __asm volatile("mcr p15, 0, %[val], c14, c2, 0" : :
156 [val] "r" (val));
157 else
158 /* cntv_tval */
159 __asm volatile("mcr p15, 0, %[val], c14, c3, 0" : :
160 [val] "r" (val));
153 isb();
154
155 return (0);
156}
157
161 isb();
162
163 return (0);
164}
165
158static inline int
159get_ctrl(void)
166static int
167get_ctrl(bool physical)
160{
161 uint32_t val;
162
168{
169 uint32_t val;
170
163 __asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
171 if (physical)
172 /* cntp_ctl */
173 __asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
174 else
175 /* cntv_ctl */
176 __asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
164
165 return (val);
166}
167
177
178 return (val);
179}
180
168static inline int
169get_tval(void)
170{
171 uint32_t val;
172
173 __asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
174
175 return (val);
176}
177
178static inline void
181static void
179disable_user_access(void)
180{
181 uint32_t cntkctl;
182
183 __asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
184 cntkctl &= ~(GT_CNTKCTL_PL0PTEN | GT_CNTKCTL_PL0VTEN |
185 GT_CNTKCTL_EVNTEN | GT_CNTKCTL_PL0VCTEN | GT_CNTKCTL_PL0PCTEN);
186 __asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
187 isb();
188}
189
190static unsigned
191arm_tmr_get_timecount(struct timecounter *tc)
192{
193
182disable_user_access(void)
183{
184 uint32_t cntkctl;
185
186 __asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
187 cntkctl &= ~(GT_CNTKCTL_PL0PTEN | GT_CNTKCTL_PL0VTEN |
188 GT_CNTKCTL_EVNTEN | GT_CNTKCTL_PL0VCTEN | GT_CNTKCTL_PL0PCTEN);
189 __asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
190 isb();
191}
192
193static unsigned
194arm_tmr_get_timecount(struct timecounter *tc)
195{
196
194 return (get_cntpct());
197 return (get_cntxct(arm_tmr_sc->physical));
195}
196
197static int
198arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
199{
200 struct arm_tmr_softc *sc;
201 int counts, ctrl;
202
203 sc = (struct arm_tmr_softc *)et->et_priv;
204
205 if (first != 0) {
206 counts = ((uint32_t)et->et_frequency * first) >> 32;
198}
199
200static int
201arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
202{
203 struct arm_tmr_softc *sc;
204 int counts, ctrl;
205
206 sc = (struct arm_tmr_softc *)et->et_priv;
207
208 if (first != 0) {
209 counts = ((uint32_t)et->et_frequency * first) >> 32;
207 ctrl = get_ctrl();
210 ctrl = get_ctrl(sc->physical);
208 ctrl &= ~GT_CTRL_INT_MASK;
209 ctrl |= GT_CTRL_ENABLE;
211 ctrl &= ~GT_CTRL_INT_MASK;
212 ctrl |= GT_CTRL_ENABLE;
210 set_tval(counts);
211 set_ctrl(ctrl);
213 set_tval(counts, sc->physical);
214 set_ctrl(ctrl, sc->physical);
212 return (0);
213 }
214
215 return (EINVAL);
216
217}
218
219static int
220arm_tmr_stop(struct eventtimer *et)
221{
215 return (0);
216 }
217
218 return (EINVAL);
219
220}
221
222static int
223arm_tmr_stop(struct eventtimer *et)
224{
225 struct arm_tmr_softc *sc;
222 int ctrl;
223
226 int ctrl;
227
224 ctrl = get_ctrl();
228 sc = (struct arm_tmr_softc *)et->et_priv;
229
230 ctrl = get_ctrl(sc->physical);
225 ctrl &= GT_CTRL_ENABLE;
231 ctrl &= GT_CTRL_ENABLE;
226 set_ctrl(ctrl);
232 set_ctrl(ctrl, sc->physical);
227
228 return (0);
229}
230
231static int
232arm_tmr_intr(void *arg)
233{
234 struct arm_tmr_softc *sc;
235 int ctrl;
236
237 sc = (struct arm_tmr_softc *)arg;
233
234 return (0);
235}
236
237static int
238arm_tmr_intr(void *arg)
239{
240 struct arm_tmr_softc *sc;
241 int ctrl;
242
243 sc = (struct arm_tmr_softc *)arg;
238 ctrl = get_ctrl();
244 ctrl = get_ctrl(sc->physical);
239 if (ctrl & GT_CTRL_INT_STAT) {
240 ctrl |= GT_CTRL_INT_MASK;
245 if (ctrl & GT_CTRL_INT_STAT) {
246 ctrl |= GT_CTRL_INT_MASK;
241 set_ctrl(ctrl);
247 set_ctrl(ctrl, sc->physical);
242 }
243
244 if (sc->et.et_active)
245 sc->et.et_event_cb(&sc->et, sc->et.et_arg);
246
247 return (FILTER_HANDLED);
248}
249

--- 40 unchanged lines hidden (view full) ---

290 if (sc->clkfreq == 0) {
291 device_printf(dev, "No clock frequency specified\n");
292 return (ENXIO);
293 }
294
295 if (bus_alloc_resources(dev, timer_spec, sc->res)) {
296 device_printf(dev, "could not allocate resources\n");
297 return (ENXIO);
248 }
249
250 if (sc->et.et_active)
251 sc->et.et_event_cb(&sc->et, sc->et.et_arg);
252
253 return (FILTER_HANDLED);
254}
255

--- 40 unchanged lines hidden (view full) ---

296 if (sc->clkfreq == 0) {
297 device_printf(dev, "No clock frequency specified\n");
298 return (ENXIO);
299 }
300
301 if (bus_alloc_resources(dev, timer_spec, sc->res)) {
302 device_printf(dev, "could not allocate resources\n");
303 return (ENXIO);
298 };
304 }
299
305
306 sc->physical = true;
307
300 arm_tmr_sc = sc;
301
308 arm_tmr_sc = sc;
309
302 /* Setup secure and non-secure IRQs handler */
303 for (i = 0; i < 2; i++) {
310 /* Setup secure, non-secure and virtual IRQs handler */
311 for (i = 0; i < 3; i++) {
304 error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK,
305 arm_tmr_intr, NULL, sc, &sc->ihl[i]);
306 if (error) {
307 device_printf(dev, "Unable to alloc int resource.\n");
308 return (ENXIO);
309 }
310 }
311

--- 64 unchanged lines hidden (view full) ---

376 * near that length of time and if they are, they should be hung
377 * out to dry.
378 */
379 if (usec >= (0x80000000U / counts_per_usec))
380 counts = (0x80000000U / counts_per_usec) - 1;
381 else
382 counts = usec * counts_per_usec;
383
312 error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK,
313 arm_tmr_intr, NULL, sc, &sc->ihl[i]);
314 if (error) {
315 device_printf(dev, "Unable to alloc int resource.\n");
316 return (ENXIO);
317 }
318 }
319

--- 64 unchanged lines hidden (view full) ---

384 * near that length of time and if they are, they should be hung
385 * out to dry.
386 */
387 if (usec >= (0x80000000U / counts_per_usec))
388 counts = (0x80000000U / counts_per_usec) - 1;
389 else
390 counts = usec * counts_per_usec;
391
384 first = get_cntpct();
392 first = get_cntxct(arm_tmr_sc->physical);
385
386 while (counts > 0) {
393
394 while (counts > 0) {
387 last = get_cntpct();
395 last = get_cntxct(arm_tmr_sc->physical);
388 counts -= (int32_t)(last - first);
389 first = last;
390 }
391}
396 counts -= (int32_t)(last - first);
397 first = last;
398 }
399}