/* * XXX:may be call at interrupt. * 20091116,HSL@RK,bug:if TIMER_CLKSRC down to 0 and set to max, and irq was disabled * */ cycle_t rockchip_timer_read(void) { #if CHIP_RK281X unsigned int t = RK_TIMER_READVALUE(TIMER_CLKSRC); return ~t; #else unsigned int t = RK_TIMER_READVALUE(TIMER_CLKSRC); unsigned int c = RK_TIMER_GETCOUNT(TIMER_CLKSRC); static unsigned int last_cycle; // for debug cycle reverse. t = (c-t); last_cycle = t; return t/rockchip_apb_clk; #endif }
static int rk29_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { do { RK_TIMER_DISABLE(TIMER_CLKEVT); RK_TIMER_SETCOUNT(TIMER_CLKEVT, cycles); RK_TIMER_ENABLE(TIMER_CLKEVT); } while (RK_TIMER_READVALUE(TIMER_CLKEVT) > cycles); return 0; }
static inline u32 rk30_timer_read_current_value(u32 n) { unsigned long flags; u32 v[3]; int loop = 100; do { local_irq_save(flags); v[0] = RK_TIMER_READVALUE(n); v[1] = RK_TIMER_READVALUE(n); v[2] = RK_TIMER_READVALUE(n); local_irq_restore(flags); if ((v[0] >= v[1]) && ((v[0] - v[1]) < 24) && (v[1] >= v[2]) && ((v[1] - v[2]) < 24)) break; } while (loop--); return v[1]; }
void rockchip_timer_freeze(int freeze ) { unsigned long flags; local_irq_save( flags ); if( freeze ) { clock_event_freeze_count = RK_TIMER_READVALUE(TIMER_CLKSRC); RK_TIMER_DISABLE(TIMER_CLKSRC); RK_TIMER_DISABLE(TIMER_CLKEVT); } else { RK_TIMER_SETCOUNT(TIMER_CLKSRC,clock_event_freeze_count); RK_TIMER_ENABLE(TIMER_CLKSRC); RK_TIMER_ENABLE(TIMER_CLKEVT); } clock_source_freezed = freeze; local_irq_restore(flags); }
static void rk29_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: do { RK_TIMER_DISABLE(TIMER_CLKEVT); RK_TIMER_SETCOUNT(TIMER_CLKEVT, 24000000/HZ - 1); RK_TIMER_ENABLE(TIMER_CLKEVT); } while (RK_TIMER_READVALUE(TIMER_CLKEVT) > (24000000/HZ - 1)); break; case CLOCK_EVT_MODE_RESUME: case CLOCK_EVT_MODE_ONESHOT: break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: RK_TIMER_DISABLE(TIMER_CLKEVT); break; } }
/* * 20091120,HSL@RK,disable irq for enable timer and set count . * */ void rockchip_timer_clocksource_suspend_resume(int suspend ) { unsigned long flags; local_irq_save( flags ); RK_TIMER_DISABLE(TIMER_CLKEVT); #if 0 if( suspend ) { RK_TIMER_SETCOUNT(TIMER_CLKEVT,RK_CHECK_VBUS_COUNT*rockchip_apb_clk); RK_TIMER_ENABLE(TIMER_CLKEVT); } else { int cyl = RK_TIMER_GETCOUNT(TIMER_CLKEVT) - RK_TIMER_READVALUE(TIMER_CLKEVT); rktimer_update_suspend_ms( CHECK_VBUS_MS*cyl / RK_TIMER_GETCOUNT(TIMER_CLKEVT) ); } S_INFO("r/s timer,load cnt=0x%x,clk_source_suspend=%ld\n" , RK_TIMER_GETCOUNT(TIMER_CLKEVT), clk_source_suspend_second); #endif local_irq_restore(flags); }