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 --- |