]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
m68knommu: add basic mmu-less m548x support
authorPhilippe De Muyter <phdm@macqel.be>
Mon, 20 Sep 2010 11:11:11 +0000 (13:11 +0200)
committerGreg Ungerer <gerg@uclinux.org>
Thu, 21 Oct 2010 00:17:30 +0000 (10:17 +1000)
Add a very basic mmu-less support for coldfire m548x family.  This is perhaps
also valid for m547x family.  The port comprises the serial, tick timer and
reboot support.  The gpio part compiles but is empty.  This gives a functional
albeit limited linux for the m548x coldfire family.  This has been tested
on a Freescale M548xEVB Lite board with a M5484 processor and the default
dbug monitor.

Signed-off-by: Philippe De Muyter <phdm@macqel.be>
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
15 files changed:
arch/m68k/include/asm/cacheflush_no.h
arch/m68k/include/asm/coldfire.h
arch/m68k/include/asm/gpio.h
arch/m68k/include/asm/m548xgpt.h [new file with mode: 0644]
arch/m68k/include/asm/m548xsim.h [new file with mode: 0644]
arch/m68k/include/asm/mcfcache.h
arch/m68k/include/asm/mcfsim.h
arch/m68k/include/asm/mcfslt.h [new file with mode: 0644]
arch/m68k/include/asm/mcfuart.h
arch/m68knommu/Kconfig
arch/m68knommu/Makefile
arch/m68knommu/platform/548x/Makefile [new file with mode: 0644]
arch/m68knommu/platform/548x/config.c [new file with mode: 0644]
arch/m68knommu/platform/coldfire/Makefile
arch/m68knommu/platform/coldfire/sltimers.c [new file with mode: 0644]

index 89f195656be74e8888e2c9d28389034408511775..7085bd51668b96d101c44b2506cf730812a23eaa 100644 (file)
@@ -29,7 +29,7 @@
 
 static inline void __flush_cache_all(void)
 {
-#ifdef CONFIG_M5407
+#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
        /*
         *      Use cpushl to push and invalidate all cache lines.
         *      Gas doesn't seem to know how to generate the ColdFire
index 83a9fa4e618accaef823f556a9492ba2f614b5d8..3b0a34d0fe33400c66e68462375ead78b2a1cb5f 100644 (file)
@@ -32,7 +32,9 @@
  */
 #define        MCF_MBAR        0x10000000
 #define        MCF_MBAR2       0x80000000
-#if defined(CONFIG_M520x)
+#if defined(CONFIG_M548x)
+#define        MCF_IPSBAR      MCF_MBAR
+#elif defined(CONFIG_M520x)
 #define        MCF_IPSBAR      0xFC000000
 #else
 #define        MCF_IPSBAR      0x40000000
index 283214dc65a7b6d051ab20fbeb592bd28749174e..1b57adbafad54b14ef1b651a5b82fdf295bf8d47 100644 (file)
@@ -36,7 +36,8 @@
  */
 #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
     defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
-    defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
+    defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+    defined(CONFIG_M532x) || defined(CONFIG_M548x)
 
 /* These parts have GPIO organized by 8 bit ports */
 
@@ -136,6 +137,8 @@ static inline u32 __mcf_gpio_ppdr(unsigned gpio)
 #endif
        else
                return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#else
+       return 0;
 #endif
 }
 
@@ -173,6 +176,8 @@ static inline u32 __mcf_gpio_podr(unsigned gpio)
 #endif
        else
                return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#else
+       return 0;
 #endif
 }
 
diff --git a/arch/m68k/include/asm/m548xgpt.h b/arch/m68k/include/asm/m548xgpt.h
new file mode 100644 (file)
index 0000000..c8ef158
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * File:       m548xgpt.h
+ * Purpose:    Register and bit definitions for the MCF548X
+ *
+ * Notes:
+ *
+ */
+
+#ifndef m548xgpt_h
+#define m548xgpt_h
+
+/*********************************************************************
+*
+* General Purpose Timers (GPT)
+*
+*********************************************************************/
+
+/* Register read/write macros */
+#define MCF_GPT_GMS0       0x000800
+#define MCF_GPT_GCIR0      0x000804
+#define MCF_GPT_GPWM0      0x000808
+#define MCF_GPT_GSR0       0x00080C
+#define MCF_GPT_GMS1       0x000810
+#define MCF_GPT_GCIR1      0x000814
+#define MCF_GPT_GPWM1      0x000818
+#define MCF_GPT_GSR1       0x00081C
+#define MCF_GPT_GMS2       0x000820
+#define MCF_GPT_GCIR2      0x000824
+#define MCF_GPT_GPWM2      0x000828
+#define MCF_GPT_GSR2       0x00082C
+#define MCF_GPT_GMS3       0x000830
+#define MCF_GPT_GCIR3      0x000834
+#define MCF_GPT_GPWM3      0x000838
+#define MCF_GPT_GSR3       0x00083C
+#define MCF_GPT_GMS(x)     (0x000800+((x)*0x010))
+#define MCF_GPT_GCIR(x)    (0x000804+((x)*0x010))
+#define MCF_GPT_GPWM(x)    (0x000808+((x)*0x010))
+#define MCF_GPT_GSR(x)     (0x00080C+((x)*0x010))
+
+/* Bit definitions and macros for MCF_GPT_GMS */
+#define MCF_GPT_GMS_TMS(x)         (((x)&0x00000007)<<0)
+#define MCF_GPT_GMS_GPIO(x)        (((x)&0x00000003)<<4)
+#define MCF_GPT_GMS_IEN            (0x00000100)
+#define MCF_GPT_GMS_OD             (0x00000200)
+#define MCF_GPT_GMS_SC             (0x00000400)
+#define MCF_GPT_GMS_CE             (0x00001000)
+#define MCF_GPT_GMS_WDEN           (0x00008000)
+#define MCF_GPT_GMS_ICT(x)         (((x)&0x00000003)<<16)
+#define MCF_GPT_GMS_OCT(x)         (((x)&0x00000003)<<20)
+#define MCF_GPT_GMS_OCPW(x)        (((x)&0x000000FF)<<24)
+#define MCF_GPT_GMS_OCT_FRCLOW     (0x00000000)
+#define MCF_GPT_GMS_OCT_PULSEHI    (0x00100000)
+#define MCF_GPT_GMS_OCT_PULSELO    (0x00200000)
+#define MCF_GPT_GMS_OCT_TOGGLE     (0x00300000)
+#define MCF_GPT_GMS_ICT_ANY        (0x00000000)
+#define MCF_GPT_GMS_ICT_RISE       (0x00010000)
+#define MCF_GPT_GMS_ICT_FALL       (0x00020000)
+#define MCF_GPT_GMS_ICT_PULSE      (0x00030000)
+#define MCF_GPT_GMS_GPIO_INPUT     (0x00000000)
+#define MCF_GPT_GMS_GPIO_OUTLO     (0x00000020)
+#define MCF_GPT_GMS_GPIO_OUTHI     (0x00000030)
+#define MCF_GPT_GMS_TMS_DISABLE    (0x00000000)
+#define MCF_GPT_GMS_TMS_INCAPT     (0x00000001)
+#define MCF_GPT_GMS_TMS_OUTCAPT    (0x00000002)
+#define MCF_GPT_GMS_TMS_PWM        (0x00000003)
+#define MCF_GPT_GMS_TMS_GPIO       (0x00000004)
+
+/* Bit definitions and macros for MCF_GPT_GCIR */
+#define MCF_GPT_GCIR_CNT(x)        (((x)&0x0000FFFF)<<0)
+#define MCF_GPT_GCIR_PRE(x)        (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GPWM */
+#define MCF_GPT_GPWM_LOAD          (0x00000001)
+#define MCF_GPT_GPWM_PWMOP         (0x00000100)
+#define MCF_GPT_GPWM_WIDTH(x)      (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GSR */
+#define MCF_GPT_GSR_CAPT           (0x00000001)
+#define MCF_GPT_GSR_COMP           (0x00000002)
+#define MCF_GPT_GSR_PWMP           (0x00000004)
+#define MCF_GPT_GSR_TEXP           (0x00000008)
+#define MCF_GPT_GSR_PIN            (0x00000100)
+#define MCF_GPT_GSR_OVF(x)         (((x)&0x00000007)<<12)
+#define MCF_GPT_GSR_CAPTURE(x)     (((x)&0x0000FFFF)<<16)
+
+/********************************************************************/
+
+#endif /* m548xgpt_h */
diff --git a/arch/m68k/include/asm/m548xsim.h b/arch/m68k/include/asm/m548xsim.h
new file mode 100644 (file)
index 0000000..149135e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *     m548xsim.h -- ColdFire 547x/548x System Integration Unit support.
+ */
+
+#ifndef        m548xsim_h
+#define m548xsim_h
+
+#define MCFINT_VECBASE      64
+
+/*
+ *      Interrupt Controller Registers
+ */
+#define MCFICM_INTC0           0x0700          /* Base for Interrupt Ctrl 0 */
+#define MCFINTC_IPRH           0x00            /* Interrupt pending 32-63 */
+#define MCFINTC_IPRL           0x04            /* Interrupt pending 1-31 */
+#define MCFINTC_IMRH           0x08            /* Interrupt mask 32-63 */
+#define MCFINTC_IMRL           0x0c            /* Interrupt mask 1-31 */
+#define MCFINTC_INTFRCH                0x10            /* Interrupt force 32-63 */
+#define MCFINTC_INTFRCL                0x14            /* Interrupt force 1-31 */
+#define MCFINTC_IRLR           0x18            /* */
+#define MCFINTC_IACKL          0x19            /* */
+#define MCFINTC_ICR0           0x40            /* Base ICR register */
+
+/*
+ *     Define system peripheral IRQ usage.
+ */
+#define MCF_IRQ_TIMER          (64 + 54)       /* Slice Timer 0 */
+#define MCF_IRQ_PROFILER       (64 + 53)       /* Slice Timer 1 */
+
+/*
+ *     Generic GPIO support
+ */
+#define MCFGPIO_PIN_MAX                0       /* I am too lazy to count */
+#define MCFGPIO_IRQ_MAX                -1
+#define MCFGPIO_IRQ_VECBASE    -1
+
+/*
+ *     Some PSC related definitions
+ */
+#define MCF_PAR_PSC(x)         (0x000A4F-((x)&0x3))
+#define MCF_PAR_SDA            (0x0008)
+#define MCF_PAR_SCL            (0x0004)
+#define MCF_PAR_PSC_TXD                (0x04)
+#define MCF_PAR_PSC_RXD                (0x08)
+#define MCF_PAR_PSC_RTS(x)     (((x)&0x03)<<4)
+#define MCF_PAR_PSC_CTS(x)     (((x)&0x03)<<6)
+#define MCF_PAR_PSC_CTS_GPIO   (0x00)
+#define MCF_PAR_PSC_CTS_BCLK   (0x80)
+#define MCF_PAR_PSC_CTS_CTS    (0xC0)
+#define MCF_PAR_PSC_RTS_GPIO    (0x00)
+#define MCF_PAR_PSC_RTS_FSYNC  (0x20)
+#define MCF_PAR_PSC_RTS_RTS    (0x30)
+#define MCF_PAR_PSC_CANRX      (0x40)
+
+#endif /* m548xsim_h */
index c042634fadaa0cecb2c83d0ea9e3feac3ecc91d5..f49dfc09f70a6949375cd9c2d628373762fc4b49 100644 (file)
 .endm
 #endif /* CONFIG_M532x */
 
-#if defined(CONFIG_M5407)
+#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
 /*
  *     Version 4 cores have a true harvard style separate instruction
  *     and data cache. Invalidate and enable cache, also enable write
index 9c70a67bf85f7c90f12be85c9aaef73ac55dec17..6901fd68165bd333b79b3dc1dc113b7a15275f72 100644 (file)
@@ -41,6 +41,8 @@
 #elif defined(CONFIG_M5407)
 #include <asm/m5407sim.h>
 #include <asm/mcfintc.h>
+#elif defined(CONFIG_M548x)
+#include <asm/m548xsim.h>
 #endif
 
 /****************************************************************************/
diff --git a/arch/m68k/include/asm/mcfslt.h b/arch/m68k/include/asm/mcfslt.h
new file mode 100644 (file)
index 0000000..d0d0ecb
--- /dev/null
@@ -0,0 +1,44 @@
+/****************************************************************************/
+
+/*
+ *     mcfslt.h -- ColdFire internal Slice (SLT) timer support defines.
+ *
+ *     (C) Copyright 2004, Greg Ungerer (gerg@snapgear.com)
+ *     (C) Copyright 2009, Philippe De Muyter (phdm@macqel.be)
+ */
+
+/****************************************************************************/
+#ifndef mcfslt_h
+#define mcfslt_h
+/****************************************************************************/
+
+/*
+ *     Get address specific defines for the 547x.
+ */
+#define MCFSLT_TIMER0          0x900   /* Base address of TIMER0 */
+#define MCFSLT_TIMER1          0x910   /* Base address of TIMER1 */
+
+
+/*
+ *     Define the SLT timer register set addresses.
+ */
+#define MCFSLT_STCNT           0x00    /* Terminal count */
+#define MCFSLT_SCR             0x04    /* Control */
+#define MCFSLT_SCNT            0x08    /* Current count */
+#define MCFSLT_SSR             0x0C    /* Status */
+
+/*
+ *     Bit definitions for the SCR control register.
+ */
+#define MCFSLT_SCR_RUN         0x04000000      /* Run mode (continuous) */
+#define MCFSLT_SCR_IEN         0x02000000      /* Interrupt enable */
+#define MCFSLT_SCR_TEN         0x01000000      /* Timer enable */
+
+/*
+ *     Bit definitions for the SSR status register.
+ */
+#define MCFSLT_SSR_BE          0x02000000      /* Bus error condition */
+#define MCFSLT_SSR_TE          0x01000000      /* Timeout condition */
+
+/****************************************************************************/
+#endif /* mcfslt_h */
index 01a8716c5fc558253538b9cbea14a923b8b889be..af16f3be4e19f451ac73f0c99e36240003ddf525 100644 (file)
 #define MCFUART_BASE1          0xfc060000      /* Base address of UART1 */
 #define MCFUART_BASE2          0xfc064000      /* Base address of UART2 */
 #define MCFUART_BASE3          0xfc068000      /* Base address of UART3 */
+#elif defined(CONFIG_M548x)
+#define MCFUART_BASE1          0x8600          /* on M548x */
+#define MCFUART_BASE2          0x8700          /* on M548x */
+#define MCFUART_BASE3          0x8800          /* on M548x */
+#define MCFUART_BASE4          0x8900          /* on M548x */
 #endif
 
 
index fd28178b5877cd4cafa06b8c44e7efcc01704bf3..9287150e5fb0604419aca81ee1a34e82fb75882e 100644 (file)
@@ -175,6 +175,11 @@ config M5407
        help
          Motorola ColdFire 5407 processor support.
 
+config M548x
+       bool "MCF548x"
+       help
+         Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
+
 endchoice
 
 config M527x
@@ -185,7 +190,7 @@ config M527x
 
 config COLDFIRE
        bool
-       depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407)
+       depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M548x)
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
        default y
index 14042574ac217550db926fd24e308b7c5620f756..026ef16fa68e6c0054ff479af392822db7de9075 100644 (file)
@@ -25,6 +25,7 @@ platform-$(CONFIG_M528x)      := 528x
 platform-$(CONFIG_M5307)       := 5307
 platform-$(CONFIG_M532x)       := 532x
 platform-$(CONFIG_M5407)       := 5407
+platform-$(CONFIG_M548x)       := 548x
 PLATFORM := $(platform-y)
 
 board-$(CONFIG_PILOT)          := pilot
@@ -73,6 +74,7 @@ cpuclass-$(CONFIG_M528x)      := coldfire
 cpuclass-$(CONFIG_M5307)       := coldfire
 cpuclass-$(CONFIG_M532x)       := coldfire
 cpuclass-$(CONFIG_M5407)       := coldfire
+cpuclass-$(CONFIG_M548x)       := coldfire
 cpuclass-$(CONFIG_M68328)      := 68328
 cpuclass-$(CONFIG_M68EZ328)    := 68328
 cpuclass-$(CONFIG_M68VZ328)    := 68328
@@ -100,6 +102,7 @@ cflags-$(CONFIG_M528x)              := $(call cc-option,-m528x,-m5307)
 cflags-$(CONFIG_M5307)         := $(call cc-option,-m5307,-m5200)
 cflags-$(CONFIG_M532x)         := $(call cc-option,-mcpu=532x,-m5307)
 cflags-$(CONFIG_M5407)         := $(call cc-option,-m5407,-m5200)
+cflags-$(CONFIG_M548x)         := $(call cc-option,-m5407,-m5200)
 cflags-$(CONFIG_M68328)                := -m68000
 cflags-$(CONFIG_M68EZ328)      := -m68000
 cflags-$(CONFIG_M68VZ328)      := -m68000
diff --git a/arch/m68knommu/platform/548x/Makefile b/arch/m68knommu/platform/548x/Makefile
new file mode 100644 (file)
index 0000000..e6035e7
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# 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
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o
+
diff --git a/arch/m68knommu/platform/548x/config.c b/arch/m68knommu/platform/548x/config.c
new file mode 100644 (file)
index 0000000..9888846
--- /dev/null
@@ -0,0 +1,115 @@
+/***************************************************************************/
+
+/*
+ *     linux/arch/m68knommu/platform/548x/config.c
+ *
+ *     Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/m548xsim.h>
+#include <asm/mcfuart.h>
+#include <asm/m548xgpt.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m548x_uart_platform[] = {
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE1,
+               .irq            = 64 + 35,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE2,
+               .irq            = 64 + 34,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE3,
+               .irq            = 64 + 33,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE4,
+               .irq            = 64 + 32,
+       },
+};
+
+static struct platform_device m548x_uart = {
+       .name                   = "mcfuart",
+       .id                     = 0,
+       .dev.platform_data      = m548x_uart_platform,
+};
+
+static struct platform_device *m548x_devices[] __initdata = {
+       &m548x_uart,
+};
+
+
+/***************************************************************************/
+
+static void __init m548x_uart_init_line(int line, int irq)
+{
+       int rts_cts;
+
+       /* enable io pins */
+       switch (line) {
+       case 0:
+               rts_cts = 0; break;
+       case 1:
+               rts_cts = MCF_PAR_PSC_RTS_RTS; break;
+       case 2:
+               rts_cts = MCF_PAR_PSC_RTS_RTS | MCF_PAR_PSC_CTS_CTS; break;
+       case 3:
+               rts_cts = 0; break;
+       }
+       __raw_writeb(MCF_PAR_PSC_TXD | rts_cts | MCF_PAR_PSC_RXD,
+                                               MCF_MBAR + MCF_PAR_PSC(line));
+}
+
+static void __init m548x_uarts_init(void)
+{
+       const int nrlines = ARRAY_SIZE(m548x_uart_platform);
+       int line;
+
+       for (line = 0; (line < nrlines); line++)
+               m548x_uart_init_line(line, m548x_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void mcf548x_reset(void)
+{
+       /* disable interrupts and enable the watchdog */
+       asm("movew #0x2700, %sr\n");
+       __raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
+       __raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
+       __raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
+                                               MCF_MBAR + MCF_GPT_GMS0);
+}
+
+/***************************************************************************/
+
+void __init config_BSP(char *commandp, int size)
+{
+       mach_reset = mcf548x_reset;
+       m548x_uarts_init();
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+
+       platform_add_devices(m548x_devices, ARRAY_SIZE(m548x_devices));
+       return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
index f72a0e5d9996a9a5104ca1d81171c2a701252dd9..df62171d986cab1e44e0a28ae3ce89893bc99f09 100644 (file)
@@ -26,6 +26,7 @@ obj-$(CONFIG_M528x)   += pit.o intc-2.o
 obj-$(CONFIG_M5307)    += timers.o intc.o
 obj-$(CONFIG_M532x)    += timers.o intc-simr.o
 obj-$(CONFIG_M5407)    += timers.o intc.o
+obj-$(CONFIG_M548x)    += sltimers.o intc-2.o
 
 obj-y                  += pinmux.o gpio.o
 extra-y := head.o
diff --git a/arch/m68knommu/platform/coldfire/sltimers.c b/arch/m68knommu/platform/coldfire/sltimers.c
new file mode 100644 (file)
index 0000000..0a1b937
--- /dev/null
@@ -0,0 +1,145 @@
+/***************************************************************************/
+
+/*
+ *     sltimers.c -- generic ColdFire slice timer support.
+ *
+ *     Copyright (C) 2009-2010, Philippe De Muyter <phdm@macqel.be>
+ *     based on
+ *     timers.c -- generic ColdFire hardware timer support.
+ *     Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/clocksource.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfslt.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+#ifdef CONFIG_HIGHPROFILE
+
+/*
+ *     By default use Slice Timer 1 as the profiler clock timer.
+ */
+#define        PA(a)   (MCF_MBAR + MCFSLT_TIMER1 + (a))
+
+/*
+ *     Choose a reasonably fast profile timer. Make it an odd value to
+ *     try and get good coverage of kernel operations.
+ */
+#define        PROFILEHZ       1013
+
+irqreturn_t mcfslt_profile_tick(int irq, void *dummy)
+{
+       /* Reset Slice Timer 1 */
+       __raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, PA(MCFSLT_SSR));
+       if (current->pid)
+               profile_tick(CPU_PROFILING);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction mcfslt_profile_irq = {
+       .name    = "profile timer",
+       .flags   = IRQF_DISABLED | IRQF_TIMER,
+       .handler = mcfslt_profile_tick,
+};
+
+void mcfslt_profile_init(void)
+{
+       printk(KERN_INFO "PROFILE: lodging TIMER 1 @ %dHz as profile timer\n",
+              PROFILEHZ);
+
+       setup_irq(MCF_IRQ_PROFILER, &mcfslt_profile_irq);
+
+       /* Set up TIMER 2 as high speed profile clock */
+       __raw_writel(MCF_BUSCLK / PROFILEHZ - 1, PA(MCFSLT_STCNT));
+       __raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+                                                               PA(MCFSLT_SCR));
+
+}
+
+#endif /* CONFIG_HIGHPROFILE */
+
+/***************************************************************************/
+
+/*
+ *     By default use Slice Timer 0 as the system clock timer.
+ */
+#define        TA(a)   (MCF_MBAR + MCFSLT_TIMER0 + (a))
+
+static u32 mcfslt_cycles_per_jiffy;
+static u32 mcfslt_cnt;
+
+static irqreturn_t mcfslt_tick(int irq, void *dummy)
+{
+       /* Reset Slice Timer 0 */
+       __raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, TA(MCFSLT_SSR));
+       mcfslt_cnt += mcfslt_cycles_per_jiffy;
+       return arch_timer_interrupt(irq, dummy);
+}
+
+static struct irqaction mcfslt_timer_irq = {
+       .name    = "timer",
+       .flags   = IRQF_DISABLED | IRQF_TIMER,
+       .handler = mcfslt_tick,
+};
+
+static cycle_t mcfslt_read_clk(struct clocksource *cs)
+{
+       unsigned long flags;
+       u32 cycles;
+       u16 scnt;
+
+       local_irq_save(flags);
+       scnt = __raw_readl(TA(MCFSLT_SCNT));
+       cycles = mcfslt_cnt;
+       local_irq_restore(flags);
+
+       /* substract because slice timers count down */
+       return cycles - scnt;
+}
+
+static struct clocksource mcfslt_clk = {
+       .name   = "slt",
+       .rating = 250,
+       .read   = mcfslt_read_clk,
+       .shift  = 20,
+       .mask   = CLOCKSOURCE_MASK(32),
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void hw_timer_init(void)
+{
+       mcfslt_cycles_per_jiffy = MCF_BUSCLK / HZ;
+       /*
+        *      The coldfire slice timer (SLT) runs from STCNT to 0 included,
+        *      then STCNT again and so on.  It counts thus actually
+        *      STCNT + 1 steps for 1 tick, not STCNT.  So if you want
+        *      n cycles, initialize STCNT with n - 1.
+        */
+       __raw_writel(mcfslt_cycles_per_jiffy - 1, TA(MCFSLT_STCNT));
+       __raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+                                                               TA(MCFSLT_SCR));
+       /* initialize mcfslt_cnt knowing that slice timers count down */
+       mcfslt_cnt = mcfslt_cycles_per_jiffy;
+
+       setup_irq(MCF_IRQ_TIMER, &mcfslt_timer_irq);
+
+       mcfslt_clk.mult = clocksource_hz2mult(MCF_BUSCLK, mcfslt_clk.shift);
+       clocksource_register(&mcfslt_clk);
+
+#ifdef CONFIG_HIGHPROFILE
+       mcfslt_profile_init();
+#endif
+}