linux/arch/m68k/platform/coldfire/m53xx.c
<<
>>
Prefs
   1/***************************************************************************/
   2
   3/*
   4 *      m53xx.c -- platform support for ColdFire 53xx based boards
   5 *
   6 *      Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
   7 *      Copyright (C) 2000, Lineo (www.lineo.com)
   8 *      Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
   9 *      Copyright Freescale Semiconductor, Inc 2006
  10 *      Copyright (c) 2006, emlix, Sebastian Hess <shess@hessware.de>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 */
  17
  18/***************************************************************************/
  19
  20#include <linux/kernel.h>
  21#include <linux/param.h>
  22#include <linux/init.h>
  23#include <linux/io.h>
  24#include <asm/machdep.h>
  25#include <asm/coldfire.h>
  26#include <asm/mcfsim.h>
  27#include <asm/mcfuart.h>
  28#include <asm/mcfdma.h>
  29#include <asm/mcfwdebug.h>
  30#include <asm/mcfclk.h>
  31
  32/***************************************************************************/
  33
  34DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
  35DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
  36DEFINE_CLK(0, "fec.0", 12, MCF_CLK);
  37DEFINE_CLK(0, "edma", 17, MCF_CLK);
  38DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
  39DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
  40DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
  41DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
  42DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
  43DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
  44DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
  45DEFINE_CLK(0, "mcfuart.2", 26, MCF_BUSCLK);
  46DEFINE_CLK(0, "mcftmr.0", 28, MCF_CLK);
  47DEFINE_CLK(0, "mcftmr.1", 29, MCF_CLK);
  48DEFINE_CLK(0, "mcftmr.2", 30, MCF_CLK);
  49DEFINE_CLK(0, "mcftmr.3", 31, MCF_CLK);
  50
  51DEFINE_CLK(0, "mcfpit.0", 32, MCF_CLK);
  52DEFINE_CLK(0, "mcfpit.1", 33, MCF_CLK);
  53DEFINE_CLK(0, "mcfpit.2", 34, MCF_CLK);
  54DEFINE_CLK(0, "mcfpit.3", 35, MCF_CLK);
  55DEFINE_CLK(0, "mcfpwm.0", 36, MCF_CLK);
  56DEFINE_CLK(0, "mcfeport.0", 37, MCF_CLK);
  57DEFINE_CLK(0, "mcfwdt.0", 38, MCF_CLK);
  58DEFINE_CLK(0, "sys.0", 40, MCF_BUSCLK);
  59DEFINE_CLK(0, "gpio.0", 41, MCF_BUSCLK);
  60DEFINE_CLK(0, "mcfrtc.0", 42, MCF_CLK);
  61DEFINE_CLK(0, "mcflcd.0", 43, MCF_CLK);
  62DEFINE_CLK(0, "mcfusb-otg.0", 44, MCF_CLK);
  63DEFINE_CLK(0, "mcfusb-host.0", 45, MCF_CLK);
  64DEFINE_CLK(0, "sdram.0", 46, MCF_CLK);
  65DEFINE_CLK(0, "ssi.0", 47, MCF_CLK);
  66DEFINE_CLK(0, "pll.0", 48, MCF_CLK);
  67
  68DEFINE_CLK(1, "mdha.0", 32, MCF_CLK);
  69DEFINE_CLK(1, "skha.0", 33, MCF_CLK);
  70DEFINE_CLK(1, "rng.0", 34, MCF_CLK);
  71
  72struct clk *mcf_clks[] = {
  73        &__clk_0_2,     /* flexbus */
  74        &__clk_0_8,     /* mcfcan.0 */
  75        &__clk_0_12,    /* fec.0 */
  76        &__clk_0_17,    /* edma */
  77        &__clk_0_18,    /* intc.0 */
  78        &__clk_0_19,    /* intc.1 */
  79        &__clk_0_21,    /* iack.0 */
  80        &__clk_0_22,    /* mcfi2c.0 */
  81        &__clk_0_23,    /* mcfqspi.0 */
  82        &__clk_0_24,    /* mcfuart.0 */
  83        &__clk_0_25,    /* mcfuart.1 */
  84        &__clk_0_26,    /* mcfuart.2 */
  85        &__clk_0_28,    /* mcftmr.0 */
  86        &__clk_0_29,    /* mcftmr.1 */
  87        &__clk_0_30,    /* mcftmr.2 */
  88        &__clk_0_31,    /* mcftmr.3 */
  89
  90        &__clk_0_32,    /* mcfpit.0 */
  91        &__clk_0_33,    /* mcfpit.1 */
  92        &__clk_0_34,    /* mcfpit.2 */
  93        &__clk_0_35,    /* mcfpit.3 */
  94        &__clk_0_36,    /* mcfpwm.0 */
  95        &__clk_0_37,    /* mcfeport.0 */
  96        &__clk_0_38,    /* mcfwdt.0 */
  97        &__clk_0_40,    /* sys.0 */
  98        &__clk_0_41,    /* gpio.0 */
  99        &__clk_0_42,    /* mcfrtc.0 */
 100        &__clk_0_43,    /* mcflcd.0 */
 101        &__clk_0_44,    /* mcfusb-otg.0 */
 102        &__clk_0_45,    /* mcfusb-host.0 */
 103        &__clk_0_46,    /* sdram.0 */
 104        &__clk_0_47,    /* ssi.0 */
 105        &__clk_0_48,    /* pll.0 */
 106
 107        &__clk_1_32,    /* mdha.0 */
 108        &__clk_1_33,    /* skha.0 */
 109        &__clk_1_34,    /* rng.0 */
 110        NULL,
 111};
 112
 113static struct clk * const enable_clks[] __initconst = {
 114        &__clk_0_2,     /* flexbus */
 115        &__clk_0_18,    /* intc.0 */
 116        &__clk_0_19,    /* intc.1 */
 117        &__clk_0_21,    /* iack.0 */
 118        &__clk_0_24,    /* mcfuart.0 */
 119        &__clk_0_25,    /* mcfuart.1 */
 120        &__clk_0_26,    /* mcfuart.2 */
 121        &__clk_0_28,    /* mcftmr.0 */
 122        &__clk_0_29,    /* mcftmr.1 */
 123        &__clk_0_32,    /* mcfpit.0 */
 124        &__clk_0_33,    /* mcfpit.1 */
 125        &__clk_0_37,    /* mcfeport.0 */
 126        &__clk_0_40,    /* sys.0 */
 127        &__clk_0_41,    /* gpio.0 */
 128        &__clk_0_46,    /* sdram.0 */
 129        &__clk_0_48,    /* pll.0 */
 130};
 131
 132static struct clk * const disable_clks[] __initconst = {
 133        &__clk_0_8,     /* mcfcan.0 */
 134        &__clk_0_12,    /* fec.0 */
 135        &__clk_0_17,    /* edma */
 136        &__clk_0_22,    /* mcfi2c.0 */
 137        &__clk_0_23,    /* mcfqspi.0 */
 138        &__clk_0_30,    /* mcftmr.2 */
 139        &__clk_0_31,    /* mcftmr.3 */
 140        &__clk_0_34,    /* mcfpit.2 */
 141        &__clk_0_35,    /* mcfpit.3 */
 142        &__clk_0_36,    /* mcfpwm.0 */
 143        &__clk_0_38,    /* mcfwdt.0 */
 144        &__clk_0_42,    /* mcfrtc.0 */
 145        &__clk_0_43,    /* mcflcd.0 */
 146        &__clk_0_44,    /* mcfusb-otg.0 */
 147        &__clk_0_45,    /* mcfusb-host.0 */
 148        &__clk_0_47,    /* ssi.0 */
 149        &__clk_1_32,    /* mdha.0 */
 150        &__clk_1_33,    /* skha.0 */
 151        &__clk_1_34,    /* rng.0 */
 152};
 153
 154
 155static void __init m53xx_clk_init(void)
 156{
 157        unsigned i;
 158
 159        /* make sure these clocks are enabled */
 160        for (i = 0; i < ARRAY_SIZE(enable_clks); ++i)
 161                __clk_init_enabled(enable_clks[i]);
 162        /* make sure these clocks are disabled */
 163        for (i = 0; i < ARRAY_SIZE(disable_clks); ++i)
 164                __clk_init_disabled(disable_clks[i]);
 165}
 166
 167/***************************************************************************/
 168
 169#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
 170
 171static void __init m53xx_qspi_init(void)
 172{
 173        /* setup QSPS pins for QSPI with gpio CS control */
 174        writew(0x01f0, MCFGPIO_PAR_QSPI);
 175}
 176
 177#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
 178
 179/***************************************************************************/
 180
 181static void __init m53xx_uarts_init(void)
 182{
 183        /* UART GPIO initialization */
 184        writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART);
 185}
 186
 187/***************************************************************************/
 188
 189static void __init m53xx_fec_init(void)
 190{
 191        u8 v;
 192
 193        /* Set multi-function pins to ethernet mode for fec0 */
 194        v = readb(MCFGPIO_PAR_FECI2C);
 195        v |= MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
 196                MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO;
 197        writeb(v, MCFGPIO_PAR_FECI2C);
 198
 199        v = readb(MCFGPIO_PAR_FEC);
 200        v = MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC;
 201        writeb(v, MCFGPIO_PAR_FEC);
 202}
 203
 204/***************************************************************************/
 205
 206void __init config_BSP(char *commandp, int size)
 207{
 208#if !defined(CONFIG_BOOTPARAM)
 209        /* Copy command line from FLASH to local buffer... */
 210        memcpy(commandp, (char *) 0x4000, 4);
 211        if(strncmp(commandp, "kcl ", 4) == 0){
 212                memcpy(commandp, (char *) 0x4004, size);
 213                commandp[size-1] = 0;
 214        } else {
 215                memset(commandp, 0, size);
 216        }
 217#endif
 218        mach_sched_init = hw_timer_init;
 219        m53xx_clk_init();
 220        m53xx_uarts_init();
 221        m53xx_fec_init();
 222#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
 223        m53xx_qspi_init();
 224#endif
 225
 226#ifdef CONFIG_BDM_DISABLE
 227        /*
 228         * Disable the BDM clocking.  This also turns off most of the rest of
 229         * the BDM device.  This is good for EMC reasons. This option is not
 230         * incompatible with the memory protection option.
 231         */
 232        wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
 233#endif
 234}
 235
 236/***************************************************************************/
 237/* Board initialization */
 238/***************************************************************************/
 239/* 
 240 * PLL min/max specifications
 241 */
 242#define MAX_FVCO        500000  /* KHz */
 243#define MAX_FSYS        80000   /* KHz */
 244#define MIN_FSYS        58333   /* KHz */
 245#define FREF            16000   /* KHz */
 246
 247
 248#define MAX_MFD         135     /* Multiplier */
 249#define MIN_MFD         88      /* Multiplier */
 250#define BUSDIV          6       /* Divider */
 251
 252/*
 253 * Low Power Divider specifications
 254 */
 255#define MIN_LPD         (1 << 0)    /* Divider (not encoded) */
 256#define MAX_LPD         (1 << 15)   /* Divider (not encoded) */
 257#define DEFAULT_LPD     (1 << 1)        /* Divider (not encoded) */
 258
 259#define SYS_CLK_KHZ     80000
 260#define SYSTEM_PERIOD   12.5
 261/*
 262 *  SDRAM Timing Parameters
 263 */  
 264#define SDRAM_BL        8       /* # of beats in a burst */
 265#define SDRAM_TWR       2       /* in clocks */
 266#define SDRAM_CASL      2.5     /* CASL in clocks */
 267#define SDRAM_TRCD      2       /* in clocks */
 268#define SDRAM_TRP       2       /* in clocks */
 269#define SDRAM_TRFC      7       /* in clocks */
 270#define SDRAM_TREFI     7800    /* in ns */
 271
 272#define EXT_SRAM_ADDRESS        (0xC0000000)
 273#define FLASH_ADDRESS           (0x00000000)
 274#define SDRAM_ADDRESS           (0x40000000)
 275
 276#define NAND_FLASH_ADDRESS      (0xD0000000)
 277
 278int sys_clk_khz = 0;
 279int sys_clk_mhz = 0;
 280
 281void wtm_init(void);
 282void scm_init(void);
 283void gpio_init(void);
 284void fbcs_init(void);
 285void sdramc_init(void);
 286int  clock_pll (int fsys, int flags);
 287int  clock_limp (int);
 288int  clock_exit_limp (void);
 289int  get_sys_clock (void);
 290
 291asmlinkage void __init sysinit(void)
 292{
 293        sys_clk_khz = clock_pll(0, 0);
 294        sys_clk_mhz = sys_clk_khz/1000;
 295        
 296        wtm_init();
 297        scm_init();
 298        gpio_init();
 299        fbcs_init();
 300        sdramc_init();
 301}
 302
 303void wtm_init(void)
 304{
 305        /* Disable watchdog timer */
 306        writew(0, MCF_WTM_WCR);
 307}
 308
 309#define MCF_SCM_BCR_GBW         (0x00000100)
 310#define MCF_SCM_BCR_GBR         (0x00000200)
 311
 312void scm_init(void)
 313{
 314        /* All masters are trusted */
 315        writel(0x77777777, MCF_SCM_MPR);
 316    
 317        /* Allow supervisor/user, read/write, and trusted/untrusted
 318           access to all slaves */
 319        writel(0, MCF_SCM_PACRA);
 320        writel(0, MCF_SCM_PACRB);
 321        writel(0, MCF_SCM_PACRC);
 322        writel(0, MCF_SCM_PACRD);
 323        writel(0, MCF_SCM_PACRE);
 324        writel(0, MCF_SCM_PACRF);
 325
 326        /* Enable bursts */
 327        writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR);
 328}
 329
 330
 331void fbcs_init(void)
 332{
 333        writeb(0x3E, MCFGPIO_PAR_CS);
 334
 335        /* Latch chip select */
 336        writel(0x10080000, MCF_FBCS1_CSAR);
 337
 338        writel(0x002A3780, MCF_FBCS1_CSCR);
 339        writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
 340
 341        /* Initialize latch to drive signals to inactive states */
 342        writew(0xffff, 0x10080000);
 343
 344        /* External SRAM */
 345        writel(EXT_SRAM_ADDRESS, MCF_FBCS1_CSAR);
 346        writel(MCF_FBCS_CSCR_PS_16 |
 347                MCF_FBCS_CSCR_AA |
 348                MCF_FBCS_CSCR_SBM |
 349                MCF_FBCS_CSCR_WS(1),
 350                MCF_FBCS1_CSCR);
 351        writel(MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
 352
 353        /* Boot Flash connected to FBCS0 */
 354        writel(FLASH_ADDRESS, MCF_FBCS0_CSAR);
 355        writel(MCF_FBCS_CSCR_PS_16 |
 356                MCF_FBCS_CSCR_BEM |
 357                MCF_FBCS_CSCR_AA |
 358                MCF_FBCS_CSCR_SBM |
 359                MCF_FBCS_CSCR_WS(7),
 360                MCF_FBCS0_CSCR);
 361        writel(MCF_FBCS_CSMR_BAM_32M | MCF_FBCS_CSMR_V, MCF_FBCS0_CSMR);
 362}
 363
 364void sdramc_init(void)
 365{
 366        /*
 367         * Check to see if the SDRAM has already been initialized
 368         * by a run control tool
 369         */
 370        if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) {
 371                /* SDRAM chip select initialization */
 372                
 373                /* Initialize SDRAM chip select */
 374                writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) |
 375                        MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE),
 376                        MCF_SDRAMC_SDCS0);
 377
 378        /*
 379         * Basic configuration and initialization
 380         */
 381        writel(MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5)) |
 382                MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) |
 383                MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL * 2) + 2)) |
 384                MCF_SDRAMC_SDCFG1_ACT2RW((int)(SDRAM_TRCD + 0.5)) |
 385                MCF_SDRAMC_SDCFG1_PRE2ACT((int)(SDRAM_TRP + 0.5)) |
 386                MCF_SDRAMC_SDCFG1_REF2ACT((int)(SDRAM_TRFC + 0.5)) |
 387                MCF_SDRAMC_SDCFG1_WTLAT(3),
 388                MCF_SDRAMC_SDCFG1);
 389        writel(MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL / 2 + 1) |
 390                MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL / 2 + SDRAM_TWR) |
 391                MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL + SDRAM_BL / 2 - 1.0) + 0.5)) |
 392                MCF_SDRAMC_SDCFG2_BL(SDRAM_BL - 1),
 393                MCF_SDRAMC_SDCFG2);
 394
 395            
 396        /*
 397         * Precharge and enable write to SDMR
 398         */
 399        writel(MCF_SDRAMC_SDCR_MODE_EN |
 400                MCF_SDRAMC_SDCR_CKE |
 401                MCF_SDRAMC_SDCR_DDR |
 402                MCF_SDRAMC_SDCR_MUX(1) |
 403                MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI / (SYSTEM_PERIOD * 64)) - 1) + 0.5)) |
 404                MCF_SDRAMC_SDCR_PS_16 |
 405                MCF_SDRAMC_SDCR_IPALL,
 406                MCF_SDRAMC_SDCR);
 407
 408        /*
 409         * Write extended mode register
 410         */
 411        writel(MCF_SDRAMC_SDMR_BNKAD_LEMR |
 412                MCF_SDRAMC_SDMR_AD(0x0) |
 413                MCF_SDRAMC_SDMR_CMD,
 414                MCF_SDRAMC_SDMR);
 415
 416        /*
 417         * Write mode register and reset DLL
 418         */
 419        writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
 420                MCF_SDRAMC_SDMR_AD(0x163) |
 421                MCF_SDRAMC_SDMR_CMD,
 422                MCF_SDRAMC_SDMR);
 423
 424        /*
 425         * Execute a PALL command
 426         */
 427        writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR);
 428
 429        /*
 430         * Perform two REF cycles
 431         */
 432        writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
 433        writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
 434
 435        /*
 436         * Write mode register and clear reset DLL
 437         */
 438        writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
 439                MCF_SDRAMC_SDMR_AD(0x063) |
 440                MCF_SDRAMC_SDMR_CMD,
 441                MCF_SDRAMC_SDMR);
 442                                
 443        /*
 444         * Enable auto refresh and lock SDMR
 445         */
 446        writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_MODE_EN,
 447                MCF_SDRAMC_SDCR);
 448        writel(MCF_SDRAMC_SDCR_REF | MCF_SDRAMC_SDCR_DQS_OE(0xC),
 449                MCF_SDRAMC_SDCR);
 450        }
 451}
 452
 453void gpio_init(void)
 454{
 455        /* Enable UART0 pins */
 456        writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0,
 457                MCFGPIO_PAR_UART);
 458
 459        /*
 460         * Initialize TIN3 as a GPIO output to enable the write
 461         * half of the latch.
 462         */
 463        writeb(0x00, MCFGPIO_PAR_TIMER);
 464        writeb(0x08, MCFGPIO_PDDR_TIMER);
 465        writeb(0x00, MCFGPIO_PCLRR_TIMER);
 466}
 467
 468int clock_pll(int fsys, int flags)
 469{
 470        int fref, temp, fout, mfd;
 471        u32 i;
 472
 473        fref = FREF;
 474        
 475        if (fsys == 0) {
 476                /* Return current PLL output */
 477                mfd = readb(MCF_PLL_PFDR);
 478
 479                return (fref * mfd / (BUSDIV * 4));
 480        }
 481
 482        /* Check bounds of requested system clock */
 483        if (fsys > MAX_FSYS)
 484                fsys = MAX_FSYS;
 485        if (fsys < MIN_FSYS)
 486                fsys = MIN_FSYS;
 487
 488        /* Multiplying by 100 when calculating the temp value,
 489           and then dividing by 100 to calculate the mfd allows
 490           for exact values without needing to include floating
 491           point libraries. */
 492        temp = 100 * fsys / fref;
 493        mfd = 4 * BUSDIV * temp / 100;
 494                        
 495        /* Determine the output frequency for selected values */
 496        fout = (fref * mfd / (BUSDIV * 4));
 497
 498        /*
 499         * Check to see if the SDRAM has already been initialized.
 500         * If it has then the SDRAM needs to be put into self refresh
 501         * mode before reprogramming the PLL.
 502         */
 503        if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
 504                /* Put SDRAM into self refresh mode */
 505                writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE,
 506                        MCF_SDRAMC_SDCR);
 507
 508        /*
 509         * Initialize the PLL to generate the new system clock frequency.
 510         * The device must be put into LIMP mode to reprogram the PLL.
 511         */
 512
 513        /* Enter LIMP mode */
 514        clock_limp(DEFAULT_LPD);
 515                                        
 516        /* Reprogram PLL for desired fsys */
 517        writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV),
 518                MCF_PLL_PODR);
 519                                                
 520        writeb(mfd, MCF_PLL_PFDR);
 521                
 522        /* Exit LIMP mode */
 523        clock_exit_limp();
 524        
 525        /*
 526         * Return the SDRAM to normal operation if it is in use.
 527         */
 528        if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
 529                /* Exit self refresh mode */
 530                writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE,
 531                        MCF_SDRAMC_SDCR);
 532
 533        /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
 534        writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX);
 535
 536        /* wait for DQS logic to relock */
 537        for (i = 0; i < 0x200; i++)
 538                ;
 539
 540        return fout;
 541}
 542
 543int clock_limp(int div)
 544{
 545        u32 temp;
 546
 547        /* Check bounds of divider */
 548        if (div < MIN_LPD)
 549                div = MIN_LPD;
 550        if (div > MAX_LPD)
 551                div = MAX_LPD;
 552    
 553        /* Save of the current value of the SSIDIV so we don't
 554           overwrite the value*/
 555        temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF);
 556      
 557        /* Apply the divider to the system clock */
 558        writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR);
 559    
 560        writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
 561    
 562        return (FREF/(3*(1 << div)));
 563}
 564
 565int clock_exit_limp(void)
 566{
 567        int fout;
 568        
 569        /* Exit LIMP mode */
 570        writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
 571
 572        /* Wait for PLL to lock */
 573        while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK))
 574                ;
 575        
 576        fout = get_sys_clock();
 577
 578        return fout;
 579}
 580
 581int get_sys_clock(void)
 582{
 583        int divider;
 584        
 585        /* Test to see if device is in LIMP mode */
 586        if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) {
 587                divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF);
 588                return (FREF/(2 << divider));
 589        }
 590        else
 591                return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4);
 592}
 593