From: Paul Mundt <lethal@Linux-SH.ORG>

This adds support for the iomap interface to sh64.  As a result of this, we
can also clean up a lot of the sh64 common I/O routines.

We also add a board-specific ioport_map() for the cayman
so we can use iomap generically.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/sh64/lib/Makefile         |    2 
 25-akpm/arch/sh64/lib/io.c             |   73 +---------------------------
 25-akpm/arch/sh64/lib/iomap.c          |   55 +++++++++++++++++++++
 25-akpm/arch/sh64/mach-cayman/Makefile |    2 
 25-akpm/arch/sh64/mach-cayman/iomap.c  |   24 +++++++++
 25-akpm/include/asm-sh64/io.h          |   85 +++++++++++++++++++--------------
 6 files changed, 135 insertions(+), 106 deletions(-)

diff -puN arch/sh64/lib/io.c~sh64-iomap-interface arch/sh64/lib/io.c
--- 25/arch/sh64/lib/io.c~sh64-iomap-interface	2005-03-07 20:41:27.000000000 -0800
+++ 25-akpm/arch/sh64/lib/io.c	2005-03-07 20:41:27.000000000 -0800
@@ -9,14 +9,12 @@
  */
 
 #include <linux/config.h>
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/io.h>
-#ifdef CONFIG_SH_CAYMAN
-#include <asm/cayman.h>
-#endif
 
 /*
  * readX/writeX() are used to access memory mapped devices. On some
@@ -25,71 +23,6 @@
  * memory location directly.
  */
 
-#define dprintk(x...)
-
-static int io_addr(int x) {
-	if (x < 0x400) {
-#ifdef CONFIG_SH_CAYMAN
-		return (x << 2) | smsc_superio_virt;
-#else
-		panic ("Illegal access to I/O port 0x%04x\n", x);
-		return 0;
-#endif
-	} else {
-#ifdef CONFIG_PCI
-		return (x + pciio_virt);
-#else
-		panic ("Illegal access to I/O port 0x%04x\n", x);
-		return 0;
-#endif
-	}
-}
-
-unsigned long inb(unsigned long port)
-{
-	unsigned long r;
-
-	r = ctrl_inb(io_addr(port));
-	dprintk("inb(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
-	return r;
-}
-
-unsigned long inw(unsigned long port)
-{
-	unsigned long r;
-
-	r = ctrl_inw(io_addr(port));
-	dprintk("inw(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
-	return r;
-}
-
-unsigned long inl(unsigned long port)
-{
-	unsigned long r;
-
-	r = ctrl_inl(io_addr(port));
-	dprintk("inl(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
-	return r;
-}
-
-void outb(unsigned long value, unsigned long port)
-{
-	dprintk("outb(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
-	ctrl_outb(value, io_addr(port));
-}
-
-void outw(unsigned long value, unsigned long port)
-{
-	dprintk("outw(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
-	ctrl_outw(value, io_addr(port));
-}
-
-void outl(unsigned long value, unsigned long port)
-{
-	dprintk("outw(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
-	ctrl_outl(value, io_addr(port));
-}
-
 /* This is horrible at the moment - needs more work to do something sensible */
 #define IO_DELAY()
 
@@ -185,7 +118,7 @@ void insl(unsigned long port, void *addr
 	}
 }
 
-void memcpy_toio(unsigned long to, const void *from, long count)
+void memcpy_toio(void __iomem *to, const void *from, long count)
 {
 	unsigned char *p = (unsigned char *) from;
 
@@ -195,7 +128,7 @@ void memcpy_toio(unsigned long to, const
 	}
 }
 
-void memcpy_fromio(void *to, unsigned long from, long count)
+void memcpy_fromio(void *to, void __iomem *from, long count)
 {
 	int i;
 	unsigned char *p = (unsigned char *) to;
diff -puN /dev/null arch/sh64/lib/iomap.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/sh64/lib/iomap.c	2005-03-07 20:41:27.000000000 -0800
@@ -0,0 +1,55 @@
+/*
+ * arch/sh64/lib/iomap.c
+ *
+ * Generic sh64 iomap interface
+ *
+ * Copyright (C) 2004  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/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void __iomem *__attribute__ ((weak))
+ioport_map(unsigned long port, unsigned int len)
+{
+	return (void __iomem *)port;
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing .. */
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len)
+		return NULL;
+	if (max && len > max)
+		len = max;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start + pciio_virt, len);
+	if (flags & IORESOURCE_MEM)
+		return (void __iomem *)start;
+
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	/* Nothing .. */
+}
+
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
diff -puN arch/sh64/lib/Makefile~sh64-iomap-interface arch/sh64/lib/Makefile
--- 25/arch/sh64/lib/Makefile~sh64-iomap-interface	2005-03-07 20:41:27.000000000 -0800
+++ 25-akpm/arch/sh64/lib/Makefile	2005-03-07 20:41:27.000000000 -0800
@@ -15,5 +15,5 @@
 
 # Panic should really be compiled as PIC
 lib-y  := udelay.o c-checksum.o dbg.o io.o panic.o memcpy.o copy_user_memcpy.o \
-		page_copy.o page_clear.o
+		page_copy.o page_clear.o iomap.o
 
diff -puN /dev/null arch/sh64/mach-cayman/iomap.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/sh64/mach-cayman/iomap.c	2005-03-07 20:41:27.000000000 -0800
@@ -0,0 +1,24 @@
+/*
+ * arch/sh64/mach-cayman/iomap.c
+ *
+ * Cayman iomap interface
+ *
+ * Copyright (C) 2004  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/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/cayman.h>
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+	if (port < 0x400)
+		return (void __iomem *)((port << 2) | smsc_superio_virt);
+
+	return (void __iomem *)port;
+}
+
diff -puN arch/sh64/mach-cayman/Makefile~sh64-iomap-interface arch/sh64/mach-cayman/Makefile
--- 25/arch/sh64/mach-cayman/Makefile~sh64-iomap-interface	2005-03-07 20:41:27.000000000 -0800
+++ 25-akpm/arch/sh64/mach-cayman/Makefile	2005-03-07 20:41:27.000000000 -0800
@@ -6,6 +6,6 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y := setup.o irq.o
+obj-y := setup.o irq.o iomap.o
 obj-$(CONFIG_HEARTBEAT)	+= led.o
 
diff -puN include/asm-sh64/io.h~sh64-iomap-interface include/asm-sh64/io.h
--- 25/include/asm-sh64/io.h~sh64-iomap-interface	2005-03-07 20:41:27.000000000 -0800
+++ 25-akpm/include/asm-sh64/io.h	2005-03-07 20:41:27.000000000 -0800
@@ -25,9 +25,11 @@
  * onchip_remap();
  */
 
+#include <linux/compiler.h>
 #include <asm/cache.h>
 #include <asm/system.h>
 #include <asm/page.h>
+#include <asm-generic/iomap.h>
 
 #define virt_to_bus virt_to_phys
 #define bus_to_virt phys_to_virt
@@ -39,75 +41,90 @@
  * with an implicit size. The traditional read{b,w,l}/write{b,w,l}
  * mess is wrapped to this, as are the SH-specific ctrl_in/out routines.
  */
-static inline unsigned char sh64_in8(unsigned long addr)
+static inline unsigned char sh64_in8(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned char *)addr;
+	return *(volatile unsigned char __force *)addr;
 }
 
-static inline unsigned short sh64_in16(unsigned long addr)
+static inline unsigned short sh64_in16(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned short *)addr;
+	return *(volatile unsigned short __force *)addr;
 }
 
-static inline unsigned long sh64_in32(unsigned long addr)
+static inline unsigned int sh64_in32(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned long *)addr;
+	return *(volatile unsigned int __force *)addr;
 }
 
-static inline unsigned long long sh64_in64(unsigned long addr)
+static inline unsigned long long sh64_in64(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned long long *)addr;
+	return *(volatile unsigned long long __force *)addr;
 }
 
-static inline void sh64_out8(unsigned char b, unsigned long addr)
+static inline void sh64_out8(unsigned char b, volatile void __iomem *addr)
 {
-	*(volatile unsigned char *)addr = b;
+	*(volatile unsigned char __force *)addr = b;
 	wmb();
 }
 
-static inline void sh64_out16(unsigned short b, unsigned long addr)
+static inline void sh64_out16(unsigned short b, volatile void __iomem *addr)
 {
-	*(volatile unsigned short *)addr = b;
+	*(volatile unsigned short __force *)addr = b;
 	wmb();
 }
 
-static inline void sh64_out32(unsigned long b, unsigned long addr)
+static inline void sh64_out32(unsigned int b, volatile void __iomem *addr)
 {
-	*(volatile unsigned long *)addr = b;
+	*(volatile unsigned int __force *)addr = b;
 	wmb();
 }
 
-static inline void sh64_out64(unsigned long long b, unsigned long addr)
+static inline void sh64_out64(unsigned long long b, volatile void __iomem *addr)
 {
-	*(volatile unsigned long long *)addr = b;
+	*(volatile unsigned long long __force *)addr = b;
 	wmb();
 }
 
 #define readb(addr)		sh64_in8(addr)
 #define readw(addr)		sh64_in16(addr)
 #define readl(addr)		sh64_in32(addr)
-#define readb_relaxed(addr)		sh64_in8(addr)
-#define readw_relaxed(addr)		sh64_in16(addr)
-#define readl_relaxed(addr)		sh64_in32(addr)
+#define readb_relaxed(addr)	sh64_in8(addr)
+#define readw_relaxed(addr)	sh64_in16(addr)
+#define readl_relaxed(addr)	sh64_in32(addr)
 
 #define writeb(b, addr)		sh64_out8(b, addr)
 #define writew(b, addr)		sh64_out16(b, addr)
 #define writel(b, addr)		sh64_out32(b, addr)
 
-#define ctrl_inb(addr)		sh64_in8(addr)
-#define ctrl_inw(addr)		sh64_in16(addr)
-#define ctrl_inl(addr)		sh64_in32(addr)
-
-#define ctrl_outb(b, addr)	sh64_out8(b, addr)
-#define ctrl_outw(b, addr)	sh64_out16(b, addr)
-#define ctrl_outl(b, addr)	sh64_out32(b, addr)
-
-unsigned long inb(unsigned long port);
-unsigned long inw(unsigned long port);
-unsigned long inl(unsigned long port);
-void outb(unsigned long value, unsigned long port);
-void outw(unsigned long value, unsigned long port);
-void outl(unsigned long value, unsigned long port);
+#define ctrl_inb(addr)		sh64_in8(ioport_map(addr, 1))
+#define ctrl_inw(addr)		sh64_in16(ioport_map(addr, 2))
+#define ctrl_inl(addr)		sh64_in32(ioport_map(addr, 4))
+
+#define ctrl_outb(b, addr)	sh64_out8(b, ioport_map(addr, 1))
+#define ctrl_outw(b, addr)	sh64_out16(b, ioport_map(addr, 2))
+#define ctrl_outl(b, addr)	sh64_out32(b, ioport_map(addr, 4))
+
+#define ioread8(addr)		sh64_in8(addr)
+#define ioread16(addr)		sh64_in16(addr)
+#define ioread32(addr)		sh64_in32(addr)
+#define iowrite8(b, addr)	sh64_out8(b, addr)
+#define iowrite16(b, addr)	sh64_out16(b, addr)
+#define iowrite32(b, addr)	sh64_out32(b, addr)
+
+#define inb(addr)		ctrl_inb(addr)
+#define inw(addr)		ctrl_inw(addr)
+#define inl(addr)		ctrl_inl(addr)
+#define outb(b, addr)		ctrl_outb(b, addr)
+#define outw(b, addr)		ctrl_outw(b, addr)
+#define outl(b, addr)		ctrl_outl(b, addr)
+
+void outsw(unsigned long port, const void *addr, unsigned long count);
+void insw(unsigned long port, void *addr, unsigned long count);
+void outsl(unsigned long port, const void *addr, unsigned long count);
+void insl(unsigned long port, void *addr, unsigned long count);
+
+void memcpy_toio(void __iomem *to, const void *from, long count);
+void memcpy_fromio(void *to, void __iomem *from, long count);
 
 #define mmiowb()
 
@@ -154,7 +171,7 @@ extern void iounmap(void *addr);
 unsigned long onchip_remap(unsigned long addr, unsigned long size, const char* name);
 extern void onchip_unmap(unsigned long vaddr);
 
-static __inline__ int check_signature(unsigned long io_addr,
+static __inline__ int check_signature(volatile void __iomem *io_addr,
 			const unsigned char *signature, int length)
 {
 	int retval = 0;
_