3 #include <asm/arch/bits.h>
4 #include <asm/arch/regs_global.h>
5 #include <asm/arch/regs_ahb.h>
6 #include <linux/types.h>
8 /*************************************************
9 * determine the clock input, by the strap pin
10 * the strap bit shows the crytal input clock
14 * return value is frequency in Mhz, 26 or 13
15 * ***********************************************/
16 uint32_t get_input_clk(void)
19 reg_content = readl(GR_GEN1);
21 if(reg_content & GEN1_CLK_26MHZ_EN){
28 /****************************************************************
29 * calculate the greatest common divisor for two input integer
30 * the two input value should be non-zero integer
32 * return is the greatest common divisor
34 * *************************************************************/
35 uint32_t cal_g_divisor(uint32_t val_one, uint32_t val_two)
37 if(val_one == 0 || val_two == 0)
42 uint32_t big_val, sml_val;
44 if(val_one >= val_two) {
52 div = big_val%sml_val;
56 div = big_val%sml_val;
60 /*************************************************
61 * config pll, AHB, AMR,EMC clock
62 * the config value is get from board specific
65 * return is ahb clock for further configuration
66 * ************************************************/
67 uint32_t config_clk(void)
69 uint32_t input_clk, ahb_clk, pll_clk, ahb_div, arm_div, emc_div, xahb_div;
70 uint32_t pll_div_m, pll_div_n;
72 uint32_t great_divisor;
75 // get the input clock
76 input_clk = get_input_clk();
77 pll_clk = CONFIG_SYS_PLL_MHZ;
79 pll_clk = input_clk; // cpu run frequency should not below input clk
81 //calculate the divisor
82 great_divisor = cal_g_divisor(pll_clk, input_clk);
83 if(great_divisor <= 0)
86 pll_div_m = input_clk / great_divisor;
89 else if(pll_div_m > PLLMN_M_MAX)
90 pll_div_m = PLLMN_M_MAX;
92 pll_div_n = pll_clk / great_divisor;
93 if(pll_div_n > PLLMN_N_MAX){
94 pll_div_n = PLLMN_N_MAX;
95 pll_div_m = (input_clk * pll_div_n)/pll_clk;
96 }else if(pll_div_n <= 0)
99 reg_config = readl(GR_GEN1); //enable mpll write
100 reg_config |= GEN1_MPLLMN_WN;
101 writel(reg_config,GR_GEN1);
102 reg_config = (pll_div_m <<PLLMN_M_SHIFT) | (pll_div_n << PLLMN_N_SHIFT);
103 writel(reg_config, GR_MPLL_MN); //config mpll register
104 reg_config = readl(GR_GEN1); //disable mpll write
105 reg_config &= ~(GEN1_MPLLMN_WN);
106 writel(reg_config, GR_GEN1);
108 for(i = 0; i<100; i++);
110 ahb_div = CONFIG_SYS_AHB_DIV;
113 else if(ahb_div > AHB_CLK_DIV_MAX)
114 ahb_div = AHB_CLK_DIV_MAX;
116 arm_div = CONFIG_SYS_ARM_DIV;
119 else if (arm_div > ARM_CLK_DIV_MAX)
120 arm_div = ARM_CLK_DIV_MAX;
122 emc_div = CONFIG_SYS_EMC_DIV;
125 else if (emc_div > EMC_CLK_DIV_MAX)
126 emc_div = EMC_CLK_DIV_MAX;
128 xahb_div = ahb_div/arm_div;
130 //config AHB ARM CLK register
131 reg_config = ((ahb_div-1) << AHB_CLK_DIV_SHIFT) | ((arm_div-1) << ARM_CLK_DIV_SHIFT) | ((emc_div-1) << EMC_CLK_DIV_SHIFT) | ((xahb_div-1) << XAHB_CLK_DIV_SHIFT);
132 writel(reg_config, AHB_AHB_ARM_CLK);
135 for(i=0; i<100; i++);
137 ahb_clk = pll_clk/ahb_div;