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

📄 time.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 3 页
字号:
-	au_sync();-	offset = pc0 - last_pc0;-	if (offset > 2*MATCH20_INC) {-		printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", -				(unsigned)offset, (unsigned)last_pc0, -				(unsigned)last_match20, (unsigned)pc0);-	}-	offset = (unsigned long)((offset * 305) / 10);-	return offset;+	irq_exit();+	return;++null:+	irq_exit();+	ack_r4ktimer(0); }+++/*+ * We read the real processor speed from the PLL.  This is important+ * because it is more accurate than computing it from the 32KHz+ * counter, if it exists.  If we don't have an accurate processor+ * speed, all of the peripherals that derive their clocks based on+ * this advertised speed will introduce error and sometimes not work+ * properly.  This function is futher convoluted to still allow configurations+ * to do that in case they have really, really old silicon with a+ * write-only PLL register, that we need the 32KHz when power management+ * "wait" is enabled, and we need to detect if the 32KHz isn't present+ * but requested......got it? :-)		-- Dan+ */+unsigned long cal_r4koff(void)+{+	u32 cpu_freq, flags;++	spin_lock_irqsave(&time_lock, flags);++#ifdef CONFIG_SOC_AU1000+	/* On early Au1000s, sys_cpupll was write-only. Since these+	silicon versions of Au1000 are not sold by AMD, we don't bend+	over backwards trying to determine the frequency */+#ifndef CONFIG_SOC_AU1000_FREQUENCY+#define CONFIG_SOC_AU1000_FREQUENCY 396000000+#endif+	if ((read_c0_prid() == 0x00030100) || /* Au1000 DA */+		(read_c0_prid() == 0x00030101) || /* Au1000 HA */+		(read_c0_prid() == 0x00030102))   /* Au1000 HB */+		cpu_freq = CONFIG_SOC_AU1000_FREQUENCY;+	else #endif+		cpu_freq = (au_readl(SYS_CPUPLL) & 0x0000003f) * CONFIG_AU1000_SRC_CLK;++	mips_hpt_frequency = cpu_freq; /* On Alchemy, Count is 1:1 CPU */+	/* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */+	set_au1x00_uart_baud_base(cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));+ 	set_au1x00_speed(cpu_freq);+ 	set_au1x00_lcd_clock(); /* program the LCD clock */++	spin_unlock_irqrestore(&time_lock, flags);++	return (cpu_freq / HZ);+}  void au1xxx_timer_setup(struct irqaction *irq) {-        unsigned int est_freq;-	extern unsigned long (*do_gettimeoffset)(void); 	extern void au1k_wait(void); -	printk("calculating r4koff... ");-	r4k_offset = cal_r4koff();-	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);+	/*	This code called at the end of time_init() in arch/mips/kernel/time.c.+	The Cp0 Counter has already been chosen as the timer source, here we+	can override the choices made by time_init(). */++#ifdef CONFIG_SOC_AU1X00_32KHZ_TIMER+	/* Setup the 32kHz oscillator as the kernel timer instead */+	if (au1xxx_32khz_startup()) {+		extern void hook_rtcm1_interrupt(void);++		/* it's too early to call request_irq(), but need to hook it anyway */+		setup_rtcm1_interrupt();+		hook_rtcm1_interrupt(); -	//est_freq = 2*r4k_offset*HZ;	-	est_freq = r4k_offset*HZ;	-	est_freq += 5000;    /* round */-	est_freq -= est_freq%10000;-	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, -	       (est_freq%1000000)*100/1000000);- 	set_au1x00_speed(est_freq);- 	set_au1x00_lcd_clock(); // program the LCD clock+		/* use 32khz flavor of do_fast_gettimeoffset() */+		do_gettimeoffset = do_fast_rtcm1_gettimeoffset; -	r4k_cur = (read_c0_count() + r4k_offset);-	write_c0_compare(r4k_cur);+		/* short-circuit CP0 Count timer handler */+		r4k_offset = 0; -#ifdef CONFIG_PM-	/*-	 * setup counter 0, since it keeps ticking after a-	 * 'wait' instruction has been executed. The CP0 timer and-	 * counter 1 do NOT continue running after 'wait'-	 *-	 * It's too early to call request_irq() here, so we handle-	 * counter 0 interrupt as a special irq and it doesn't show-	 * up under /proc/interrupts.-	 *-	 * Check to ensure we really have a 32KHz oscillator before-	 * we do this.-	 */-	if (no_au1xxx_32khz) {-		unsigned int c0_status;--		printk("WARNING: no 32KHz clock found.\n");-		do_gettimeoffset = do_fast_cp0_gettimeoffset;--		/* Ensure we get CPO_COUNTER interrupts.-		*/-		c0_status = read_c0_status();-		c0_status |= IE_IRQ5;-		write_c0_status(c0_status);+		/* allow WAIT instruction in cpu-probe.c */+		au1k_wait_ptr = au1k_wait; 	} 	else {-		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);-		au_writel(0, SYS_TOYWRITE);-		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);--		au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);-		au_writel(~0, SYS_WAKESRC);-		au_sync();-		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);--		/* setup match20 to interrupt once every 10ms */-		last_pc0 = last_match20 = au_readl(SYS_TOYREAD);-		au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);-		au_sync();-		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);-		startup_match20_interrupt();--		do_gettimeoffset = do_fast_pm_gettimeoffset;--		/* We can use the real 'wait' instruction.-		*/-		au1k_wait_ptr = au1k_wait;+		printk("WARNING: no 32KHz clock found...reverting to CP0 timer\n"); 	}- #else-	/* We have to do this here instead of in timer_init because-	 * the generic code in arch/mips/kernel/time.c will write-	 * over our function pointer.-	 */-	do_gettimeoffset = do_fast_cp0_gettimeoffset;-#endif+	/* Setup first CP0 timer interrupt */+	setup_cp0_interrupt();+#endif /* CONFIG_SOC_AU1X00_32KHZ_TIMER */+ }  void __init au1xxx_time_init(void) {+	/* This called at the start of time_init() in arch/mips/kernel/time.c */+	/* An RTC for use by time_init()/kernel is supposed to be setup here */++#ifdef CONFIG_SOC_AU1X00_32KHZ+	if (au1xxx_32khz_startup()) {+		/* set the kernel function pointers */+		rtc_get_time = rtc_au1xxx_get_time;+		rtc_set_time = rtc_au1xxx_set_time;+	}+#endif /* CONFIG_SOC_AU1X00_32KHZ */++	/* Determine CP0 timer values */+	printk("calculating r4koff... ");+	r4k_offset = cal_r4koff();+	printk("%08x(%d)\n", r4k_offset, (int) r4k_offset); }diff -Naur linux26-cvs/arch/mips/Kconfig _timer/arch/mips/Kconfig--- linux26-cvs/arch/mips/Kconfig	2005-05-18 11:27:54.000000000 -0500+++ _timer/arch/mips/Kconfig	2005-05-18 11:46:45.271794264 -0500@@ -34,6 +34,8 @@ 	select HW_HAS_PCI 	select SWAP_IO_SPACE 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_PB1100 	bool "AMD Alchemy PB1100 board"@@ -42,6 +44,8 @@ 	select HW_HAS_PCI 	select SWAP_IO_SPACE 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_PB1500 	bool "AMD Alchemy PB1500 board"@@ -49,6 +53,8 @@ 	select DMA_NONCOHERENT 	select HW_HAS_PCI 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_PB1550 	bool "AMD Alchemy PB1550 board"@@ -57,6 +63,8 @@ 	select HW_HAS_PCI 	select MIPS_DISABLE_OBSOLETE_IDE 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_PB1200 	bool "AMD Alchemy PB1200 board"@@ -65,6 +73,8 @@ 	select MIPS_DISABLE_OBSOLETE_IDE 	select SYS_SUPPORTS_LITTLE_ENDIAN 	select HW_HAS_PCI+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_DB1000 	bool "AMD Alchemy DB1000 board"@@ -72,12 +82,16 @@ 	select DMA_NONCOHERENT 	select HW_HAS_PCI 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_DB1100 	bool "AMD Alchemy DB1100 board" 	select SOC_AU1100 	select DMA_NONCOHERENT 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_DB1500 	bool "AMD Alchemy DB1500 board"@@ -86,6 +100,8 @@ 	select HW_HAS_PCI 	select MIPS_DISABLE_OBSOLETE_IDE 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_DB1550 	bool "AMD Alchemy DB1550 board"@@ -94,6 +110,8 @@ 	select DMA_NONCOHERENT 	select MIPS_DISABLE_OBSOLETE_IDE 	select SYS_SUPPORTS_LITTLE_ENDIAN+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_DB1200 	bool "AMD Alchemy DB1200 board"@@ -102,6 +120,8 @@ 	select MIPS_DISABLE_OBSOLETE_IDE 	select SYS_SUPPORTS_LITTLE_ENDIAN 	select HW_HAS_PCI+	select SOC_AU1X00_32KHZ+	select SOC_AU1X00_32KHZ_TIMER  config MIPS_MIRAGE 	bool "AMD Alchemy Mirage board"@@ -802,6 +822,13 @@ 	bool 	select SYS_SUPPORTS_32BIT_KERNEL +config SOC_AU1X00_32KHZ+	bool++config SOC_AU1X00_32KHZ_TIMER+	select SOC_AU1X00_32KHZ+	bool+ config SWAP_IO_SPACE 	bool diff -Naur -x CVS linux26-cvs/Documentation/Alchemy.README _timer/Documentation/Alchemy.README--- linux26-cvs/Documentation/Alchemy.README	1969-12-31 18:00:00.000000000 -0600+++ _timer/Documentation/Alchemy.README	2005-05-13 22:21:00.000000000 -0500@@ -0,0 +1,105 @@+README for arch/mips/au1000/common directory and subdirectories++Embedded Edge, Embedded Alley++MOTIVATION+----------++The Alchemy family of SOCs are very similarly architecturally, which+lends itself well to sharing a great deal of kernel code, and drivers.++The code in this directory is utilized by all Alchemy-based designs,+and is intended to be as board-independent as possible, but with the+appropriate SOC changes.++HOW TO CHOOSE THE KERNEL TIMER++	There can be three sources for the kernel timer tick with the Au1x00:+	- MIPS CP0 Count/Compare mechanism+	- Au1XXX RTC/TOY integrated timer+	- External timer+	The CP0 Counter operates at the frequency of the Au1 core; however,+	it does not count during the WAIT/Idle modes.++	The TOY/RTC operates from an optional 32kHz external oscillator; both+	count during the WAIT/Idle modes, but only the TOY continues to+	count during the Sleep mode of the Au1x00.++	The external timer could be anything, presumably connected via a GPIO.+	This might be used in systems where an external battery-backed clock+	source is required since early Au1x00 silicon drained the battery+	too quickly in Sleep mode. With an external timer source, the WAIT/Idle+	mode can be utilized.++	The different abilities of the timing sources lead to several possible+	configurations for building this time management code:++	1) Use CP0 Count/Compare as the ticker and source for real-time clock;+	   note this prevents the use of the WAIT instruction and its power savings.+	2) Use Cp0 Count/Compare as the ticker and RTC/TOY as the source for+	   the real-time clock (again, can not use the WAIT instruction).+	3) Use the TOY/RTC as the ticker source and also as the source for+	   the real-time clock. This mode permits the use of the WAIT+	   instruction and the Au1 core Idle modes for power savings.+	4) Use of an external timer as the ticker source, which also permits+	   the use of WAIT instruction and its power savings.++	The support for these scenarios is modularized as such:+	CONFIG_SOC_AU1X00_32KHZ is declared if the board populates a 32kHz+	oscillator. If so, it is assumed that the TOY/RTC will be used for+	the kernel's real-time clock, and thus will enable the appropriate+	code.++	CONFIG_SOC_AU1X00_32KHZ_TIMER is declared if the board is to utilize+	the TOY/RTC as the kernel timer tick. In the absence of this+	declaration, the kernel will assume the use of the MIPS CP0 Counter.++	If an external timer source is utilized, then arch/mips/au1000/common/+	time.c will need to	be examined and changed appropriately.++	When the TOY/RTC is used to source the real-time clock, it is the TOY+	that is used, not the RTC. While this is definitely possibly confusing,+	keep in mind that the TOY is able to count during Sleep modes, and so+	it makes sense to maintain the real-time clock in the TOY so that an+	alarm based on date/time configured in the TOY match 2 register can+	be utilized to awake the Au1x00 system from sleep state.++	Since the 32KHz crystal is not [typically] an integer multiple+	of HZ, there will be some drift associated with utilizing it+	as a timer tick source. Here's the scoop.+	1/32768 = 0.00003051s is 30.5microseconds per tick+	if HZ=100:+		trim is 32768/100 rounded UP = 328+		328 * 30.5us = 0.010004us+	So the periodic rate is extremely close to the desired 0.01,+	but it is not exact. Thus the drift is calculated as:+		0.01 / 0.000004 = 2500+	Which means that every 2500 timer intervals, the timer has+	drift one HZ. So we must account for that.+	if HZ=1000:+		trim is 32768/1000 rounded UP = 33+		33 * 30.5us = 0.0010065us+		0.001 / 0.0000065 = 153.8++	Also, in rtcm1_irq(), the code checks to make sure that the counter+	is not at the value we're about to program into the match; since it+	takes one counter tick for the update to occur. This can occur since+	Linux' interrupt response time is highly irregular, and so the RTC+	may already be near the next RTCM1 value by the time this handler+	is invoked. To do this, the code estimates how many RTC ticks will+	elapse by the time the update occurs, and figures this into the+	check. The check is complicated since the RTC can be ahead of RTCM1,+	and vice versa, and that can be valid, or not, depending upon whether+	or not RTC, or RTCM1, has rolled-over.++	See also Documentation/mips/time.README.++HOW TO ADD A BOARD+------------------++TBD++TO-DO LIST+----------++TBDdiff -Naur -x CVS linux26-cvs/include/asm-mips/mach-au1x00/au1000.h _timer/include/asm-mips/mach-au1x00/au1000.h--- linux26-cvs/include/asm-mips/mach-au1x00/au1000.h	2005-05-16 13:39:23.924915792 -0500+++ _timer/include/asm-mips/mach-au1x00/au1000.h	2005-05-13 22:20:15.000000000 -0500@@ -155,13 +155,6 @@  #endif /* !defined (_LANGUAGE_ASSEMBLY) */ -#ifdef CONFIG_PM-/* no CP0 timer irq */-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)-#else-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)-#endif- /*  * SDRAM Register Offsets  */@@ -1036,25 +1029,22 @@ /* Programmable Counters 0 and 1 */ #define SYS_BASE                   0xB1900000 #define SYS_COUNTER_CNTRL          (SYS_BASE + 0x14)-  #define SYS_CNTRL_E1S            (1<<23)-  #define SYS_CNTRL_T1S            (1<<20)-  #define SYS_CNTRL_M21            (1<<19)-  #define SYS_CNTRL_M11            (1<<18)-  #define SYS_CNTRL_M01            (1<<17)-  #define SYS_CNTRL_C1S            (1<<16)-  #define SYS_CNTRL_BP             (1<<14)-  #define SYS_CNTRL_EN1            (1<<13)-  #define SYS_CNTRL_BT1            (1<<12)-  #define SYS_CNTRL_EN0            (1<<11)-  #define SYS_CNTRL_BT0            (1<<10)-  #define SYS_CNTRL_E0             (1<<8)-  #define SYS_CNTRL_E0S            (1<<7)-  #define SYS_CNTRL_32S            (1<<5)-  #define SYS_CNTRL_T0S            (1<<4)-  #define SYS_CNTRL_M20            (1<<3)-  #define SYS_CNTRL_M10            (1<<2)-  #define SYS_CNTRL_M00            (1<<1)-  #define SYS_CNTRL_C0S            (1<<0)+#define SYS_CNTRCTRL_RTS	(1<<20)+#define SYS_CNTRCTRL_RM2	(1<<19)+#define SYS_CNTRCTRL_RM1	(1<<18)+#define SYS_CNTRCTRL_RM0	(1<<17)+#define SYS_CNTRCTRL_RS		(1<<16)+#define SYS_CNTRCTRL_BP		(1<<14)+#define SYS_CNTRCTRL_E0		(1<<8)+#define SYS_CNTRCTRL_CCS	(1<<7)+#define SYS_CNTRCTRL_32S	(1<<5)+#define SYS_CNTRCTRL_TTS	(1<<4)+#define SYS_CNTRCTRL_TM2	(1<<3)+#define SYS_CNTRCTRL_TM1	(1<<2)+#define SYS_CNTRCTRL_TM0	(1<<1)+#define SYS_CNTRCTRL_TS		(1<<0)++  /* Programmable Counter 0 Registers */ #define SYS_TOYTRIM                 (SYS_BASE + 0)@@ -1781,7 +1771,7 @@ #define PCI_IO_START    0 #define PCI_IO_END      0 #define PCI_MEM_START   0-#define PCI_MEM_END     0 +#define PCI_MEM_END     0 #define PCI_FIRST_DEVFN 0 #define PCI_LAST_DEVFN  0 

⌨️ 快捷键说明

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