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