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