timer.c (9b4fcf851a73554063d4a2de9a4f10cd23a0a4f6) timer.c (16694521fe80f54bf8f37334fe9a54bc5c953a6a)
1/*-
2 * Copyright (c) 2006 Benno Rice.
3 * Copyright (C) 2007-2008 MARVELL INTERNATIONAL LTD.
4 * All rights reserved.
5 *
6 * Adapted to Marvell SoC by Semihalf.
7 *
8 * Redistribution and use in source and binary forms, with or without

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

50#include <arm/mv/mvvar.h>
51
52#include <dev/ofw/ofw_bus.h>
53#include <dev/ofw/ofw_bus_subr.h>
54
55#define INITIAL_TIMECOUNTER (0xffffffff)
56#define MAX_WATCHDOG_TICKS (0xffffffff)
57
1/*-
2 * Copyright (c) 2006 Benno Rice.
3 * Copyright (C) 2007-2008 MARVELL INTERNATIONAL LTD.
4 * All rights reserved.
5 *
6 * Adapted to Marvell SoC by Semihalf.
7 *
8 * Redistribution and use in source and binary forms, with or without

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

50#include <arm/mv/mvvar.h>
51
52#include <dev/ofw/ofw_bus.h>
53#include <dev/ofw/ofw_bus_subr.h>
54
55#define INITIAL_TIMECOUNTER (0xffffffff)
56#define MAX_WATCHDOG_TICKS (0xffffffff)
57
58#if defined(SOC_MV_ARMADAXP)
59#define MV_CLOCK_SRC get_l2clk()
60#else
61#define MV_CLOCK_SRC get_tclk()
62#endif
63
58struct mv_timer_softc {
59 struct resource * timer_res[2];
60 bus_space_tag_t timer_bst;
61 bus_space_handle_t timer_bsh;
62 struct mtx timer_mtx;
63 struct eventtimer et;
64};
65

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

111}
112
113static int
114mv_timer_attach(device_t dev)
115{
116 int error;
117 void *ihl;
118 struct mv_timer_softc *sc;
64struct mv_timer_softc {
65 struct resource * timer_res[2];
66 bus_space_tag_t timer_bst;
67 bus_space_handle_t timer_bsh;
68 struct mtx timer_mtx;
69 struct eventtimer et;
70};
71

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

117}
118
119static int
120mv_timer_attach(device_t dev)
121{
122 int error;
123 void *ihl;
124 struct mv_timer_softc *sc;
125#if !defined(SOC_MV_ARMADAXP)
119 uint32_t irq_cause, irq_mask;
126 uint32_t irq_cause, irq_mask;
127#endif
120
121 if (timer_softc != NULL)
122 return (ENXIO);
123
124 sc = (struct mv_timer_softc *)device_get_softc(dev);
125 timer_softc = sc;
126
127 error = bus_alloc_resources(dev, mv_timer_spec, sc->timer_res);

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

140 if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK,
141 mv_hardclock, NULL, sc, &ihl) != 0) {
142 bus_release_resources(dev, mv_timer_spec, sc->timer_res);
143 device_printf(dev, "Could not setup interrupt.\n");
144 return (ENXIO);
145 }
146
147 mv_setup_timers();
128
129 if (timer_softc != NULL)
130 return (ENXIO);
131
132 sc = (struct mv_timer_softc *)device_get_softc(dev);
133 timer_softc = sc;
134
135 error = bus_alloc_resources(dev, mv_timer_spec, sc->timer_res);

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

148 if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK,
149 mv_hardclock, NULL, sc, &ihl) != 0) {
150 bus_release_resources(dev, mv_timer_spec, sc->timer_res);
151 device_printf(dev, "Could not setup interrupt.\n");
152 return (ENXIO);
153 }
154
155 mv_setup_timers();
156#if !defined(SOC_MV_ARMADAXP)
148 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
157 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
149 irq_cause &= ~(IRQ_TIMER0);
158 irq_cause &= IRQ_TIMER0_CLR;
159
150 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
151 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
152 irq_mask |= IRQ_TIMER0_MASK;
153 irq_mask &= ~IRQ_TIMER1_MASK;
154 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
160 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
161 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
162 irq_mask |= IRQ_TIMER0_MASK;
163 irq_mask &= ~IRQ_TIMER1_MASK;
164 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
155
165#endif
156 sc->et.et_name = "CPUTimer0";
157 sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
158 sc->et.et_quality = 1000;
166 sc->et.et_name = "CPUTimer0";
167 sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
168 sc->et.et_quality = 1000;
159 sc->et.et_frequency = get_tclk();
169
170 sc->et.et_frequency = MV_CLOCK_SRC;
160 sc->et.et_min_period.sec = 0;
161 sc->et.et_min_period.frac =
162 ((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
163 sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
164 sc->et.et_max_period.frac =
165 ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
166 sc->et.et_start = mv_timer_start;
167 sc->et.et_stop = mv_timer_stop;
168 sc->et.et_priv = sc;
169 et_register(&sc->et);
171 sc->et.et_min_period.sec = 0;
172 sc->et.et_min_period.frac =
173 ((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
174 sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
175 sc->et.et_max_period.frac =
176 ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
177 sc->et.et_start = mv_timer_start;
178 sc->et.et_stop = mv_timer_stop;
179 sc->et.et_priv = sc;
180 et_register(&sc->et);
170 mv_timer_timecounter.tc_frequency = get_tclk();
181 mv_timer_timecounter.tc_frequency = MV_CLOCK_SRC;
171 tc_init(&mv_timer_timecounter);
172
173 return (0);
174}
175
176static int
177mv_hardclock(void *arg)
178{
179 struct mv_timer_softc *sc;
180 uint32_t irq_cause;
181
182 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
182 tc_init(&mv_timer_timecounter);
183
184 return (0);
185}
186
187static int
188mv_hardclock(void *arg)
189{
190 struct mv_timer_softc *sc;
191 uint32_t irq_cause;
192
193 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
183 irq_cause &= ~(IRQ_TIMER0);
194 irq_cause &= IRQ_TIMER0_CLR;
184 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
185
186 sc = (struct mv_timer_softc *)arg;
187 if (sc->et.et_active)
188 sc->et.et_event_cb(&sc->et, sc->et.et_arg);
189
190 return (FILTER_HANDLED);
191}

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

230 if (!timers_initialized) {
231 for (; usec > 0; usec--)
232 for (val = 100; val > 0; val--)
233 __asm __volatile("nop" ::: "memory");
234 return;
235 }
236
237 val = mv_get_timer(1);
195 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
196
197 sc = (struct mv_timer_softc *)arg;
198 if (sc->et.et_active)
199 sc->et.et_event_cb(&sc->et, sc->et.et_arg);
200
201 return (FILTER_HANDLED);
202}

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

241 if (!timers_initialized) {
242 for (; usec > 0; usec--)
243 for (val = 100; val > 0; val--)
244 __asm __volatile("nop" ::: "memory");
245 return;
246 }
247
248 val = mv_get_timer(1);
238 nticks = ((get_tclk() / 1000000 + 1) * usec);
249 nticks = ((MV_CLOCK_SRC / 1000000 + 1) * usec);
239
240 while (nticks > 0) {
241 val_temp = mv_get_timer(1);
242 if (val > val_temp)
243 nticks -= (val - val_temp);
244 else
245 nticks -= (val + (INITIAL_TIMECOUNTER - val_temp));
246

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

286
287 bus_space_write_4(timer_softc->timer_bst,
288 timer_softc->timer_bsh, CPU_TIMER0_REL + timer * 0x8, val);
289}
290
291static void
292mv_watchdog_enable(void)
293{
250
251 while (nticks > 0) {
252 val_temp = mv_get_timer(1);
253 if (val > val_temp)
254 nticks -= (val - val_temp);
255 else
256 nticks -= (val + (INITIAL_TIMECOUNTER - val_temp));
257

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

297
298 bus_space_write_4(timer_softc->timer_bst,
299 timer_softc->timer_bsh, CPU_TIMER0_REL + timer * 0x8, val);
300}
301
302static void
303mv_watchdog_enable(void)
304{
294 uint32_t val;
295 uint32_t irq_cause, irq_mask;
305 uint32_t val, irq_cause;
306#if !defined(SOC_MV_ARMADAXP)
307 uint32_t irq_mask;
308#endif
296
297 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
309
310 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
298 irq_cause &= ~(IRQ_TIMER_WD);
311 irq_cause &= IRQ_TIMER_WD_CLR;
299 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
300
312 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
313
314#if !defined(SOC_MV_ARMADAXP)
301 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
302 irq_mask |= IRQ_TIMER_WD_MASK;
303 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
315 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
316 irq_mask |= IRQ_TIMER_WD_MASK;
317 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
318#endif
304
305 val = read_cpu_ctrl(RSTOUTn_MASK);
306 val |= WD_RST_OUT_EN;
307 write_cpu_ctrl(RSTOUTn_MASK, val);
308
309 val = mv_get_timer_control();
310 val |= CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO;
311 mv_set_timer_control(val);
312}
313
314static void
315mv_watchdog_disable(void)
316{
319
320 val = read_cpu_ctrl(RSTOUTn_MASK);
321 val |= WD_RST_OUT_EN;
322 write_cpu_ctrl(RSTOUTn_MASK, val);
323
324 val = mv_get_timer_control();
325 val |= CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO;
326 mv_set_timer_control(val);
327}
328
329static void
330mv_watchdog_disable(void)
331{
317 uint32_t val;
318 uint32_t irq_cause, irq_mask;
332 uint32_t val, irq_cause;
333#if !defined(SOC_MV_ARMADAXP)
334 uint32_t irq_mask;
335#endif
319
320 val = mv_get_timer_control();
321 val &= ~(CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO);
322 mv_set_timer_control(val);
323
324 val = read_cpu_ctrl(RSTOUTn_MASK);
325 val &= ~WD_RST_OUT_EN;
326 write_cpu_ctrl(RSTOUTn_MASK, val);
327
336
337 val = mv_get_timer_control();
338 val &= ~(CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO);
339 mv_set_timer_control(val);
340
341 val = read_cpu_ctrl(RSTOUTn_MASK);
342 val &= ~WD_RST_OUT_EN;
343 write_cpu_ctrl(RSTOUTn_MASK, val);
344
345#if !defined(SOC_MV_ARMADAXP)
328 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
329 irq_mask &= ~(IRQ_TIMER_WD_MASK);
330 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
346 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
347 irq_mask &= ~(IRQ_TIMER_WD_MASK);
348 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
349#endif
331
332 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
350
351 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
333 irq_cause &= ~(IRQ_TIMER_WD);
352 irq_cause &= IRQ_TIMER_WD_CLR;
334 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
335}
336
337
338/*
339 * Watchdog event handler.
340 */
341static void

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

348 if (cmd == 0)
349 mv_watchdog_disable();
350 else {
351 /*
352 * Watchdog timeout is in nanosecs, calculation according to
353 * watchdog(9)
354 */
355 ns = (uint64_t)1 << (cmd & WD_INTERVAL);
353 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
354}
355
356
357/*
358 * Watchdog event handler.
359 */
360static void

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

367 if (cmd == 0)
368 mv_watchdog_disable();
369 else {
370 /*
371 * Watchdog timeout is in nanosecs, calculation according to
372 * watchdog(9)
373 */
374 ns = (uint64_t)1 << (cmd & WD_INTERVAL);
356 ticks = (uint64_t)(ns * get_tclk()) / 1000000000;
375 ticks = (uint64_t)(ns * MV_CLOCK_SRC) / 1000000000;
357 if (ticks > MAX_WATCHDOG_TICKS)
358 mv_watchdog_disable();
359 else {
360 /* Timer 2 is the watchdog */
361 mv_set_timer(2, ticks);
362 mv_watchdog_enable();
363 *error = 0;
364 }

--- 63 unchanged lines hidden ---
376 if (ticks > MAX_WATCHDOG_TICKS)
377 mv_watchdog_disable();
378 else {
379 /* Timer 2 is the watchdog */
380 mv_set_timer(2, ticks);
381 mv_watchdog_enable();
382 *error = 0;
383 }

--- 63 unchanged lines hidden ---