]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
sh: Finish the sh64 migration off of ARCH_USES_GETTIMEOFFSET.
authorPaul Mundt <lethal@linux-sh.org>
Fri, 8 May 2009 07:12:17 +0000 (16:12 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Fri, 8 May 2009 07:12:17 +0000 (16:12 +0900)
This adds sh_tmu support to the SH-5 subtypes, which subsequently allows
us to kill off time_64.c and use the now generic time_32.c. As a bonus,
SH-5 now supports highres timers and tickless for the first time.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/Kconfig
arch/sh/kernel/Makefile_64
arch/sh/kernel/cpu/sh5/setup-sh5.c
arch/sh/kernel/time_64.c [deleted file]

index 88eb118e9fa66010c34497b2b4154377458b0b3e..ca5c09b241c301af3799fabd765051f3da208995 100644 (file)
@@ -141,10 +141,6 @@ config ARCH_NO_VIRT_TO_BUS
 config ARCH_HAS_DEFAULT_IDLE
        def_bool y
 
-config ARCH_USES_GETTIMEOFFSET
-       def_bool y 
-       depends on SUPERH64
-
 config IO_TRAPPED
        bool
 
@@ -190,6 +186,7 @@ config CPU_SH4AL_DSP
 config CPU_SH5
        bool
        select CPU_HAS_FPU
+       select SYS_SUPPORTS_TMU
 
 config CPU_SHX2
        bool
index d256c774695747256102d84d190d5887feb1ee38..4667d4cac953830cb2e4ddcfc71d8ec2797805ef 100644 (file)
@@ -2,7 +2,7 @@ extra-y := head_64.o init_task.o vmlinux.lds
 
 obj-y  := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \
           ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
-          syscalls_64.o time_64.o topology.o traps.o traps_64.o
+          syscalls_64.o time_32.o topology.o traps.o traps_64.o
 
 obj-y                          += cpu/ timers/
 obj-$(CONFIG_VSYSCALL)         += vsyscall/
index 9a362c8f3fe9799fcd4435a5dc5aebf45b3286df..678d69bdebbae823d2e05de3ef62db44339e0bbd 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/serial_sci.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/sh_timer.h>
 #include <asm/addrspace.h>
 
 static struct plat_sci_port sci_platform_data[] = {
@@ -64,6 +65,110 @@ static struct platform_device rtc_device = {
        .resource       = rtc_resources,
 };
 
+#define        TMU_BLOCK_OFF   0x01020000
+#define TMU_BASE       PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
+#define TMU0_BASE      (TMU_BASE + 0x8 + (0xc * 0x0))
+#define TMU1_BASE      (TMU_BASE + 0x8 + (0xc * 0x1))
+#define TMU2_BASE      (TMU_BASE + 0x8 + (0xc * 0x2))
+
+static struct sh_timer_config tmu0_platform_data = {
+       .name = "TMU0",
+       .channel_offset = 0x04,
+       .timer_bit = 0,
+       .clk = "module_clk",
+       .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+       [0] = {
+               .name   = "TMU0",
+               .start  = TMU0_BASE,
+               .end    = TMU0_BASE + 0xc - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_TUNI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device tmu0_device = {
+       .name           = "sh_tmu",
+       .id             = 0,
+       .dev = {
+               .platform_data  = &tmu0_platform_data,
+       },
+       .resource       = tmu0_resources,
+       .num_resources  = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+       .name = "TMU1",
+       .channel_offset = 0x10,
+       .timer_bit = 1,
+       .clk = "module_clk",
+       .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+       [0] = {
+               .name   = "TMU1",
+               .start  = TMU1_BASE,
+               .end    = TMU1_BASE + 0xc - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_TUNI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device tmu1_device = {
+       .name           = "sh_tmu",
+       .id             = 1,
+       .dev = {
+               .platform_data  = &tmu1_platform_data,
+       },
+       .resource       = tmu1_resources,
+       .num_resources  = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+       .name = "TMU2",
+       .channel_offset = 0x1c,
+       .timer_bit = 2,
+       .clk = "module_clk",
+};
+
+static struct resource tmu2_resources[] = {
+       [0] = {
+               .name   = "TMU2",
+               .start  = TMU2_BASE,
+               .end    = TMU2_BASE + 0xc - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_TUNI2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device tmu2_device = {
+       .name           = "sh_tmu",
+       .id             = 2,
+       .dev = {
+               .platform_data  = &tmu2_platform_data,
+       },
+       .resource       = tmu2_resources,
+       .num_resources  = ARRAY_SIZE(tmu2_resources),
+};
+
+static struct platform_device *sh5_early_devices[] __initdata = {
+       &tmu0_device,
+       &tmu1_device,
+       &tmu2_device,
+};
+
 static struct platform_device *sh5_devices[] __initdata = {
        &sci_device,
        &rtc_device,
@@ -71,7 +176,20 @@ static struct platform_device *sh5_devices[] __initdata = {
 
 static int __init sh5_devices_setup(void)
 {
+       int ret;
+
+       ret = platform_add_devices(sh5_early_devices,
+                                  ARRAY_SIZE(sh5_early_devices));
+       if (unlikely(ret != 0))
+               return ret;
+
        return platform_add_devices(sh5_devices,
                                    ARRAY_SIZE(sh5_devices));
 }
 __initcall(sh5_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+       early_platform_add_devices(sh5_early_devices,
+                                  ARRAY_SIZE(sh5_early_devices));
+}
diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c
deleted file mode 100644 (file)
index b4fe770..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * arch/sh/kernel/time_64.c
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003 - 2007  Paul Mundt
- * Copyright (C) 2003  Richard Curnow
- *
- *    Original TMU/RTC code taken from sh version.
- *    Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
- *      Some code taken from i386 version.
- *      Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/errno.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-#include <linux/smp.h>
-#include <linux/module.h>
-#include <linux/bcd.h>
-#include <linux/timex.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <cpu/registers.h>      /* required by inline __asm__ stmt. */
-#include <cpu/irq.h>
-#include <asm/addrspace.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/clock.h>
-
-#define TMU_TOCR_INIT  0x00
-#define TMU0_TCR_INIT  0x0020
-#define TMU_TSTR_INIT  1
-#define TMU_TSTR_OFF   0
-
-/* Time Management Unit */
-#define        TMU_BLOCK_OFF   0x01020000
-#define TMU_BASE       PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
-#define TMU0_BASE      tmu_base + 0x8 + (0xc * 0x0)
-#define TMU1_BASE      tmu_base + 0x8 + (0xc * 0x1)
-#define TMU2_BASE      tmu_base + 0x8 + (0xc * 0x2)
-
-#define TMU_TOCR       tmu_base+0x0    /* Byte access */
-#define TMU_TSTR       tmu_base+0x4    /* Byte access */
-
-#define TMU0_TCOR      TMU0_BASE+0x0   /* Long access */
-#define TMU0_TCNT      TMU0_BASE+0x4   /* Long access */
-#define TMU0_TCR       TMU0_BASE+0x8   /* Word access */
-
-#define TICK_SIZE (tick_nsec / 1000)
-
-static unsigned long tmu_base;
-
-/* Variables to allow interpolation of time of day to resolution better than a
- * jiffy. */
-
-/* This is effectively protected by xtime_lock */
-static unsigned long ctc_last_interrupt;
-static unsigned long long usecs_per_jiffy = 1000000/HZ; /* Approximation */
-
-#define CTC_JIFFY_SCALE_SHIFT 40
-
-/* 2**CTC_JIFFY_SCALE_SHIFT / ctc_ticks_per_jiffy */
-static unsigned long long scaled_recip_ctc_ticks_per_jiffy;
-
-/* Estimate number of microseconds that have elapsed since the last timer tick,
-   by scaling the delta that has occurred in the CTC register.
-
-   WARNING WARNING WARNING : This algorithm relies on the CTC decrementing at
-   the CPU clock rate.  If the CPU sleeps, the CTC stops counting.  Bear this
-   in mind if enabling SLEEP_WORKS in process.c.  In that case, this algorithm
-   probably needs to use TMU.TCNT0 instead.  This will work even if the CPU is
-   sleeping, though will be coarser.
-
-   FIXME : What if usecs_per_tick is moving around too much, e.g. if an adjtime
-   is running or if the freq or tick arguments of adjtimex are modified after
-   we have calibrated the scaling factor?  This will result in either a jump at
-   the end of a tick period, or a wrap backwards at the start of the next one,
-   if the application is reading the time of day often enough.  I think we
-   ought to do better than this.  For this reason, usecs_per_jiffy is left
-   separated out in the calculation below.  This allows some future hook into
-   the adjtime-related stuff in kernel/timer.c to remove this hazard.
-
-*/
-
-static unsigned long usecs_since_tick(void)
-{
-       unsigned long long current_ctc;
-       long ctc_ticks_since_interrupt;
-       unsigned long long ull_ctc_ticks_since_interrupt;
-       unsigned long result;
-
-       unsigned long long mul1_out;
-       unsigned long long mul1_out_high;
-       unsigned long long mul2_out_low, mul2_out_high;
-
-       /* Read CTC register */
-       asm ("getcon cr62, %0" : "=r" (current_ctc));
-       /* Note, the CTC counts down on each CPU clock, not up.
-          Note(2), use long type to get correct wraparound arithmetic when
-          the counter crosses zero. */
-       ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc;
-       ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt;
-
-       /* Inline assembly to do 32x32x32->64 multiplier */
-       asm volatile ("mulu.l %1, %2, %0" :
-            "=r" (mul1_out) :
-            "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy));
-
-       mul1_out_high = mul1_out >> 32;
-
-       asm volatile ("mulu.l %1, %2, %0" :
-            "=r" (mul2_out_low) :
-            "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy));
-
-#if 1
-       asm volatile ("mulu.l %1, %2, %0" :
-            "=r" (mul2_out_high) :
-            "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy));
-#endif
-
-       result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT);
-
-       return result;
-}
-
-u32 arch_gettimeoffset(void)
-{
-       return usecs_since_tick() * 1000;
-}
-
-/* Dummy RTC ops */
-static void null_rtc_get_time(struct timespec *tv)
-{
-       tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
-       tv->tv_nsec = 0;
-}
-
-static int null_rtc_set_time(const time_t secs)
-{
-       return 0;
-}
-
-void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
-int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
-
-/* last time the RTC clock got updated */
-static long last_rtc_update;
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static inline void do_timer_interrupt(void)
-{
-       unsigned long long current_ctc;
-
-       if (current->pid)
-               profile_tick(CPU_PROFILING);
-
-       /*
-        * Here we are in the timer irq handler. We just have irqs locally
-        * disabled but we don't know if the timer_bh is running on the other
-        * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-        * the irq version of write_lock because as just said we have irq
-        * locally disabled. -arca
-        */
-       write_seqlock(&xtime_lock);
-       asm ("getcon cr62, %0" : "=r" (current_ctc));
-       ctc_last_interrupt = (unsigned long) current_ctc;
-
-       do_timer(1);
-
-       /*
-        * If we have an externally synchronized Linux clock, then update
-        * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-        * called as close as possible to 500 ms before the new second starts.
-        */
-       if (ntp_synced() &&
-           xtime.tv_sec > last_rtc_update + 660 &&
-           (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
-           (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-               if (rtc_sh_set_time(xtime.tv_sec) == 0)
-                       last_rtc_update = xtime.tv_sec;
-               else
-                       /* do it again in 60 s */
-                       last_rtc_update = xtime.tv_sec - 600;
-       }
-       write_sequnlock(&xtime_lock);
-
-#ifndef CONFIG_SMP
-       update_process_times(user_mode(get_irq_regs()));
-#endif
-}
-
-/*
- * This is the same as the above, except we _also_ save the current
- * Time Stamp Counter value at the time of the timer interrupt, so that
- * we later on can estimate the time of day more exactly.
- */
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-       unsigned long timer_status;
-
-       /* Clear UNF bit */
-       timer_status = ctrl_inw(TMU0_TCR);
-       timer_status &= ~0x100;
-       ctrl_outw(timer_status, TMU0_TCR);
-
-       do_timer_interrupt();
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction irq0  = {
-       .handler = timer_interrupt,
-       .flags = IRQF_DISABLED,
-       .name = "timer",
-};
-
-void __init time_init(void)
-{
-       unsigned long interval;
-       struct clk *clk;
-
-       tmu_base = (unsigned long)ioremap_nocache(TMU_BASE, 1024);
-       if (!tmu_base) {
-               panic("Unable to remap TMU\n");
-       }
-
-       clk = clk_get(NULL, "cpu_clk");
-       scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) /
-                       (unsigned long long)(clk_get_rate(clk) / HZ));
-
-       rtc_sh_get_time(&xtime);
-
-       setup_irq(TIMER_IRQ, &irq0);
-
-       clk = clk_get(NULL, "module_clk");
-       interval = (clk_get_rate(clk)/(HZ*4));
-
-       printk("Interval = %ld\n", interval);
-
-       /* Start TMU0 */
-       ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
-       ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
-       ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
-       ctrl_outl(interval, TMU0_TCOR);
-       ctrl_outl(interval, TMU0_TCNT);
-       ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-}