ソースを参照

Merge branch 'sh-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* 'sh-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6:
  sh: include Migo-R TS driver in Migo-R defconfig
  sh: correct definitions to access stack pointers
  sh: Tidy up SH-4A unaligned load support.
  dma: shdma: NMI support.
  sh: mach-sdk7786: Handle baseboard NMI source selection.
  sh: mach-rsk: Add polled GPIO buttons support for RSK+7203.
  sh: Break out cpuinfo_op procfs bits.
  sh: Enable optional gpiolib for all CPUs with pinmux tables.
  sh: migrate SH_CLK_MD to mode pin API.
  sh: machvec IO death.
Linus Torvalds 14 年 前
コミット
9858a38ea3

+ 10 - 10
arch/sh/Kconfig

@@ -162,7 +162,8 @@ config ARCH_HAS_CPU_IDLE_WAIT
 	def_bool y
 
 config NO_IOPORT
-	bool
+	def_bool !PCI
+	depends on !SH_CAYMAN && !SH_SH4202_MICRODEV
 
 config IO_TRAPPED
 	bool
@@ -275,6 +276,7 @@ config CPU_SUBTYPE_SH7203
 	select CPU_HAS_FPU
 	select SYS_SUPPORTS_CMT
 	select SYS_SUPPORTS_MTU2
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config CPU_SUBTYPE_SH7206
 	bool "Support SH7206 processor"
@@ -346,6 +348,7 @@ config CPU_SUBTYPE_SH7720
 	select CPU_SH3
 	select CPU_HAS_DSP
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Select SH7720 if you have a SH3-DSP SH7720 CPU.
 
@@ -408,6 +411,7 @@ config CPU_SUBTYPE_SH7723
 	select ARCH_SHMOBILE
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Select SH7723 if you have an SH-MobileR2 CPU.
 
@@ -418,6 +422,7 @@ config CPU_SUBTYPE_SH7724
 	select ARCH_SHMOBILE
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Select SH7724 if you have an SH-MobileR2R CPU.
 
@@ -425,6 +430,7 @@ config CPU_SUBTYPE_SH7757
 	bool "Support SH7757 processor"
 	select CPU_SH4A
 	select CPU_SHX2
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Select SH7757 if you have a SH4A SH7757 CPU.
 
@@ -448,6 +454,7 @@ config CPU_SUBTYPE_SH7785
 	select CPU_SHX2
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config CPU_SUBTYPE_SH7786
 	bool "Support SH7786 processor"
@@ -455,6 +462,7 @@ config CPU_SUBTYPE_SH7786
 	select CPU_SHX3
 	select CPU_HAS_PTEAEX
 	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config CPU_SUBTYPE_SHX3
 	bool "Support SH-X3 processor"
@@ -479,6 +487,7 @@ config CPU_SUBTYPE_SH7722
 	select ARCH_SPARSEMEM_ENABLE
 	select SYS_SUPPORTS_NUMA
 	select SYS_SUPPORTS_CMT
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config CPU_SUBTYPE_SH7366
 	bool "Support SH7366 processor"
@@ -568,15 +577,6 @@ config SH_CLK_CPG_LEGACY
 	def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
 		      !CPU_SHX3 && !CPU_SUBTYPE_SH7757
 
-config SH_CLK_MD
-	int "CPU Mode Pin Setting"
-	depends on CPU_SH2
-	default 6 if CPU_SUBTYPE_SH7206
-	default 5 if CPU_SUBTYPE_SH7619
-	default 0
-	help
-	  MD2 - MD0 pin setting.
-
 source "kernel/time/Kconfig"
 
 endmenu

+ 0 - 2
arch/sh/boards/board-secureedge5410.c

@@ -29,8 +29,6 @@ unsigned short secureedge5410_ioport;
  */
 static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id)
 {
-	ctrl_delay();	/* dummy read */
-
 	printk("SnapGear: erase switch interrupt!\n");
 
 	return IRQ_HANDLED;

+ 36 - 1
arch/sh/boards/mach-rsk/devices-rsk7203.c

@@ -1,7 +1,7 @@
 /*
  * Renesas Technology Europe RSK+ 7203 Support.
  *
- * Copyright (C) 2008 Paul Mundt
+ * Copyright (C) 2008 - 2010  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
@@ -12,7 +12,9 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/smsc911x.h>
+#include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
 #include <linux/leds.h>
 #include <asm/machvec.h>
 #include <asm/io.h>
@@ -84,9 +86,42 @@ static struct platform_device led_device = {
 	},
 };
 
+static struct gpio_keys_button rsk7203_gpio_keys_table[] = {
+	{
+		.code		= BTN_0,
+		.gpio		= GPIO_PB0,
+		.active_low	= 1,
+		.desc		= "SW1",
+	}, {
+		.code		= BTN_1,
+		.gpio		= GPIO_PB1,
+		.active_low	= 1,
+		.desc		= "SW2",
+	}, {
+		.code		= BTN_2,
+		.gpio		= GPIO_PB2,
+		.active_low	= 1,
+		.desc		= "SW3",
+	},
+};
+
+static struct gpio_keys_platform_data rsk7203_gpio_keys_info = {
+	.buttons	= rsk7203_gpio_keys_table,
+	.nbuttons	= ARRAY_SIZE(rsk7203_gpio_keys_table),
+	.poll_interval	= 50, /* default to 50ms */
+};
+
+static struct platform_device keys_device = {
+	.name		= "gpio-keys-polled",
+	.dev		= {
+		.platform_data	= &rsk7203_gpio_keys_info,
+	},
+};
+
 static struct platform_device *rsk7203_devices[] __initdata = {
 	&smsc911x_device,
 	&led_device,
+	&keys_device,
 };
 
 static int __init rsk7203_devices_setup(void)

+ 1 - 1
arch/sh/boards/mach-sdk7786/Makefile

@@ -1,4 +1,4 @@
-obj-y	:= fpga.o irq.o setup.o
+obj-y	:= fpga.o irq.o nmi.o setup.o
 
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_HAVE_SRAM_POOL)	+= sram.o

+ 83 - 0
arch/sh/boards/mach-sdk7786/nmi.c

@@ -0,0 +1,83 @@
+/*
+ * SDK7786 FPGA NMI Support.
+ *
+ * Copyright (C) 2010  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/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <mach/fpga.h>
+
+enum {
+	NMI_MODE_MANUAL,
+	NMI_MODE_AUX,
+	NMI_MODE_MASKED,
+	NMI_MODE_ANY,
+	NMI_MODE_UNKNOWN,
+};
+
+/*
+ * Default to the manual NMI switch.
+ */
+static unsigned int __initdata nmi_mode = NMI_MODE_ANY;
+
+static int __init nmi_mode_setup(char *str)
+{
+	if (!str)
+		return 0;
+
+	if (strcmp(str, "manual") == 0)
+		nmi_mode = NMI_MODE_MANUAL;
+	else if (strcmp(str, "aux") == 0)
+		nmi_mode = NMI_MODE_AUX;
+	else if (strcmp(str, "masked") == 0)
+		nmi_mode = NMI_MODE_MASKED;
+	else if (strcmp(str, "any") == 0)
+		nmi_mode = NMI_MODE_ANY;
+	else {
+		nmi_mode = NMI_MODE_UNKNOWN;
+		pr_warning("Unknown NMI mode %s\n", str);
+	}
+
+	printk("Set NMI mode to %d\n", nmi_mode);
+	return 0;
+}
+early_param("nmi_mode", nmi_mode_setup);
+
+void __init sdk7786_nmi_init(void)
+{
+	unsigned int source, mask, tmp;
+
+	switch (nmi_mode) {
+	case NMI_MODE_MANUAL:
+		source = NMISR_MAN_NMI;
+		mask = NMIMR_MAN_NMIM;
+		break;
+	case NMI_MODE_AUX:
+		source = NMISR_AUX_NMI;
+		mask = NMIMR_AUX_NMIM;
+		break;
+	case NMI_MODE_ANY:
+		source = NMISR_MAN_NMI | NMISR_AUX_NMI;
+		mask = NMIMR_MAN_NMIM | NMIMR_AUX_NMIM;
+		break;
+	case NMI_MODE_MASKED:
+	case NMI_MODE_UNKNOWN:
+	default:
+		source = mask = 0;
+		break;
+	}
+
+	/* Set the NMI source */
+	tmp = fpga_read_reg(NMISR);
+	tmp &= ~NMISR_MASK;
+	tmp |= source;
+	fpga_write_reg(tmp, NMISR);
+
+	/* And the IRQ masking */
+	fpga_write_reg(NMIMR_MASK ^ mask, NMIMR);
+}

+ 1 - 0
arch/sh/boards/mach-sdk7786/setup.c

@@ -237,6 +237,7 @@ static void __init sdk7786_setup(char **cmdline_p)
 	pr_info("Renesas Technology Europe SDK7786 support:\n");
 
 	sdk7786_fpga_init();
+	sdk7786_nmi_init();
 
 	pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf);
 

+ 6 - 0
arch/sh/boards/mach-se/7206/setup.c

@@ -79,6 +79,11 @@ static int __init se7206_devices_setup(void)
 }
 __initcall(se7206_devices_setup);
 
+static int se7206_mode_pins(void)
+{
+	return MODE_PIN1 | MODE_PIN2;
+}
+
 /*
  * The Machine Vector
  */
@@ -87,4 +92,5 @@ static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 256,
 	.mv_init_irq		= init_se7206_IRQ,
+	.mv_mode_pins		= se7206_mode_pins,
 };

+ 6 - 0
arch/sh/boards/mach-se/board-se7619.c

@@ -11,6 +11,11 @@
 #include <asm/io.h>
 #include <asm/machvec.h>
 
+static int se7619_mode_pins(void)
+{
+	return MODE_PIN2 | MODE_PIN0;
+}
+
 /*
  * The Machine Vector
  */
@@ -18,4 +23,5 @@
 static struct sh_machine_vector mv_se __initmv = {
 	.mv_name		= "SolutionEngine",
 	.mv_nr_irqs		= 108,
+	.mv_mode_pins		= se7619_mode_pins,
 };

+ 2 - 0
arch/sh/configs/migor_defconfig

@@ -54,6 +54,8 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_SH_KEYSC=y
 # CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MIGOR=y
 # CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_SH_SCI=y

+ 1 - 2
arch/sh/drivers/pci/pci.c

@@ -382,14 +382,13 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev,
 	struct pci_channel *chan = dev->sysdata;
 
 	if (unlikely(!chan->io_map_base)) {
-		chan->io_map_base = generic_io_base;
+		chan->io_map_base = sh_io_port_base;
 
 		if (pci_domains_supported)
 			panic("To avoid data corruption io_map_base MUST be "
 			      "set with multiple PCI domains.");
 	}
 
-
 	return (void __iomem *)(chan->io_map_base + port);
 }
 

+ 180 - 165
arch/sh/include/asm/io.h

@@ -1,5 +1,6 @@
 #ifndef __ASM_SH_IO_H
 #define __ASM_SH_IO_H
+
 /*
  * Convention:
  *    read{b,w,l,q}/write{b,w,l,q} are for PCI,
@@ -15,12 +16,6 @@
  * SuperH specific I/O (raw I/O to on-chip CPU peripherals). In practice
  * these have the same semantics as the __raw variants, and as such, all
  * new code should be using the __raw versions.
- *
- * All ISA I/O routines are wrapped through the machine vector. If a
- * board does not provide overrides, a generic set that are copied in
- * from the default machine vector are used instead. These are largely
- * for old compat code for I/O offseting to SuperIOs, all of which are
- * better handled through the machvec ioport mapping routines these days.
  */
 #include <linux/errno.h>
 #include <asm/cache.h>
@@ -31,39 +26,10 @@
 #include <asm-generic/iomap.h>
 
 #ifdef __KERNEL__
-/*
- * Depending on which platform we are running on, we need different
- * I/O functions.
- */
-#define __IO_PREFIX	generic
+#define __IO_PREFIX     generic
 #include <asm/io_generic.h>
 #include <asm/io_trapped.h>
 
-#ifdef CONFIG_HAS_IOPORT
-
-#define inb(p)			sh_mv.mv_inb((p))
-#define inw(p)			sh_mv.mv_inw((p))
-#define inl(p)			sh_mv.mv_inl((p))
-#define outb(x,p)		sh_mv.mv_outb((x),(p))
-#define outw(x,p)		sh_mv.mv_outw((x),(p))
-#define outl(x,p)		sh_mv.mv_outl((x),(p))
-
-#define inb_p(p)		sh_mv.mv_inb_p((p))
-#define inw_p(p)		sh_mv.mv_inw_p((p))
-#define inl_p(p)		sh_mv.mv_inl_p((p))
-#define outb_p(x,p)		sh_mv.mv_outb_p((x),(p))
-#define outw_p(x,p)		sh_mv.mv_outw_p((x),(p))
-#define outl_p(x,p)		sh_mv.mv_outl_p((x),(p))
-
-#define insb(p,b,c)		sh_mv.mv_insb((p), (b), (c))
-#define insw(p,b,c)		sh_mv.mv_insw((p), (b), (c))
-#define insl(p,b,c)		sh_mv.mv_insl((p), (b), (c))
-#define outsb(p,b,c)		sh_mv.mv_outsb((p), (b), (c))
-#define outsw(p,b,c)		sh_mv.mv_outsw((p), (b), (c))
-#define outsl(p,b,c)		sh_mv.mv_outsl((p), (b), (c))
-
-#endif
-
 #define __raw_writeb(v,a)	(__chk_io_ptr(a), *(volatile u8  __force *)(a) = (v))
 #define __raw_writew(v,a)	(__chk_io_ptr(a), *(volatile u16 __force *)(a) = (v))
 #define __raw_writel(v,a)	(__chk_io_ptr(a), *(volatile u32 __force *)(a) = (v))
@@ -74,68 +40,39 @@
 #define __raw_readl(a)		(__chk_io_ptr(a), *(volatile u32 __force *)(a))
 #define __raw_readq(a)		(__chk_io_ptr(a), *(volatile u64 __force *)(a))
 
-#define readb(a)		({ u8  r_ = __raw_readb(a); mb(); r_; })
-#define readw(a)		({ u16 r_ = __raw_readw(a); mb(); r_; })
-#define readl(a)		({ u32 r_ = __raw_readl(a); mb(); r_; })
-#define readq(a)		({ u64 r_ = __raw_readq(a); mb(); r_; })
-
-#define writeb(v,a)		({ __raw_writeb((v),(a)); mb(); })
-#define writew(v,a)		({ __raw_writew((v),(a)); mb(); })
-#define writel(v,a)		({ __raw_writel((v),(a)); mb(); })
-#define writeq(v,a)		({ __raw_writeq((v),(a)); mb(); })
-
-/*
- * Legacy SuperH on-chip I/O functions
- *
- * These are all deprecated, all new (and especially cross-platform) code
- * should be using the __raw_xxx() routines directly.
- */
-static inline u8 __deprecated ctrl_inb(unsigned long addr)
-{
-	return __raw_readb(addr);
-}
-
-static inline u16 __deprecated ctrl_inw(unsigned long addr)
-{
-	return __raw_readw(addr);
-}
-
-static inline u32 __deprecated ctrl_inl(unsigned long addr)
-{
-	return __raw_readl(addr);
-}
-
-static inline u64 __deprecated ctrl_inq(unsigned long addr)
-{
-	return __raw_readq(addr);
-}
-
-static inline void __deprecated ctrl_outb(u8 v, unsigned long addr)
-{
-	__raw_writeb(v, addr);
-}
-
-static inline void __deprecated ctrl_outw(u16 v, unsigned long addr)
-{
-	__raw_writew(v, addr);
-}
-
-static inline void __deprecated ctrl_outl(u32 v, unsigned long addr)
-{
-	__raw_writel(v, addr);
-}
-
-static inline void __deprecated ctrl_outq(u64 v, unsigned long addr)
-{
-	__raw_writeq(v, addr);
-}
-
-extern unsigned long generic_io_base;
-
-static inline void ctrl_delay(void)
-{
-	__raw_readw(generic_io_base);
-}
+#define readb_relaxed(c)	({ u8  __v = __raw_readb(c); __v; })
+#define readw_relaxed(c)	({ u16 __v = le16_to_cpu((__force __le16) \
+					__raw_readw(c)); __v; })
+#define readl_relaxed(c)	({ u32 __v = le32_to_cpu((__force __le32) \
+					__raw_readl(c)); __v; })
+#define readq_relaxed(c)	({ u64 __v = le64_to_cpu((__force __le64) \
+					__raw_readq(c)); __v; })
+
+#define writeb_relaxed(v,c)	((void)__raw_writeb(v,c))
+#define writew_relaxed(v,c)	((void)__raw_writew((__force u16) \
+					cpu_to_le16(v),c))
+#define writel_relaxed(v,c)	((void)__raw_writel((__force u32) \
+					cpu_to_le32(v),c))
+#define writeq_relaxed(v,c)	((void)__raw_writeq((__force u64) \
+					cpu_to_le64(v),c))
+
+#define readb(a)		({ u8  r_ = readb_relaxed(a); rmb(); r_; })
+#define readw(a)		({ u16 r_ = readw_relaxed(a); rmb(); r_; })
+#define readl(a)		({ u32 r_ = readl_relaxed(a); rmb(); r_; })
+#define readq(a)		({ u64 r_ = readq_relaxed(a); rmb(); r_; })
+
+#define writeb(v,a)		({ wmb(); writeb_relaxed((v),(a)); })
+#define writew(v,a)		({ wmb(); writew_relaxed((v),(a)); })
+#define writel(v,a)		({ wmb(); writel_relaxed((v),(a)); })
+#define writeq(v,a)		({ wmb(); writeq_relaxed((v),(a)); })
+
+#define readsb(p,d,l)		__raw_readsb(p,d,l)
+#define readsw(p,d,l)		__raw_readsw(p,d,l)
+#define readsl(p,d,l)		__raw_readsl(p,d,l)
+
+#define writesb(p,d,l)		__raw_writesb(p,d,l)
+#define writesw(p,d,l)		__raw_writesw(p,d,l)
+#define writesl(p,d,l)		__raw_writesl(p,d,l)
 
 #define __BUILD_UNCACHED_IO(bwlq, type)					\
 static inline type read##bwlq##_uncached(unsigned long addr)		\
@@ -159,10 +96,11 @@ __BUILD_UNCACHED_IO(w, u16)
 __BUILD_UNCACHED_IO(l, u32)
 __BUILD_UNCACHED_IO(q, u64)
 
-#define __BUILD_MEMORY_STRING(bwlq, type)				\
+#define __BUILD_MEMORY_STRING(pfx, bwlq, type)				\
 									\
-static inline void __raw_writes##bwlq(volatile void __iomem *mem,	\
-				const void *addr, unsigned int count)	\
+static inline void							\
+pfx##writes##bwlq(volatile void __iomem *mem, const void *addr,		\
+		  unsigned int count)					\
 {									\
 	const volatile type *__addr = addr;				\
 									\
@@ -172,8 +110,8 @@ static inline void __raw_writes##bwlq(volatile void __iomem *mem,	\
 	}								\
 }									\
 									\
-static inline void __raw_reads##bwlq(volatile void __iomem *mem,	\
-			       void *addr, unsigned int count)		\
+static inline void pfx##reads##bwlq(volatile void __iomem *mem,		\
+				    void *addr, unsigned int count)	\
 {									\
 	volatile type *__addr = addr;					\
 									\
@@ -183,85 +121,166 @@ static inline void __raw_reads##bwlq(volatile void __iomem *mem,	\
 	}								\
 }
 
-__BUILD_MEMORY_STRING(b, u8)
-__BUILD_MEMORY_STRING(w, u16)
+__BUILD_MEMORY_STRING(__raw_, b, u8)
+__BUILD_MEMORY_STRING(__raw_, w, u16)
 
 #ifdef CONFIG_SUPERH32
 void __raw_writesl(void __iomem *addr, const void *data, int longlen);
 void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 #else
-__BUILD_MEMORY_STRING(l, u32)
+__BUILD_MEMORY_STRING(__raw_, l, u32)
 #endif
 
-__BUILD_MEMORY_STRING(q, u64)
-
-#define writesb			__raw_writesb
-#define writesw			__raw_writesw
-#define writesl			__raw_writesl
-
-#define readsb			__raw_readsb
-#define readsw			__raw_readsw
-#define readsl			__raw_readsl
-
-#define readb_relaxed(a)	readb(a)
-#define readw_relaxed(a)	readw(a)
-#define readl_relaxed(a)	readl(a)
-#define readq_relaxed(a)	readq(a)
-
-#ifndef CONFIG_GENERIC_IOMAP
-/* Simple MMIO */
-#define ioread8(a)		__raw_readb(a)
-#define ioread16(a)		__raw_readw(a)
-#define ioread16be(a)		be16_to_cpu(__raw_readw((a)))
-#define ioread32(a)		__raw_readl(a)
-#define ioread32be(a)		be32_to_cpu(__raw_readl((a)))
-
-#define iowrite8(v,a)		__raw_writeb((v),(a))
-#define iowrite16(v,a)		__raw_writew((v),(a))
-#define iowrite16be(v,a)	__raw_writew(cpu_to_be16((v)),(a))
-#define iowrite32(v,a)		__raw_writel((v),(a))
-#define iowrite32be(v,a)	__raw_writel(cpu_to_be32((v)),(a))
-
-#define ioread8_rep(a, d, c)	__raw_readsb((a), (d), (c))
-#define ioread16_rep(a, d, c)	__raw_readsw((a), (d), (c))
-#define ioread32_rep(a, d, c)	__raw_readsl((a), (d), (c))
-
-#define iowrite8_rep(a, s, c)	__raw_writesb((a), (s), (c))
-#define iowrite16_rep(a, s, c)	__raw_writesw((a), (s), (c))
-#define iowrite32_rep(a, s, c)	__raw_writesl((a), (s), (c))
+__BUILD_MEMORY_STRING(__raw_, q, u64)
+
+#ifdef CONFIG_HAS_IOPORT
+
+/*
+ * Slowdown I/O port space accesses for antique hardware.
+ */
+#undef CONF_SLOWDOWN_IO
+
+/*
+ * On SuperH I/O ports are memory mapped, so we access them using normal
+ * load/store instructions. sh_io_port_base is the virtual address to
+ * which all ports are being mapped.
+ */
+extern const unsigned long sh_io_port_base;
+
+static inline void __set_io_port_base(unsigned long pbase)
+{
+	*(unsigned long *)&sh_io_port_base = pbase;
+	barrier();
+}
+
+#ifdef CONFIG_GENERIC_IOMAP
+#define __ioport_map ioport_map
+#else
+extern void __iomem *__ioport_map(unsigned long addr, unsigned int size);
 #endif
 
-#define mmio_insb(p,d,c)	__raw_readsb(p,d,c)
-#define mmio_insw(p,d,c)	__raw_readsw(p,d,c)
-#define mmio_insl(p,d,c)	__raw_readsl(p,d,c)
+#ifdef CONF_SLOWDOWN_IO
+#define SLOW_DOWN_IO __raw_readw(sh_io_port_base)
+#else
+#define SLOW_DOWN_IO
+#endif
 
-#define mmio_outsb(p,s,c)	__raw_writesb(p,s,c)
-#define mmio_outsw(p,s,c)	__raw_writesw(p,s,c)
-#define mmio_outsl(p,s,c)	__raw_writesl(p,s,c)
+#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow)			\
+									\
+static inline void pfx##out##bwlq##p(type val, unsigned long port)	\
+{									\
+	volatile type *__addr;						\
+									\
+	__addr = __ioport_map(port, sizeof(type));			\
+	*__addr = val;							\
+	slow;								\
+}									\
+									\
+static inline type pfx##in##bwlq##p(unsigned long port)			\
+{									\
+	volatile type *__addr;						\
+	type __val;							\
+									\
+	__addr = __ioport_map(port, sizeof(type));			\
+	__val = *__addr;						\
+	slow;								\
+									\
+	return __val;							\
+}
 
-/* synco on SH-4A, otherwise a nop */
-#define mmiowb()		wmb()
+#define __BUILD_IOPORT_PFX(bus, bwlq, type)				\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, ,)			\
+	__BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO)
 
-#define IO_SPACE_LIMIT 0xffffffff
+#define BUILDIO_IOPORT(bwlq, type)					\
+	__BUILD_IOPORT_PFX(, bwlq, type)
 
-#ifdef CONFIG_HAS_IOPORT
+BUILDIO_IOPORT(b, u8)
+BUILDIO_IOPORT(w, u16)
+BUILDIO_IOPORT(l, u32)
+BUILDIO_IOPORT(q, u64)
+
+#define __BUILD_IOPORT_STRING(bwlq, type)				\
+									\
+static inline void outs##bwlq(unsigned long port, const void *addr,	\
+			      unsigned int count)			\
+{									\
+	const volatile type *__addr = addr;				\
+									\
+	while (count--) {						\
+		out##bwlq(*__addr, port);				\
+		__addr++;						\
+	}								\
+}									\
+									\
+static inline void ins##bwlq(unsigned long port, void *addr,		\
+			     unsigned int count)			\
+{									\
+	volatile type *__addr = addr;					\
+									\
+	while (count--) {						\
+		*__addr = in##bwlq(port);				\
+		__addr++;						\
+	}								\
+}
+
+__BUILD_IOPORT_STRING(b, u8)
+__BUILD_IOPORT_STRING(w, u16)
+__BUILD_IOPORT_STRING(l, u32)
+__BUILD_IOPORT_STRING(q, u64)
+
+#endif
 
 /*
- * This function provides a method for the generic case where a
- * board-specific ioport_map simply needs to return the port + some
- * arbitrary port base.
+ * Legacy SuperH on-chip I/O functions
  *
- * We use this at board setup time to implicitly set the port base, and
- * as a result, we can use the generic ioport_map.
+ * These are all deprecated, all new (and especially cross-platform) code
+ * should be using the __raw_xxx() routines directly.
  */
-static inline void __set_io_port_base(unsigned long pbase)
+static inline u8 __deprecated ctrl_inb(unsigned long addr)
 {
-	generic_io_base = pbase;
+	return __raw_readb(addr);
 }
 
-#define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n))
+static inline u16 __deprecated ctrl_inw(unsigned long addr)
+{
+	return __raw_readw(addr);
+}
 
-#endif
+static inline u32 __deprecated ctrl_inl(unsigned long addr)
+{
+	return __raw_readl(addr);
+}
+
+static inline u64 __deprecated ctrl_inq(unsigned long addr)
+{
+	return __raw_readq(addr);
+}
+
+static inline void __deprecated ctrl_outb(u8 v, unsigned long addr)
+{
+	__raw_writeb(v, addr);
+}
+
+static inline void __deprecated ctrl_outw(u16 v, unsigned long addr)
+{
+	__raw_writew(v, addr);
+}
+
+static inline void __deprecated ctrl_outl(u32 v, unsigned long addr)
+{
+	__raw_writel(v, addr);
+}
+
+static inline void __deprecated ctrl_outq(u64 v, unsigned long addr)
+{
+	__raw_writeq(v, addr);
+}
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* synco on SH-4A, otherwise a nop */
+#define mmiowb()		wmb()
 
 /* We really want to try and get these to memcpy etc */
 void memcpy_fromio(void *, const volatile void __iomem *, unsigned long);
@@ -395,10 +414,6 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; }
 #define ioremap_nocache	ioremap
 #define iounmap		__iounmap
 
-#define maybebadio(port) \
-	printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
-	       __func__, __LINE__, (port), (u32)__builtin_return_address(0))
-
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access

+ 0 - 25
arch/sh/include/asm/io_generic.h

@@ -11,31 +11,6 @@
 #error "Don't include this header without a valid system prefix"
 #endif
 
-u8 IO_CONCAT(__IO_PREFIX,inb)(unsigned long);
-u16 IO_CONCAT(__IO_PREFIX,inw)(unsigned long);
-u32 IO_CONCAT(__IO_PREFIX,inl)(unsigned long);
-
-void IO_CONCAT(__IO_PREFIX,outb)(u8, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outw)(u16, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outl)(u32, unsigned long);
-
-u8 IO_CONCAT(__IO_PREFIX,inb_p)(unsigned long);
-u16 IO_CONCAT(__IO_PREFIX,inw_p)(unsigned long);
-u32 IO_CONCAT(__IO_PREFIX,inl_p)(unsigned long);
-void IO_CONCAT(__IO_PREFIX,outb_p)(u8, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outw_p)(u16, unsigned long);
-void IO_CONCAT(__IO_PREFIX,outl_p)(u32, unsigned long);
-
-void IO_CONCAT(__IO_PREFIX,insb)(unsigned long, void *dst, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,insw)(unsigned long, void *dst, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,insl)(unsigned long, void *dst, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,outsb)(unsigned long, const void *src, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,outsw)(unsigned long, const void *src, unsigned long count);
-void IO_CONCAT(__IO_PREFIX,outsl)(unsigned long, const void *src, unsigned long count);
-
-void *IO_CONCAT(__IO_PREFIX,ioremap)(unsigned long offset, unsigned long size);
-void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr);
-
 void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size);
 void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr);
 void IO_CONCAT(__IO_PREFIX,mem_init)(void);

+ 0 - 21
arch/sh/include/asm/machvec.h

@@ -23,27 +23,6 @@ struct sh_machine_vector {
 	void (*mv_init_irq)(void);
 
 #ifdef CONFIG_HAS_IOPORT
-	u8 (*mv_inb)(unsigned long);
-	u16 (*mv_inw)(unsigned long);
-	u32 (*mv_inl)(unsigned long);
-	void (*mv_outb)(u8, unsigned long);
-	void (*mv_outw)(u16, unsigned long);
-	void (*mv_outl)(u32, unsigned long);
-
-	u8 (*mv_inb_p)(unsigned long);
-	u16 (*mv_inw_p)(unsigned long);
-	u32 (*mv_inl_p)(unsigned long);
-	void (*mv_outb_p)(u8, unsigned long);
-	void (*mv_outw_p)(u16, unsigned long);
-	void (*mv_outl_p)(u32, unsigned long);
-
-	void (*mv_insb)(unsigned long, void *dst, unsigned long count);
-	void (*mv_insw)(unsigned long, void *dst, unsigned long count);
-	void (*mv_insl)(unsigned long, void *dst, unsigned long count);
-	void (*mv_outsb)(unsigned long, const void *src, unsigned long count);
-	void (*mv_outsw)(unsigned long, const void *src, unsigned long count);
-	void (*mv_outsl)(unsigned long, const void *src, unsigned long count);
-
 	void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
 	void (*mv_ioport_unmap)(void __iomem *);
 #endif

+ 2 - 2
arch/sh/include/asm/ptrace.h

@@ -40,8 +40,8 @@
 #include <asm/system.h>
 
 #define user_mode(regs)			(((regs)->sr & 0x40000000)==0)
-#define user_stack_pointer(regs)	((unsigned long)(regs)->regs[15])
-#define kernel_stack_pointer(regs)	((unsigned long)(regs)->regs[15])
+#define user_stack_pointer(_regs)	((unsigned long)(_regs)->regs[15])
+#define kernel_stack_pointer(_regs)	((unsigned long)(_regs)->regs[15])
 #define instruction_pointer(regs)	((unsigned long)(regs)->pc)
 
 extern void show_regs(struct pt_regs *);

+ 1 - 1
arch/sh/include/asm/ptrace_32.h

@@ -76,7 +76,7 @@ struct pt_dspregs {
 #ifdef __KERNEL__
 
 #define MAX_REG_OFFSET		offsetof(struct pt_regs, tra)
-#define regs_return_value(regs)	((regs)->regs[0])
+#define regs_return_value(_regs)	((_regs)->regs[0])
 
 #endif /* __KERNEL__ */
 

+ 1 - 1
arch/sh/include/asm/ptrace_64.h

@@ -13,7 +13,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 
 #define MAX_REG_OFFSET		offsetof(struct pt_regs, tregs[7])
-#define regs_return_value(regs)	((regs)->regs[3])
+#define regs_return_value(_regs)	((_regs)->regs[3])
 
 #endif /* __KERNEL__ */
 

+ 52 - 112
arch/sh/include/asm/unaligned-sh4a.h

@@ -18,10 +18,20 @@
  * of spill registers and blowing up when building at low optimization
  * levels. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34777.
  */
+#include <linux/unaligned/packed_struct.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
-static __always_inline u32 __get_unaligned_cpu32(const u8 *p)
+static inline u16 sh4a_get_unaligned_cpu16(const u8 *p)
+{
+#ifdef __LITTLE_ENDIAN
+	return p[0] | p[1] << 8;
+#else
+	return p[0] << 8 | p[1];
+#endif
+}
+
+static __always_inline u32 sh4a_get_unaligned_cpu32(const u8 *p)
 {
 	unsigned long unaligned;
 
@@ -34,218 +44,148 @@ static __always_inline u32 __get_unaligned_cpu32(const u8 *p)
 	return unaligned;
 }
 
-struct __una_u16 { u16 x __attribute__((packed)); };
-struct __una_u32 { u32 x __attribute__((packed)); };
-struct __una_u64 { u64 x __attribute__((packed)); };
-
-static inline u16 __get_unaligned_cpu16(const u8 *p)
-{
-#ifdef __LITTLE_ENDIAN
-	return p[0] | p[1] << 8;
-#else
-	return p[0] << 8 | p[1];
-#endif
-}
-
 /*
  * Even though movua.l supports auto-increment on the read side, it can
  * only store to r0 due to instruction encoding constraints, so just let
  * the compiler sort it out on its own.
  */
-static inline u64 __get_unaligned_cpu64(const u8 *p)
+static inline u64 sh4a_get_unaligned_cpu64(const u8 *p)
 {
 #ifdef __LITTLE_ENDIAN
-	return (u64)__get_unaligned_cpu32(p + 4) << 32 |
-		    __get_unaligned_cpu32(p);
+	return (u64)sh4a_get_unaligned_cpu32(p + 4) << 32 |
+		    sh4a_get_unaligned_cpu32(p);
 #else
-	return (u64)__get_unaligned_cpu32(p) << 32 |
-		    __get_unaligned_cpu32(p + 4);
+	return (u64)sh4a_get_unaligned_cpu32(p) << 32 |
+		    sh4a_get_unaligned_cpu32(p + 4);
 #endif
 }
 
 static inline u16 get_unaligned_le16(const void *p)
 {
-	return le16_to_cpu(__get_unaligned_cpu16(p));
+	return le16_to_cpu(sh4a_get_unaligned_cpu16(p));
 }
 
 static inline u32 get_unaligned_le32(const void *p)
 {
-	return le32_to_cpu(__get_unaligned_cpu32(p));
+	return le32_to_cpu(sh4a_get_unaligned_cpu32(p));
 }
 
 static inline u64 get_unaligned_le64(const void *p)
 {
-	return le64_to_cpu(__get_unaligned_cpu64(p));
+	return le64_to_cpu(sh4a_get_unaligned_cpu64(p));
 }
 
 static inline u16 get_unaligned_be16(const void *p)
 {
-	return be16_to_cpu(__get_unaligned_cpu16(p));
+	return be16_to_cpu(sh4a_get_unaligned_cpu16(p));
 }
 
 static inline u32 get_unaligned_be32(const void *p)
 {
-	return be32_to_cpu(__get_unaligned_cpu32(p));
+	return be32_to_cpu(sh4a_get_unaligned_cpu32(p));
 }
 
 static inline u64 get_unaligned_be64(const void *p)
 {
-	return be64_to_cpu(__get_unaligned_cpu64(p));
+	return be64_to_cpu(sh4a_get_unaligned_cpu64(p));
 }
 
-static inline void __put_le16_noalign(u8 *p, u16 val)
+static inline void nonnative_put_le16(u16 val, u8 *p)
 {
 	*p++ = val;
 	*p++ = val >> 8;
 }
 
-static inline void __put_le32_noalign(u8 *p, u32 val)
+static inline void nonnative_put_le32(u32 val, u8 *p)
 {
-	__put_le16_noalign(p, val);
-	__put_le16_noalign(p + 2, val >> 16);
+	nonnative_put_le16(val, p);
+	nonnative_put_le16(val >> 16, p + 2);
 }
 
-static inline void __put_le64_noalign(u8 *p, u64 val)
+static inline void nonnative_put_le64(u64 val, u8 *p)
 {
-	__put_le32_noalign(p, val);
-	__put_le32_noalign(p + 4, val >> 32);
+	nonnative_put_le32(val, p);
+	nonnative_put_le32(val >> 32, p + 4);
 }
 
-static inline void __put_be16_noalign(u8 *p, u16 val)
+static inline void nonnative_put_be16(u16 val, u8 *p)
 {
 	*p++ = val >> 8;
 	*p++ = val;
 }
 
-static inline void __put_be32_noalign(u8 *p, u32 val)
+static inline void nonnative_put_be32(u32 val, u8 *p)
 {
-	__put_be16_noalign(p, val >> 16);
-	__put_be16_noalign(p + 2, val);
+	nonnative_put_be16(val >> 16, p);
+	nonnative_put_be16(val, p + 2);
 }
 
-static inline void __put_be64_noalign(u8 *p, u64 val)
+static inline void nonnative_put_be64(u64 val, u8 *p)
 {
-	__put_be32_noalign(p, val >> 32);
-	__put_be32_noalign(p + 4, val);
+	nonnative_put_be32(val >> 32, p);
+	nonnative_put_be32(val, p + 4);
 }
 
 static inline void put_unaligned_le16(u16 val, void *p)
 {
 #ifdef __LITTLE_ENDIAN
-	((struct __una_u16 *)p)->x = val;
+	__put_unaligned_cpu16(val, p);
 #else
-	__put_le16_noalign(p, val);
+	nonnative_put_le16(val, p);
 #endif
 }
 
 static inline void put_unaligned_le32(u32 val, void *p)
 {
 #ifdef __LITTLE_ENDIAN
-	((struct __una_u32 *)p)->x = val;
+	__put_unaligned_cpu32(val, p);
 #else
-	__put_le32_noalign(p, val);
+	nonnative_put_le32(val, p);
 #endif
 }
 
 static inline void put_unaligned_le64(u64 val, void *p)
 {
 #ifdef __LITTLE_ENDIAN
-	((struct __una_u64 *)p)->x = val;
+	__put_unaligned_cpu64(val, p);
 #else
-	__put_le64_noalign(p, val);
+	nonnative_put_le64(val, p);
 #endif
 }
 
 static inline void put_unaligned_be16(u16 val, void *p)
 {
 #ifdef __BIG_ENDIAN
-	((struct __una_u16 *)p)->x = val;
+	__put_unaligned_cpu16(val, p);
 #else
-	__put_be16_noalign(p, val);
+	nonnative_put_be16(val, p);
 #endif
 }
 
 static inline void put_unaligned_be32(u32 val, void *p)
 {
 #ifdef __BIG_ENDIAN
-	((struct __una_u32 *)p)->x = val;
+	__put_unaligned_cpu32(val, p);
 #else
-	__put_be32_noalign(p, val);
+	nonnative_put_be32(val, p);
 #endif
 }
 
 static inline void put_unaligned_be64(u64 val, void *p)
 {
 #ifdef __BIG_ENDIAN
-	((struct __una_u64 *)p)->x = val;
+	__put_unaligned_cpu64(val, p);
 #else
-	__put_be64_noalign(p, val);
+	nonnative_put_be64(val, p);
 #endif
 }
 
 /*
- * Cause a link-time error if we try an unaligned access other than
- * 1,2,4 or 8 bytes long
+ * While it's a bit non-obvious, even though the generic le/be wrappers
+ * use the __get/put_xxx prefixing, they actually wrap in to the
+ * non-prefixed get/put_xxx variants as provided above.
  */
-extern void __bad_unaligned_access_size(void);
-
-#define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)),	\
-	__bad_unaligned_access_size()))));					\
-	}))
-
-#define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),			\
-	__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)),	\
-	__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)),	\
-	__bad_unaligned_access_size()))));					\
-	}))
-
-#define __put_unaligned_le(val, ptr) ({					\
-	void *__gu_p = (ptr);						\
-	switch (sizeof(*(ptr))) {					\
-	case 1:								\
-		*(u8 *)__gu_p = (__force u8)(val);			\
-		break;							\
-	case 2:								\
-		put_unaligned_le16((__force u16)(val), __gu_p);		\
-		break;							\
-	case 4:								\
-		put_unaligned_le32((__force u32)(val), __gu_p);		\
-		break;							\
-	case 8:								\
-		put_unaligned_le64((__force u64)(val), __gu_p);		\
-		break;							\
-	default:							\
-		__bad_unaligned_access_size();				\
-		break;							\
-	}								\
-	(void)0; })
-
-#define __put_unaligned_be(val, ptr) ({					\
-	void *__gu_p = (ptr);						\
-	switch (sizeof(*(ptr))) {					\
-	case 1:								\
-		*(u8 *)__gu_p = (__force u8)(val);			\
-		break;							\
-	case 2:								\
-		put_unaligned_be16((__force u16)(val), __gu_p);		\
-		break;							\
-	case 4:								\
-		put_unaligned_be32((__force u32)(val), __gu_p);		\
-		break;							\
-	case 8:								\
-		put_unaligned_be64((__force u64)(val), __gu_p);		\
-		break;							\
-	default:							\
-		__bad_unaligned_access_size();				\
-		break;							\
-	}								\
-	(void)0; })
+#include <linux/unaligned/generic.h>
 
 #ifdef __LITTLE_ENDIAN
 # define get_unaligned __get_unaligned_le

+ 8 - 0
arch/sh/include/mach-sdk7786/mach/fpga.h

@@ -14,11 +14,16 @@
 #define INTTESTR	0x040
 #define SYSSR		0x050
 #define NRGPR		0x060
+
 #define NMISR		0x070
+#define  NMISR_MAN_NMI	BIT(0)
+#define  NMISR_AUX_NMI	BIT(1)
+#define  NMISR_MASK	(NMISR_MAN_NMI | NMISR_AUX_NMI)
 
 #define NMIMR		0x080
 #define  NMIMR_MAN_NMIM	BIT(0)	/* Manual NMI mask */
 #define  NMIMR_AUX_NMIM	BIT(1)	/* Auxiliary NMI mask */
+#define  NMIMR_MASK	(NMIMR_MAN_NMIM | NMIMR_AUX_NMIM)
 
 #define INTBSR		0x090
 #define INTBMR		0x0a0
@@ -126,6 +131,9 @@
 extern void __iomem *sdk7786_fpga_base;
 extern void sdk7786_fpga_init(void);
 
+/* arch/sh/boards/mach-sdk7786/nmi.c */
+extern void sdk7786_nmi_init(void);
+
 #define SDK7786_FPGA_REGADDR(reg)	(sdk7786_fpga_base + (reg))
 
 /*

+ 5 - 1
arch/sh/kernel/Makefile

@@ -20,6 +20,11 @@ obj-y	:= clkdev.o debugtraps.o dma-nommu.o dumpstack.o 		\
 	   syscalls_$(BITS).o time.o topology.o traps.o			\
 	   traps_$(BITS).o unwinder.o
 
+ifndef CONFIG_GENERIC_IOMAP
+obj-y				+= iomap.o
+obj-$(CONFIG_HAS_IOPORT)	+= ioport.o
+endif
+
 obj-y				+= cpu/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
 obj-$(CONFIG_SMP)		+= smp.o
@@ -39,7 +44,6 @@ obj-$(CONFIG_DUMP_CODE)		+= disassemble.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o
 obj-$(CONFIG_DWARF_UNWINDER)	+= dwarf.o
 obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_callchain.o
-obj-$(CONFIG_HAS_IOPORT)	+= io_generic.o
 
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)		+= hw_breakpoint.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)	+= localtimer.o

+ 1 - 1
arch/sh/kernel/cpu/Makefile

@@ -20,4 +20,4 @@ obj-$(CONFIG_SH_CLK_CPG_LEGACY)	+= clock-cpg.o
 obj-$(CONFIG_SH_FPU)		+= fpu.o
 obj-$(CONFIG_SH_FPU_EMU)	+= fpu.o
 
-obj-y	+= irq/ init.o clock.o hwblk.o
+obj-y	+= irq/ init.o clock.o hwblk.o proc.o

+ 148 - 0
arch/sh/kernel/cpu/proc.c

@@ -0,0 +1,148 @@
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/machvec.h>
+#include <asm/processor.h>
+
+static const char *cpu_name[] = {
+	[CPU_SH7201]	= "SH7201",
+	[CPU_SH7203]	= "SH7203",	[CPU_SH7263]	= "SH7263",
+	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
+	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
+	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
+	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
+	[CPU_SH7712]	= "SH7712",	[CPU_SH7720]	= "SH7720",
+	[CPU_SH7721]	= "SH7721",	[CPU_SH7729]	= "SH7729",
+	[CPU_SH7750]	= "SH7750",	[CPU_SH7750S]	= "SH7750S",
+	[CPU_SH7750R]	= "SH7750R",	[CPU_SH7751]	= "SH7751",
+	[CPU_SH7751R]	= "SH7751R",	[CPU_SH7760]	= "SH7760",
+	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
+	[CPU_SH7763]	= "SH7763",	[CPU_SH7770]	= "SH7770",
+	[CPU_SH7780]	= "SH7780",	[CPU_SH7781]	= "SH7781",
+	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
+	[CPU_SH7786]	= "SH7786",	[CPU_SH7757]	= "SH7757",
+	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
+	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
+	[CPU_MXG]	= "MX-G",	[CPU_SH7723]	= "SH7723",
+	[CPU_SH7366]	= "SH7366",	[CPU_SH7724]	= "SH7724",
+	[CPU_SH_NONE]	= "Unknown"
+};
+
+const char *get_cpu_subtype(struct sh_cpuinfo *c)
+{
+	return cpu_name[c->type];
+}
+EXPORT_SYMBOL(get_cpu_subtype);
+
+#ifdef CONFIG_PROC_FS
+/* 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", "op32", "pteaex", NULL
+};
+
+static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
+{
+	unsigned long i;
+
+	seq_printf(m, "cpu flags\t:");
+
+	if (!c->flags) {
+		seq_printf(m, " %s\n", cpu_flags[0]);
+		return;
+	}
+
+	for (i = 0; cpu_flags[i]; i++)
+		if ((c->flags & (1 << i)))
+			seq_printf(m, " %s", cpu_flags[i+1]);
+
+	seq_printf(m, "\n");
+}
+
+static void show_cacheinfo(struct seq_file *m, const char *type,
+			   struct cache_info info)
+{
+	unsigned int cache_size;
+
+	cache_size = info.ways * info.sets * info.linesz;
+
+	seq_printf(m, "%s size\t: %2dKiB (%d-way)\n",
+		   type, cache_size >> 10, info.ways);
+}
+
+/*
+ *	Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	struct sh_cpuinfo *c = v;
+	unsigned int cpu = c - cpu_data;
+
+	if (!cpu_online(cpu))
+		return 0;
+
+	if (cpu == 0)
+		seq_printf(m, "machine\t\t: %s\n", get_system_type());
+	else
+		seq_printf(m, "\n");
+
+	seq_printf(m, "processor\t: %d\n", cpu);
+	seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
+	seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
+	if (c->cut_major == -1)
+		seq_printf(m, "cut\t\t: unknown\n");
+	else if (c->cut_minor == -1)
+		seq_printf(m, "cut\t\t: %d.x\n", c->cut_major);
+	else
+		seq_printf(m, "cut\t\t: %d.%d\n", c->cut_major, c->cut_minor);
+
+	show_cpuflags(m, c);
+
+	seq_printf(m, "cache type\t: ");
+
+	/*
+	 * Check for what type of cache we have, we support both the
+	 * unified cache on the SH-2 and SH-3, as well as the harvard
+	 * style cache on the SH-4.
+	 */
+	if (c->icache.flags & SH_CACHE_COMBINED) {
+		seq_printf(m, "unified\n");
+		show_cacheinfo(m, "cache", c->icache);
+	} else {
+		seq_printf(m, "split (harvard)\n");
+		show_cacheinfo(m, "icache", c->icache);
+		show_cacheinfo(m, "dcache", c->dcache);
+	}
+
+	/* Optional secondary cache */
+	if (c->flags & CPU_HAS_L2_CACHE)
+		show_cacheinfo(m, "scache", c->scache);
+
+	seq_printf(m, "address sizes\t: %u bits physical\n", c->phys_bits);
+
+	seq_printf(m, "bogomips\t: %lu.%02lu\n",
+		     c->loops_per_jiffy/(500000/HZ),
+		     (c->loops_per_jiffy/(5000/HZ)) % 100);
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+}
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
+};
+#endif /* CONFIG_PROC_FS */

+ 12 - 10
arch/sh/kernel/cpu/sh2/clock-sh7619.c

@@ -14,24 +14,18 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/io.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
-#include <asm/io.h>
+#include <asm/processor.h>
 
 static const int pll1rate[] = {1,2};
 static const int pfc_divisors[] = {1,2,0,4};
-
-#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6)
-#define PLL2 (2)
-#else
-#error "Illigal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
+	clk->rate *= pll2_mult * pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
 }
 
 static struct clk_ops sh7619_master_clk_ops = {
@@ -70,6 +64,14 @@ static struct clk_ops *sh7619_clk_ops[] = {
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN2 | MODE_PIN0) ||
+	    test_mode_pin(MODE_PIN2 | MODE_PIN1))
+		pll2_mult = 2;
+	else if (test_mode_pin(MODE_PIN0) || test_mode_pin(MODE_PIN1))
+		pll2_mult = 4;
+
+	BUG_ON(!pll2_mult);
+
 	if (idx < ARRAY_SIZE(sh7619_clk_ops))
 		*ops = sh7619_clk_ops[idx];
 }

+ 10 - 10
arch/sh/kernel/cpu/sh2a/clock-sh7201.c

@@ -22,19 +22,12 @@ static const int pll1rate[]={1,2,3,4,6,8};
 static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
-#if (CONFIG_SH_CLK_MD == 0)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 3)
-#define PLL2 (1)
-#else
-#error "Illegal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate = 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+	clk->rate = 10000000 * pll2_mult *
+	       pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7201_master_clk_ops = {
@@ -80,6 +73,13 @@ static struct clk_ops *sh7201_clk_ops[] = {
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN1 | MODE_PIN0))
+		pll2_mult = 1;
+	else if (test_mode_pin(MODE_PIN1))
+		pll2_mult = 2;
+	else
+		pll2_mult = 4;
+
 	if (idx < ARRAY_SIZE(sh7201_clk_ops))
 		*ops = sh7201_clk_ops[idx];
 }

+ 9 - 12
arch/sh/kernel/cpu/sh2a/clock-sh7203.c

@@ -25,21 +25,11 @@ static const int pll1rate[]={8,12,16,0};
 static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
-#if (CONFIG_SH_CLK_MD == 0)
-#define PLL2 (1)
-#elif (CONFIG_SH_CLK_MD == 1)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 3)
-#define PLL2 (4)
-#else
-#error "Illegal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * PLL2 ;
+	clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * pll2_mult;
 }
 
 static struct clk_ops sh7203_master_clk_ops = {
@@ -79,6 +69,13 @@ static struct clk_ops *sh7203_clk_ops[] = {
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN1))
+		pll2_mult = 4;
+	else if (test_mode_pin(MODE_PIN0))
+		pll2_mult = 2;
+	else
+		pll2_mult = 1;
+
 	if (idx < ARRAY_SIZE(sh7203_clk_ops))
 		*ops = sh7203_clk_ops[idx];
 }

+ 9 - 11
arch/sh/kernel/cpu/sh2a/clock-sh7206.c

@@ -22,19 +22,11 @@ static const int pll1rate[]={1,2,3,4,6,8};
 static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
-#if (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 6)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 7)
-#define PLL2 (1)
-#else
-#error "Illigal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
 
 static void master_clk_init(struct clk *clk)
 {
-	clk->rate *= PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+	clk->rate *= pll2_mult * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7206_master_clk_ops = {
@@ -79,7 +71,13 @@ static struct clk_ops *sh7206_clk_ops[] = {
 
 void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
 {
+	if (test_mode_pin(MODE_PIN2 | MODE_PIN1 | MODE_PIN0))
+		pll2_mult = 1;
+	else if (test_mode_pin(MODE_PIN2 | MODE_PIN1))
+		pll2_mult = 2;
+	else if (test_mode_pin(MODE_PIN1))
+		pll2_mult = 4;
+
 	if (idx < ARRAY_SIZE(sh7206_clk_ops))
 		*ops = sh7206_clk_ops[idx];
 }
-

+ 0 - 180
arch/sh/kernel/io_generic.c

@@ -1,180 +0,0 @@
-/*
- * arch/sh/kernel/io_generic.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- * Copyright (C) 2005 - 2007 Paul Mundt
- *
- * Generic I/O routine. These can be used where a machine specific version
- * is not required.
- *
- * 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/module.h>
-#include <linux/io.h>
-#include <asm/machvec.h>
-
-#ifdef CONFIG_CPU_SH3
-/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
- * workaround. */
-/* I'm not sure SH7709 has this kind of bug */
-#define dummy_read()	__raw_readb(0xba000000)
-#else
-#define dummy_read()
-#endif
-
-unsigned long generic_io_base = 0;
-
-u8 generic_inb(unsigned long port)
-{
-	return __raw_readb(__ioport_map(port, 1));
-}
-
-u16 generic_inw(unsigned long port)
-{
-	return __raw_readw(__ioport_map(port, 2));
-}
-
-u32 generic_inl(unsigned long port)
-{
-	return __raw_readl(__ioport_map(port, 4));
-}
-
-u8 generic_inb_p(unsigned long port)
-{
-	unsigned long v = generic_inb(port);
-
-	ctrl_delay();
-	return v;
-}
-
-u16 generic_inw_p(unsigned long port)
-{
-	unsigned long v = generic_inw(port);
-
-	ctrl_delay();
-	return v;
-}
-
-u32 generic_inl_p(unsigned long port)
-{
-	unsigned long v = generic_inl(port);
-
-	ctrl_delay();
-	return v;
-}
-
-/*
- * insb/w/l all read a series of bytes/words/longs from a fixed port
- * address. However as the port address doesn't change we only need to
- * convert the port address to real address once.
- */
-
-void generic_insb(unsigned long port, void *dst, unsigned long count)
-{
-	__raw_readsb(__ioport_map(port, 1), dst, count);
-	dummy_read();
-}
-
-void generic_insw(unsigned long port, void *dst, unsigned long count)
-{
-	__raw_readsw(__ioport_map(port, 2), dst, count);
-	dummy_read();
-}
-
-void generic_insl(unsigned long port, void *dst, unsigned long count)
-{
-	__raw_readsl(__ioport_map(port, 4), dst, count);
-	dummy_read();
-}
-
-void generic_outb(u8 b, unsigned long port)
-{
-	__raw_writeb(b, __ioport_map(port, 1));
-}
-
-void generic_outw(u16 b, unsigned long port)
-{
-	__raw_writew(b, __ioport_map(port, 2));
-}
-
-void generic_outl(u32 b, unsigned long port)
-{
-	__raw_writel(b, __ioport_map(port, 4));
-}
-
-void generic_outb_p(u8 b, unsigned long port)
-{
-	generic_outb(b, port);
-	ctrl_delay();
-}
-
-void generic_outw_p(u16 b, unsigned long port)
-{
-	generic_outw(b, port);
-	ctrl_delay();
-}
-
-void generic_outl_p(u32 b, unsigned long port)
-{
-	generic_outl(b, port);
-	ctrl_delay();
-}
-
-/*
- * outsb/w/l all write a series of bytes/words/longs to a fixed port
- * address. However as the port address doesn't change we only need to
- * convert the port address to real address once.
- */
-void generic_outsb(unsigned long port, const void *src, unsigned long count)
-{
-	__raw_writesb(__ioport_map(port, 1), src, count);
-	dummy_read();
-}
-
-void generic_outsw(unsigned long port, const void *src, unsigned long count)
-{
-	__raw_writesw(__ioport_map(port, 2), src, count);
-	dummy_read();
-}
-
-void generic_outsl(unsigned long port, const void *src, unsigned long count)
-{
-	__raw_writesl(__ioport_map(port, 4), src, count);
-	dummy_read();
-}
-
-void __iomem *generic_ioport_map(unsigned long addr, unsigned int size)
-{
-#ifdef P1SEG
-	if (PXSEG(addr) >= P1SEG)
-		return (void __iomem *)addr;
-#endif
-
-	return (void __iomem *)(addr + generic_io_base);
-}
-
-void generic_ioport_unmap(void __iomem *addr)
-{
-}
-
-#ifndef CONFIG_GENERIC_IOMAP
-void __iomem *ioport_map(unsigned long port, unsigned int nr)
-{
-	void __iomem *ret;
-
-	ret = __ioport_map_trapped(port, nr);
-	if (ret)
-		return ret;
-
-	return __ioport_map(port, nr);
-}
-EXPORT_SYMBOL(ioport_map);
-
-void ioport_unmap(void __iomem *addr)
-{
-	sh_mv.mv_ioport_unmap(addr);
-}
-EXPORT_SYMBOL(ioport_unmap);
-#endif /* CONFIG_GENERIC_IOMAP */

+ 165 - 0
arch/sh/kernel/iomap.c

@@ -0,0 +1,165 @@
+/*
+ * arch/sh/kernel/iomap.c
+ *
+ * Copyright (C) 2000  Niibe Yutaka
+ * Copyright (C) 2005 - 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/module.h>
+#include <linux/io.h>
+
+unsigned int ioread8(void __iomem *addr)
+{
+	return readb(addr);
+}
+EXPORT_SYMBOL(ioread8);
+
+unsigned int ioread16(void __iomem *addr)
+{
+	return readw(addr);
+}
+EXPORT_SYMBOL(ioread16);
+
+unsigned int ioread16be(void __iomem *addr)
+{
+	return be16_to_cpu(__raw_readw(addr));
+}
+EXPORT_SYMBOL(ioread16be);
+
+unsigned int ioread32(void __iomem *addr)
+{
+	return readl(addr);
+}
+EXPORT_SYMBOL(ioread32);
+
+unsigned int ioread32be(void __iomem *addr)
+{
+	return be32_to_cpu(__raw_readl(addr));
+}
+EXPORT_SYMBOL(ioread32be);
+
+void iowrite8(u8 val, void __iomem *addr)
+{
+	writeb(val, addr);
+}
+EXPORT_SYMBOL(iowrite8);
+
+void iowrite16(u16 val, void __iomem *addr)
+{
+	writew(val, addr);
+}
+EXPORT_SYMBOL(iowrite16);
+
+void iowrite16be(u16 val, void __iomem *addr)
+{
+	__raw_writew(cpu_to_be16(val), addr);
+}
+EXPORT_SYMBOL(iowrite16be);
+
+void iowrite32(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+EXPORT_SYMBOL(iowrite32);
+
+void iowrite32be(u32 val, void __iomem *addr)
+{
+	__raw_writel(cpu_to_be32(val), addr);
+}
+EXPORT_SYMBOL(iowrite32be);
+
+/*
+ * These are the "repeat MMIO read/write" functions.
+ * Note the "__raw" accesses, since we don't want to
+ * convert to CPU byte order. We write in "IO byte
+ * order" (we also don't have IO barriers).
+ */
+static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
+{
+	while (--count >= 0) {
+		u8 data = __raw_readb(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
+{
+	while (--count >= 0) {
+		u16 data = __raw_readw(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
+{
+	while (--count >= 0) {
+		u32 data = __raw_readl(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writeb(*src, addr);
+		src++;
+	}
+}
+
+static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writew(*src, addr);
+		src++;
+	}
+}
+
+static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writel(*src, addr);
+		src++;
+	}
+}
+
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insb(addr, dst, count);
+}
+EXPORT_SYMBOL(ioread8_rep);
+
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insw(addr, dst, count);
+}
+EXPORT_SYMBOL(ioread16_rep);
+
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	mmio_insl(addr, dst, count);
+}
+EXPORT_SYMBOL(ioread32_rep);
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsb(addr, src, count);
+}
+EXPORT_SYMBOL(iowrite8_rep);
+
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsw(addr, src, count);
+}
+EXPORT_SYMBOL(iowrite16_rep);
+
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	mmio_outsl(addr, src, count);
+}
+EXPORT_SYMBOL(iowrite32_rep);

+ 43 - 0
arch/sh/kernel/ioport.c

@@ -0,0 +1,43 @@
+/*
+ * arch/sh/kernel/ioport.c
+ *
+ * Copyright (C) 2000  Niibe Yutaka
+ * Copyright (C) 2005 - 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/module.h>
+#include <linux/io.h>
+
+const unsigned long sh_io_port_base __read_mostly = -1;
+EXPORT_SYMBOL(sh_io_port_base);
+
+void __iomem *__ioport_map(unsigned long addr, unsigned int size)
+{
+	if (sh_mv.mv_ioport_map)
+		return sh_mv.mv_ioport_map(addr, size);
+
+	return (void __iomem *)(addr + sh_io_port_base);
+}
+EXPORT_SYMBOL(__ioport_map);
+
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	void __iomem *ret;
+
+	ret = __ioport_map_trapped(port, nr);
+	if (ret)
+		return ret;
+
+	return __ioport_map(port, nr);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+	if (sh_mv.mv_ioport_unmap)
+		sh_mv.mv_ioport_unmap(addr);
+}
+EXPORT_SYMBOL(ioport_unmap);

+ 0 - 22
arch/sh/kernel/machvec.c

@@ -118,28 +118,6 @@ void __init sh_mv_setup(void)
 		sh_mv.mv_##elem = generic_##elem; \
 } while (0)
 
-#ifdef CONFIG_HAS_IOPORT
-
-#ifdef P2SEG
-	__set_io_port_base(P2SEG);
-#else
-	__set_io_port_base(0);
-#endif
-
-	mv_set(inb);	mv_set(inw);	mv_set(inl);
-	mv_set(outb);	mv_set(outw);	mv_set(outl);
-
-	mv_set(inb_p);	mv_set(inw_p);	mv_set(inl_p);
-	mv_set(outb_p);	mv_set(outw_p);	mv_set(outl_p);
-
-	mv_set(insb);	mv_set(insw);	mv_set(insl);
-	mv_set(outsb);	mv_set(outsw);	mv_set(outsl);
-
-	mv_set(ioport_map);
-	mv_set(ioport_unmap);
-
-#endif
-
 	mv_set(irq_demux);
 	mv_set(mode_pins);
 	mv_set(mem_init);

+ 0 - 144
arch/sh/kernel/setup.c

@@ -12,7 +12,6 @@
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/console.h>
-#include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/utsname.h>
 #include <linux/nodemask.h>
@@ -319,146 +318,3 @@ int test_mode_pin(int pin)
 {
 	return sh_mv.mv_mode_pins() & pin;
 }
-
-static const char *cpu_name[] = {
-	[CPU_SH7201]	= "SH7201",
-	[CPU_SH7203]	= "SH7203",	[CPU_SH7263]	= "SH7263",
-	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
-	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
-	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
-	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
-	[CPU_SH7712]	= "SH7712",	[CPU_SH7720]	= "SH7720",
-	[CPU_SH7721]	= "SH7721",	[CPU_SH7729]	= "SH7729",
-	[CPU_SH7750]	= "SH7750",	[CPU_SH7750S]	= "SH7750S",
-	[CPU_SH7750R]	= "SH7750R",	[CPU_SH7751]	= "SH7751",
-	[CPU_SH7751R]	= "SH7751R",	[CPU_SH7760]	= "SH7760",
-	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
-	[CPU_SH7763]	= "SH7763",	[CPU_SH7770]	= "SH7770",
-	[CPU_SH7780]	= "SH7780",	[CPU_SH7781]	= "SH7781",
-	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
-	[CPU_SH7786]	= "SH7786",	[CPU_SH7757]	= "SH7757",
-	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
-	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
-	[CPU_MXG]	= "MX-G",	[CPU_SH7723]	= "SH7723",
-	[CPU_SH7366]	= "SH7366",	[CPU_SH7724]	= "SH7724",
-	[CPU_SH_NONE]	= "Unknown"
-};
-
-const char *get_cpu_subtype(struct sh_cpuinfo *c)
-{
-	return cpu_name[c->type];
-}
-EXPORT_SYMBOL(get_cpu_subtype);
-
-#ifdef CONFIG_PROC_FS
-/* 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", "op32", "pteaex", NULL
-};
-
-static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
-{
-	unsigned long i;
-
-	seq_printf(m, "cpu flags\t:");
-
-	if (!c->flags) {
-		seq_printf(m, " %s\n", cpu_flags[0]);
-		return;
-	}
-
-	for (i = 0; cpu_flags[i]; i++)
-		if ((c->flags & (1 << i)))
-			seq_printf(m, " %s", cpu_flags[i+1]);
-
-	seq_printf(m, "\n");
-}
-
-static void show_cacheinfo(struct seq_file *m, const char *type,
-			   struct cache_info info)
-{
-	unsigned int cache_size;
-
-	cache_size = info.ways * info.sets * info.linesz;
-
-	seq_printf(m, "%s size\t: %2dKiB (%d-way)\n",
-		   type, cache_size >> 10, info.ways);
-}
-
-/*
- *	Get CPU information for use by the procfs.
- */
-static int show_cpuinfo(struct seq_file *m, void *v)
-{
-	struct sh_cpuinfo *c = v;
-	unsigned int cpu = c - cpu_data;
-
-	if (!cpu_online(cpu))
-		return 0;
-
-	if (cpu == 0)
-		seq_printf(m, "machine\t\t: %s\n", get_system_type());
-	else
-		seq_printf(m, "\n");
-
-	seq_printf(m, "processor\t: %d\n", cpu);
-	seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
-	seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
-	if (c->cut_major == -1)
-		seq_printf(m, "cut\t\t: unknown\n");
-	else if (c->cut_minor == -1)
-		seq_printf(m, "cut\t\t: %d.x\n", c->cut_major);
-	else
-		seq_printf(m, "cut\t\t: %d.%d\n", c->cut_major, c->cut_minor);
-
-	show_cpuflags(m, c);
-
-	seq_printf(m, "cache type\t: ");
-
-	/*
-	 * Check for what type of cache we have, we support both the
-	 * unified cache on the SH-2 and SH-3, as well as the harvard
-	 * style cache on the SH-4.
-	 */
-	if (c->icache.flags & SH_CACHE_COMBINED) {
-		seq_printf(m, "unified\n");
-		show_cacheinfo(m, "cache", c->icache);
-	} else {
-		seq_printf(m, "split (harvard)\n");
-		show_cacheinfo(m, "icache", c->icache);
-		show_cacheinfo(m, "dcache", c->dcache);
-	}
-
-	/* Optional secondary cache */
-	if (c->flags & CPU_HAS_L2_CACHE)
-		show_cacheinfo(m, "scache", c->scache);
-
-	seq_printf(m, "address sizes\t: %u bits physical\n", c->phys_bits);
-
-	seq_printf(m, "bogomips\t: %lu.%02lu\n",
-		     c->loops_per_jiffy/(500000/HZ),
-		     (c->loops_per_jiffy/(5000/HZ)) % 100);
-
-	return 0;
-}
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
-}
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	++*pos;
-	return c_start(m, pos);
-}
-static void c_stop(struct seq_file *m, void *v)
-{
-}
-const struct seq_operations cpuinfo_op = {
-	.start	= c_start,
-	.next	= c_next,
-	.stop	= c_stop,
-	.show	= show_cpuinfo,
-};
-#endif /* CONFIG_PROC_FS */

+ 114 - 18
drivers/dma/shdma.c

@@ -27,7 +27,10 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/sh_dma.h>
-
+#include <linux/notifier.h>
+#include <linux/kdebug.h>
+#include <linux/spinlock.h>
+#include <linux/rculist.h>
 #include "shdma.h"
 
 /* DMA descriptor control */
@@ -43,6 +46,13 @@ enum sh_dmae_desc_status {
 /* Default MEMCPY transfer size = 2^2 = 4 bytes */
 #define LOG2_DEFAULT_XFER_SIZE	2
 
+/*
+ * Used for write-side mutual exclusion for the global device list,
+ * read-side synchronization by way of RCU.
+ */
+static DEFINE_SPINLOCK(sh_dmae_lock);
+static LIST_HEAD(sh_dmae_devices);
+
 /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
 static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
 
@@ -817,10 +827,9 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data)
 	return ret;
 }
 
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
-static irqreturn_t sh_dmae_err(int irq, void *data)
+static unsigned int sh_dmae_reset(struct sh_dmae_device *shdev)
 {
-	struct sh_dmae_device *shdev = (struct sh_dmae_device *)data;
+	unsigned int handled = 0;
 	int i;
 
 	/* halt the dma controller */
@@ -829,25 +838,35 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
 	/* We cannot detect, which channel caused the error, have to reset all */
 	for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) {
 		struct sh_dmae_chan *sh_chan = shdev->chan[i];
-		if (sh_chan) {
-			struct sh_desc *desc;
-			/* Stop the channel */
-			dmae_halt(sh_chan);
-			/* Complete all  */
-			list_for_each_entry(desc, &sh_chan->ld_queue, node) {
-				struct dma_async_tx_descriptor *tx = &desc->async_tx;
-				desc->mark = DESC_IDLE;
-				if (tx->callback)
-					tx->callback(tx->callback_param);
-			}
-			list_splice_init(&sh_chan->ld_queue, &sh_chan->ld_free);
+		struct sh_desc *desc;
+
+		if (!sh_chan)
+			continue;
+
+		/* Stop the channel */
+		dmae_halt(sh_chan);
+
+		/* Complete all  */
+		list_for_each_entry(desc, &sh_chan->ld_queue, node) {
+			struct dma_async_tx_descriptor *tx = &desc->async_tx;
+			desc->mark = DESC_IDLE;
+			if (tx->callback)
+				tx->callback(tx->callback_param);
 		}
+
+		list_splice_init(&sh_chan->ld_queue, &sh_chan->ld_free);
+		handled++;
 	}
+
 	sh_dmae_rst(shdev);
 
-	return IRQ_HANDLED;
+	return !!handled;
+}
+
+static irqreturn_t sh_dmae_err(int irq, void *data)
+{
+	return IRQ_RETVAL(sh_dmae_reset(data));
 }
-#endif
 
 static void dmae_do_tasklet(unsigned long data)
 {
@@ -876,6 +895,60 @@ static void dmae_do_tasklet(unsigned long data)
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 }
 
+static bool sh_dmae_nmi_notify(struct sh_dmae_device *shdev)
+{
+	unsigned int handled;
+
+	/* Fast path out if NMIF is not asserted for this controller */
+	if ((dmaor_read(shdev) & DMAOR_NMIF) == 0)
+		return false;
+
+	handled = sh_dmae_reset(shdev);
+	if (handled)
+		return true;
+
+	return false;
+}
+
+static int sh_dmae_nmi_handler(struct notifier_block *self,
+			       unsigned long cmd, void *data)
+{
+	struct sh_dmae_device *shdev;
+	int ret = NOTIFY_DONE;
+	bool triggered;
+
+	/*
+	 * Only concern ourselves with NMI events.
+	 *
+	 * Normally we would check the die chain value, but as this needs
+	 * to be architecture independent, check for NMI context instead.
+	 */
+	if (!in_nmi())
+		return NOTIFY_DONE;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(shdev, &sh_dmae_devices, node) {
+		/*
+		 * Only stop if one of the controllers has NMIF asserted,
+		 * we do not want to interfere with regular address error
+		 * handling or NMI events that don't concern the DMACs.
+		 */
+		triggered = sh_dmae_nmi_notify(shdev);
+		if (triggered == true)
+			ret = NOTIFY_OK;
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+
+static struct notifier_block sh_dmae_nmi_notifier __read_mostly = {
+	.notifier_call	= sh_dmae_nmi_handler,
+
+	/* Run before NMI debug handler and KGDB */
+	.priority	= 1,
+};
+
 static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
 					int irq, unsigned long flags)
 {
@@ -967,6 +1040,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 	struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
 	unsigned long irqflags = IRQF_DISABLED,
 		chan_flag[SH_DMAC_MAX_CHANNELS] = {};
+	unsigned long flags;
 	int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
 	int err, i, irq_cnt = 0, irqres = 0;
 	struct sh_dmae_device *shdev;
@@ -1032,6 +1106,15 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
+	spin_lock_irqsave(&sh_dmae_lock, flags);
+	list_add_tail_rcu(&shdev->node, &sh_dmae_devices);
+	spin_unlock_irqrestore(&sh_dmae_lock, flags);
+
+	/* Wire up NMI handling before bringing the controller online */
+	err = register_die_notifier(&sh_dmae_nmi_notifier);
+	if (err)
+		goto notifier_err;
+
 	/* reset dma controller */
 	err = sh_dmae_rst(shdev);
 	if (err)
@@ -1135,6 +1218,12 @@ eirqres:
 eirq_err:
 #endif
 rst_err:
+	unregister_die_notifier(&sh_dmae_nmi_notifier);
+notifier_err:
+	spin_lock_irqsave(&sh_dmae_lock, flags);
+	list_del_rcu(&shdev->node);
+	spin_unlock_irqrestore(&sh_dmae_lock, flags);
+
 	pm_runtime_put(&pdev->dev);
 	if (dmars)
 		iounmap(shdev->dmars);
@@ -1155,6 +1244,7 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
 {
 	struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
 	struct resource *res;
+	unsigned long flags;
 	int errirq = platform_get_irq(pdev, 0);
 
 	dma_async_device_unregister(&shdev->common);
@@ -1162,6 +1252,12 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
 	if (errirq > 0)
 		free_irq(errirq, shdev);
 
+	unregister_die_notifier(&sh_dmae_nmi_notifier);
+
+	spin_lock_irqsave(&sh_dmae_lock, flags);
+	list_del_rcu(&shdev->node);
+	spin_unlock_irqrestore(&sh_dmae_lock, flags);
+
 	/* channel data remove */
 	sh_dmae_chan_remove(shdev);
 

+ 1 - 0
drivers/dma/shdma.h

@@ -43,6 +43,7 @@ struct sh_dmae_device {
 	struct dma_device common;
 	struct sh_dmae_chan *chan[SH_DMAC_MAX_CHANNELS];
 	struct sh_dmae_pdata *pdata;
+	struct list_head node;
 	u32 __iomem *chan_reg;
 	u16 __iomem *dmars;
 };