Deleted Added
full compact
timer.c (294416) timer.c (294436)
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

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

24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_timer.c, rev 1
29 */
30
31#include <sys/cdefs.h>
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

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

24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_timer.c, rev 1
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/arm/mv/timer.c 294416 2016-01-20 13:14:36Z zbb $");
32__FBSDID("$FreeBSD: head/sys/arm/mv/timer.c 294436 2016-01-20 14:23:57Z zbb $");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/bus.h>
37#include <sys/kernel.h>
38#include <sys/module.h>
39#include <sys/malloc.h>
40#include <sys/rman.h>

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

49#include <arm/mv/mvvar.h>
50
51#include <dev/ofw/ofw_bus.h>
52#include <dev/ofw/ofw_bus_subr.h>
53
54#define INITIAL_TIMECOUNTER (0xffffffff)
55#define MAX_WATCHDOG_TICKS (0xffffffff)
56
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/bus.h>
37#include <sys/kernel.h>
38#include <sys/module.h>
39#include <sys/malloc.h>
40#include <sys/rman.h>

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

49#include <arm/mv/mvvar.h>
50
51#include <dev/ofw/ofw_bus.h>
52#include <dev/ofw/ofw_bus_subr.h>
53
54#define INITIAL_TIMECOUNTER (0xffffffff)
55#define MAX_WATCHDOG_TICKS (0xffffffff)
56
57#define MV_TMR 0x1
58#define MV_WDT 0x2
59#define MV_NONE 0x0
60
57#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X)
58#define MV_CLOCK_SRC 25000000 /* Timers' 25MHz mode */
59#else
60#define MV_CLOCK_SRC get_tclk()
61#endif
62
61#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X)
62#define MV_CLOCK_SRC 25000000 /* Timers' 25MHz mode */
63#else
64#define MV_CLOCK_SRC get_tclk()
65#endif
66
67#if defined(SOC_MV_ARMADA38X)
68#define WATCHDOG_TIMER 4
69#else
70#define WATCHDOG_TIMER 2
71#endif
72
63struct mv_timer_softc {
64 struct resource * timer_res[2];
65 bus_space_tag_t timer_bst;
66 bus_space_handle_t timer_bsh;
67 struct mtx timer_mtx;
68 struct eventtimer et;
69};
70
71static struct resource_spec mv_timer_spec[] = {
72 { SYS_RES_MEMORY, 0, RF_ACTIVE },
73struct mv_timer_softc {
74 struct resource * timer_res[2];
75 bus_space_tag_t timer_bst;
76 bus_space_handle_t timer_bsh;
77 struct mtx timer_mtx;
78 struct eventtimer et;
79};
80
81static struct resource_spec mv_timer_spec[] = {
82 { SYS_RES_MEMORY, 0, RF_ACTIVE },
73 { SYS_RES_IRQ, 0, RF_ACTIVE },
83 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL },
74 { -1, 0 }
75};
76
84 { -1, 0 }
85};
86
87/* Interrupt is not required by MV_WDT devices */
88static struct ofw_compat_data mv_timer_compat[] = {
89 {"mrvl,timer", MV_TMR | MV_WDT },
90 {"marvell,armada-380-wdt", MV_WDT },
91 {NULL, MV_NONE }
92};
93
77static struct mv_timer_softc *timer_softc = NULL;
78static int timers_initialized = 0;
79
80static int mv_timer_probe(device_t);
81static int mv_timer_attach(device_t);
82
83static int mv_hardclock(void *);
84static unsigned mv_timer_get_timecount(struct timecounter *);

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

106
107static int
108mv_timer_probe(device_t dev)
109{
110
111 if (!ofw_bus_status_okay(dev))
112 return (ENXIO);
113
94static struct mv_timer_softc *timer_softc = NULL;
95static int timers_initialized = 0;
96
97static int mv_timer_probe(device_t);
98static int mv_timer_attach(device_t);
99
100static int mv_hardclock(void *);
101static unsigned mv_timer_get_timecount(struct timecounter *);

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

123
124static int
125mv_timer_probe(device_t dev)
126{
127
128 if (!ofw_bus_status_okay(dev))
129 return (ENXIO);
130
114 if (!ofw_bus_is_compatible(dev, "mrvl,timer"))
131 if (ofw_bus_search_compatible(dev, mv_timer_compat)->ocd_data == MV_NONE)
115 return (ENXIO);
116
117 device_set_desc(dev, "Marvell CPU Timer");
118 return (0);
119}
120
121static int
122mv_timer_attach(device_t dev)

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

142
143 sc->timer_bst = rman_get_bustag(sc->timer_res[0]);
144 sc->timer_bsh = rman_get_bushandle(sc->timer_res[0]);
145
146 mtx_init(&timer_softc->timer_mtx, "watchdog", NULL, MTX_DEF);
147 mv_watchdog_disable();
148 EVENTHANDLER_REGISTER(watchdog_list, mv_watchdog_event, sc, 0);
149
132 return (ENXIO);
133
134 device_set_desc(dev, "Marvell CPU Timer");
135 return (0);
136}
137
138static int
139mv_timer_attach(device_t dev)

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

159
160 sc->timer_bst = rman_get_bustag(sc->timer_res[0]);
161 sc->timer_bsh = rman_get_bushandle(sc->timer_res[0]);
162
163 mtx_init(&timer_softc->timer_mtx, "watchdog", NULL, MTX_DEF);
164 mv_watchdog_disable();
165 EVENTHANDLER_REGISTER(watchdog_list, mv_watchdog_event, sc, 0);
166
167 if (ofw_bus_search_compatible(dev, mv_timer_compat)->ocd_data
168 == MV_WDT) {
169 /* Don't set timers for wdt-only entry. */
170 device_printf(dev, "only watchdog attached\n");
171 return (0);
172 } else if (sc->timer_res[1] == NULL) {
173 device_printf(dev, "no interrupt resource\n");
174 bus_release_resources(dev, mv_timer_spec, sc->timer_res);
175 return (ENXIO);
176 }
177
150 if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK,
151 mv_hardclock, NULL, sc, &ihl) != 0) {
152 bus_release_resources(dev, mv_timer_spec, sc->timer_res);
153 device_printf(dev, "Could not setup interrupt.\n");
154 return (ENXIO);
155 }
156
157 mv_setup_timers();

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

301 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
302 irq_cause &= IRQ_TIMER_WD_CLR;
303 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
304
305#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X)
306 val = read_cpu_mp_clocks(WD_RSTOUTn_MASK);
307 val |= (WD_GLOBAL_MASK | WD_CPU0_MASK);
308 write_cpu_mp_clocks(WD_RSTOUTn_MASK, val);
178 if (bus_setup_intr(dev, sc->timer_res[1], INTR_TYPE_CLK,
179 mv_hardclock, NULL, sc, &ihl) != 0) {
180 bus_release_resources(dev, mv_timer_spec, sc->timer_res);
181 device_printf(dev, "Could not setup interrupt.\n");
182 return (ENXIO);
183 }
184
185 mv_setup_timers();

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

329 irq_cause = read_cpu_ctrl(BRIDGE_IRQ_CAUSE);
330 irq_cause &= IRQ_TIMER_WD_CLR;
331 write_cpu_ctrl(BRIDGE_IRQ_CAUSE, irq_cause);
332
333#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X)
334 val = read_cpu_mp_clocks(WD_RSTOUTn_MASK);
335 val |= (WD_GLOBAL_MASK | WD_CPU0_MASK);
336 write_cpu_mp_clocks(WD_RSTOUTn_MASK, val);
337
338 val = read_cpu_misc(RSTOUTn_MASK);
339 val &= ~RSTOUTn_MASK_WD;
340 write_cpu_misc(RSTOUTn_MASK, val);
309#else
310 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
311 irq_mask |= IRQ_TIMER_WD_MASK;
312 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
313
314 val = read_cpu_ctrl(RSTOUTn_MASK);
315 val |= WD_RST_OUT_EN;
316 write_cpu_ctrl(RSTOUTn_MASK, val);
317#endif
318
319 val = mv_get_timer_control();
341#else
342 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
343 irq_mask |= IRQ_TIMER_WD_MASK;
344 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);
345
346 val = read_cpu_ctrl(RSTOUTn_MASK);
347 val |= WD_RST_OUT_EN;
348 write_cpu_ctrl(RSTOUTn_MASK, val);
349#endif
350
351 val = mv_get_timer_control();
320 val |= CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO;
321#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X)
322 val |= CPU_TIMER_WD_25MHZ_EN;
352#if defined(SOC_MV_ARMADA38X)
353 val |= CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO | CPU_TIMER_WD_25MHZ_EN;
354#elif defined(SOC_MV_ARMADAXP)
355 val |= CPU_TIMER2_EN | CPU_TIMER2_AUTO | CPU_TIMER_WD_25MHZ_EN;
356#else
357 val |= CPU_TIMER2_EN | CPU_TIMER2_AUTO;
323#endif
324 mv_set_timer_control(val);
325}
326
327static void
328mv_watchdog_disable(void)
329{
330 uint32_t val, irq_cause;
331#if !defined(SOC_MV_ARMADAXP) && !defined(SOC_MV_ARMADA38X)
332 uint32_t irq_mask;
333#endif
334
335 val = mv_get_timer_control();
358#endif
359 mv_set_timer_control(val);
360}
361
362static void
363mv_watchdog_disable(void)
364{
365 uint32_t val, irq_cause;
366#if !defined(SOC_MV_ARMADAXP) && !defined(SOC_MV_ARMADA38X)
367 uint32_t irq_mask;
368#endif
369
370 val = mv_get_timer_control();
371#if defined(SOC_MV_ARMADA38X)
336 val &= ~(CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO);
372 val &= ~(CPU_TIMER_WD_EN | CPU_TIMER_WD_AUTO);
373#else
374 val &= ~(CPU_TIMER2_EN | CPU_TIMER2_AUTO);
375#endif
337 mv_set_timer_control(val);
338
339#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X)
340 val = read_cpu_mp_clocks(WD_RSTOUTn_MASK);
341 val &= ~(WD_GLOBAL_MASK | WD_CPU0_MASK);
342 write_cpu_mp_clocks(WD_RSTOUTn_MASK, val);
376 mv_set_timer_control(val);
377
378#if defined(SOC_MV_ARMADAXP) || defined(SOC_MV_ARMADA38X)
379 val = read_cpu_mp_clocks(WD_RSTOUTn_MASK);
380 val &= ~(WD_GLOBAL_MASK | WD_CPU0_MASK);
381 write_cpu_mp_clocks(WD_RSTOUTn_MASK, val);
382
383 val = read_cpu_misc(RSTOUTn_MASK);
384 val |= RSTOUTn_MASK_WD;
385 write_cpu_misc(RSTOUTn_MASK, RSTOUTn_MASK_WD);
343#else
344 val = read_cpu_ctrl(RSTOUTn_MASK);
345 val &= ~WD_RST_OUT_EN;
346 write_cpu_ctrl(RSTOUTn_MASK, val);
347
348 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
349 irq_mask &= ~(IRQ_TIMER_WD_MASK);
350 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);

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

373 * Watchdog timeout is in nanosecs, calculation according to
374 * watchdog(9)
375 */
376 ns = (uint64_t)1 << (cmd & WD_INTERVAL);
377 ticks = (uint64_t)(ns * MV_CLOCK_SRC) / 1000000000;
378 if (ticks > MAX_WATCHDOG_TICKS)
379 mv_watchdog_disable();
380 else {
386#else
387 val = read_cpu_ctrl(RSTOUTn_MASK);
388 val &= ~WD_RST_OUT_EN;
389 write_cpu_ctrl(RSTOUTn_MASK, val);
390
391 irq_mask = read_cpu_ctrl(BRIDGE_IRQ_MASK);
392 irq_mask &= ~(IRQ_TIMER_WD_MASK);
393 write_cpu_ctrl(BRIDGE_IRQ_MASK, irq_mask);

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

416 * Watchdog timeout is in nanosecs, calculation according to
417 * watchdog(9)
418 */
419 ns = (uint64_t)1 << (cmd & WD_INTERVAL);
420 ticks = (uint64_t)(ns * MV_CLOCK_SRC) / 1000000000;
421 if (ticks > MAX_WATCHDOG_TICKS)
422 mv_watchdog_disable();
423 else {
381 /* Timer 2 is the watchdog */
382 mv_set_timer(2, ticks);
424 mv_set_timer(WATCHDOG_TIMER, ticks);
383 mv_watchdog_enable();
384 *error = 0;
385 }
386 }
387 mtx_unlock(&timer_softc->timer_mtx);
388}
389
390static int

--- 57 unchanged lines hidden ---
425 mv_watchdog_enable();
426 *error = 0;
427 }
428 }
429 mtx_unlock(&timer_softc->timer_mtx);
430}
431
432static int

--- 57 unchanged lines hidden ---