linux/arch/m68k/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
 169static void __init m53xx_qspi_init(void)
 170{
 171#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
 172        /* setup QSPS pins for QSPI with gpio CS control */
 173        writew(0x01f0, MCFGPIO_PAR_QSPI);
 174#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
 175}
 176
 177/***************************************************************************/
 178
 179static void __init m53xx_uarts_init(void)
 180{
 181        /* UART GPIO initialization */
 182        writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART);
 183}
 184
 185/***************************************************************************/
 186
 187static void __init m53xx_fec_init(void)
 188{
 189        u8 v;
 190
 191        /* Set multi-function pins to ethernet mode for fec0 */
 192        v = readb(MCFGPIO_PAR_FECI2C);
 193        v |= MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
 194                MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO;
 195        writeb(v, MCFGPIO_PAR_FECI2C);
 196
 197        v = readb(MCFGPIO_PAR_FEC);
 198        v = MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC;
 199        writeb(v, MCFGPIO_PAR_FEC);
 200}
 201
 202/***************************************************************************/
 203
 204void __init config_BSP(char *commandp, int size)
 205{
 206#if !defined(CONFIG_BOOTPARAM)
 207        /* Copy command line from FLASH to local buffer... */
 208        memcpy(commandp, (char *) 0x4000, 4);
 209        if(strncmp(commandp, "kcl ", 4) == 0){
 210                memcpy(commandp, (char *) 0x4004, size);
 211                commandp[size-1] = 0;
 212        } else {
 213                memset(commandp, 0, size);
 214        }
 215#endif
 216        mach_sched_init = hw_timer_init;
 217        m53xx_clk_init();
 218        m53xx_uarts_init();
 219        m53xx_fec_init();
 220        m53xx_qspi_init();
 221
 222#ifdef CONFIG_BDM_DISABLE
 223        /*
 224         * Disable the BDM clocking.  This also turns off most of the rest of
 225         * the BDM device.  This is good for EMC reasons. This option is not
 226         * incompatible with the memory protection option.
 227         */
 228        wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
 229#endif
 230}
 231
 232/***************************************************************************/
 233/* Board initialization */
 234/***************************************************************************/
 235/* 
 236 * PLL min/max specifications
 237 */
 238#define MAX_FVCO        500000  /* KHz */
 239#define MAX_FSYS        80000   /* KHz */
 240#define MIN_FSYS        58333   /* KHz */
 241#define FREF            16000   /* KHz */
 242
 243
 244#define MAX_MFD         135     /* Multiplier */
 245#define MIN_MFD         88      /* Multiplier */
 246#define BUSDIV          6       /* Divider */
 247
 248/*
 249 * Low Power Divider specifications
 250 */
 251#define MIN_LPD         (1 << 0)    /* Divider (not encoded) */
 252#define MAX_LPD         (1 << 15)   /* Divider (not encoded) */
 253#define DEFAULT_LPD     (1 << 1)        /* Divider (not encoded) */
 254
 255#define SYS_CLK_KHZ     80000
 256#define SYSTEM_PERIOD   12.5
 257/*
 258 *  SDRAM Timing Parameters
 259 */  
 260#define SDRAM_BL        8       /* # of beats in a burst */
 261#define SDRAM_TWR       2       /* in clocks */
 262#define SDRAM_CASL      2.5     /* CASL in clocks */
 263#define SDRAM_TRCD      2       /* in clocks */
 264#define SDRAM_TRP       2       /* in clocks */
 265#define SDRAM_TRFC      7       /* in clocks */
 266#define SDRAM_TREFI     7800    /* in ns */
 267
 268#define EXT_SRAM_ADDRESS        (0xC0000000)
 269#define FLASH_ADDRESS           (0x00000000)
 270#define SDRAM_ADDRESS           (0x40000000)
 271
 272#define NAND_FLASH_ADDRESS      (0xD0000000)
 273
 274int sys_clk_khz = 0;
 275int sys_clk_mhz = 0;
 276
 277void wtm_init(void);
 278void scm_init(void);
 279void gpio_init(void);
 280void fbcs_init(void);
 281void sdramc_init(void);
 282int  clock_pll (int fsys, int flags);
 283int  clock_limp (int);
 284int  clock_exit_limp (void);
 285int  get_sys_clock (void);
 286
 287asmlinkage void __init sysinit(void)
 288{
 289        sys_clk_khz = clock_pll(0, 0);
 290        sys_clk_mhz = sys_clk_khz/1000;
 291        
 292        wtm_init();
 293        scm_init();
 294        gpio_init();
 295        fbcs_init();
 296        sdramc_init();
 297}
 298
 299void wtm_init(void)
 300{
 301        /* Disable watchdog timer */
 302        writew(0, MCF_WTM_WCR);
 303}
 304
 305#define MCF_SCM_BCR_GBW         (0x00000100)
 306#define MCF_SCM_BCR_GBR         (0x00000200)
 307
 308void scm_init(void)
 309{
 310        /* All masters are trusted */
 311        writel(0x77777777, MCF_SCM_MPR);
 312    
 313        /* Allow supervisor/user, read/write, and trusted/untrusted
 314           access to all slaves */
 315        writel(0, MCF_SCM_PACRA);
 316        writel(0, MCF_SCM_PACRB);
 317        writel(0, MCF_SCM_PACRC);
 318        writel(0, MCF_SCM_PACRD);
 319        writel(0, MCF_SCM_PACRE);
 320        writel(0, MCF_SCM_PACRF);
 321
 322        /* Enable bursts */
 323        writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR);
 324}
 325
 326
 327void fbcs_init(void)
 328{
 329        writeb(0x3E, MCFGPIO_PAR_CS);
 330
 331        /* Latch chip select */
 332        writel(0x10080000, MCF_FBCS1_CSAR);
 333
 334        writel(0x002A3780, MCF_FBCS1_CSCR);
 335        writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
 336
 337        /* Initialize latch to drive signals to inactive states */
 338        writew(0xffff, 0x10080000);
 339
 340        /* External SRAM */
 341        writel(EXT_SRAM_ADDRESS, MCF_FBCS1_CSAR);
 342        writel(MCF_FBCS_CSCR_PS_16 |
 343                MCF_FBCS_CSCR_AA |
 344                MCF_FBCS_CSCR_SBM |
 345                MCF_FBCS_CSCR_WS(1),
 346                MCF_FBCS1_CSCR);
 347        writel(MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
 348
 349        /* Boot Flash connected to FBCS0 */
 350        writel(FLASH_ADDRESS, MCF_FBCS0_CSAR);
 351        writel(MCF_FBCS_CSCR_PS_16 |
 352                MCF_FBCS_CSCR_BEM |
 353                MCF_FBCS_CSCR_AA |
 354                MCF_FBCS_CSCR_SBM |
 355                MCF_FBCS_CSCR_WS(7),
 356                MCF_FBCS0_CSCR);
 357        writel(MCF_FBCS_CSMR_BAM_32M | MCF_FBCS_CSMR_V, MCF_FBCS0_CSMR);
 358}
 359
 360void sdramc_init(void)
 361{
 362        /*
 363         * Check to see if the SDRAM has already been initialized
 364         * by a run control tool
 365         */
 366        if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) {
 367                /* SDRAM chip select initialization */
 368                
 369                /* Initialize SDRAM chip select */
 370                writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) |
 371                        MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE),
 372                        MCF_SDRAMC_SDCS0);
 373
 374        /*
 375         * Basic configuration and initialization
 376         */
 377        writel(MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5)) |
 378                MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) |
 379                MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL * 2) + 2)) |
 380                MCF_SDRAMC_SDCFG1_ACT2RW((int)(SDRAM_TRCD + 0.5)) |
 381                MCF_SDRAMC_SDCFG1_PRE2ACT((int)(SDRAM_TRP + 0.5)) |
 382                MCF_SDRAMC_SDCFG1_REF2ACT((int)(SDRAM_TRFC + 0.5)) |
 383                MCF_SDRAMC_SDCFG1_WTLAT(3),
 384                MCF_SDRAMC_SDCFG1);
 385        writel(MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL / 2 + 1) |
 386                MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL / 2 + SDRAM_TWR) |
 387                MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL + SDRAM_BL / 2 - 1.0) + 0.5)) |
 388                MCF_SDRAMC_SDCFG2_BL(SDRAM_BL - 1),
 389                MCF_SDRAMC_SDCFG2);
 390
 391            
 392        /*
 393         * Precharge and enable write to SDMR
 394         */
 395        writel(MCF_SDRAMC_SDCR_MODE_EN |
 396                MCF_SDRAMC_SDCR_CKE |
 397                MCF_SDRAMC_SDCR_DDR |
 398                MCF_SDRAMC_SDCR_MUX(1) |
 399                MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI / (SYSTEM_PERIOD * 64)) - 1) + 0.5)) |
 400                MCF_SDRAMC_SDCR_PS_16 |
 401                MCF_SDRAMC_SDCR_IPALL,
 402                MCF_SDRAMC_SDCR);
 403
 404        /*
 405         * Write extended mode register
 406         */
 407        writel(MCF_SDRAMC_SDMR_BNKAD_LEMR |
 408                MCF_SDRAMC_SDMR_AD(0x0) |
 409                MCF_SDRAMC_SDMR_CMD,
 410                MCF_SDRAMC_SDMR);
 411
 412        /*
 413         * Write mode register and reset DLL
 414         */
 415        writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
 416                MCF_SDRAMC_SDMR_AD(0x163) |
 417                MCF_SDRAMC_SDMR_CMD,
 418                MCF_SDRAMC_SDMR);
 419
 420        /*
 421         * Execute a PALL command
 422         */
 423        writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR);
 424
 425        /*
 426         * Perform two REF cycles
 427         */
 428        writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
 429        writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
 430
 431        /*
 432         * Write mode register and clear reset DLL
 433         */
 434        writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
 435                MCF_SDRAMC_SDMR_AD(0x063) |
 436                MCF_SDRAMC_SDMR_CMD,
 437                MCF_SDRAMC_SDMR);
 438                                
 439        /*
 440         * Enable auto refresh and lock SDMR
 441         */
 442        writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_MODE_EN,
 443                MCF_SDRAMC_SDCR);
 444        writel(MCF_SDRAMC_SDCR_REF | MCF_SDRAMC_SDCR_DQS_OE(0xC),
 445                MCF_SDRAMC_SDCR);
 446        }
 447}
 448
 449void gpio_init(void)
 450{
 451        /* Enable UART0 pins */
 452        writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0,
 453                MCFGPIO_PAR_UART);
 454
 455        /*
 456         * Initialize TIN3 as a GPIO output to enable the write
 457         * half of the latch.
 458         */
 459        writeb(0x00, MCFGPIO_PAR_TIMER);
 460        writeb(0x08, MCFGPIO_PDDR_TIMER);
 461        writeb(0x00, MCFGPIO_PCLRR_TIMER);
 462}
 463
 464int clock_pll(int fsys, int flags)
 465{
 466        int fref, temp, fout, mfd;
 467        u32 i;
 468
 469        fref = FREF;
 470        
 471        if (fsys == 0) {
 472                /* Return current PLL output */
 473                mfd = readb(MCF_PLL_PFDR);
 474
 475                return (fref * mfd / (BUSDIV * 4));
 476        }
 477
 478        /* Check bounds of requested system clock */
 479        if (fsys > MAX_FSYS)
 480                fsys = MAX_FSYS;
 481        if (fsys < MIN_FSYS)
 482                fsys = MIN_FSYS;
 483
 484        /* Multiplying by 100 when calculating the temp value,
 485           and then dividing by 100 to calculate the mfd allows
 486           for exact values without needing to include floating
 487           point libraries. */
 488        temp = 100 * fsys / fref;
 489        mfd = 4 * BUSDIV * temp / 100;
 490                        
 491        /* Determine the output frequency for selected values */
 492        fout = (fref * mfd / (BUSDIV * 4));
 493
 494        /*
 495         * Check to see if the SDRAM has already been initialized.
 496         * If it has then the SDRAM needs to be put into self refresh
 497         * mode before reprogramming the PLL.
 498         */
 499        if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
 500                /* Put SDRAM into self refresh mode */
 501                writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE,
 502                        MCF_SDRAMC_SDCR);
 503
 504        /*
 505         * Initialize the PLL to generate the new system clock frequency.
 506         * The device must be put into LIMP mode to reprogram the PLL.
 507         */
 508
 509        /* Enter LIMP mode */
 510        clock_limp(DEFAULT_LPD);
 511                                        
 512        /* Reprogram PLL for desired fsys */
 513        writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV),
 514                MCF_PLL_PODR);
 515                                                
 516        writeb(mfd, MCF_PLL_PFDR);
 517                
 518        /* Exit LIMP mode */
 519        clock_exit_limp();
 520        
 521        /*
 522         * Return the SDRAM to normal operation if it is in use.
 523         */
 524        if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
 525                /* Exit self refresh mode */
 526                writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE,
 527                        MCF_SDRAMC_SDCR);
 528
 529        /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
 530        writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX);
 531
 532        /* wait for DQS logic to relock */
 533        for (i = 0; i < 0x200; i++)
 534                ;
 535
 536        return fout;
 537}
 538
 539int clock_limp(int div)
 540{
 541        u32 temp;
 542
 543        /* Check bounds of divider */
 544        if (div < MIN_LPD)
 545                div = MIN_LPD;
 546        if (div > MAX_LPD)
 547                div = MAX_LPD;
 548    
 549        /* Save of the current value of the SSIDIV so we don't
 550           overwrite the value*/
 551        temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF);
 552      
 553        /* Apply the divider to the system clock */
 554        writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR);
 555    
 556        writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
 557    
 558        return (FREF/(3*(1 << div)));
 559}
 560
 561int clock_exit_limp(void)
 562{
 563        int fout;
 564        
 565        /* Exit LIMP mode */
 566        writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
 567
 568        /* Wait for PLL to lock */
 569        while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK))
 570                ;
 571        
 572        fout = get_sys_clock();
 573
 574        return fout;
 575}
 576
 577int get_sys_clock(void)
 578{
 579        int divider;
 580        
 581        /* Test to see if device is in LIMP mode */
 582        if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) {
 583                divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF);
 584                return (FREF/(2 << divider));
 585        }
 586        else
 587                return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4);
 588}
 589