diff options
| -rw-r--r-- | cpu/ppc4xx/cpu_init.c | 69 | ||||
| -rw-r--r-- | include/ppc440.h | 7 | ||||
| -rw-r--r-- | include/ppc4xx.h | 2 | 
3 files changed, 77 insertions, 1 deletions
diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index a00da408c..ccd999367 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -330,3 +330,72 @@ int cpu_init_r (void)  	return 0;  } + +#if defined(CONFIG_PCI) && \ +	(defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ +	 defined(CONFIG_440GR) || defined(CONFIG_440GRX)) +/* + * 440EP(x)/GR(x) PCI async/sync clocking restriction: + * + * In asynchronous PCI mode, the synchronous PCI clock must meet + * certain requirements. The following equation describes the + * relationship that must be maintained between the asynchronous PCI + * clock and synchronous PCI clock. Select an appropriate PCI:PLB + * ratio to maintain the relationship: + * + * AsyncPCIClk - 1MHz <= SyncPCIclock <= (2 * AsyncPCIClk) - 1MHz + */ +static int ppc4xx_pci_sync_clock_ok(u32 sync, u32 async) +{ +	if (((async - 1000000) > sync) || (sync > ((2 * async) - 1000000))) +		return 0; +	else +		return 1; +} + +int ppc4xx_pci_sync_clock_config(u32 async) +{ +	sys_info_t sys_info; +	u32 sync; +	int div; +	u32 reg; +	u32 spcid_val[] = { +		CPR0_SPCID_SPCIDV0_DIV1, CPR0_SPCID_SPCIDV0_DIV2, +		CPR0_SPCID_SPCIDV0_DIV3, CPR0_SPCID_SPCIDV0_DIV4 }; + +	get_sys_info(&sys_info); +	sync = sys_info.freqPCI; + +	/* +	 * First check if the equation above is met +	 */ +	if (!ppc4xx_pci_sync_clock_ok(sync, async)) { +		/* +		 * Reconfigure PCI sync clock to meet the equation. +		 * Start with highest possible PCI sync frequency +		 * (divider 1). +		 */ +		for (div = 1; div <= 4; div++) { +			sync = sys_info.freqPLB / div; +			if (ppc4xx_pci_sync_clock_ok(sync, async)) +			    break; +		} + +		if (div <= 4) { +			mtcpr(CPR0_SPCID, spcid_val[div]); + +			mfcpr(CPR0_ICFG, reg); +			reg |= CPR0_ICFG_RLI_MASK; +			mtcpr(CPR0_ICFG, reg); + +			/* do chip reset */ +			mtspr(SPRN_DBCR0, 0x20000000); +		} else { +			/* Impossible to configure the PCI sync clock */ +			return -1; +		} +	} + +	return 0; +} +#endif diff --git a/include/ppc440.h b/include/ppc440.h index fe0db93b5..e54a977dc 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -1701,9 +1701,14 @@  #define PLLSYS1_NTO1_MASK	0x00000001	/* CPU:PLB N-to-1 ratio */  #endif /* CONFIG_440GX */ -#if defined (CONFIG_440EPX) || defined (CONFIG_440GRX) +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)  #define CPR0_ICFG_RLI_MASK	0x80000000  #define CPR0_SPCID_SPCIDV0_MASK	0x03000000 +#define CPR0_SPCID_SPCIDV0_DIV1	0x01000000 +#define CPR0_SPCID_SPCIDV0_DIV2	0x02000000 +#define CPR0_SPCID_SPCIDV0_DIV3	0x03000000 +#define CPR0_SPCID_SPCIDV0_DIV4	0x00000000  #define CPR0_PERD_PERDV0_MASK	0x07000000  #endif diff --git a/include/ppc4xx.h b/include/ppc4xx.h index 3bff00a55..5024db447 100644 --- a/include/ppc4xx.h +++ b/include/ppc4xx.h @@ -221,6 +221,8 @@ static inline void set_mcsr(u32 val)  	asm volatile("mtspr 0x23c, %0" : "=r" (val) :);  } +int ppc4xx_pci_sync_clock_config(u32 async); +  #endif	/* __ASSEMBLY__ */  /* for multi-cpu support */  |