1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] 4 * 5 * Copyright (C) 2005 David Brownell 6 * Copyright (C) 2005 Ivan Kokshaysky 7 * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 8 */ 9 10 #include <common.h> 11 #include <asm/io.h> 12 #include <asm/arch/hardware.h> 13 #include <asm/arch/at91_pmc.h> 14 #include <asm/arch/clk.h> 15 16 #if !defined(CONFIG_AT91FAMILY) 17 # error You need to define CONFIG_AT91FAMILY in your board config! 18 #endif 19 20 #define EN_PLLB_TIMEOUT 500 21 22 DECLARE_GLOBAL_DATA_PTR; 23 24 static unsigned long at91_css_to_rate(unsigned long css) 25 { 26 switch (css) { 27 case AT91_PMC_MCKR_CSS_SLOW: 28 return CONFIG_SYS_AT91_SLOW_CLOCK; 29 case AT91_PMC_MCKR_CSS_MAIN: 30 return gd->arch.main_clk_rate_hz; 31 case AT91_PMC_MCKR_CSS_PLLA: 32 return gd->arch.plla_rate_hz; 33 case AT91_PMC_MCKR_CSS_PLLB: 34 return gd->arch.pllb_rate_hz; 35 } 36 37 return 0; 38 } 39 40 #ifdef CONFIG_USB_ATMEL 41 static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq) 42 { 43 unsigned i, div = 0, mul = 0, diff = 1 << 30; 44 unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00; 45 46 /* PLL output max 240 MHz (or 180 MHz per errata) */ 47 if (out_freq > 240000000) 48 goto fail; 49 50 for (i = 1; i < 256; i++) { 51 int diff1; 52 unsigned input, mul1; 53 54 /* 55 * PLL input between 1MHz and 32MHz per spec, but lower 56 * frequences seem necessary in some cases so allow 100K. 57 * Warning: some newer products need 2MHz min. 58 */ 59 input = main_freq / i; 60 #if defined(CONFIG_AT91SAM9G20) 61 if (input < 2000000) 62 continue; 63 #endif 64 if (input < 100000) 65 continue; 66 if (input > 32000000) 67 continue; 68 69 mul1 = out_freq / input; 70 #if defined(CONFIG_AT91SAM9G20) 71 if (mul > 63) 72 continue; 73 #endif 74 if (mul1 > 2048) 75 continue; 76 if (mul1 < 2) 77 goto fail; 78 79 diff1 = out_freq - input * mul1; 80 if (diff1 < 0) 81 diff1 = -diff1; 82 if (diff > diff1) { 83 diff = diff1; 84 div = i; 85 mul = mul1; 86 if (diff == 0) 87 break; 88 } 89 } 90 if (i == 256 && diff > (out_freq >> 5)) 91 goto fail; 92 return ret | ((mul - 1) << 16) | div; 93 fail: 94 return 0; 95 } 96 #endif 97 98 static u32 at91_pll_rate(u32 freq, u32 reg) 99 { 100 unsigned mul, div; 101 102 div = reg & 0xff; 103 mul = (reg >> 16) & 0x7ff; 104 if (div && mul) { 105 freq /= div; 106 freq *= mul + 1; 107 } else 108 freq = 0; 109 110 return freq; 111 } 112 113 int at91_clock_init(unsigned long main_clock) 114 { 115 unsigned freq, mckr; 116 at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; 117 #ifndef CONFIG_SYS_AT91_MAIN_CLOCK 118 unsigned tmp; 119 /* 120 * When the bootloader initialized the main oscillator correctly, 121 * there's no problem using the cycle counter. But if it didn't, 122 * or when using oscillator bypass mode, we must be told the speed 123 * of the main clock. 124 */ 125 if (!main_clock) { 126 do { 127 tmp = readl(&pmc->mcfr); 128 } while (!(tmp & AT91_PMC_MCFR_MAINRDY)); 129 tmp &= AT91_PMC_MCFR_MAINF_MASK; 130 main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); 131 } 132 #endif 133 gd->arch.main_clk_rate_hz = main_clock; 134 135 /* report if PLLA is more than mildly overclocked */ 136 gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); 137 138 #ifdef CONFIG_USB_ATMEL 139 /* 140 * USB clock init: choose 48 MHz PLLB value, 141 * disable 48MHz clock during usb peripheral suspend. 142 * 143 * REVISIT: assumes MCK doesn't derive from PLLB! 144 */ 145 gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | 146 AT91_PMC_PLLBR_USBDIV_2; 147 gd->arch.pllb_rate_hz = at91_pll_rate(main_clock, 148 gd->arch.at91_pllb_usb_init); 149 #endif 150 151 /* 152 * MCK and CPU derive from one of those primary clocks. 153 * For now, assume this parentage won't change. 154 */ 155 mckr = readl(&pmc->mckr); 156 #if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \ 157 || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5) 158 /* plla divisor by 2 */ 159 gd->arch.plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12)); 160 #endif 161 gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); 162 freq = gd->arch.mck_rate_hz; 163 164 #if defined(CONFIG_AT91SAM9X5) 165 /* different in prescale on at91sam9x5 */ 166 freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 4)); 167 #else 168 freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ 169 #endif 170 171 #if defined(CONFIG_AT91SAM9G20) 172 /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ 173 gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ? 174 freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq; 175 if (mckr & AT91_PMC_MCKR_MDIV_MASK) 176 freq /= 2; /* processor clock division */ 177 #elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) \ 178 || defined(CONFIG_AT91SAM9N12) || defined(CONFIG_AT91SAM9X5) 179 /* mdiv <==> divisor 180 * 0 <==> 1 181 * 1 <==> 2 182 * 2 <==> 4 183 * 3 <==> 3 184 */ 185 gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) == 186 (AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4) 187 ? freq / 3 188 : freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); 189 #else 190 gd->arch.mck_rate_hz = freq / 191 (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); 192 #endif 193 gd->arch.cpu_clk_rate_hz = freq; 194 195 return 0; 196 } 197 198 #if !defined(AT91_PLL_LOCK_TIMEOUT) 199 #define AT91_PLL_LOCK_TIMEOUT 1000000 200 #endif 201 202 void at91_plla_init(u32 pllar) 203 { 204 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 205 206 writel(pllar, &pmc->pllar); 207 while (!(readl(&pmc->sr) & AT91_PMC_LOCKA)) 208 ; 209 } 210 void at91_pllb_init(u32 pllbr) 211 { 212 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 213 214 writel(pllbr, &pmc->pllbr); 215 while (!(readl(&pmc->sr) & AT91_PMC_LOCKB)) 216 ; 217 } 218 219 void at91_mck_init(u32 mckr) 220 { 221 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 222 u32 tmp; 223 224 tmp = readl(&pmc->mckr); 225 tmp &= ~AT91_PMC_MCKR_PRES_MASK; 226 tmp |= mckr & AT91_PMC_MCKR_PRES_MASK; 227 writel(tmp, &pmc->mckr); 228 while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) 229 ; 230 231 tmp = readl(&pmc->mckr); 232 tmp &= ~AT91_PMC_MCKR_MDIV_MASK; 233 tmp |= mckr & AT91_PMC_MCKR_MDIV_MASK; 234 writel(tmp, &pmc->mckr); 235 while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) 236 ; 237 238 tmp = readl(&pmc->mckr); 239 tmp &= ~AT91_PMC_MCKR_PLLADIV_MASK; 240 tmp |= mckr & AT91_PMC_MCKR_PLLADIV_MASK; 241 writel(tmp, &pmc->mckr); 242 while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) 243 ; 244 245 tmp = readl(&pmc->mckr); 246 tmp &= ~AT91_PMC_MCKR_CSS_MASK; 247 tmp |= mckr & AT91_PMC_MCKR_CSS_MASK; 248 writel(tmp, &pmc->mckr); 249 while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) 250 ; 251 } 252 253 int at91_pllb_clk_enable(u32 pllbr) 254 { 255 struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; 256 ulong start_time, tmp_time; 257 258 start_time = get_timer(0); 259 writel(pllbr, &pmc->pllbr); 260 while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != AT91_PMC_LOCKB) { 261 tmp_time = get_timer(0); 262 if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) { 263 printf("ERROR: failed to enable PLLB\n"); 264 return -1; 265 } 266 } 267 268 return 0; 269 } 270 271 int at91_pllb_clk_disable(void) 272 { 273 struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; 274 ulong start_time, tmp_time; 275 276 start_time = get_timer(0); 277 writel(0, &pmc->pllbr); 278 while ((readl(&pmc->sr) & AT91_PMC_LOCKB) != 0) { 279 tmp_time = get_timer(0); 280 if ((tmp_time - start_time) > EN_PLLB_TIMEOUT) { 281 printf("ERROR: failed to disable PLLB\n"); 282 return -1; 283 } 284 } 285 286 return 0; 287 } 288