cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

m53xx.c (16305B)


      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 operation 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}