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