mirror of
				https://github.com/Stichting-MINIX-Research-Foundation/u-boot.git
				synced 2025-11-03 18:55:00 -05:00 
			
		
		
		
	Fix variable CPU clock for MPC859/866 systems for low CPU clocks
This commit is contained in:
		
							parent
							
								
									6876609446
								
							
						
					
					
						commit
						75d1ea7f6a
					
				@ -2,6 +2,8 @@
 | 
				
			|||||||
Changes since U-Boot 1.0.1:
 | 
					Changes since U-Boot 1.0.1:
 | 
				
			||||||
======================================================================
 | 
					======================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Fix variable CPU clock for MPC859/866 systems for low CPU clocks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Implement adaptive SDRAM timing configuration based on actual CPU
 | 
					* Implement adaptive SDRAM timing configuration based on actual CPU
 | 
				
			||||||
  clock frequency for INCA-IP; fix problem with board hanging when
 | 
					  clock frequency for INCA-IP; fix problem with board hanging when
 | 
				
			||||||
  switching from 150MHz to 100MHz
 | 
					  switching from 150MHz to 100MHz
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										18
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README
									
									
									
									
									
								
							@ -415,12 +415,28 @@ The following options need to be configured:
 | 
				
			|||||||
		Define exactly one of
 | 
							Define exactly one of
 | 
				
			||||||
		CONFIG_MPC8240, CONFIG_MPC8245
 | 
							CONFIG_MPC8240, CONFIG_MPC8245
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 8xx CPU Options: (if using an 8xx cpu)
 | 
					- 8xx CPU Options: (if using an MPC8xx cpu)
 | 
				
			||||||
		Define one or more of
 | 
							Define one or more of
 | 
				
			||||||
		CONFIG_8xx_GCLK_FREQ	- if get_gclk_freq() cannot work
 | 
							CONFIG_8xx_GCLK_FREQ	- if get_gclk_freq() cannot work
 | 
				
			||||||
					  e.g. if there is no 32KHz
 | 
										  e.g. if there is no 32KHz
 | 
				
			||||||
					  reference PIT/RTC clock
 | 
										  reference PIT/RTC clock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 859/866 CPU options: (if using a MPC859 or MPC866 CPU):
 | 
				
			||||||
 | 
							CFG_866_OSCCLK
 | 
				
			||||||
 | 
							CFG_866_CPUCLK_MIN
 | 
				
			||||||
 | 
							CFG_866_CPUCLK_MAX
 | 
				
			||||||
 | 
							CFG_866_CPUCLK_DEFAULT
 | 
				
			||||||
 | 
								See doc/README.MPC866
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CFG_MEASURE_CPUCLK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Define this to measure the actual CPU clock instead
 | 
				
			||||||
 | 
					                of relying on the correctness of the configured
 | 
				
			||||||
 | 
					                values. Mostly useful for board bringup to make sure
 | 
				
			||||||
 | 
					                the PLL is locked at the intended frequency. Note
 | 
				
			||||||
 | 
					                that this requires a (stable) reference clock (32 kHz
 | 
				
			||||||
 | 
					                RTC clock),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Linux Kernel Interface:
 | 
					- Linux Kernel Interface:
 | 
				
			||||||
		CONFIG_CLOCKS_IN_MHZ
 | 
							CONFIG_CLOCKS_IN_MHZ
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -128,14 +128,6 @@ int checkboard (void)
 | 
				
			|||||||
			break;
 | 
								break;
 | 
				
			||||||
		putc (*s);
 | 
							putc (*s);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#if defined(CFG_866_CPUCLK_MIN) && defined(CFG_866_CPUCLK_MAX)
 | 
					 | 
				
			||||||
	printf ("  [%d.%d...%d.%d MHz]",
 | 
					 | 
				
			||||||
		CFG_866_CPUCLK_MIN / 1000000,
 | 
					 | 
				
			||||||
		((CFG_866_CPUCLK_MIN % 1000000) + 50000) / 100000,
 | 
					 | 
				
			||||||
		CFG_866_CPUCLK_MAX / 1000000,
 | 
					 | 
				
			||||||
		((CFG_866_CPUCLK_MAX % 1000000) + 50000) / 100000
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	putc ('\n');
 | 
						putc ('\n');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
 | 
				
			|||||||
@ -123,10 +123,22 @@ static int check_CPU (long clock, uint pvr, uint immr)
 | 
				
			|||||||
	else
 | 
						else
 | 
				
			||||||
		printf ("unknown M%s (0x%08x)", id_str, k);
 | 
							printf ("unknown M%s (0x%08x)", id_str, k);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf (" at %s MHz:", strmhz (buf, clock));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf (" %u kB I-Cache", checkicache () >> 10);
 | 
					#if defined(CFG_866_CPUCLK_MIN) && defined(CFG_866_CPUCLK_MAX)
 | 
				
			||||||
	printf (" %u kB D-Cache", checkdcache () >> 10);
 | 
						printf (" at %s MHz [%d.%d...%d.%d MHz]\n       ",
 | 
				
			||||||
 | 
							strmhz (buf, clock),
 | 
				
			||||||
 | 
							CFG_866_CPUCLK_MIN / 1000000,
 | 
				
			||||||
 | 
							((CFG_866_CPUCLK_MIN % 1000000) + 50000) / 100000,
 | 
				
			||||||
 | 
							CFG_866_CPUCLK_MAX / 1000000,
 | 
				
			||||||
 | 
							((CFG_866_CPUCLK_MAX % 1000000) + 50000) / 100000
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						printf (" at %s MHz: ", strmhz (buf, clock));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						printf ("%u kB I-Cache %u kB D-Cache",
 | 
				
			||||||
 | 
							checkicache () >> 10,
 | 
				
			||||||
 | 
							checkdcache () >> 10
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* do we have a FEC (860T/P or 852/859/866)? */
 | 
						/* do we have a FEC (860T/P or 852/859/866)? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -71,11 +71,11 @@
 | 
				
			|||||||
static void serial_setdivisor(volatile cpm8xx_t *cp)
 | 
					static void serial_setdivisor(volatile cpm8xx_t *cp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	DECLARE_GLOBAL_DATA_PTR;
 | 
						DECLARE_GLOBAL_DATA_PTR;
 | 
				
			||||||
	int divisor=gd->cpu_clk/16/gd->baudrate;
 | 
						int divisor=(gd->cpu_clk + 8*gd->baudrate)/16/gd->baudrate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(divisor/16>0x1000) {
 | 
						if(divisor/16>0x1000) {
 | 
				
			||||||
		/* bad divisor, assume 50Mhz clock and 9600 baud */
 | 
							/* bad divisor, assume 50Mhz clock and 9600 baud */
 | 
				
			||||||
		divisor=(50*1000*1000)/16/9600;
 | 
							divisor=(50*1000*1000 + 8*9600)/16/9600;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CFG_BRGCLK_PRESCALE
 | 
					#ifdef CFG_BRGCLK_PRESCALE
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@
 | 
				
			|||||||
#include <mpc8xx.h>
 | 
					#include <mpc8xx.h>
 | 
				
			||||||
#include <asm/processor.h>
 | 
					#include <asm/processor.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef CONFIG_TQM866M
 | 
					#if !defined(CONFIG_TQM866M) || defined(CFG_MEASURE_CPUCLK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PITC_SHIFT 16
 | 
					#define PITC_SHIFT 16
 | 
				
			||||||
#define PITR_SHIFT 16
 | 
					#define PITR_SHIFT 16
 | 
				
			||||||
@ -170,6 +170,10 @@ unsigned long measure_gclk(void)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(CONFIG_TQM866M)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * get_clocks() fills in gd->cpu_clock depending on CONFIG_8xx_GCLK_FREQ
 | 
					 * get_clocks() fills in gd->cpu_clock depending on CONFIG_8xx_GCLK_FREQ
 | 
				
			||||||
 * or (if it is not defined) measure_gclk() (which uses the ref clock)
 | 
					 * or (if it is not defined) measure_gclk() (which uses the ref clock)
 | 
				
			||||||
@ -230,6 +234,9 @@ int get_clocks_866 (void)
 | 
				
			|||||||
		cpuclk = CFG_866_CPUCLK_DEFAULT;
 | 
							cpuclk = CFG_866_CPUCLK_DEFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gd->cpu_clk = init_pll_866 (cpuclk);
 | 
						gd->cpu_clk = init_pll_866 (cpuclk);
 | 
				
			||||||
 | 
					#if defined(CFG_MEASURE_CPUCLK)
 | 
				
			||||||
 | 
						gd->cpu_clk = measure_gclk ();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((immr->im_clkrst.car_sccr & SCCR_EBDF11) == 0)
 | 
						if ((immr->im_clkrst.car_sccr & SCCR_EBDF11) == 0)
 | 
				
			||||||
		gd->bus_clk = gd->cpu_clk;
 | 
							gd->bus_clk = gd->cpu_clk;
 | 
				
			||||||
@ -269,8 +276,19 @@ static long init_pll_866 (long clk)
 | 
				
			|||||||
	char              mfi, mfn, mfd, s, pdf;
 | 
						char              mfi, mfn, mfd, s, pdf;
 | 
				
			||||||
	long              step_mfi, step_mfn;
 | 
						long              step_mfi, step_mfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pdf = 0;
 | 
						if (clk < 20000000) {
 | 
				
			||||||
	if (clk < 80000000) {
 | 
							clk *= 2;
 | 
				
			||||||
 | 
							pdf = 1;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							pdf = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (clk < 40000000) {
 | 
				
			||||||
 | 
							s = 2;
 | 
				
			||||||
 | 
							step_mfi = CFG_866_OSCCLK / 4;
 | 
				
			||||||
 | 
							mfd = 7;
 | 
				
			||||||
 | 
							step_mfn = CFG_866_OSCCLK / 30;
 | 
				
			||||||
 | 
						} else if (clk < 80000000) {
 | 
				
			||||||
		s = 1;
 | 
							s = 1;
 | 
				
			||||||
		step_mfi = CFG_866_OSCCLK / 2;
 | 
							step_mfi = CFG_866_OSCCLK / 2;
 | 
				
			||||||
		mfd = 14;
 | 
							mfd = 14;
 | 
				
			||||||
@ -294,13 +312,14 @@ static long init_pll_866 (long clk)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Calculate effective clk
 | 
						/* Calculate effective clk
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	n = (mfi * step_mfi) + (mfn * step_mfn);
 | 
						n = ((mfi * step_mfi) + (mfn * step_mfn)) / (pdf + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
 | 
						immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	plprcr = (immr->im_clkrst.car_plprcr & ~(PLPRCR_MFN_MSK
 | 
						plprcr = (immr->im_clkrst.car_plprcr & ~(PLPRCR_MFN_MSK
 | 
				
			||||||
			| PLPRCR_MFD_MSK | PLPRCR_S_MSK
 | 
								| PLPRCR_MFD_MSK | PLPRCR_S_MSK
 | 
				
			||||||
			| PLPRCR_MFI_MSK | PLPRCR_DBRMO))
 | 
								| PLPRCR_MFI_MSK | PLPRCR_DBRMO
 | 
				
			||||||
 | 
								| PLPRCR_PDF_MSK))
 | 
				
			||||||
			| (mfn << PLPRCR_MFN_SHIFT)
 | 
								| (mfn << PLPRCR_MFN_SHIFT)
 | 
				
			||||||
			| (mfd << PLPRCR_MFD_SHIFT)
 | 
								| (mfd << PLPRCR_MFD_SHIFT)
 | 
				
			||||||
			| (s << PLPRCR_S_SHIFT)
 | 
								| (s << PLPRCR_S_SHIFT)
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,10 @@ If the "cpuclk" environment variable value is within the CPUCLK_MIN /
 | 
				
			|||||||
CPUCLK_MAX limits, the specified value is used. Otherwise, the
 | 
					CPUCLK_MAX limits, the specified value is used. Otherwise, the
 | 
				
			||||||
default CPU clock value is set.
 | 
					default CPU clock value is set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please make sure you understand what you are doing, and understand
 | 
				
			||||||
 | 
					the restrictions of your hardware (board, processor). For example,
 | 
				
			||||||
 | 
					ethernet will stop working for CPU clock frequencies below 25 MHz.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Please note that for now the new clock-handling code has been enabled
 | 
					Please note that for now the new clock-handling code has been enabled
 | 
				
			||||||
for the TQM866M board only, even though it should be pretty much
 | 
					for the TQM866M board only, even though it should be pretty much
 | 
				
			||||||
common for other MPC859 / MPC866 based boards also. Our intention
 | 
					common for other MPC859 / MPC866 based boards also. Our intention
 | 
				
			||||||
 | 
				
			|||||||
@ -37,12 +37,19 @@
 | 
				
			|||||||
#define CONFIG_TQM866M		1	/* ...on a TQM8xxM module	*/
 | 
					#define CONFIG_TQM866M		1	/* ...on a TQM8xxM module	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CFG_866_OSCCLK		 10000000	/*  10 MHz - PLL input clock		*/
 | 
					#define CFG_866_OSCCLK		 10000000	/*  10 MHz - PLL input clock		*/
 | 
				
			||||||
#define CFG_866_CPUCLK_MIN	 10000000	/*  10 MHz - CPU minimum clock		*/
 | 
					#define CFG_866_CPUCLK_MIN	 15000000	/*  15 MHz - CPU minimum clock		*/
 | 
				
			||||||
#define CFG_866_CPUCLK_MAX	133000000	/* 133 MHz - CPU maximum clock		*/
 | 
					#define CFG_866_CPUCLK_MAX	133000000	/* 133 MHz - CPU maximum clock		*/
 | 
				
			||||||
#define CFG_866_CPUCLK_DEFAULT	 50000000	/*  50 MHz - CPU default clock		*/
 | 
					#define CFG_866_CPUCLK_DEFAULT	 50000000	/*  50 MHz - CPU default clock		*/
 | 
				
			||||||
						/* (it will be used if there is no	*/
 | 
											/* (it will be used if there is no	*/
 | 
				
			||||||
						/* 'cpuclk' variable with valid value)	*/
 | 
											/* 'cpuclk' variable with valid value)	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef CFG_MEASURE_CPUCLK			/* Measure real cpu clock	*/
 | 
				
			||||||
 | 
											/* (function measure_gclk()	*/
 | 
				
			||||||
 | 
											/* will be called)		*/
 | 
				
			||||||
 | 
					#ifdef CFG_MEASURE_CPUCLK
 | 
				
			||||||
 | 
					#define CFG_8XX_XIN		10000000	/* measure_gclk() needs this	*/
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONFIG_8xx_CONS_SMC1	1	/* Console is on SMC1		*/
 | 
					#define CONFIG_8xx_CONS_SMC1	1	/* Console is on SMC1		*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONFIG_BAUDRATE		115200	/* console baudrate = 115kbps	*/
 | 
					#define CONFIG_BAUDRATE		115200	/* console baudrate = 115kbps	*/
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user