uboot/arch/m68k/cpu/mcf5227x/speed.c
<<
>>
Prefs
   1/*
   2 *
   3 * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
   4 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25#include <common.h>
  26#include <asm/processor.h>
  27
  28#include <asm/immap.h>
  29
  30DECLARE_GLOBAL_DATA_PTR;
  31
  32/*
  33 * Low Power Divider specifications
  34 */
  35#define CLOCK_LPD_MIN           (1 << 0)        /* Divider (decoded) */
  36#define CLOCK_LPD_MAX           (1 << 15)       /* Divider (decoded) */
  37
  38#define CLOCK_PLL_FVCO_MAX      540000000
  39#define CLOCK_PLL_FVCO_MIN      300000000
  40
  41#define CLOCK_PLL_FSYS_MAX      266666666
  42#define CLOCK_PLL_FSYS_MIN      100000000
  43#define MHZ                     1000000
  44
  45void clock_enter_limp(int lpdiv)
  46{
  47        volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;
  48        int i, j;
  49
  50        /* Check bounds of divider */
  51        if (lpdiv < CLOCK_LPD_MIN)
  52                lpdiv = CLOCK_LPD_MIN;
  53        if (lpdiv > CLOCK_LPD_MAX)
  54                lpdiv = CLOCK_LPD_MAX;
  55
  56        /* Round divider down to nearest power of two */
  57        for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ;
  58
  59        /* Apply the divider to the system clock */
  60        ccm->cdr = (ccm->cdr & 0xF0FF) | CCM_CDR_LPDIV(i);
  61
  62        /* Enable Limp Mode */
  63        ccm->misccr |= CCM_MISCCR_LIMP;
  64}
  65
  66/*
  67 * brief   Exit Limp mode
  68 * warning The PLL should be set and locked prior to exiting Limp mode
  69 */
  70void clock_exit_limp(void)
  71{
  72        volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;
  73        volatile pll_t *pll = (volatile pll_t *)MMAP_PLL;
  74
  75        /* Exit Limp mode */
  76        ccm->misccr &= ~CCM_MISCCR_LIMP;
  77
  78        /* Wait for the PLL to lock */
  79        while (!(pll->psr & PLL_PSR_LOCK)) ;
  80}
  81
  82/*
  83 * get_clocks() fills in gd->cpu_clock and gd->bus_clk
  84 */
  85int get_clocks(void)
  86{
  87
  88        volatile ccm_t *ccm = (volatile ccm_t *)MMAP_CCM;
  89        volatile pll_t *pll = (volatile pll_t *)MMAP_PLL;
  90        int vco, temp, pcrvalue, pfdr;
  91        u8 bootmode;
  92
  93        pcrvalue = pll->pcr & 0xFF0F0FFF;
  94        pfdr = pcrvalue >> 24;
  95
  96        if (pfdr == 0x1E)
  97                bootmode = 0;   /* Normal Mode */
  98
  99#ifdef CONFIG_CF_SBF
 100        bootmode = 3;           /* Serial Mode */
 101#endif
 102
 103        if (bootmode == 0) {
 104                /* Normal mode */
 105                vco = ((pll->pcr & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC;
 106                if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {
 107                        /* Default value */
 108                        pcrvalue = (pll->pcr & 0x00FFFFFF);
 109                        pcrvalue |= 0x1E << 24;
 110                        pll->pcr = pcrvalue;
 111                        vco =
 112                            ((pll->pcr & 0xFF000000) >> 24) *
 113                            CONFIG_SYS_INPUT_CLKSRC;
 114                }
 115                gd->vco_clk = vco;      /* Vco clock */
 116        } else if (bootmode == 3) {
 117                /* serial mode */
 118                vco = ((pll->pcr & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC;
 119                gd->vco_clk = vco;      /* Vco clock */
 120        }
 121
 122        if ((ccm->ccr & CCM_MISCCR_LIMP) == CCM_MISCCR_LIMP) {
 123                /* Limp mode */
 124        } else {
 125                gd->inp_clk = CONFIG_SYS_INPUT_CLKSRC;  /* Input clock */
 126
 127                temp = (pll->pcr & PLL_PCR_OUTDIV1_MASK) + 1;
 128                gd->cpu_clk = vco / temp;       /* cpu clock */
 129
 130                temp = ((pll->pcr & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;
 131                gd->flb_clk = vco / temp;       /* flexbus clock */
 132                gd->bus_clk = gd->flb_clk;
 133        }
 134
 135#ifdef CONFIG_FSL_I2C
 136        gd->i2c1_clk = gd->bus_clk;
 137#endif
 138
 139        return (0);
 140}
 141