diff options
-rw-r--r-- | arch/m68k/include/asm/cacheflush_no.h | 2 | ||||
-rw-r--r-- | arch/m68k/include/asm/coldfire.h | 4 | ||||
-rw-r--r-- | arch/m68k/include/asm/gpio.h | 7 | ||||
-rw-r--r-- | arch/m68k/include/asm/m548xgpt.h | 88 | ||||
-rw-r--r-- | arch/m68k/include/asm/m548xsim.h | 55 | ||||
-rw-r--r-- | arch/m68k/include/asm/mcfcache.h | 2 | ||||
-rw-r--r-- | arch/m68k/include/asm/mcfsim.h | 2 | ||||
-rw-r--r-- | arch/m68k/include/asm/mcfslt.h | 44 | ||||
-rw-r--r-- | arch/m68k/include/asm/mcfuart.h | 5 | ||||
-rw-r--r-- | arch/m68knommu/Kconfig | 7 | ||||
-rw-r--r-- | arch/m68knommu/Makefile | 3 | ||||
-rw-r--r-- | arch/m68knommu/platform/548x/Makefile | 18 | ||||
-rw-r--r-- | arch/m68knommu/platform/548x/config.c | 115 | ||||
-rw-r--r-- | arch/m68knommu/platform/coldfire/Makefile | 1 | ||||
-rw-r--r-- | arch/m68knommu/platform/coldfire/sltimers.c | 145 |
15 files changed, 493 insertions, 5 deletions
diff --git a/arch/m68k/include/asm/cacheflush_no.h b/arch/m68k/include/asm/cacheflush_no.h index 89f195656be7..7085bd51668b 100644 --- a/arch/m68k/include/asm/cacheflush_no.h +++ b/arch/m68k/include/asm/cacheflush_no.h @@ -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 diff --git a/arch/m68k/include/asm/coldfire.h b/arch/m68k/include/asm/coldfire.h index 83a9fa4e618a..3b0a34d0fe33 100644 --- a/arch/m68k/include/asm/coldfire.h +++ b/arch/m68k/include/asm/coldfire.h @@ -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 diff --git a/arch/m68k/include/asm/gpio.h b/arch/m68k/include/asm/gpio.h index 283214dc65a7..1b57adbafad5 100644 --- a/arch/m68k/include/asm/gpio.h +++ b/arch/m68k/include/asm/gpio.h @@ -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 index 000000000000..c8ef158a1c4e --- /dev/null +++ b/arch/m68k/include/asm/m548xgpt.h @@ -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 index 000000000000..149135ef30d2 --- /dev/null +++ b/arch/m68k/include/asm/m548xsim.h @@ -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 */ diff --git a/arch/m68k/include/asm/mcfcache.h b/arch/m68k/include/asm/mcfcache.h index c042634fadaa..f49dfc09f70a 100644 --- a/arch/m68k/include/asm/mcfcache.h +++ b/arch/m68k/include/asm/mcfcache.h @@ -107,7 +107,7 @@ .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 diff --git a/arch/m68k/include/asm/mcfsim.h b/arch/m68k/include/asm/mcfsim.h index 9c70a67bf85f..6901fd68165b 100644 --- a/arch/m68k/include/asm/mcfsim.h +++ b/arch/m68k/include/asm/mcfsim.h @@ -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 index 000000000000..d0d0ecba5333 --- /dev/null +++ b/arch/m68k/include/asm/mcfslt.h @@ -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 */ diff --git a/arch/m68k/include/asm/mcfuart.h b/arch/m68k/include/asm/mcfuart.h index 01a8716c5fc5..af16f3be4e19 100644 --- a/arch/m68k/include/asm/mcfuart.h +++ b/arch/m68k/include/asm/mcfuart.h @@ -47,6 +47,11 @@ #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 diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index fd28178b5877..9287150e5fb0 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -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 diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile index 14042574ac21..026ef16fa68e 100644 --- a/arch/m68knommu/Makefile +++ b/arch/m68knommu/Makefile @@ -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 index 000000000000..e6035e7a2d3f --- /dev/null +++ b/arch/m68knommu/platform/548x/Makefile @@ -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 index 000000000000..9888846bd1cf --- /dev/null +++ b/arch/m68knommu/platform/548x/config.c @@ -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); + +/***************************************************************************/ diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile index f72a0e5d9996..df62171d986c 100644 --- a/arch/m68knommu/platform/coldfire/Makefile +++ b/arch/m68knommu/platform/coldfire/Makefile @@ -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 index 000000000000..0a1b937c3e18 --- /dev/null +++ b/arch/m68knommu/platform/coldfire/sltimers.c @@ -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 +} |