1/* 2 * arch/blackfin/kernel/time.c 3 * 4 * This file contains the Blackfin-specific time handling details. 5 * Most of the stuff is located in the machine specific files. 6 * 7 * Copyright 2004-2008 Analog Devices Inc. 8 * Licensed under the GPL-2 or later. 9 */ 10 11#include <linux/module.h> 12#include <linux/profile.h> 13#include <linux/interrupt.h> 14#include <linux/time.h> 15#include <linux/irq.h> 16#include <linux/delay.h> 17#include <linux/sched.h> 18 19#include <asm/blackfin.h> 20#include <asm/time.h> 21#include <asm/gptimers.h> 22 23/* This is an NTP setting */ 24#define TICK_SIZE (tick_nsec / 1000) 25 26static struct irqaction bfin_timer_irq = { 27 .name = "Blackfin Timer Tick", 28 .flags = IRQF_DISABLED 29}; 30 31#if defined(CONFIG_IPIPE) 32void __init setup_system_timer0(void) 33{ 34 /* Power down the core timer, just to play safe. */ 35 bfin_write_TCNTL(0); 36 37 disable_gptimers(TIMER0bit); 38 set_gptimer_status(0, TIMER_STATUS_TRUN0); 39 while (get_gptimer_status(0) & TIMER_STATUS_TRUN0) 40 udelay(10); 41 42 set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */ 43 set_gptimer_period(TIMER0_id, get_sclk() / HZ); 44 set_gptimer_pwidth(TIMER0_id, 1); 45 SSYNC(); 46 enable_gptimers(TIMER0bit); 47} 48#else 49void __init setup_core_timer(void) 50{ 51 u32 tcount; 52 53 /* power up the timer, but don't enable it just yet */ 54 bfin_write_TCNTL(1); 55 CSYNC(); 56 57 /* the TSCALE prescaler counter */ 58 bfin_write_TSCALE(TIME_SCALE - 1); 59 60 tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); 61 bfin_write_TPERIOD(tcount); 62 bfin_write_TCOUNT(tcount); 63 64 /* now enable the timer */ 65 CSYNC(); 66 67 bfin_write_TCNTL(7); 68} 69#endif 70 71static void __init 72time_sched_init(irqreturn_t(*timer_routine) (int, void *)) 73{ 74#if defined(CONFIG_IPIPE) 75 setup_system_timer0(); 76 bfin_timer_irq.handler = timer_routine; 77 setup_irq(IRQ_TIMER0, &bfin_timer_irq); 78#else 79 setup_core_timer(); 80 bfin_timer_irq.handler = timer_routine; 81 setup_irq(IRQ_CORETMR, &bfin_timer_irq); 82#endif 83} 84 85#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET 86/* 87 * Should return useconds since last timer tick 88 */ 89u32 arch_gettimeoffset(void) 90{ 91 unsigned long offset; 92 unsigned long clocks_per_jiffy; 93 94#if defined(CONFIG_IPIPE) 95 clocks_per_jiffy = bfin_read_TIMER0_PERIOD(); 96 offset = bfin_read_TIMER0_COUNTER() / \ 97 (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); 98 99 if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2)) 100 offset += (USEC_PER_SEC / HZ); 101#else 102 clocks_per_jiffy = bfin_read_TPERIOD(); 103 offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \ 104 (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC); 105 106 /* Check if we just wrapped the counters and maybe missed a tick */ 107 if ((bfin_read_ILAT() & (1 << IRQ_CORETMR)) 108 && (offset < (100000 / HZ / 2))) 109 offset += (USEC_PER_SEC / HZ); 110#endif 111 return offset; 112} 113#endif 114 115static inline int set_rtc_mmss(unsigned long nowtime) 116{ 117 return 0; 118} 119 120/* 121 * timer_interrupt() needs to keep up the real-time clock, 122 * as well as call the "do_timer()" routine every clocktick 123 */ 124#ifdef CONFIG_CORE_TIMER_IRQ_L1 125__attribute__((l1_text)) 126#endif 127irqreturn_t timer_interrupt(int irq, void *dummy) 128{ 129 /* last time the cmos clock got updated */ 130 static long last_rtc_update; 131 132 write_seqlock(&xtime_lock); 133 do_timer(1); 134 135 /* 136 * If we have an externally synchronized Linux clock, then update 137 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be 138 * called as close as possible to 500 ms before the new second starts. 139 */ 140 if (ntp_synced() && 141 xtime.tv_sec > last_rtc_update + 660 && 142 (xtime.tv_nsec / NSEC_PER_USEC) >= 143 500000 - ((unsigned)TICK_SIZE) / 2 144 && (xtime.tv_nsec / NSEC_PER_USEC) <= 145 500000 + ((unsigned)TICK_SIZE) / 2) { 146 if (set_rtc_mmss(xtime.tv_sec) == 0) 147 last_rtc_update = xtime.tv_sec; 148 else 149 /* Do it again in 60s. */ 150 last_rtc_update = xtime.tv_sec - 600; 151 } 152 write_sequnlock(&xtime_lock); 153 154#ifdef CONFIG_IPIPE 155 update_root_process_times(get_irq_regs()); 156#else 157 update_process_times(user_mode(get_irq_regs())); 158#endif 159 profile_tick(CPU_PROFILING); 160 161 return IRQ_HANDLED; 162} 163 164void __init time_init(void) 165{ 166 time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */ 167 168#ifdef CONFIG_RTC_DRV_BFIN 169 /* [#2663] hack to filter junk RTC values that would cause 170 * userspace to have to deal with time values greater than 171 * 2^31 seconds (which uClibc cannot cope with yet) 172 */ 173 if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) { 174 printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n"); 175 bfin_write_RTC_STAT(0); 176 } 177#endif 178 179 /* Initialize xtime. From now on, xtime is updated with timer interrupts */ 180 xtime.tv_sec = secs_since_1970; 181 xtime.tv_nsec = 0; 182 183 wall_to_monotonic.tv_sec = -xtime.tv_sec; 184 185 time_sched_init(timer_interrupt); 186} 187 188/* 189 * Scheduler clock - returns current time in nanosec units. 190 */ 191unsigned long long sched_clock(void) 192{ 193 return (unsigned long long)jiffies *(NSEC_PER_SEC / HZ); 194} 195