From 5e47f9535f53fd4cc05f32fb6166870f976fbb4e Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 19 Oct 2009 14:06:23 +0200 Subject: ppc4xx: Add function to check and dynamically change PCI sync clock PPC440EP(x)/PPC440GR(x): 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 This patch now adds a function to check and reconfigure the sync PCI clock to meet this requirement. This is in preparation for some AMCC boards (Sequoia/Rainier and Yosemite/Yellowstone) using this function to not violate the PCI clocking rules. Signed-off-by: Stefan Roese --- cpu/ppc4xx/cpu_init.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'cpu') diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index a00da408c9..ccd9993677 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 -- cgit v1.2.3