⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 time.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	asm ("getcon cr62, %0" : "=r" (current_ctc));	ctc_last_interrupt = (unsigned long) current_ctc;	do_timer(regs);#ifndef CONFIG_SMP	update_process_times(user_mode(regs));#endif	profile_tick(CPU_PROFILING, regs);#ifdef CONFIG_HEARTBEAT	{		extern void heartbeat(void);		heartbeat();	}#endif	/*	 * If we have an externally synchronized Linux clock, then update	 * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be	 * called as close as possible to 500 ms before the new second starts.	 */	if (ntp_synced() &&	    xtime.tv_sec > last_rtc_update + 660 &&	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {		if (set_rtc_time(xtime.tv_sec) == 0)			last_rtc_update = xtime.tv_sec;		else			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */	}}/* * This is the same as the above, except we _also_ save the current * Time Stamp Counter value at the time of the timer interrupt, so that * we later on can estimate the time of day more exactly. */static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs){	unsigned long timer_status;	/* Clear UNF bit */	timer_status = ctrl_inw(TMU0_TCR);	timer_status &= ~0x100;	ctrl_outw(timer_status, TMU0_TCR);	/*	 * Here we are in the timer irq handler. We just have irqs locally	 * disabled but we don't know if the timer_bh is running on the other	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need	 * the irq version of write_lock because as just said we have irq	 * locally disabled. -arca	 */	write_lock(&xtime_lock);	do_timer_interrupt(irq, regs);	write_unlock(&xtime_lock);	return IRQ_HANDLED;}static unsigned long get_rtc_time(void){	unsigned int sec, min, hr, wk, day, mon, yr, yr100; again:	do {		ctrl_outb(0, RCR1);  /* Clear CF-bit */		sec = ctrl_inb(RSECCNT);		min = ctrl_inb(RMINCNT);		hr  = ctrl_inb(RHRCNT);		wk  = ctrl_inb(RWKCNT);		day = ctrl_inb(RDAYCNT);		mon = ctrl_inb(RMONCNT);		yr  = ctrl_inw(RYRCNT);		yr100 = (yr >> 8);		yr &= 0xff;	} while ((ctrl_inb(RCR1) & RCR1_CF) != 0);	BCD_TO_BIN(yr100);	BCD_TO_BIN(yr);	BCD_TO_BIN(mon);	BCD_TO_BIN(day);	BCD_TO_BIN(hr);	BCD_TO_BIN(min);	BCD_TO_BIN(sec);	if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||	    hr > 23 || min > 59 || sec > 59) {		printk(KERN_ERR		       "SH RTC: invalid value, resetting to 1 Jan 2000\n");		ctrl_outb(RCR2_RESET, RCR2);  /* Reset & Stop */		ctrl_outb(0, RSECCNT);		ctrl_outb(0, RMINCNT);		ctrl_outb(0, RHRCNT);		ctrl_outb(6, RWKCNT);		ctrl_outb(1, RDAYCNT);		ctrl_outb(1, RMONCNT);		ctrl_outw(0x2000, RYRCNT);		ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2);  /* Start */		goto again;	}	return mktime(yr100 * 100 + yr, mon, day, hr, min, sec);}static __init unsigned int get_cpu_hz(void){	unsigned int count;	unsigned long __dummy;	unsigned long ctc_val_init, ctc_val;	/*	** Regardless the toolchain, force the compiler to use the	** arbitrary register r3 as a clock tick counter.	** NOTE: r3 must be in accordance with rtc_interrupt()	*/	register unsigned long long  __rtc_irq_flag __asm__ ("r3");	local_irq_enable();	do {} while (ctrl_inb(R64CNT) != 0);	ctrl_outb(RCR1_CIE, RCR1); /* Enable carry interrupt */	/*	 * r3 is arbitrary. CDC does not support "=z".	 */	ctc_val_init = 0xffffffff;	ctc_val = ctc_val_init;	asm volatile("gettr	tr0, %1\n\t"		     "putcon	%0, " __CTC "\n\t"		     "and	%2, r63, %2\n\t"		     "pta	$+4, tr0\n\t"		     "beq/l	%2, r63, tr0\n\t"		     "ptabs	%1, tr0\n\t"		     "getcon	" __CTC ", %0\n\t"		: "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag)		: "0" (0));	local_irq_disable();	/*	 * SH-3:	 * CPU clock = 4 stages * loop	 * tst    rm,rm      if id ex	 * bt/s   1b            if id ex	 * add    #1,rd            if id ex         *                            (if) pipe line stole	 * tst    rm,rm                  if id ex         * ....	 *	 *	 * SH-4:	 * CPU clock = 6 stages * loop	 * I don't know why.         * ....	 *	 * SH-5:	 * Use CTC register to count.  This approach returns the right value	 * even if the I-cache is disabled (e.g. whilst debugging.)	 *	 */	count = ctc_val_init - ctc_val; /* CTC counts down */#if defined (CONFIG_SH_SIMULATOR)	/*	 * Let's pretend we are a 5MHz SH-5 to avoid a too	 * little timer interval. Also to keep delay	 * calibration within a reasonable time.	 */	return 5000000;#else	/*	 * This really is count by the number of clock cycles         * by the ratio between a complete R64CNT         * wrap-around (128) and CUI interrupt being raised (64).	 */	return count*2;#endif}static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs){	ctrl_outb(0, RCR1);	/* Disable Carry Interrupts */	regs->regs[3] = 1;	/* Using r3 */	return IRQ_HANDLED;}static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};static struct irqaction irq1  = { rtc_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "rtc", NULL, NULL};void __init time_init(void){	unsigned int cpu_clock, master_clock, bus_clock, module_clock;	unsigned long interval;	unsigned long frqcr, ifc, pfc;	static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 };#define bfc_table ifc_table	/* Same */#define pfc_table ifc_table	/* Same */	tmu_base = onchip_remap(TMU_BASE, 1024, "TMU");	if (!tmu_base) {		panic("Unable to remap TMU\n");	}	rtc_base = onchip_remap(RTC_BASE, 1024, "RTC");	if (!rtc_base) {		panic("Unable to remap RTC\n");	}	cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC");	if (!cprc_base) {		panic("Unable to remap CPRC\n");	}	xtime.tv_sec = get_rtc_time();	xtime.tv_nsec = 0;	setup_irq(TIMER_IRQ, &irq0);	setup_irq(RTC_IRQ, &irq1);	/* Check how fast it is.. */	cpu_clock = get_cpu_hz();	/* Note careful order of operations to maintain reasonable precision and avoid overflow. */	scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) / (unsigned long long)(cpu_clock / HZ));	disable_irq(RTC_IRQ);	printk("CPU clock: %d.%02dMHz\n",	       (cpu_clock / 1000000), (cpu_clock % 1000000)/10000);	{		unsigned short bfc;		frqcr = ctrl_inl(FRQCR);		ifc  = ifc_table[(frqcr>> 6) & 0x0007];		bfc  = bfc_table[(frqcr>> 3) & 0x0007];		pfc  = pfc_table[(frqcr>> 12) & 0x0007];		master_clock = cpu_clock * ifc;		bus_clock = master_clock/bfc;	}	printk("Bus clock: %d.%02dMHz\n",	       (bus_clock/1000000), (bus_clock % 1000000)/10000);	module_clock = master_clock/pfc;	printk("Module clock: %d.%02dMHz\n",	       (module_clock/1000000), (module_clock % 1000000)/10000);	interval = (module_clock/(HZ*4));	printk("Interval = %ld\n", interval);	current_cpu_data.cpu_clock    = cpu_clock;	current_cpu_data.master_clock = master_clock;	current_cpu_data.bus_clock    = bus_clock;	current_cpu_data.module_clock = module_clock;	/* Start TMU0 */	ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);	ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);	ctrl_outl(interval, TMU0_TCOR);	ctrl_outl(interval, TMU0_TCNT);	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);}void enter_deep_standby(void){	/* Disable watchdog timer */	ctrl_outl(0xa5000000, WTCSR);	/* Configure deep standby on sleep */	ctrl_outl(0x03, STBCR);#ifdef CONFIG_SH_ALPHANUMERIC	{		extern void mach_alphanum(int position, unsigned char value);		extern void mach_alphanum_brightness(int setting);		char halted[] = "Halted. ";		int i;		mach_alphanum_brightness(6); /* dimmest setting above off */		for (i=0; i<8; i++) {			mach_alphanum(i, halted[i]);		}		asm __volatile__ ("synco");	}#endif	asm __volatile__ ("sleep");	asm __volatile__ ("synci");	asm __volatile__ ("nop");	asm __volatile__ ("nop");	asm __volatile__ ("nop");	asm __volatile__ ("nop");	panic("Unexpected wakeup!\n");}/* * Scheduler clock - returns current time in nanosec units. */unsigned long long sched_clock(void){	return (unsigned long long)jiffies * (1000000000 / HZ);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -