]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 9 May 2007 20:08:20 +0000 (13:08 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 9 May 2007 20:08:20 +0000 (13:08 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6:
  sh: Fix stacktrace simplification fallout.
  sh: SH7760 DMABRG support.
  sh: clockevent/clocksource/hrtimers/nohz TMU support.
  sh: Truncate MAX_ACTIVE_REGIONS for the common case.
  rtc: rtc-sh: Fix rtc_dev pointer for rtc_update_irq().
  sh: Convert to common die chain.
  sh: Wire up utimensat syscall.
  sh: landisk mv_nr_irqs definition.
  sh: Fixup ndelay() xloops calculation for alternate HZ.
  sh: Add 32-bit opcode feature CPU flag.
  sh: Fix PC adjustments for varying opcode length.
  sh: Support for SH-2A 32-bit opcodes.
  sh: Kill off redundant __div64_32 symbol export.
  sh: Share exception vector table for SH-3/4.
  sh: Always define TRAPA_BUG_OPCODE.
  sh: __GFP_REPEAT for pte allocations, too.
  rtc: rtc-sh: Fix up dev_dbg() warnings.
  sh: generic quicklist support.

36 files changed:
arch/sh/Kconfig
arch/sh/boards/landisk/setup.c
arch/sh/drivers/Makefile
arch/sh/drivers/dma/Kconfig
arch/sh/drivers/dma/Makefile
arch/sh/drivers/dma/dmabrg.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/Makefile
arch/sh/kernel/cpu/sh2a/opcode_helper.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/probe.c
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh4/Makefile
arch/sh/kernel/cpu/sh4/ex.S [deleted file]
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/process.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms.c
arch/sh/kernel/signal.c
arch/sh/kernel/stacktrace.c
arch/sh/kernel/syscalls.S
arch/sh/kernel/time.c
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/traps.c
arch/sh/lib/delay.c
arch/sh/mm/Kconfig
arch/sh/mm/fault.c
arch/sh/mm/init.c
drivers/rtc/rtc-sh.c
include/asm-sh/bug.h
include/asm-sh/cpu-features.h
include/asm-sh/dmabrg.h [new file with mode: 0644]
include/asm-sh/kdebug.h
include/asm-sh/pgalloc.h
include/asm-sh/system.h
include/asm-sh/timer.h
include/asm-sh/unistd.h
mm/Kconfig

index d74eb120a9c6b2255deb2812e8069b635f9b9a32..038179ecf6a904dd03fe65f9ab1d0654d4e2427a 100644 (file)
@@ -52,6 +52,9 @@ config GENERIC_IOMAP
 config GENERIC_TIME
        def_bool n
 
+config GENERIC_CLOCKEVENTS
+       def_bool n
+
 config SYS_SUPPORTS_APM_EMULATION
        bool
 
@@ -436,11 +439,11 @@ endmenu
 
 menu "Timer and clock configuration"
 
-if !GENERIC_TIME
-
 config SH_TMU
        bool "TMU timer support"
        depends on CPU_SH3 || CPU_SH4
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
        default y
        help
          This enables the use of the TMU as the system timer.
@@ -459,8 +462,6 @@ config SH_MTU2
        help
          This enables the use of the MTU2 as the system timer.
 
-endif
-
 config SH_TIMER_IRQ
        int
        default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
@@ -468,24 +469,6 @@ config SH_TIMER_IRQ
        default "140" if CPU_SUBTYPE_SH7206
        default "16"
 
-config NO_IDLE_HZ
-       bool "Dynamic tick timer"
-       help
-         Select this option if you want to disable continuous timer ticks
-         and have them programmed to occur as required. This option saves
-         power as the system can remain in idle state for longer.
-
-         By default dynamic tick is disabled during the boot, and can be
-         manually enabled with:
-
-           echo 1 > /sys/devices/system/timer/timer0/dyn_tick
-
-         Alternatively, if you want dynamic tick automatically enabled
-         during boot, pass "dyntick=enable" via the kernel command string.
-
-         Please note that dynamic tick may affect the accuracy of
-         timekeeping on some platforms depending on the implementation.
-
 config SH_PCLK_FREQ
        int "Peripheral clock frequency (in Hz)"
        default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
@@ -509,6 +492,8 @@ config SH_CLK_MD
        help
          MD2 - MD0 pin setting.
 
+source "kernel/time/Kconfig"
+
 endmenu
 
 menu "CPU Frequency scaling"
index a83a5d9587bb3532abd3c33ba4ee39f11f818e43..4058b4f50d44eda199717a64d09fc2e2169545ba 100644 (file)
@@ -93,6 +93,7 @@ static void __init landisk_setup(char **cmdline_p)
  */
 struct sh_machine_vector mv_landisk __initmv = {
        .mv_name = "LANDISK",
+       .mv_nr_irqs = 72,
        .mv_setup = landisk_setup,
        .mv_init_irq = init_landisk_IRQ,
 };
index 6cb92676c5fc4a51178a72524a61ee6d93ac7f11..e13f06bebd9221c9247d27754b0fcd396eb11e57 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for the Linux SuperH-specific device drivers.
 #
 
+obj-y          += dma/
+
 obj-$(CONFIG_PCI)              += pci/
-obj-$(CONFIG_SH_DMA)           += dma/
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_PUSH_SWITCH)      += push-switch.o
 obj-$(CONFIG_HEARTBEAT)                += heartbeat.o
index defc13c37d483c3d4b064f1035609546ba3d4633..99935f9daf4b89b53825eefdf7df3ae2546e4d10 100644 (file)
@@ -1,12 +1,12 @@
 menu "DMA support"
 
-config SH_DMA
-       bool "DMA controller (DMAC) support"
-       help
-         Selecting this option will provide same API as PC's Direct Memory
-         Access Controller(8237A) for SuperH DMAC.
+config SH_DMA_API
+       bool
 
-         If unsure, say N.
+config SH_DMA
+       bool "SuperH on-chip DMA controller (DMAC) support"
+       select SH_DMA_API
+       default n
 
 config NR_ONCHIP_DMA_CHANNELS
        depends on SH_DMA
@@ -53,4 +53,12 @@ config DMA_PAGE_OPS_CHANNEL
          in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
          are dual-address capable.
 
+config SH_DMABRG
+       bool "SH7760 DMABRG support"
+       depends on CPU_SUBTYPE_SH7760
+       help
+         The DMABRG does data transfers from main memory to Audio/USB units
+         of the SH7760.
+         Say Y if you want to use Audio/USB DMA on your SH7760 board.
+
 endmenu
index db1295d32268b51fdd393227bac89a0347004696..1ac812d2448837dd02ae30a784ab91d69554f349 100644 (file)
@@ -2,8 +2,8 @@
 # Makefile for the SuperH DMA specific kernel interface routines under Linux.
 #
 
-obj-y                          += dma-api.o
+obj-$(CONFIG_SH_DMA_API)       += dma-api.o dma-sysfs.o
 obj-$(CONFIG_ISA_DMA_API)      += dma-isa.o
-obj-$(CONFIG_SYSFS)            += dma-sysfs.o
 obj-$(CONFIG_SH_DMA)           += dma-sh.o
 obj-$(CONFIG_SH_DREAMCAST)     += dma-pvr2.o dma-g2.o
+obj-$(CONFIG_SH_DMABRG)                += dmabrg.o
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
new file mode 100644 (file)
index 0000000..9d0a293
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * SH7760 DMABRG IRQ handling
+ *
+ * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
+ *  licensed under the GPLv2.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/dma.h>
+#include <asm/dmabrg.h>
+#include <asm/io.h>
+
+/*
+ * The DMABRG is a special DMA unit within the SH7760. It does transfers
+ * from USB-SRAM/Audio units to main memory (and also the LCDC; but that
+ * part is sensibly placed  in the LCDC  registers and requires no irqs)
+ * It has 3 IRQ lines which trigger 10 events, and works independently
+ * from the traditional SH DMAC (although it blocks usage of DMAC 0)
+ *
+ * BRGIRQID   | component | dir | meaning      | source
+ * -----------------------------------------------------
+ *     0      | USB-DMA   | ... | xfer done    | DMABRGI1
+ *     1      | USB-UAE   | ... | USB addr err.| DMABRGI0
+ *     2      | HAC0/SSI0 | play| all done     | DMABRGI1
+ *     3      | HAC0/SSI0 | play| half done    | DMABRGI2
+ *     4      | HAC0/SSI0 | rec | all done     | DMABRGI1
+ *     5      | HAC0/SSI0 | rec | half done    | DMABRGI2
+ *     6      | HAC1/SSI1 | play| all done     | DMABRGI1
+ *     7      | HAC1/SSI1 | play| half done    | DMABRGI2
+ *     8      | HAC1/SSI1 | rec | all done     | DMABRGI1
+ *     9      | HAC1/SSI1 | rec | half done    | DMABRGI2
+ *
+ * all can be enabled/disabled in the DMABRGCR register,
+ * as well as checked if they occured.
+ *
+ * DMABRGI0 services  USB  DMA  Address  errors,  but it still must be
+ * enabled/acked in the DMABRGCR register.  USB-DMA complete indicator
+ * is grouped together with the audio buffer end indicators, too bad...
+ *
+ * DMABRGCR:   Bits 31-24: audio-dma ENABLE flags,
+ *             Bits 23-16: audio-dma STATUS flags,
+ *             Bits  9-8:  USB error/xfer ENABLE,
+ *             Bits  1-0:  USB error/xfer STATUS.
+ *     Ack an IRQ by writing 0 to the STATUS flag.
+ *     Mask IRQ by writing 0 to ENABLE flag.
+ *
+ * Usage is almost like with any other IRQ:
+ *  dmabrg_request_irq(BRGIRQID, handler, data)
+ *  dmabrg_free_irq(BRGIRQID)
+ *
+ * handler prototype:  void brgirqhandler(void *data)
+ */
+
+#define DMARSRA                0xfe090000
+#define DMAOR          0xffa00040
+#define DMACHCR0       0xffa0000c
+#define DMABRGCR       0xfe3c0000
+
+#define DMAOR_BRG      0x0000c000
+#define DMAOR_DMEN     0x00000001
+
+#define DMABRGI0       68
+#define DMABRGI1       69
+#define DMABRGI2       70
+
+struct dmabrg_handler {
+       void (*handler)(void *);
+       void *data;
+} *dmabrg_handlers;
+
+static inline void dmabrg_call_handler(int i)
+{
+       dmabrg_handlers[i].handler(dmabrg_handlers[i].data);
+}
+
+/*
+ * main DMABRG irq handler. It acks irqs and then
+ * handles every set and unmasked bit sequentially.
+ * No locking and no validity checks; it should be
+ * as fast as possible (audio!)
+ */
+static irqreturn_t dmabrg_irq(int irq, void *data)
+{
+       unsigned long dcr;
+       unsigned int i;
+
+       dcr = ctrl_inl(DMABRGCR);
+       ctrl_outl(dcr & ~0x00ff0003, DMABRGCR); /* ack all */
+       dcr &= dcr >> 8;        /* ignore masked */
+
+       /* USB stuff, get it out of the way first */
+       if (dcr & 1)
+               dmabrg_call_handler(DMABRGIRQ_USBDMA);
+       if (dcr & 2)
+               dmabrg_call_handler(DMABRGIRQ_USBDMAERR);
+
+       /* Audio */
+       dcr >>= 16;
+       while (dcr) {
+               i = __ffs(dcr);
+               dcr &= dcr - 1;
+               dmabrg_call_handler(i + DMABRGIRQ_A0TXF);
+       }
+       return IRQ_HANDLED;
+}
+
+static void dmabrg_disable_irq(unsigned int dmairq)
+{
+       unsigned long dcr;
+       dcr = ctrl_inl(DMABRGCR);
+       dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+       ctrl_outl(dcr, DMABRGCR);
+}
+
+static void dmabrg_enable_irq(unsigned int dmairq)
+{
+       unsigned long dcr;
+       dcr = ctrl_inl(DMABRGCR);
+       dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+       ctrl_outl(dcr, DMABRGCR);
+}
+
+int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*),
+                      void *data)
+{
+       if ((dmairq > 9) || !handler)
+               return -ENOENT;
+       if (dmabrg_handlers[dmairq].handler)
+               return -EBUSY;
+
+       dmabrg_handlers[dmairq].handler = handler;
+       dmabrg_handlers[dmairq].data = data;
+       
+       dmabrg_enable_irq(dmairq);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dmabrg_request_irq);
+
+void dmabrg_free_irq(unsigned int dmairq)
+{
+       if (likely(dmairq < 10)) {
+               dmabrg_disable_irq(dmairq);
+               dmabrg_handlers[dmairq].handler = NULL;
+               dmabrg_handlers[dmairq].data = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(dmabrg_free_irq);
+
+static int __init dmabrg_init(void)
+{
+       unsigned long or;
+       int ret;
+
+       dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler),
+                                 GFP_KERNEL);
+       if (!dmabrg_handlers)
+               return -ENOMEM;
+
+#ifdef CONFIG_SH_DMA
+       /* request DMAC channel 0 before anyone else can get it */
+       ret = request_dma(0, "DMAC 0 (DMABRG)");
+       if (ret < 0)
+               printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n");
+#endif
+
+       ctrl_outl(0, DMABRGCR);
+       ctrl_outl(0, DMACHCR0);
+       ctrl_outl(0x94000000, DMARSRA); /* enable DMABRG in DMAC 0 */
+
+       /* enable DMABRG mode, enable the DMAC */
+       or = ctrl_inl(DMAOR);
+       ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
+
+       ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
+                       "DMABRG USB address error", NULL);
+       if (ret)
+               goto out0;
+
+       ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED,
+                       "DMABRG Transfer End", NULL);
+       if (ret)
+               goto out1;
+
+       ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED,
+                       "DMABRG Transfer Half", NULL);
+       if (ret == 0)
+               return ret;
+
+       free_irq(DMABRGI1, 0);
+out1:  free_irq(DMABRGI0, 0);
+out0:  kfree(dmabrg_handlers);
+       return ret;
+}
+subsys_initcall(dmabrg_init);
index 350972ae9410df1e11b37658e6ce993817b6cc33..965fa2572b2368230bffb56ee00be7d8714eebdf 100644 (file)
@@ -2,9 +2,8 @@
 # Makefile for the Linux/SuperH SH-2A backends.
 #
 
-obj-y  := common.o probe.o
+obj-y  := common.o probe.o opcode_helper.o
 
-common-y       += $(addprefix ../sh2/, ex.o)
-common-y       += $(addprefix ../sh2/, entry.o)
+common-y       += $(addprefix ../sh2/, ex.o entry.o)
 
 obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
diff --git a/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
new file mode 100644 (file)
index 0000000..9704b79
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/opcode_helper.c
+ *
+ * Helper for the SH-2A 32-bit opcodes.
+ *
+ *  Copyright (C) 2007  Paul Mundt
+ *
+ * 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/kernel.h>
+#include <asm/system.h>
+
+/*
+ * Instructions on SH are generally fixed at 16-bits, however, SH-2A
+ * introduces some 32-bit instructions. Since there are no real
+ * constraints on their use (and they can be mixed and matched), we need
+ * to check the instruction encoding to work out if it's a true 32-bit
+ * instruction or not.
+ *
+ * Presently, 32-bit opcodes have only slight variations in what the
+ * actual encoding looks like in the first-half of the instruction, which
+ * makes it fairly straightforward to differentiate from the 16-bit ones.
+ *
+ * First 16-bits of encoding           Used by
+ *
+ *     0011nnnnmmmm0001        mov.b, mov.w, mov.l, fmov.d,
+ *                             fmov.s, movu.b, movu.w
+ *
+ *     0011nnnn0iii1001        bclr.b, bld.b, bset.b, bst.b, band.b,
+ *                             bandnot.b, bldnot.b, bor.b, bornot.b,
+ *                             bxor.b
+ *
+ *     0000nnnniiii0000        movi20
+ *     0000nnnniiii0001        movi20s
+ */
+unsigned int instruction_size(unsigned int insn)
+{
+       /* Look for the common cases */
+       switch ((insn & 0xf00f)) {
+       case 0x0000:    /* movi20 */
+       case 0x0001:    /* movi20s */
+       case 0x3001:    /* 32-bit mov/fmov/movu variants */
+               return 4;
+       }
+
+       /* And the special cases.. */
+       switch ((insn & 0xf08f)) {
+       case 0x3009:    /* 32-bit b*.b bit operations */
+               return 4;
+       }
+
+       return 2;
+}
index 426f6db01fc69d117621398e5be60f29a09f261a..f455c3509789b8ba5b4943e758b31b27d9626695 100644 (file)
@@ -18,6 +18,7 @@ int __init detect_cpu_and_cache_system(void)
 {
        /* Just SH7206 for now .. */
        current_cpu_data.type                   = CPU_SH7206;
+       current_cpu_data.flags                  |= CPU_HAS_OP32;
 
        current_cpu_data.dcache.ways            = 4;
        current_cpu_data.dcache.way_incr        = (1 << 11);
index ba3082d640b5f1d06191a7cc9671ee62a4bb111e..2b2a9e02fb752d1e358f41787369cb8731412501 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  arch/sh/kernel/cpu/sh3/ex.S
  *
- *  The SH-3 exception vector table.
+ *  The SH-3 and SH-4 exception vector table.
 
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  *  Copyright (C) 2003 - 2006  Paul Mundt
@@ -9,7 +9,6 @@
  * 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/linkage.h>
 
@@ -36,8 +35,12 @@ ENTRY(exception_handling_table)
        .long   exception_error ! address error load
        .long   exception_error ! address error store   /* 100 */
 #endif
-       .long   exception_error ! fpu_exception /* 120 */
-       .long   exception_error                 /* 140 */
+#if defined(CONFIG_SH_FPU)
+       .long   do_fpu_error            /* 120 */
+#else
+       .long   exception_error         /* 120 */
+#endif
+       .long   exception_error         /* 140 */
        .long   system_call     ! Unconditional Trap     /* 160 */
        .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
        .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
@@ -55,4 +58,4 @@ ENTRY(user_break_point_trap)
         * away offsets can be manually inserted in to their appropriate
         * location via set_exception_table_{evt,vec}().
         */
-       .balign 4096,0,4096
+       .balign 4096,0,4096
index 19ca68c71884176ed9f7f2230ab4618660842a47..8add10bd82683d5efd5064faee11b0746e146c61 100644 (file)
@@ -2,10 +2,10 @@
 # Makefile for the Linux/SuperH SH-4 backends.
 #
 
-obj-y  := ex.o probe.o common.o
-common-y       += $(addprefix ../sh3/, entry.o)
+obj-y  := probe.o common.o
+common-y       += $(addprefix ../sh3/, entry.o ex.o)
 
-obj-$(CONFIG_SH_FPU)                    += fpu.o
+obj-$(CONFIG_SH_FPU)                   += fpu.o
 obj-$(CONFIG_SH_STORE_QUEUES)          += sq.o
 
 # CPU subtype setup
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
deleted file mode 100644 (file)
index ac8ab57..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  arch/sh/kernel/cpu/sh4/ex.S
- *
- *  The SH-4 exception vector table.
-
- *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003 - 2006  Paul Mundt
- *
- * 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/linkage.h>
-
-       .align 2
-       .data
-
-ENTRY(exception_handling_table)
-       .long   exception_error         /* 000 */
-       .long   exception_error
-#if defined(CONFIG_MMU)
-       .long   tlb_miss_load           /* 040 */
-       .long   tlb_miss_store
-       .long   initial_page_write
-       .long   tlb_protection_violation_load
-       .long   tlb_protection_violation_store
-       .long   address_error_load
-       .long   address_error_store     /* 100 */
-#else
-       .long   exception_error ! tlb miss load         /* 040 */
-       .long   exception_error ! tlb miss store
-       .long   exception_error ! initial page write
-       .long   exception_error ! tlb prot violation load
-       .long   exception_error ! tlb prot violation store
-       .long   exception_error ! address error load
-       .long   exception_error ! address error store   /* 100 */
-#endif
-#if defined(CONFIG_SH_FPU)
-       .long   do_fpu_error            /* 120 */
-#else
-       .long   exception_error         /* 120 */
-#endif
-       .long   exception_error         /* 140 */
-       .long   system_call     ! Unconditional Trap     /* 160 */
-       .long   exception_error ! reserved_instruction (filled by trap_init) /* 180 */
-       .long   exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
-ENTRY(nmi_slot)
-#if defined (CONFIG_KGDB_NMI)
-       .long   debug_enter     /* 1C0 */       ! Allow trap to debugger
-#else
-       .long   exception_none  /* 1C0 */       ! Not implemented yet
-#endif
-ENTRY(user_break_point_trap)
-       .long   break_point_trap        /* 1E0 */
-
-       /*
-        * Pad the remainder of the table out, exceptions residing in far
-        * away offsets can be manually inserted in to their appropriate
-        * location via set_exception_table_{evt,vec}().
-        */
-       .balign 4096,0,4096
index 7624677f66281e7ef31b99d9b48caf1bc7534b5d..d61dd599169f97b0acb1f42fc9b19acc2dd26835 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/processor.h>
+#include <asm/system.h>
 #include <asm/io.h>
 
 /* The PR (precision) bit in the FP Status Register must be clear when
@@ -265,7 +266,7 @@ ieee_fpe_handler (struct pt_regs *regs)
                nextpc = regs->pr;
                finsn = *(unsigned short *) (regs->pc + 2);
        } else {
-               nextpc = regs->pc + 2;
+               nextpc = regs->pc + instruction_size(insn);
                finsn = insn;
        }
 
index 329b3f3051de9d53bb5b58b7418e595d11d74e09..6b4f5748d0be682a2b6334ca7d6f5ccc406be271 100644 (file)
 #include <linux/pm.h>
 #include <linux/kallsyms.h>
 #include <linux/kexec.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
+#include <linux/tick.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
 #include <asm/ubc.h>
 
 static int hlt_counter;
@@ -58,12 +61,15 @@ void cpu_idle(void)
                if (!idle)
                        idle = default_idle;
 
+               tick_nohz_stop_sched_tick();
                while (!need_resched())
                        idle();
+               tick_nohz_restart_sched_tick();
 
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
+               check_pgt_cache();
        }
 }
 
@@ -495,9 +501,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
        /* Rewind */
-       regs->pc -= 2;
+       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-       if (notify_die(DIE_TRAP, regs, regs->tra & 0xff,
+       if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff,
                       SIGTRAP) == NOTIFY_STOP)
                return;
 
@@ -514,9 +520,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 
        /* Rewind */
-       regs->pc -= 2;
+       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
 
-       if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff,
+       if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
                       SIGTRAP) == NOTIFY_STOP)
                return;
 
index 477d2a854fc4e4a59d0f83cec2341b8648b10fd1..c27729135935d77a8a4387fdb562e3bb86158357 100644 (file)
@@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c)
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
        "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-       "ptea", "llsc", "l2", NULL
+       "ptea", "llsc", "l2", "op32", NULL
 };
 
 static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
index fa91641c1f62c34a4eb0e478bc9654fec48ae585..c1cfcb9f047c1803f3e5564079bdba127f6509e4 100644 (file)
@@ -58,8 +58,6 @@ EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL(__div64_32);
-
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
 
 /* These symbols are generated by the compiler itself */
index eb0191c374b6839caffd65099899e7166c0d30e2..b32c35a7c0a3e42512765962e8b71c0c1096a5c8 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
-
+#include <asm/system.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -500,7 +500,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                                }
                        /* fallthrough */
                        case -ERESTARTNOINTR:
-                               regs->pc -= 2;
+                               regs->pc -= instruction_size(
+                                               ctrl_inw(regs->pc - 4));
+                               break;
                }
        } else {
                /* gUSA handling */
@@ -516,7 +518,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                        regs->regs[15] = regs->regs[1];
                        if (regs->pc < regs->regs[0])
                                /* Go to rewind point #1 */
-                               regs->pc = regs->regs[0] + offset - 2;
+                               regs->pc = regs->regs[0] + offset -
+                                       instruction_size(ctrl_inw(regs->pc-4));
                }
 #ifdef CONFIG_PREEMPT
                local_irq_restore(flags);
@@ -600,9 +603,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
                    regs->regs[0] == -ERESTARTSYS ||
                    regs->regs[0] == -ERESTARTNOINTR) {
                        regs->regs[0] = save_r0;
-                       regs->pc -= 2;
+                       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
                } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
-                       regs->pc -= 2;
+                       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
                        regs->regs[3] = __NR_restart_syscall;
                }
        }
index 4bdd2f83535da137635e7507b19f608592f0fd7a..d41e561be20eafacbacf9c99fd08a84d1f1e2321 100644 (file)
@@ -17,7 +17,7 @@
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
 {
        unsigned long *sp = (unsigned long *)current_stack_pointer;
 
index 38fc8cd3ea3a12fbe35dc6a014d12b651eab6795..4357d1a6358f61ba39a2ab7094fdfd968daec8aa 100644 (file)
@@ -354,3 +354,4 @@ ENTRY(sys_call_table)
        .long sys_move_pages
        .long sys_getcpu
        .long sys_epoll_pwait
+       .long sys_utimensat             /* 320 */
index d47e775962e955054f8e0296f4f3a5fdd65377e5..a3a67d151e520285b08c7fd58cc93d618e079fe6 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002 - 2006  Paul Mundt
+ *  Copyright (C) 2002 - 2007  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
  *
  *  Some code taken from i386 version.
@@ -15,6 +15,7 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
+#include <linux/clockchips.h>
 #include <asm/clock.h>
 #include <asm/rtc.h>
 #include <asm/timer.h>
@@ -38,6 +39,14 @@ static int null_rtc_set_time(const time_t secs)
        return 0;
 }
 
+/*
+ * Null high precision timer functions for systems lacking one.
+ */
+static cycle_t null_hpt_read(void)
+{
+       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;
 
@@ -101,6 +110,7 @@ int do_settimeofday(struct timespec *tv)
 EXPORT_SYMBOL(do_settimeofday);
 #endif /* !CONFIG_GENERIC_TIME */
 
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
@@ -138,6 +148,7 @@ void handle_timer_tick(void)
                        last_rtc_update = xtime.tv_sec - 600;
        }
 }
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 #ifdef CONFIG_PM
 int timer_suspend(struct sys_device *dev, pm_message_t state)
@@ -168,136 +179,58 @@ static struct sysdev_class timer_sysclass = {
        .resume  = timer_resume,
 };
 
-#ifdef CONFIG_NO_IDLE_HZ
-static int timer_dyn_tick_enable(void)
+static int __init timer_init_sysfs(void)
 {
-       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-       unsigned long flags;
-       int ret = -ENODEV;
-
-       if (dyn_tick) {
-               spin_lock_irqsave(&dyn_tick->lock, flags);
-               ret = 0;
-               if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
-                       ret = dyn_tick->enable();
-
-                       if (ret == 0)
-                               dyn_tick->state |= DYN_TICK_ENABLED;
-               }
-               spin_unlock_irqrestore(&dyn_tick->lock, flags);
-       }
+       int ret = sysdev_class_register(&timer_sysclass);
+       if (ret != 0)
+               return ret;
 
-       return ret;
+       sys_timer->dev.cls = &timer_sysclass;
+       return sysdev_register(&sys_timer->dev);
 }
+device_initcall(timer_init_sysfs);
 
-static int timer_dyn_tick_disable(void)
-{
-       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-       unsigned long flags;
-       int ret = -ENODEV;
-
-       if (dyn_tick) {
-               spin_lock_irqsave(&dyn_tick->lock, flags);
-               ret = 0;
-               if (dyn_tick->state & DYN_TICK_ENABLED) {
-                       ret = dyn_tick->disable();
-
-                       if (ret == 0)
-                               dyn_tick->state &= ~DYN_TICK_ENABLED;
-               }
-               spin_unlock_irqrestore(&dyn_tick->lock, flags);
-       }
-
-       return ret;
-}
+void (*board_time_init)(void);
 
 /*
- * Reprogram the system timer for at least the calculated time interval.
- * This function should be called from the idle thread with IRQs disabled,
- * immediately before sleeping.
+ * Shamelessly based on the MIPS and Sparc64 work.
  */
-void timer_dyn_reprogram(void)
-{
-       struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
-       unsigned long next, seq, flags;
-
-       if (!dyn_tick)
-               return;
-
-       spin_lock_irqsave(&dyn_tick->lock, flags);
-       if (dyn_tick->state & DYN_TICK_ENABLED) {
-               next = next_timer_interrupt();
-               do {
-                       seq = read_seqbegin(&xtime_lock);
-                       dyn_tick->reprogram(next - jiffies);
-               } while (read_seqretry(&xtime_lock, seq));
-       }
-       spin_unlock_irqrestore(&dyn_tick->lock, flags);
-}
+static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
+unsigned long sh_hpt_frequency = 0;
+
+#define NSEC_PER_CYC_SHIFT     10
+
+struct clocksource clocksource_sh = {
+       .name           = "SuperH",
+       .rating         = 200,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .read           = null_hpt_read,
+       .shift          = 16,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
 
-static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
+static void __init init_sh_clocksource(void)
 {
-       return sprintf(buf, "%i\n",
-                      (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
-}
+       if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read)
+               return;
 
-static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
-                                 size_t count)
-{
-       unsigned int enable = simple_strtoul(buf, NULL, 2);
+       clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency,
+                                                 clocksource_sh.shift);
 
-       if (enable)
-               timer_dyn_tick_enable();
-       else
-               timer_dyn_tick_disable();
+       timer_ticks_per_nsec_quotient =
+               clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT);
 
-       return count;
+       clocksource_register(&clocksource_sh);
 }
-static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
 
-/*
- * dyntick=enable|disable
- */
-static char dyntick_str[4] __initdata = "";
-
-static int __init dyntick_setup(char *str)
+#ifdef CONFIG_GENERIC_TIME
+unsigned long long sched_clock(void)
 {
-       if (str)
-               strlcpy(dyntick_str, str, sizeof(dyntick_str));
-       return 1;
+       unsigned long long ticks = clocksource_sh.read();
+       return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT;
 }
-
-__setup("dyntick=", dyntick_setup);
-#endif
-
-static int __init timer_init_sysfs(void)
-{
-       int ret = sysdev_class_register(&timer_sysclass);
-       if (ret != 0)
-               return ret;
-
-       sys_timer->dev.cls = &timer_sysclass;
-       ret = sysdev_register(&sys_timer->dev);
-
-#ifdef CONFIG_NO_IDLE_HZ
-       if (ret == 0 && sys_timer->dyn_tick) {
-               ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
-
-               /*
-                * Turn on dynamic tick after calibrate delay
-                * for correct bogomips
-                */
-               if (ret == 0 && dyntick_str[0] == 'e')
-                       ret = timer_dyn_tick_enable();
-       }
 #endif
 
-       return ret;
-}
-device_initcall(timer_init_sysfs);
-
-void (*board_time_init)(void);
-
 void __init time_init(void)
 {
        if (board_time_init)
@@ -316,10 +249,15 @@ void __init time_init(void)
        sys_timer = get_sys_timer();
        printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
 
-#ifdef CONFIG_NO_IDLE_HZ
-       if (sys_timer->dyn_tick)
-               spin_lock_init(&sys_timer->dyn_tick->lock);
-#endif
+       if (sys_timer->ops->read)
+               clocksource_sh.read = sys_timer->ops->read;
+
+       init_sh_clocksource();
+
+       if (sh_hpt_frequency)
+               printk("Using %lu.%03lu MHz high precision timer.\n",
+                      ((sh_hpt_frequency + 500) / 1000) / 1000,
+                      ((sh_hpt_frequency + 500) / 1000) % 1000);
 
 #if defined(CONFIG_SH_KGDB)
        /*
index d9e3151c891e9cd197aaa87e4f6efe2d7f81e73c..2d997e2a5b6cc6a0961810c8b02beb49df44efac 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
  *
- *  Copyright (C) 2005  Paul Mundt
+ *  Copyright (C) 2005 - 2007  Paul Mundt
  *
  * TMU handling code hacked out of arch/sh/kernel/time.c
  *
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/seqlock.h>
+#include <linux/clockchips.h>
 #include <asm/timer.h>
 #include <asm/rtc.h>
 #include <asm/io.h>
 #include <asm/clock.h>
 
 #define TMU_TOCR_INIT  0x00
-#define TMU0_TCR_INIT  0x0020
-#define TMU_TSTR_INIT  1
+#define TMU_TCR_INIT   0x0020
 
-#define TMU0_TCR_CALIB 0x0000
+static int tmu_timer_start(void)
+{
+       ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
+       return 0;
+}
 
-static unsigned long tmu_timer_get_offset(void)
+static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
 {
-       int count;
-       static int count_p = 0x7fffffff;    /* for the first call after boot */
-       static unsigned long jiffies_p = 0;
+       ctrl_outl(interval, TMU0_TCNT);
 
        /*
-        * cache volatile jiffies temporarily; we have IRQs turned off.
+        * TCNT reloads from TCOR on underflow, clear it if we don't
+        * intend to auto-reload
         */
-       unsigned long jiffies_t;
+       if (reload)
+               ctrl_outl(interval, TMU0_TCOR);
+       else
+               ctrl_outl(0, TMU0_TCOR);
 
-       /* timer count may underflow right here */
-       count = ctrl_inl(TMU0_TCNT);    /* read the latched count */
+       tmu_timer_start();
+}
 
-       jiffies_t = jiffies;
+static int tmu_timer_stop(void)
+{
+       ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
+       return 0;
+}
 
-       /*
-        * avoiding timer inconsistencies (they are rare, but they happen)...
-        * there is one kind of problem that must be avoided here:
-        *  1. the timer counter underflows
-        */
+static cycle_t tmu_timer_read(void)
+{
+       return ~ctrl_inl(TMU1_TCNT);
+}
+
+static int tmu_set_next_event(unsigned long cycles,
+                             struct clock_event_device *evt)
+{
+       tmu0_timer_set_interval(cycles, 1);
+       return 0;
+}
 
-       if (jiffies_t == jiffies_p) {
-               if (count > count_p) {
-                       /* the nutcase */
-                       if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
-                               count -= LATCH;
-                       } else {
-                               printk("%s (): hardware timer problem?\n",
-                                      __FUNCTION__);
-                       }
-               }
-       } else
-               jiffies_p = jiffies_t;
-
-       count_p = count;
-
-       count = ((LATCH-1) - count) * TICK_SIZE;
-       count = (count + LATCH/2) / LATCH;
-
-       return count;
+static void tmu_set_mode(enum clock_event_mode mode,
+                        struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               ctrl_outl(0, TMU0_TCOR);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               break;
+       }
 }
 
+static struct clock_event_device tmu0_clockevent = {
+       .name           = "tmu0",
+       .shift          = 32,
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = tmu_set_mode,
+       .set_next_event = tmu_set_next_event,
+};
+
 static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 {
+       struct clock_event_device *evt = &tmu0_clockevent;
        unsigned long timer_status;
 
        /* Clear UNF bit */
@@ -82,72 +102,76 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
        timer_status &= ~0x100;
        ctrl_outw(timer_status, TMU0_TCR);
 
-       /*
-        * 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);
-       handle_timer_tick();
-       write_sequnlock(&xtime_lock);
+       evt->event_handler(evt);
 
        return IRQ_HANDLED;
 }
 
-static struct irqaction tmu_irq = {
-       .name           = "timer",
+static struct irqaction tmu0_irq = {
+       .name           = "periodic timer",
        .handler        = tmu_timer_interrupt,
        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .mask           = CPU_MASK_NONE,
 };
 
-static void tmu_clk_init(struct clk *clk)
+static void tmu0_clk_init(struct clk *clk)
 {
-       u8 divisor = TMU0_TCR_INIT & 0x7;
-       ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
+       u8 divisor = TMU_TCR_INIT & 0x7;
+       ctrl_outw(TMU_TCR_INIT, TMU0_TCR);
        clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static void tmu_clk_recalc(struct clk *clk)
+static void tmu0_clk_recalc(struct clk *clk)
 {
        u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
        clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static struct clk_ops tmu_clk_ops = {
-       .init           = tmu_clk_init,
-       .recalc         = tmu_clk_recalc,
+static struct clk_ops tmu0_clk_ops = {
+       .init           = tmu0_clk_init,
+       .recalc         = tmu0_clk_recalc,
 };
 
 static struct clk tmu0_clk = {
        .name           = "tmu0_clk",
-       .ops            = &tmu_clk_ops,
+       .ops            = &tmu0_clk_ops,
 };
 
-static int tmu_timer_start(void)
+static void tmu1_clk_init(struct clk *clk)
 {
-       ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-       return 0;
+       u8 divisor = TMU_TCR_INIT & 0x7;
+       ctrl_outw(divisor, TMU1_TCR);
+       clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
-static int tmu_timer_stop(void)
+static void tmu1_clk_recalc(struct clk *clk)
 {
-       ctrl_outb(0, TMU_TSTR);
-       return 0;
+       u8 divisor = ctrl_inw(TMU1_TCR) & 0x7;
+       clk->rate = clk->parent->rate / (4 << (divisor << 1));
 }
 
+static struct clk_ops tmu1_clk_ops = {
+       .init           = tmu1_clk_init,
+       .recalc         = tmu1_clk_recalc,
+};
+
+static struct clk tmu1_clk = {
+       .name           = "tmu1_clk",
+       .ops            = &tmu1_clk_ops,
+};
+
 static int tmu_timer_init(void)
 {
        unsigned long interval;
+       unsigned long frequency;
 
-       setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
+       setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq);
 
        tmu0_clk.parent = clk_get(NULL, "module_clk");
+       tmu1_clk.parent = clk_get(NULL, "module_clk");
 
-       /* Start TMU0 */
        tmu_timer_stop();
+
 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7760) && \
     !defined(CONFIG_CPU_SUBTYPE_SH7785)
@@ -155,15 +179,29 @@ static int tmu_timer_init(void)
 #endif
 
        clk_register(&tmu0_clk);
+       clk_register(&tmu1_clk);
        clk_enable(&tmu0_clk);
+       clk_enable(&tmu1_clk);
 
-       interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
-       printk(KERN_INFO "Interval = %ld\n", interval);
+       frequency = clk_get_rate(&tmu0_clk);
+       interval = (frequency + HZ / 2) / HZ;
 
-       ctrl_outl(interval, TMU0_TCOR);
-       ctrl_outl(interval, TMU0_TCNT);
+       sh_hpt_frequency = clk_get_rate(&tmu1_clk);
+       ctrl_outl(~0, TMU1_TCNT);
+       ctrl_outl(~0, TMU1_TCOR);
 
-       tmu_timer_start();
+       tmu0_timer_set_interval(interval, 1);
+
+       tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
+                                     tmu0_clockevent.shift);
+       tmu0_clockevent.max_delta_ns =
+                       clockevent_delta2ns(-1, &tmu0_clockevent);
+       tmu0_clockevent.min_delta_ns =
+                       clockevent_delta2ns(1, &tmu0_clockevent);
+
+       tmu0_clockevent.cpumask = cpumask_of_cpu(0);
+
+       clockevents_register_device(&tmu0_clockevent);
 
        return 0;
 }
@@ -172,9 +210,7 @@ struct sys_timer_ops tmu_timer_ops = {
        .init           = tmu_timer_init,
        .start          = tmu_timer_start,
        .stop           = tmu_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
-       .get_offset     = tmu_timer_get_offset,
-#endif
+       .read           = tmu_timer_read,
 };
 
 struct sys_timer tmu_timer = {
index 7b40f0ff3dfc8701a8121dfddaaf3f9044db97c0..3a197649cd83c6c57227156fbcdd6d06e86ef7a2 100644 (file)
 #include <linux/io.h>
 #include <linux/bug.h>
 #include <linux/debug_locks.h>
+#include <linux/kdebug.h>
 #include <linux/limits.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/kdebug.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -76,20 +76,6 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
        }
 }
 
-ATOMIC_NOTIFIER_HEAD(shdie_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
 static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -505,7 +491,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
  simple:
        ret = handle_unaligned_ins(instruction,regs);
        if (ret==0)
-               regs->pc += 2;
+               regs->pc += instruction_size(instruction);
        return ret;
 }
 #endif /* CONFIG_CPU_SH2A */
@@ -682,7 +668,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
 
        err = do_fpu_inst(inst, regs);
        if (!err) {
-               regs->pc += 2;
+               regs->pc += instruction_size(inst);
                return;
        }
        /* not a FPU inst. */
index 351714694d6d4b9b6f81d183e774f1fc47e0e215..f3ddd2133e6f4edffb5a7fc7958350d9d1c2f680 100644 (file)
@@ -24,9 +24,10 @@ inline void __const_udelay(unsigned long xloops)
        __asm__("dmulu.l        %0, %2\n\t"
                "sts    mach, %0"
                : "=r" (xloops)
-               : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy)
+               : "0" (xloops),
+                 "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy)
                : "macl", "mach");
-       __delay(xloops * HZ);
+       __delay(xloops);
 }
 
 void __udelay(unsigned long usecs)
index 12f3d394dc28e97df806d7884cb92b890f681e92..253346d7b316fc1bd3a934f6e37c8b038c18a303 100644 (file)
@@ -218,6 +218,9 @@ endmenu
 
 menu "Memory management options"
 
+config QUICKLIST
+       def_bool y
+
 config MMU
         bool "Support for memory management hardware"
        depends on !CPU_SH2
@@ -300,6 +303,10 @@ config NODES_SHIFT
 config ARCH_FLATMEM_ENABLE
        def_bool y
 
+config MAX_ACTIVE_REGIONS
+       int
+       default "1"
+
 config ARCH_POPULATES_NODE_MAP
        def_bool y
 
index 0ecc117cade4525042e98b8240e1a0ebcda9b882..9207da67ff8a669841170bc73b600f9782d3037d 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
index 4d030988b3681b3102e859d1f4464afbd23cdef8..8fe223a890ed4aaedf8947493f947041e4bed535 100644 (file)
@@ -67,6 +67,8 @@ void show_mem(void)
        printk("%d slab pages\n", slab);
        printk("%d pages shared\n", shared);
        printk("%d pages swap cached\n", cached);
+       printk(KERN_INFO "Total of %ld pages in page table cache\n",
+              quicklist_total_size());
 }
 
 #ifdef CONFIG_MMU
index 6abf4811958c3969270fb09e3f8fffd23b656013..e0f91dfce0f56bcb8f340058d208557e613a44dd 100644 (file)
@@ -104,7 +104,7 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
 
        writeb(tmp, rtc->regbase + RCR1);
 
-       rtc_update_irq(&rtc->rtc_dev, 1, events);
+       rtc_update_irq(rtc->rtc_dev, 1, events);
 
        spin_unlock(&rtc->lock);
 
@@ -139,7 +139,7 @@ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
 
                rtc->rearm_aie = 1;
 
-               rtc_update_irq(&rtc->rtc_dev, 1, events);
+               rtc_update_irq(rtc->rtc_dev, 1, events);
        }
 
        spin_unlock(&rtc->lock);
@@ -153,7 +153,7 @@ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
 
        spin_lock(&rtc->lock);
 
-       rtc_update_irq(&rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+       rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
 
        spin_unlock(&rtc->lock);
 
@@ -341,7 +341,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
                tm->tm_sec--;
 #endif
 
-       dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+       dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
                __FUNCTION__,
                tm->tm_sec, tm->tm_min, tm->tm_hour,
index 794c36daf06da9e3530ee167a87958cc1672048a..46f925c815aca9918823e4b23607b1e50e833cd4 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
+#define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
+
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_WARN_ON
 
-#define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
-
 /**
  * _EMIT_BUG_ENTRY
  * %1 - __FILE__
index 4bccd7c032f9c3d2320c8c7735b7fb5a0d02937b..86308aa3973180867a7b30a2f95e43f6137e54c2 100644 (file)
@@ -20,5 +20,6 @@
 #define CPU_HAS_PTEA           0x0020  /* PTEA register */
 #define CPU_HAS_LLSC           0x0040  /* movli.l/movco.l */
 #define CPU_HAS_L2_CACHE       0x0080  /* Secondary cache / URAM */
+#define CPU_HAS_OP32           0x0100  /* 32-bit instruction support */
 
 #endif /* __ASM_SH_CPU_FEATURES_H */
diff --git a/include/asm-sh/dmabrg.h b/include/asm-sh/dmabrg.h
new file mode 100644 (file)
index 0000000..c5edba2
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SH7760 DMABRG (USB/Audio) support
+ */
+
+#ifndef _DMABRG_H_
+#define _DMABRG_H_
+
+/* IRQ sources */
+#define DMABRGIRQ_USBDMA       0
+#define DMABRGIRQ_USBDMAERR    1
+#define DMABRGIRQ_A0TXF                2
+#define DMABRGIRQ_A0TXH                3
+#define DMABRGIRQ_A0RXF                4
+#define DMABRGIRQ_A0RXH                5
+#define DMABRGIRQ_A1TXF                6
+#define DMABRGIRQ_A1TXH                7
+#define DMABRGIRQ_A1RXF                8
+#define DMABRGIRQ_A1RXH                9
+
+extern int dmabrg_request_irq(unsigned int, void(*)(void *), void *);
+extern void dmabrg_free_irq(unsigned int);
+
+#endif
index 493c206297479adb4ffdb7f14457c0e8b8338c13..16578b7c9da12cf3ac7a2100ebaeea7e287fce73 100644 (file)
@@ -2,20 +2,6 @@
 #define __ASM_SH_KDEBUG_H
 
 #include <linux/notifier.h>
-#include <asm-generic/kdebug.h>
-
-struct pt_regs;
-
-struct die_args {
-       struct pt_regs *regs;
-       int trapnr;
-};
-
-int register_die_notifier(struct notifier_block *nb);
-int unregister_die_notifier(struct notifier_block *nb);
-int register_page_fault_notifier(struct notifier_block *nb);
-int unregister_page_fault_notifier(struct notifier_block *nb);
-extern struct atomic_notifier_head shdie_chain;
 
 /* Grossly misnamed. */
 enum die_val {
@@ -23,14 +9,7 @@ enum die_val {
        DIE_PAGE_FAULT,
 };
 
-static inline int notify_die(enum die_val val, struct pt_regs *regs,
-                            int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .trapnr = trap,
-       };
+int register_page_fault_notifier(struct notifier_block *nb);
+int unregister_page_fault_notifier(struct notifier_block *nb);
 
-       return atomic_notifier_call_chain(&shdie_chain, val, &args);
-}
 #endif /* __ASM_SH_KDEBUG_H */
index 888e4529e6fe3c4bb2108f134b8b7674435836c3..18b613c57cf5118a8ea6fc452d0a0230ff4d50bf 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef __ASM_SH_PGALLOC_H
 #define __ASM_SH_PGALLOC_H
 
+#include <linux/quicklist.h>
+#include <asm/page.h>
+
+#define QUICK_PGD 0    /* We preserve special mappings over free */
+#define QUICK_PT 1     /* Other page table pages that are zero on free */
+
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
                                       pte_t *pte)
 {
@@ -13,48 +19,49 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
        set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
 }
 
+static inline void pgd_ctor(void *x)
+{
+       pgd_t *pgd = x;
+
+       memcpy(pgd + USER_PTRS_PER_PGD,
+              swapper_pg_dir + USER_PTRS_PER_PGD,
+              (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+}
+
 /*
  * Allocate and free page tables.
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
-
-       if (pgd) {
-               memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-               memcpy(pgd + USER_PTRS_PER_PGD,
-                      swapper_pg_dir + USER_PTRS_PER_PGD,
-                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-       }
-
-       return pgd;
+       return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
-       free_page((unsigned long)pgd);
+       quicklist_free(QUICK_PGD, NULL, pgd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
 }
 
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
                                         unsigned long address)
 {
-       return alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       void *pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+       return pg ? virt_to_page(pg) : NULL;
 }
 
 static inline void pte_free_kernel(pte_t *pte)
 {
-       free_page((unsigned long)pte);
+       quicklist_free(QUICK_PT, NULL, pte);
 }
 
 static inline void pte_free(struct page *pte)
 {
-       __free_page(pte);
+       quicklist_free_page(QUICK_PT, NULL, pte);
 }
 
 #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
@@ -66,6 +73,11 @@ static inline void pte_free(struct page *pte)
 
 #define pmd_free(x)                    do { } while (0)
 #define __pmd_free_tlb(tlb,x)          do { } while (0)
-#define check_pgt_cache()              do { } while (0)
+
+static inline void check_pgt_cache(void)
+{
+       quicklist_trim(QUICK_PGD, NULL, 25, 16);
+       quicklist_trim(QUICK_PT, NULL, 25, 16);
+}
 
 #endif /* __ASM_SH_PGALLOC_H */
index e7e96ee0c8a5470e39f044e6067dcf8de8dea7a4..82f3e229e62135c2e944e1fbbe5e316744e2c4c1 100644 (file)
@@ -255,6 +255,15 @@ static inline void *set_exception_table_evt(unsigned int evt, void *handler)
        return set_exception_table_vec(evt >> 5, handler);
 }
 
+/*
+ * SH-2A has both 16 and 32-bit opcodes, do lame encoding checks.
+ */
+#ifdef CONFIG_CPU_SH2A
+extern unsigned int instruction_size(unsigned int insn);
+#else
+#define instruction_size(insn) (2)
+#endif
+
 /* XXX
  * disable hlt during certain critical i/o operations
  */
index 17b5e76a4c3131471599b52bb3aea12ce78aad43..701ba84c7049305dd1e763efe671bfbf15ed9439 100644 (file)
@@ -2,12 +2,14 @@
 #define __ASM_SH_TIMER_H
 
 #include <linux/sysdev.h>
+#include <linux/clocksource.h>
 #include <asm/cpu/timer.h>
 
 struct sys_timer_ops {
        int (*init)(void);
        int (*start)(void);
        int (*stop)(void);
+       cycle_t (*read)(void);
 #ifndef CONFIG_GENERIC_TIME
        unsigned long (*get_offset)(void);
 #endif
@@ -18,29 +20,8 @@ struct sys_timer {
 
        struct sys_device       dev;
        struct sys_timer_ops    *ops;
-
-#ifdef CONFIG_NO_IDLE_HZ
-       struct dyn_tick_timer   *dyn_tick;
-#endif
 };
 
-#ifdef CONFIG_NO_IDLE_HZ
-#define DYN_TICK_ENABLED       (1 << 1)
-
-struct dyn_tick_timer {
-       spinlock_t      lock;
-       unsigned int    state;                  /* Current state */
-       int             (*enable)(void);        /* Enables dynamic tick */
-       int             (*disable)(void);       /* Disables dynamic tick */
-       void            (*reprogram)(unsigned long); /* Reprograms the timer */
-       int             (*handler)(int, void *);
-};
-
-void timer_dyn_reprogram(void);
-#else
-#define timer_dyn_reprogram()  do { } while (0)
-#endif
-
 #define TICK_SIZE (tick_nsec / 1000)
 
 extern struct sys_timer tmu_timer, cmt_timer, mtu2_timer;
@@ -58,5 +39,7 @@ struct sys_timer *get_sys_timer(void);
 
 /* arch/sh/kernel/time.c */
 void handle_timer_tick(void);
+extern unsigned long sh_hpt_frequency;
+extern struct clocksource clocksource_sh;
 
 #endif /* __ASM_SH_TIMER_H */
index 49be50a36b77dc3dc02dad61892100051f030377..af71e379a5eea94097e029e44e555ab5b3c4cd40 100644 (file)
@@ -85,7 +85,7 @@
 #define __NR_sigpending                 73
 #define __NR_sethostname        74
 #define __NR_setrlimit          75
-#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
+#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
 #define __NR_getrusage          77
 #define __NR_gettimeofday       78
 #define __NR_settimeofday       79
 #define __NR_move_pages                317
 #define __NR_getcpu            318
 #define __NR_epoll_pwait       319
+#define __NR_utimensat         320
 
-#define NR_syscalls 320
+#define NR_syscalls 321
 
 #ifdef __KERNEL__
 
index 1ac718f636ec6f5842217bd6b06c7ef0bff0dd21..a17da8bafe62758b6f0d86816d9d6c64b464e687 100644 (file)
@@ -166,5 +166,5 @@ config ZONE_DMA_FLAG
 config NR_QUICK
        int
        depends on QUICKLIST
+       default "2" if SUPERH
        default "1"
-