| /* | 
 |  * arch/ppc/syslib/ibm440gp_common.c | 
 |  * | 
 |  * PPC440GP system library | 
 |  * | 
 |  * Matt Porter <mporter@mvista.com> | 
 |  * Copyright 2002-2003 MontaVista Software Inc. | 
 |  * | 
 |  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | 
 |  * Copyright (c) 2003 Zultys Technologies | 
 |  * | 
 |  * This program is free software; you can redistribute  it and/or modify it | 
 |  * under  the terms of  the GNU General  Public License as published by the | 
 |  * Free Software Foundation;  either version 2 of the  License, or (at your | 
 |  * option) any later version. | 
 |  * | 
 |  */ | 
 | #include <linux/config.h> | 
 | #include <linux/types.h> | 
 | #include <asm/reg.h> | 
 | #include <asm/ibm44x.h> | 
 | #include <asm/mmu.h> | 
 |  | 
 | /* | 
 |  * Calculate 440GP clocks | 
 |  */ | 
 | void __init ibm440gp_get_clocks(struct ibm44x_clocks* p, | 
 | 				unsigned int sys_clk, | 
 | 				unsigned int ser_clk) | 
 | { | 
 | 	u32 cpc0_sys0 = mfdcr(DCRN_CPC0_SYS0); | 
 | 	u32 cpc0_cr0 = mfdcr(DCRN_CPC0_CR0); | 
 | 	u32 opdv = ((cpc0_sys0 >> 10) & 0x3) + 1; | 
 | 	u32 epdv = ((cpc0_sys0 >> 8) & 0x3) + 1; | 
 |  | 
 | 	if (cpc0_sys0 & 0x2){ | 
 | 		/* Bypass system PLL */ | 
 | 		p->cpu = p->plb = sys_clk; | 
 | 	} | 
 | 	else { | 
 | 		u32 fbdv, fwdva, fwdvb, m, vco; | 
 |  | 
 | 		fbdv = (cpc0_sys0 >> 18) & 0x0f; | 
 | 		if (!fbdv) | 
 | 			fbdv = 16; | 
 |  | 
 | 		fwdva = 8 - ((cpc0_sys0 >> 15) & 0x7); | 
 | 		fwdvb = 8 - ((cpc0_sys0 >> 12) & 0x7); | 
 |  | 
 |     		/* Feedback path */	 | 
 | 		if (cpc0_sys0 & 0x00000080){ | 
 | 			/* PerClk */ | 
 | 			m = fwdvb * opdv * epdv; | 
 | 		} | 
 | 		else { | 
 | 			/* CPU clock */ | 
 | 			m = fbdv * fwdva; | 
 |     		} | 
 | 		vco = sys_clk * m; | 
 | 		p->cpu = vco / fwdva; | 
 | 		p->plb = vco / fwdvb; | 
 | 	} | 
 |  | 
 | 	p->opb = p->plb / opdv; | 
 | 	p->ebc = p->opb / epdv; | 
 |  | 
 | 	if (cpc0_cr0 & 0x00400000){ | 
 | 		/* External UART clock */ | 
 | 		p->uart0 = p->uart1 = ser_clk; | 
 | 	} | 
 | 	else { | 
 | 		/* Internal UART clock */ | 
 |     		u32 uart_div = ((cpc0_cr0 >> 16) & 0x1f) + 1; | 
 | 		p->uart0 = p->uart1 = p->plb / uart_div; | 
 | 	} | 
 | } |