| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * arch/ppc/syslib/ibm440gp_common.c | 
|  | 3 | * | 
|  | 4 | * PPC440GP system library | 
|  | 5 | * | 
|  | 6 | * Matt Porter <mporter@mvista.com> | 
|  | 7 | * Copyright 2002-2003 MontaVista Software Inc. | 
|  | 8 | * | 
|  | 9 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | 
|  | 10 | * Copyright (c) 2003 Zultys Technologies | 
|  | 11 | * | 
|  | 12 | * This program is free software; you can redistribute  it and/or modify it | 
|  | 13 | * under  the terms of  the GNU General  Public License as published by the | 
|  | 14 | * Free Software Foundation;  either version 2 of the  License, or (at your | 
|  | 15 | * option) any later version. | 
|  | 16 | * | 
|  | 17 | */ | 
|  | 18 | #include <linux/config.h> | 
|  | 19 | #include <linux/types.h> | 
|  | 20 | #include <asm/reg.h> | 
|  | 21 | #include <asm/ibm44x.h> | 
|  | 22 | #include <asm/mmu.h> | 
|  | 23 |  | 
|  | 24 | /* | 
|  | 25 | * Calculate 440GP clocks | 
|  | 26 | */ | 
|  | 27 | void __init ibm440gp_get_clocks(struct ibm44x_clocks* p, | 
|  | 28 | unsigned int sys_clk, | 
|  | 29 | unsigned int ser_clk) | 
|  | 30 | { | 
|  | 31 | u32 cpc0_sys0 = mfdcr(DCRN_CPC0_SYS0); | 
|  | 32 | u32 cpc0_cr0 = mfdcr(DCRN_CPC0_CR0); | 
|  | 33 | u32 opdv = ((cpc0_sys0 >> 10) & 0x3) + 1; | 
|  | 34 | u32 epdv = ((cpc0_sys0 >> 8) & 0x3) + 1; | 
|  | 35 |  | 
|  | 36 | if (cpc0_sys0 & 0x2){ | 
|  | 37 | /* Bypass system PLL */ | 
|  | 38 | p->cpu = p->plb = sys_clk; | 
|  | 39 | } | 
|  | 40 | else { | 
|  | 41 | u32 fbdv, fwdva, fwdvb, m, vco; | 
|  | 42 |  | 
|  | 43 | fbdv = (cpc0_sys0 >> 18) & 0x0f; | 
|  | 44 | if (!fbdv) | 
|  | 45 | fbdv = 16; | 
|  | 46 |  | 
|  | 47 | fwdva = 8 - ((cpc0_sys0 >> 15) & 0x7); | 
|  | 48 | fwdvb = 8 - ((cpc0_sys0 >> 12) & 0x7); | 
|  | 49 |  | 
|  | 50 | /* Feedback path */ | 
|  | 51 | if (cpc0_sys0 & 0x00000080){ | 
|  | 52 | /* PerClk */ | 
|  | 53 | m = fwdvb * opdv * epdv; | 
|  | 54 | } | 
|  | 55 | else { | 
|  | 56 | /* CPU clock */ | 
|  | 57 | m = fbdv * fwdva; | 
|  | 58 | } | 
|  | 59 | vco = sys_clk * m; | 
|  | 60 | p->cpu = vco / fwdva; | 
|  | 61 | p->plb = vco / fwdvb; | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | p->opb = p->plb / opdv; | 
|  | 65 | p->ebc = p->opb / epdv; | 
|  | 66 |  | 
|  | 67 | if (cpc0_cr0 & 0x00400000){ | 
|  | 68 | /* External UART clock */ | 
|  | 69 | p->uart0 = p->uart1 = ser_clk; | 
|  | 70 | } | 
|  | 71 | else { | 
|  | 72 | /* Internal UART clock */ | 
|  | 73 | u32 uart_div = ((cpc0_cr0 >> 16) & 0x1f) + 1; | 
|  | 74 | p->uart0 = p->uart1 = p->plb / uart_div; | 
|  | 75 | } | 
|  | 76 | } |