static void kw_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { unsigned long flags; local_irq_save(flags); if (mode == CLOCK_EVT_MODE_PERIODIC) { /* * Setup latch cycles in timer and enable reload interrupt. */ MV_REG_WRITE(CNTMR_RELOAD_REG(CLOCKEVENT), ((mvBoardTclkGet() + HZ/2) / HZ)); MV_REG_WRITE(CNTMR_VAL_REG(CLOCKEVENT), ((mvBoardTclkGet() + HZ/2) / HZ)); MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT)); MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT) | TIMER_EN(CLOCKEVENT)); } else { /* * Disable timer and interrupt */ MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT)); MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT)); MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT) | TIMER_EN(CLOCKEVENT)); } local_irq_restore(flags); }
int mv_enable_fc_events(void *fc_event_handler, unsigned long period_ns) { unsigned long flags; uint64_t clock_ticks = period_ns; if (fc_event_handler == 0) return -1; local_irq_save(flags); mv_fc_event_handler = fc_event_handler; clock_ticks *= kw_clkevt.mult; clock_ticks >>= kw_clkevt.shift; /* Setup timer value */ MV_REG_WRITE(CNTMR_RELOAD_REG(FCTRLEVENT), (unsigned long)clock_ticks); MV_REG_WRITE(CNTMR_VAL_REG(FCTRLEVENT), (unsigned long)clock_ticks); /* Enable periodic timer and timer interrupt */ MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(FCTRLEVENT)); MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(FCTRLEVENT) | TIMER_EN(FCTRLEVENT)); fc_disabled = 0; local_irq_restore(flags); return 0; }
/******************************************************************************* * mvCntmrLoad - * * DESCRIPTION: * Load an init Value to a given counter/timer * * INPUT: * countNum - counter number * value - value to be loaded * * OUTPUT: * None. * * RETURN: * MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess *******************************************************************************/ MV_STATUS mvCntmrLoad(MV_U32 countNum, MV_U32 value) { if (countNum >= MV_CNTMR_MAX_COUNTER) { mvOsPrintf(("mvCntmrLoad: Err. illegal counter number \n")); return MV_BAD_PARAM;; } MV_REG_WRITE(CNTMR_RELOAD_REG(countNum), value); MV_REG_WRITE(CNTMR_VAL_REG(countNum), value); return MV_OK; }
/* * init the counter */ int timer_init(void) { unsigned int cntmrctrl; /* load value into timer */ writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR)); writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR)); /* enable timer in auto reload mode */ cntmrctrl = readl(CNTMR_CTRL_REG); cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR); cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR); writel(cntmrctrl, CNTMR_CTRL_REG); return 0; }
static void mv_init_timer(void) { /* * Setup clocksource free running timer (no interrupt on reload) */ MV_REG_WRITE(CNTMR_VAL_REG(CLOCKSOURCE), 0xffffffff); MV_REG_WRITE(CNTMR_RELOAD_REG(CLOCKSOURCE), 0xffffffff); MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKSOURCE)); MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKSOURCE) | TIMER_EN(CLOCKSOURCE)); kw_clkevt.cpumask = cpumask_of(0); /* * Register clocksource */ kw_clksrc.mult = clocksource_hz2mult(mvBoardTclkGet(), kw_clksrc.shift); clocksource_register(&kw_clksrc); /* * Connect and enable tick handler */ setup_irq(IRQ_BRIDGE, &kw_timer_irq); /* * Register clockevent */ kw_clkevt.mult = div_sc(mvBoardTclkGet(), NSEC_PER_SEC, kw_clkevt.shift); kw_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &kw_clkevt); kw_clkevt.min_delta_ns = clockevent_delta2ns(1, &kw_clkevt); /* * Setup clockevent timer (interrupt-driven.) */ clockevents_register_device(&kw_clkevt); }