summaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/platform
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68knommu/platform')
-rw-r--r--arch/m68knommu/platform/5307/Makefile1
-rw-r--r--arch/m68knommu/platform/5307/entry.S46
-rw-r--r--arch/m68knommu/platform/5307/pit.c37
-rw-r--r--arch/m68knommu/platform/5307/timers.c49
-rw-r--r--arch/m68knommu/platform/532x/Makefile20
-rw-r--r--arch/m68knommu/platform/532x/config.c486
6 files changed, 570 insertions, 69 deletions
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 8d1619dc1ea6..2fd37dcc309b 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_M5249) += timers.o
obj-$(CONFIG_M527x) += pit.o
obj-$(CONFIG_M5272) += timers.o
obj-$(CONFIG_M5307) += config.o timers.o
+obj-$(CONFIG_M532x) += timers.o
obj-$(CONFIG_M528x) += pit.o
obj-$(CONFIG_M5407) += timers.o
diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S
index 89b180d4ed6a..9ddf5476ef8f 100644
--- a/arch/m68knommu/platform/5307/entry.S
+++ b/arch/m68knommu/platform/5307/entry.S
@@ -4,8 +4,8 @@
* Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
* Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>,
- * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- * Copyright (C) 2004 Macq Electronique SA. (www.macqel.com)
+ * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
+ * Copyright (C) 2004-2006 Macq Electronique SA. (www.macqel.com)
*
* Based on:
*
@@ -56,32 +56,27 @@ sw_usp:
.globl inthandler
.globl fasthandler
+enosys:
+ mov.l #sys_ni_syscall,%d3
+ bra 1f
+
ENTRY(system_call)
SAVE_ALL
move #0x2000,%sr /* enable intrs again */
- movel #-LENOSYS,%d2
- movel %d2,PT_D0(%sp) /* default return value in d0 */
- /* original D0 is in orig_d0 */
- movel %d0,%d2
-
- /* save top of frame */
- pea %sp@
- jbsr set_esp0
- addql #4,%sp
-
- cmpl #NR_syscalls,%d2
- jcc ret_from_exception
+ cmpl #NR_syscalls,%d0
+ jcc enosys
lea sys_call_table,%a0
- lsll #2,%d2 /* movel %a0@(%d2:l:4),%d3 */
- movel %a0@(%d2),%d3
- jeq ret_from_exception
- lsrl #2,%d2
+ lsll #2,%d0 /* movel %a0@(%d0:l:4),%d3 */
+ movel %a0@(%d0),%d3
+ jeq enosys
+1:
movel %sp,%d2 /* get thread_info pointer */
andl #-THREAD_SIZE,%d2 /* at start of kernel stack */
movel %d2,%a0
- btst #TIF_SYSCALL_TRACE,%a0@(TI_FLAGS)
+ movel %sp,%a0@(THREAD_ESP0) /* save top of frame */
+ btst #(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
bnes 1f
movel %d3,%a0
@@ -126,8 +121,8 @@ Luser_return:
jne Lwork_to_do /* still work to do */
Lreturn:
- move #0x2700,%sr /* disable intrs */
- movel sw_usp,%a0 /* get usp */
+ move #0x2700,%sr /* disable intrs */
+ movel sw_usp,%a0 /* get usp */
movel %sp@(PT_PC),%a0@- /* copy exception program counter */
movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
moveml %sp@,%d1-%d5/%a0-%a2
@@ -170,7 +165,7 @@ ENTRY(inthandler)
movel %d0,%sp@(PT_ORIG_D0)
addql #1,local_irq_count
- movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */
+ movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */
andl #0x03fc,%d0 /* mask out vector only */
leal per_cpu__kstat+STAT_IRQ,%a0
@@ -184,7 +179,7 @@ ENTRY(inthandler)
movel %sp,%sp@- /* push regs arg onto stack */
movel %a0@(8),%sp@- /* push devid arg */
- movel %d0,%sp@- /* push vector # on stack */
+ movel %d0,%sp@- /* push vector # on stack */
movel %a0@,%a0 /* get function to call */
jbsr %a0@ /* call vector handler */
@@ -201,7 +196,7 @@ ENTRY(inthandler)
ENTRY(fasthandler)
SAVE_LOCAL
- movew %sp@(PT_FORMATVEC),%d0
+ movew %sp@(PT_FORMATVEC),%d0
andl #0x03fc,%d0 /* mask out vector only */
leal per_cpu__kstat+STAT_IRQ,%a0
@@ -210,7 +205,7 @@ ENTRY(fasthandler)
movel %sp,%sp@- /* push regs arg onto stack */
clrl %sp@- /* push devid arg */
lsrl #2,%d0 /* calculate real vector # */
- movel %d0,%sp@- /* push vector # on stack */
+ movel %d0,%sp@- /* push vector # on stack */
lsll #4,%d0 /* adjust for array offset */
lea irq_list,%a0
@@ -265,4 +260,3 @@ ENTRY(resume)
movew %a1@(TASK_THREAD+THREAD_SR),%d0 /* restore thread status reg */
movew %d0, %sr
rts
-
diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c
index 323f2677e49d..ef174748825f 100644
--- a/arch/m68knommu/platform/5307/pit.c
+++ b/arch/m68knommu/platform/5307/pit.c
@@ -1,11 +1,11 @@
/***************************************************************************/
/*
- * pit.c -- Motorola ColdFire PIT timer. Currently this type of
- * hardware timer only exists in the Motorola ColdFire
+ * pit.c -- Freescale ColdFire PIT timer. Currently this type of
+ * hardware timer only exists in the Freescale ColdFire
* 5270/5271, 5282 and other CPUs.
*
- * Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 1999-2006, Greg Ungerer (gerg@snapgear.com)
* Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
*
*/
@@ -18,6 +18,7 @@
#include <linux/param.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <asm/io.h>
#include <asm/irq.h>
#include <asm/coldfire.h>
#include <asm/mcfpit.h>
@@ -25,13 +26,20 @@
/***************************************************************************/
+/*
+ * By default use timer1 as the system clock timer.
+ */
+#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a))
+
+/***************************************************************************/
+
void coldfire_pit_tick(void)
{
- volatile struct mcfpit *tp;
+ unsigned short pcsr;
/* Reset the ColdFire timer */
- tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
- tp->pcsr |= MCFPIT_PCSR_PIF;
+ pcsr = __raw_readw(TA(MCFPIT_PCSR));
+ __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
}
/***************************************************************************/
@@ -40,7 +48,6 @@ void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
{
volatile unsigned char *icrp;
volatile unsigned long *imrp;
- volatile struct mcfpit *tp;
request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, SA_INTERRUPT,
"ColdFire Timer", NULL);
@@ -53,27 +60,23 @@ void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
*imrp &= ~MCFPIT_IMR_IBIT;
/* Set up PIT timer 1 as poll clock */
- tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
- tp->pcsr = MCFPIT_PCSR_DISABLE;
-
- tp->pmr = ((MCF_CLK / 2) / 64) / HZ;
- tp->pcsr = MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
- MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64;
+ __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+ __raw_writew(((MCF_CLK / 2) / 64) / HZ, TA(MCFPIT_PMR));
+ __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
+ MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
}
/***************************************************************************/
unsigned long coldfire_pit_offset(void)
{
- volatile struct mcfpit *tp;
volatile unsigned long *ipr;
unsigned long pmr, pcntr, offset;
- tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
- pmr = *(&tp->pmr);
- pcntr = *(&tp->pcntr);
+ pmr = __raw_readw(TA(MCFPIT_PMR));
+ pcntr = __raw_readw(TA(MCFPIT_PCNTR));
/*
* If we are still in the first half of the upcount and a
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index ef49596aa09c..83b8b89dfa09 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -14,6 +14,7 @@
#include <linux/param.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <asm/io.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/machdep.h>
@@ -24,6 +25,11 @@
/***************************************************************************/
/*
+ * By default use timer1 as the system clock timer.
+ */
+#define TA(a) (MCF_MBAR + MCFTIMER_BASE1 + (a))
+
+/*
* Default the timer and vector to use for ColdFire. Some ColdFire
* CPU's and some boards may want different. Their sub-architecture
* startup code (in config.c) can change these if they want.
@@ -32,8 +38,6 @@ unsigned int mcf_timervector = 29;
unsigned int mcf_profilevector = 31;
unsigned int mcf_timerlevel = 5;
-static volatile struct mcftimer *mcf_timerp;
-
/*
* These provide the underlying interrupt vector support.
* Unfortunately it is a little different on each ColdFire.
@@ -46,20 +50,17 @@ extern int mcf_timerirqpending(int timer);
void coldfire_tick(void)
{
/* Reset the ColdFire timer */
- mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+ __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER));
}
/***************************************************************************/
void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
{
- /* Set up an internal TIMER as poll clock */
- mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1);
- mcf_timerp->tmr = MCFTIMER_TMR_DISABLE;
-
- mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ);
- mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
- MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+ __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
+ __raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
+ __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+ MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL);
mcf_settimericr(1, mcf_timerlevel);
@@ -75,13 +76,8 @@ unsigned long coldfire_timer_offset(void)
{
unsigned long trr, tcn, offset;
- /*
- * The change to pointer and de-reference is to force the compiler
- * to read the registers with a single 16bit access. Otherwise it
- * does some crazy 8bit read combining.
- */
- tcn = *(&mcf_timerp->tcn);
- trr = *(&mcf_timerp->trr);
+ tcn = __raw_readw(TA(MCFTIMER_TCN));
+ trr = __raw_readw(TA(MCFTIMER_TRR));
offset = (tcn * (1000000 / HZ)) / trr;
/* Check if we just wrapped the counters and maybe missed a tick */
@@ -95,21 +91,23 @@ unsigned long coldfire_timer_offset(void)
/***************************************************************************/
/*
+ * By default use timer2 as the profiler clock timer.
+ */
+#define PA(a) (MCF_MBAR + MCFTIMER_BASE2 + (a))
+
+/*
* Choose a reasonably fast profile timer. Make it an odd value to
* try and get good coverage of kernal operations.
*/
#define PROFILEHZ 1013
-static volatile struct mcftimer *mcf_proftp;
-
/*
* Use the other timer to provide high accuracy profiling info.
*/
-
void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
{
/* Reset ColdFire timer2 */
- mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+ __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
if (current->pid)
profile_tick(CPU_PROFILING, regs);
}
@@ -121,12 +119,11 @@ void coldfire_profile_init(void)
printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ);
/* Set up TIMER 2 as high speed profile clock */
- mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2);
- mcf_proftp->tmr = MCFTIMER_TMR_DISABLE;
+ __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR));
- mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ);
- mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
- MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+ __raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
+ __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+ MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR));
request_irq(mcf_profilevector, coldfire_profile_tick,
(SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL);
diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile
new file mode 100644
index 000000000000..12301803b9eb
--- /dev/null
+++ b/arch/m68knommu/platform/532x/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this, which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
+obj-y := config.o
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
new file mode 100644
index 000000000000..ceef9bc181ea
--- /dev/null
+++ b/arch/m68knommu/platform/532x/config.c
@@ -0,0 +1,486 @@
+/***************************************************************************/
+
+/*
+ * linux/arch/m68knommu/platform/532x/config.c
+ *
+ * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 2000, Lineo (www.lineo.com)
+ * Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
+ * Copyright Freescale Semiconductor, Inc 2006
+ * Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+#include <asm/mcfwdebug.h>
+
+/***************************************************************************/
+
+void coldfire_tick(void);
+void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+extern unsigned int mcf_timervector;
+extern unsigned int mcf_profilevector;
+extern unsigned int mcf_timerlevel;
+
+/***************************************************************************/
+
+/*
+ * DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { };
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
+
+void mcf_settimericr(unsigned int timer, unsigned int level)
+{
+ volatile unsigned char *icrp;
+ unsigned int icr;
+ unsigned char irq;
+
+ if (timer <= 2) {
+ switch (timer) {
+ case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break;
+ default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
+ }
+
+ icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+ *icrp = level;
+ mcf_enable_irq0(irq);
+ }
+}
+
+/***************************************************************************/
+
+int mcf_timerirqpending(int timer)
+{
+ unsigned int imr = 0;
+
+ switch (timer) {
+ case 1: imr = 0x1; break;
+ case 2: imr = 0x2; break;
+ default: break;
+ }
+ return (mcf_getiprh() & imr);
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+ mcf_setimr(MCFSIM_IMR_MASKALL);
+
+#if defined(CONFIG_BOOTPARAM)
+ strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+ commandp[size-1] = 0;
+#else
+ /* Copy command line from FLASH to local buffer... */
+ memcpy(commandp, (char *) 0x4000, 4);
+ if(strncmp(commandp, "kcl ", 4) == 0){
+ memcpy(commandp, (char *) 0x4004, size);
+ commandp[size-1] = 0;
+ } else {
+ memset(commandp, 0, size);
+ }
+#endif
+
+ mcf_timervector = 64+32;
+ mcf_profilevector = 64+33;
+ mach_sched_init = coldfire_timer_init;
+ mach_tick = coldfire_tick;
+ mach_gettimeoffset = coldfire_timer_offset;
+ mach_trap_init = coldfire_trap_init;
+ mach_reset = coldfire_reset;
+
+#ifdef MCF_BDM_DISABLE
+ /*
+ * Disable the BDM clocking. This also turns off most of the rest of
+ * the BDM device. This is good for EMC reasons. This option is not
+ * incompatible with the memory protection option.
+ */
+ wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
+#endif
+}
+
+/***************************************************************************/
+/* Board initialization */
+
+/********************************************************************/
+/*
+ * PLL min/max specifications
+ */
+#define MAX_FVCO 500000 /* KHz */
+#define MAX_FSYS 80000 /* KHz */
+#define MIN_FSYS 58333 /* KHz */
+#define FREF 16000 /* KHz */
+
+
+#define MAX_MFD 135 /* Multiplier */
+#define MIN_MFD 88 /* Multiplier */
+#define BUSDIV 6 /* Divider */
+
+/*
+ * Low Power Divider specifications
+ */
+#define MIN_LPD (1 << 0) /* Divider (not encoded) */
+#define MAX_LPD (1 << 15) /* Divider (not encoded) */
+#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
+
+#define SYS_CLK_KHZ 80000
+#define SYSTEM_PERIOD 12.5
+/*
+ * SDRAM Timing Parameters
+ */
+#define SDRAM_BL 8 /* # of beats in a burst */
+#define SDRAM_TWR 2 /* in clocks */
+#define SDRAM_CASL 2.5 /* CASL in clocks */
+#define SDRAM_TRCD 2 /* in clocks */
+#define SDRAM_TRP 2 /* in clocks */
+#define SDRAM_TRFC 7 /* in clocks */
+#define SDRAM_TREFI 7800 /* in ns */
+
+#define EXT_SRAM_ADDRESS (0xC0000000)
+#define FLASH_ADDRESS (0x00000000)
+#define SDRAM_ADDRESS (0x40000000)
+
+#define NAND_FLASH_ADDRESS (0xD0000000)
+
+int sys_clk_khz = 0;
+int sys_clk_mhz = 0;
+
+void wtm_init(void);
+void scm_init(void);
+void gpio_init(void);
+void fbcs_init(void);
+void sdramc_init(void);
+int clock_pll (int fsys, int flags);
+int clock_limp (int);
+int clock_exit_limp (void);
+int get_sys_clock (void);
+
+asmlinkage void __init sysinit(void)
+{
+ sys_clk_khz = clock_pll(0, 0);
+ sys_clk_mhz = sys_clk_khz/1000;
+
+ wtm_init();
+ scm_init();
+ gpio_init();
+ fbcs_init();
+ sdramc_init();
+}
+
+void wtm_init(void)
+{
+ /* Disable watchdog timer */
+ MCF_WTM_WCR = 0;
+}
+
+#define MCF_SCM_BCR_GBW (0x00000100)
+#define MCF_SCM_BCR_GBR (0x00000200)
+
+void scm_init(void)
+{
+ /* All masters are trusted */
+ MCF_SCM_MPR = 0x77777777;
+
+ /* Allow supervisor/user, read/write, and trusted/untrusted
+ access to all slaves */
+ MCF_SCM_PACRA = 0;
+ MCF_SCM_PACRB = 0;
+ MCF_SCM_PACRC = 0;
+ MCF_SCM_PACRD = 0;
+ MCF_SCM_PACRE = 0;
+ MCF_SCM_PACRF = 0;
+
+ /* Enable bursts */
+ MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
+}
+
+
+void fbcs_init(void)
+{
+ MCF_GPIO_PAR_CS = 0x0000003E;
+
+ /* Latch chip select */
+ MCF_FBCS1_CSAR = 0x10080000;
+
+ MCF_FBCS1_CSCR = 0x002A3780;
+ MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
+
+ /* Initialize latch to drive signals to inactive states */
+ *((u16 *)(0x10080000)) = 0xFFFF;
+
+ /* External SRAM */
+ MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
+ MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
+ | MCF_FBCS_CSCR_AA
+ | MCF_FBCS_CSCR_SBM
+ | MCF_FBCS_CSCR_WS(1));
+ MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
+ | MCF_FBCS_CSMR_V);
+
+ /* Boot Flash connected to FBCS0 */
+ MCF_FBCS0_CSAR = FLASH_ADDRESS;
+ MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
+ | MCF_FBCS_CSCR_BEM
+ | MCF_FBCS_CSCR_AA
+ | MCF_FBCS_CSCR_SBM
+ | MCF_FBCS_CSCR_WS(7));
+ MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
+ | MCF_FBCS_CSMR_V);
+}
+
+void sdramc_init(void)
+{
+ /*
+ * Check to see if the SDRAM has already been initialized
+ * by a run control tool
+ */
+ if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
+ /* SDRAM chip select initialization */
+
+ /* Initialize SDRAM chip select */
+ MCF_SDRAMC_SDCS0 = (0
+ | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
+ | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
+
+ /*
+ * Basic configuration and initialization
+ */
+ MCF_SDRAMC_SDCFG1 = (0
+ | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
+ | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
+ | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
+ | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
+ | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
+ | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
+ | MCF_SDRAMC_SDCFG1_WTLAT(3));
+ MCF_SDRAMC_SDCFG2 = (0
+ | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
+ | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
+ | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
+ | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
+
+
+ /*
+ * Precharge and enable write to SDMR
+ */
+ MCF_SDRAMC_SDCR = (0
+ | MCF_SDRAMC_SDCR_MODE_EN
+ | MCF_SDRAMC_SDCR_CKE
+ | MCF_SDRAMC_SDCR_DDR
+ | MCF_SDRAMC_SDCR_MUX(1)
+ | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
+ | MCF_SDRAMC_SDCR_PS_16
+ | MCF_SDRAMC_SDCR_IPALL);
+
+ /*
+ * Write extended mode register
+ */
+ MCF_SDRAMC_SDMR = (0
+ | MCF_SDRAMC_SDMR_BNKAD_LEMR
+ | MCF_SDRAMC_SDMR_AD(0x0)
+ | MCF_SDRAMC_SDMR_CMD);
+
+ /*
+ * Write mode register and reset DLL
+ */
+ MCF_SDRAMC_SDMR = (0
+ | MCF_SDRAMC_SDMR_BNKAD_LMR
+ | MCF_SDRAMC_SDMR_AD(0x163)
+ | MCF_SDRAMC_SDMR_CMD);
+
+ /*
+ * Execute a PALL command
+ */
+ MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
+
+ /*
+ * Perform two REF cycles
+ */
+ MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+ MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+
+ /*
+ * Write mode register and clear reset DLL
+ */
+ MCF_SDRAMC_SDMR = (0
+ | MCF_SDRAMC_SDMR_BNKAD_LMR
+ | MCF_SDRAMC_SDMR_AD(0x063)
+ | MCF_SDRAMC_SDMR_CMD);
+
+ /*
+ * Enable auto refresh and lock SDMR
+ */
+ MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
+ MCF_SDRAMC_SDCR |= (0
+ | MCF_SDRAMC_SDCR_REF
+ | MCF_SDRAMC_SDCR_DQS_OE(0xC));
+ }
+}
+
+void gpio_init(void)
+{
+ /* Enable UART0 pins */
+ MCF_GPIO_PAR_UART = ( 0
+ | MCF_GPIO_PAR_UART_PAR_URXD0
+ | MCF_GPIO_PAR_UART_PAR_UTXD0);
+
+ /* Initialize TIN3 as a GPIO output to enable the write
+ half of the latch */
+ MCF_GPIO_PAR_TIMER = 0x00;
+ MCF_GPIO_PDDR_TIMER = 0x08;
+ MCF_GPIO_PCLRR_TIMER = 0x0;
+
+}
+
+int clock_pll(int fsys, int flags)
+{
+ int fref, temp, fout, mfd;
+ u32 i;
+
+ fref = FREF;
+
+ if (fsys == 0) {
+ /* Return current PLL output */
+ mfd = MCF_PLL_PFDR;
+
+ return (fref * mfd / (BUSDIV * 4));
+ }
+
+ /* Check bounds of requested system clock */
+ if (fsys > MAX_FSYS)
+ fsys = MAX_FSYS;
+ if (fsys < MIN_FSYS)
+ fsys = MIN_FSYS;
+
+ /* Multiplying by 100 when calculating the temp value,
+ and then dividing by 100 to calculate the mfd allows
+ for exact values without needing to include floating
+ point libraries. */
+ temp = 100 * fsys / fref;
+ mfd = 4 * BUSDIV * temp / 100;
+
+ /* Determine the output frequency for selected values */
+ fout = (fref * mfd / (BUSDIV * 4));
+
+ /*
+ * Check to see if the SDRAM has already been initialized.
+ * If it has then the SDRAM needs to be put into self refresh
+ * mode before reprogramming the PLL.
+ */
+ if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+ /* Put SDRAM into self refresh mode */
+ MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
+
+ /*
+ * Initialize the PLL to generate the new system clock frequency.
+ * The device must be put into LIMP mode to reprogram the PLL.
+ */
+
+ /* Enter LIMP mode */
+ clock_limp(DEFAULT_LPD);
+
+ /* Reprogram PLL for desired fsys */
+ MCF_PLL_PODR = (0
+ | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
+ | MCF_PLL_PODR_BUSDIV(BUSDIV));
+
+ MCF_PLL_PFDR = mfd;
+
+ /* Exit LIMP mode */
+ clock_exit_limp();
+
+ /*
+ * Return the SDRAM to normal operation if it is in use.
+ */
+ if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+ /* Exit self refresh mode */
+ MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
+
+ /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
+ MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
+
+ /* wait for DQS logic to relock */
+ for (i = 0; i < 0x200; i++)
+ ;
+
+ return fout;
+}
+
+int clock_limp(int div)
+{
+ u32 temp;
+
+ /* Check bounds of divider */
+ if (div < MIN_LPD)
+ div = MIN_LPD;
+ if (div > MAX_LPD)
+ div = MAX_LPD;
+
+ /* Save of the current value of the SSIDIV so we don't
+ overwrite the value*/
+ temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
+
+ /* Apply the divider to the system clock */
+ MCF_CCM_CDR = ( 0
+ | MCF_CCM_CDR_LPDIV(div)
+ | MCF_CCM_CDR_SSIDIV(temp));
+
+ MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
+
+ return (FREF/(3*(1 << div)));
+}
+
+int clock_exit_limp(void)
+{
+ int fout;
+
+ /* Exit LIMP mode */
+ MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
+
+ /* Wait for PLL to lock */
+ while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
+ ;
+
+ fout = get_sys_clock();
+
+ return fout;
+}
+
+int get_sys_clock(void)
+{
+ int divider;
+
+ /* Test to see if device is in LIMP mode */
+ if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
+ divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
+ return (FREF/(2 << divider));
+ }
+ else
+ return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
+}