time.c

来自「底层驱动开发」· C语言 代码 · 共 638 行 · 第 1/2 页

C
638
字号
		if (prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {			prom_printf("clock_probe: FAILED!\n");			prom_halt();		}		if (sparc_cpu_model == sun4d)			prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1);		else			prom_apply_obio_ranges(clk_reg, 1);		/* Map the clock register io area read-only */		r.flags = clk_reg[0].which_io;		r.start = clk_reg[0].phys_addr;		mstk48t02_regs = sbus_ioremap(&r, 0,		    sizeof(struct mostek48t02), "mk48t02");		mstk48t08_regs = NULL;  /* To catch weirdness */	} else if (strcmp(model, "mk48t08") == 0) {		sp_clock_typ = MSTK48T08;		if(prom_getproperty(node, "reg", (char *) clk_reg,				    sizeof(clk_reg)) == -1) {			prom_printf("clock_probe: FAILED!\n");			prom_halt();		}		if (sparc_cpu_model == sun4d)			prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1);		else			prom_apply_obio_ranges(clk_reg, 1);		/* Map the clock register io area read-only */		/* XXX r/o attribute is somewhere in r.flags */		r.flags = clk_reg[0].which_io;		r.start = clk_reg[0].phys_addr;		mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0,		    sizeof(struct mostek48t08), "mk48t08");		mstk48t02_regs = &mstk48t08_regs->regs;	} else {		prom_printf("CLOCK: Unknown model name '%s'\n",model);		prom_halt();	}	/* Report a low battery voltage condition. */	if (has_low_battery())		printk(KERN_CRIT "NVRAM: Low battery voltage!\n");	/* Kick start the clock if it is completely stopped. */	if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)		kick_start_clock();}void __init sbus_time_init(void){	unsigned int year, mon, day, hour, min, sec;	struct mostek48t02 *mregs;#ifdef CONFIG_SUN4	int temp;	struct intersil *iregs;#endif	BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);	btfixup();	if (ARCH_SUN4)		sun4_clock_probe();	else		clock_probe();	sparc_init_timers(timer_interrupt);	#ifdef CONFIG_SUN4	if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {#endif	mregs = (struct mostek48t02 *)mstk48t02_regs;	if(!mregs) {		prom_printf("Something wrong, clock regs not mapped yet.\n");		prom_halt();	}			spin_lock_irq(&mostek_lock);	mregs->creg |= MSTK_CREG_READ;	sec = MSTK_REG_SEC(mregs);	min = MSTK_REG_MIN(mregs);	hour = MSTK_REG_HOUR(mregs);	day = MSTK_REG_DOM(mregs);	mon = MSTK_REG_MONTH(mregs);	year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);        set_normalized_timespec(&wall_to_monotonic,                                -xtime.tv_sec, -xtime.tv_nsec);	mregs->creg &= ~MSTK_CREG_READ;	spin_unlock_irq(&mostek_lock);#ifdef CONFIG_SUN4	} else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) {		/* initialise the intersil on sun4 */		iregs=intersil_clock;		if(!iregs) {			prom_printf("Something wrong, clock regs not mapped yet.\n");			prom_halt();		}		intersil_intr(intersil_clock,INTERSIL_INT_100HZ);		disable_pil_irq(10);		intersil_stop(iregs);		intersil_read_intr(intersil_clock, temp);		temp = iregs->clk.int_csec;		sec = iregs->clk.int_sec;		min = iregs->clk.int_min;		hour = iregs->clk.int_hour;		day = iregs->clk.int_day;		mon = iregs->clk.int_month;		year = MSTK_CVT_YEAR(iregs->clk.int_year);		enable_pil_irq(10);		intersil_start(iregs);		xtime.tv_sec = mktime(year, mon, day, hour, min, sec);		xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);	        set_normalized_timespec(&wall_to_monotonic, 	                               -xtime.tv_sec, -xtime.tv_nsec);		printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec);	}#endif	/* Now that OBP ticker has been silenced, it is safe to enable IRQ. */	local_irq_enable();}void __init time_init(void){#ifdef CONFIG_PCI	extern void pci_time_init(void);	if (pcic_present()) {		pci_time_init();		return;	}#endif	sbus_time_init();}static inline unsigned long do_gettimeoffset(void){	return (*master_l10_counter >> 10) & 0x1fffff;}/* * Returns nanoseconds * XXX This is a suboptimal implementation. */unsigned long long sched_clock(void){	return (unsigned long long)jiffies * (1000000000 / HZ);}/* Ok, my cute asm atomicity trick doesn't work anymore. * There are just too many variables that need to be protected * now (both members of xtime, wall_jiffies, et al.) */void do_gettimeofday(struct timeval *tv){	unsigned long flags;	unsigned long seq;	unsigned long usec, sec;	unsigned long max_ntp_tick = tick_usec - tickadj;	do {		unsigned long lost;		seq = read_seqbegin_irqsave(&xtime_lock, flags);		usec = do_gettimeoffset();		lost = jiffies - wall_jiffies;		/*		 * If time_adjust is negative then NTP is slowing the clock		 * so make sure not to go into next possible interval.		 * Better to lose some accuracy than have time go backwards..		 */		if (unlikely(time_adjust < 0)) {			usec = min(usec, max_ntp_tick);			if (lost)				usec += lost * max_ntp_tick;		}		else if (unlikely(lost))			usec += lost * tick_usec;		sec = xtime.tv_sec;		usec += (xtime.tv_nsec / 1000);	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));	while (usec >= 1000000) {		usec -= 1000000;		sec++;	}	tv->tv_sec = sec;	tv->tv_usec = usec;}EXPORT_SYMBOL(do_gettimeofday);int do_settimeofday(struct timespec *tv){	int ret;	write_seqlock_irq(&xtime_lock);	ret = bus_do_settimeofday(tv);	write_sequnlock_irq(&xtime_lock);	clock_was_set();	return ret;}EXPORT_SYMBOL(do_settimeofday);static int sbus_do_settimeofday(struct timespec *tv){	time_t wtm_sec, sec = tv->tv_sec;	long wtm_nsec, nsec = tv->tv_nsec;	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)		return -EINVAL;	/*	 * This is revolting. We need to set "xtime" correctly. However, the	 * value in this location is the value at the most recent update of	 * wall time.  Discover what correction gettimeofday() would have	 * made, and then undo it!	 */	nsec -= 1000 * (do_gettimeoffset() +			(jiffies - wall_jiffies) * (USEC_PER_SEC / HZ));	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);	set_normalized_timespec(&xtime, sec, nsec);	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);	ntp_clear();	return 0;}/* * BUG: This routine does not handle hour overflow properly; it just *      sets the minutes. Usually you won't notice until after reboot! */static int set_rtc_mmss(unsigned long nowtime){	int real_seconds, real_minutes, mostek_minutes;	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;	unsigned long flags;#ifdef CONFIG_SUN4	struct intersil *iregs = intersil_clock;	int temp;#endif	/* Not having a register set can lead to trouble. */	if (!regs) {#ifdef CONFIG_SUN4		if(!iregs)		return -1;	 	else {			temp = iregs->clk.int_csec;			mostek_minutes = iregs->clk.int_min;			real_seconds = nowtime % 60;			real_minutes = nowtime / 60;			if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)				real_minutes += 30;	/* correct for half hour time zone */			real_minutes %= 60;			if (abs(real_minutes - mostek_minutes) < 30) {				intersil_stop(iregs);				iregs->clk.int_sec=real_seconds;				iregs->clk.int_min=real_minutes;				intersil_start(iregs);			} else {				printk(KERN_WARNING			       "set_rtc_mmss: can't update from %d to %d\n",				       mostek_minutes, real_minutes);				return -1;			}						return 0;		}#endif	}	spin_lock_irqsave(&mostek_lock, flags);	/* Read the current RTC minutes. */	regs->creg |= MSTK_CREG_READ;	mostek_minutes = MSTK_REG_MIN(regs);	regs->creg &= ~MSTK_CREG_READ;	/*	 * since we're only adjusting minutes and seconds,	 * don't interfere with hour overflow. This avoids	 * messing with unknown time zones but requires your	 * RTC not to be off by more than 15 minutes	 */	real_seconds = nowtime % 60;	real_minutes = nowtime / 60;	if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)		real_minutes += 30;	/* correct for half hour time zone */	real_minutes %= 60;	if (abs(real_minutes - mostek_minutes) < 30) {		regs->creg |= MSTK_CREG_WRITE;		MSTK_SET_REG_SEC(regs,real_seconds);		MSTK_SET_REG_MIN(regs,real_minutes);		regs->creg &= ~MSTK_CREG_WRITE;		spin_unlock_irqrestore(&mostek_lock, flags);		return 0;	} else {		spin_unlock_irqrestore(&mostek_lock, flags);		return -1;	}}

⌨️ 快捷键说明

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