uboot/arch/arm/cpu/arm920t/at91/clock.c
<<
>>
Prefs
   1/*
   2 * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c]
   3 *
   4 * Copyright (C) 2011 Andreas Bießmann
   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 * SPDX-License-Identifier:     GPL-2.0+
  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
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23static unsigned long at91_css_to_rate(unsigned long css)
  24{
  25        switch (css) {
  26        case AT91_PMC_MCKR_CSS_SLOW:
  27                return CONFIG_SYS_AT91_SLOW_CLOCK;
  28        case AT91_PMC_MCKR_CSS_MAIN:
  29                return gd->arch.main_clk_rate_hz;
  30        case AT91_PMC_MCKR_CSS_PLLA:
  31                return gd->arch.plla_rate_hz;
  32        case AT91_PMC_MCKR_CSS_PLLB:
  33                return gd->arch.pllb_rate_hz;
  34        }
  35
  36        return 0;
  37}
  38
  39#ifdef CONFIG_USB_ATMEL
  40static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq)
  41{
  42        unsigned i, div = 0, mul = 0, diff = 1 << 30;
  43        unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
  44
  45        /* PLL output max 240 MHz (or 180 MHz per errata) */
  46        if (out_freq > 240000000)
  47                goto fail;
  48
  49        for (i = 1; i < 256; i++) {
  50                int diff1;
  51                unsigned input, mul1;
  52
  53                /*
  54                 * PLL input between 1MHz and 32MHz per spec, but lower
  55                 * frequences seem necessary in some cases so allow 100K.
  56                 * Warning: some newer products need 2MHz min.
  57                 */
  58                input = main_freq / i;
  59                if (input < 100000)
  60                        continue;
  61                if (input > 32000000)
  62                        continue;
  63
  64                mul1 = out_freq / input;
  65                if (mul1 > 2048)
  66                        continue;
  67                if (mul1 < 2)
  68                        goto fail;
  69
  70                diff1 = out_freq - input * mul1;
  71                if (diff1 < 0)
  72                        diff1 = -diff1;
  73                if (diff > diff1) {
  74                        diff = diff1;
  75                        div = i;
  76                        mul = mul1;
  77                        if (diff == 0)
  78                                break;
  79                }
  80        }
  81        if (i == 256 && diff > (out_freq >> 5))
  82                goto fail;
  83        return ret | ((mul - 1) << 16) | div;
  84fail:
  85        return 0;
  86}
  87#endif
  88
  89static u32 at91_pll_rate(u32 freq, u32 reg)
  90{
  91        unsigned mul, div;
  92
  93        div = reg & 0xff;
  94        mul = (reg >> 16) & 0x7ff;
  95        if (div && mul) {
  96                freq /= div;
  97                freq *= mul + 1;
  98        } else
  99                freq = 0;
 100
 101        return freq;
 102}
 103
 104int at91_clock_init(unsigned long main_clock)
 105{
 106        unsigned freq, mckr;
 107        at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC;
 108#ifndef CONFIG_SYS_AT91_MAIN_CLOCK
 109        unsigned tmp;
 110        /*
 111         * When the bootloader initialized the main oscillator correctly,
 112         * there's no problem using the cycle counter.  But if it didn't,
 113         * or when using oscillator bypass mode, we must be told the speed
 114         * of the main clock.
 115         */
 116        if (!main_clock) {
 117                do {
 118                        tmp = readl(&pmc->mcfr);
 119                } while (!(tmp & AT91_PMC_MCFR_MAINRDY));
 120                tmp &= AT91_PMC_MCFR_MAINF_MASK;
 121                main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16);
 122        }
 123#endif
 124        gd->arch.main_clk_rate_hz = main_clock;
 125
 126        /* report if PLLA is more than mildly overclocked */
 127        gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar));
 128
 129#ifdef CONFIG_USB_ATMEL
 130        /*
 131         * USB clock init:  choose 48 MHz PLLB value,
 132         * disable 48MHz clock during usb peripheral suspend.
 133         *
 134         * REVISIT:  assumes MCK doesn't derive from PLLB!
 135         */
 136        gd->arch.at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) |
 137                             AT91_PMC_PLLBR_USBDIV_2;
 138        gd->arch.pllb_rate_hz = at91_pll_rate(main_clock,
 139                                              gd->arch.at91_pllb_usb_init);
 140#endif
 141
 142        /*
 143         * MCK and CPU derive from one of those primary clocks.
 144         * For now, assume this parentage won't change.
 145         */
 146        mckr = readl(&pmc->mckr);
 147        gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK);
 148        freq = gd->arch.mck_rate_hz;
 149
 150        freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */
 151        /* mdiv */
 152        gd->arch.mck_rate_hz = freq /
 153                        (1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8));
 154        gd->arch.cpu_clk_rate_hz = freq;
 155
 156        return 0;
 157}
 158